summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurits van Rees <maurits@vanrees.org>2021-09-02 12:58:01 +0200
committerMaurits van Rees <maurits@vanrees.org>2021-09-02 12:58:01 +0200
commit583cde4a37e6d76f11b767dea8c518433748ec17 (patch)
treeadaf3e25199843fdc376457adf1c9a404b88c8a6
parent5e1cd72d4db7cf076e34bb6d86fd03b683ab43a2 (diff)
downloadzope-i18n-583cde4a37e6d76f11b767dea8c518433748ec17.tar.gz
black without string normalization
-rw-r--r--setup.py37
-rw-r--r--src/zope/i18n/__init__.py31
-rw-r--r--src/zope/i18n/compile.py9
-rw-r--r--src/zope/i18n/config.py4
-rw-r--r--src/zope/i18n/format.py198
-rw-r--r--src/zope/i18n/gettextmessagecatalog.py18
-rw-r--r--src/zope/i18n/interfaces/__init__.py116
-rw-r--r--src/zope/i18n/interfaces/locales.py397
-rw-r--r--src/zope/i18n/locales/__init__.py112
-rw-r--r--src/zope/i18n/locales/fallbackcollator.py2
-rw-r--r--src/zope/i18n/locales/inheritance.py24
-rw-r--r--src/zope/i18n/locales/provider.py5
-rw-r--r--src/zope/i18n/locales/tests/test_docstrings.py19
-rw-r--r--src/zope/i18n/locales/tests/test_fallbackcollator.py13
-rw-r--r--src/zope/i18n/locales/tests/test_locales.py51
-rw-r--r--src/zope/i18n/locales/tests/test_xmlfactory.py11
-rw-r--r--src/zope/i18n/locales/xmlfactory.py159
-rw-r--r--src/zope/i18n/negotiator.py1
-rw-r--r--src/zope/i18n/simpletranslationdomain.py29
-rw-r--r--src/zope/i18n/testing.py2
-rw-r--r--src/zope/i18n/testmessagecatalog.py5
-rw-r--r--src/zope/i18n/tests/test.py19
-rw-r--r--src/zope/i18n/tests/test_compile.py10
-rw-r--r--src/zope/i18n/tests/test_formats.py1684
-rw-r--r--src/zope/i18n/tests/test_gettextmessagecatalog.py3
-rw-r--r--src/zope/i18n/tests/test_imessagecatalog.py4
-rw-r--r--src/zope/i18n/tests/test_itranslationdomain.py47
-rw-r--r--src/zope/i18n/tests/test_negotiator.py25
-rw-r--r--src/zope/i18n/tests/test_plurals.py408
-rw-r--r--src/zope/i18n/tests/test_simpletranslationdomain.py4
-rw-r--r--src/zope/i18n/tests/test_testmessagecatalog.py8
-rw-r--r--src/zope/i18n/tests/test_translationdomain.py141
-rw-r--r--src/zope/i18n/tests/test_zcml.py118
-rw-r--r--src/zope/i18n/tests/testi18nawareobject.py8
-rw-r--r--src/zope/i18n/translationdomain.py97
-rw-r--r--src/zope/i18n/zcml.py33
36 files changed, 2411 insertions, 1441 deletions
diff --git a/setup.py b/setup.py
index dc3b83c..88010f7 100644
--- a/setup.py
+++ b/setup.py
@@ -21,17 +21,21 @@
import os
from setuptools import setup, find_packages
+
def read(*rnames):
with open(os.path.join(os.path.dirname(__file__), *rnames)) as f:
return f.read()
+
def alltests():
import sys
import unittest
+
# use the zope.testrunner machinery to find all the
# test suites we've put under ourselves
import zope.testrunner.find
import zope.testrunner.options
+
here = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))
args = sys.argv[:]
defaults = ["--test-path", here]
@@ -39,6 +43,7 @@ def alltests():
suites = list(zope.testrunner.find.find_suites(options))
return unittest.TestSuite(suites)
+
COMPILE_REQUIRES = [
# python-gettext used to be here, but it's now
# a fixed requirement. Keep the extra to avoid
@@ -51,11 +56,15 @@ ZCML_REQUIRES = [
'zope.security',
]
-TESTS_REQUIRE = COMPILE_REQUIRES + ZCML_REQUIRES + [
- 'zope.publisher',
- 'zope.testing',
- 'zope.testrunner',
-]
+TESTS_REQUIRE = (
+ COMPILE_REQUIRES
+ + ZCML_REQUIRES
+ + [
+ 'zope.publisher',
+ 'zope.testing',
+ 'zope.testrunner',
+ ]
+)
setup(
name='zope.i18n',
@@ -63,14 +72,12 @@ setup(
author='Zope Foundation and Contributors',
author_email='zope-dev@zope.org',
description='Zope Internationalization Support',
- long_description=(
- read('README.rst')
- + '\n\n' +
- read('CHANGES.rst')
- ),
+ long_description=(read('README.rst') + '\n\n' + read('CHANGES.rst')),
license='ZPL 2.1',
- keywords=('zope3 internationalization localization i18n l10n '
- 'gettext ICU locale'),
+ keywords=(
+ 'zope3 internationalization localization i18n l10n '
+ 'gettext ICU locale'
+ ),
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
@@ -93,7 +100,9 @@ setup(
url='https://github.com/zopefoundation/zope.i18n',
packages=find_packages('src'),
package_dir={'': 'src'},
- namespace_packages=['zope',],
+ namespace_packages=[
+ 'zope',
+ ],
install_requires=[
'setuptools',
'python-gettext',
@@ -116,4 +125,4 @@ setup(
test_suite='__main__.alltests',
include_package_data=True,
zip_safe=False,
- )
+)
diff --git a/src/zope/i18n/__init__.py b/src/zope/i18n/__init__.py
index dd525ea..f7b582c 100644
--- a/src/zope/i18n/__init__.py
+++ b/src/zope/i18n/__init__.py
@@ -30,12 +30,12 @@ text_type = str if bytes is not str else unicode
# zope.tal.taldefs module:
NAME_RE = r"[a-zA-Z_][-a-zA-Z0-9_]*"
-_interp_regex = re.compile(r'(?<!\$)(\$(?:(%(n)s)|{(%(n)s)}))'
- % ({'n': NAME_RE}))
+_interp_regex = re.compile(
+ r'(?<!\$)(\$(?:(%(n)s)|{(%(n)s)}))' % ({'n': NAME_RE})
+)
class _FallbackNegotiator(object):
-
def getLanguage(self, _allowed, _context):
return None
@@ -81,9 +81,17 @@ def negotiate(context):
return negotiator.getLanguage(ALLOWED_LANGUAGES, context)
-def translate(msgid, domain=None, mapping=None, context=None,
- target_language=None, default=None, msgid_plural=None,
- default_plural=None, number=None):
+def translate(
+ msgid,
+ domain=None,
+ mapping=None,
+ context=None,
+ target_language=None,
+ default=None,
+ msgid_plural=None,
+ default_plural=None,
+ number=None,
+):
"""Translate text.
First setup some test components:
@@ -190,8 +198,15 @@ def translate(msgid, domain=None, mapping=None, context=None,
target_language = negotiate(context)
return util.translate(
- msgid, mapping, context, target_language, default,
- msgid_plural, default_plural, number)
+ msgid,
+ mapping,
+ context,
+ target_language,
+ default,
+ msgid_plural,
+ default_plural,
+ number,
+ )
def interpolate(text, mapping=None):
diff --git a/src/zope/i18n/compile.py b/src/zope/i18n/compile.py
index 834bf24..30f794e 100644
--- a/src/zope/i18n/compile.py
+++ b/src/zope/i18n/compile.py
@@ -11,12 +11,14 @@ logger = logging.getLogger('zope.i18n')
HAS_PYTHON_GETTEXT = True
+
def _safe_mtime(path):
try:
return os.path.getmtime(path)
except (IOError, OSError):
return None
+
def compile_mo_file(domain, lc_messages_path):
"""Creates or updates a mo file in the locales folder."""
@@ -28,8 +30,7 @@ def compile_mo_file(domain, lc_messages_path):
mo_mtime = _safe_mtime(mofile) or 0
if po_mtime is None:
- logger.debug("Unable to access %s (%s)",
- pofile, po_mtime)
+ logger.debug("Unable to access %s (%s)", pofile, po_mtime)
return
if po_mtime > mo_mtime:
@@ -44,6 +45,8 @@ def compile_mo_file(domain, lc_messages_path):
with open(mofile, 'wb') as fd:
fd.write(mo.read())
except PoSyntaxError as err:
- logger.warning('Syntax error while compiling %s (%s).', pofile, err.msg)
+ logger.warning(
+ 'Syntax error while compiling %s (%s).', pofile, err.msg
+ )
except (IOError, OSError) as err:
logger.warning('Error while compiling %s (%s).', pofile, err)
diff --git a/src/zope/i18n/config.py b/src/zope/i18n/config.py
index 1636083..ca60ed0 100644
--- a/src/zope/i18n/config.py
+++ b/src/zope/i18n/config.py
@@ -45,4 +45,6 @@ def _parse_languages(value):
#: A set of languages that `zope.i18n.negotiate` will pass to the
#: `zope.i18n.interfaces.INegotiator` utility. If this is None,
#: no utility will be used.
-ALLOWED_LANGUAGES = _parse_languages(os.environ.get(ALLOWED_LANGUAGES_KEY, None))
+ALLOWED_LANGUAGES = _parse_languages(
+ os.environ.get(ALLOWED_LANGUAGES_KEY, None)
+)
diff --git a/src/zope/i18n/format.py b/src/zope/i18n/format.py
index abc3e50..43c19c9 100644
--- a/src/zope/i18n/format.py
+++ b/src/zope/i18n/format.py
@@ -31,7 +31,7 @@ NATIVE_NUMBER_TYPES = (int, float)
try:
NATIVE_NUMBER_TYPES += (long,)
except NameError:
- pass # Py3
+ pass # Py3
def roundHalfUp(n):
@@ -45,8 +45,11 @@ def roundHalfUp(n):
def _findFormattingCharacterInPattern(char, pattern):
- return [entry for entry in pattern
- if isinstance(entry, tuple) and entry[0] == char]
+ return [
+ entry
+ for entry in pattern
+ if isinstance(entry, tuple) and entry[0] == char
+ ]
class DateTimeParseError(Exception):
@@ -74,8 +77,9 @@ class DateTimeFormat(object):
def setPattern(self, pattern):
"See zope.i18n.interfaces.IFormat"
self._pattern = pattern
- self._bin_pattern = parseDateTimePattern(self._pattern,
- self._DATETIMECHARS)
+ self._bin_pattern = parseDateTimePattern(
+ self._pattern, self._DATETIMECHARS
+ )
def getPattern(self):
"See zope.i18n.interfaces.IFormat"
@@ -100,8 +104,8 @@ class DateTimeFormat(object):
results = re.match(regex, text).groups()
except AttributeError:
raise DateTimeParseError(
- 'The datetime string did not match the pattern %r.'
- % pattern)
+ 'The datetime string did not match the pattern %r.' % pattern
+ )
# Sometimes you only want the parse results
if not asObject:
return results
@@ -138,11 +142,14 @@ class DateTimeFormat(object):
ampm_entry = _findFormattingCharacterInPattern('a', bin_pattern)
if not ampm_entry:
raise DateTimeParseError(
- 'Cannot handle 12-hour format without am/pm marker.')
- ampm = self.calendar.pm == results[bin_pattern.index(ampm_entry[0])]
+ 'Cannot handle 12-hour format without am/pm marker.'
+ )
+ ampm = (
+ self.calendar.pm == results[bin_pattern.index(ampm_entry[0])]
+ )
if hour == 12:
ampm = not ampm
- ordered[3] = (hour + 12*ampm)%24
+ ordered[3] = (hour + 12 * ampm) % 24
# Shortcut for the simple int functions
dt_fields_map = {'d': 2, 'H': 3, 'm': 4, 's': 5, 'S': 6}
@@ -155,7 +162,7 @@ class DateTimeFormat(object):
# Handle timezones
tzinfo = None
- pytz_tzinfo = False # If True, we should use pytz specific syntax
+ pytz_tzinfo = False # If True, we should use pytz specific syntax
tz_entry = _findFormattingCharacterInPattern('z', bin_pattern)
if ordered[3:] != [None, None, None, None] and tz_entry:
length = tz_entry[0][1]
@@ -187,18 +194,20 @@ class DateTimeFormat(object):
return tzinfo.localize(
datetime.datetime.combine(
datetime.date.today(),
- datetime.time(*[e or 0 for e in ordered[3:]]))).timetz()
+ datetime.time(*[e or 0 for e in ordered[3:]]),
+ )
+ ).timetz()
return datetime.time(
- *[e or 0 for e in ordered[3:]], **{'tzinfo' :tzinfo}
+ *[e or 0 for e in ordered[3:]], **{'tzinfo': tzinfo}
)
if pytz_tzinfo:
- return tzinfo.localize(datetime.datetime(
- *[e or 0 for e in ordered]
- ))
+ return tzinfo.localize(
+ datetime.datetime(*[e or 0 for e in ordered])
+ )
return datetime.datetime(
- *[e or 0 for e in ordered], **{'tzinfo' :tzinfo}
+ *[e or 0 for e in ordered], **{'tzinfo': tzinfo}
)
def format(self, obj, pattern=None):
@@ -235,7 +244,7 @@ class NumberFormat(object):
self.symbols = {
u"decimal": u".",
u"group": u",",
- u"list": u";",
+ u"list": u";",
u"percentSign": u"%",
u"nativeZeroDigit": u"0",
u"patternDigit": u"#",
@@ -244,7 +253,7 @@ class NumberFormat(object):
u"exponential": u"E",
u"perMille": u"\xe2\x88\x9e",
u"infinity": u"\xef\xbf\xbd",
- u"nan": u''
+ u"nan": u'',
}
self.symbols.update(symbols)
if pattern is not None:
@@ -281,20 +290,20 @@ class NumberFormat(object):
min_size = bin_pattern[sign][INTEGER].count('0')
if bin_pattern[sign][GROUPING]:
regex += self.symbols['group']
- min_size += min_size/3
- regex += ']{%i,100}' %(min_size)
+ min_size += min_size / 3
+ regex += ']{%i,100}' % (min_size)
if bin_pattern[sign][FRACTION]:
max_precision = len(bin_pattern[sign][FRACTION])
min_precision = bin_pattern[sign][FRACTION].count('0')
- regex += '['+self.symbols['decimal']+']?'
- regex += '[0-9]{%i,%i}' %(min_precision, max_precision)
+ regex += '[' + self.symbols['decimal'] + ']?'
+ regex += '[0-9]{%i,%i}' % (min_precision, max_precision)
if bin_pattern[sign][EXPONENTIAL] != '':
regex += self.symbols['exponential']
min_exp_size = bin_pattern[sign][EXPONENTIAL].count('0')
pre_symbols = self.symbols['minusSign']
if bin_pattern[sign][EXPONENTIAL][0] == '+':
pre_symbols += self.symbols['plusSign']
- regex += '[%s]?[0-9]{%i,100}' %(pre_symbols, min_exp_size)
+ regex += '[%s]?[0-9]{%i,100}' % (pre_symbols, min_exp_size)
regex += ')'
if bin_pattern[sign][PADDING3] is not None:
regex += '[' + bin_pattern[sign][PADDING3] + ']+'
@@ -312,8 +321,9 @@ class NumberFormat(object):
num_str = num_res[1].groups()[0]
sign = -1
else:
- raise NumberParseError('Not a valid number for this pattern %r.'
- % pattern)
+ raise NumberParseError(
+ 'Not a valid number for this pattern %r.' % pattern
+ )
# Remove possible grouping separators
num_str = num_str.replace(self.symbols['group'], '')
# Extract number
@@ -326,13 +336,15 @@ class NumberFormat(object):
num_str = num_str.replace(self.symbols['exponential'], 'E')
if self.type:
type = self.type
- return sign*type(num_str)
+ return sign * type(num_str)
def _format_integer(self, integer, pattern):
size = len(integer)
min_size = pattern.count('0')
if size < min_size:
- integer = self.symbols['nativeZeroDigit']*(min_size-size) + integer
+ integer = (
+ self.symbols['nativeZeroDigit'] * (min_size - size) + integer
+ )
return integer
def _format_fraction(self, fraction, pattern, rounding=True):
@@ -353,7 +365,7 @@ class NumberFormat(object):
fractionLen = len(fraction)
rounded = int(fraction) + 1
fraction = ('%0' + str(fractionLen) + 'i') % rounded
- if len(fraction) > fractionLen: # rounded fraction >= 1
+ if len(fraction) > fractionLen: # rounded fraction >= 1
roundInt = True
fraction = fraction[1:]
else:
@@ -361,8 +373,9 @@ class NumberFormat(object):
roundInt = True
if precision < min_precision:
- fraction += self.symbols['nativeZeroDigit']*(min_precision -
- precision)
+ fraction += self.symbols['nativeZeroDigit'] * (
+ min_precision - precision
+ )
if fraction != '':
fraction = self.symbols['decimal'] + fraction
return fraction, roundInt
@@ -439,22 +452,24 @@ class NumberFormat(object):
# abs() of number smaller 1
if len(obj_int_frac) > 1:
res = re.match('(0*)[0-9]*', obj_int_frac[1]).groups()[0]
- exponent = self._format_integer(str(len(res)+1),
- exp_bin_pattern)
- exponent = self.symbols['minusSign']+exponent
- number = obj_int_frac[1][len(res):]
+ exponent = self._format_integer(
+ str(len(res) + 1), exp_bin_pattern
+ )
+ exponent = self.symbols['minusSign'] + exponent
+ number = obj_int_frac[1][len(res) :]
else:
# We have exactly 0
exponent = self._format_integer('0', exp_bin_pattern)
number = self.symbols['nativeZeroDigit']
else:
- exponent = self._format_integer(str(len(obj_int_frac[0])-1),
- exp_bin_pattern)
+ exponent = self._format_integer(
+ str(len(obj_int_frac[0]) - 1), exp_bin_pattern
+ )
number = ''.join(obj_int_frac)
- fraction, roundInt = self._format_fraction(number[1:],
- bin_pattern[FRACTION],
- rounding=rounding)
+ fraction, roundInt = self._format_fraction(
+ number[1:], bin_pattern[FRACTION], rounding=rounding
+ )
if roundInt:
number = str(int(number[0]) + 1) + fraction
else:
@@ -471,40 +486,42 @@ class NumberFormat(object):
else:
if len(obj_int_frac) > 1:
fraction, roundInt = self._format_fraction(
- obj_int_frac[1], bin_pattern[FRACTION], rounding=rounding)
+ obj_int_frac[1], bin_pattern[FRACTION], rounding=rounding
+ )
else:
fraction = ''
roundInt = False
if roundInt:
obj = roundHalfUp(obj)
- integer = self._format_integer(str(int(math.fabs(obj))),
- bin_pattern[INTEGER])
+ integer = self._format_integer(
+ str(int(math.fabs(obj))), bin_pattern[INTEGER]
+ )
# Adding grouping
if bin_pattern[GROUPING]:
integer = self._group(integer, bin_pattern[GROUPING])
pre_padding = len(bin_pattern[INTEGER]) - len(integer)
- post_padding = len(bin_pattern[FRACTION]) - len(fraction)+1
+ post_padding = len(bin_pattern[FRACTION]) - len(fraction) + 1
number = integer + fraction
# Put it all together
text = ''
if bin_pattern[PADDING1] is not None and pre_padding > 0:
- text += bin_pattern[PADDING1]*pre_padding
+ text += bin_pattern[PADDING1] * pre_padding
text += bin_pattern[PREFIX]
if bin_pattern[PADDING2] is not None and pre_padding > 0:
if bin_pattern[PADDING1] is not None:
text += bin_pattern[PADDING2]
- else: # pragma: no cover
+ else: # pragma: no cover
text += bin_pattern[PADDING2] * pre_padding
text += number
if bin_pattern[PADDING3] is not None and post_padding > 0:
if bin_pattern[PADDING4] is not None:
text += bin_pattern[PADDING3]
else:
- text += bin_pattern[PADDING3]*post_padding
+ text += bin_pattern[PADDING3] * post_padding
text += bin_pattern[SUFFIX]
if bin_pattern[PADDING4] is not None and post_padding > 0:
- text += bin_pattern[PADDING4]*post_padding
+ text += bin_pattern[PADDING4] * post_padding
# TODO: Need to make sure unicode is everywhere
return text_type(text)
@@ -578,16 +595,18 @@ def parseDateTimePattern(pattern, DATETIMECHARS="aGyMdEDFwWhHmsSkKz"):
# Some cleaning up
if state == IN_QUOTE:
- if quote_start == -1: # pragma: no cover
+ if quote_start == -1: # pragma: no cover
# It should not be possible to get into this state.
# The only time we set quote_start to -1 we also set the state
# to DEFAULT.
raise DateTimePatternParseError(
- 'Waaa: state = IN_QUOTE and quote_start = -1!')
+ 'Waaa: state = IN_QUOTE and quote_start = -1!'
+ )
else:
raise DateTimePatternParseError(
- 'The quote starting at character %i is not closed.' %
- quote_start)
+ 'The quote starting at character %i is not closed.'
+ % quote_start
+ )
elif state == IN_DATETIMEFIELD:
result.append((helper[0], len(helper)))
elif state == DEFAULT:
@@ -605,7 +624,7 @@ def buildDateTimeParseInfo(calendar, pattern):
for entry in _findFormattingCharacterInPattern(field, pattern):
# The maximum amount of digits should be infinity, but 1000 is
# close enough here.
- info[entry] = r'([0-9]{%i,1000})' %entry[1]
+ info[entry] = r'([0-9]{%i,1000})' % entry[1]
# year (Number)
for entry in _findFormattingCharacterInPattern('y', pattern):
@@ -618,12 +637,12 @@ def buildDateTimeParseInfo(calendar, pattern):
# am/pm marker (Text)
for entry in _findFormattingCharacterInPattern('a', pattern):
- info[entry] = r'(%s|%s)' %(calendar.am, calendar.pm)
+ info[entry] = r'(%s|%s)' % (calendar.am, calendar.pm)
# era designator (Text)
# TODO: works for gregorian only right now
for entry in _findFormattingCharacterInPattern('G', pattern):
- info[entry] = r'(%s|%s)' %(calendar.eras[1][1], calendar.eras[2][1])
+ info[entry] = r'(%s|%s)' % (calendar.eras[1][1], calendar.eras[2][1])
# time zone (Text)
for entry in _findFormattingCharacterInPattern('z', pattern):
@@ -643,9 +662,11 @@ def buildDateTimeParseInfo(calendar, pattern):
elif entry[1] == 2:
info[entry] = r'([0-9]{2})'
elif entry[1] == 3:
- info[entry] = r'('+'|'.join(calendar.getMonthAbbreviations())+')'
+ info[entry] = (
+ r'(' + '|'.join(calendar.getMonthAbbreviations()) + ')'
+ )
else:
- info[entry] = r'('+'|'.join(calendar.getMonthNames())+')'
+ info[entry] = r'(' + '|'.join(calendar.getMonthNames()) + ')'
# day in week (Text and Number)
for entry in _findFormattingCharacterInPattern('E', pattern):
@@ -654,9 +675,9 @@ def buildDateTimeParseInfo(calendar, pattern):
elif entry[1] == 2:
info[entry] = r'([0-9]{2})'
elif entry[1] == 3:
- info[entry] = r'('+'|'.join(calendar.getDayAbbreviations())+')'
+ info[entry] = r'(' + '|'.join(calendar.getDayAbbreviations()) + ')'
else:
- info[entry] = r'('+'|'.join(calendar.getDayNames())+')'
+ info[entry] = r'(' + '|'.join(calendar.getDayNames()) + ')'
return info
@@ -665,10 +686,12 @@ def buildDateTimeInfo(dt, calendar, pattern):
"""Create the bits and pieces of the datetime object that can be put
together."""
if isinstance(dt, datetime.time):
- dt = datetime.datetime(1969, 1, 1, dt.hour, dt.minute, dt.second,
- dt.microsecond)
- elif (isinstance(dt, datetime.date) and
- not isinstance(dt, datetime.datetime)):
+ dt = datetime.datetime(
+ 1969, 1, 1, dt.hour, dt.minute, dt.second, dt.microsecond
+ )
+ elif isinstance(dt, datetime.date) and not isinstance(
+ dt, datetime.datetime
+ ):
dt = datetime.datetime(dt.year, dt.month, dt.day)
if dt.hour >= 12:
@@ -676,7 +699,7 @@ def buildDateTimeInfo(dt, calendar, pattern):
else:
ampm = calendar.am
- h = dt.hour%12
+ h = dt.hour % 12
if h == 0:
h = 12
@@ -693,7 +716,7 @@ def buildDateTimeInfo(dt, calendar, pattern):
tz_mins = int(math.fabs(tz_secs % 3600 / 60))
tz_hours = int(math.fabs(tz_secs / 3600))
tz_sign = '-' if tz_secs < 0 else '+'
- tz_defaultname = "%s%i%.2i" %(tz_sign, tz_hours, tz_mins)
+ tz_defaultname = "%s%i%.2i" % (tz_sign, tz_hours, tz_mins)
tz_name = tzinfo.tzname(dt) or tz_defaultname
tz_fullname = getattr(tzinfo, 'zone', None) or tz_name
@@ -703,14 +726,22 @@ def buildDateTimeInfo(dt, calendar, pattern):
}
# Generic Numbers
- for field, value in (('d', dt.day), ('D', int(dt.strftime('%j'))),
- ('F', day_of_week_in_month), ('k', dt.hour or 24),
- ('K', dt.hour%12), ('h', h), ('H', dt.hour),
- ('m', dt.minute), ('s', dt.second),
- ('S', dt.microsecond), ('w', int(dt.strftime('%W'))),
- ('W', week_in_month)):
+ for field, value in (
+ ('d', dt.day),
+ ('D', int(dt.strftime('%j'))),
+ ('F', day_of_week_in_month),
+ ('k', dt.hour or 24),
+ ('K', dt.hour % 12),
+ ('h', h),
+ ('H', dt.hour),
+ ('m', dt.minute),
+ ('s', dt.second),
+ ('S', dt.microsecond),
+ ('w', int(dt.strftime('%W'))),
+ ('W', week_in_month),
+ ):
for entry in _findFormattingCharacterInPattern(field, pattern):
- info[entry] = (u"%%.%ii" %entry[1]) %value
+ info[entry] = (u"%%.%ii" % entry[1]) % value
# am/pm marker (Text)
for entry in _findFormattingCharacterInPattern('a', pattern):
@@ -724,9 +755,9 @@ def buildDateTimeInfo(dt, calendar, pattern):
# time zone (Text)
for entry in _findFormattingCharacterInPattern('z', pattern):
if entry[1] == 1:
- info[entry] = u"%s%i%.2i" %(tz_sign, tz_hours, tz_mins)
+ info[entry] = u"%s%i%.2i" % (tz_sign, tz_hours, tz_mins)
elif entry[1] == 2:
- info[entry] = u"%s%.2i:%.2i" %(tz_sign, tz_hours, tz_mins)
+ info[entry] = u"%s%.2i:%.2i" % (tz_sign, tz_hours, tz_mins)
elif entry[1] == 3:
info[entry] = tz_name
else:
@@ -820,7 +851,8 @@ def parseNumberPattern(pattern):
helper += char
else:
raise NumberPatternParseError(
- 'Wrong syntax at beginning of pattern.')
+ 'Wrong syntax at beginning of pattern.'
+ )
elif state == READ_PADDING_1:
padding_1 = char
@@ -964,15 +996,25 @@ def parseNumberPattern(pattern):
last_index = -1
for index, char in enumerate(reversed(integer)):
if char == ",":
- grouping += (index-last_index-1,)
+ grouping += (index - last_index - 1,)
last_index = index
# use last group ad infinitum
grouping += (0,)
# remove grouping markers from integer pattern
integer = integer.replace(",", "")
- pattern = (padding_1, prefix, padding_2, integer, fraction, exponential,
- padding_3, suffix, padding_4, grouping)
+ pattern = (
+ padding_1,
+ prefix,
+ padding_2,
+ integer,
+ fraction,
+ exponential,
+ padding_3,
+ suffix,
+ padding_4,
+ grouping,
+ )
if neg_pattern is None:
neg_pattern = pattern
diff --git a/src/zope/i18n/gettextmessagecatalog.py b/src/zope/i18n/gettextmessagecatalog.py
index 8e1272b..1fff37b 100644
--- a/src/zope/i18n/gettextmessagecatalog.py
+++ b/src/zope/i18n/gettextmessagecatalog.py
@@ -39,6 +39,7 @@ def plural_formatting(func):
Please note that the interpolation can be done, alternatively,
using the mapping. This is only present as a conveniance.
"""
+
@wraps(func)
def pformat(catalog, singular, plural, n, *args, **kwargs):
msg = func(catalog, singular, plural, n, *args, **kwargs)
@@ -47,6 +48,7 @@ def plural_formatting(func):
except TypeError:
# The message cannot be formatted : return it "raw".
return msg
+
return pformat
@@ -59,19 +61,23 @@ class GettextMessageCatalog(object):
def __init__(self, language, domain, path_to_file):
"""Initialize the message catalog"""
self.language = (
- language.decode('utf-8') if isinstance(language, bytes)
- else language)
+ language.decode('utf-8')
+ if isinstance(language, bytes)
+ else language
+ )
self.domain = (
- domain.decode("utf-8") if isinstance(domain, bytes)
- else domain)
+ domain.decode("utf-8") if isinstance(domain, bytes) else domain
+ )
self._path_to_file = path_to_file
self.reload()
catalog = self._catalog
catalog.add_fallback(_KeyErrorRaisingFallback())
self._gettext = (
- catalog.gettext if str is not bytes else catalog.ugettext)
+ catalog.gettext if str is not bytes else catalog.ugettext
+ )
self._ngettext = (
- catalog.ngettext if str is not bytes else catalog.ungettext)
+ catalog.ngettext if str is not bytes else catalog.ungettext
+ )
def reload(self):
'See IMessageCatalog'
diff --git a/src/zope/i18n/interfaces/__init__.py b/src/zope/i18n/interfaces/__init__.py
index c5a3328..3231605 100644
--- a/src/zope/i18n/interfaces/__init__.py
+++ b/src/zope/i18n/interfaces/__init__.py
@@ -87,12 +87,14 @@ class IMessageCatalog(Interface):
language = TextLine(
title=u"Language",
description=u"The language the catalog translates to.",
- required=True)
+ required=True,
+ )
domain = TextLine(
title=u"Domain",
description=u"The domain the catalog is registered for.",
- required=True)
+ required=True,
+ )
def getIdentifier():
"""Return a identifier for this message catalog. Note that this
@@ -104,7 +106,6 @@ class IMessageCatalog(Interface):
class IGlobalMessageCatalog(IMessageCatalog):
-
def reload():
"""Reload and parse .po file"""
@@ -151,11 +152,19 @@ class ITranslationDomain(Interface):
domain = TextLine(
title=u"Domain Name",
description=u"The name of the domain this object represents.",
- required=True)
-
- def translate(msgid, mapping=None, context=None, target_language=None,
- default=None, msgid_plural=None, default_plural=None,
- number=None):
+ required=True,
+ )
+
+ def translate(
+ msgid,
+ mapping=None,
+ context=None,
+ target_language=None,
+ default=None,
+ msgid_plural=None,
+ default_plural=None,
+ number=None,
+ ):
"""Return the translation for the message referred to by msgid.
Return the default if no translation is found.
@@ -178,8 +187,7 @@ class IFallbackTranslationDomainFactory(Interface):
"""
def __call__(domain_id=u""):
- """Return a fallback translation domain for the given domain id.
- """
+ """Return a fallback translation domain for the given domain id."""
class ITranslator(Interface):
@@ -189,8 +197,14 @@ class ITranslator(Interface):
the domain, context, and target language.
"""
- def translate(msgid, mapping=None, default=None,
- msgid_plural=None, default_plural=None, number=None):
+ def translate(
+ msgid,
+ mapping=None,
+ default=None,
+ msgid_plural=None,
+ default_plural=None,
+ number=None,
+ ):
"""Translate the source msgid using the given mapping.
See ITranslationService for details.
@@ -200,21 +214,19 @@ class ITranslator(Interface):
class IMessageImportFilter(Interface):
"""The Import Filter for Translation Service Messages.
- Classes implementing this interface should usually be Adaptors, as
- they adapt the IEditableTranslationService interface."""
-
+ Classes implementing this interface should usually be Adaptors, as
+ they adapt the IEditableTranslationService interface."""
def importMessages(domains, languages, file):
"""Import all messages that are defined in the specified domains and
- languages.
+ languages.
- Note that some implementations might limit to only one domain and
- one language. A good example for that is a GettextFile.
+ Note that some implementations might limit to only one domain and
+ one language. A good example for that is a GettextFile.
"""
class ILanguageAvailability(Interface):
-
def getAvailableLanguages():
"""Return a sequence of 3-tuples for available languages
@@ -239,7 +251,6 @@ class IUserPreferredLanguages(Interface):
class IModifiableUserPreferredLanguages(IUserPreferredLanguages):
-
def setPreferredLanguages(languages):
"""Set a sequence of user preferred languages.
@@ -251,22 +262,20 @@ class IModifiableUserPreferredLanguages(IUserPreferredLanguages):
class IMessageExportFilter(Interface):
"""The Export Filter for Translation Service Messages.
- Classes implementing this interface should usually be Adaptors, as
- they adapt the IEditableTranslationService interface."""
-
+ Classes implementing this interface should usually be Adaptors, as
+ they adapt the IEditableTranslationService interface."""
def exportMessages(domains, languages):
"""Export all messages that are defined in the specified domains and
- languages.
+ languages.
- Note that some implementations might limit to only one domain and
- one language. A good example for that is a GettextFile.
+ Note that some implementations might limit to only one domain and
+ one language. A good example for that is a GettextFile.
"""
class INegotiator(Interface):
- """A language negotiation service.
- """
+ """A language negotiation service."""
def getLanguage(langs, env):
"""Return the matching language to use.
@@ -295,13 +304,12 @@ class INegotiator(Interface):
class IUserPreferredCharsets(Interface):
- """This interface provides charset negotiation based on user preferences.
- """
+ """This interface provides charset negotiation based on user preferences."""
def getPreferredCharsets():
"""Return a sequence of user preferred charsets. Note that the order
- should describe the order of preference. Therefore the first
- character set in the list is the most preferred one.
+ should describe the order of preference. Therefore the first
+ character set in the list is the most preferred one.
"""
@@ -326,7 +334,6 @@ class IFormat(Interface):
"""Format an object to a string using the pattern as a rule."""
-
class INumberFormat(IFormat):
r"""Specific number formatting interface. Here are the formatting
rules (I modified the rules from ICU a bit, since I think they did not
@@ -383,21 +390,38 @@ class INumberFormat(IFormat):
type = Field(
title=u"Type",
- description=((u"The type into which a string is parsed. If ``None``, "
- u"then ``int`` will be used for whole numbers and "
- u"``float`` for decimals.")),
+ description=(
+ (
+ u"The type into which a string is parsed. If ``None``, "
+ u"then ``int`` will be used for whole numbers and "
+ u"``float`` for decimals."
+ )
+ ),
default=None,
- required=False)
+ required=False,
+ )
symbols = Dict(
title=u"Number Symbols",
key_type=Choice(
title=u"Dictionary Class",
- values=(u"decimal", u"group", u"list", u"percentSign",
- u"nativeZeroDigit", u"patternDigit", u"plusSign",
- u"minusSign", u"exponential", u"perMille",
- u"infinity", u"nan")),
- value_type=TextLine(title=u"Symbol"))
+ values=(
+ u"decimal",
+ u"group",
+ u"list",
+ u"percentSign",
+ u"nativeZeroDigit",
+ u"patternDigit",
+ u"plusSign",
+ u"minusSign",
+ u"exponential",
+ u"perMille",
+ u"infinity",
+ u"nan",
+ ),
+ ),
+ value_type=TextLine(title=u"Symbol"),
+ )
class IDateTimeFormat(IFormat):
@@ -448,7 +472,9 @@ class IDateTimeFormat(IFormat):
Three or over, use text, otherwise use number. (for example, "M"
produces "1", "MM" produces "01", "MMM" produces "Jan", and "MMMM"
- produces "January".) """
+ produces "January".)"""
- calendar = Attribute("""This object must implement ILocaleCalendar. See
- this interface's documentation for details.""")
+ calendar = Attribute(
+ """This object must implement ILocaleCalendar. See
+ this interface's documentation for details."""
+ )
diff --git a/src/zope/i18n/interfaces/locales.py b/src/zope/i18n/interfaces/locales.py
index f6017ad..98e6c18 100644
--- a/src/zope/i18n/interfaces/locales.py
+++ b/src/zope/i18n/interfaces/locales.py
@@ -16,8 +16,17 @@
import datetime
import re
from zope.interface import Interface, Attribute
-from zope.schema import \
- Field, Text, TextLine, Int, Bool, Tuple, List, Dict, Date
+from zope.schema import (
+ Field,
+ Text,
+ TextLine,
+ Int,
+ Bool,
+ Tuple,
+ List,
+ Dict,
+ Date,
+)
from zope.schema import Choice
@@ -28,7 +37,7 @@ class ILocaleProvider(Interface):
This service will be singelton global service, since it doe not make much
sense to have many locale facilities, especially since this one will be so
- complete, since we will the ICU XML Files as data. """
+ complete, since we will the ICU XML Files as data."""
def loadLocale(language=None, country=None, variant=None):
"""Load the locale with the specs that are given by the arguments of
@@ -70,32 +79,39 @@ class ILocaleIdentity(Interface):
description=u"The language for which a locale is applicable.",
constraint=re.compile(r'[a-z]{2}').match,
required=True,
- readonly=True)
+ readonly=True,
+ )
script = TextLine(
title=u"Script Type",
- description=(u"""The script for which the language/locale is
- applicable."""),
- constraint=re.compile(r'[a-z]*').match)
+ description=(
+ u"""The script for which the language/locale is
+ applicable."""
+ ),
+ constraint=re.compile(r'[a-z]*').match,
+ )
territory = TextLine(
title=u"Territory Type",
description=u"The territory for which a locale is applicable.",
constraint=re.compile(r'[A-Z]{2}').match,
required=True,
- readonly=True)
+ readonly=True,
+ )
variant = TextLine(
title=u"Variant Type",
description=u"The variant for which a locale is applicable.",
constraint=re.compile(r'[a-zA-Z]*').match,
required=True,
- readonly=True)
+ readonly=True,
+ )
version = Field(
title=u"Locale Version",
description=u"The value of this field is an ILocaleVersion object.",
- readonly=True)
+ readonly=True,
+ )
def __repr__(self):
"""Defines the representation of the id, which should be a compact
@@ -113,18 +129,21 @@ class ILocaleVersion(Interface):
description=u"The version number of the locale.",
constraint=re.compile(r'^([0-9].)*[0-9]$').match,
required=True,
- readonly=True)
+ readonly=True,
+ )
generationDate = Date(
title=u"Generation Date",
description=u"Specifies the creation date of the locale.",
constraint=lambda date: date < datetime.datetime.now(),
- readonly=True)
+ readonly=True,
+ )
notes = Text(
title=u"Notes",
description=u"Some release notes for the version of this locale.",
- readonly=True)
+ readonly=True,
+ )
class ILocaleDisplayNames(Interface):
@@ -138,32 +157,38 @@ class ILocaleDisplayNames(Interface):
languages = Dict(
title=u"Language type to translated name",
key_type=TextLine(title=u"Language Type"),
- value_type=TextLine(title=u"Language Name"))
+ value_type=TextLine(title=u"Language Name"),
+ )
scripts = Dict(
title=u"Script type to script name",
key_type=TextLine(title=u"Script Type"),
- value_type=TextLine(title=u"Script Name"))
+ value_type=TextLine(title=u"Script Name"),
+ )
territories = Dict(
title=u"Territory type to translated territory name",
key_type=TextLine(title=u"Territory Type"),
- value_type=TextLine(title=u"Territory Name"))
+ value_type=TextLine(title=u"Territory Name"),
+ )
variants = Dict(
title=u"Variant type to name",
key_type=TextLine(title=u"Variant Type"),
- value_type=TextLine(title=u"Variant Name"))
+ value_type=TextLine(title=u"Variant Name"),
+ )
keys = Dict(
title=u"Key type to name",
key_type=TextLine(title=u"Key Type"),
- value_type=TextLine(title=u"Key Name"))
+ value_type=TextLine(title=u"Key Name"),
+ )
types = Dict(
title=u"Type type and key to localized name",
key_type=Tuple(title=u"Type Type and Key"),
- value_type=TextLine(title=u"Type Name"))
+ value_type=TextLine(title=u"Type Name"),
+ )
class ILocaleTimeZone(Interface):
@@ -179,26 +204,32 @@ class ILocaleTimeZone(Interface):
title=u"Time Zone Type",
description=u"Standard name of the timezone for unique referencing.",
required=True,
- readonly=True)
+ readonly=True,
+ )
cities = List(
title=u"Cities",
description=u"Cities in Timezone",
value_type=TextLine(title=u"City Name"),
required=True,
- readonly=True)
-
+ readonly=True,
+ )
names = Dict(
title=u"Time Zone Names",
description=u"Various names of the timezone.",
key_type=Choice(
title=u"Time Zone Name Type",
- values=(u"generic", u"standard", u"daylight")),
- value_type=Tuple(title=u"Time Zone Name and Abbreviation",
- min_length=2, max_length=2),
+ values=(u"generic", u"standard", u"daylight"),
+ ),
+ value_type=Tuple(
+ title=u"Time Zone Name and Abbreviation",
+ min_length=2,
+ max_length=2,
+ ),
required=True,
- readonly=True)
+ readonly=True,
+ )
class ILocaleFormat(Interface):
@@ -208,19 +239,22 @@ class ILocaleFormat(Interface):
title=u"Format Type",
description=u"The name of the format",
required=False,
- readonly=True)
+ readonly=True,
+ )
displayName = TextLine(
title=u"Display Name",
description=u"Name of the calendar, for example 'gregorian'.",
required=False,
- readonly=True)
+ readonly=True,
+ )
pattern = TextLine(
title=u"Format Pattern",
description=u"The pattern that is used to format the object.",
required=True,
- readonly=True)
+ readonly=True,
+ )
class ILocaleFormatLength(Interface):
@@ -229,12 +263,13 @@ class ILocaleFormatLength(Interface):
type = Choice(
title=u"Format Length Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")
- )
+ values=(u"full", u"long", u"medium", u"short"),
+ )
default = TextLine(
title=u"Default Format",
- description=u"The name of the defaulkt format.")
+ description=u"The name of the defaulkt format.",
+ )
formats = Dict(
title=u"Formats",
@@ -242,9 +277,11 @@ class ILocaleFormatLength(Interface):
key_type=TextLine(title=u"Format Type"),
value_type=Field(
title=u"Format Object",
- description=u"Values are ILocaleFormat objects."),
+ description=u"Values are ILocaleFormat objects.",
+ ),
required=True,
- readonly=True)
+ readonly=True,
+ )
class ILocaleMonthContext(Interface):
@@ -252,23 +289,25 @@ class ILocaleMonthContext(Interface):
type = TextLine(
title=u"Month context type",
- description=u"Name of the month context, format or stand-alone.")
+ description=u"Name of the month context, format or stand-alone.",
+ )
- defaultWidth = TextLine(
- title=u"Default month name width",
- default=u"wide")
+ defaultWidth = TextLine(title=u"Default month name width", default=u"wide")
months = Dict(
title=u"Month Names",
- description=(u"A mapping of month name widths to a mapping of"
- u"corresponding month names."),
+ description=(
+ u"A mapping of month name widths to a mapping of"
+ u"corresponding month names."
+ ),
key_type=Choice(
- title=u"Width type",
- values=(u"wide", u"abbreviated", u"narrow")),
+ title=u"Width type", values=(u"wide", u"abbreviated", u"narrow")
+ ),
value_type=Dict(
title=u"Month name",
key_type=Int(title=u"Type", min=1, max=12),
- value_type=TextLine(title=u"Month Name"))
+ value_type=TextLine(title=u"Month Name"),
+ ),
)
@@ -277,26 +316,36 @@ class ILocaleDayContext(Interface):
type = TextLine(
title=u"Day context type",
- description=u"Name of the day context, format or stand-alone.")
+ description=u"Name of the day context, format or stand-alone.",
+ )
- defaultWidth = TextLine(
- title=u"Default day name width",
- default=u"wide")
+ defaultWidth = TextLine(title=u"Default day name width", default=u"wide")
days = Dict(
title=u"Day Names",
- description=(u"A mapping of day name widths to a mapping of"
- u"corresponding day names."),
+ description=(
+ u"A mapping of day name widths to a mapping of"
+ u"corresponding day names."
+ ),
key_type=Choice(
- title=u"Width type",
- values=(u"wide", u"abbreviated", u"narrow")),
+ title=u"Width type", values=(u"wide", u"abbreviated", u"narrow")
+ ),
value_type=Dict(
title=u"Day name",
key_type=Choice(
title=u"Type",
- values=(u"sun", u"mon", u"tue", u"wed",
- u"thu", u"fri", u"sat")),
- value_type=TextLine(title=u"Day Name"))
+ values=(
+ u"sun",
+ u"mon",
+ u"tue",
+ u"wed",
+ u"thu",
+ u"fri",
+ u"sat",
+ ),
+ ),
+ value_type=TextLine(title=u"Day Name"),
+ ),
)
@@ -306,56 +355,66 @@ class ILocaleCalendar(Interface):
type = TextLine(
title=u"Calendar Type",
- description=u"Name of the calendar, for example 'gregorian'.")
+ description=u"Name of the calendar, for example 'gregorian'.",
+ )
defaultMonthContext = TextLine(
- title=u"Default month context",
- default=u"format")
+ title=u"Default month context", default=u"format"
+ )
monthContexts = Dict(
title=u"Month Contexts",
- description=(u"A mapping of month context types to "
- u"ILocaleMonthContext objects"),
- key_type=Choice(title=u"Type",
- values=(u"format", u"stand-alone")),
- value_type=Field(title=u"ILocaleMonthContext object"))
+ description=(
+ u"A mapping of month context types to "
+ u"ILocaleMonthContext objects"
+ ),
+ key_type=Choice(title=u"Type", values=(u"format", u"stand-alone")),
+ value_type=Field(title=u"ILocaleMonthContext object"),
+ )
# BBB: leftover from CLDR 1.0
months = Dict(
title=u"Month Names",
description=u"A mapping of all month names and abbreviations",
key_type=Int(title=u"Type", min=1, max=12),
- value_type=Tuple(title=u"Month Name and Abbreviation",
- min_length=2, max_length=2))
+ value_type=Tuple(
+ title=u"Month Name and Abbreviation", min_length=2, max_length=2
+ ),
+ )
defaultDayContext = TextLine(
- title=u"Default day context",
- default=u"format")
+ title=u"Default day context", default=u"format"
+ )
dayContexts = Dict(
title=u"Day Contexts",
- description=(u"A mapping of day context types to "
- u"ILocaleDayContext objects"),
- key_type=Choice(title=u"Type",
- values=(u"format", u"stand-alone")),
- value_type=Field(title=u"ILocaleDayContext object"))
+ description=(
+ u"A mapping of day context types to " u"ILocaleDayContext objects"
+ ),
+ key_type=Choice(title=u"Type", values=(u"format", u"stand-alone")),
+ value_type=Field(title=u"ILocaleDayContext object"),
+ )
# BBB: leftover from CLDR 1.0
days = Dict(
title=u"Weekdays Names",
description=u"A mapping of all month names and abbreviations",
- key_type=Choice(title=u"Type",
- values=(u"sun", u"mon", u"tue", u"wed",
- u"thu", u"fri", u"sat")),
- value_type=Tuple(title=u"Weekdays Name and Abbreviation",
- min_length=2, max_length=2))
+ key_type=Choice(
+ title=u"Type",
+ values=(u"sun", u"mon", u"tue", u"wed", u"thu", u"fri", u"sat"),
+ ),
+ value_type=Tuple(
+ title=u"Weekdays Name and Abbreviation", min_length=2, max_length=2
+ ),
+ )
week = Dict(
title=u"Week Information",
description=u"Contains various week information",
key_type=Choice(
title=u"Type",
- description=(u"""
+ description=(
+ u"""
Varies Week information:
- 'minDays' is just an integer between 1 and 7.
@@ -364,9 +423,11 @@ class ILocaleCalendar(Interface):
- The 'weekendStart' and 'weekendEnd' are tuples of the form
(weekDayNumber, datetime.time)
- """),
- values=(u"minDays", u"firstDay",
- u"weekendStart", u"weekendEnd")))
+ """
+ ),
+ values=(u"minDays", u"firstDay", u"weekendStart", u"weekendEnd"),
+ ),
+ )
am = TextLine(title=u"AM String")
@@ -375,8 +436,10 @@ class ILocaleCalendar(Interface):
eras = Dict(
title=u"Era Names",
key_type=Int(title=u"Type", min=0),
- value_type=Tuple(title=u"Era Name and Abbreviation",
- min_length=2, max_length=2))
+ value_type=Tuple(
+ title=u"Era Name and Abbreviation", min_length=2, max_length=2
+ ),
+ )
defaultDateFormat = TextLine(title=u"Default Date Format Type")
@@ -386,8 +449,10 @@ class ILocaleCalendar(Interface):
key_type=Choice(
title=u"Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")),
- value_type=Field(title=u"ILocaleFormatLength object"))
+ values=(u"full", u"long", u"medium", u"short"),
+ ),
+ value_type=Field(title=u"ILocaleFormatLength object"),
+ )
defaultTimeFormat = TextLine(title=u"Default Time Format Type")
@@ -397,8 +462,10 @@ class ILocaleCalendar(Interface):
key_type=Choice(
title=u"Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")),
- value_type=Field(title=u"ILocaleFormatLength object"))
+ values=(u"full", u"long", u"medium", u"short"),
+ ),
+ value_type=Field(title=u"ILocaleFormatLength object"),
+ )
defaultDateTimeFormat = TextLine(title=u"Default Date-Time Format Type")
@@ -408,8 +475,10 @@ class ILocaleCalendar(Interface):
key_type=Choice(
title=u"Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")),
- value_type=Field(title=u"ILocaleFormatLength object"))
+ values=(u"full", u"long", u"medium", u"short"),
+ ),
+ value_type=Field(title=u"ILocaleFormatLength object"),
+ )
def getMonthNames():
"""Return a list of month names."""
@@ -447,27 +516,36 @@ class ILocaleDates(Interface):
localizedPatternChars = TextLine(
title=u"Localized Pattern Characters",
- description=u"Localized pattern characters used in dates and times")
+ description=u"Localized pattern characters used in dates and times",
+ )
calendars = Dict(
title=u"Calendar type to ILocaleCalendar",
key_type=Choice(
title=u"Calendar Type",
- values=(u"gregorian",
- u"arabic",
- u"chinese",
- u"civil-arabic",
- u"hebrew",
- u"japanese",
- u"thai-buddhist")),
- value_type=Field(title=u"Calendar",
- description=u"This is a ILocaleCalendar object."))
+ values=(
+ u"gregorian",
+ u"arabic",
+ u"chinese",
+ u"civil-arabic",
+ u"hebrew",
+ u"japanese",
+ u"thai-buddhist",
+ ),
+ ),
+ value_type=Field(
+ title=u"Calendar", description=u"This is a ILocaleCalendar object."
+ ),
+ )
timezones = Dict(
title=u"Time zone type to ILocaleTimezone",
key_type=TextLine(title=u"Time Zone type"),
- value_type=Field(title=u"Time Zone",
- description=u"This is a ILocaleTimeZone object."))
+ value_type=Field(
+ title=u"Time Zone",
+ description=u"This is a ILocaleTimeZone object.",
+ ),
+ )
def getFormatter(category, length=None, name=None, calendar=u"gregorian"):
"""Get a date/time formatter.
@@ -491,6 +569,7 @@ class ILocaleCurrency(Interface):
symbolChoice = Bool(title=u"Symbol Choice")
+
class ILocaleNumbers(Interface):
"""This object contains various data about numbers and currencies."""
@@ -498,11 +577,23 @@ class ILocaleNumbers(Interface):
title=u"Number Symbols",
key_type=Choice(
title=u"Format Name",
- values=(u"decimal", u"group", u"list", u"percentSign",
- u"nativeZeroDigit", u"patternDigit", u"plusSign",
- u"minusSign", u"exponential", u"perMille",
- u"infinity", u"nan")),
- value_type=TextLine(title=u"Symbol"))
+ values=(
+ u"decimal",
+ u"group",
+ u"list",
+ u"percentSign",
+ u"nativeZeroDigit",
+ u"patternDigit",
+ u"plusSign",
+ u"minusSign",
+ u"exponential",
+ u"perMille",
+ u"infinity",
+ u"nan",
+ ),
+ ),
+ value_type=TextLine(title=u"Symbol"),
+ )
defaultDecimalFormat = TextLine(title=u"Default Decimal Format Type")
@@ -512,8 +603,10 @@ class ILocaleNumbers(Interface):
key_type=Choice(
title=u"Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")),
- value_type=Field(title=u"ILocaleFormatLength object"))
+ values=(u"full", u"long", u"medium", u"short"),
+ ),
+ value_type=Field(title=u"ILocaleFormatLength object"),
+ )
defaultScientificFormat = TextLine(title=u"Default Scientific Format Type")
@@ -523,8 +616,10 @@ class ILocaleNumbers(Interface):
key_type=Choice(
title=u"Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")),
- value_type=Field(title=u"ILocaleFormatLength object"))
+ values=(u"full", u"long", u"medium", u"short"),
+ ),
+ value_type=Field(title=u"ILocaleFormatLength object"),
+ )
defaultPercentFormat = TextLine(title=u"Default Percent Format Type")
@@ -534,8 +629,10 @@ class ILocaleNumbers(Interface):
key_type=Choice(
title=u"Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")),
- value_type=Field(title=u"ILocaleFormatLength object"))
+ values=(u"full", u"long", u"medium", u"short"),
+ ),
+ value_type=Field(title=u"ILocaleFormatLength object"),
+ )
defaultCurrencyFormat = TextLine(title=u"Default Currency Format Type")
@@ -545,17 +642,19 @@ class ILocaleNumbers(Interface):
key_type=Choice(
title=u"Type",
description=u"Name of the format length",
- values=(u"full", u"long", u"medium", u"short")),
- value_type=Field(title=u"ILocaleFormatLength object"))
+ values=(u"full", u"long", u"medium", u"short"),
+ ),
+ value_type=Field(title=u"ILocaleFormatLength object"),
+ )
currencies = Dict(
title=u"Currencies",
description=u"Contains various Currency data.",
key_type=TextLine(
- title=u"Type",
- description=u"Name of the format length"),
- value_type=Field(title=u"ILocaleCurrency object"))
-
+ title=u"Type", description=u"Name of the format length"
+ ),
+ value_type=Field(title=u"ILocaleCurrency object"),
+ )
def getFormatter(category, length=None, name=u""):
"""Get the NumberFormat based on the category, length and name of the
@@ -577,22 +676,30 @@ class ILocaleNumbers(Interface):
def getDefaultCurrency():
"""Get the default currency."""
-_orientations = [u"left-to-right", u"right-to-left",
- u"top-to-bottom", u"bottom-to-top"]
+
+_orientations = [
+ u"left-to-right",
+ u"right-to-left",
+ u"top-to-bottom",
+ u"bottom-to-top",
+]
+
+
class ILocaleOrientation(Interface):
"""Information about the orientation of text."""
characters = Choice(
title=u"Orientation of characters",
values=_orientations,
- default=u"left-to-right"
- )
+ default=u"left-to-right",
+ )
lines = Choice(
title=u"Orientation of characters",
values=_orientations,
- default=u"top-to-bottom"
- )
+ default=u"top-to-bottom",
+ )
+
class ILocale(Interface):
"""This class contains all important information about the locale.
@@ -610,24 +717,31 @@ class ILocale(Interface):
title=u"Locale identity",
description=u"ILocaleIdentity object identifying the locale.",
required=True,
- readonly=True)
+ readonly=True,
+ )
displayNames = Field(
title=u"Display Names",
- description=(u"""ILocaleDisplayNames object that contains localized
- names."""))
+ description=(
+ u"""ILocaleDisplayNames object that contains localized
+ names."""
+ ),
+ )
dates = Field(
title=u"Dates",
- description=u"ILocaleDates object that contains date/time data.")
+ description=u"ILocaleDates object that contains date/time data.",
+ )
numbers = Field(
title=u"Numbers",
- description=u"ILocaleNumbers object that contains number data.")
+ description=u"ILocaleNumbers object that contains number data.",
+ )
orientation = Field(
title=u"Orientation",
- description=u"ILocaleOrientation with text orientation info.")
+ description=u"ILocaleOrientation with text orientation info.",
+ )
delimiters = Dict(
title=u"Delimiters",
@@ -635,11 +749,15 @@ class ILocale(Interface):
key_type=Choice(
title=u"Delimiter Type",
description=u"Delimiter name.",
- values=(u"quotationStart",
- u"quotationEnd",
- u"alternateQuotationStart",
- u"alternateQuotationEnd")),
- value_type=Field(title=u"Delimiter symbol"))
+ values=(
+ u"quotationStart",
+ u"quotationEnd",
+ u"alternateQuotationStart",
+ u"alternateQuotationEnd",
+ ),
+ ),
+ value_type=Field(title=u"Delimiter symbol"),
+ )
def getLocaleID():
"""Return a locale id as specified in the LDML specification"""
@@ -657,8 +775,11 @@ class ILocaleInheritance(Interface):
__name__ = TextLine(
title=u"The name within the parent",
- description=(u"""The parent can be traversed with this name to get
- the object."""))
+ description=(
+ u"""The parent can be traversed with this name to get
+ the object."""
+ ),
+ )
def getInheritedSelf():
"""Return itself but in the next higher up Locale."""
@@ -699,6 +820,7 @@ class IDictionaryInheritance(ILocaleInheritance):
object is consulted.
"""
+
class ICollator(Interface):
"""Provide support for collating text strings
@@ -706,8 +828,7 @@ class ICollator(Interface):
"""
def key(text):
- """Return a collation key for the given text.
- """
+ """Return a collation key for the given text."""
def cmp(text1, text2):
"""Compare two text strings.
diff --git a/src/zope/i18n/locales/__init__.py b/src/zope/i18n/locales/__init__.py
index 030c453..27de94c 100644
--- a/src/zope/i18n/locales/__init__.py
+++ b/src/zope/i18n/locales/__init__.py
@@ -28,13 +28,17 @@ from zope.i18n.interfaces.locales import ILocaleFormat, ILocaleFormatLength
from zope.i18n.interfaces.locales import ILocaleOrientation
from zope.i18n.interfaces.locales import ILocaleDayContext, ILocaleMonthContext
from zope.i18n.format import NumberFormat, DateTimeFormat
-from zope.i18n.locales.inheritance import \
- AttributeInheritance, InheritingDictionary, NoParentException
+from zope.i18n.locales.inheritance import (
+ AttributeInheritance,
+ InheritingDictionary,
+ NoParentException,
+)
from zope.i18n.locales.provider import LocaleProvider, LoadLocaleError
# Setup the locale directory
from zope import i18n
+
LOCALEDIR = os.path.join(os.path.dirname(i18n.__file__), "locales", "data")
# Global LocaleProvider. We really just need this single one.
@@ -63,15 +67,25 @@ FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
-dayMapping = {'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4,
- 'fri': 5, 'sat': 6, 'sun': 7}
+dayMapping = {
+ 'mon': 1,
+ 'tue': 2,
+ 'wed': 3,
+ 'thu': 4,
+ 'fri': 5,
+ 'sat': 6,
+ 'sun': 7,
+}
BC = 1
AD = 2
-calendarAliases = {'islamic': ('arabic',),
- 'islamic-civil': ('civil-arabic',),
- 'buddhist': ('thai-buddhist', )}
+calendarAliases = {
+ 'islamic': ('arabic',),
+ 'islamic-civil': ('civil-arabic',),
+ 'buddhist': ('thai-buddhist',),
+}
+
@implementer(ILocaleIdentity)
class LocaleIdentity(object):
@@ -102,7 +116,9 @@ class LocaleIdentity(object):
<LocaleIdentity (en, None, US, POSIX)>
"""
- def __init__(self, language=None, script=None, territory=None, variant=None):
+ def __init__(
+ self, language=None, script=None, territory=None, variant=None
+ ):
"""Initialize object."""
self.language = language
self.script = script
@@ -110,10 +126,13 @@ class LocaleIdentity(object):
self.variant = variant
def __repr__(self):
- """See zope.i18n.interfaces.ILocaleIdentity
- """
- return "<LocaleIdentity (%s, %s, %s, %s)>" %(
- self.language, self.script, self.territory, self.variant)
+ """See zope.i18n.interfaces.ILocaleIdentity"""
+ return "<LocaleIdentity (%s, %s, %s, %s)>" % (
+ self.language,
+ self.script,
+ self.territory,
+ self.variant,
+ )
@implementer(ILocaleVersion)
@@ -151,12 +170,17 @@ class LocaleVersion(object):
self.notes = notes
def __lt__(self, other):
- return ((self.generationDate, self.number) <
- (other.generationDate, other.number))
+ return (self.generationDate, self.number) < (
+ other.generationDate,
+ other.number,
+ )
def __eq__(self, other):
- return ((self.generationDate, self.number) ==
- (other.generationDate, other.number))
+ return (self.generationDate, self.number) == (
+ other.generationDate,
+ other.number,
+ )
+
@implementer(ILocaleDisplayNames)
class LocaleDisplayNames(AttributeInheritance):
@@ -233,7 +257,6 @@ class LocaleFormatLength(AttributeInheritance):
"""Specifies one of the format lengths of a specific quantity, like
numbers, dates, times and datetimes."""
-
def __init__(self, type=None):
"""Initialize the object."""
self.type = type
@@ -242,7 +265,6 @@ class LocaleFormatLength(AttributeInheritance):
@implementer(ILocaleMonthContext)
class LocaleMonthContext(AttributeInheritance):
-
def __init__(self, type=None):
"""Initialize the object."""
self.type = type
@@ -251,7 +273,6 @@ class LocaleMonthContext(AttributeInheritance):
@implementer(ILocaleDayContext)
class LocaleDayContext(AttributeInheritance):
-
def __init__(self, type=None):
"""Initialize the object."""
self.type = type
@@ -343,7 +364,9 @@ class LocaleCalendar(AttributeInheritance):
def getMonthNames(self):
"""See zope.i18n.interfaces.ILocaleCalendar"""
- return [self.months.get(type, (None, None))[0] for type in range(1, 13)]
+ return [
+ self.months.get(type, (None, None))[0] for type in range(1, 13)
+ ]
def getMonthTypeFromName(self, name):
"""See zope.i18n.interfaces.ILocaleCalendar"""
@@ -353,7 +376,9 @@ class LocaleCalendar(AttributeInheritance):
def getMonthAbbreviations(self):
"""See zope.i18n.interfaces.ILocaleCalendar"""
- return [self.months.get(type, (None, None))[1] for type in range(1, 13)]
+ return [
+ self.months.get(type, (None, None))[1] for type in range(1, 13)
+ ]
def getMonthTypeFromAbbreviation(self, abbr):
"""See zope.i18n.interfaces.ILocaleCalendar"""
@@ -491,26 +516,34 @@ class LocaleDates(AttributeInheritance):
"""
- def getFormatter(self, category, length=None, name=None,
- calendar=u"gregorian"):
+ def getFormatter(
+ self, category, length=None, name=None, calendar=u"gregorian"
+ ):
"""See zope.i18n.interfaces.locales.ILocaleDates"""
if category not in (u"date", u"time", u"dateTime"):
raise ValueError('Invalid category: %s' % category)
- if calendar not in (u"gregorian", u"arabic", u"chinese",
- u"civil-arabic", u"hebrew", u"japanese",
- u"thai-buddhist"):
+ if calendar not in (
+ u"gregorian",
+ u"arabic",
+ u"chinese",
+ u"civil-arabic",
+ u"hebrew",
+ u"japanese",
+ u"thai-buddhist",
+ ):
raise ValueError('Invalid calendar: %s' % calendar)
if length not in (u"short", u"medium", u"long", u"full", None):
raise ValueError('Invalid format length: %s' % length)
cal = self.calendars[calendar]
- formats = getattr(cal, category+'Formats')
+ formats = getattr(cal, category + 'Formats')
if length is None:
length = getattr(
cal,
- 'default'+category[0].upper()+category[1:]+'Format',
- list(formats.keys())[0])
+ 'default' + category[0].upper() + category[1:] + 'Format',
+ list(formats.keys())[0],
+ )
# 'datetime' is always a bit special; we often do not have a length
# specification, but we need it for looking up the date and time
@@ -528,9 +561,11 @@ class LocaleDates(AttributeInheritance):
if category == 'dateTime':
date_pat = self.getFormatter(
- 'date', length, name, calendar).getPattern()
+ 'date', length, name, calendar
+ ).getPattern()
time_pat = self.getFormatter(
- 'time', length, name, calendar).getPattern()
+ 'time', length, name, calendar
+ ).getPattern()
pattern = pattern.replace('{1}', date_pat)
pattern = pattern.replace('{0}', time_pat)
@@ -636,7 +671,8 @@ class LocaleNumbers(AttributeInheritance):
length = getattr(
self,
'default' + category[0].upper() + category[1:] + 'Format',
- list(formats.keys())[0])
+ list(formats.keys())[0],
+ )
formatLength = formats[length]
if name is None:
@@ -649,8 +685,8 @@ class LocaleNumbers(AttributeInheritance):
@implementer(ILocaleOrientation)
class LocaleOrientation(AttributeInheritance):
- """Implementation of ILocaleOrientation
- """
+ """Implementation of ILocaleOrientation"""
+
@implementer(ILocale)
class Locale(AttributeInheritance):
@@ -682,15 +718,15 @@ class Locale(AttributeInheritance):
"""
id = self.id
- pieces = [x for x in
- (id.language, id.script, id.territory, id.variant)
- if x]
+ pieces = [
+ x for x in (id.language, id.script, id.territory, id.variant) if x
+ ]
id_string = '_'.join(pieces)
# TODO: What about keys??? Where do I get this info from?
# Notice that 'pieces' is always empty.
pieces = [key + '=' + type for (key, type) in ()]
assert not pieces
- if pieces: # pragma: no cover
+ if pieces: # pragma: no cover
id_string += '@' + ','.join(pieces)
return id_string
diff --git a/src/zope/i18n/locales/fallbackcollator.py b/src/zope/i18n/locales/fallbackcollator.py
index fc76a58..f747b34 100644
--- a/src/zope/i18n/locales/fallbackcollator.py
+++ b/src/zope/i18n/locales/fallbackcollator.py
@@ -16,8 +16,8 @@
from unicodedata import normalize
-class FallbackCollator:
+class FallbackCollator:
def __init__(self, locale):
pass
diff --git a/src/zope/i18n/locales/inheritance.py b/src/zope/i18n/locales/inheritance.py
index 912d8c9..5cfe7e8 100644
--- a/src/zope/i18n/locales/inheritance.py
+++ b/src/zope/i18n/locales/inheritance.py
@@ -23,12 +23,17 @@ __docformat__ = 'restructuredtext'
from zope.deprecation import deprecate
from zope.interface import implementer
-from zope.i18n.interfaces.locales import \
- ILocaleInheritance, IAttributeInheritance, IDictionaryInheritance
+from zope.i18n.interfaces.locales import (
+ ILocaleInheritance,
+ IAttributeInheritance,
+ IDictionaryInheritance,
+)
+
class NoParentException(AttributeError):
pass
+
@implementer(ILocaleInheritance)
class Inheritance(object):
"""A simple base version of locale inheritance.
@@ -37,7 +42,6 @@ class Inheritance(object):
'ILocaleInheritance' implementations.
"""
-
# See zope.i18n.interfaces.locales.ILocaleInheritance
__parent__ = None
@@ -100,18 +104,15 @@ class AttributeInheritance(Inheritance):
True
"""
-
def __setattr__(self, name, value):
"""See zope.i18n.interfaces.locales.ILocaleInheritance"""
# If we have a value that can also inherit data from other locales, we
# set its parent and name, so that we know how to get to it.
- if (ILocaleInheritance.providedBy(value) and
- not name.startswith('__')):
+ if ILocaleInheritance.providedBy(value) and not name.startswith('__'):
value.__parent__ = self
value.__name__ = name
super(AttributeInheritance, self).__setattr__(name, value)
-
def __getattr__(self, name):
"""See zope.i18n.interfaces.locales.ILocaleInheritance"""
try:
@@ -119,9 +120,10 @@ class AttributeInheritance(Inheritance):
except NoParentException:
# There was simply no parent anymore, so let's raise an error
# for good
- raise AttributeError("'%s' object (or any of its parents) has no "
- "attribute '%s'" % (self.__class__.__name__,
- name))
+ raise AttributeError(
+ "'%s' object (or any of its parents) has no "
+ "attribute '%s'" % (self.__class__.__name__, name)
+ )
else:
value = getattr(selfUp, name)
# Since a locale hierarchy never changes after startup, we can
@@ -134,7 +136,6 @@ class AttributeInheritance(Inheritance):
return value
-
@implementer(IDictionaryInheritance)
class InheritingDictionary(Inheritance, dict):
"""Implementation of a dictionary that can also inherit values.
@@ -197,7 +198,6 @@ class InheritingDictionary(Inheritance, dict):
`value` is a deprecated synonym for `values`
"""
-
def __setitem__(self, name, value):
"""See zope.i18n.interfaces.locales.ILocaleInheritance"""
if ILocaleInheritance.providedBy(value):
diff --git a/src/zope/i18n/locales/provider.py b/src/zope/i18n/locales/provider.py
index 3864b7a..5ed415f 100644
--- a/src/zope/i18n/locales/provider.py
+++ b/src/zope/i18n/locales/provider.py
@@ -20,6 +20,7 @@ import os
from zope.interface import implementer
from zope.i18n.interfaces.locales import ILocaleProvider
+
class LoadLocaleError(Exception):
"""This error is raised if a locale cannot be loaded."""
@@ -28,7 +29,6 @@ class LoadLocaleError(Exception):
class LocaleProvider(object):
"""A locale provider that gets its data from the XML data."""
-
def __init__(self, locale_dir):
self._locales = {}
self._locale_dir = locale_dir
@@ -55,7 +55,8 @@ class LocaleProvider(object):
path = os.path.join(self._locale_dir, filename)
if not os.path.exists(path):
raise LoadLocaleError(
- 'The desired locale is not available.\nPath: %s' % path)
+ 'The desired locale is not available.\nPath: %s' % path
+ )
# Import here to avoid circular imports
from zope.i18n.locales.xmlfactory import LocaleFactory
diff --git a/src/zope/i18n/locales/tests/test_docstrings.py b/src/zope/i18n/locales/tests/test_docstrings.py
index fa52078..c40b691 100644
--- a/src/zope/i18n/locales/tests/test_docstrings.py
+++ b/src/zope/i18n/locales/tests/test_docstrings.py
@@ -20,8 +20,8 @@ from zope.i18n.locales.inheritance import NoParentException
from zope.i18n.testing import unicode_checker
-class LocaleInheritanceStub(AttributeInheritance):
+class LocaleInheritanceStub(AttributeInheritance):
def __init__(self, nextLocale=None):
self.__nextLocale__ = nextLocale
@@ -32,11 +32,18 @@ class LocaleInheritanceStub(AttributeInheritance):
def test_suite():
- return unittest.TestSuite((
- DocTestSuite('zope.i18n.locales', checker=unicode_checker),
- DocTestSuite('zope.i18n.locales.inheritance', checker=unicode_checker),
- DocTestSuite('zope.i18n.locales.xmlfactory', checker=unicode_checker),
- ))
+ return unittest.TestSuite(
+ (
+ DocTestSuite('zope.i18n.locales', checker=unicode_checker),
+ DocTestSuite(
+ 'zope.i18n.locales.inheritance', checker=unicode_checker
+ ),
+ DocTestSuite(
+ 'zope.i18n.locales.xmlfactory', checker=unicode_checker
+ ),
+ )
+ )
+
if __name__ == '__main__':
unittest.main()
diff --git a/src/zope/i18n/locales/tests/test_fallbackcollator.py b/src/zope/i18n/locales/tests/test_fallbackcollator.py
index 7e10b50..4ecf34d 100644
--- a/src/zope/i18n/locales/tests/test_fallbackcollator.py
+++ b/src/zope/i18n/locales/tests/test_fallbackcollator.py
@@ -17,11 +17,16 @@ import doctest
from zope.i18n.testing import unicode_checker
+
def test_suite():
- return unittest.TestSuite((
- doctest.DocFileSuite('../fallbackcollator.txt', checker=unicode_checker),
- ))
+ return unittest.TestSuite(
+ (
+ doctest.DocFileSuite(
+ '../fallbackcollator.txt', checker=unicode_checker
+ ),
+ )
+ )
+
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
diff --git a/src/zope/i18n/locales/tests/test_locales.py b/src/zope/i18n/locales/tests/test_locales.py
index 2b100b8..58cecda 100644
--- a/src/zope/i18n/locales/tests/test_locales.py
+++ b/src/zope/i18n/locales/tests/test_locales.py
@@ -22,8 +22,10 @@ from zope.i18n.locales import locales
from zope.i18n.locales.provider import LocaleProvider, LoadLocaleError
import zope.i18n
+
datadir = os.path.join(os.path.dirname(zope.i18n.__file__), 'locales', 'data')
+
class AbstractTestILocaleProviderMixin(object):
"""Test the functionality of an implmentation of the ILocaleProvider
interface."""
@@ -60,14 +62,14 @@ class AbstractTestILocaleProviderMixin(object):
class TestLocaleProvider(AbstractTestILocaleProviderMixin, TestCase):
-
def _makeNewProvider(self):
return LocaleProvider(datadir)
def test_loadLocale(self):
self.locales.loadLocale(None, None, None)
- self.assertEqual(list(self.locales._locales.keys()),
- [(None, None, None)])
+ self.assertEqual(
+ list(self.locales._locales.keys()), [(None, None, None)]
+ )
self.locales.loadLocale('en', None, None)
self.assertIn(('en', None, None), self.locales._locales.keys())
@@ -94,27 +96,34 @@ class TestLocaleAndProvider(TestCase):
def test_getTimeFormatter(self):
formatter = self.locale.dates.getFormatter('time', 'medium')
self.assertEqual(formatter.getPattern(), 'h:mm:ss a')
- self.assertEqual(formatter.format(datetime.time(12, 30, 10)),
- '12:30:10 PM')
- self.assertEqual(formatter.parse('12:30:10 PM'),
- datetime.time(12, 30, 10))
+ self.assertEqual(
+ formatter.format(datetime.time(12, 30, 10)), '12:30:10 PM'
+ )
+ self.assertEqual(
+ formatter.parse('12:30:10 PM'), datetime.time(12, 30, 10)
+ )
def test_getDateFormatter(self):
formatter = self.locale.dates.getFormatter('date', 'medium')
self.assertEqual(formatter.getPattern(), 'MMM d, yyyy')
- self.assertEqual(formatter.format(datetime.date(2003, 1, 2)),
- 'Jan 2, 2003')
- self.assertEqual(formatter.parse('Jan 2, 2003'),
- datetime.date(2003, 1, 2))
+ self.assertEqual(
+ formatter.format(datetime.date(2003, 1, 2)), 'Jan 2, 2003'
+ )
+ self.assertEqual(
+ formatter.parse('Jan 2, 2003'), datetime.date(2003, 1, 2)
+ )
def test_getDateTimeFormatter(self):
formatter = self.locale.dates.getFormatter('dateTime', 'medium')
self.assertEqual(formatter.getPattern(), 'MMM d, yyyy h:mm:ss a')
self.assertEqual(
formatter.format(datetime.datetime(2003, 1, 2, 12, 30)),
- 'Jan 2, 2003 12:30:00 PM')
- self.assertEqual(formatter.parse('Jan 2, 2003 12:30:00 PM'),
- datetime.datetime(2003, 1, 2, 12, 30))
+ 'Jan 2, 2003 12:30:00 PM',
+ )
+ self.assertEqual(
+ formatter.parse('Jan 2, 2003 12:30:00 PM'),
+ datetime.datetime(2003, 1, 2, 12, 30),
+ )
def test_getNumberFormatter(self):
formatter = self.locale.numbers.getFormatter('decimal')
@@ -126,7 +135,6 @@ class TestLocaleAndProvider(TestCase):
class TestGlobalLocaleProvider(TestCase):
-
def testLoading(self):
locales.loadLocale(None, None, None)
self.assertIn((None, None, None), locales._locales)
@@ -143,6 +151,7 @@ class TestGlobalLocaleProvider(TestCase):
self.assertEqual(locale.id.territory, 'GB')
self.assertEqual(locale.id.variant, None)
+
class TestRootLocale(TestCase):
"""There were some complaints that the root locale does not work
correctly, so make sure it does."""
@@ -153,10 +162,14 @@ class TestRootLocale(TestCase):
def test_dateFormatter(self):
formatter = self.locale.dates.getFormatter('date')
self.assertEqual(
- formatter.format(datetime.date(2004, 10, 31), 'E'), '1')
+ formatter.format(datetime.date(2004, 10, 31), 'E'), '1'
+ )
self.assertEqual(
- formatter.format(datetime.date(2004, 10, 31), 'EE'), '01')
+ formatter.format(datetime.date(2004, 10, 31), 'EE'), '01'
+ )
self.assertEqual(
- formatter.format(datetime.date(2004, 10, 31), 'EEE'), '1')
+ formatter.format(datetime.date(2004, 10, 31), 'EEE'), '1'
+ )
self.assertEqual(
- formatter.format(datetime.date(2004, 10, 31), 'EEEE'), '1')
+ formatter.format(datetime.date(2004, 10, 31), 'EEEE'), '1'
+ )
diff --git a/src/zope/i18n/locales/tests/test_xmlfactory.py b/src/zope/i18n/locales/tests/test_xmlfactory.py
index 792c96d..b1c09bd 100644
--- a/src/zope/i18n/locales/tests/test_xmlfactory.py
+++ b/src/zope/i18n/locales/tests/test_xmlfactory.py
@@ -19,6 +19,7 @@ from unittest import TestCase, TestSuite
from zope.i18n.locales.xmlfactory import LocaleFactory
import zope.i18n
+
class LocaleXMLFileTestCase(TestCase):
"""This test verifies that every locale XML file can be loaded."""
@@ -34,13 +35,13 @@ class LocaleXMLFileTestCase(TestCase):
# necessary for the xml files to have all format definitions.
## Making sure all number format patterns parse
- #for category in (u'decimal', u'scientific', u'percent', u'currency'):
+ # for category in (u'decimal', u'scientific', u'percent', u'currency'):
# for length in getattr(locale.numbers, category+'Formats').values():
# for format in length.formats.values():
# self.assert_(parseNumberPattern(format.pattern) is not None)
## Making sure all datetime patterns parse
- #for calendar in locale.dates.calendars.values():
+ # for calendar in locale.dates.calendars.values():
# for category in ('date', 'time', 'dateTime'):
# for length in getattr(calendar, category+'Formats').values():
# for format in length.formats.values():
@@ -48,11 +49,11 @@ class LocaleXMLFileTestCase(TestCase):
# parseDateTimePattern(format.pattern) is not None)
-
def test_suite():
suite = TestSuite()
- locale_dir = os.path.join(os.path.dirname(zope.i18n.__file__),
- 'locales', 'data')
+ locale_dir = os.path.join(
+ os.path.dirname(zope.i18n.__file__), 'locales', 'data'
+ )
for path in os.listdir(locale_dir):
if not path.endswith(".xml"):
continue
diff --git a/src/zope/i18n/locales/xmlfactory.py b/src/zope/i18n/locales/xmlfactory.py
index 5b2dbf5..244d17e 100644
--- a/src/zope/i18n/locales/xmlfactory.py
+++ b/src/zope/i18n/locales/xmlfactory.py
@@ -41,7 +41,6 @@ class LocaleFactory(object):
rc = rc + node.data
return rc
-
def _extractVersion(self, identity_node):
"""Extract the Locale's version info based on data from the DOM
tree.
@@ -81,7 +80,6 @@ class LocaleFactory(object):
return LocaleVersion(number, generationDate, notes)
-
def _extractIdentity(self):
"""Extract the Locale's identity object based on info from the DOM
tree.
@@ -119,7 +117,7 @@ class LocaleFactory(object):
# Retrieve the language of the locale
nodes = identity.getElementsByTagName('language')
if nodes != []:
- id.language = nodes[0].getAttribute('type') or None
+ id.language = nodes[0].getAttribute('type') or None
# Retrieve the territory of the locale
nodes = identity.getElementsByTagName('territory')
if nodes != []:
@@ -132,7 +130,6 @@ class LocaleFactory(object):
id.version = self._extractVersion(identity)
return id
-
def _extractTypes(self, names_node):
"""Extract all types from the names_node.
@@ -179,7 +176,6 @@ class LocaleFactory(object):
types[(type, key)] = self._getText(type_node.childNodes)
return types
-
def _extractDisplayNames(self):
"""Extract all display names from the DOM tree.
@@ -265,11 +261,13 @@ class LocaleFactory(object):
if names_nodes == []:
return displayNames
- for group_tag, single_tag in (('languages', 'language'),
- ('scripts', 'script'),
- ('territories', 'territory'),
- ('variants', 'variant'),
- ('keys', 'key')):
+ for group_tag, single_tag in (
+ ('languages', 'language'),
+ ('scripts', 'script'),
+ ('territories', 'territory'),
+ ('variants', 'variant'),
+ ('keys', 'key'),
+ ):
group_nodes = names_nodes[0].getElementsByTagName(group_tag)
if group_nodes == []:
continue
@@ -285,7 +283,6 @@ class LocaleFactory(object):
displayNames.types = types
return displayNames
-
def _extractMonths(self, months_node, calendar):
"""Extract all month entries from cal_node and store them in calendar.
@@ -385,14 +382,16 @@ class LocaleFactory(object):
defaultMonthContext_node = months_node.getElementsByTagName('default')
if defaultMonthContext_node:
- calendar.defaultMonthContext = defaultMonthContext_node[0].getAttribute('type')
+ calendar.defaultMonthContext = defaultMonthContext_node[
+ 0
+ ].getAttribute('type')
monthContext_nodes = months_node.getElementsByTagName('monthContext')
if not monthContext_nodes:
return
calendar.monthContexts = InheritingDictionary()
- names_node = abbrs_node = None # BBB
+ names_node = abbrs_node = None # BBB
for node in monthContext_nodes:
context_type = node.getAttribute('type')
@@ -438,9 +437,10 @@ class LocaleFactory(object):
# Put the info together
calendar.months = InheritingDictionary()
for type in range(1, 13):
- calendar.months[type] = (names.get(type, None),
- abbrs.get(type, None))
-
+ calendar.months[type] = (
+ names.get(type, None),
+ abbrs.get(type, None),
+ )
def _extractDays(self, days_node, calendar):
"""Extract all day entries from cal_node and store them in
@@ -529,14 +529,16 @@ class LocaleFactory(object):
defaultDayContext_node = days_node.getElementsByTagName('default')
if defaultDayContext_node:
- calendar.defaultDayContext = defaultDayContext_node[0].getAttribute('type')
+ calendar.defaultDayContext = defaultDayContext_node[
+ 0
+ ].getAttribute('type')
dayContext_nodes = days_node.getElementsByTagName('dayContext')
if not dayContext_nodes:
return
calendar.dayContexts = InheritingDictionary()
- names_node = abbrs_node = None # BBB
+ names_node = abbrs_node = None # BBB
for node in dayContext_nodes:
context_type = node.getAttribute('type')
@@ -581,9 +583,10 @@ class LocaleFactory(object):
# Put the info together
calendar.days = InheritingDictionary()
for type in range(1, 13):
- calendar.days[type] = (names.get(type, None),
- abbrs.get(type, None))
-
+ calendar.days[type] = (
+ names.get(type, None),
+ abbrs.get(type, None),
+ )
def _extractWeek(self, cal_node, calendar):
"""Extract all week entries from cal_node and store them in
@@ -644,7 +647,6 @@ class LocaleFactory(object):
time_args = map(int, node.getAttribute('time').split(':'))
calendar.week['weekendEnd'] = (day, time(*time_args))
-
def _extractEras(self, cal_node, calendar):
"""Extract all era entries from cal_node and store them in
calendar.
@@ -703,8 +705,10 @@ class LocaleFactory(object):
calendar.eras = InheritingDictionary()
for type in abbrs.keys():
- calendar.eras[type] = (names.get(type, None), abbrs.get(type, None))
-
+ calendar.eras[type] = (
+ names.get(type, None),
+ abbrs.get(type, None),
+ )
def _extractFormats(self, formats_node, lengthNodeName, formatNodeName):
"""Extract all format entries from formats_node and return a
@@ -765,14 +769,18 @@ class LocaleFactory(object):
if length_node.getElementsByTagName(formatNodeName):
length.formats = InheritingDictionary()
- for format_node in length_node.getElementsByTagName(formatNodeName):
+ for format_node in length_node.getElementsByTagName(
+ formatNodeName
+ ):
format = LocaleFormat()
format.type = format_node.getAttribute('type') or None
pattern_node = format_node.getElementsByTagName('pattern')[0]
format.pattern = self._getText(pattern_node.childNodes)
name_nodes = format_node.getElementsByTagName('displayName')
if name_nodes:
- format.displayName = self._getText(name_nodes[0].childNodes)
+ format.displayName = self._getText(
+ name_nodes[0].childNodes
+ )
length.formats[format.type] = format
lengths[length.type] = length
@@ -905,17 +913,21 @@ class LocaleFactory(object):
self._extractEras(cal_node, calendar)
for formatsName, lengthName, formatName in (
- ('dateFormats', 'dateFormatLength', 'dateFormat'),
- ('timeFormats', 'timeFormatLength', 'timeFormat'),
- ('dateTimeFormats', 'dateTimeFormatLength', 'dateTimeFormat')):
+ ('dateFormats', 'dateFormatLength', 'dateFormat'),
+ ('timeFormats', 'timeFormatLength', 'timeFormat'),
+ ('dateTimeFormats', 'dateTimeFormatLength', 'dateTimeFormat'),
+ ):
formats_nodes = cal_node.getElementsByTagName(formatsName)
if formats_nodes:
default, formats = self._extractFormats(
- formats_nodes[0], lengthName, formatName)
- setattr(calendar,
- 'default'+formatName[0].upper()+formatName[1:],
- default)
+ formats_nodes[0], lengthName, formatName
+ )
+ setattr(
+ calendar,
+ 'default' + formatName[0].upper() + formatName[1:],
+ default,
+ )
setattr(calendar, formatsName, formats)
calendars[calendar.type] = calendar
@@ -925,7 +937,6 @@ class LocaleFactory(object):
return calendars
-
def _extractTimeZones(self, dates_node):
"""Extract all timezone information for the locale from the DOM
tree.
@@ -1009,7 +1020,6 @@ class LocaleFactory(object):
return zones
-
def _extractDates(self):
"""Extract all date information from the DOM tree"""
dates_nodes = self._data.getElementsByTagName('dates')
@@ -1025,7 +1035,6 @@ class LocaleFactory(object):
dates.timezones = timezones
return dates
-
def _extractSymbols(self, numbers_node):
"""Extract all week entries from cal_node and store them in
calendar.
@@ -1071,17 +1080,26 @@ class LocaleFactory(object):
return
symbols = InheritingDictionary()
- for name in (u"decimal", u"group", u"list", u"percentSign",
- u"nativeZeroDigit", u"patternDigit", u"plusSign",
- u"minusSign", u"exponential", u"perMille",
- u"infinity", u"nan"):
+ for name in (
+ u"decimal",
+ u"group",
+ u"list",
+ u"percentSign",
+ u"nativeZeroDigit",
+ u"patternDigit",
+ u"plusSign",
+ u"minusSign",
+ u"exponential",
+ u"perMille",
+ u"infinity",
+ u"nan",
+ ):
nodes = symbols_nodes[0].getElementsByTagName(name)
if nodes:
symbols[name] = self._getText(nodes[0].childNodes)
return symbols
-
def _extractNumberFormats(self, numbers_node, numbers):
"""Extract all number formats from the numbers_node and save the data
in numbers.
@@ -1162,19 +1180,19 @@ class LocaleFactory(object):
"""
for category in ('decimal', 'scientific', 'percent', 'currency'):
- formatsName = category+'Formats'
- lengthName = category+'FormatLength'
- formatName = category+'Format'
- defaultName = 'default'+formatName[0].upper()+formatName[1:]
+ formatsName = category + 'Formats'
+ lengthName = category + 'FormatLength'
+ formatName = category + 'Format'
+ defaultName = 'default' + formatName[0].upper() + formatName[1:]
formats_nodes = numbers_node.getElementsByTagName(formatsName)
if formats_nodes:
default, formats = self._extractFormats(
- formats_nodes[0], lengthName, formatName)
+ formats_nodes[0], lengthName, formatName
+ )
setattr(numbers, defaultName, default)
setattr(numbers, formatsName, formats)
-
def _extractCurrencies(self, numbers_node):
"""Extract all currency definitions and their information from the
Locale's DOM tree.
@@ -1231,8 +1249,9 @@ class LocaleFactory(object):
nodes = curr_node.getElementsByTagName('symbol')
if nodes:
currency.symbol = self._getText(nodes[0].childNodes)
- currency.symbolChoice = \
- nodes[0].getAttribute('choice') == u"true"
+ currency.symbolChoice = (
+ nodes[0].getAttribute('choice') == u"true"
+ )
nodes = curr_node.getElementsByTagName('displayName')
if nodes:
@@ -1242,7 +1261,6 @@ class LocaleFactory(object):
return currencies
-
def _extractNumbers(self):
"""Extract all number information from the DOM tree"""
numbers_nodes = self._data.getElementsByTagName('numbers')
@@ -1259,7 +1277,6 @@ class LocaleFactory(object):
numbers.currencies = currencies
return numbers
-
def _extractDelimiters(self):
"""Extract all delimiter entries from the DOM tree.
@@ -1307,33 +1324,36 @@ class LocaleFactory(object):
return
delimiters = InheritingDictionary()
- for name in (u'quotationStart', u"quotationEnd",
- u"alternateQuotationStart", u"alternateQuotationEnd"):
+ for name in (
+ u'quotationStart',
+ u"quotationEnd",
+ u"alternateQuotationStart",
+ u"alternateQuotationEnd",
+ ):
nodes = delimiters_nodes[0].getElementsByTagName(name)
if nodes:
delimiters[name] = self._getText(nodes[0].childNodes)
return delimiters
-
def _extractOrientation(self):
"""Extract orientation information.
- >>> factory = LocaleFactory(None)
- >>> from xml.dom.minidom import parseString
- >>> xml = u'''
- ... <ldml>
- ... <layout>
- ... <orientation lines="bottom-to-top" characters="right-to-left" />
- ... </layout>
- ... </ldml>'''
- >>> dom = parseString(xml)
- >>> factory._data = parseString(xml).documentElement
- >>> orientation = factory._extractOrientation()
- >>> orientation.lines
- u'bottom-to-top'
- >>> orientation.characters
- u'right-to-left'
+ >>> factory = LocaleFactory(None)
+ >>> from xml.dom.minidom import parseString
+ >>> xml = u'''
+ ... <ldml>
+ ... <layout>
+ ... <orientation lines="bottom-to-top" characters="right-to-left" />
+ ... </layout>
+ ... </ldml>'''
+ >>> dom = parseString(xml)
+ >>> factory._data = parseString(xml).documentElement
+ >>> orientation = factory._extractOrientation()
+ >>> orientation.lines
+ u'bottom-to-top'
+ >>> orientation.characters
+ u'right-to-left'
"""
orientation_nodes = self._data.getElementsByTagName('orientation')
if not orientation_nodes:
@@ -1345,7 +1365,6 @@ class LocaleFactory(object):
setattr(orientation, name, value)
return orientation
-
def __call__(self):
"""Create the Locale."""
locale = Locale(self._extractIdentity())
diff --git a/src/zope/i18n/negotiator.py b/src/zope/i18n/negotiator.py
index 3c5fa17..8fa0609 100644
--- a/src/zope/i18n/negotiator.py
+++ b/src/zope/i18n/negotiator.py
@@ -36,7 +36,6 @@ def normalize_langs(langs):
@implementer(INegotiator)
class Negotiator(object):
-
def getLanguage(self, langs, env):
envadapter = IUserPreferredLanguages(env)
userlangs = envadapter.getPreferredLanguages()
diff --git a/src/zope/i18n/simpletranslationdomain.py b/src/zope/i18n/simpletranslationdomain.py
index b093db8..889d6db 100644
--- a/src/zope/i18n/simpletranslationdomain.py
+++ b/src/zope/i18n/simpletranslationdomain.py
@@ -25,15 +25,15 @@ text_type = str if bytes is not str else unicode
@implementer(ITranslationDomain)
class SimpleTranslationDomain(object):
"""This is the simplest implementation of the ITranslationDomain I
- could come up with.
+ could come up with.
- The constructor takes one optional argument 'messages', which will be
- used to do the translation. The 'messages' attribute has to have the
- following structure:
+ The constructor takes one optional argument 'messages', which will be
+ used to do the translation. The 'messages' attribute has to have the
+ following structure:
- {('language', 'msg_id'): 'message', ...}
+ {('language', 'msg_id'): 'message', ...}
- Note: This Translation Domain does not use message catalogs.
+ Note: This Translation Domain does not use message catalogs.
"""
# See zope.i18n.interfaces.ITranslationDomain
@@ -42,13 +42,22 @@ class SimpleTranslationDomain(object):
def __init__(self, domain, messages=None):
"""Initializes the object. No arguments are needed."""
self.domain = (
- domain.decode("utf-8") if isinstance(domain, bytes) else domain)
+ domain.decode("utf-8") if isinstance(domain, bytes) else domain
+ )
self.messages = messages if messages is not None else {}
assert self.messages is not None
- def translate(self, msgid, mapping=None, context=None,
- target_language=None, default=None, msgid_plural=None,
- default_plural=None, number=None):
+ def translate(
+ self,
+ msgid,
+ mapping=None,
+ context=None,
+ target_language=None,
+ default=None,
+ msgid_plural=None,
+ default_plural=None,
+ number=None,
+ ):
'''See interface ITranslationDomain'''
# Find out what the target language should be
if target_language is None and context is not None:
diff --git a/src/zope/i18n/testing.py b/src/zope/i18n/testing.py
index 035827c..8fd1c04 100644
--- a/src/zope/i18n/testing.py
+++ b/src/zope/i18n/testing.py
@@ -34,12 +34,12 @@ def setUp(test=None):
import zope.component
from zope.publisher.browser import BrowserLanguages
from zope.publisher.http import HTTPCharsets
+
zope.component.provideAdapter(HTTPCharsets)
zope.component.provideAdapter(BrowserLanguages)
class PlacelessSetup(object):
-
def setUp(self):
"""
Install the language and charset negotiators.
diff --git a/src/zope/i18n/testmessagecatalog.py b/src/zope/i18n/testmessagecatalog.py
index 8420c58..a06b15a 100644
--- a/src/zope/i18n/testmessagecatalog.py
+++ b/src/zope/i18n/testmessagecatalog.py
@@ -18,6 +18,7 @@ from zope import interface
import zope.i18n.interfaces
from zope.i18n.translationdomain import TranslationDomain
+
@interface.implementer(zope.i18n.interfaces.IGlobalMessageCatalog)
class TestMessageCatalog(object):
@@ -43,13 +44,15 @@ class TestMessageCatalog(object):
def reload(self):
pass
+
@interface.implementer(zope.i18n.interfaces.ITranslationDomain)
def TestMessageFallbackDomain(domain_id=u""):
domain = TranslationDomain(domain_id)
domain.addCatalog(TestMessageCatalog(domain_id))
return domain
+
interface.directlyProvides(
TestMessageFallbackDomain,
zope.i18n.interfaces.IFallbackTranslationDomainFactory,
- )
+)
diff --git a/src/zope/i18n/tests/test.py b/src/zope/i18n/tests/test.py
index 4fb4f4c..64fdbeb 100644
--- a/src/zope/i18n/tests/test.py
+++ b/src/zope/i18n/tests/test.py
@@ -22,18 +22,23 @@ from zope.i18n.testing import unicode_checker
def test_suite():
options = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
+
def suite(name):
return doctest.DocTestSuite(
name,
- setUp=setUp, tearDown=tearDown,
+ setUp=setUp,
+ tearDown=tearDown,
optionflags=options,
- checker=unicode_checker)
+ checker=unicode_checker,
+ )
- return unittest.TestSuite([
- suite('zope.i18n'),
- suite("zope.i18n.config"),
- suite("zope.i18n.testing"),
- ])
+ return unittest.TestSuite(
+ [
+ suite('zope.i18n'),
+ suite("zope.i18n.config"),
+ suite("zope.i18n.testing"),
+ ]
+ )
if __name__ == '__main__':
diff --git a/src/zope/i18n/tests/test_compile.py b/src/zope/i18n/tests/test_compile.py
index d82c3e7..214c240 100644
--- a/src/zope/i18n/tests/test_compile.py
+++ b/src/zope/i18n/tests/test_compile.py
@@ -19,10 +19,8 @@ from zope.testing.loggingsupport import InstalledHandler
from zope.i18n import compile
-@unittest.skipUnless(compile.HAS_PYTHON_GETTEXT,
- "Need python-gettext")
+@unittest.skipUnless(compile.HAS_PYTHON_GETTEXT, "Need python-gettext")
class TestCompile(unittest.TestCase):
-
def setUp(self):
self.handler = InstalledHandler('zope.i18n')
self.addCleanup(self.handler.uninstall)
@@ -43,8 +41,7 @@ class TestCompile(unittest.TestCase):
compile.compile_mo_file('foo', td)
- self.assertIn("Syntax error while compiling",
- str(self.handler))
+ self.assertIn("Syntax error while compiling", str(self.handler))
def test_po_exists_cannot_write_mo(self):
import tempfile
@@ -68,5 +65,4 @@ class TestCompile(unittest.TestCase):
compile.compile_mo_file('foo', td)
- self.assertIn("Error while compiling",
- str(self.handler))
+ self.assertIn("Error while compiling", str(self.handler))
diff --git a/src/zope/i18n/tests/test_formats.py b/src/zope/i18n/tests/test_formats.py
index 83c9129..29de8c9 100644
--- a/src/zope/i18n/tests/test_formats.py
+++ b/src/zope/i18n/tests/test_formats.py
@@ -34,6 +34,7 @@ from zope.i18n.format import NumberPatternParseError
class LocaleStub(object):
pass
+
class LocaleCalendarStub(object):
type = u"gregorian"
@@ -50,7 +51,7 @@ class LocaleCalendarStub(object):
9: ('September', 'Sep'),
10: ('Oktober', 'Okt'),
11: ('November', 'Nov'),
- 12: ('Dezember', 'Dez')
+ 12: ('Dezember', 'Dez'),
}
days = {
@@ -60,7 +61,7 @@ class LocaleCalendarStub(object):
4: ('Donnerstag', 'Do'),
5: ('Freitag', 'Fr'),
6: ('Samstag', 'Sa'),
- 7: ('Sonntag', 'So')
+ 7: ('Sonntag', 'So'),
}
am = 'vorm.'
@@ -71,7 +72,9 @@ class LocaleCalendarStub(object):
week = {'firstDay': 1, 'minDays': 1}
def getMonthNames(self):
- return [self.months.get(type, (None, None))[0] for type in range(1, 13)]
+ return [
+ self.months.get(type, (None, None))[0] for type in range(1, 13)
+ ]
def getMonthTypeFromName(self, name):
for item in self.months.items():
@@ -79,7 +82,9 @@ class LocaleCalendarStub(object):
return item[0]
def getMonthAbbreviations(self):
- return [self.months.get(type, (None, None))[1] for type in range(1, 13)]
+ return [
+ self.months.get(type, (None, None))[1] for type in range(1, 13)
+ ]
def getMonthTypeFromAbbreviation(self, abbr):
for item in self.months.items():
@@ -102,94 +107,170 @@ class LocaleCalendarStub(object):
class _TestCase(TestCase):
# Avoid deprecation warnings in Python 3 by making the preferred
# method name available for Python 2.
- assertRaisesRegex = getattr(TestCase, 'assertRaisesRegex', TestCase.assertRaisesRegexp)
+ assertRaisesRegex = getattr(
+ TestCase, 'assertRaisesRegex', TestCase.assertRaisesRegexp
+ )
class TestDateTimePatternParser(_TestCase):
"""Extensive tests for the ICU-based-syntax datetime pattern parser."""
-
def testParseSimpleTimePattern(self):
- self.assertEqual(parseDateTimePattern('HH'),
- [('H', 2)])
- self.assertEqual(parseDateTimePattern('HH:mm'),
- [('H', 2), ':', ('m', 2)])
- self.assertEqual(parseDateTimePattern('HH:mm:ss'),
- [('H', 2), ':', ('m', 2), ':', ('s', 2)])
- self.assertEqual(parseDateTimePattern('mm:ss'),
- [('m', 2), ':', ('s', 2)])
- self.assertEqual(parseDateTimePattern('H:m:s'),
- [('H', 1), ':', ('m', 1), ':', ('s', 1)])
- self.assertEqual(parseDateTimePattern('HHH:mmmm:sssss'),
- [('H', 3), ':', ('m', 4), ':', ('s', 5)])
+ self.assertEqual(parseDateTimePattern('HH'), [('H', 2)])
+ self.assertEqual(
+ parseDateTimePattern('HH:mm'), [('H', 2), ':', ('m', 2)]
+ )
+ self.assertEqual(
+ parseDateTimePattern('HH:mm:ss'),
+ [('H', 2), ':', ('m', 2), ':', ('s', 2)],
+ )
+ self.assertEqual(
+ parseDateTimePattern('mm:ss'), [('m', 2), ':', ('s', 2)]
+ )
+ self.assertEqual(
+ parseDateTimePattern('H:m:s'),
+ [('H', 1), ':', ('m', 1), ':', ('s', 1)],
+ )
+ self.assertEqual(
+ parseDateTimePattern('HHH:mmmm:sssss'),
+ [('H', 3), ':', ('m', 4), ':', ('s', 5)],
+ )
def testParseGermanTimePattern(self):
# German full
- self.assertEqual(parseDateTimePattern("H:mm' Uhr 'z"),
- [('H', 1), ':', ('m', 2), ' Uhr ', ('z', 1)])
+ self.assertEqual(
+ parseDateTimePattern("H:mm' Uhr 'z"),
+ [('H', 1), ':', ('m', 2), ' Uhr ', ('z', 1)],
+ )
# German long
- self.assertEqual(parseDateTimePattern("HH:mm:ss z"),
- [('H', 2), ':', ('m', 2), ':', ('s', 2), ' ',
- ('z', 1)])
+ self.assertEqual(
+ parseDateTimePattern("HH:mm:ss z"),
+ [('H', 2), ':', ('m', 2), ':', ('s', 2), ' ', ('z', 1)],
+ )
# German medium
- self.assertEqual(parseDateTimePattern("HH:mm:ss"),
- [('H', 2), ':', ('m', 2), ':', ('s', 2)])
+ self.assertEqual(
+ parseDateTimePattern("HH:mm:ss"),
+ [('H', 2), ':', ('m', 2), ':', ('s', 2)],
+ )
# German short
- self.assertEqual(parseDateTimePattern("HH:mm"),
- [('H', 2), ':', ('m', 2)])
+ self.assertEqual(
+ parseDateTimePattern("HH:mm"), [('H', 2), ':', ('m', 2)]
+ )
def testParseRealDate(self):
# German full
- self.assertEqual(parseDateTimePattern("EEEE, d. MMMM yyyy"),
- [('E', 4), ', ', ('d', 1), '. ', ('M', 4),
- ' ', ('y', 4)])
+ self.assertEqual(
+ parseDateTimePattern("EEEE, d. MMMM yyyy"),
+ [('E', 4), ', ', ('d', 1), '. ', ('M', 4), ' ', ('y', 4)],
+ )
# German long
- self.assertEqual(parseDateTimePattern("d. MMMM yyyy"),
- [('d', 1), '. ', ('M', 4), ' ', ('y', 4)])
+ self.assertEqual(
+ parseDateTimePattern("d. MMMM yyyy"),
+ [('d', 1), '. ', ('M', 4), ' ', ('y', 4)],
+ )
# German medium
- self.assertEqual(parseDateTimePattern("dd.MM.yyyy"),
- [('d', 2), '.', ('M', 2), '.', ('y', 4)])
+ self.assertEqual(
+ parseDateTimePattern("dd.MM.yyyy"),
+ [('d', 2), '.', ('M', 2), '.', ('y', 4)],
+ )
# German short
- self.assertEqual(parseDateTimePattern("dd.MM.yy"),
- [('d', 2), '.', ('M', 2), '.', ('y', 2)])
+ self.assertEqual(
+ parseDateTimePattern("dd.MM.yy"),
+ [('d', 2), '.', ('M', 2), '.', ('y', 2)],
+ )
def testParseRealDateTime(self):
# German full
self.assertEqual(
parseDateTimePattern("EEEE, d. MMMM yyyy H:mm' Uhr 'z"),
- [('E', 4), ', ', ('d', 1), '. ', ('M', 4), ' ', ('y', 4),
- ' ', ('H', 1), ':', ('m', 2), ' Uhr ', ('z', 1)])
+ [
+ ('E', 4),
+ ', ',
+ ('d', 1),
+ '. ',
+ ('M', 4),
+ ' ',
+ ('y', 4),
+ ' ',
+ ('H', 1),
+ ':',
+ ('m', 2),
+ ' Uhr ',
+ ('z', 1),
+ ],
+ )
# German long
self.assertEqual(
parseDateTimePattern("d. MMMM yyyy HH:mm:ss z"),
- [('d', 1), '. ', ('M', 4), ' ', ('y', 4),
- ' ', ('H', 2), ':', ('m', 2), ':', ('s', 2), ' ', ('z', 1)])
+ [
+ ('d', 1),
+ '. ',
+ ('M', 4),
+ ' ',
+ ('y', 4),
+ ' ',
+ ('H', 2),
+ ':',
+ ('m', 2),
+ ':',
+ ('s', 2),
+ ' ',
+ ('z', 1),
+ ],
+ )
# German medium
self.assertEqual(
parseDateTimePattern("dd.MM.yyyy HH:mm:ss"),
- [('d', 2), '.', ('M', 2), '.', ('y', 4),
- ' ', ('H', 2), ':', ('m', 2), ':', ('s', 2)])
+ [
+ ('d', 2),
+ '.',
+ ('M', 2),
+ '.',
+ ('y', 4),
+ ' ',
+ ('H', 2),
+ ':',
+ ('m', 2),
+ ':',
+ ('s', 2),
+ ],
+ )
# German short
self.assertEqual(
parseDateTimePattern("dd.MM.yy HH:mm"),
- [('d', 2), '.', ('M', 2), '.', ('y', 2),
- ' ', ('H', 2), ':', ('m', 2)])
+ [
+ ('d', 2),
+ '.',
+ ('M', 2),
+ '.',
+ ('y', 2),
+ ' ',
+ ('H', 2),
+ ':',
+ ('m', 2),
+ ],
+ )
def testParseQuotesInPattern(self):
- self.assertEqual(parseDateTimePattern("HH''mm"),
- [('H', 2), "'", ('m', 2)])
- self.assertEqual(parseDateTimePattern("HH'HHmm'mm"),
- [('H', 2), 'HHmm', ('m', 2)])
- self.assertEqual(parseDateTimePattern("HH':'''':'mm"),
- [('H', 2), ":':", ('m', 2)])
- self.assertEqual(parseDateTimePattern("HH':' ':'mm"),
- [('H', 2), ": :", ('m', 2)])
+ self.assertEqual(
+ parseDateTimePattern("HH''mm"), [('H', 2), "'", ('m', 2)]
+ )
+ self.assertEqual(
+ parseDateTimePattern("HH'HHmm'mm"), [('H', 2), 'HHmm', ('m', 2)]
+ )
+ self.assertEqual(
+ parseDateTimePattern("HH':'''':'mm"), [('H', 2), ":':", ('m', 2)]
+ )
+ self.assertEqual(
+ parseDateTimePattern("HH':' ':'mm"), [('H', 2), ": :", ('m', 2)]
+ )
def testParseDateTimePatternError(self):
# Quote not closed
with self.assertRaisesRegex(
- DateTimePatternParseError,
- 'The quote starting at character 2 is not closed.'):
+ DateTimePatternParseError,
+ 'The quote starting at character 2 is not closed.',
+ ):
parseDateTimePattern("HH' Uhr")
# Test correct length of characters in datetime fields
@@ -198,10 +279,7 @@ class TestDateTimePatternParser(_TestCase):
def testParseDateTimePatternRepeatDateTimeChars(self):
result = parseDateTimePattern('aG')
- self.assertEqual(
- result,
- [('a', 1), ('G', 1)]
- )
+ self.assertEqual(result, [('a', 1), ('G', 1)])
class TestBuildDateTimeParseInfo(_TestCase):
@@ -216,8 +294,10 @@ class TestBuildDateTimeParseInfo(_TestCase):
def testGenericNumbers(self):
for char in 'dDFkKhHmsSwW':
for length in range(1, 6):
- self.assertEqual(self.info((char, length)),
- '([0-9]{%i,1000})' %length)
+ self.assertEqual(
+ self.info((char, length)), '([0-9]{%i,1000})' % length
+ )
+
def testYear(self):
self.assertEqual(self.info(('y', 2)), '([0-9]{2})')
self.assertEqual(self.info(('y', 4)), '([0-9]{4})')
@@ -228,7 +308,9 @@ class TestBuildDateTimeParseInfo(_TestCase):
def testAMPMMarker(self):
names = ['vorm.', 'nachm.']
for length in range(1, 6):
- self.assertEqual(self.info(('a', length)), '('+'|'.join(names)+')')
+ self.assertEqual(
+ self.info(('a', length)), '(' + '|'.join(names) + ')'
+ )
def testEra(self):
self.assertEqual(self.info(('G', 1)), '(v. Chr.|n. Chr.)')
@@ -245,30 +327,60 @@ class TestBuildDateTimeParseInfo(_TestCase):
self.assertEqual(self.info(('M', 2)), '([0-9]{2})')
def testMonthNames(self):
- names = [u"Januar", u"Februar", u"Maerz", u"April",
- u"Mai", u"Juni", u"Juli", u"August", u"September", u"Oktober",
- u"November", u"Dezember"]
- self.assertEqual(self.info(('M', 4)), '('+'|'.join(names)+')')
+ names = [
+ u"Januar",
+ u"Februar",
+ u"Maerz",
+ u"April",
+ u"Mai",
+ u"Juni",
+ u"Juli",
+ u"August",
+ u"September",
+ u"Oktober",
+ u"November",
+ u"Dezember",
+ ]
+ self.assertEqual(self.info(('M', 4)), '(' + '|'.join(names) + ')')
def testMonthAbbr(self):
- names = ['Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug',
- 'Sep', 'Okt', 'Nov', 'Dez']
- self.assertEqual(self.info(('M', 3)), '('+'|'.join(names)+')')
+ names = [
+ 'Jan',
+ 'Feb',
+ 'Mrz',
+ 'Apr',
+ 'Mai',
+ 'Jun',
+ 'Jul',
+ 'Aug',
+ 'Sep',
+ 'Okt',
+ 'Nov',
+ 'Dez',
+ ]
+ self.assertEqual(self.info(('M', 3)), '(' + '|'.join(names) + ')')
def testWeekdayNumber(self):
self.assertEqual(self.info(('E', 1)), '([0-9])')
self.assertEqual(self.info(('E', 2)), '([0-9]{2})')
def testWeekdayNames(self):
- names = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',
- 'Freitag', 'Samstag', 'Sonntag']
- self.assertEqual(self.info(('E', 4)), '('+'|'.join(names)+')')
- self.assertEqual(self.info(('E', 5)), '('+'|'.join(names)+')')
- self.assertEqual(self.info(('E', 10)), '('+'|'.join(names)+')')
+ names = [
+ 'Montag',
+ 'Dienstag',
+ 'Mittwoch',
+ 'Donnerstag',
+ 'Freitag',
+ 'Samstag',
+ 'Sonntag',
+ ]
+ self.assertEqual(self.info(('E', 4)), '(' + '|'.join(names) + ')')
+ self.assertEqual(self.info(('E', 5)), '(' + '|'.join(names) + ')')
+ self.assertEqual(self.info(('E', 10)), '(' + '|'.join(names) + ')')
def testWeekdayAbbr(self):
names = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
- self.assertEqual(self.info(('E', 3)), '('+'|'.join(names)+')')
+ self.assertEqual(self.info(('E', 3)), '(' + '|'.join(names) + ')')
class TestDateTimeFormat(_TestCase):
@@ -284,36 +396,44 @@ class TestDateTimeFormat(_TestCase):
# German short
self.assertEqual(
self.format.parse('02.01.03 21:48', 'dd.MM.yy HH:mm'),
- datetime.datetime(2003, 1, 2, 21, 48))
+ datetime.datetime(2003, 1, 2, 21, 48),
+ )
def testParseRealDateTime(self):
# German medium
self.assertEqual(
self.format.parse('02.01.2003 21:48:01', 'dd.MM.yyyy HH:mm:ss'),
- datetime.datetime(2003, 1, 2, 21, 48, 1))
+ datetime.datetime(2003, 1, 2, 21, 48, 1),
+ )
# German long
# TODO: The parser does not support timezones yet.
self.assertEqual(
self.format.parse(
- '2. Januar 2003 21:48:01 +100',
- 'd. MMMM yyyy HH:mm:ss z'),
+ '2. Januar 2003 21:48:01 +100', 'd. MMMM yyyy HH:mm:ss z'
+ ),
pytz.timezone('Europe/Berlin').localize(
- datetime.datetime(2003, 1, 2, 21, 48, 1)))
+ datetime.datetime(2003, 1, 2, 21, 48, 1)
+ ),
+ )
# German full
# TODO: The parser does not support timezones yet.
self.assertEqual(
self.format.parse(
'Donnerstag, 2. Januar 2003 21:48 Uhr +100',
- "EEEE, d. MMMM yyyy H:mm' Uhr 'z"),
+ "EEEE, d. MMMM yyyy H:mm' Uhr 'z",
+ ),
pytz.timezone('Europe/Berlin').localize(
- datetime.datetime(2003, 1, 2, 21, 48)))
+ datetime.datetime(2003, 1, 2, 21, 48)
+ ),
+ )
def testParseAMPMDateTime(self):
self.assertEqual(
self.format.parse('02.01.03 09:48 nachm.', 'dd.MM.yy hh:mm a'),
- datetime.datetime(2003, 1, 2, 21, 48))
+ datetime.datetime(2003, 1, 2, 21, 48),
+ )
def testParseTimeZone(self):
dt = self.format.parse('09:48 -600', 'HH:mm z')
@@ -338,15 +458,17 @@ class TestDateTimeFormat(_TestCase):
self.assertEqual(dt.tzinfo.zone, 'EST')
self.assertEqual(dt.tzinfo.tzname(dt), 'EST')
- dt = self.format.parse('01.01.2003 09:48 US/Eastern',
- 'dd.MM.yyyy HH:mm zzzz')
+ dt = self.format.parse(
+ '01.01.2003 09:48 US/Eastern', 'dd.MM.yyyy HH:mm zzzz'
+ )
self.assertEqual(pickle.loads(pickle.dumps(dt)), dt)
self.assertEqual(dt.tzinfo.utcoffset(dt), datetime.timedelta(hours=-5))
self.assertEqual(dt.tzinfo.zone, 'US/Eastern')
self.assertEqual(dt.tzinfo.tzname(dt), 'EST')
- dt = self.format.parse('01.01.2003 09:48 Canada/Eastern',
- 'dd.MM.yyyy HH:mm zzzz')
+ dt = self.format.parse(
+ '01.01.2003 09:48 Canada/Eastern', 'dd.MM.yyyy HH:mm zzzz'
+ )
self.assertEqual(dt.tzinfo.utcoffset(dt), datetime.timedelta(hours=-5))
self.assertEqual(dt.tzinfo.zone, 'Canada/Eastern')
self.assertEqual(dt.tzinfo.tzname(dt), 'EST')
@@ -354,13 +476,15 @@ class TestDateTimeFormat(_TestCase):
# Note that historical and future (as far as known)
# timezones are handled happily using the pytz timezone database
# US DST transition points are changing in 2007
- dt = self.format.parse('01.04.2006 09:48 US/Eastern',
- 'dd.MM.yyyy HH:mm zzzz')
+ dt = self.format.parse(
+ '01.04.2006 09:48 US/Eastern', 'dd.MM.yyyy HH:mm zzzz'
+ )
self.assertEqual(dt.tzinfo.zone, 'US/Eastern')
self.assertEqual(dt.tzinfo.tzname(dt), 'EST')
self.assertEqual(dt.tzinfo.utcoffset(dt), datetime.timedelta(hours=-5))
- dt = self.format.parse('01.04.2007 09:48 US/Eastern',
- 'dd.MM.yyyy HH:mm zzzz')
+ dt = self.format.parse(
+ '01.04.2007 09:48 US/Eastern', 'dd.MM.yyyy HH:mm zzzz'
+ )
self.assertEqual(dt.tzinfo.zone, 'US/Eastern')
self.assertEqual(dt.tzinfo.tzname(dt), 'EDT')
self.assertEqual(dt.tzinfo.utcoffset(dt), datetime.timedelta(hours=-4))
@@ -376,65 +500,75 @@ class TestDateTimeFormat(_TestCase):
def testParse12PM(self):
self.assertEqual(
self.format.parse('01.01.03 12:00 nachm.', 'dd.MM.yy hh:mm a'),
- datetime.datetime(2003, 1, 1, 12, 00, 00, 00))
+ datetime.datetime(2003, 1, 1, 12, 00, 00, 00),
+ )
def testParseUnusualFormats(self):
self.assertEqual(
- self.format.parse('001. Januar 03 0012:00',
- 'ddd. MMMMM yy HHHH:mm'),
- datetime.datetime(2003, 1, 1, 12, 00, 00, 00))
+ self.format.parse(
+ '001. Januar 03 0012:00', 'ddd. MMMMM yy HHHH:mm'
+ ),
+ datetime.datetime(2003, 1, 1, 12, 00, 00, 00),
+ )
self.assertEqual(
- self.format.parse('0001. Jan 2003 0012:00 vorm.',
- 'dddd. MMM yyyy hhhh:mm a'),
- datetime.datetime(2003, 1, 1, 00, 00, 00, 00))
+ self.format.parse(
+ '0001. Jan 2003 0012:00 vorm.', 'dddd. MMM yyyy hhhh:mm a'
+ ),
+ datetime.datetime(2003, 1, 1, 00, 00, 00, 00),
+ )
def testParseNotObject(self):
self.assertEqual(
('2017', '01', '01'),
- self.format.parse('2017-01-01', 'yyyy-MM-dd', asObject=False))
+ self.format.parse('2017-01-01', 'yyyy-MM-dd', asObject=False),
+ )
def testParseTwoDigitYearIs20thCentury(self):
self.assertEqual(
datetime.date(1952, 1, 1),
- self.format.parse('52-01-01', 'yy-MM-dd'))
+ self.format.parse('52-01-01', 'yy-MM-dd'),
+ )
# 30 is the cut off
self.assertEqual(
datetime.date(1931, 1, 1),
- self.format.parse('31-01-01', 'yy-MM-dd'))
+ self.format.parse('31-01-01', 'yy-MM-dd'),
+ )
self.assertEqual(
datetime.date(2030, 1, 1),
- self.format.parse('30-01-01', 'yy-MM-dd'))
+ self.format.parse('30-01-01', 'yy-MM-dd'),
+ )
def testParseAMPMMissing(self):
with self.assertRaisesRegex(
- DateTimeParseError,
- 'Cannot handle 12-hour format without am/pm marker.'):
+ DateTimeParseError,
+ 'Cannot handle 12-hour format without am/pm marker.',
+ ):
self.format.parse('02.01.03 09:48', 'dd.MM.yy hh:mm')
def testParseBadTimezone(self):
# Produces an object without pytz info
self.assertEqual(
datetime.time(21, 48, 1),
- self.format.parse(
- '21:48:01 Bad/Timezone',
- 'HH:mm:ss zzzz'))
+ self.format.parse('21:48:01 Bad/Timezone', 'HH:mm:ss zzzz'),
+ )
def testParsePyTzTimezone(self):
tzinfo = pytz.timezone("US/Central")
self.assertEqual(
datetime.time(21, 48, 1, tzinfo=tzinfo),
- self.format.parse(
- '21:48:01 US/Central',
- 'HH:mm:ss zzzz'))
+ self.format.parse('21:48:01 US/Central', 'HH:mm:ss zzzz'),
+ )
def testFormatSimpleDateTime(self):
# German short
self.assertEqual(
- self.format.format(datetime.datetime(2003, 1, 2, 21, 48),
- 'dd.MM.yy HH:mm'),
- '02.01.03 21:48')
+ self.format.format(
+ datetime.datetime(2003, 1, 2, 21, 48), 'dd.MM.yy HH:mm'
+ ),
+ '02.01.03 21:48',
+ )
def testFormatRealDateTime(self):
tz = pytz.timezone('Europe/Berlin')
@@ -442,80 +576,89 @@ class TestDateTimeFormat(_TestCase):
# German medium
self.assertEqual(
self.format.format(dt, 'dd.MM.yyyy HH:mm:ss'),
- '02.01.2003 21:48:01')
+ '02.01.2003 21:48:01',
+ )
# German long
self.assertEqual(
self.format.format(dt, 'd. MMMM yyyy HH:mm:ss z'),
- '2. Januar 2003 21:48:01 +100')
+ '2. Januar 2003 21:48:01 +100',
+ )
# German full
self.assertEqual(
- self.format.format(
- dt, "EEEE, d. MMMM yyyy H:mm' Uhr 'z"),
- 'Donnerstag, 2. Januar 2003 21:48 Uhr +100')
+ self.format.format(dt, "EEEE, d. MMMM yyyy H:mm' Uhr 'z"),
+ 'Donnerstag, 2. Januar 2003 21:48 Uhr +100',
+ )
def testFormatAMPMDateTime(self):
self.assertEqual(
self.format.format(
- datetime.datetime(2003, 1, 2, 21, 48),
- 'dd.MM.yy hh:mm a'),
- '02.01.03 09:48 nachm.')
+ datetime.datetime(2003, 1, 2, 21, 48), 'dd.MM.yy hh:mm a'
+ ),
+ '02.01.03 09:48 nachm.',
+ )
def testFormatAllWeekdays(self):
for day in range(1, 8):
self.assertEqual(
self.format.format(
- datetime.datetime(2003, 1, day+5, 21, 48),
- "EEEE, d. MMMM yyyy H:mm' Uhr 'z"),
- '%s, %i. Januar 2003 21:48 Uhr +000' % (
- self.format.calendar.days[day][0], day+5))
+ datetime.datetime(2003, 1, day + 5, 21, 48),
+ "EEEE, d. MMMM yyyy H:mm' Uhr 'z",
+ ),
+ '%s, %i. Januar 2003 21:48 Uhr +000'
+ % (self.format.calendar.days[day][0], day + 5),
+ )
def testFormatTimeZone(self):
self.assertEqual(
- self.format.format(
- datetime.datetime(2003, 1, 2, 12, 00), 'z'),
- '+000')
+ self.format.format(datetime.datetime(2003, 1, 2, 12, 00), 'z'),
+ '+000',
+ )
self.assertEqual(
- self.format.format(
- datetime.datetime(2003, 1, 2, 12, 00), 'zz'),
- '+00:00')
+ self.format.format(datetime.datetime(2003, 1, 2, 12, 00), 'zz'),
+ '+00:00',
+ )
self.assertEqual(
- self.format.format(
- datetime.datetime(2003, 1, 2, 12, 00), 'zzz'),
- 'UTC')
+ self.format.format(datetime.datetime(2003, 1, 2, 12, 00), 'zzz'),
+ 'UTC',
+ )
self.assertEqual(
- self.format.format(
- datetime.datetime(2003, 1, 2, 12, 00), 'zzzz'),
- 'UTC')
+ self.format.format(datetime.datetime(2003, 1, 2, 12, 00), 'zzzz'),
+ 'UTC',
+ )
tz = pytz.timezone('US/Eastern')
self.assertEqual(
self.format.format(
- tz.localize(datetime.datetime(2003, 1, 2, 12)), 'z'),
- '-500')
+ tz.localize(datetime.datetime(2003, 1, 2, 12)), 'z'
+ ),
+ '-500',
+ )
self.assertEqual(
self.format.format(
- tz.localize(datetime.datetime(2003, 1, 2, 12)), 'zz'),
- '-05:00')
+ tz.localize(datetime.datetime(2003, 1, 2, 12)), 'zz'
+ ),
+ '-05:00',
+ )
self.assertEqual(
self.format.format(
- tz.localize(datetime.datetime(2003, 1, 2, 12)), 'zzz'),
- 'EST')
+ tz.localize(datetime.datetime(2003, 1, 2, 12)), 'zzz'
+ ),
+ 'EST',
+ )
self.assertEqual(
self.format.format(
- tz.localize(datetime.datetime(2003, 1, 2, 12)), 'zzzz'),
- 'US/Eastern')
+ tz.localize(datetime.datetime(2003, 1, 2, 12)), 'zzzz'
+ ),
+ 'US/Eastern',
+ )
def testFormatWeekDay(self):
date = datetime.date(2003, 1, 2)
- self.assertEqual(self.format.format(date, "E"),
- '4')
- self.assertEqual(self.format.format(date, "EE"),
- '04')
- self.assertEqual(self.format.format(date, "EEE"),
- 'Do')
- self.assertEqual(self.format.format(date, "EEEE"),
- 'Donnerstag')
+ self.assertEqual(self.format.format(date, "E"), '4')
+ self.assertEqual(self.format.format(date, "EE"), '04')
+ self.assertEqual(self.format.format(date, "EEE"), 'Do')
+ self.assertEqual(self.format.format(date, "EEEE"), 'Donnerstag')
# Create custom calendar, which has Sunday as the first day of the
# week. I am assigning a totally new dict here, since dicts are
@@ -525,166 +668,146 @@ class TestDateTimeFormat(_TestCase):
calendar.week = {'firstDay': 7, 'minDays': 1}
format = DateTimeFormat(calendar=calendar)
- self.assertEqual(format.format(date, "E"),
- '5')
- self.assertEqual(format.format(date, "EE"),
- '05')
+ self.assertEqual(format.format(date, "E"), '5')
+ self.assertEqual(format.format(date, "EE"), '05')
def testFormatDayOfWeekInMonth(self):
date = datetime.date(2003, 1, 2)
- self.assertEqual(self.format.format(date, "F"),
- '1')
- self.assertEqual(self.format.format(date, "FF"),
- '01')
+ self.assertEqual(self.format.format(date, "F"), '1')
+ self.assertEqual(self.format.format(date, "FF"), '01')
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 9), "F"),
- '2')
+ self.format.format(datetime.date(2003, 1, 9), "F"), '2'
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 16), "F"),
- '3')
+ self.format.format(datetime.date(2003, 1, 16), "F"), '3'
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 23), "F"),
- '4')
+ self.format.format(datetime.date(2003, 1, 23), "F"), '4'
+ )
def testFormatWeekInMonth(self):
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 3), "W"),
- '1')
+ self.format.format(datetime.date(2003, 1, 3), "W"), '1'
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 3), "WW"),
- '01')
+ self.format.format(datetime.date(2003, 1, 3), "WW"), '01'
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 8), "W"),
- '2')
+ self.format.format(datetime.date(2003, 1, 8), "W"), '2'
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 19), "W"),
- '3')
+ self.format.format(datetime.date(2003, 1, 19), "W"), '3'
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 20), "W"),
- '4')
+ self.format.format(datetime.date(2003, 1, 20), "W"), '4'
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 31), "W"),
- '5')
+ self.format.format(datetime.date(2003, 1, 31), "W"), '5'
+ )
def testFormatHourInDayOneTo24(self):
- self.assertEqual(
- self.format.format(datetime.time(5, 0), "k"),
- '5')
- self.assertEqual(
- self.format.format(datetime.time(5, 0), "kk"),
- '05')
- self.assertEqual(
- self.format.format(datetime.time(0, 0), "k"),
- '24')
- self.assertEqual(
- self.format.format(datetime.time(1, 0), "k"),
- '1')
+ self.assertEqual(self.format.format(datetime.time(5, 0), "k"), '5')
+ self.assertEqual(self.format.format(datetime.time(5, 0), "kk"), '05')
+ self.assertEqual(self.format.format(datetime.time(0, 0), "k"), '24')
+ self.assertEqual(self.format.format(datetime.time(1, 0), "k"), '1')
def testFormatHourInDayZeroToEleven(self):
- self.assertEqual(
- self.format.format(datetime.time(5, 0), "K"),
- '5')
- self.assertEqual(
- self.format.format(datetime.time(5, 0), "KK"),
- '05')
- self.assertEqual(
- self.format.format(datetime.time(0, 0), "K"),
- '0')
- self.assertEqual(
- self.format.format(datetime.time(12, 0), "K"),
- '0')
- self.assertEqual(
- self.format.format(datetime.time(11, 0), "K"),
- '11')
- self.assertEqual(
- self.format.format(datetime.time(23, 0), "K"),
- '11')
+ self.assertEqual(self.format.format(datetime.time(5, 0), "K"), '5')
+ self.assertEqual(self.format.format(datetime.time(5, 0), "KK"), '05')
+ self.assertEqual(self.format.format(datetime.time(0, 0), "K"), '0')
+ self.assertEqual(self.format.format(datetime.time(12, 0), "K"), '0')
+ self.assertEqual(self.format.format(datetime.time(11, 0), "K"), '11')
+ self.assertEqual(self.format.format(datetime.time(23, 0), "K"), '11')
def testFormatSimpleHourRepresentation(self):
self.assertEqual(
- self.format.format(datetime.datetime(2003, 1, 2, 23, 00),
- 'dd.MM.yy h:mm:ss a'),
- '02.01.03 11:00:00 nachm.')
+ self.format.format(
+ datetime.datetime(2003, 1, 2, 23, 00), 'dd.MM.yy h:mm:ss a'
+ ),
+ '02.01.03 11:00:00 nachm.',
+ )
self.assertEqual(
- self.format.format(datetime.datetime(2003, 1, 2, 2, 00),
- 'dd.MM.yy h:mm:ss a'),
- '02.01.03 2:00:00 vorm.')
+ self.format.format(
+ datetime.datetime(2003, 1, 2, 2, 00), 'dd.MM.yy h:mm:ss a'
+ ),
+ '02.01.03 2:00:00 vorm.',
+ )
self.assertEqual(
- self.format.format(datetime.time(0, 15), 'h:mm a'),
- '12:15 vorm.')
+ self.format.format(datetime.time(0, 15), 'h:mm a'), '12:15 vorm.'
+ )
self.assertEqual(
- self.format.format(datetime.time(1, 15), 'h:mm a'),
- '1:15 vorm.')
+ self.format.format(datetime.time(1, 15), 'h:mm a'), '1:15 vorm.'
+ )
self.assertEqual(
- self.format.format(datetime.time(12, 15), 'h:mm a'),
- '12:15 nachm.')
+ self.format.format(datetime.time(12, 15), 'h:mm a'), '12:15 nachm.'
+ )
self.assertEqual(
- self.format.format(datetime.time(13, 15), 'h:mm a'),
- '1:15 nachm.')
+ self.format.format(datetime.time(13, 15), 'h:mm a'), '1:15 nachm.'
+ )
def testFormatDayInYear(self):
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 3), 'D'),
- u"3")
+ self.format.format(datetime.date(2003, 1, 3), 'D'), u"3"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 3), 'DD'),
- u"03")
+ self.format.format(datetime.date(2003, 1, 3), 'DD'), u"03"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 3), 'DDD'),
- u"003")
+ self.format.format(datetime.date(2003, 1, 3), 'DDD'), u"003"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 12, 31), 'D'),
- u"365")
+ self.format.format(datetime.date(2003, 12, 31), 'D'), u"365"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 12, 31), 'DD'),
- u"365")
+ self.format.format(datetime.date(2003, 12, 31), 'DD'), u"365"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 12, 31), 'DDD'),
- u"365")
+ self.format.format(datetime.date(2003, 12, 31), 'DDD'), u"365"
+ )
self.assertEqual(
- self.format.format(datetime.date(2004, 12, 31), 'DDD'),
- u"366")
+ self.format.format(datetime.date(2004, 12, 31), 'DDD'), u"366"
+ )
def testFormatDayOfWeekInMOnth(self):
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 3), 'F'),
- u"1")
+ self.format.format(datetime.date(2003, 1, 3), 'F'), u"1"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 10), 'F'),
- u"2")
+ self.format.format(datetime.date(2003, 1, 10), 'F'), u"2"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 17), 'F'),
- u"3")
+ self.format.format(datetime.date(2003, 1, 17), 'F'), u"3"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 24), 'F'),
- u"4")
+ self.format.format(datetime.date(2003, 1, 24), 'F'), u"4"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 31), 'F'),
- u"5")
+ self.format.format(datetime.date(2003, 1, 31), 'F'), u"5"
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 6), 'F'),
- u"1")
+ self.format.format(datetime.date(2003, 1, 6), 'F'), u"1"
+ )
def testFormatUnusualFormats(self):
self.assertEqual(
self.format.format(datetime.date(2003, 1, 3), 'DDD-yyyy'),
- u"003-2003")
+ u"003-2003",
+ )
self.assertEqual(
- self.format.format(datetime.date(2003, 1, 10),
- "F. EEEE 'im' MMMM, yyyy"),
- u"2. Freitag im Januar, 2003")
-
+ self.format.format(
+ datetime.date(2003, 1, 10), "F. EEEE 'im' MMMM, yyyy"
+ ),
+ u"2. Freitag im Januar, 2003",
+ )
def testFormatGregorianEra(self):
self.assertEqual(
- self.format.format(datetime.date(2017, 12, 17), 'G'),
- u'n. Chr.'
+ self.format.format(datetime.date(2017, 12, 17), 'G'), u'n. Chr.'
)
def testFormateMonthLengthOne(self):
self.assertEqual(
- self.format.format(datetime.date(2017, 12, 17), 'M'),
- u'12'
+ self.format.format(datetime.date(2017, 12, 17), 'M'), u'12'
)
@@ -694,515 +817,757 @@ class TestNumberPatternParser(_TestCase):
def testParseSimpleIntegerPattern(self):
self.assertEqual(
parseNumberPattern('###0'),
- ((None, '', None, '###0', '', '', None, '', None, ()),
- (None, '', None, '###0', '', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '', '', None, '', None, ()),
+ (None, '', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
def testParseScientificIntegerPattern(self):
self.assertEqual(
parseNumberPattern('###0E#0'),
- ((None, '', None, '###0', '', '#0', None, '', None, ()),
- (None, '', None, '###0', '', '#0', None, '', None, ())))
+ (
+ (None, '', None, '###0', '', '#0', None, '', None, ()),
+ (None, '', None, '###0', '', '#0', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0E+#0'),
- ((None, '', None, '###0', '', '+#0', None, '', None, ()),
- (None, '', None, '###0', '', '+#0', None, '', None, ())))
+ (
+ (None, '', None, '###0', '', '+#0', None, '', None, ()),
+ (None, '', None, '###0', '', '+#0', None, '', None, ()),
+ ),
+ )
def testParsePosNegAlternativeIntegerPattern(self):
self.assertEqual(
parseNumberPattern('###0;#0'),
- ((None, '', None, '###0', '', '', None, '', None, ()),
- (None, '', None, '#0', '', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '', '', None, '', None, ()),
+ (None, '', None, '#0', '', '', None, '', None, ()),
+ ),
+ )
def testParsePrefixedIntegerPattern(self):
self.assertEqual(
parseNumberPattern('+###0'),
- ((None, '+', None, '###0', '', '', None, '', None, ()),
- (None, '+', None, '###0', '', '', None, '', None, ())))
+ (
+ (None, '+', None, '###0', '', '', None, '', None, ()),
+ (None, '+', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
def testParsePosNegIntegerPattern(self):
self.assertEqual(
parseNumberPattern('+###0;-###0'),
- ((None, '+', None, '###0', '', '', None, '', None, ()),
- (None, '-', None, '###0', '', '', None, '', None, ())))
+ (
+ (None, '+', None, '###0', '', '', None, '', None, ()),
+ (None, '-', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
def testParseScientificPosNegIntegerPattern(self):
self.assertEqual(
parseNumberPattern('+###0E0;-###0E#0'),
- ((None, '+', None, '###0', '', '0', None, '', None, ()),
- (None, '-', None, '###0', '', '#0', None, '', None, ())))
+ (
+ (None, '+', None, '###0', '', '0', None, '', None, ()),
+ (None, '-', None, '###0', '', '#0', None, '', None, ()),
+ ),
+ )
def testParseThousandSeparatorIntegerPattern(self):
self.assertEqual(
parseNumberPattern('#,##0'),
- ((None, '', None, '###0', '', '', None, '', None, (3, 0)),
- (None, '', None, '###0', '', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '', '', None, '', None, (3, 0)),
+ (None, '', None, '###0', '', '', None, '', None, (3, 0)),
+ ),
+ )
def testParseSimpleDecimalPattern(self):
self.assertEqual(
parseNumberPattern('###0.00#'),
- ((None, '', None, '###0', '00#', '', None, '', None, ()),
- (None, '', None, '###0', '00#', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '00#', '', None, '', None, ()),
+ (None, '', None, '###0', '00#', '', None, '', None, ()),
+ ),
+ )
def testParseScientificDecimalPattern(self):
self.assertEqual(
parseNumberPattern('###0.00#E#0'),
- ((None, '', None, '###0', '00#', '#0', None, '', None, ()),
- (None, '', None, '###0', '00#', '#0', None, '', None, ())))
+ (
+ (None, '', None, '###0', '00#', '#0', None, '', None, ()),
+ (None, '', None, '###0', '00#', '#0', None, '', None, ()),
+ ),
+ )
def testParsePosNegAlternativeFractionPattern(self):
self.assertEqual(
parseNumberPattern('###0.00#;#0.0#'),
- ((None, '', None, '###0', '00#', '', None, '', None, ()),
- (None, '', None, '#0', '0#', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '00#', '', None, '', None, ()),
+ (None, '', None, '#0', '0#', '', None, '', None, ()),
+ ),
+ )
def testParsePosNegFractionPattern(self):
self.assertEqual(
parseNumberPattern('+###0.0##;-###0.0##'),
- ((None, '+', None, '###0', '0##', '', None, '', None, ()),
- (None, '-', None, '###0', '0##', '', None, '', None, ())))
+ (
+ (None, '+', None, '###0', '0##', '', None, '', None, ()),
+ (None, '-', None, '###0', '0##', '', None, '', None, ()),
+ ),
+ )
def testParseScientificPosNegFractionPattern(self):
self.assertEqual(
parseNumberPattern('+###0.0##E#0;-###0.0##E0'),
- ((None, '+', None, '###0', '0##', '#0', None, '', None, ()),
- (None, '-', None, '###0', '0##', '0', None, '', None, ())))
+ (
+ (None, '+', None, '###0', '0##', '#0', None, '', None, ()),
+ (None, '-', None, '###0', '0##', '0', None, '', None, ()),
+ ),
+ )
def testParseThousandSeparatorFractionPattern(self):
self.assertEqual(
parseNumberPattern('#,##0.0#'),
- ((None, '', None, '###0', '0#', '', None, '', None, (3, 0)),
- (None, '', None, '###0', '0#', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '0#', '', None, '', None, (3, 0)),
+ (None, '', None, '###0', '0#', '', None, '', None, (3, 0)),
+ ),
+ )
def testParseThousandSeparatorPatterns(self):
# the following patterns are present in the ICU XMLs:
self.assertEqual(
parseNumberPattern('#,##0.00;-#,##0.00'),
- ((None, '', None, '###0', '00', '', None, '', None, (3, 0)),
- (None, '-', None, '###0', '00', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '00', '', None, '', None, (3, 0)),
+ (None, '-', None, '###0', '00', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##,##0.###;-#,##,##0.###'),
- ((None, '', None, '#####0', '###', '', None, '', None, (3, 2, 0)),
- (None, '-', None, '#####0', '###', '', None, '', None, (3, 2, 0))))
+ (
+ (
+ None,
+ '',
+ None,
+ '#####0',
+ '###',
+ '',
+ None,
+ '',
+ None,
+ (3, 2, 0),
+ ),
+ (
+ None,
+ '-',
+ None,
+ '#####0',
+ '###',
+ '',
+ None,
+ '',
+ None,
+ (3, 2, 0),
+ ),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.##;-#,##0.##'),
- ((None, '', None, '###0', '##', '', None, '', None, (3, 0)),
- (None, '-', None, '###0', '##', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '##', '', None, '', None, (3, 0)),
+ (None, '-', None, '###0', '##', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.###;-#,##0.###'),
- ((None, '', None, '###0', '###', '', None, '', None, (3, 0)),
- (None, '-', None, '###0', '###', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '###', '', None, '', None, (3, 0)),
+ (None, '-', None, '###0', '###', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.###;(#,##0.###)'),
- ((None, '', None, '###0', '###', '', None, '', None, (3, 0)),
- (None, '(', None, '###0', '###', '', None, ')', None, (3, 0))))
+ (
+ (None, '', None, '###0', '###', '', None, '', None, (3, 0)),
+ (None, '(', None, '###0', '###', '', None, ')', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.###;#,##0.###-'),
- ((None, '', None, '###0', '###', '', None, '', None, (3, 0)),
- (None, '', None, '###0', '###', '', None, '-', None, (3, 0))))
+ (
+ (None, '', None, '###0', '###', '', None, '', None, (3, 0)),
+ (None, '', None, '###0', '###', '', None, '-', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('##,##,##0.###;-##,##,##0.###'),
- ((None, '', None, '######0', '###', '', None, '', None, (3, 2, 0)),
- (None, '-', None, '######0', '###', '', None, '', None, (3, 2, 0))))
+ (
+ (
+ None,
+ '',
+ None,
+ '######0',
+ '###',
+ '',
+ None,
+ '',
+ None,
+ (3, 2, 0),
+ ),
+ (
+ None,
+ '-',
+ None,
+ '######0',
+ '###',
+ '',
+ None,
+ '',
+ None,
+ (3, 2, 0),
+ ),
+ ),
+ )
self.assertEqual(
parseNumberPattern('##,##0.##;-##,##0.##'),
- ((None, '', None, '####0', '##', '', None, '', None, (3, 0)),
- (None, '-', None, '####0', '##', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '####0', '##', '', None, '', None, (3, 0)),
+ (None, '-', None, '####0', '##', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.###;-###0.###'),
- ((None, '', None, '###0', '###', '', None, '', None, ()),
- (None, '-', None, '###0', '###', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '###', '', None, '', None, ()),
+ (None, '-', None, '###0', '###', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.###;###0.###-'),
- ((None, '', None, '###0', '###', '', None, '', None, ()),
- (None, '', None, '###0', '###', '', None, '-', None, ())))
+ (
+ (None, '', None, '###0', '###', '', None, '', None, ()),
+ (None, '', None, '###0', '###', '', None, '-', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#0.###;-#0.###'),
- ((None, '', None, '#0', '###', '', None, '', None, ()),
- (None, '-', None, '#0', '###', '', None, '', None, ())))
+ (
+ (None, '', None, '#0', '###', '', None, '', None, ()),
+ (None, '-', None, '#0', '###', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.###;#,##0.###'),
- ((None, '', None, '###0', '###', '', None, '', None, (3, 0)),
- (None, '', None, '###0', '###', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '###', '', None, '', None, (3, 0)),
+ (None, '', None, '###0', '###', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.###;-###0.###'),
- ((None, '', None, '###0', '###', '', None, '', None, ()),
- (None, '-', None, '###0', '###', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '###', '', None, '', None, ()),
+ (None, '-', None, '###0', '###', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.00;-#,##0.00'),
- ((None, '', None, '###0', '00', '', None, '', None, (3, 0)),
- (None, '-', None, '###0', '00', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '00', '', None, '', None, (3, 0)),
+ (None, '-', None, '###0', '00', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.00;(#,##0.00)'),
- ((None, '', None, '###0', '00', '', None, '', None, (3, 0)),
- (None, '(', None, '###0', '00', '', None, ')', None, (3, 0))))
+ (
+ (None, '', None, '###0', '00', '', None, '', None, (3, 0)),
+ (None, '(', None, '###0', '00', '', None, ')', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0.00;-#,##0.00'),
- ((None, '', None, '###0', '00', '', None, '', None, (3, 0)),
- (None, '-', None, '###0', '00', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '00', '', None, '', None, (3, 0)),
+ (None, '-', None, '###0', '00', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('##,##,##0.00;-##,##,##0.00'),
- ((None, '', None, '######0', '00', '', None, '', None, (3, 2, 0)),
- (None, '-', None, '######0', '00', '', None, '', None, (3, 2, 0))))
+ (
+ (
+ None,
+ '',
+ None,
+ '######0',
+ '00',
+ '',
+ None,
+ '',
+ None,
+ (3, 2, 0),
+ ),
+ (
+ None,
+ '-',
+ None,
+ '######0',
+ '00',
+ '',
+ None,
+ '',
+ None,
+ (3, 2, 0),
+ ),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.00;-###0.00'),
- ((None, '', None, '###0', '00', '', None, '', None, ()),
- (None, '-', None, '###0', '00', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '00', '', None, '', None, ()),
+ (None, '-', None, '###0', '00', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('#,##0;-#,##0'),
- ((None, '', None, '###0', '', '', None, '', None, (3, 0)),
- (None, '-', None, '###0', '', '', None, '', None, (3, 0))))
+ (
+ (None, '', None, '###0', '', '', None, '', None, (3, 0)),
+ (None, '-', None, '###0', '', '', None, '', None, (3, 0)),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.00;-###0.00'),
- ((None, '', None, '###0', '00', '', None, '', None, ()),
- (None, '-', None, '###0', '00', '', None, '', None, ())))
+ (
+ (None, '', None, '###0', '00', '', None, '', None, ()),
+ (None, '-', None, '###0', '00', '', None, '', None, ()),
+ ),
+ )
def testParsePadding1WithoutPrefixPattern(self):
self.assertEqual(
parseNumberPattern('* ###0'),
- ((' ', '', None, '###0', '', '', None, '', None, ()),
- (' ', '', None, '###0', '', '', None, '', None, ())))
+ (
+ (' ', '', None, '###0', '', '', None, '', None, ()),
+ (' ', '', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('* ###0.0##'),
- ((' ', '', None, '###0', '0##', '', None, '', None, ()),
- (' ', '', None, '###0', '0##', '', None, '', None, ())))
+ (
+ (' ', '', None, '###0', '0##', '', None, '', None, ()),
+ (' ', '', None, '###0', '0##', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('* ###0.0##;*_###0.0##'),
- ((' ', '', None, '###0', '0##', '', None, '', None, ()),
- ('_', '', None, '###0', '0##', '', None, '', None, ())))
+ (
+ (' ', '', None, '###0', '0##', '', None, '', None, ()),
+ ('_', '', None, '###0', '0##', '', None, '', None, ()),
+ ),
+ )
def testParsePadding1WithPrefixPattern(self):
self.assertEqual(
parseNumberPattern('* +###0'),
- ((' ', '+', None, '###0', '', '', None, '', None, ()),
- (' ', '+', None, '###0', '', '', None, '', None, ())))
+ (
+ (' ', '+', None, '###0', '', '', None, '', None, ()),
+ (' ', '+', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('* +###0.0##'),
- ((' ', '+', None, '###0', '0##', '', None, '', None, ()),
- (' ', '+', None, '###0', '0##', '', None, '', None, ())))
+ (
+ (' ', '+', None, '###0', '0##', '', None, '', None, ()),
+ (' ', '+', None, '###0', '0##', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('* +###0.0##;*_-###0.0##'),
- ((' ', '+', None, '###0', '0##', '', None, '', None, ()),
- ('_', '-', None, '###0', '0##', '', None, '', None, ())))
+ (
+ (' ', '+', None, '###0', '0##', '', None, '', None, ()),
+ ('_', '-', None, '###0', '0##', '', None, '', None, ()),
+ ),
+ )
def testParsePadding1Padding2WithPrefixPattern(self):
self.assertEqual(
parseNumberPattern('* +* ###0'),
- ((' ', '+', ' ', '###0', '', '', None, '', None, ()),
- (' ', '+', ' ', '###0', '', '', None, '', None, ())))
+ (
+ (' ', '+', ' ', '###0', '', '', None, '', None, ()),
+ (' ', '+', ' ', '###0', '', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('* +* ###0.0##'),
- ((' ', '+', ' ', '###0', '0##', '', None, '', None, ()),
- (' ', '+', ' ', '###0', '0##', '', None, '', None, ())))
+ (
+ (' ', '+', ' ', '###0', '0##', '', None, '', None, ()),
+ (' ', '+', ' ', '###0', '0##', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('* +* ###0.0##;*_-*_###0.0##'),
- ((' ', '+', ' ', '###0', '0##', '', None, '', None, ()),
- ('_', '-', '_', '###0', '0##', '', None, '', None, ())))
+ (
+ (' ', '+', ' ', '###0', '0##', '', None, '', None, ()),
+ ('_', '-', '_', '###0', '0##', '', None, '', None, ()),
+ ),
+ )
def testParsePadding3WithoutSuffixPattern(self):
self.assertEqual(
parseNumberPattern('###0* '),
- ((None, '', None, '###0', '', '', ' ', '', None, ()),
- (None, '', None, '###0', '', '', ' ', '', None, ())))
+ (
+ (None, '', None, '###0', '', '', ' ', '', None, ()),
+ (None, '', None, '###0', '', '', ' ', '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.0##* '),
- ((None, '', None, '###0', '0##', '', ' ', '', None, ()),
- (None, '', None, '###0', '0##', '', ' ', '', None, ())))
+ (
+ (None, '', None, '###0', '0##', '', ' ', '', None, ()),
+ (None, '', None, '###0', '0##', '', ' ', '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.0##* ;###0.0##*_'),
- ((None, '', None, '###0', '0##', '', ' ', '', None, ()),
- (None, '', None, '###0', '0##', '', '_', '', None, ())))
+ (
+ (None, '', None, '###0', '0##', '', ' ', '', None, ()),
+ (None, '', None, '###0', '0##', '', '_', '', None, ()),
+ ),
+ )
def testParsePadding3InScientificPattern(self):
self.assertEqual(
parseNumberPattern('###0E#0* '),
- ((None, '', None, '###0', '', '#0', ' ', '', None, ()),
- (None, '', None, '###0', '', '#0', ' ', '', None, ())))
+ (
+ (None, '', None, '###0', '', '#0', ' ', '', None, ()),
+ (None, '', None, '###0', '', '#0', ' ', '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.0##E0* '),
- ((None, '', None, '###0', '0##', '0', ' ', '', None, ()),
- (None, '', None, '###0', '0##', '0', ' ', '', None, ())))
+ (
+ (None, '', None, '###0', '0##', '0', ' ', '', None, ()),
+ (None, '', None, '###0', '0##', '0', ' ', '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.0##E#0* ;###0.0##E0*_'),
- ((None, '', None, '###0', '0##', '#0', ' ', '', None, ()),
- (None, '', None, '###0', '0##', '0', '_', '', None, ())))
+ (
+ (None, '', None, '###0', '0##', '#0', ' ', '', None, ()),
+ (None, '', None, '###0', '0##', '0', '_', '', None, ()),
+ ),
+ )
def testParsePadding3WithSufffixPattern(self):
self.assertEqual(
parseNumberPattern('###0* /'),
- ((None, '', None, '###0', '', '', ' ', '/', None, ()),
- (None, '', None, '###0', '', '', ' ', '/', None, ())))
+ (
+ (None, '', None, '###0', '', '', ' ', '/', None, ()),
+ (None, '', None, '###0', '', '', ' ', '/', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.0#* /'),
- ((None, '', None, '###0', '0#', '', ' ', '/', None, ()),
- (None, '', None, '###0', '0#', '', ' ', '/', None, ())))
+ (
+ (None, '', None, '###0', '0#', '', ' ', '/', None, ()),
+ (None, '', None, '###0', '0#', '', ' ', '/', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0.0#* /;###0.0#*_/'),
- ((None, '', None, '###0', '0#', '', ' ', '/', None, ()),
- (None, '', None, '###0', '0#', '', '_', '/', None, ())))
+ (
+ (None, '', None, '###0', '0#', '', ' ', '/', None, ()),
+ (None, '', None, '###0', '0#', '', '_', '/', None, ()),
+ ),
+ )
def testParsePadding3And4WithSuffixPattern(self):
self.assertEqual(
parseNumberPattern('###0* /* '),
- ((None, '', None, '###0', '', '', ' ', '/', ' ', ()),
- (None, '', None, '###0', '', '', ' ', '/', ' ', ())))
+ (
+ (None, '', None, '###0', '', '', ' ', '/', ' ', ()),
+ (None, '', None, '###0', '', '', ' ', '/', ' ', ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('###0* /* ;###0*_/*_'),
- ((None, '', None, '###0', '', '', ' ', '/', ' ', ()),
- (None, '', None, '###0', '', '', '_', '/', '_', ())))
+ (
+ (None, '', None, '###0', '', '', ' ', '/', ' ', ()),
+ (None, '', None, '###0', '', '', '_', '/', '_', ()),
+ ),
+ )
def testParseMultipleCharacterPrefix(self):
self.assertEqual(
parseNumberPattern('DM###0'),
- ((None, 'DM', None, '###0', '', '', None, '', None, ()),
- (None, 'DM', None, '###0', '', '', None, '', None, ())))
+ (
+ (None, 'DM', None, '###0', '', '', None, '', None, ()),
+ (None, 'DM', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern('DM* ###0'),
- ((None, 'DM', ' ', '###0', '', '', None, '', None, ()),
- (None, 'DM', ' ', '###0', '', '', None, '', None, ())))
+ (
+ (None, 'DM', ' ', '###0', '', '', None, '', None, ()),
+ (None, 'DM', ' ', '###0', '', '', None, '', None, ()),
+ ),
+ )
def testParseStringEscapedPrefix(self):
self.assertEqual(
parseNumberPattern("'DEM'###0"),
- ((None, 'DEM', None, '###0', '', '', None, '', None, ()),
- (None, 'DEM', None, '###0', '', '', None, '', None, ())))
+ (
+ (None, 'DEM', None, '###0', '', '', None, '', None, ()),
+ (None, 'DEM', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern("D'EM'###0"),
- ((None, 'DEM', None, '###0', '', '', None, '', None, ()),
- (None, 'DEM', None, '###0', '', '', None, '', None, ())))
+ (
+ (None, 'DEM', None, '###0', '', '', None, '', None, ()),
+ (None, 'DEM', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern("D'E'M###0"),
- ((None, 'DEM', None, '###0', '', '', None, '', None, ()),
- (None, 'DEM', None, '###0', '', '', None, '', None, ())))
+ (
+ (None, 'DEM', None, '###0', '', '', None, '', None, ()),
+ (None, 'DEM', None, '###0', '', '', None, '', None, ()),
+ ),
+ )
def testParseStringEscapedSuffix(self):
self.assertEqual(
parseNumberPattern("###0'DEM'"),
- ((None, '', None, '###0', '', '', None, 'DEM', None, ()),
- (None, '', None, '###0', '', '', None, 'DEM', None, ())))
+ (
+ (None, '', None, '###0', '', '', None, 'DEM', None, ()),
+ (None, '', None, '###0', '', '', None, 'DEM', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern("###0D'EM'"),
- ((None, '', None, '###0', '', '', None, 'DEM', None, ()),
- (None, '', None, '###0', '', '', None, 'DEM', None, ())))
+ (
+ (None, '', None, '###0', '', '', None, 'DEM', None, ()),
+ (None, '', None, '###0', '', '', None, 'DEM', None, ()),
+ ),
+ )
self.assertEqual(
parseNumberPattern("###0D'E'M"),
- ((None, '', None, '###0', '', '', None, 'DEM', None, ()),
- (None, '', None, '###0', '', '', None, 'DEM', None, ())))
+ (
+ (None, '', None, '###0', '', '', None, 'DEM', None, ()),
+ (None, '', None, '###0', '', '', None, 'DEM', None, ()),
+ ),
+ )
def testParseInvalidBegin(self):
- with self.assertRaisesRegex(NumberPatternParseError,
- "Wrong syntax at beginning"):
+ with self.assertRaisesRegex(
+ NumberPatternParseError, "Wrong syntax at beginning"
+ ):
parseNumberPattern(".")
def testParseFractionQuote(self):
pattern, neg_pattern = parseNumberPattern("0.'")
self.assertEqual(
- (None, '', None, '0', '', '', None, '', None, ()),
- pattern)
+ (None, '', None, '0', '', '', None, '', None, ()), pattern
+ )
self.assertEqual(
- (None, '', None, '0', '', '', None, '', None, ()),
- neg_pattern)
+ (None, '', None, '0', '', '', None, '', None, ()), neg_pattern
+ )
def testParseExponentialQuote(self):
pattern, neg_pattern = parseNumberPattern("0E'")
self.assertEqual(
- (None, '', None, '0', '', '', None, '', None, ()),
- pattern)
+ (None, '', None, '0', '', '', None, '', None, ()), pattern
+ )
self.assertEqual(
- (None, '', None, '0', '', '', None, '', None, ()),
- neg_pattern)
+ (None, '', None, '0', '', '', None, '', None, ()), neg_pattern
+ )
def testParseExponentialNumber(self):
pattern, neg_pattern = parseNumberPattern("0E1")
self.assertEqual(
- (None, '', None, '0', '', '', None, '1', None, ()),
- pattern)
+ (None, '', None, '0', '', '', None, '1', None, ()), pattern
+ )
self.assertEqual(
- (None, '', None, '0', '', '', None, '1', None, ()),
- neg_pattern)
+ (None, '', None, '0', '', '', None, '1', None, ()), neg_pattern
+ )
class TestNumberFormat(_TestCase):
"""Test the functionality of an implmentation of the NumberFormat."""
- format = NumberFormat(symbols={
- 'decimal': '.', 'group': ',', 'list': ';', 'percentSign': '%',
- 'nativeZeroDigit': '0', 'patternDigit': '#', 'plusSign': '+',
- 'minusSign': '-', 'exponential': 'E', 'perMille': 'o/oo',
- 'infinity': 'oo', 'nan': 'N/A'})
+ format = NumberFormat(
+ symbols={
+ 'decimal': '.',
+ 'group': ',',
+ 'list': ';',
+ 'percentSign': '%',
+ 'nativeZeroDigit': '0',
+ 'patternDigit': '#',
+ 'plusSign': '+',
+ 'minusSign': '-',
+ 'exponential': 'E',
+ 'perMille': 'o/oo',
+ 'infinity': 'oo',
+ 'nan': 'N/A',
+ }
+ )
def testInterfaceConformity(self):
self.assertTrue(INumberFormat.providedBy(self.format))
def testParseSimpleInteger(self):
- self.assertEqual(self.format.parse('23341', '###0'),
- 23341)
- self.assertEqual(self.format.parse('041', '#000'),
- 41)
+ self.assertEqual(self.format.parse('23341', '###0'), 23341)
+ self.assertEqual(self.format.parse('041', '#000'), 41)
def testParseScientificInteger(self):
- self.assertEqual(self.format.parse('2.3341E4', '0.0###E0'),
- 23341)
- self.assertEqual(self.format.parse('4.100E01', '0.000##E00'),
- 41)
- self.assertEqual(self.format.parse('1E0', '0E0'),
- 1)
- self.assertEqual(self.format.parse('0E0', '0E0'),
- 0)
+ self.assertEqual(self.format.parse('2.3341E4', '0.0###E0'), 23341)
+ self.assertEqual(self.format.parse('4.100E01', '0.000##E00'), 41)
+ self.assertEqual(self.format.parse('1E0', '0E0'), 1)
+ self.assertEqual(self.format.parse('0E0', '0E0'), 0)
# This is a special case I found not working, but is used frequently
# in the new LDML Locale files.
- self.assertEqual(self.format.parse('2.3341E+04', '0.000###E+00'),
- 23341)
+ self.assertEqual(
+ self.format.parse('2.3341E+04', '0.000###E+00'), 23341
+ )
def testParsePosNegAlternativeInteger(self):
- self.assertEqual(self.format.parse('23341', '#000;#00'),
- 23341)
- self.assertEqual(self.format.parse('041', '#000;#00'),
- 41)
- self.assertEqual(self.format.parse('41', '#000;#00'),
- -41)
- self.assertEqual(self.format.parse('01', '#000;#00'),
- -1)
+ self.assertEqual(self.format.parse('23341', '#000;#00'), 23341)
+ self.assertEqual(self.format.parse('041', '#000;#00'), 41)
+ self.assertEqual(self.format.parse('41', '#000;#00'), -41)
+ self.assertEqual(self.format.parse('01', '#000;#00'), -1)
def testParsePrefixedInteger(self):
- self.assertEqual(self.format.parse('+23341', '+###0'),
- 23341)
- self.assertEqual(self.format.parse('+041', '+#000'),
- 41)
+ self.assertEqual(self.format.parse('+23341', '+###0'), 23341)
+ self.assertEqual(self.format.parse('+041', '+#000'), 41)
def testParsePosNegInteger(self):
- self.assertEqual(self.format.parse('+23341', '+###0;-###0'),
- 23341)
- self.assertEqual(self.format.parse('+041', '+#000;-#000'),
- 41)
- self.assertEqual(self.format.parse('-23341', '+###0;-###0'),
- -23341)
- self.assertEqual(self.format.parse('-041', '+#000;-#000'),
- -41)
+ self.assertEqual(self.format.parse('+23341', '+###0;-###0'), 23341)
+ self.assertEqual(self.format.parse('+041', '+#000;-#000'), 41)
+ self.assertEqual(self.format.parse('-23341', '+###0;-###0'), -23341)
+ self.assertEqual(self.format.parse('-041', '+#000;-#000'), -41)
def testParseThousandSeparatorInteger(self):
- self.assertEqual(self.format.parse('+23,341', '+#,##0;-#,##0'),
- 23341)
- self.assertEqual(self.format.parse('-23,341', '+#,##0;-#,##0'),
- -23341)
- self.assertEqual(self.format.parse('+0,041', '+#0,000;-#0,000'),
- 41)
- self.assertEqual(self.format.parse('-0,041', '+#0,000;-#0,000'),
- -41)
+ self.assertEqual(self.format.parse('+23,341', '+#,##0;-#,##0'), 23341)
+ self.assertEqual(self.format.parse('-23,341', '+#,##0;-#,##0'), -23341)
+ self.assertEqual(self.format.parse('+0,041', '+#0,000;-#0,000'), 41)
+ self.assertEqual(self.format.parse('-0,041', '+#0,000;-#0,000'), -41)
def testParseDecimal(self):
- self.assertEqual(self.format.parse('23341.02', '###0.0#'),
- 23341.02)
- self.assertEqual(self.format.parse('23341.1', '###0.0#'),
- 23341.1)
- self.assertEqual(self.format.parse('23341.020', '###0.000#'),
- 23341.02)
+ self.assertEqual(self.format.parse('23341.02', '###0.0#'), 23341.02)
+ self.assertEqual(self.format.parse('23341.1', '###0.0#'), 23341.1)
+ self.assertEqual(self.format.parse('23341.020', '###0.000#'), 23341.02)
def testParseDecimalWithOptionalDecimalDigits(self):
- self.assertEqual(self.format.parse('23341.02', '###0.##'),
- 23341.02)
- self.assertEqual(self.format.parse('23341', '###0.#'),
- 23341.0)
- self.assertEqual(self.format.parse('23341.', '###0.#'),
- 23341.0)
+ self.assertEqual(self.format.parse('23341.02', '###0.##'), 23341.02)
+ self.assertEqual(self.format.parse('23341', '###0.#'), 23341.0)
+ self.assertEqual(self.format.parse('23341.', '###0.#'), 23341.0)
def testParseScientificDecimal(self):
- self.assertEqual(self.format.parse('2.334102E04', '0.00####E00'),
- 23341.02)
- self.assertEqual(self.format.parse('2.3341020E004', '0.0000000E000'),
- 23341.02)
- self.assertEqual(self.format.parse('0.0E0', '0.0#E0'),
- 0.0)
+ self.assertEqual(
+ self.format.parse('2.334102E04', '0.00####E00'), 23341.02
+ )
+ self.assertEqual(
+ self.format.parse('2.3341020E004', '0.0000000E000'), 23341.02
+ )
+ self.assertEqual(self.format.parse('0.0E0', '0.0#E0'), 0.0)
def testParseScientificDecimalSmallerOne(self):
- self.assertEqual(self.format.parse('2.357E-02', '0.00####E00'),
- 0.02357)
- self.assertEqual(self.format.parse('2.0000E-02', '0.0000E00'),
- 0.02)
+ self.assertEqual(
+ self.format.parse('2.357E-02', '0.00####E00'), 0.02357
+ )
+ self.assertEqual(self.format.parse('2.0000E-02', '0.0000E00'), 0.02)
def testParsePadding1WithoutPrefix(self):
- self.assertEqual(self.format.parse(' 41', '* ##0;*_##0'),
- 41)
- self.assertEqual(self.format.parse('_41', '* ##0;*_##0'),
- -41)
+ self.assertEqual(self.format.parse(' 41', '* ##0;*_##0'), 41)
+ self.assertEqual(self.format.parse('_41', '* ##0;*_##0'), -41)
def testParsePadding1WithPrefix(self):
- self.assertEqual(self.format.parse(' +41', '* +##0;*_-##0'),
- 41)
- self.assertEqual(self.format.parse('_-41', '* +##0;*_-##0'),
- -41)
+ self.assertEqual(self.format.parse(' +41', '* +##0;*_-##0'), 41)
+ self.assertEqual(self.format.parse('_-41', '* +##0;*_-##0'), -41)
def testParsePadding1Padding2WithPrefix(self):
- self.assertEqual(self.format.parse(' + 41', '* +* ###0;*_-*_###0'),
- +41)
- self.assertEqual(self.format.parse('__-_41', '* +* ###0;*_-*_###0'),
- -41)
+ self.assertEqual(
+ self.format.parse(' + 41', '* +* ###0;*_-*_###0'), +41
+ )
+ self.assertEqual(
+ self.format.parse('__-_41', '* +* ###0;*_-*_###0'), -41
+ )
def testParsePadding1Scientific(self):
- self.assertEqual(self.format.parse(' 4.102E1',
- '* 0.0####E0;*_0.0####E0'),
- 41.02)
- self.assertEqual(self.format.parse('__4.102E1',
- '* 0.0####E0;*_0.0####E0'),
- -41.02)
- self.assertEqual(self.format.parse(' +4.102E1',
- '* +0.0###E0;*_-0.0###E0'),
- 41.02)
- self.assertEqual(self.format.parse('_-4.102E1',
- '* +0.0###E0;*_-0.0###E0'),
- -41.02)
+ self.assertEqual(
+ self.format.parse(' 4.102E1', '* 0.0####E0;*_0.0####E0'), 41.02
+ )
+ self.assertEqual(
+ self.format.parse('__4.102E1', '* 0.0####E0;*_0.0####E0'), -41.02
+ )
+ self.assertEqual(
+ self.format.parse(' +4.102E1', '* +0.0###E0;*_-0.0###E0'), 41.02
+ )
+ self.assertEqual(
+ self.format.parse('_-4.102E1', '* +0.0###E0;*_-0.0###E0'), -41.02
+ )
def testParsePadding3WithoutSufffix(self):
- self.assertEqual(self.format.parse('41.02 ', '#0.0###* ;#0.0###*_'),
- 41.02)
- self.assertEqual(self.format.parse('41.02__', '#0.0###* ;#0.0###*_'),
- -41.02)
+ self.assertEqual(
+ self.format.parse('41.02 ', '#0.0###* ;#0.0###*_'), 41.02
+ )
+ self.assertEqual(
+ self.format.parse('41.02__', '#0.0###* ;#0.0###*_'), -41.02
+ )
def testParsePadding3WithSufffix(self):
self.assertEqual(
- self.format.parse('[41.02 ]', '[#0.0###* ];(#0.0###*_)'),
- 41.02)
+ self.format.parse('[41.02 ]', '[#0.0###* ];(#0.0###*_)'), 41.02
+ )
self.assertEqual(
- self.format.parse('(41.02__)', '[#0.0###* ];(#0.0###*_)'),
- -41.02)
+ self.format.parse('(41.02__)', '[#0.0###* ];(#0.0###*_)'), -41.02
+ )
def testParsePadding3Scientific(self):
- self.assertEqual(self.format.parse('4.102E1 ',
- '0.0##E0##* ;0.0##E0##*_'),
- 41.02)
- self.assertEqual(self.format.parse('4.102E1__',
- '0.0##E0##* ;0.0##E0##*_'),
- -41.02)
- self.assertEqual(self.format.parse('(4.102E1 )',
- '(0.0##E0##* );0.0E0'),
- 41.02)
- self.assertEqual(self.format.parse('[4.102E1__]',
- '0.0E0;[0.0##E0##*_]'),
- -41.02)
+ self.assertEqual(
+ self.format.parse('4.102E1 ', '0.0##E0##* ;0.0##E0##*_'), 41.02
+ )
+ self.assertEqual(
+ self.format.parse('4.102E1__', '0.0##E0##* ;0.0##E0##*_'), -41.02
+ )
+ self.assertEqual(
+ self.format.parse('(4.102E1 )', '(0.0##E0##* );0.0E0'), 41.02
+ )
+ self.assertEqual(
+ self.format.parse('[4.102E1__]', '0.0E0;[0.0##E0##*_]'), -41.02
+ )
def testParsePadding3Padding4WithSuffix(self):
- self.assertEqual(self.format.parse('(41.02 ) ', '(#0.0###* )* '),
- 41.02)
- self.assertEqual(self.format.parse('(4.102E1 ) ', '(0.0##E0##* )* '),
- 41.02)
+ self.assertEqual(
+ self.format.parse('(41.02 ) ', '(#0.0###* )* '), 41.02
+ )
+ self.assertEqual(
+ self.format.parse('(4.102E1 ) ', '(0.0##E0##* )* '), 41.02
+ )
def testParseDecimalWithGermanDecimalSeparator(self):
format = NumberFormat(symbols={'decimal': ',', 'group': '.'})
@@ -1210,7 +1575,8 @@ class TestNumberFormat(_TestCase):
def testParseWithAlternativeExponentialSymbol(self):
format = NumberFormat(
- symbols={'decimal': '.', 'group': ',', 'exponential': 'X'})
+ symbols={'decimal': '.', 'group': ',', 'exponential': 'X'}
+ )
self.assertEqual(format.parse('1.2X11', '#.#E0'), 1.2e11)
def testParseFailWithInvalidCharacters(self):
@@ -1232,112 +1598,94 @@ class TestNumberFormat(_TestCase):
def testChangeOutputType(self):
format = NumberFormat()
format.type = decimal.Decimal
- self.assertEqual(format.parse('23341', '###0'),
- decimal.Decimal('23341'))
- self.assertEqual(format.parse('233.41', '###0.00'),
- decimal.Decimal('233.41'))
+ self.assertEqual(
+ format.parse('23341', '###0'), decimal.Decimal('23341')
+ )
+ self.assertEqual(
+ format.parse('233.41', '###0.00'), decimal.Decimal('233.41')
+ )
def testFormatSimpleInteger(self):
- self.assertEqual(self.format.format(23341, '###0'),
- '23341')
- self.assertEqual(self.format.format(41, '#000'),
- '041')
+ self.assertEqual(self.format.format(23341, '###0'), '23341')
+ self.assertEqual(self.format.format(41, '#000'), '041')
def testFormatScientificInteger(self):
- self.assertEqual(self.format.format(23341, '0.000#E0'),
- '2.3341E4')
- self.assertEqual(self.format.format(23341, '0.000#E00'),
- '2.3341E04')
- self.assertEqual(self.format.format(1, '0.##E0'),
- '1E0')
- self.assertEqual(self.format.format(1, '0.00E00'),
- '1.00E00')
+ self.assertEqual(self.format.format(23341, '0.000#E0'), '2.3341E4')
+ self.assertEqual(self.format.format(23341, '0.000#E00'), '2.3341E04')
+ self.assertEqual(self.format.format(1, '0.##E0'), '1E0')
+ self.assertEqual(self.format.format(1, '0.00E00'), '1.00E00')
# This is a special case I found not working, but is used frequently
# in the new LDML Locale files.
- self.assertEqual(self.format.format(23341, '0.000###E+00'),
- '2.3341E+04')
+ self.assertEqual(
+ self.format.format(23341, '0.000###E+00'), '2.3341E+04'
+ )
def testFormatScientificZero(self):
- self.assertEqual(self.format.format(0, '0.00E00'),
- '0.00E00')
- self.assertEqual(self.format.format(0, '0E0'),
- '0E0')
+ self.assertEqual(self.format.format(0, '0.00E00'), '0.00E00')
+ self.assertEqual(self.format.format(0, '0E0'), '0E0')
def testFormatPosNegAlternativeInteger(self):
- self.assertEqual(self.format.format(23341, '#000;#00'),
- '23341')
- self.assertEqual(self.format.format(41, '#000;#00'),
- '041')
- self.assertEqual(self.format.format(-23341, '#000;#00'),
- '23341')
- self.assertEqual(self.format.format(-41, '#000;#00'),
- '41')
- self.assertEqual(self.format.format(-1, '#000;#00'),
- '01')
+ self.assertEqual(self.format.format(23341, '#000;#00'), '23341')
+ self.assertEqual(self.format.format(41, '#000;#00'), '041')
+ self.assertEqual(self.format.format(-23341, '#000;#00'), '23341')
+ self.assertEqual(self.format.format(-41, '#000;#00'), '41')
+ self.assertEqual(self.format.format(-1, '#000;#00'), '01')
def testFormatPrefixedInteger(self):
- self.assertEqual(self.format.format(23341, '+###0'),
- '+23341')
- self.assertEqual(self.format.format(41, '+#000'),
- '+041')
- self.assertEqual(self.format.format(-23341, '+###0'),
- '+23341')
- self.assertEqual(self.format.format(-41, '+#000'),
- '+041')
+ self.assertEqual(self.format.format(23341, '+###0'), '+23341')
+ self.assertEqual(self.format.format(41, '+#000'), '+041')
+ self.assertEqual(self.format.format(-23341, '+###0'), '+23341')
+ self.assertEqual(self.format.format(-41, '+#000'), '+041')
def testFormatPosNegInteger(self):
- self.assertEqual(self.format.format(23341, '+###0;-###0'),
- '+23341')
- self.assertEqual(self.format.format(41, '+#000;-#000'),
- '+041')
- self.assertEqual(self.format.format(-23341, '+###0;-###0'),
- '-23341')
- self.assertEqual(self.format.format(-41, '+#000;-#000'),
- '-041')
+ self.assertEqual(self.format.format(23341, '+###0;-###0'), '+23341')
+ self.assertEqual(self.format.format(41, '+#000;-#000'), '+041')
+ self.assertEqual(self.format.format(-23341, '+###0;-###0'), '-23341')
+ self.assertEqual(self.format.format(-41, '+#000;-#000'), '-041')
def testFormatPosNegScientificInteger(self):
- self.assertEqual(self.format.format(23341, '+0.00###E00;-0.00###E00'),
- '+2.3341E04')
- self.assertEqual(self.format.format(23341, '-0.00###E00;-0.00###E00'),
- '-2.3341E04')
-
- def testFormatThousandSeparatorInteger(self):
- self.assertEqual(
- self.format.format(23341, '+#,##0;-#,##0'),
- '+23,341')
self.assertEqual(
- self.format.format(-23341, '+#,##0;-#,##0'),
- '-23,341')
+ self.format.format(23341, '+0.00###E00;-0.00###E00'), '+2.3341E04'
+ )
self.assertEqual(
- self.format.format(41, '+#0,000;-#0,000'),
- '+0,041')
+ self.format.format(23341, '-0.00###E00;-0.00###E00'), '-2.3341E04'
+ )
+
+ def testFormatThousandSeparatorInteger(self):
+ self.assertEqual(self.format.format(23341, '+#,##0;-#,##0'), '+23,341')
self.assertEqual(
- self.format.format(-41, '+#0,000;-#0,000'),
- '-0,041')
+ self.format.format(-23341, '+#,##0;-#,##0'), '-23,341'
+ )
+ self.assertEqual(self.format.format(41, '+#0,000;-#0,000'), '+0,041')
+ self.assertEqual(self.format.format(-41, '+#0,000;-#0,000'), '-0,041')
self.assertEqual(
- self.format.format(987654321, '+#,##0;-#,##0'),
- '+987,654,321')
+ self.format.format(987654321, '+#,##0;-#,##0'), '+987,654,321'
+ )
self.assertEqual(
- self.format.format(-987654321, '+#,##0;-#,##0'),
- '-987,654,321')
+ self.format.format(-987654321, '+#,##0;-#,##0'), '-987,654,321'
+ )
self.assertEqual(
self.format.format(987654321, '+#,##,#0,000;-#,##,#0,000'),
- '+98,76,54,321')
+ '+98,76,54,321',
+ )
self.assertEqual(
self.format.format(-987654321, '+#,##,#0,000;-#,##,#0,000'),
- '-98,76,54,321')
+ '-98,76,54,321',
+ )
def testFormatBadThousandSeparator(self):
- self.assertRaises(ValueError,
- self.format.format, 23341, '0,')
+ self.assertRaises(ValueError, self.format.format, 23341, '0,')
def testFormatDecimal(self):
- self.assertEqual(self.format.format(23341.02357, '###0.0#'),
- '23341.02')
- self.assertEqual(self.format.format(23341.02357, '###0.000#'),
- '23341.0236')
- self.assertEqual(self.format.format(23341.02, '###0.000#'),
- '23341.020')
+ self.assertEqual(
+ self.format.format(23341.02357, '###0.0#'), '23341.02'
+ )
+ self.assertEqual(
+ self.format.format(23341.02357, '###0.000#'), '23341.0236'
+ )
+ self.assertEqual(
+ self.format.format(23341.02, '###0.000#'), '23341.020'
+ )
def testRounding(self):
self.assertEqual(self.format.format(0.5, '#'), '1')
@@ -1348,110 +1696,126 @@ class TestNumberFormat(_TestCase):
self.assertEqual(self.format.format(1.9999, '0.000'), '2.000')
self.assertEqual(self.format.format(1.9999, '0.0000'), '1.9999')
-
def testFormatScientificDecimal(self):
- self.assertEqual(self.format.format(23341.02357, '0.00####E00'),
- '2.334102E04')
- self.assertEqual(self.format.format(23341.02, '0.0000000E000'),
- '2.3341020E004')
+ self.assertEqual(
+ self.format.format(23341.02357, '0.00####E00'), '2.334102E04'
+ )
+ self.assertEqual(
+ self.format.format(23341.02, '0.0000000E000'), '2.3341020E004'
+ )
def testFormatScientificDecimalSmallerOne(self):
- self.assertEqual(self.format.format(0.02357, '0.00####E00'),
- '2.357E-02')
- self.assertEqual(self.format.format(0.02, '0.0000E00'),
- '2.0000E-02')
+ self.assertEqual(
+ self.format.format(0.02357, '0.00####E00'), '2.357E-02'
+ )
+ self.assertEqual(self.format.format(0.02, '0.0000E00'), '2.0000E-02')
def testFormatPadding1WithoutPrefix(self):
- self.assertEqual(self.format.format(41, '* ##0;*_##0'),
- ' 41')
- self.assertEqual(self.format.format(-41, '* ##0;*_##0'),
- '_41')
+ self.assertEqual(self.format.format(41, '* ##0;*_##0'), ' 41')
+ self.assertEqual(self.format.format(-41, '* ##0;*_##0'), '_41')
def testFormatPadding1WithPrefix(self):
- self.assertEqual(self.format.format(41, '* +##0;*_-##0'),
- ' +41')
- self.assertEqual(self.format.format(-41, '* +##0;*_-##0'),
- '_-41')
+ self.assertEqual(self.format.format(41, '* +##0;*_-##0'), ' +41')
+ self.assertEqual(self.format.format(-41, '* +##0;*_-##0'), '_-41')
def testFormatPadding1Scientific(self):
- self.assertEqual(self.format.format(41.02, '* 0.0####E0;*_0.0####E0'),
- ' 4.102E1')
- self.assertEqual(self.format.format(-41.02, '* 0.0####E0;*_0.0####E0'),
- '__4.102E1')
- self.assertEqual(self.format.format(41.02, '* +0.0###E0;*_-0.0###E0'),
- ' +4.102E1')
- self.assertEqual(self.format.format(-41.02, '* +0.0###E0;*_-0.0###E0'),
- '_-4.102E1')
+ self.assertEqual(
+ self.format.format(41.02, '* 0.0####E0;*_0.0####E0'), ' 4.102E1'
+ )
+ self.assertEqual(
+ self.format.format(-41.02, '* 0.0####E0;*_0.0####E0'), '__4.102E1'
+ )
+ self.assertEqual(
+ self.format.format(41.02, '* +0.0###E0;*_-0.0###E0'), ' +4.102E1'
+ )
+ self.assertEqual(
+ self.format.format(-41.02, '* +0.0###E0;*_-0.0###E0'), '_-4.102E1'
+ )
def testFormatPadding1Padding2WithPrefix(self):
- self.assertEqual(self.format.format(41, '* +* ###0;*_-*_###0'),
- ' + 41')
- self.assertEqual(self.format.format(-41, '* +* ###0;*_-*_###0'),
- '__-_41')
+ self.assertEqual(
+ self.format.format(41, '* +* ###0;*_-*_###0'), ' + 41'
+ )
+ self.assertEqual(
+ self.format.format(-41, '* +* ###0;*_-*_###0'), '__-_41'
+ )
def testFormatPadding3WithoutSufffix(self):
- self.assertEqual(self.format.format(41.02, '#0.0###* ;#0.0###*_'),
- '41.02 ')
- self.assertEqual(self.format.format(-41.02, '#0.0###* ;#0.0###*_'),
- '41.02__')
+ self.assertEqual(
+ self.format.format(41.02, '#0.0###* ;#0.0###*_'), '41.02 '
+ )
+ self.assertEqual(
+ self.format.format(-41.02, '#0.0###* ;#0.0###*_'), '41.02__'
+ )
def testFormatPadding3WithSufffix(self):
- self.assertEqual(self.format.format(41.02, '[#0.0###* ];(#0.0###*_)'),
- '[41.02 ]')
- self.assertEqual(self.format.format(-41.02, '[#0.0###* ];(#0.0###*_)'),
- '(41.02__)')
+ self.assertEqual(
+ self.format.format(41.02, '[#0.0###* ];(#0.0###*_)'), '[41.02 ]'
+ )
+ self.assertEqual(
+ self.format.format(-41.02, '[#0.0###* ];(#0.0###*_)'), '(41.02__)'
+ )
def testFormatPadding3Scientific(self):
- self.assertEqual(self.format.format(41.02, '0.0##E0##* ;0.0##E0##*_'),
- '4.102E1 ')
- self.assertEqual(self.format.format(-41.02, '0.0##E0##* ;0.0##E0##*_'),
- '4.102E1__')
- self.assertEqual(self.format.format(41.02, '(0.0##E0##* );0.0E0'),
- '(4.102E1 )')
- self.assertEqual(self.format.format(-41.02, '0.0E0;[0.0##E0##*_]'),
- '[4.102E1__]')
+ self.assertEqual(
+ self.format.format(41.02, '0.0##E0##* ;0.0##E0##*_'), '4.102E1 '
+ )
+ self.assertEqual(
+ self.format.format(-41.02, '0.0##E0##* ;0.0##E0##*_'), '4.102E1__'
+ )
+ self.assertEqual(
+ self.format.format(41.02, '(0.0##E0##* );0.0E0'), '(4.102E1 )'
+ )
+ self.assertEqual(
+ self.format.format(-41.02, '0.0E0;[0.0##E0##*_]'), '[4.102E1__]'
+ )
def testFormatPadding3Padding4WithSuffix(self):
- self.assertEqual(self.format.format(41.02, '(#0.0###* )* '),
- '(41.02 ) ')
- self.assertEqual(self.format.format(41.02, '(0.0##E0##* )* '),
- '(4.102E1 ) ')
+ self.assertEqual(
+ self.format.format(41.02, '(#0.0###* )* '), '(41.02 ) '
+ )
+ self.assertEqual(
+ self.format.format(41.02, '(0.0##E0##* )* '), '(4.102E1 ) '
+ )
def testFormatSmallNumbers(self):
- self.assertEqual(self.format.format(
- -1e-7, '(#0.00#####);(-#0.00#####)'), '(-0.0000001)')
+ self.assertEqual(
+ self.format.format(-1e-7, '(#0.00#####);(-#0.00#####)'),
+ '(-0.0000001)',
+ )
self.assertEqual(self.format.format(1e-9, '(#0.00###)'), '(0.00)')
self.assertEqual(self.format.format(1e-9, '(#0.00###)'), '(0.00)')
def testFormatHighPrecisionNumbers(self):
self.assertEqual(
- self.format.format(
- 1+1e-7, '(#0.00#####);(-#0.00#####)'),
- '(1.0000001)')
+ self.format.format(1 + 1e-7, '(#0.00#####);(-#0.00#####)'),
+ '(1.0000001)',
+ )
self.assertEqual(
- self.format.format(
- 1+1e-7, '(#0.00###)'),
- '(1.00000)')
+ self.format.format(1 + 1e-7, '(#0.00###)'), '(1.00000)'
+ )
self.assertEqual(
- self.format.format(
- 1+1e-9, '(#0.00#######);(-#0.00#######)'),
- '(1.000000001)')
+ self.format.format(1 + 1e-9, '(#0.00#######);(-#0.00#######)'),
+ '(1.000000001)',
+ )
self.assertEqual(
- self.format.format(
- 1+1e-9, '(#0.00###)'),
- '(1.00000)')
+ self.format.format(1 + 1e-9, '(#0.00###)'), '(1.00000)'
+ )
self.assertEqual(
self.format.format(
- 1+1e-12, '(#0.00##########);(-#0.00##########)'),
- '(1.000000000001)')
+ 1 + 1e-12, '(#0.00##########);(-#0.00##########)'
+ ),
+ '(1.000000000001)',
+ )
self.assertEqual(
- self.format.format(
- 1+1e-12, '(#0.00###)'),
- '(1.00000)')
+ self.format.format(1 + 1e-12, '(#0.00###)'), '(1.00000)'
+ )
def testNoRounding(self):
# Witout Rounding
self.assertEqual(
self.format.format(
- decimal.Decimal('0.99999'), '0.###', rounding=False),
- '0.99999')
+ decimal.Decimal('0.99999'), '0.###', rounding=False
+ ),
+ '0.99999',
+ )
diff --git a/src/zope/i18n/tests/test_gettextmessagecatalog.py b/src/zope/i18n/tests/test_gettextmessagecatalog.py
index 07a0932..3160c97 100644
--- a/src/zope/i18n/tests/test_gettextmessagecatalog.py
+++ b/src/zope/i18n/tests/test_gettextmessagecatalog.py
@@ -19,14 +19,13 @@ from zope.i18n.tests import test_imessagecatalog
class GettextMessageCatalogTest(test_imessagecatalog.TestIMessageCatalog):
-
def _getMessageCatalog(self):
from zope.i18n import tests
+
path = os.path.dirname(tests.__file__)
self._path = os.path.join(path, 'en-default.mo')
catalog = GettextMessageCatalog('en', 'default', self._path)
return catalog
-
def _getUniqueIndentifier(self):
return self._path
diff --git a/src/zope/i18n/tests/test_imessagecatalog.py b/src/zope/i18n/tests/test_imessagecatalog.py
index 803d4f0..36fb43c 100644
--- a/src/zope/i18n/tests/test_imessagecatalog.py
+++ b/src/zope/i18n/tests/test_imessagecatalog.py
@@ -21,7 +21,6 @@ from zope.schema import getValidationErrors
class TestIMessageCatalog(unittest.TestCase):
-
# This should be overridden by every class that inherits this test
def _getMessageCatalog(self):
raise NotImplementedError()
@@ -29,7 +28,6 @@ class TestIMessageCatalog(unittest.TestCase):
def _getUniqueIndentifier(self):
raise NotImplementedError()
-
def setUp(self):
self._catalog = self._getMessageCatalog()
@@ -63,4 +61,4 @@ class TestIMessageCatalog(unittest.TestCase):
def test_suite():
- return unittest.TestSuite() # Deliberately empty
+ return unittest.TestSuite() # Deliberately empty
diff --git a/src/zope/i18n/tests/test_itranslationdomain.py b/src/zope/i18n/tests/test_itranslationdomain.py
index 79c385f..e061d87 100644
--- a/src/zope/i18n/tests/test_itranslationdomain.py
+++ b/src/zope/i18n/tests/test_itranslationdomain.py
@@ -28,16 +28,16 @@ from zope.i18n.interfaces import ITranslationDomain
text_type = str if bytes is not str else unicode
+
@implementer(IUserPreferredLanguages)
class Environment(object):
-
-
def __init__(self, langs=()):
self.langs = langs
def getPreferredLanguages(self):
return self.langs
+
class TestITranslationDomain(PlacelessSetup):
# This should be overwritten by every class that inherits this test
@@ -70,25 +70,40 @@ class TestITranslationDomain(PlacelessSetup):
translate = self._domain.translate
eq = self.assertEqual
# Testing both translation and interpolation
- eq(translate('greeting', mapping={'name': 'Stephan'},
- target_language='de'),
- 'Hallo Stephan, wie geht es Dir?')
+ eq(
+ translate(
+ 'greeting', mapping={'name': 'Stephan'}, target_language='de'
+ ),
+ 'Hallo Stephan, wie geht es Dir?',
+ )
# Testing default value interpolation
- eq(translate('greeting', mapping={'name': 'Philipp'},
- target_language='fr',
- default="Hello $name, how are you?"),
- 'Hello Philipp, how are you?')
+ eq(
+ translate(
+ 'greeting',
+ mapping={'name': 'Philipp'},
+ target_language='fr',
+ default="Hello $name, how are you?",
+ ),
+ 'Hello Philipp, how are you?',
+ )
def testNoTranslation(self):
translate = self._domain.translate
eq = self.assertEqual
# Verify that an unknown message id will end up not being translated
- eq(translate('glorp_smurf_hmpf', target_language='en'),
- 'glorp_smurf_hmpf')
+ eq(
+ translate('glorp_smurf_hmpf', target_language='en'),
+ 'glorp_smurf_hmpf',
+ )
# Test default value behaviour
- eq(translate('glorp_smurf_hmpf', target_language='en',
- default='Glorp Smurf Hmpf'),
- 'Glorp Smurf Hmpf')
+ eq(
+ translate(
+ 'glorp_smurf_hmpf',
+ target_language='en',
+ default='Glorp Smurf Hmpf',
+ ),
+ 'Glorp Smurf Hmpf',
+ )
def testUnicodeDefaultValue(self):
translate = self._domain.translate
@@ -100,7 +115,7 @@ class TestITranslationDomain(PlacelessSetup):
translate = self._domain.translate
eq = self.assertEqual
# Test that default is returned when no language can be negotiated
- context = Environment(('xx', ))
+ context = Environment(('xx',))
eq(translate('short_greeting', context=context, default=42), 42)
# Test that default is returned when there's no destination language
@@ -108,4 +123,4 @@ class TestITranslationDomain(PlacelessSetup):
def test_suite():
- return unittest.TestSuite() # Deliberately empty
+ return unittest.TestSuite() # Deliberately empty
diff --git a/src/zope/i18n/tests/test_negotiator.py b/src/zope/i18n/tests/test_negotiator.py
index f8a0336..d78218e 100644
--- a/src/zope/i18n/tests/test_negotiator.py
+++ b/src/zope/i18n/tests/test_negotiator.py
@@ -20,9 +20,9 @@ from zope.i18n.interfaces import IUserPreferredLanguages
from zope.component.testing import PlacelessSetup
from zope.interface import implementer
+
@implementer(IUserPreferredLanguages)
class Env(object):
-
def __init__(self, langs=()):
self.langs = langs
@@ -31,7 +31,6 @@ class Env(object):
class NegotiatorTest(PlacelessSetup, unittest.TestCase):
-
def setUp(self):
super(NegotiatorTest, self).setUp()
self.negotiator = Negotiator()
@@ -39,23 +38,23 @@ class NegotiatorTest(PlacelessSetup, unittest.TestCase):
def test_findLanguages(self):
_cases = (
- (('en','de'), ('en','de','fr'), 'en'),
- (('en'), ('it','de','fr'), None),
- (('pt-br','de'), ('pt_BR','de','fr'), 'pt_BR'),
- (('pt-br','en'), ('pt', 'en', 'fr'), 'pt'),
- (('pt-br','en-us', 'de'), ('de', 'en', 'fr'), 'en'),
- )
+ (('en', 'de'), ('en', 'de', 'fr'), 'en'),
+ (('en'), ('it', 'de', 'fr'), None),
+ (('pt-br', 'de'), ('pt_BR', 'de', 'fr'), 'pt_BR'),
+ (('pt-br', 'en'), ('pt', 'en', 'fr'), 'pt'),
+ (('pt-br', 'en-us', 'de'), ('de', 'en', 'fr'), 'en'),
+ )
for user_pref_langs, obj_langs, expected in _cases:
env = Env(user_pref_langs)
- self.assertEqual(self.negotiator.getLanguage(obj_langs, env),
- expected)
+ self.assertEqual(
+ self.negotiator.getLanguage(obj_langs, env), expected
+ )
def test_suite():
- return unittest.TestSuite((
- unittest.makeSuite(NegotiatorTest),
- ))
+ return unittest.TestSuite((unittest.makeSuite(NegotiatorTest),))
+
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
diff --git a/src/zope/i18n/tests/test_plurals.py b/src/zope/i18n/tests/test_plurals.py
index d4f57c7..76f1823 100644
--- a/src/zope/i18n/tests/test_plurals.py
+++ b/src/zope/i18n/tests/test_plurals.py
@@ -26,7 +26,6 @@ from zope.i18n.interfaces import ITranslationDomain
class TestPlurals(unittest.TestCase):
-
def _getMessageCatalog(self, locale, variant="default"):
path = os.path.dirname(tests.__file__)
self._path = os.path.join(path, '%s-%s.mo' % (locale, variant))
@@ -47,21 +46,32 @@ class TestPlurals(unittest.TestCase):
self.assertEqual(
catalog.queryPluralMessage(
- 'One apple', '%d apples', 0,
- dft1='One fruit', dft2='%d fruits'),
- '0 fruits')
+ 'One apple', '%d apples', 0, dft1='One fruit', dft2='%d fruits'
+ ),
+ '0 fruits',
+ )
self.assertEqual(
catalog.queryPluralMessage(
- 'One apple.', '%d apples.', 1,
- dft1='One fruit', dft2='%d fruits'),
- 'One fruit')
+ 'One apple.',
+ '%d apples.',
+ 1,
+ dft1='One fruit',
+ dft2='%d fruits',
+ ),
+ 'One fruit',
+ )
self.assertEqual(
catalog.queryPluralMessage(
- 'One apple.', '%d apples.', 2,
- dft1='One fruit', dft2='%d fruits'),
- '2 fruits')
+ 'One apple.',
+ '%d apples.',
+ 2,
+ dft1='One fruit',
+ dft2='%d fruits',
+ ),
+ '2 fruits',
+ )
def test_missing_getPluralMessage(self):
catalog = self._getMessageCatalog('en')
@@ -83,37 +93,65 @@ class TestPlurals(unittest.TestCase):
catalog = self._getMessageCatalog('de')
self.assertEqual(catalog.language, 'de')
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 1),
- 'Es gibt eine Datei.')
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 3),
- 'Es gibt 3 Dateien.')
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 0),
- 'Es gibt 0 Dateien.')
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 1
+ ),
+ 'Es gibt eine Datei.',
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 3
+ ),
+ 'Es gibt 3 Dateien.',
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 0
+ ),
+ 'Es gibt 0 Dateien.',
+ )
# Unknown id
- self.assertRaises(KeyError, catalog.getPluralMessage,
- 'There are %d files.', 'bar', 6)
+ self.assertRaises(
+ KeyError, catalog.getPluralMessage, 'There are %d files.', 'bar', 6
+ )
# Query without default values
- self.assertEqual(catalog.queryPluralMessage(
- 'There is one file.', 'There are %d files.', 1),
- 'Es gibt eine Datei.')
- self.assertEqual(catalog.queryPluralMessage(
- 'There is one file.', 'There are %d files.', 3),
- 'Es gibt 3 Dateien.')
+ self.assertEqual(
+ catalog.queryPluralMessage(
+ 'There is one file.', 'There are %d files.', 1
+ ),
+ 'Es gibt eine Datei.',
+ )
+ self.assertEqual(
+ catalog.queryPluralMessage(
+ 'There is one file.', 'There are %d files.', 3
+ ),
+ 'Es gibt 3 Dateien.',
+ )
# Query with default values
- self.assertEqual(catalog.queryPluralMessage(
- 'There are %d files.', 'There is one file.', 1,
- 'Es gibt 1 Datei.', 'Es gibt %d Dateien !', ),
- 'Es gibt 1 Datei.')
- self.assertEqual(catalog.queryPluralMessage(
- 'There are %d files.', 'There is one file.', 3,
- 'Es gibt 1 Datei.', 'Es gibt %d Dateien !', ),
- 'Es gibt 3 Dateien !')
+ self.assertEqual(
+ catalog.queryPluralMessage(
+ 'There are %d files.',
+ 'There is one file.',
+ 1,
+ 'Es gibt 1 Datei.',
+ 'Es gibt %d Dateien !',
+ ),
+ 'Es gibt 1 Datei.',
+ )
+ self.assertEqual(
+ catalog.queryPluralMessage(
+ 'There are %d files.',
+ 'There is one file.',
+ 3,
+ 'Es gibt 1 Datei.',
+ 'Es gibt %d Dateien !',
+ ),
+ 'Es gibt 3 Dateien !',
+ )
def test_PolishPlurals(self):
"""Polish has a complex rule for plurals. It makes for a good
@@ -122,24 +160,42 @@ class TestPlurals(unittest.TestCase):
catalog = self._getMessageCatalog('pl')
self.assertEqual(catalog.language, 'pl')
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 0),
- u"Istnieją 0 plików.")
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 1),
- u"Istnieje 1 plik.")
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 3),
- u"IstniejÄ… 3 pliki.")
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 17),
- u"Istnieją 17 plików.")
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 23),
- u"IstniejÄ… 23 pliki.")
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 28),
- u"Istnieją 28 plików.")
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 0
+ ),
+ u"Istnieją 0 plików.",
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 1
+ ),
+ u"Istnieje 1 plik.",
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 3
+ ),
+ u"IstniejÄ… 3 pliki.",
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 17
+ ),
+ u"Istnieją 17 plików.",
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 23
+ ),
+ u"IstniejÄ… 23 pliki.",
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 28
+ ),
+ u"Istnieją 28 plików.",
+ )
def test_floater(self):
"""Test with the number being a float.
@@ -149,101 +205,175 @@ class TestPlurals(unittest.TestCase):
self.assertEqual(catalog.language, 'en')
# It's cast to integer because of the %d in the translation string.
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 1.0),
- 'There is one file.')
- self.assertEqual(catalog.getPluralMessage(
- 'There is one file.', 'There are %d files.', 3.5),
- 'There are 3 files.')
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 1.0
+ ),
+ 'There is one file.',
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is one file.', 'There are %d files.', 3.5
+ ),
+ 'There are 3 files.',
+ )
# It's cast to a string because of the %s in the translation string.
- self.assertEqual(catalog.getPluralMessage(
- 'The item is rated 1/5 star.',
- 'The item is rated %s/5 stars.', 3.5),
- 'The item is rated 3.5/5 stars.')
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'The item is rated 1/5 star.',
+ 'The item is rated %s/5 stars.',
+ 3.5,
+ ),
+ 'The item is rated 3.5/5 stars.',
+ )
# It's cast either to an int or a float because of the %s in
# the translation string.
- self.assertEqual(catalog.getPluralMessage(
- 'There is %d chance.',
- 'There are %f chances.', 1.5),
- 'There are 1.500000 chances.')
- self.assertEqual(catalog.getPluralMessage(
- 'There is %d chance.',
- 'There are %f chances.', 3.5),
- 'There are 3.500000 chances.')
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is %d chance.', 'There are %f chances.', 1.5
+ ),
+ 'There are 1.500000 chances.',
+ )
+ self.assertEqual(
+ catalog.getPluralMessage(
+ 'There is %d chance.', 'There are %f chances.', 3.5
+ ),
+ 'There are 3.500000 chances.',
+ )
def test_translate_without_defaults(self):
domain = self._getTranslationDomain('en')
zope.component.provideUtility(domain, ITranslationDomain, 'default')
self.assertEqual(
- translate('One apple', domain='default',
- msgid_plural='%d apples', number=0),
- '0 apples')
+ translate(
+ 'One apple',
+ domain='default',
+ msgid_plural='%d apples',
+ number=0,
+ ),
+ '0 apples',
+ )
self.assertEqual(
- translate('One apple', domain='default',
- msgid_plural='%d apples', number=1),
- 'One apple')
+ translate(
+ 'One apple',
+ domain='default',
+ msgid_plural='%d apples',
+ number=1,
+ ),
+ 'One apple',
+ )
self.assertEqual(
- translate('One apple', domain='default',
- msgid_plural='%d apples', number=2),
- '2 apples')
+ translate(
+ 'One apple',
+ domain='default',
+ msgid_plural='%d apples',
+ number=2,
+ ),
+ '2 apples',
+ )
def test_translate_with_defaults(self):
domain = self._getTranslationDomain('en')
zope.component.provideUtility(domain, ITranslationDomain, 'default')
self.assertEqual(
- translate('One apple', domain='default',
- msgid_plural='%d apples', number=0,
- default='One fruit', default_plural='%d fruits'),
- '0 fruits')
+ translate(
+ 'One apple',
+ domain='default',
+ msgid_plural='%d apples',
+ number=0,
+ default='One fruit',
+ default_plural='%d fruits',
+ ),
+ '0 fruits',
+ )
self.assertEqual(
- translate('One apple', domain='default',
- msgid_plural='%d apples', number=1,
- default='One fruit', default_plural='%d fruits'),
- 'One fruit')
+ translate(
+ 'One apple',
+ domain='default',
+ msgid_plural='%d apples',
+ number=1,
+ default='One fruit',
+ default_plural='%d fruits',
+ ),
+ 'One fruit',
+ )
self.assertEqual(
- translate('One apple', domain='default',
- msgid_plural='%d apples', number=2,
- default='One fruit', default_plural='%d fruits'),
- '2 fruits')
+ translate(
+ 'One apple',
+ domain='default',
+ msgid_plural='%d apples',
+ number=2,
+ default='One fruit',
+ default_plural='%d fruits',
+ ),
+ '2 fruits',
+ )
def test_translate_message_without_defaults(self):
domain = self._getTranslationDomain('en')
factory = MessageFactory('default')
zope.component.provideUtility(domain, ITranslationDomain, 'default')
self.assertEqual(
- translate(factory('One apple', msgid_plural='%d apples',
- number=0)),
- '0 apples')
+ translate(
+ factory('One apple', msgid_plural='%d apples', number=0)
+ ),
+ '0 apples',
+ )
self.assertEqual(
- translate(factory('One apple', msgid_plural='%d apples',
- number=1)),
- 'One apple')
+ translate(
+ factory('One apple', msgid_plural='%d apples', number=1)
+ ),
+ 'One apple',
+ )
self.assertEqual(
- translate(factory('One apple', msgid_plural='%d apples',
- number=2)),
- '2 apples')
+ translate(
+ factory('One apple', msgid_plural='%d apples', number=2)
+ ),
+ '2 apples',
+ )
def test_translate_message_with_defaults(self):
domain = self._getTranslationDomain('en')
factory = MessageFactory('default')
zope.component.provideUtility(domain, ITranslationDomain, 'default')
self.assertEqual(
- translate(factory('One apple', msgid_plural='%d apples', number=0,
- default='One fruit',
- default_plural='%d fruits')),
- '0 fruits')
+ translate(
+ factory(
+ 'One apple',
+ msgid_plural='%d apples',
+ number=0,
+ default='One fruit',
+ default_plural='%d fruits',
+ )
+ ),
+ '0 fruits',
+ )
self.assertEqual(
- translate(factory('One apple', msgid_plural='%d apples', number=1,
- default='One fruit',
- default_plural='%d fruits')),
- 'One fruit')
+ translate(
+ factory(
+ 'One apple',
+ msgid_plural='%d apples',
+ number=1,
+ default='One fruit',
+ default_plural='%d fruits',
+ )
+ ),
+ 'One fruit',
+ )
self.assertEqual(
- translate(factory('One apple', msgid_plural='%d apples', number=2,
- default='One fruit',
- default_plural='%d fruits')),
- '2 fruits')
+ translate(
+ factory(
+ 'One apple',
+ msgid_plural='%d apples',
+ number=2,
+ default='One fruit',
+ default_plural='%d fruits',
+ )
+ ),
+ '2 fruits',
+ )
def test_translate_recursive(self):
domain = self._getTranslationDomain('en')
@@ -251,30 +381,42 @@ class TestPlurals(unittest.TestCase):
# Singular
banana = factory('banana', msgid_plural='bananas', number=1)
- phrase = factory('There is %d ${type}.',
- msgid_plural='There are %d ${type}.',
- number=1, mapping={'type': banana})
+ phrase = factory(
+ 'There is %d ${type}.',
+ msgid_plural='There are %d ${type}.',
+ number=1,
+ mapping={'type': banana},
+ )
self.assertEqual(
domain.translate(phrase, target_language="en"),
- 'There is 1 banana.')
+ 'There is 1 banana.',
+ )
# Plural
apple = factory('apple', msgid_plural='apples', number=10)
- phrase = factory('There is %d ${type}.',
- msgid_plural='There are %d ${type}.',
- number=10, mapping={'type': apple})
+ phrase = factory(
+ 'There is %d ${type}.',
+ msgid_plural='There are %d ${type}.',
+ number=10,
+ mapping={'type': apple},
+ )
self.assertEqual(
domain.translate(phrase, target_language="en"),
- 'There are 10 apples.')
+ 'There are 10 apples.',
+ )
# Straight translation with translatable mapping
apple = factory('apple', msgid_plural='apples', number=75)
self.assertEqual(
- domain.translate(msgid='There is %d ${type}.',
- msgid_plural='There are %d ${type}.',
- mapping={'type': apple},
- target_language="en", number=75),
- 'There are 75 apples.')
+ domain.translate(
+ msgid='There is %d ${type}.',
+ msgid_plural='There are %d ${type}.',
+ mapping={'type': apple},
+ target_language="en",
+ number=75,
+ ),
+ 'There are 75 apples.',
+ )
# Add another catalog, to test the domain's catalogs iteration
# We add this catalog in first position, to resolve the translations
@@ -285,8 +427,12 @@ class TestPlurals(unittest.TestCase):
apple = factory('apple', msgid_plural='apples', number=42)
self.assertEqual(
- domain.translate(msgid='There is %d ${type}.',
- msgid_plural='There are %d ${type}.',
- mapping={'type': apple},
- target_language="de", number=42),
- 'There are 42 oranges.')
+ domain.translate(
+ msgid='There is %d ${type}.',
+ msgid_plural='There are %d ${type}.',
+ mapping={'type': apple},
+ target_language="de",
+ number=42,
+ ),
+ 'There are 42 oranges.',
+ )
diff --git a/src/zope/i18n/tests/test_simpletranslationdomain.py b/src/zope/i18n/tests/test_simpletranslationdomain.py
index 7c87c40..eabf2a1 100644
--- a/src/zope/i18n/tests/test_simpletranslationdomain.py
+++ b/src/zope/i18n/tests/test_simpletranslationdomain.py
@@ -22,11 +22,11 @@ data = {
('en', 'short_greeting'): 'Hello!',
('de', 'short_greeting'): 'Hallo!',
('en', 'greeting'): 'Hello $name, how are you?',
- ('de', 'greeting'): 'Hallo $name, wie geht es Dir?'}
+ ('de', 'greeting'): 'Hallo $name, wie geht es Dir?',
+}
class TestSimpleTranslationDomain(unittest.TestCase, TestITranslationDomain):
-
def setUp(self):
TestITranslationDomain.setUp(self)
diff --git a/src/zope/i18n/tests/test_testmessagecatalog.py b/src/zope/i18n/tests/test_testmessagecatalog.py
index ce5adc6..e90ac1a 100644
--- a/src/zope/i18n/tests/test_testmessagecatalog.py
+++ b/src/zope/i18n/tests/test_testmessagecatalog.py
@@ -15,10 +15,12 @@
import unittest
import doctest
+
def test_suite():
- return unittest.TestSuite((
- doctest.DocFileSuite('../testmessagecatalog.rst')
- ))
+ return unittest.TestSuite(
+ (doctest.DocFileSuite('../testmessagecatalog.rst'))
+ )
+
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
diff --git a/src/zope/i18n/tests/test_translationdomain.py b/src/zope/i18n/tests/test_translationdomain.py
index f8efbd9..4687107 100644
--- a/src/zope/i18n/tests/test_translationdomain.py
+++ b/src/zope/i18n/tests/test_translationdomain.py
@@ -17,8 +17,10 @@ import unittest
import os
from zope.i18n.translationdomain import TranslationDomain
from zope.i18n.gettextmessagecatalog import GettextMessageCatalog
-from zope.i18n.tests.test_itranslationdomain import \
- TestITranslationDomain, Environment
+from zope.i18n.tests.test_itranslationdomain import (
+ TestITranslationDomain,
+ Environment,
+)
from zope.i18nmessageid import MessageFactory
from zope.i18n.interfaces import ITranslationDomain
@@ -31,13 +33,10 @@ de_file = os.path.join(testdir, 'de-default.mo')
class TestGlobalTranslationDomain(TestITranslationDomain, unittest.TestCase):
-
def _getTranslationDomain(self):
domain = TranslationDomain('default')
- en_catalog = GettextMessageCatalog('en', 'default',
- en_file)
- de_catalog = GettextMessageCatalog('de', 'default',
- de_file)
+ en_catalog = GettextMessageCatalog('en', 'default', en_file)
+ de_catalog = GettextMessageCatalog('de', 'default', de_file)
domain.addCatalog(en_catalog)
domain.addCatalog(de_catalog)
return domain
@@ -56,14 +55,24 @@ class TestGlobalTranslationDomain(TestITranslationDomain, unittest.TestCase):
# Test that a translation in an unsupported language returns the
# default, if there is no fallback language
eq(translate('short_greeting', target_language='es'), 'short_greeting')
- eq(translate('short_greeting', target_language='es',
- default='short_greeting'), 'short_greeting')
+ eq(
+ translate(
+ 'short_greeting',
+ target_language='es',
+ default='short_greeting',
+ ),
+ 'short_greeting',
+ )
# Same test, but use the context argument instead of target_language
context = Environment()
eq(translate('short_greeting', context=context), 'short_greeting')
- eq(translate('short_greeting', context=context,
- default='short_greeting'), 'short_greeting')
+ eq(
+ translate(
+ 'short_greeting', context=context, default='short_greeting'
+ ),
+ 'short_greeting',
+ )
def testEmptyStringTranslate(self):
translate = self._domain.translate
@@ -73,7 +82,8 @@ class TestGlobalTranslationDomain(TestITranslationDomain, unittest.TestCase):
def testStringTranslate(self):
self.assertEqual(
self._domain.translate(u"short_greeting", target_language='en'),
- u"Hello!")
+ u"Hello!",
+ )
def testMessageIDTranslate(self):
factory = MessageFactory('default')
@@ -81,44 +91,58 @@ class TestGlobalTranslationDomain(TestITranslationDomain, unittest.TestCase):
msgid = factory(u"short_greeting", 'default')
self.assertEqual(translate(msgid, target_language='en'), u"Hello!")
# MessageID attributes override arguments
- msgid = factory('43-not-there', 'this ${that} the other',
- mapping={'that': 'THAT'})
+ msgid = factory(
+ '43-not-there', 'this ${that} the other', mapping={'that': 'THAT'}
+ )
self.assertEqual(
- translate(msgid, target_language='en', default="default",
- mapping={"that": "that"}), "this THAT the other")
+ translate(
+ msgid,
+ target_language='en',
+ default="default",
+ mapping={"that": "that"},
+ ),
+ "this THAT the other",
+ )
def testMessageIDRecursiveTranslate(self):
factory = MessageFactory('default')
translate = self._domain.translate
- msgid_sub1 = factory(u"44-not-there", '${blue}',
- mapping={'blue': 'BLUE'})
- msgid_sub2 = factory(u"45-not-there", '${yellow}',
- mapping={'yellow': 'YELLOW'})
- mapping = {'color1': msgid_sub1,
- 'color2': msgid_sub2}
- msgid = factory(u"46-not-there", 'Color: ${color1}/${color2}',
- mapping=mapping)
+ msgid_sub1 = factory(
+ u"44-not-there", '${blue}', mapping={'blue': 'BLUE'}
+ )
+ msgid_sub2 = factory(
+ u"45-not-there", '${yellow}', mapping={'yellow': 'YELLOW'}
+ )
+ mapping = {'color1': msgid_sub1, 'color2': msgid_sub2}
+ msgid = factory(
+ u"46-not-there", 'Color: ${color1}/${color2}', mapping=mapping
+ )
self.assertEqual(
translate(msgid, target_language='en', default="default"),
- "Color: BLUE/YELLOW")
+ "Color: BLUE/YELLOW",
+ )
# The recursive translation must not change the mappings
- self.assertEqual(msgid.mapping, {'color1': msgid_sub1,
- 'color2': msgid_sub2})
+ self.assertEqual(
+ msgid.mapping, {'color1': msgid_sub1, 'color2': msgid_sub2}
+ )
# A circular reference should not lead to crashes
- msgid1 = factory(u"47-not-there", 'Message 1 and $msg2',
- mapping={})
- msgid2 = factory(u"48-not-there", 'Message 2 and $msg1',
- mapping={})
+ msgid1 = factory(u"47-not-there", 'Message 1 and $msg2', mapping={})
+ msgid2 = factory(u"48-not-there", 'Message 2 and $msg1', mapping={})
msgid1.mapping['msg2'] = msgid2
msgid2.mapping['msg1'] = msgid1
- self.assertRaises(ValueError,
- translate, msgid1, None, None, 'en', "default")
+ self.assertRaises(
+ ValueError, translate, msgid1, None, None, 'en', "default"
+ )
# Recursive translations also work if the original message id wasn't a
# message id but a Unicode with a directly passed mapping
self.assertEqual(
"Color: BLUE/YELLOW",
- translate(u"Color: ${color1}/${color2}", mapping=mapping,
- target_language='en'))
+ translate(
+ u"Color: ${color1}/${color2}",
+ mapping=mapping,
+ target_language='en',
+ ),
+ )
# If we have mapping with a message id from a different
# domain, make sure we use that domain, not ours. If the
@@ -127,29 +151,34 @@ class TestGlobalTranslationDomain(TestITranslationDomain, unittest.TestCase):
alt_factory = MessageFactory('alt')
msgid_sub = alt_factory(u"special", default=u"oohhh")
mapping = {'message': msgid_sub}
- msgid = factory(u"46-not-there", 'Message: ${message}',
- mapping=mapping)
+ msgid = factory(
+ u"46-not-there", 'Message: ${message}', mapping=mapping
+ )
# test we get a default with no domain registered
self.assertEqual(
translate(msgid, target_language='en', default="default"),
- "Message: oohhh")
+ "Message: oohhh",
+ )
# provide the domain
domain = TranslationDomain('alt')
path = testdir
- en_catalog = GettextMessageCatalog('en', 'alt',
- os.path.join(path, 'en-alt.mo'))
+ en_catalog = GettextMessageCatalog(
+ 'en', 'alt', os.path.join(path, 'en-alt.mo')
+ )
domain.addCatalog(en_catalog)
# test that we get the right translation
zope.component.provideUtility(domain, ITranslationDomain, 'alt')
self.assertEqual(
translate(msgid, target_language='en', default="default"),
- "Message: Wow")
+ "Message: Wow",
+ )
def testMessageIDTranslateForDifferentDomain(self):
domain = TranslationDomain('alt')
path = testdir
- en_catalog = GettextMessageCatalog('en', 'alt',
- os.path.join(path, 'en-alt.mo'))
+ en_catalog = GettextMessageCatalog(
+ 'en', 'alt', os.path.join(path, 'en-alt.mo')
+ )
domain.addCatalog(en_catalog)
zope.component.provideUtility(domain, ITranslationDomain, 'alt')
@@ -157,34 +186,34 @@ class TestGlobalTranslationDomain(TestITranslationDomain, unittest.TestCase):
factory = MessageFactory('alt')
msgid = factory(u"special", 'default')
self.assertEqual(
- self._domain.translate(msgid, target_language='en'), u"Wow")
+ self._domain.translate(msgid, target_language='en'), u"Wow"
+ )
def testSimpleFallbackTranslation(self):
translate = self._domain.translate
eq = self.assertEqual
# Test that a translation in an unsupported language returns a
# translation in the fallback language (by default, English)
- eq(translate('short_greeting', target_language='es'),
- u"Hello!")
+ eq(translate('short_greeting', target_language='es'), u"Hello!")
# Same test, but use the context argument instead of target_language
context = Environment()
- eq(translate('short_greeting', context=context),
- u"Hello!")
+ eq(translate('short_greeting', context=context), u"Hello!")
def testInterpolationWithoutTranslation(self):
translate = self._domain.translate
self.assertEqual(
- translate('42-not-there', target_language="en",
- default="this ${that} the other",
- mapping={"that": "THAT"}),
- "this THAT the other")
+ translate(
+ '42-not-there',
+ target_language="en",
+ default="this ${that} the other",
+ mapping={"that": "THAT"},
+ ),
+ "this THAT the other",
+ )
def test_getCatalogInfos(self):
cats = self._domain.getCatalogsInfo()
- self.assertEqual(
- cats,
- {'en': [en_file],
- 'de': [de_file]})
+ self.assertEqual(cats, {'en': [en_file], 'de': [de_file]})
def test_releoadCatalogs(self):
# It uses the keys we pass
diff --git a/src/zope/i18n/tests/test_zcml.py b/src/zope/i18n/tests/test_zcml.py
index 52ee437..89bff33 100644
--- a/src/zope/i18n/tests/test_zcml.py
+++ b/src/zope/i18n/tests/test_zcml.py
@@ -37,6 +37,7 @@ template = """\
%s
</configure>"""
+
class DirectivesTest(PlacelessSetup, unittest.TestCase):
# This test suite needs the [zcml] and [compile] extra dependencies
@@ -54,13 +55,21 @@ class DirectivesTest(PlacelessSetup, unittest.TestCase):
def testRegisterTranslations(self):
self.assertTrue(queryUtility(ITranslationDomain) is None)
xmlconfig.string(
- template % '''
+ template
+ % '''
<configure package="zope.i18n.tests">
<i18n:registerTranslations directory="locale" />
</configure>
- ''', self.context)
- path = os.path.join(os.path.dirname(zope.i18n.tests.__file__),
- 'locale', 'en', 'LC_MESSAGES', 'zope-i18n.mo')
+ ''',
+ self.context,
+ )
+ path = os.path.join(
+ os.path.dirname(zope.i18n.tests.__file__),
+ 'locale',
+ 'en',
+ 'LC_MESSAGES',
+ 'zope-i18n.mo',
+ )
util = getUtility(ITranslationDomain, 'zope-i18n')
self.assertEqual(util._catalogs.get('test'), ['test'])
self.assertEqual(util._catalogs.get('en'), [text_type(path)])
@@ -69,39 +78,65 @@ class DirectivesTest(PlacelessSetup, unittest.TestCase):
self.assertTrue(queryUtility(ITranslationDomain) is None)
config.ALLOWED_LANGUAGES = ('de', 'fr')
xmlconfig.string(
- template % '''
+ template
+ % '''
<configure package="zope.i18n.tests">
<i18n:registerTranslations directory="locale" />
</configure>
- ''', self.context)
- path = os.path.join(os.path.dirname(zope.i18n.tests.__file__),
- 'locale', 'de', 'LC_MESSAGES', 'zope-i18n.mo')
+ ''',
+ self.context,
+ )
+ path = os.path.join(
+ os.path.dirname(zope.i18n.tests.__file__),
+ 'locale',
+ 'de',
+ 'LC_MESSAGES',
+ 'zope-i18n.mo',
+ )
util = getUtility(ITranslationDomain, 'zope-i18n')
- self.assertEqual(util._catalogs,
- {'test': ['test'], 'de': [text_type(path)]})
+ self.assertEqual(
+ util._catalogs, {'test': ['test'], 'de': [text_type(path)]}
+ )
def testRegisterDistributedTranslations(self):
self.assertTrue(queryUtility(ITranslationDomain, 'zope-i18n') is None)
xmlconfig.string(
- template % '''
+ template
+ % '''
<configure package="zope.i18n.tests">
<i18n:registerTranslations directory="locale" />
</configure>
- ''', self.context)
+ ''',
+ self.context,
+ )
xmlconfig.string(
- template % '''
+ template
+ % '''
<configure package="zope.i18n.tests">
<i18n:registerTranslations directory="locale2" />
</configure>
- ''', self.context)
- path1 = os.path.join(os.path.dirname(zope.i18n.tests.__file__),
- 'locale', 'en', 'LC_MESSAGES', 'zope-i18n.mo')
- path2 = os.path.join(os.path.dirname(zope.i18n.tests.__file__),
- 'locale2', 'en', 'LC_MESSAGES', 'zope-i18n.mo')
+ ''',
+ self.context,
+ )
+ path1 = os.path.join(
+ os.path.dirname(zope.i18n.tests.__file__),
+ 'locale',
+ 'en',
+ 'LC_MESSAGES',
+ 'zope-i18n.mo',
+ )
+ path2 = os.path.join(
+ os.path.dirname(zope.i18n.tests.__file__),
+ 'locale2',
+ 'en',
+ 'LC_MESSAGES',
+ 'zope-i18n.mo',
+ )
util = getUtility(ITranslationDomain, 'zope-i18n')
self.assertEqual(util._catalogs.get('test'), ['test', 'test'])
- self.assertEqual(util._catalogs.get('en'),
- [text_type(path1), text_type(path2)])
+ self.assertEqual(
+ util._catalogs.get('en'), [text_type(path1), text_type(path2)]
+ )
msg = util.translate(u"Additional message", target_language='en')
self.assertEqual(msg, u"Additional message translated")
@@ -131,14 +166,18 @@ class DirectivesTest(PlacelessSetup, unittest.TestCase):
os.utime(path, (path_atime, path_mtime - 6000))
xmlconfig.string(
- template % '''
+ template
+ % '''
<configure package="zope.i18n.tests">
<i18n:registerTranslations directory="locale3" />
</configure>
- ''', self.context)
+ ''',
+ self.context,
+ )
util = getUtility(ITranslationDomain, 'zope-i18n')
- self.assertEqual(util._catalogs,
- {'test': ['test'], 'en': [text_type(path)]})
+ self.assertEqual(
+ util._catalogs, {'test': ['test'], 'en': [text_type(path)]}
+ )
msg = util.translate(u"I'm a newer file", target_language='en')
self.assertEqual(msg, u"I'm a newer file translated")
@@ -154,22 +193,33 @@ class DirectivesTest(PlacelessSetup, unittest.TestCase):
self.assertTrue(queryUtility(ITranslationDomain, 'zope-i18n') is None)
self.assertTrue(queryUtility(ITranslationDomain, 'zope-i18n2') is None)
xmlconfig.string(
- template % '''
+ template
+ % '''
<configure package="zope.i18n.tests">
<i18n:registerTranslations directory="locale3" domain="zope-i18n" />
</configure>
- ''', self.context)
- path = os.path.join(os.path.dirname(zope.i18n.tests.__file__),
- 'locale3', 'en', 'LC_MESSAGES', 'zope-i18n.mo')
+ ''',
+ self.context,
+ )
+ path = os.path.join(
+ os.path.dirname(zope.i18n.tests.__file__),
+ 'locale3',
+ 'en',
+ 'LC_MESSAGES',
+ 'zope-i18n.mo',
+ )
util = getUtility(ITranslationDomain, 'zope-i18n')
- self.assertEqual(util._catalogs,
- {'test': ['test'], 'en': [text_type(path)]})
+ self.assertEqual(
+ util._catalogs, {'test': ['test'], 'en': [text_type(path)]}
+ )
self.assertTrue(queryUtility(ITranslationDomain, 'zope-i18n2') is None)
def test_suite():
- return unittest.TestSuite((
- unittest.defaultTestLoader.loadTestsFromName(__name__),
- doctest.DocFileSuite('configure.txt'),
- ))
+ return unittest.TestSuite(
+ (
+ unittest.defaultTestLoader.loadTestsFromName(__name__),
+ doctest.DocFileSuite('configure.txt'),
+ )
+ )
diff --git a/src/zope/i18n/tests/testi18nawareobject.py b/src/zope/i18n/tests/testi18nawareobject.py
index 21a61f4..b1a175e 100644
--- a/src/zope/i18n/tests/testi18nawareobject.py
+++ b/src/zope/i18n/tests/testi18nawareobject.py
@@ -21,7 +21,6 @@ from zope.interface import implementer
@implementer(II18nAware)
class I18nAwareContentObject(object):
-
def __init__(self):
self.content = {}
self.defaultLanguage = 'en'
@@ -54,8 +53,8 @@ class I18nAwareContentObject(object):
#
############################################################
-class AbstractTestII18nAwareMixin(object):
+class AbstractTestII18nAwareMixin(object):
def setUp(self):
self.object = self._createObject()
self.object.setDefaultLanguage('fr')
@@ -73,11 +72,12 @@ class AbstractTestII18nAwareMixin(object):
self.assertEqual(self.object.getDefaultLanguage(), 'lt')
def testGetAvailableLanguages(self):
- self.assertEqual(sorted(self.object.getAvailableLanguages()), ['en', 'fr', 'lt'])
+ self.assertEqual(
+ sorted(self.object.getAvailableLanguages()), ['en', 'fr', 'lt']
+ )
class TestI18nAwareObject(AbstractTestII18nAwareMixin, unittest.TestCase):
-
def _createObject(self):
object = I18nAwareContentObject()
object.setContent('English', 'en')
diff --git a/src/zope/i18n/translationdomain.py b/src/zope/i18n/translationdomain.py
index b9287f0..af8eee2 100644
--- a/src/zope/i18n/translationdomain.py
+++ b/src/zope/i18n/translationdomain.py
@@ -37,10 +37,10 @@ text_type = str if bytes is not str else unicode
@zope.interface.implementer(ITranslationDomain)
class TranslationDomain(object):
-
def __init__(self, domain, fallbacks=None):
self.domain = (
- domain.decode("utf-8") if isinstance(domain, bytes) else domain)
+ domain.decode("utf-8") if isinstance(domain, bytes) else domain
+ )
# _catalogs maps (language, domain) to IMessageCatalog instances
self._catalogs = {}
# _data maps IMessageCatalog.getIdentifier() to IMessageCatalog
@@ -56,17 +56,24 @@ class TranslationDomain(object):
def addCatalog(self, catalog):
self._data[catalog.getIdentifier()] = catalog
- self._registerMessageCatalog(catalog.language,
- catalog.getIdentifier())
+ self._registerMessageCatalog(catalog.language, catalog.getIdentifier())
def setLanguageFallbacks(self, fallbacks=None):
if fallbacks is None:
fallbacks = LANGUAGE_FALLBACKS
self._fallbacks = fallbacks
- def translate(self, msgid, mapping=None, context=None,
- target_language=None, default=None,
- msgid_plural=None, default_plural=None, number=None):
+ def translate(
+ self,
+ msgid,
+ mapping=None,
+ context=None,
+ target_language=None,
+ default=None,
+ msgid_plural=None,
+ default_plural=None,
+ number=None,
+ ):
"""See zope.i18n.interfaces.ITranslationDomain"""
# if the msgid is empty, let's save a lot of calculations and return
# an empty string.
@@ -81,19 +88,43 @@ class TranslationDomain(object):
target_language = negotiator.getLanguage(langs, context)
return self._recursive_translate(
- msgid, mapping, target_language, default, context,
- msgid_plural, default_plural, number)
-
- def _recursive_translate(self, msgid, mapping, target_language, default,
- context, msgid_plural, default_plural, number,
- seen=None):
+ msgid,
+ mapping,
+ target_language,
+ default,
+ context,
+ msgid_plural,
+ default_plural,
+ number,
+ )
+
+ def _recursive_translate(
+ self,
+ msgid,
+ mapping,
+ target_language,
+ default,
+ context,
+ msgid_plural,
+ default_plural,
+ number,
+ seen=None,
+ ):
"""Recursively translate msg."""
# MessageID attributes override arguments
if isinstance(msgid, Message):
if msgid.domain != self.domain:
return translate(
- msgid, msgid.domain, mapping, context, target_language,
- default, msgid_plural, default_plural, number)
+ msgid,
+ msgid.domain,
+ mapping,
+ context,
+ target_language,
+ default,
+ msgid_plural,
+ default_plural,
+ number,
+ )
default = msgid.default
mapping = msgid.mapping
msgid_plural = msgid.msgid_plural
@@ -101,8 +132,9 @@ class TranslationDomain(object):
number = msgid.number
# Recursively translate mappings, if they are translatable
- if (mapping is not None
- and Message in (type(m) for m in mapping.values())):
+ if mapping is not None and Message in (
+ type(m) for m in mapping.values()
+ ):
if seen is None:
seen = set()
seen.add((msgid, msgid_plural))
@@ -113,11 +145,20 @@ class TranslationDomain(object):
# https://bugs.launchpad.net/zope3/+bug/220122
if (value, value.msgid_plural) in seen:
raise ValueError(
- "Circular reference in mappings detected: %s" %
- value)
+ "Circular reference in mappings detected: %s"
+ % value
+ )
mapping[key] = self._recursive_translate(
- value, mapping, target_language, default, context,
- msgid_plural, default_plural, number, seen)
+ value,
+ mapping,
+ target_language,
+ default,
+ context,
+ msgid_plural,
+ default_plural,
+ number,
+ seen,
+ )
if default is None:
default = text_type(msgid)
@@ -142,18 +183,24 @@ class TranslationDomain(object):
if msgid_plural is not None:
# This is a plural
text = self._data[catalog_names[0]].queryPluralMessage(
- msgid, msgid_plural, number, default, default_plural)
+ msgid, msgid_plural, number, default, default_plural
+ )
else:
text = self._data[catalog_names[0]].queryMessage(
- msgid, default)
+ msgid, default
+ )
else:
for name in catalog_names:
catalog = self._data[name]
if msgid_plural is not None:
# This is a plural
s = catalog.queryPluralMessage(
- msgid, msgid_plural, number,
- default, default_plural)
+ msgid,
+ msgid_plural,
+ number,
+ default,
+ default_plural,
+ )
else:
s = catalog.queryMessage(msgid)
if s is not None:
diff --git a/src/zope/i18n/zcml.py b/src/zope/i18n/zcml.py
index 4df9ccb..7ae6319 100644
--- a/src/zope/i18n/zcml.py
+++ b/src/zope/i18n/zcml.py
@@ -1,4 +1,3 @@
-
# ##############################################################################
#
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
@@ -44,15 +43,17 @@ class IRegisterTranslationsDirective(Interface):
directory = Path(
title=u"Directory",
description=u"Directory containing the translations",
- required=True
- )
+ required=True,
+ )
domain = TextLine(
title=u"Domain",
- description=(u"Translation domain to register. If not specified, "
- u"all domains found in the directory are registered"),
- required=False
- )
+ description=(
+ u"Translation domain to register. If not specified, "
+ u"all domains found in the directory are registered"
+ ),
+ required=False,
+ )
def allow_language(lang):
@@ -90,13 +91,15 @@ def registerTranslations(_context, directory, domain='*'):
if os.path.isdir(lc_messages_path):
# Preprocess files and update or compile the mo files
if config.COMPILE_MO_FILES:
- for domain_path in glob(os.path.join(lc_messages_path,
- '%s.po' % domain)):
+ for domain_path in glob(
+ os.path.join(lc_messages_path, '%s.po' % domain)
+ ):
domain_file = os.path.basename(domain_path)
name = domain_file[:-3]
compile_mo_file(name, lc_messages_path)
- for domain_path in glob(os.path.join(lc_messages_path,
- '%s.mo' % domain)):
+ for domain_path in glob(
+ os.path.join(lc_messages_path, '%s.mo' % domain)
+ ):
loaded = True
domain_file = os.path.basename(domain_path)
name = domain_file[:-3]
@@ -115,13 +118,13 @@ def registerTranslations(_context, directory, domain='*'):
# `zope.component.zcml.utility`) since we need the actual utilities
# in place before the merging can be done...
_context.action(
- discriminator=None,
- callable=handler,
- args=(catalogs, name))
+ discriminator=None, callable=handler, args=(catalogs, name)
+ )
# also register the interface for the translation utilities
provides = ITranslationDomain
_context.action(
discriminator=None,
callable=provideInterface,
- args=(provides.__module__ + '.' + provides.getName(), provides))
+ args=(provides.__module__ + '.' + provides.getName(), provides),
+ )