diff --git a/CHANGES.rst b/CHANGES.rst index 173b1bb..ff03a45 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -14,7 +14,8 @@ New features: Bug fixes: -- *add item here* +- Add Python 2 / 3 compatibility + [pbauer] 3.0.7 (2017-05-16) @@ -22,7 +23,7 @@ Bug fixes: Bug fixes: -- Add missing entries to requirements in setup.py. +- Add missing entries to requirements in setup.py. [dhavlik] diff --git a/bootstrap.py b/bootstrap.py deleted file mode 100644 index daeeef5..0000000 --- a/bootstrap.py +++ /dev/null @@ -1,127 +0,0 @@ -############################################################################## -# -# Copyright (c) 2006 Zope Foundation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Bootstrap a buildout-based project - -Simply run this script in a directory containing a buildout.cfg. -The script accepts buildout command-line options, so you can -use the -c option to specify an alternate configuration file. - -$Id$ -""" - -import os, shutil, sys, tempfile, urllib2 -from optparse import OptionParser - -tmpeggs = tempfile.mkdtemp() - -is_jython = sys.platform.startswith('java') - -# parsing arguments -parser = OptionParser( - 'This is a custom version of the zc.buildout %prog script. It is ' - 'intended to meet a temporary need if you encounter problems with ' - 'the zc.buildout 1.5 release.') -parser.add_option("-v", "--version", dest="version", default='1.4.4', - help='Use a specific zc.buildout version. *This ' - 'bootstrap script defaults to ' - '1.4.4, unlike usual buildpout bootstrap scripts.*') -parser.add_option("-d", "--distribute", - action="store_true", dest="distribute", default=False, - help="Use Disribute rather than Setuptools.") - -parser.add_option("-c", None, action="store", dest="config_file", - help=("Specify the path to the buildout configuration " - "file to be used.")) - -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 = '' - -USE_DISTRIBUTE = options.distribute -args = args + ['bootstrap'] - -to_reload = False -try: - import pkg_resources - 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) - - 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 - -ws = pkg_resources.working_set - -if USE_DISTRIBUTE: - requirement = 'distribute' -else: - requirement = 'setuptools' - -env = dict(os.environ, - PYTHONPATH= - ws.find(pkg_resources.Requirement.parse(requirement)).location - ) - -cmd = [quote(sys.executable), - '-c', - quote('from setuptools.command.easy_install import main; main()'), - '-mqNxd', - quote(tmpeggs)] - -if 'bootstrap-testing-find-links' in os.environ: - cmd.extend(['-f', os.environ['bootstrap-testing-find-links']]) - -cmd.append('zc.buildout' + VERSION) - -if is_jython: - import subprocess - exitcode = subprocess.Popen(cmd, env=env).wait() -else: # Windows prefers this, apparently; otherwise we would prefer subprocess - exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) -assert exitcode == 0 - -ws.add_entry(tmpeggs) -ws.require('zc.buildout' + VERSION) -import zc.buildout.buildout -zc.buildout.buildout.main(args) -shutil.rmtree(tmpeggs) diff --git a/buildout.cfg b/buildout.cfg deleted file mode 100644 index 85d04b9..0000000 --- a/buildout.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[buildout] -develop = . -parts = test - -[test] -recipe = zc.recipe.testrunner -defaults = ['-s', 'plone.i18n'] -eggs = - plone.i18n [test] diff --git a/plone/i18n/locales/countries.py b/plone/i18n/locales/countries.py index eda81b5..01f5075 100644 --- a/plone/i18n/locales/countries.py +++ b/plone/i18n/locales/countries.py @@ -3,6 +3,8 @@ from plone.i18n.locales.interfaces import ICountryAvailability from zope.interface import implementer +import six + @implementer(ICountryAvailability) class CountryAvailability(object): @@ -292,4 +294,4 @@ def getCountryListing(self): for code in _countrylist: value = _countrylist[code] if u'name' in value: - value[u'name'] = unicode(value[u'name'], 'utf-8') + value[u'name'] = six.text_type(value[u'name'], 'utf-8') diff --git a/plone/i18n/locales/languages.py b/plone/i18n/locales/languages.py index 279c8b3..bf797a8 100644 --- a/plone/i18n/locales/languages.py +++ b/plone/i18n/locales/languages.py @@ -1,10 +1,11 @@ # -*- coding: UTF-8 -*- - from plone.i18n.locales.interfaces import IContentLanguageAvailability from plone.i18n.locales.interfaces import ILanguageAvailability from plone.i18n.locales.interfaces import IMetadataLanguageAvailability from zope.interface import implementer +import six + @implementer(ILanguageAvailability) class LanguageAvailability(object): @@ -251,9 +252,9 @@ class MetadataLanguageAvailability(LanguageAvailability): for code in _languagelist: value = _languagelist[code] if u'name' in value: - value[u'name'] = unicode(value[u'name'], 'utf-8') + value[u'name'] = six.text_type(value[u'name'], 'utf-8') if u'native' in value: - value[u'native'] = unicode(value[u'native'], 'utf-8') + value[u'native'] = six.text_type(value[u'native'], 'utf-8') _combinedlanguagelist = { u'ar-ae' : {u'name' : 'Arabic (United Arab Emirates)', u'flag' : u'/++resource++country-flags/ae.gif'}, @@ -488,6 +489,6 @@ class MetadataLanguageAvailability(LanguageAvailability): for code in _combinedlanguagelist: value = _combinedlanguagelist[code] if u'name' in value: - value[u'name'] = unicode(value[u'name'], 'utf-8') + value[u'name'] = six.text_type(value[u'name'], 'utf-8') if u'native' in value: - value[u'native'] = unicode(value[u'native'], 'utf-8') + value[u'native'] = six.text_type(value[u'native'], 'utf-8') diff --git a/plone/i18n/normalizer/base.py b/plone/i18n/normalizer/base.py index 46f6096..7380ccb 100644 --- a/plone/i18n/normalizer/base.py +++ b/plone/i18n/normalizer/base.py @@ -2,6 +2,7 @@ from unicodedata import decomposition from unicodedata import normalize +import six import string @@ -51,7 +52,7 @@ def baseNormalize(text): >>> baseNormalize(u"\u5317\u4EB0") '53174eb0' """ - if not isinstance(text, basestring): + if not isinstance(text, six.string_types): # This most surely ends up in something the user does not expect # to see. But at least it does not break. return repr(text) diff --git a/plone/i18n/normalizer/tests/test_normalizer.py b/plone/i18n/normalizer/tests/test_normalizer.py index 764815a..4216196 100644 --- a/plone/i18n/normalizer/tests/test_normalizer.py +++ b/plone/i18n/normalizer/tests/test_normalizer.py @@ -9,9 +9,11 @@ from zope.component import queryUtility import doctest +import six import unittest + def testIDNormalizer(): """ >>> util = queryUtility(IIDNormalizer) @@ -30,7 +32,7 @@ def testIDNormalizer(): >>> util.normalize(u">>>here'!--s yet another!!!") 'here-s-yet-another' - >>> util.normalize(unicode("umläut.doc", 'utf-8')) + >>> util.normalize(six.text_type("umläut.doc", 'utf-8')) 'umlaut-doc' >>> from plone.i18n.normalizer import MAX_LENGTH @@ -53,7 +55,7 @@ def testIDNormalizer(): >>> len(util.normalize(testString)) <= MAX_LENGTH True - >>> util.normalize(unicode("rest `n` peace", 'utf-8')) + >>> util.normalize(six.text_type("rest `n` peace", 'utf-8')) 'rest-n-peace' >>> util.normalize(u"short-hello-version", max_length=10) @@ -81,13 +83,13 @@ def testLocaleAwareIDNormalizer(): >>> util.normalize(u'simpleandsafe', locale='de') 'simpleandsafe' - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de') 'text-with-umlaeut' Make sure we get the de normalizer as there's no special one for de-DE registered. - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de-DE') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de-DE') 'text-with-umlaeut' >>> util.normalize(u'simpleandsafe', locale='pt-BR') @@ -105,7 +107,7 @@ def testLocaleAwareIDNormalizer(): Make sure we also handle POSIX-format locale identifiers, for backwards-compatibility with an earlier version of plone.i18n. - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de_DE') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de_DE') 'text-with-umlaeut' """ @@ -135,13 +137,13 @@ def testFileNameNormalizer(): >>> util.normalize("pseudo_filename,pot,#1.doc") 'pseudo_filename-pot-#1.doc' - >>> util.normalize(unicode("umläut.doc", 'utf-8')) + >>> util.normalize(six.text_type("umläut.doc", 'utf-8')) 'umlaut.doc' >>> len(util.normalize(u'aa' * 2000)) 1023 - >>> util.normalize(unicode("rest `n` peace", 'utf-8')) + >>> util.normalize(six.text_type("rest `n` peace", 'utf-8')) 'rest -n- peace' >>> util.normalize(u"short-hello-version", max_length=10) @@ -164,13 +166,13 @@ def testLocaleAwareFileNameNormalizer(): >>> util.normalize(u'simpleandsafe', locale='de') 'simpleandsafe' - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de') 'text with umlaeut' Make sure we get the de normalizer as there's no special one for de-DE registered. - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de-DE') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de-DE') 'text with umlaeut' >>> util.normalize(u'simpleandsafe', locale='pt-BR') @@ -188,7 +190,7 @@ def testLocaleAwareFileNameNormalizer(): Make sure we also handle POSIX-format locale identifiers, for backwards-compatibility with an earlier version of plone.i18n. - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de_DE') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de_DE') 'text with umlaeut' """ @@ -215,7 +217,7 @@ def testURLNormalizer(): >>> util.normalize(u"Doe, Joe") 'doe-joe' - >>> util.normalize(unicode("umläut.doc", 'utf-8')) + >>> util.normalize(six.text_type("umläut.doc", 'utf-8')) 'umlaut.doc' >>> util.normalize('quote "this"!') @@ -230,7 +232,7 @@ def testURLNormalizer(): >>> util.normalize("I'm a big file.TXT") 'im-a-big-file.txt' - >>> util.normalize(unicode("rest `n` peace", 'utf-8')) + >>> util.normalize(six.text_type("rest `n` peace", 'utf-8')) 'rest-n-peace' >>> len(util.normalize(u'aa' * 2000)) @@ -255,13 +257,13 @@ def testLocaleAwareURLNormalizer(): >>> util.normalize(u'simpleandsafe', locale='de') 'simpleandsafe' - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de') 'text-with-umlaeut' Make sure we get the de normalizer as there's no special one for de-DE registered. - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de-DE') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de-DE') 'text-with-umlaeut' >>> util.normalize(u'simpleandsafe', locale='pt-BR') @@ -276,7 +278,7 @@ def testLocaleAwareURLNormalizer(): Make sure we also handle POSIX-format locale identifiers, for backwards-compatibility with an earlier version of plone.i18n. - >>> util.normalize(unicode('text with umläut', 'utf-8'), locale='de_DE') + >>> util.normalize(six.text_type('text with umläut', 'utf-8'), locale='de_DE') 'text-with-umlaeut' """ diff --git a/setup.cfg b/setup.cfg index 41baae6..1c775ea 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,8 +4,6 @@ ignore = .coveragerc .editorconfig .gitattributes - bootstrap.py - buildout.cfg [isort] # for details see diff --git a/setup.py b/setup.py index 04e1c92..206f08e 100644 --- a/setup.py +++ b/setup.py @@ -32,6 +32,7 @@ 'Products.CMFCore', 'Products.CMFPlone', 'setuptools', + 'six', 'Unidecode', 'zope.component', 'zope.i18n',