From 7513ce1562a34f83d751199ecec8d680656eb5c0 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 14 Feb 2018 10:51:47 -0800 Subject: [PATCH 01/15] Move .tox directory out of homedir Stop writing directly to a users homedir, so we don't leave random files lying around if the user deletes the repo. Instead use the default .tox location. --- .gitignore | 1 + tox.ini | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5ed36ad..ca6bfe9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ pip-log.txt .DS_Store *.egg-info +.tox/ diff --git a/tox.ini b/tox.ini index 342cc93..e937ec5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,5 @@ [tox] envlist = py26-1.4, py26-1.5, py26-1.6, py27-1.4, py27-1.5, py27-1.6 -toxworkdir = {homedir}/.tox-tower [testenv] commands = From 34d6e9dd3d9546147f26c29a95ad9ce3c1e87181 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 14 Feb 2018 11:26:31 -0800 Subject: [PATCH 02/15] Fix package versions to pass tests Newer versions of jingo and django-nose no longer work with older versions of Django, so pin to get tests passing again. --- tox.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index e937ec5..c0eddac 100644 --- a/tox.ini +++ b/tox.ini @@ -4,11 +4,11 @@ envlist = py26-1.4, py26-1.5, py26-1.6, py27-1.4, py27-1.5, py27-1.6 [testenv] commands = python run_tests.py -deps = -egit+https://github.com/jbalogh/jingo.git#egg=jingo +deps = -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo babel==1.3 jinja2 translate-toolkit - django-nose + django-nose==1.4.3 mock [testenv:py26-1.4] From f5fffa71bb60641e360d2af39c18c5c649dd06e8 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 14 Feb 2018 12:20:12 -0800 Subject: [PATCH 03/15] Update travis to use test matrix Based on https://docs.travis-ci.com/user/languages/python/#Using-Tox-as-the-Build-Script --- .travis.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 35748bf..611eaee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,14 @@ language: python -python: 2.6 -env: - - TOX_ENV=py26-1.4 - - TOX_ENV=py26-1.5 - - TOX_ENV=py26-1.6 - - TOX_ENV=py27-1.4 - - TOX_ENV=py27-1.5 - - TOX_ENV=py27-1.6 +matrix: + include: + - python: 2.6 + env: + - TOX_ENV=py26-1.4 + - TOX_ENV=py26-1.5 + - TOX_ENV=py26-1.6 + - python: 2.7 + env: TOXENV=py27-1.4,py27-1.5,py27-1.6 install: - pip install tox script: - - tox -e $TOX_ENV + - tox From aa0190e32d01b1debf5dc49476614bc0205a036f Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 14 Feb 2018 12:25:37 -0800 Subject: [PATCH 04/15] Drop python2.6 support Python2.6 is unsupported by all major distros. And Django stopped supporting it in Django 1.6. --- .travis.yml | 5 ----- README.rst | 2 +- setup.py | 1 - tox.ini | 20 +------------------- 4 files changed, 2 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 611eaee..3e58747 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,6 @@ language: python matrix: include: - - python: 2.6 - env: - - TOX_ENV=py26-1.4 - - TOX_ENV=py26-1.5 - - TOX_ENV=py26-1.6 - python: 2.7 env: TOXENV=py27-1.4,py27-1.5,py27-1.6 install: diff --git a/README.rst b/README.rst index 8177d16..74fdb7c 100644 --- a/README.rst +++ b/README.rst @@ -11,7 +11,7 @@ and the Babel library. * Author: Wil Clouser and contributors_ * Licence: BSD -* Compatibility: Python 2.6 and 2.7, Django 1.4, 1.5 and 1.6 +* Compatibility: Python 2.7, Django 1.4, 1.5 and 1.6 * Requirements: django, babel, jinja2, jingo and translate-toolkit * Project URL: https://github.com/clouserw/tower * Documentation: http://tower.readthedocs.org/en/latest/ diff --git a/setup.py b/setup.py index 2d939e6..f3d4667 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,6 @@ 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Topic :: Software Development :: Libraries :: Python Modules', ] diff --git a/tox.ini b/tox.ini index c0eddac..00e2f38 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py26-1.4, py26-1.5, py26-1.6, py27-1.4, py27-1.5, py27-1.6 +envlist = py27-1.4, py27-1.5, py27-1.6 [testenv] commands = @@ -11,24 +11,6 @@ deps = -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo django-nose==1.4.3 mock -[testenv:py26-1.4] -basepython = python2.6 -deps = - Django==1.4.10 - {[testenv]deps} - -[testenv:py26-1.5] -basepython = python2.6 -deps = - Django==1.5.5 - {[testenv]deps} - -[testenv:py26-1.6] -basepython = python2.6 -deps = - Django==1.6 - {[testenv]deps} - [testenv:py27-1.4] basepython = python2.7 deps = From 7be3131beb74c90415959e9b6a2257613aa4f0db Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 14 Feb 2018 13:00:33 -0800 Subject: [PATCH 05/15] Drop Travis test for py27-1.4 In the travis env getting the following error: ... File "/home/travis/build/clouserw/tower/tower/tests/test_l10n.py", line 35, in setup tower.activate('xx') File "/home/travis/build/clouserw/tower/tower/__init__.py", line 104, in activate django_trans._active.value = _activate(locale) File "/home/travis/build/clouserw/tower/tower/__init__.py", line 130, in _activate t.set_language(locale) AttributeError: NullTranslations instance has no attribute 'set_language' This appears to related to https://code.djangoproject.com/ticket/18192 --- .travis.yml | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3e58747..1be7560 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: python matrix: include: - python: 2.7 - env: TOXENV=py27-1.4,py27-1.5,py27-1.6 + env: TOXENV=py27-1.5,py27-1.6 install: - pip install tox script: diff --git a/tox.ini b/tox.ini index 00e2f38..7c71dc5 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ deps = -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo [testenv:py27-1.4] basepython = python2.7 deps = - Django==1.4.10 + Django==1.4.20 {[testenv]deps} From 5ad3bd852e85ab4edc1d8dde5a6810f5934a03fc Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 14 Feb 2018 14:57:04 -0800 Subject: [PATCH 06/15] Test against Django 1.7 --- .travis.yml | 2 +- examples/tower-project/settings.py | 9 +++++++++ run_tests.py | 6 ++++++ tox.ini | 8 +++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1be7560..483c98b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: python matrix: include: - python: 2.7 - env: TOXENV=py27-1.5,py27-1.6 + env: TOXENV=py27-1.5,py27-1.6,py27-1.7 install: - pip install tox script: diff --git a/examples/tower-project/settings.py b/examples/tower-project/settings.py index 744dced..d7b4af3 100644 --- a/examples/tower-project/settings.py +++ b/examples/tower-project/settings.py @@ -31,3 +31,12 @@ def JINJA_CONFIG(): } SECRET_KEY = 'useless not secret key used for tests' + +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) diff --git a/run_tests.py b/run_tests.py index 74b0fae..26649b1 100755 --- a/run_tests.py +++ b/run_tests.py @@ -18,4 +18,10 @@ from django.core.management import call_command # Run the equivalent of "django-admin.py test" +try: + from django import setup + setup() +except ImportError: + # Django 1.6 and below does not require setup() + pass call_command('test') diff --git a/tox.ini b/tox.ini index 7c71dc5..75d05d8 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27-1.4, py27-1.5, py27-1.6 +envlist = py27-1.4, py27-1.5, py27-1.6, py27-1.7 [testenv] commands = @@ -29,3 +29,9 @@ basepython = python2.7 deps = Django==1.6 {[testenv]deps} + +[testenv:py27-1.7] +basepython = python2.7 +deps = + Django==1.7 + {[testenv]deps} From c8407c76d45cd74c66fda37593daa74fff366d8e Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Thu, 15 Feb 2018 10:20:12 -0800 Subject: [PATCH 07/15] Add Django 1.8 support * Use Jingo 0.8 for Django 1.8 * As of https://github.com/django/django/commit/a5f6cbce07b5f3ab48d931e3fd1883c757fb9b45 DjangoTranslation object won't work when passed into gettext.translation. So use default gettext.GNUTranslations just like Django --- .travis.yml | 2 +- tower/__init__.py | 15 +++++++++++---- tower/tests/test_l10n.py | 19 +++++++++++++++---- tox.ini | 18 +++++++++++++++--- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 483c98b..745e540 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: python matrix: include: - python: 2.7 - env: TOXENV=py27-1.5,py27-1.6,py27-1.7 + env: TOXENV=py27-1.5,py27-1.6,py27-1.7,py27-1.8 install: - pip install tox script: diff --git a/tower/__init__.py b/tower/__init__.py index 95245b6..e97af46 100644 --- a/tower/__init__.py +++ b/tower/__init__.py @@ -87,7 +87,11 @@ class Translation(object): ungettext = staticmethod(ungettext) import jingo - jingo.env.install_gettext_translations(Translation) + try: + jingo.env.install_gettext_translations(Translation) + except Exception: + # jingo 0.8 requires get_env() instead. + jingo.get_env().install_gettext_translations(Translation) def activate(locale): @@ -116,6 +120,7 @@ def _activate(locale): # Django caches the translation objects here t = django_trans._translations.get(locale, None) + if t is not None: return t @@ -127,7 +132,9 @@ def _activate(locale): # our foreign catalog into en-US. Since Django stuck the en-US catalog # into its cache for this locale, we have to update that too. t = copy.deepcopy(django_trans.translation(locale)) - t.set_language(locale) + if hasattr(t, 'set_language'): + # not required for django 1.8+ + t.set_language(locale) try: # When trying to load css, js, and images through the Django server # gettext() throws an exception saying it can't find the .mo files. I @@ -144,8 +151,8 @@ def _activate(locale): # If you've got extra .mo files to load, this is the place. path = import_module(settings_module).path domain = getattr(settings, 'TEXT_DOMAIN', 'messages') - bonus = gettext.translation(domain, path('locale'), [locale], - django_trans.DjangoTranslation) + bonus = gettext.translation(domain=domain, localedir=path('locale'), languages=[locale], + codeset='utf-8') t.merge(bonus) # Overwrite t (defaults to en-US) with our real locale's plural form diff --git a/tower/tests/test_l10n.py b/tower/tests/test_l10n.py index 9d2c9b0..d6ce56e 100644 --- a/tower/tests/test_l10n.py +++ b/tower/tests/test_l10n.py @@ -43,10 +43,19 @@ def teardown(): tower.deactivate_all() +def get_jingo_env(): + try: + return jingo.env + except Exception: + # jingo 0.8 requires get_env() instead. + return jingo.get_env() + def test_install_jinja_translations(): - jingo.env.install_null_translations() + env = get_jingo_env() + + env.install_null_translations() tower.activate('xx') - eq_(jingo.env.globals['gettext'], _) + eq_(env.globals['gettext'], _) @patch.object(tower, 'INSTALL_JINJA_TRANSLATIONS', False) @@ -55,9 +64,11 @@ def test_no_install_jinja_translations(): Setting `TOWER_INSTALL_JINJA_TRANSLATIONS` to False should skip setting the gettext and ngettext functions in the Jinja2 environment. """ - jingo.env.install_null_translations() + env = get_jingo_env() + + env.install_null_translations() tower.activate('xx') - ok_(jingo.env.globals['gettext'] != _) + ok_(env.globals['gettext'] != _) @with_setup(setup, teardown) diff --git a/tox.ini b/tox.ini index 75d05d8..753aaca 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,10 @@ [tox] -envlist = py27-1.4, py27-1.5, py27-1.6, py27-1.7 +envlist = py27-1.4, py27-1.5, py27-1.6, py27-1.7, py27-1.8 [testenv] commands = python run_tests.py -deps = -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo +deps = babel==1.3 jinja2 translate-toolkit @@ -15,6 +15,8 @@ deps = -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo basepython = python2.7 deps = Django==1.4.20 + -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo + babel==1.3 {[testenv]deps} @@ -22,16 +24,26 @@ deps = basepython = python2.7 deps = Django==1.5.5 + -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo {[testenv]deps} [testenv:py27-1.6] basepython = python2.7 deps = Django==1.6 + -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo {[testenv]deps} [testenv:py27-1.7] basepython = python2.7 deps = - Django==1.7 + Django==1.7.11 + -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo + {[testenv]deps} + +[testenv:py27-1.8] +basepython = python2.7 +deps = + Django==1.8 + -egit+https://github.com/jbalogh/jingo.git@v0.8.2#egg=jingo {[testenv]deps} From 74126052927f3bb6a4b8fd154db6239207cf0f94 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 28 Feb 2018 14:57:57 -0800 Subject: [PATCH 08/15] Futurize stage 1 futurize -1 -w -n tower/ First step in adding python3 support. --- tower/management/commands/amalgamate.py | 15 ++++++++------- tower/management/commands/extract.py | 7 ++++--- tower/management/commands/merge.py | 13 +++++++------ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/tower/management/commands/amalgamate.py b/tower/management/commands/amalgamate.py index c430bb5..0d29266 100644 --- a/tower/management/commands/amalgamate.py +++ b/tower/management/commands/amalgamate.py @@ -1,3 +1,4 @@ +from __future__ import print_function import os import sys from subprocess import Popen @@ -58,10 +59,10 @@ def handle(self, *args, **options): 'messages.po') if not os.path.isfile(r_messages): - print " Can't find (%s). Skipping..." % (r_messages) + print(" Can't find (%s). Skipping..." % (r_messages)) continue - print "Mushing python strings into messages.po for %s" % (locale) + print("Mushing python strings into messages.po for %s" % (locale)) # Step 3: Merge our new combined .pot with the .po file if locale == "en_US": @@ -90,7 +91,7 @@ def handle(self, *args, **options): # commands in the middle of Step 3. for domain in standalone_domains: - print "Merging %s strings to each locale..." % domain + print("Merging %s strings to each locale..." % domain) z_domain_keys = os.path.join(locale_dir, 'z-%s.pot' % domain) if not os.path.isfile(z_domain_keys): sys.exit("Can't find z-%s.pot" % domain) @@ -104,11 +105,11 @@ def handle(self, *args, **options): 'z-%s.po' % domain) if not os.path.isfile(z_domain_messages): - print " Can't find (%s). Creating..." % (z_domain_messages) + print(" Can't find (%s). Creating..." % (z_domain_messages)) t = open(z_domain_messages, 'w') t.close() - print "Merging z-%s.po for %s" % (domain, locale) + print("Merging z-%s.po for %s" % (domain, locale)) z_domain_keys_file = open(z_domain_keys) @@ -133,6 +134,6 @@ def handle(self, *args, **options): p4.communicate() mergeme.close() - print "Domain %s finished" % domain + print("Domain %s finished" % domain) - print "All finished" + print("All finished") diff --git a/tower/management/commands/extract.py b/tower/management/commands/extract.py index be2f586..837c5fb 100644 --- a/tower/management/commands/extract.py +++ b/tower/management/commands/extract.py @@ -1,3 +1,4 @@ +from __future__ import print_function import os import tempfile from optparse import make_option @@ -129,11 +130,11 @@ def handle(self, *args, **options): def callback(filename, method, options): if method != 'ignore': - print " %s" % filename + print(" %s" % filename) for domain in domains: - print "Extracting all strings in domain %s..." % (domain) + print("Extracting all strings in domain %s..." % (domain)) methods = settings.DOMAIN_METHODS[domain] extracted = extract_from_dir(root, @@ -179,4 +180,4 @@ def callback(filename, method, options): for i in [x for x in domains if x not in standalone_domains]: os.remove(os.path.join(outputdir, '%s.pot' % i)) - print 'done' + print('done') diff --git a/tower/management/commands/merge.py b/tower/management/commands/merge.py index 6d6a52b..4fd063f 100644 --- a/tower/management/commands/merge.py +++ b/tower/management/commands/merge.py @@ -1,3 +1,4 @@ +from __future__ import print_function import os import sys from optparse import make_option @@ -50,7 +51,7 @@ def handle(self, *args, **options): for domain in domains: - print "Merging %s strings to each locale..." % domain + print("Merging %s strings to each locale..." % domain) domain_pot = os.path.join(locale_dir, 'templates', 'LC_MESSAGES', '%s.pot' % domain) if not os.path.isfile(domain_pot): @@ -69,7 +70,7 @@ def handle(self, *args, **options): '%s.po' % domain) if not os.path.isfile(domain_po): - print " Can't find (%s). Creating..." % (domain_po) + print(" Can't find (%s). Creating..." % (domain_po)) if not call(["which", "msginit"], stdout=PIPE) == 0: raise Exception("You do not have gettext installed.") p1 = Popen(["msginit", @@ -80,7 +81,7 @@ def handle(self, *args, **options): "--width=200",]) p1.communicate() - print "Merging %s.po for %s" % (domain, locale) + print("Merging %s.po for %s" % (domain, locale)) domain_pot_file = open(domain_pot) @@ -100,13 +101,13 @@ def handle(self, *args, **options): domain_po, "-"] if os.path.isfile(compendium): - print "(using a compendium)" + print("(using a compendium)") command.insert(1, '--compendium=%s' % compendium) p3 = Popen(command, stdin=mergeme) p3.communicate() mergeme.close() - print "Domain %s finished" % domain + print("Domain %s finished" % domain) - print "All finished" + print("All finished") Command.help = Command.__doc__ From 84da6dd1e9cc69bd8d67e2b8b8109c527fcdd672 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 28 Feb 2018 15:04:50 -0800 Subject: [PATCH 09/15] futurize stage 2 Add future as a dependency futurize -2 -w -n tower/ --- requirements.txt | 1 + tower/__init__.py | 6 ++++-- tower/management/commands/extract.py | 2 +- tower/tests/test_l10n.py | 25 ++++++++++++++----------- tox.ini | 1 + 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/requirements.txt b/requirements.txt index 41dabba..e2f02a1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ babel==1.3 jinja2 translate-toolkit -e git://github.com/jbalogh/jingo.git#egg=jingo +future # Requirements for running the tests django-nose==1.1 diff --git a/tower/__init__.py b/tower/__init__.py index e97af46..63ff442 100644 --- a/tower/__init__.py +++ b/tower/__init__.py @@ -1,3 +1,5 @@ +from past.builtins import basestring +from builtins import object import copy import gettext import re @@ -52,8 +54,8 @@ def ungettext(singular, plural, number, context=None): return plural_stripped return ret -ugettext_lazy = lazy(ugettext, unicode) -ungettext_lazy = lazy(ungettext, unicode) +ugettext_lazy = lazy(ugettext, str) +ungettext_lazy = lazy(ungettext, str) def add_context(context, message): diff --git a/tower/management/commands/extract.py b/tower/management/commands/extract.py index 837c5fb..54ec9b5 100644 --- a/tower/management/commands/extract.py +++ b/tower/management/commands/extract.py @@ -122,7 +122,7 @@ def handle(self, *args, **options): os.makedirs(outputdir) if domains == "all": - domains = settings.DOMAIN_METHODS.keys() + domains = list(settings.DOMAIN_METHODS.keys()) else: domains = [domains] diff --git a/tower/tests/test_l10n.py b/tower/tests/test_l10n.py index d6ce56e..4ec3473 100644 --- a/tower/tests/test_l10n.py +++ b/tower/tests/test_l10n.py @@ -1,4 +1,7 @@ -from cStringIO import StringIO +from future import standard_library +standard_library.install_aliases() +from builtins import str +from io import StringIO import django from django.utils import translation @@ -127,16 +130,16 @@ def test_ungettext_not_found(): @with_setup(setup, teardown) def test_ugettext_lazy(): - eq_(unicode(_lazy_strings['nocontext']), 'you ran a test!') - eq_(unicode(_lazy_strings['context']), 'What time is it? (context=1)') + eq_(str(_lazy_strings['nocontext']), 'you ran a test!') + eq_(str(_lazy_strings['context']), 'What time is it? (context=1)') @with_setup(setup, teardown) def test_ungettext_lazy(): - eq_(unicode(n_lazy_strings['s_nocontext']), 'you found a light!') - eq_(unicode(n_lazy_strings['p_nocontext']), 'you found a pile of lights!') - eq_(unicode(n_lazy_strings['s_context']), '%d poodle (context=1)') - eq_(unicode(n_lazy_strings['p_context']), '%d poodles (context=1)') + eq_(str(n_lazy_strings['s_nocontext']), 'you found a light!') + eq_(str(n_lazy_strings['p_nocontext']), 'you found a pile of lights!') + eq_(str(n_lazy_strings['s_context']), '%d poodle (context=1)') + eq_(str(n_lazy_strings['p_context']), '%d poodles (context=1)') def test_add_context(): @@ -279,7 +282,7 @@ def test_extract_tower_python(): method=method) # god help you if these are ever unequal - eq_(TEST_PO_OUTPUT, unicode(create_pofile_from_babel(output))) + eq_(TEST_PO_OUTPUT, str(create_pofile_from_babel(output))) def test_extract_tower_template(): @@ -289,7 +292,7 @@ def test_extract_tower_template(): method=method) # god help you if these are ever unequal - eq_(TEST_TEMPLATE_OUTPUT, unicode(create_pofile_from_babel(output))) + eq_(TEST_TEMPLATE_OUTPUT, str(create_pofile_from_babel(output))) def test_extract_tower_python_backwards_compatible(): @@ -299,7 +302,7 @@ def test_extract_tower_python_backwards_compatible(): method=method) # god help you if these are ever unequal - eq_(TEST_PO_OUTPUT, unicode(create_pofile_from_babel(output))) + eq_(TEST_PO_OUTPUT, str(create_pofile_from_babel(output))) def test_extract_tower_template_backwards_compatible(): @@ -309,7 +312,7 @@ def test_extract_tower_template_backwards_compatible(): method=method) # god help you if these are ever unequal - eq_(TEST_TEMPLATE_OUTPUT, unicode(create_pofile_from_babel(output))) + eq_(TEST_TEMPLATE_OUTPUT, str(create_pofile_from_babel(output))) diff --git a/tox.ini b/tox.ini index 753aaca..e55ae02 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,7 @@ deps = translate-toolkit django-nose==1.4.3 mock + future [testenv:py27-1.4] basepython = python2.7 From db5237b73cc1e80efffb95578b50a0c46c2974b8 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 28 Feb 2018 16:39:54 -0800 Subject: [PATCH 10/15] Fix tests to work with Python3 str(pofile) wouldn't return the contents. So instead write to BytesIO and read from there. Add a tox endpoint for py36-1.8, Django 1-7 and below doesn't support py35+ --- tower/management/commands/extract.py | 6 +++-- tower/tests/test_l10n.py | 38 ++++++++++++++++++---------- tox.ini | 9 ++++++- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/tower/management/commands/extract.py b/tower/management/commands/extract.py index 54ec9b5..c72bf82 100644 --- a/tower/management/commands/extract.py +++ b/tower/management/commands/extract.py @@ -1,4 +1,6 @@ from __future__ import print_function +from io import StringIO + import os import tempfile from optparse import make_option @@ -73,9 +75,9 @@ def create_pofile_from_babel(extracted): if settings.TOWER_ADD_HEADERS: catalog = po.pofile() else: - catalog = po.pofile(inputfile="") + catalog = po.pofile(inputfile=StringIO(u"")) except AttributeError: - catalog = po.pofile(inputfile="") + catalog = po.pofile(inputfile=StringIO(u"")) for extracted_unit in extracted: # Babel 1.3 has an additional value: context. diff --git a/tower/tests/test_l10n.py b/tower/tests/test_l10n.py index 4ec3473..4b09bbf 100644 --- a/tower/tests/test_l10n.py +++ b/tower/tests/test_l10n.py @@ -1,7 +1,7 @@ from future import standard_library standard_library.install_aliases() from builtins import str -from io import StringIO +from io import StringIO, BytesIO import django from django.utils import translation @@ -276,47 +276,59 @@ def test_template_gettext_functions(): def test_extract_tower_python(): - fileobj = StringIO(TEST_PO_INPUT) + fileobj = BytesIO(TEST_PO_INPUT) method = 'tower.extract_tower_python' output = fake_extract_from_dir(filename="filename", fileobj=fileobj, method=method) # god help you if these are ever unequal - eq_(TEST_PO_OUTPUT, str(create_pofile_from_babel(output))) + out = BytesIO() + create_pofile_from_babel(output).serialize(out) + out.seek(0) + eq_(TEST_PO_OUTPUT, out.read()) def test_extract_tower_template(): - fileobj = StringIO(TEST_TEMPLATE_INPUT) + fileobj = BytesIO(TEST_TEMPLATE_INPUT) method = 'tower.extract_tower_template' output = fake_extract_from_dir(filename="filename", fileobj=fileobj, method=method) # god help you if these are ever unequal - eq_(TEST_TEMPLATE_OUTPUT, str(create_pofile_from_babel(output))) + out = BytesIO() + create_pofile_from_babel(output).serialize(out) + out.seek(0) + eq_(TEST_TEMPLATE_OUTPUT, out.read()) def test_extract_tower_python_backwards_compatible(): - fileobj = StringIO(TEST_PO_INPUT) + fileobj = BytesIO(TEST_PO_INPUT) method = 'tower.management.commands.extract.extract_tower_python' output = fake_extract_from_dir(filename="filename", fileobj=fileobj, method=method) # god help you if these are ever unequal - eq_(TEST_PO_OUTPUT, str(create_pofile_from_babel(output))) + out = BytesIO() + create_pofile_from_babel(output).serialize(out) + out.seek(0) + eq_(TEST_PO_OUTPUT, out.read()) def test_extract_tower_template_backwards_compatible(): - fileobj = StringIO(TEST_TEMPLATE_INPUT) + fileobj = BytesIO(TEST_TEMPLATE_INPUT) method = 'tower.management.commands.extract.extract_tower_template' output = fake_extract_from_dir(filename="filename", fileobj=fileobj, method=method) # god help you if these are ever unequal - eq_(TEST_TEMPLATE_OUTPUT, str(create_pofile_from_babel(output))) + out = BytesIO() + create_pofile_from_babel(output).serialize(out) + out.seek(0) + eq_(TEST_TEMPLATE_OUTPUT, out.read()) -TEST_PO_INPUT = """ +TEST_PO_INPUT = b""" # Make sure multiple contexts stay separate _('fligtar') _('fligtar', 'atwork') @@ -342,7 +354,7 @@ def test_extract_tower_template_backwards_compatible(): _lazy('a lazy string') """ -TEST_PO_OUTPUT = """\ +TEST_PO_OUTPUT = b"""\ #: filename:3 msgid "fligtar" msgstr "" @@ -385,7 +397,7 @@ def test_extract_tower_template_backwards_compatible(): msgstr "" """ -TEST_TEMPLATE_INPUT = """ +TEST_TEMPLATE_INPUT = b""" {{ _('sunshine') }} {{ _('sunshine', 'nothere') }} {{ _('sunshine', 'outside') }} @@ -412,7 +424,7 @@ def test_extract_tower_template_backwards_compatible(): {% endtrans %} """ -TEST_TEMPLATE_OUTPUT = """\ +TEST_TEMPLATE_OUTPUT = b"""\ #: filename:2 msgid "sunshine" msgstr "" diff --git a/tox.ini b/tox.ini index e55ae02..ae416b5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27-1.4, py27-1.5, py27-1.6, py27-1.7, py27-1.8 +envlist = py27-1.4, py27-1.5, py27-1.6, py27-1.7, py36-1.8 [testenv] commands = @@ -48,3 +48,10 @@ deps = Django==1.8 -egit+https://github.com/jbalogh/jingo.git@v0.8.2#egg=jingo {[testenv]deps} + +[testenv:py36-1.8] +basepython = python3.6 +deps = + Django==1.8 + -egit+https://github.com/jbalogh/jingo.git@v0.8.2#egg=jingo + {[testenv]deps} From eab201c9c6e3f44f1f0f5a8da116adef68b61cc4 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 28 Feb 2018 16:44:34 -0800 Subject: [PATCH 11/15] Add python3 classifier So https://github.com/brettcannon/caniusepython3 can be used to programmatically detect this works with python 3. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index f3d4667..439db29 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,7 @@ 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.6', 'Topic :: Software Development :: Libraries :: Python Modules', ] ) From 7a521adb3042dc556f56503ed738ee48e0154eca Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Wed, 28 Feb 2018 16:46:19 -0800 Subject: [PATCH 12/15] Update README and travis testing For python3 --- .travis.yml | 2 ++ README.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 745e540..b9b9370 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,8 @@ matrix: include: - python: 2.7 env: TOXENV=py27-1.5,py27-1.6,py27-1.7,py27-1.8 + - python: 3.6 + env: TOXENV=py36-1.8 install: - pip install tox script: diff --git a/README.rst b/README.rst index 74fdb7c..ffdda36 100644 --- a/README.rst +++ b/README.rst @@ -11,7 +11,7 @@ and the Babel library. * Author: Wil Clouser and contributors_ * Licence: BSD -* Compatibility: Python 2.7, Django 1.4, 1.5 and 1.6 +* Compatibility: Python 2.7 and 3.6, Django 1.4, 1.5 and 1.6, 1.8, 1.8 * Requirements: django, babel, jinja2, jingo and translate-toolkit * Project URL: https://github.com/clouserw/tower * Documentation: http://tower.readthedocs.org/en/latest/ From bc9f1c6b22acaed94d14d09f9fb0d83b3076324f Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 23 May 2018 15:38:08 -0400 Subject: [PATCH 13/15] Drop Python 2.6 support --- tower/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tower/__init__.py b/tower/__init__.py index 63ff442..2eaa047 100644 --- a/tower/__init__.py +++ b/tower/__init__.py @@ -1,5 +1,6 @@ from past.builtins import basestring from builtins import object +from importlib import import_module import copy import gettext import re @@ -7,7 +8,6 @@ import django from django.conf import settings from django.utils.functional import lazy -from django.utils.importlib import import_module from django.utils.translation import (trans_real as django_trans, ugettext as django_ugettext, ungettext as django_nugettext) From f60205ab3999f96b2a77fdfb084c159e411fd215 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Tue, 29 May 2018 18:27:59 -0400 Subject: [PATCH 14/15] Fix lazy variants --- tower/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tower/__init__.py b/tower/__init__.py index 2eaa047..bd29e67 100644 --- a/tower/__init__.py +++ b/tower/__init__.py @@ -7,6 +7,7 @@ import django from django.conf import settings +from django.utils import six from django.utils.functional import lazy from django.utils.translation import (trans_real as django_trans, ugettext as django_ugettext, @@ -54,8 +55,9 @@ def ungettext(singular, plural, number, context=None): return plural_stripped return ret -ugettext_lazy = lazy(ugettext, str) -ungettext_lazy = lazy(ungettext, str) + +ugettext_lazy = lazy(ugettext, six.text_type) +ungettext_lazy = lazy(ungettext, six.text_type) def add_context(context, message): From e288635ba4c07d1380a98520b6674292d32fab87 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 5 Sep 2018 13:07:00 -0400 Subject: [PATCH 15/15] Stop testing against Django 1.4. --- tox.ini | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tox.ini b/tox.ini index ae416b5..72c9cd1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27-1.4, py27-1.5, py27-1.6, py27-1.7, py36-1.8 +envlist = py27-1.5, py27-1.6, py27-1.7, py36-1.8 [testenv] commands = @@ -12,15 +12,6 @@ deps = mock future -[testenv:py27-1.4] -basepython = python2.7 -deps = - Django==1.4.20 - -egit+https://github.com/jbalogh/jingo.git@v0.7.1#egg=jingo - babel==1.3 - {[testenv]deps} - - [testenv:py27-1.5] basepython = python2.7 deps =