summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Lebedev <andrey@lebedev.lt>2013-02-15 12:40:06 +0000
committerAndrey Lebedev <andrey@lebedev.lt>2013-02-15 12:40:06 +0000
commit570ca504d25bc9ae756ff1b163e758861d3349e9 (patch)
tree0a8a548e5c7eb122bee29234b2e5032e73f5b67d
parent3fb5a4e020f5583140c820ef3b3bdbfe1b12da8b (diff)
downloadzope-i18n-570ca504d25bc9ae756ff1b163e758861d3349e9.tar.gz
Support for python-3.3 added
-rw-r--r--CHANGES.txt2
-rw-r--r--bootstrap.py186
-rw-r--r--setup.py2
-rw-r--r--src/zope/i18n/__init__.py5
-rw-r--r--src/zope/i18n/format.py19
-rw-r--r--src/zope/i18n/gettextmessagecatalog.py12
-rw-r--r--src/zope/i18n/locales/__init__.py38
-rw-r--r--src/zope/i18n/locales/fallbackcollator.py5
-rw-r--r--src/zope/i18n/locales/inheritance.py4
-rw-r--r--src/zope/i18n/locales/provider.py2
-rw-r--r--src/zope/i18n/locales/tests/test_docstrings.py8
-rw-r--r--src/zope/i18n/locales/tests/test_fallbackcollator.py4
-rw-r--r--src/zope/i18n/locales/tests/test_locales.py19
-rw-r--r--src/zope/i18n/locales/xmlfactory.py16
-rw-r--r--src/zope/i18n/simpletranslationdomain.py5
-rw-r--r--src/zope/i18n/testing.py22
-rw-r--r--src/zope/i18n/tests/test.py4
-rw-r--r--src/zope/i18n/tests/test_formats.py52
-rw-r--r--src/zope/i18n/tests/test_itranslationdomain.py4
-rw-r--r--src/zope/i18n/tests/test_testmessagecatalog.py4
-rw-r--r--src/zope/i18n/tests/test_zcml.py5
-rw-r--r--src/zope/i18n/tests/testii18naware.py4
-rw-r--r--src/zope/i18n/translationdomain.py5
-rw-r--r--tox.ini12
24 files changed, 277 insertions, 162 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 0583318..1a4546e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -5,6 +5,8 @@ CHANGES
4.0.0 (unreleased)
------------------
+- Support for python-3.3 added
+
- log DEBUG when loading translations from directories.
- Replaced deprecated ``zope.interface.implements`` usage with equivalent
diff --git a/bootstrap.py b/bootstrap.py
index a6da5d3..ec3757a 100644
--- a/bootstrap.py
+++ b/bootstrap.py
@@ -18,102 +18,148 @@ The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
-import os, shutil, sys, tempfile, urllib2
+import os, shutil, sys, tempfile
from optparse import OptionParser
tmpeggs = tempfile.mkdtemp()
-is_jython = sys.platform.startswith('java')
+usage = '''\
+[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
-# parsing arguments
-parser = OptionParser()
-parser.add_option("-v", "--version", dest="version",
- help="use a specific zc.buildout version")
-parser.add_option("-d", "--distribute",
- action="store_true", dest="distribute", default=False,
- help="Use Disribute rather than Setuptools.")
+Bootstraps a buildout-based project.
-parser.add_option("-c", None, action="store", dest="config_file",
+Simply run this script in a directory containing a buildout.cfg, using the
+Python that you want bin/buildout to use.
+
+Note that by using --setup-source and --download-base to point to
+local resources, you can keep this script from going over the network.
+'''
+
+parser = OptionParser(usage=usage)
+parser.add_option("-v", "--version", help="use a specific zc.buildout version")
+
+parser.add_option("-t", "--accept-buildout-test-releases",
+ dest='accept_buildout_test_releases',
+ action="store_true", default=False,
+ help=("Normally, if you do not specify a --version, the "
+ "bootstrap script and buildout gets the newest "
+ "*final* versions of zc.buildout and its recipes and "
+ "extensions for you. If you use this flag, "
+ "bootstrap and buildout will get the newest releases "
+ "even if they are alphas or betas."))
+parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
+parser.add_option("-f", "--find-links",
+ help=("Specify a URL to search for buildout releases"))
-options, args = parser.parse_args()
-
-# if -c was provided, we push it back into args for buildout' main function
-if options.config_file is not None:
- args += ['-c', options.config_file]
-if options.version is not None:
- VERSION = '==%s' % options.version
-else:
- VERSION = ''
+options, args = parser.parse_args()
-USE_DISTRIBUTE = options.distribute
-args = args + ['bootstrap']
+######################################################################
+# load/install distribute
to_reload = False
try:
- import pkg_resources
+ import pkg_resources, setuptools
if not hasattr(pkg_resources, '_distribute'):
to_reload = True
raise ImportError
except ImportError:
ez = {}
- if USE_DISTRIBUTE:
- exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py'
- ).read() in ez
- ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
- else:
- exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
- ).read() in ez
- ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+ try:
+ from urllib.request import urlopen
+ except ImportError:
+ from urllib2 import urlopen
+
+ exec(urlopen('http://python-distribute.org/distribute_setup.py').read(), ez)
+ setup_args = dict(to_dir=tmpeggs, download_delay=0, no_fake=True)
+ ez['use_setuptools'](**setup_args)
if to_reload:
reload(pkg_resources)
- else:
- import pkg_resources
-
-if sys.platform == 'win32':
- def quote(c):
- if ' ' in c:
- return '"%s"' % c # work around spawn lamosity on windows
- else:
- return c
-else:
- def quote (c):
- return c
-
-cmd = 'from setuptools.command.easy_install import main; main()'
+ import pkg_resources
+ # This does not (always?) update the default working set. We will
+ # do it.
+ for path in sys.path:
+ if path not in pkg_resources.working_set.entries:
+ pkg_resources.working_set.add_entry(path)
+
+######################################################################
+# Install buildout
+
ws = pkg_resources.working_set
-if USE_DISTRIBUTE:
- requirement = 'distribute'
-else:
- requirement = 'setuptools'
-
-if is_jython:
- import subprocess
-
- assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
- quote(tmpeggs), 'zc.buildout' + VERSION],
- env=dict(os.environ,
- PYTHONPATH=
- ws.find(pkg_resources.Requirement.parse(requirement)).location
- ),
- ).wait() == 0
-
-else:
- assert os.spawnle(
- os.P_WAIT, sys.executable, quote (sys.executable),
- '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION,
- dict(os.environ,
- PYTHONPATH=
- ws.find(pkg_resources.Requirement.parse(requirement)).location
- ),
- ) == 0
+cmd = [sys.executable, '-c',
+ 'from setuptools.command.easy_install import main; main()',
+ '-mZqNxd', tmpeggs]
+
+find_links = os.environ.get(
+ 'bootstrap-testing-find-links',
+ options.find_links or
+ ('http://downloads.buildout.org/'
+ if options.accept_buildout_test_releases else None)
+ )
+if find_links:
+ cmd.extend(['-f', find_links])
+
+distribute_path = ws.find(
+ pkg_resources.Requirement.parse('distribute')).location
+
+requirement = 'zc.buildout'
+version = options.version
+if version is None and not options.accept_buildout_test_releases:
+ # Figure out the most recent final version of zc.buildout.
+ import setuptools.package_index
+ _final_parts = '*final-', '*final'
+ def _final_version(parsed_version):
+ for part in parsed_version:
+ if (part[:1] == '*') and (part not in _final_parts):
+ return False
+ return True
+ index = setuptools.package_index.PackageIndex(
+ search_path=[distribute_path])
+ if find_links:
+ index.add_find_links((find_links,))
+ req = pkg_resources.Requirement.parse(requirement)
+ if index.obtain(req) is not None:
+ best = []
+ bestv = None
+ for dist in index[req.project_name]:
+ distv = dist.parsed_version
+ if _final_version(distv):
+ if bestv is None or distv > bestv:
+ best = [dist]
+ bestv = distv
+ elif distv == bestv:
+ best.append(dist)
+ if best:
+ best.sort()
+ version = best[-1].version
+if version:
+ requirement = '=='.join((requirement, version))
+cmd.append(requirement)
+
+import subprocess
+if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=distribute_path)) != 0:
+ raise Exception(
+ "Failed to execute command:\n%s",
+ repr(cmd)[1:-1])
+
+######################################################################
+# Import and run buildout
ws.add_entry(tmpeggs)
-ws.require('zc.buildout' + VERSION)
+ws.require(requirement)
import zc.buildout.buildout
+
+if not [a for a in args if '=' not in a]:
+ args.append('bootstrap')
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+ args[0:0] = ['-c', options.config_file]
+
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)
diff --git a/setup.py b/setup.py
index f6b3876..eedb8f8 100644
--- a/setup.py
+++ b/setup.py
@@ -48,6 +48,8 @@ setup(
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.3",
'Natural Language :: English',
'Operating System :: OS Independent',
'Topic :: Internet :: WWW/HTTP',
diff --git a/src/zope/i18n/__init__.py b/src/zope/i18n/__init__.py
index aeb1c91..ca4974e 100644
--- a/src/zope/i18n/__init__.py
+++ b/src/zope/i18n/__init__.py
@@ -13,6 +13,7 @@
##############################################################################
"""i18n support.
"""
+import sys
import re
from zope.component import queryUtility
@@ -23,6 +24,10 @@ from zope.i18n.interfaces import INegotiator
from zope.i18n.interfaces import ITranslationDomain
from zope.i18n.interfaces import IFallbackTranslationDomainFactory
+PY3 = sys.version_info[0] == 3
+if PY3:
+ unicode = str
+
# Set up regular expressions for finding interpolation variables in text.
# NAME_RE must exactly match the expression of the same name in the
# zope.tal.taldefs module:
diff --git a/src/zope/i18n/format.py b/src/zope/i18n/format.py
index 101bd7e..51d64f1 100644
--- a/src/zope/i18n/format.py
+++ b/src/zope/i18n/format.py
@@ -16,6 +16,7 @@
This module implements basic object formatting functionality, such as
date/time, number and money formatting.
"""
+import sys
import re
import math
import datetime
@@ -25,6 +26,18 @@ import pytz.reference
from zope.i18n.interfaces import IDateTimeFormat, INumberFormat
from zope.interface import implementer
+PY3 = sys.version_info[0] == 3
+if PY3:
+ unicode = str
+
+def roundHalfUp(n):
+ """Works like round() in python2.x
+
+ Implementation of round() was changed in python3 - it rounds halfs to
+ nearest even number, so that round(0.5) == 0. This function is here to
+ unify behaviour between python 2.x and 3.x for the purposes of this module.
+ """
+ return math.floor(n + math.copysign(0.5, n))
def _findFormattingCharacterInPattern(char, pattern):
return [entry for entry in pattern
@@ -86,7 +99,7 @@ class DateTimeFormat(object):
# Map the parsing results to a datetime object
ordered = [None, None, None, None, None, None, None]
- bin_pattern = filter(lambda x: isinstance(x, tuple), bin_pattern)
+ bin_pattern = list(filter(lambda x: isinstance(x, tuple), bin_pattern))
# Handle years; note that only 'yy' and 'yyyy' are allowed
if ('y', 2) in bin_pattern:
@@ -408,7 +421,7 @@ class NumberFormat(object):
fraction = ''
roundInt = False
if roundInt:
- obj = round(obj)
+ obj = roundHalfUp(obj)
integer = self._format_integer(str(int(math.fabs(obj))),
bin_pattern[INTEGER])
# Adding grouping
@@ -599,7 +612,7 @@ 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, 01, 01, dt.hour, dt.minute, dt.second,
+ 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)):
diff --git a/src/zope/i18n/gettextmessagecatalog.py b/src/zope/i18n/gettextmessagecatalog.py
index b121298..1376d11 100644
--- a/src/zope/i18n/gettextmessagecatalog.py
+++ b/src/zope/i18n/gettextmessagecatalog.py
@@ -13,21 +13,23 @@
##############################################################################
"""A simple implementation of a Message Catalog.
"""
+import sys
from gettext import GNUTranslations
from zope.i18n.interfaces import IGlobalMessageCatalog
from zope.interface import implementer
+PY2 = sys.version_info[0] == 2
class _KeyErrorRaisingFallback(object):
def ugettext(self, message):
raise KeyError(message)
+ gettext = ugettext
@implementer(IGlobalMessageCatalog)
class GettextMessageCatalog(object):
"""A message catalog based on GNU gettext and Python's gettext module."""
-
def __init__(self, language, domain, path_to_file):
"""Initialize the message catalog"""
self.language = language
@@ -35,6 +37,10 @@ class GettextMessageCatalog(object):
self._path_to_file = path_to_file
self.reload()
self._catalog.add_fallback(_KeyErrorRaisingFallback())
+ if PY2:
+ self._gettext = self._catalog.ugettext
+ else:
+ self._gettext = self._catalog.gettext
def reload(self):
'See IMessageCatalog'
@@ -46,12 +52,12 @@ class GettextMessageCatalog(object):
def getMessage(self, id):
'See IMessageCatalog'
- return self._catalog.ugettext(id)
+ return self._gettext(id)
def queryMessage(self, id, default=None):
'See IMessageCatalog'
try:
- return self._catalog.ugettext(id)
+ return self._gettext(id)
except KeyError:
return default
diff --git a/src/zope/i18n/locales/__init__.py b/src/zope/i18n/locales/__init__.py
index d6d0d05..da83db3 100644
--- a/src/zope/i18n/locales/__init__.py
+++ b/src/zope/i18n/locales/__init__.py
@@ -124,21 +124,21 @@ class LocaleVersion(object):
Examples::
- >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
+ >>> (LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes') ==
... LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes again'))
- 0
+ True
- >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
+ >>> (LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes') <
... LocaleVersion('1.0', datetime(2004, 1, 2), 'no notes again'))
- -1
+ True
- >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
+ >>> (LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes') <
... LocaleVersion('0.9', datetime(2004, 1, 2), 'no notes again'))
- -1
+ True
- >>> cmp(LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes'),
+ >>> (LocaleVersion('1.0', datetime(2004, 1, 1), 'no notes') >
... LocaleVersion('0.9', datetime(2004, 1, 1), 'no notes again'))
- 1
+ True
"""
@@ -149,11 +149,13 @@ class LocaleVersion(object):
self.generationDate = generationDate
self.notes = notes
- def __cmp__(self, other):
- "See zope.i18n.interfaces.ILocaleVersion"
- return cmp((self.generationDate, self.number),
- (other.generationDate, other.number))
+ def __lt__(self, other):
+ return ((self.generationDate, self.number) <
+ (other.generationDate, other.number))
+ def __eq__(self, other):
+ return ((self.generationDate, self.number) ==
+ (other.generationDate, other.number))
@implementer(ILocaleDisplayNames)
class LocaleDisplayNames(AttributeInheritance):
@@ -413,11 +415,11 @@ class LocaleDates(AttributeInheritance):
>>> cal.defaultDateFormat = 'medium'
>>> formatter = dates.getFormatter('date')
- >>> formatter.format(date(2004, 02, 04))
+ >>> formatter.format(date(2004, 2, 4))
u'04.02.2004'
>>> formatter = dates.getFormatter('date', length='full')
- >>> formatter.format(date(2004, 02, 04))
+ >>> formatter.format(date(2004, 2, 4))
u'Mittwoch, 4. Februar 2004'
Let's also test the time formatter::
@@ -453,11 +455,11 @@ class LocaleDates(AttributeInheritance):
>>> cal.dateTimeFormats = {None: length}
>>> formatter = dates.getFormatter('dateTime')
- >>> formatter.format(datetime(2004, 02, 04, 12, 15, 00))
+ >>> formatter.format(datetime(2004, 2, 4, 12, 15, 00))
u'04.02.2004 12:15:00'
>>> formatter = dates.getFormatter('dateTime', length='full')
- >>> formatter.format(datetime(2004, 02, 04, 12, 15, 00))
+ >>> formatter.format(datetime(2004, 2, 4, 12, 15, 00))
u'Mittwoch, 4. Februar 2004 12:15 Uhr +000'
Finally, we'll test some invalid input::
@@ -495,7 +497,7 @@ class LocaleDates(AttributeInheritance):
length = getattr(
cal,
'default'+category[0].upper()+category[1:]+'Format',
- formats.keys()[0])
+ 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
@@ -621,7 +623,7 @@ class LocaleNumbers(AttributeInheritance):
length = getattr(
self,
'default'+category[0].upper()+category[1:]+'Format',
- formats.keys()[0])
+ list(formats.keys())[0])
formatLength = formats[length]
if name is None:
diff --git a/src/zope/i18n/locales/fallbackcollator.py b/src/zope/i18n/locales/fallbackcollator.py
index 0cf2679..fc76a58 100644
--- a/src/zope/i18n/locales/fallbackcollator.py
+++ b/src/zope/i18n/locales/fallbackcollator.py
@@ -26,4 +26,7 @@ class FallbackCollator:
return s.lower(), s
def cmp(self, s1, s2):
- return cmp(self.key(s1), self.key(s2))
+ k1, k2 = self.key(s1), self.key(s2)
+ if k1 == k2:
+ return 0
+ return -1 if k1 < k2 else 1
diff --git a/src/zope/i18n/locales/inheritance.py b/src/zope/i18n/locales/inheritance.py
index 3201081..29c1fef 100644
--- a/src/zope/i18n/locales/inheritance.py
+++ b/src/zope/i18n/locales/inheritance.py
@@ -176,7 +176,7 @@ class InheritingDictionary(Inheritance, dict):
True
>>> locale.data.keys()
[1, 2, 3]
- >>> locale.data.items()
+ >>> list(locale.data.items())
[(1, 'eins'), (2, 'two'), (3, 'three')]
"""
@@ -190,7 +190,7 @@ class InheritingDictionary(Inheritance, dict):
def __getitem__(self, name):
"""See zope.i18n.interfaces.locales.ILocaleInheritance"""
- if not self.has_key(name):
+ if name not in self:
try:
selfUp = self.getInheritedSelf()
except NoParentException:
diff --git a/src/zope/i18n/locales/provider.py b/src/zope/i18n/locales/provider.py
index a39247e..391a130 100644
--- a/src/zope/i18n/locales/provider.py
+++ b/src/zope/i18n/locales/provider.py
@@ -72,6 +72,6 @@ class LocaleProvider(object):
country = country.upper()
if variant:
variant = variant.upper()
- if not self._locales.has_key((language, country, variant)):
+ if (language, country, variant) not in self._locales:
self.loadLocale(language, country, variant)
return self._locales[(language, country, variant)]
diff --git a/src/zope/i18n/locales/tests/test_docstrings.py b/src/zope/i18n/locales/tests/test_docstrings.py
index 3cfad9b..fa52078 100644
--- a/src/zope/i18n/locales/tests/test_docstrings.py
+++ b/src/zope/i18n/locales/tests/test_docstrings.py
@@ -18,6 +18,8 @@ from doctest import DocTestSuite
from zope.i18n.locales.inheritance import AttributeInheritance
from zope.i18n.locales.inheritance import NoParentException
+from zope.i18n.testing import unicode_checker
+
class LocaleInheritanceStub(AttributeInheritance):
def __init__(self, nextLocale=None):
@@ -31,9 +33,9 @@ class LocaleInheritanceStub(AttributeInheritance):
def test_suite():
return unittest.TestSuite((
- DocTestSuite('zope.i18n.locales'),
- DocTestSuite('zope.i18n.locales.inheritance'),
- DocTestSuite('zope.i18n.locales.xmlfactory'),
+ 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__':
diff --git a/src/zope/i18n/locales/tests/test_fallbackcollator.py b/src/zope/i18n/locales/tests/test_fallbackcollator.py
index 6bbffcc..7e10b50 100644
--- a/src/zope/i18n/locales/tests/test_fallbackcollator.py
+++ b/src/zope/i18n/locales/tests/test_fallbackcollator.py
@@ -15,9 +15,11 @@
import unittest
import doctest
+from zope.i18n.testing import unicode_checker
+
def test_suite():
return unittest.TestSuite((
- doctest.DocFileSuite('../fallbackcollator.txt'),
+ doctest.DocFileSuite('../fallbackcollator.txt', checker=unicode_checker),
))
if __name__ == '__main__':
diff --git a/src/zope/i18n/locales/tests/test_locales.py b/src/zope/i18n/locales/tests/test_locales.py
index 2668669..663c0e4 100644
--- a/src/zope/i18n/locales/tests/test_locales.py
+++ b/src/zope/i18n/locales/tests/test_locales.py
@@ -66,7 +66,8 @@ class TestLocaleProvider(TestILocaleProvider):
def test_loadLocale(self):
self.locales.loadLocale(None, None, None)
- self.assertEqual(self.locales._locales.keys(), [(None, None, None)])
+ self.assertEqual(list(self.locales._locales.keys()),
+ [(None, None, None)])
self.locales.loadLocale('en', None, None)
self.assert_(('en', None, None) in self.locales._locales.keys())
@@ -97,19 +98,19 @@ class TestLocaleAndProvider(TestCase):
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, 01, 02)),
+ self.assertEqual(formatter.format(datetime.date(2003, 1, 2)),
'Jan 2, 2003')
self.assertEqual(formatter.parse('Jan 2, 2003'),
- datetime.date(2003, 01, 02))
+ 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, 01, 02, 12, 30)),
+ 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, 01, 02, 12, 30))
+ datetime.datetime(2003, 1, 2, 12, 30))
def test_getNumberFormatter(self):
formatter = self.locale.numbers.getFormatter('decimal')
@@ -124,13 +125,13 @@ class TestGlobalLocaleProvider(TestCase):
def testLoading(self):
locales.loadLocale(None, None, None)
- self.assert_(locales._locales.has_key((None, None, None)))
+ self.assert_((None, None, None) in locales._locales)
locales.loadLocale('en', None, None)
- self.assert_(locales._locales.has_key(('en', None, None)))
+ self.assert_(('en', None, None) in locales._locales)
locales.loadLocale('en', 'US', None)
- self.assert_(locales._locales.has_key(('en', 'US', None)))
+ self.assert_(('en', 'US', None) in locales._locales)
locales.loadLocale('en', 'US', 'POSIX')
- self.assert_(locales._locales.has_key(('en', 'US', 'POSIX')))
+ self.assert_(('en', 'US', 'POSIX') in locales._locales)
def test_getLocale(self):
locale = locales.getLocale('en', 'GB')
diff --git a/src/zope/i18n/locales/xmlfactory.py b/src/zope/i18n/locales/xmlfactory.py
index 4d4712f..1276d7b 100644
--- a/src/zope/i18n/locales/xmlfactory.py
+++ b/src/zope/i18n/locales/xmlfactory.py
@@ -343,13 +343,13 @@ class LocaleFactory(object):
>>> ctx.defaultWidth
u'wide'
- >>> names = [ctx.months[u'wide'][type] for type in xrange(1,13)]
+ >>> names = [ctx.months[u'wide'][type] for type in range(1,13)]
>>> names[:7]
[u'Januar', u'Februar', u'Maerz', u'April', u'Mai', u'Juni', u'Juli']
>>> names[7:]
[u'August', u'September', u'Oktober', u'November', u'Dezember']
- >>> abbrs = [ctx.months[u'abbreviated'][type] for type in xrange(1,13)]
+ >>> abbrs = [ctx.months[u'abbreviated'][type] for type in range(1,13)]
>>> abbrs[:6]
[u'Jan', u'Feb', u'Mrz', u'Apr', u'Mai', u'Jun']
>>> abbrs[6:]
@@ -428,7 +428,7 @@ class LocaleFactory(object):
# Put the info together
calendar.months = InheritingDictionary()
- for type in xrange(1, 13):
+ for type in range(1, 13):
calendar.months[type] = (names.get(type, None),
abbrs.get(type, None))
@@ -482,13 +482,13 @@ class LocaleFactory(object):
>>> ctx.defaultWidth
u'wide'
- >>> names = [ctx.days[u'wide'][type] for type in xrange(1,8)]
+ >>> names = [ctx.days[u'wide'][type] for type in range(1,8)]
>>> names[:4]
[u'Montag', u'Dienstag', u'Mittwoch', u'Donnerstag']
>>> names[4:]
[u'Freitag', u'Samstag', u'Sonntag']
- >>> abbrs = [ctx.days[u'abbreviated'][type] for type in xrange(1,8)]
+ >>> abbrs = [ctx.days[u'abbreviated'][type] for type in range(1,8)]
>>> abbrs
[u'Mo', u'Di', u'Mi', u'Do', u'Fr', u'Sa', u'So']
@@ -496,14 +496,14 @@ class LocaleFactory(object):
abbreviations::
>>> names = [calendar.days.get(type, (None, None))[0]
- ... for type in xrange(1, 8)]
+ ... for type in range(1, 8)]
>>> names[:4]
[u'Montag', u'Dienstag', u'Mittwoch', u'Donnerstag']
>>> names[4:]
[u'Freitag', u'Samstag', u'Sonntag']
>>> abbrs = [calendar.days.get(type, (None, None))[1]
- ... for type in xrange(1, 8)]
+ ... for type in range(1, 8)]
>>> abbrs
[u'Mo', u'Di', u'Mi', u'Do', u'Fr', u'Sa', u'So']
"""
@@ -561,7 +561,7 @@ class LocaleFactory(object):
# Put the info together
calendar.days = InheritingDictionary()
- for type in xrange(1, 13):
+ for type in range(1, 13):
calendar.days[type] = (names.get(type, None),
abbrs.get(type, None))
diff --git a/src/zope/i18n/simpletranslationdomain.py b/src/zope/i18n/simpletranslationdomain.py
index 448da5e..1fb16f5 100644
--- a/src/zope/i18n/simpletranslationdomain.py
+++ b/src/zope/i18n/simpletranslationdomain.py
@@ -13,11 +13,16 @@
##############################################################################
"""This is a simple implementation of the ITranslationDomain interface.
"""
+import sys
+
from zope.interface import implementer
from zope.component import getUtility
from zope.i18n.interfaces import ITranslationDomain, INegotiator
from zope.i18n import interpolate
+PY3 = sys.version_info[0] == 3
+if PY3:
+ unicode = str
@implementer(ITranslationDomain)
class SimpleTranslationDomain(object):
diff --git a/src/zope/i18n/testing.py b/src/zope/i18n/testing.py
index ca09d08..293928b 100644
--- a/src/zope/i18n/testing.py
+++ b/src/zope/i18n/testing.py
@@ -13,15 +13,15 @@
##############################################################################
"""Unit test logic for setting up and tearing down basic infrastructure
"""
-import zope.component
-from zope.publisher.browser import BrowserLanguages
-from zope.publisher.http import HTTPCharsets
+import sys
+import re
-def setUp(test=None):
- zope.component.provideAdapter(HTTPCharsets)
- zope.component.provideAdapter(BrowserLanguages)
-
-class PlacelessSetup(object):
-
- def setUp(self):
- setUp()
+if sys.version_info[0] == 2:
+ import doctest
+ unicode_checker = doctest.OutputChecker()
+else:
+ from zope.testing import renormalizing
+ rules = [(re.compile("u('.*?')"), r"\1"),
+ (re.compile('u(".*?")'), r"\1"),
+ ]
+ unicode_checker = renormalizing.RENormalizing(rules)
diff --git a/src/zope/i18n/tests/test.py b/src/zope/i18n/tests/test.py
index 0333dc1..998bd6e 100644
--- a/src/zope/i18n/tests/test.py
+++ b/src/zope/i18n/tests/test.py
@@ -17,10 +17,12 @@ import unittest
import doctest
from zope.component.testing import setUp, tearDown
+from zope.i18n.testing import unicode_checker
def test_suite():
- return doctest.DocTestSuite("zope.i18n", setUp=setUp, tearDown=tearDown)
+ return doctest.DocTestSuite("zope.i18n", setUp=setUp, tearDown=tearDown,
+ checker=unicode_checker)
if __name__ == '__main__':
diff --git a/src/zope/i18n/tests/test_formats.py b/src/zope/i18n/tests/test_formats.py
index 114a771..0c260b4 100644
--- a/src/zope/i18n/tests/test_formats.py
+++ b/src/zope/i18n/tests/test_formats.py
@@ -171,13 +171,13 @@ class TestDateTimePatternParser(TestCase):
# Quote not closed
try:
parseDateTimePattern("HH' Uhr")
- except DateTimePatternParseError, err:
+ except DateTimePatternParseError as err:
self.assertEqual(
str(err), 'The quote starting at character 2 is not closed.')
# Test correct length of characters in datetime fields
try:
parseDateTimePattern("HHHHH")
- except DateTimePatternParseError, err:
+ except DateTimePatternParseError as err:
self.assert_(str(err).endswith('You have: 5'))
@@ -261,20 +261,20 @@ class TestDateTimeFormat(TestCase):
# German short
self.assertEqual(
self.format.parse('02.01.03 21:48', 'dd.MM.yy HH:mm'),
- datetime.datetime(2003, 01, 02, 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, 01, 02, 21, 48, 01))
+ 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'),
- datetime.datetime(2003, 01, 02, 21, 48, 01,
+ datetime.datetime(2003, 1, 2, 21, 48, 1,
tzinfo=pytz.timezone('Europe/Berlin')))
# German full
@@ -282,13 +282,13 @@ class TestDateTimeFormat(TestCase):
self.assertEqual(self.format.parse(
'Donnerstag, 2. Januar 2003 21:48 Uhr +100',
"EEEE, d. MMMM yyyy H:mm' Uhr 'z"),
- datetime.datetime(2003, 01, 02, 21, 48,
+ datetime.datetime(2003, 1, 2, 21, 48,
tzinfo=pytz.timezone('Europe/Berlin')))
def testParseAMPMDateTime(self):
self.assertEqual(
self.format.parse('02.01.03 09:48 nachm.', 'dd.MM.yy hh:mm a'),
- datetime.datetime(2003, 01, 02, 21, 48))
+ datetime.datetime(2003, 1, 2, 21, 48))
def testParseTimeZone(self):
dt = self.format.parse('09:48 -600', 'HH:mm z')
@@ -352,28 +352,28 @@ 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, 01, 01, 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, 01, 01, 12, 00, 00, 00))
+ 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, 01, 01, 00, 00, 00, 00))
+ datetime.datetime(2003, 1, 1, 00, 00, 00, 00))
def testFormatSimpleDateTime(self):
# German short
self.assertEqual(
- self.format.format(datetime.datetime(2003, 01, 02, 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')
- dt = datetime.datetime(2003, 01, 02, 21, 48, 01, tzinfo=tz)
+ dt = datetime.datetime(2003, 1, 2, 21, 48, 1, tzinfo=tz)
# German medium
self.assertEqual(
self.format.format(dt, 'dd.MM.yyyy HH:mm:ss'),
@@ -391,47 +391,47 @@ class TestDateTimeFormat(TestCase):
def testFormatAMPMDateTime(self):
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 21, 48),
+ 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, 01, day+5, 21, 48),
+ 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, 01, 02, 12, 00), 'z'),
+ datetime.datetime(2003, 1, 2, 12, 00), 'z'),
'+000')
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 12, 00), 'zz'),
+ datetime.datetime(2003, 1, 2, 12, 00), 'zz'),
'+00:00')
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 12, 00), 'zzz'),
+ datetime.datetime(2003, 1, 2, 12, 00), 'zzz'),
'UTC')
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 12, 00), 'zzzz'),
+ datetime.datetime(2003, 1, 2, 12, 00), 'zzzz'),
'UTC')
tz = pytz.timezone('US/Eastern')
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 12, tzinfo=tz), 'z'),
+ datetime.datetime(2003, 1, 2, 12, tzinfo=tz), 'z'),
'-500')
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 12, tzinfo=tz), 'zz'),
+ datetime.datetime(2003, 1, 2, 12, tzinfo=tz), 'zz'),
'-05:00')
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 12, tzinfo=tz), 'zzz'),
+ datetime.datetime(2003, 1, 2, 12, tzinfo=tz), 'zzz'),
'EST')
self.assertEqual(self.format.format(
- datetime.datetime(2003, 01, 02, 12, tzinfo=tz), 'zzzz'),
+ datetime.datetime(2003, 1, 2, 12, tzinfo=tz), 'zzzz'),
'US/Eastern')
def testFormatWeekDay(self):
- date = datetime.date(2003, 01, 02)
+ date = datetime.date(2003, 1, 2)
self.assertEqual(self.format.format(date, "E"),
'4')
self.assertEqual(self.format.format(date, "EE"),
@@ -455,7 +455,7 @@ class TestDateTimeFormat(TestCase):
'05')
def testFormatDayOfWeekInMonth(self):
- date = datetime.date(2003, 01, 02)
+ date = datetime.date(2003, 1, 2)
self.assertEqual(self.format.format(date, "F"),
'1')
self.assertEqual(self.format.format(date, "FF"),
@@ -526,11 +526,11 @@ class TestDateTimeFormat(TestCase):
def testFormatSimpleHourRepresentation(self):
self.assertEqual(
- self.format.format(datetime.datetime(2003, 01, 02, 23, 00),
+ 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, 01, 02, 02, 00),
+ 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(
diff --git a/src/zope/i18n/tests/test_itranslationdomain.py b/src/zope/i18n/tests/test_itranslationdomain.py
index 93d457e..9e1775c 100644
--- a/src/zope/i18n/tests/test_itranslationdomain.py
+++ b/src/zope/i18n/tests/test_itranslationdomain.py
@@ -13,6 +13,7 @@
##############################################################################
"""This is an 'abstract' test for the ITranslationDomain interface.
"""
+import sys
import unittest
from zope.interface.verify import verifyObject
from zope.interface import implementer
@@ -24,6 +25,9 @@ from zope.i18n.negotiator import negotiator
from zope.i18n.interfaces import INegotiator, IUserPreferredLanguages
from zope.i18n.interfaces import ITranslationDomain
+PY3 = sys.version_info[0] == 3
+if PY3:
+ unicode = str
@implementer(IUserPreferredLanguages)
class Environment(object):
diff --git a/src/zope/i18n/tests/test_testmessagecatalog.py b/src/zope/i18n/tests/test_testmessagecatalog.py
index e868310..62c2dd8 100644
--- a/src/zope/i18n/tests/test_testmessagecatalog.py
+++ b/src/zope/i18n/tests/test_testmessagecatalog.py
@@ -15,9 +15,11 @@
import unittest
import doctest
+from zope.i18n.testing import unicode_checker
+
def test_suite():
return unittest.TestSuite((
- doctest.DocFileSuite('../testmessagecatalog.txt'),
+ doctest.DocFileSuite('../testmessagecatalog.txt', checker=unicode_checker),
))
if __name__ == '__main__':
diff --git a/src/zope/i18n/tests/test_zcml.py b/src/zope/i18n/tests/test_zcml.py
index c32e087..fc9d90c 100644
--- a/src/zope/i18n/tests/test_zcml.py
+++ b/src/zope/i18n/tests/test_zcml.py
@@ -13,6 +13,7 @@
##############################################################################
"""Test the gts ZCML namespace directives.
"""
+import sys
import doctest
import os
import shutil
@@ -27,6 +28,10 @@ import zope.i18n.tests
from zope.i18n.interfaces import ITranslationDomain
from zope.i18n import config
+PY3 = sys.version_info[0] == 3
+if PY3:
+ unicode = str
+
template = """\
<configure
xmlns='http://namespaces.zope.org/zope'
diff --git a/src/zope/i18n/tests/testii18naware.py b/src/zope/i18n/tests/testii18naware.py
index 83e0864..cc37ef8 100644
--- a/src/zope/i18n/tests/testii18naware.py
+++ b/src/zope/i18n/tests/testii18naware.py
@@ -15,10 +15,6 @@
"""
import unittest
-def sorted(list):
- list.sort()
- return list
-
class TestII18nAware(unittest.TestCase):
def setUp(self):
diff --git a/src/zope/i18n/translationdomain.py b/src/zope/i18n/translationdomain.py
index dfc7f41..6629c9e 100644
--- a/src/zope/i18n/translationdomain.py
+++ b/src/zope/i18n/translationdomain.py
@@ -13,6 +13,8 @@
##############################################################################
"""Global Translation Service for providing I18n to file-based code.
"""
+import sys
+
import zope.component
from zope.i18nmessageid import Message
from zope.i18n import translate, interpolate
@@ -29,6 +31,9 @@ from zope.i18n.interfaces import ITranslationDomain, INegotiator
# message in a catalog is not translated, tough luck, you get the msgid.
LANGUAGE_FALLBACKS = ['en']
+PY3 = sys.version_info[0] == 3
+if PY3:
+ unicode = str
class TranslationDomain(SimpleTranslationDomain):
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..66fef8d
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,12 @@
+# content of: tox.ini , put in same dir as setup.py
+[tox]
+envlist = py26,py27,py33
+
+[testenv]
+deps=zope.testrunner
+ zope.testing
+ python-gettext
+ zope.configuration
+ zope.security
+
+commands=zope-testrunner --all --test-path=src -v