Check PEP8 while running tests

Use polib >= 1.1.0
Rosetta version bump and changelog
This commit is contained in:
Marco Bonetti 2018-01-10 12:43:09 +01:00
parent d797b76a10
commit a43d369387
17 changed files with 93 additions and 70 deletions

3
.pep8 Normal file
View file

@ -0,0 +1,3 @@
[flake8]
ignore = E501
exclude = south_migrations,migrations,.venv_*,docs

10
CHANGES
View file

@ -1,6 +1,16 @@
Version History
===============
Version 0.8.0
--------------
* PR #194, huge thanks to @jbaldivieso:
* Better, cleaner RESTful URLs
* Massive rewrite of Rosetta's view functions as CBVs
* Better management of cached content
* Check for PEP8 validity during tests
Version 0.7.14
--------------
* Updated installation docs (PR #190, thanks @AuHau)

View file

@ -19,7 +19,8 @@ import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('..'))
from rosetta import get_version
# -- General configuration ------------------------------------------------
@ -47,7 +48,7 @@ master_doc = 'index'
# General information about the project.
project = u'Django Rosetta'
copyright = u'2008 2017 Marco Bonetti and contributors'
copyright = u'2008 2018 Marco Bonetti and contributors'
author = u'Marco Bonetti'
# The version info for the project you're documenting, acts as replacement for
@ -55,9 +56,9 @@ author = u'Marco Bonetti'
# built documents.
#
# The short X.Y version.
version = '0.7.14'
version = get_version()
# The full version, including alpha/beta/rc tags.
release = '0.7.14'
release = get_version()
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View file

@ -1,4 +1,4 @@
VERSION = (0, 7, 14)
VERSION = (0, 8, 0)
default_app_config = "rosetta.apps.RosettaAppConfig"

View file

@ -1,5 +1,4 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
# Number of messages to display per page.
MESSAGES_PER_PAGE = getattr(settings, 'ROSETTA_MESSAGES_PER_PAGE', 10)

View file

@ -1,2 +0,0 @@
from django.db import models
# Create your models here.

View file

@ -61,7 +61,6 @@ def find_pos(lang, project_apps=True, django_apps=False, third_party_apps=False)
if os.path.isdir(localepath):
paths.append(localepath)
# project/app/locale
has_appconfig = False
for appname in settings.INSTALLED_APPS:
@ -94,7 +93,6 @@ def find_pos(lang, project_apps=True, django_apps=False, third_party_apps=False)
if not project_apps and abs_project_path in app_path:
continue
if os.path.isdir(app_path):
paths.append(app_path)
@ -127,10 +125,10 @@ def find_pos(lang, project_apps=True, django_apps=False, third_party_apps=False)
langs = [lang, ]
if u'-' in lang:
_l, _c = map(lambda x: x.lower(), lang.split(u'-', 1))
langs += [u'%s_%s' % (_l, _c), u'%s_%s' % (_l, _c.upper()), u'%s_%s' % (_l, _c.capitalize()),]
langs += [u'%s_%s' % (_l, _c), u'%s_%s' % (_l, _c.upper()), u'%s_%s' % (_l, _c.capitalize())]
elif u'_' in lang:
_l, _c = map(lambda x: x.lower(), lang.split(u'_', 1))
langs += [u'%s-%s' % (_l, _c), u'%s-%s' % (_l, _c.upper()), u'%s_%s' % (_l, _c.capitalize()),]
langs += [u'%s-%s' % (_l, _c), u'%s-%s' % (_l, _c.upper()), u'%s_%s' % (_l, _c.capitalize())]
paths = map(os.path.normpath, paths)
paths = list(set(paths))

View file

@ -1,8 +1,8 @@
from django import dispatch
entry_changed = dispatch.Signal(
providing_args=["user", "old_msgstr", "old_fuzzy", "pofile", "language_code",]
providing_args=["user", "old_msgstr", "old_fuzzy", "pofile", "language_code"]
)
post_save = dispatch.Signal(
providing_args=["language_code","request",]
providing_args=["language_code", "request"]
)

View file

@ -101,19 +101,19 @@ class CacheRosettaStorage(BaseRosettaStorage):
self.delete('rosetta_cache_test')
def get(self, key, default=None):
#print ('get', self._key_prefix + key)
# print ('get', self._key_prefix + key)
return cache.get(self._key_prefix + key, default)
def set(self, key, val):
#print ('set', self._key_prefix + key)
# print ('set', self._key_prefix + key)
cache.set(self._key_prefix + key, val, 86400)
def has(self, key):
#print ('has', self._key_prefix + key)
# print ('has', self._key_prefix + key)
return (self._key_prefix + key) in cache
def delete(self, key):
#print ('del', self._key_prefix + key)
# print ('del', self._key_prefix + key)
cache.delete(self._key_prefix + key)

View file

@ -48,7 +48,7 @@ def do_incr(parser, token):
name = args[1]
if not hasattr(parser, '_namedIncrNodes'):
parser._namedIncrNodes = {}
if not name in parser._namedIncrNodes:
if name not in parser._namedIncrNodes:
parser._namedIncrNodes[name] = IncrNode(0)
return parser._namedIncrNodes[name]
do_incr = register.tag('increment', do_incr)

View file

@ -1 +1 @@
from .tests import *
from .tests import * # NOQA

View file

@ -30,7 +30,7 @@ class RosettaTestCase(TestCase):
self.curdir = os.path.dirname(__file__)
self.dest_file = os.path.normpath(
os.path.join(self.curdir, '../locale/xx/LC_MESSAGES/django.po')
)
)
def setUp(self):
from django.contrib.auth.models import User
@ -101,7 +101,7 @@ class RosettaTestCase(TestCase):
r = self.client.get(self.third_party_file_list_url)
self.assertTrue(
os.path.normpath('rosetta/locale/xx/LC_MESSAGES/django.po') in str(r.content)
)
)
def test_2_PickFile(self):
r = self.client.get(self.xx_form_url)
@ -304,28 +304,28 @@ class RosettaTestCase(TestCase):
r = self.client.get(self.third_party_file_list_url)
self.assertTrue(
os.path.normpath('rosetta/locale/xx/LC_MESSAGES/django.po') in str(r.content)
)
)
self.assertTrue(('contrib') not in str(r.content))
url = reverse('rosetta-file-list', kwargs={'po_filter': 'django'})
r = self.client.get(url)
self.assertTrue(
os.path.normpath('rosetta/locale/xx/LC_MESSAGES/django.po') not in str(r.content)
)
)
self.assertTrue(('contrib') in str(r.content))
url = reverse('rosetta-file-list', kwargs={'po_filter': 'all'})
r = self.client.get(url)
self.assertTrue(
os.path.normpath('rosetta/locale/xx/LC_MESSAGES/django.po') in str(r.content)
)
)
self.assertTrue(('contrib') in str(r.content))
url = reverse('rosetta-file-list', kwargs={'po_filter': 'project'})
r = self.client.get(url)
self.assertTrue(
os.path.normpath('rosetta/locale/xx/LC_MESSAGES/django.po') not in str(r.content)
)
)
self.assertTrue(('contrib') not in str(r.content))
def test_14_issue_99_context_and_comments(self):
@ -432,7 +432,7 @@ class RosettaTestCase(TestCase):
'm_ff7060c1a9aae9c42af4d54ac8551f67_0': 'Foo %s',
'm_ff7060c1a9aae9c42af4d54ac8551f67_1': 'Bar %s',
'm_09f7e02f1290be211da707a266f153b3': 'Salut',
}
}
r = self.client.post(self.xx_form_url, data)
with open(self.dest_file, 'r') as po_file:
pofile_content = po_file.read()
@ -478,7 +478,7 @@ class RosettaTestCase(TestCase):
self.assertNotEqual(
self.client.session.get('rosetta_cache_storage_key_prefix'),
self.client2.session.get('rosetta_cache_storage_key_prefix')
)
)
# Clean up (restore perms)
os.chmod(self.dest_file, 420) # 0644
@ -498,7 +498,7 @@ class RosettaTestCase(TestCase):
unicode_user = User.objects.create_user(
'test_unicode', 'save_header_data@test.com', 'test_unicode'
)
)
unicode_user.first_name = "aéaéaé aàaàaàa"
unicode_user.last_name = "aâââ üüüü"
unicode_user.is_superuser, unicode_user.is_staff = True, True
@ -561,7 +561,7 @@ class RosettaTestCase(TestCase):
url = reverse(
'rosetta-form',
kwargs={'po_filter': 'all', 'lang_id': 'fr_FR.utf8', 'idx': 0}
)
)
r = self.client.get(url)
self.assertTrue('French (France), UTF8' in str(r.content))
self.assertTrue('m_03a603523bd75b00414a413657acdeb2' in str(r.content))
@ -598,11 +598,11 @@ class RosettaTestCase(TestCase):
os.unlink(self.dest_file)
destfile = os.path.normpath(
os.path.join(self.curdir, '../locale/xx/LC_MESSAGES/pr44.po')
)
)
shutil.copy(
os.path.normpath(os.path.join(self.curdir, './pr44.po.template')),
destfile
)
)
r = self.client.get(self.third_party_file_list_url)
self.assertTrue('xx/LC_MESSAGES/pr44.po' in str(r.content))
@ -847,7 +847,7 @@ class RosettaTestCase(TestCase):
view=views.TranslationFormView(),
request=request,
**kwargs
)
)
self.assertTrue(view.po_file_is_writable)
# Now try again with the file not writable. (Regenerate the view, since
@ -858,7 +858,7 @@ class RosettaTestCase(TestCase):
view=views.TranslationFormView(),
request=request,
**kwargs
)
)
self.assertFalse(view.po_file_is_writable)
# Cleanup
@ -878,7 +878,7 @@ class RosettaTestCase(TestCase):
view=views.TranslationFormView(),
request=request,
**kwargs
)
)
self.assertEqual(view.po_file_path, self.dest_file)
# But if the language isn't an option, we get a 404
@ -888,7 +888,7 @@ class RosettaTestCase(TestCase):
view=views.TranslationFormView(),
request=request,
**kwargs
)
)
with self.assertRaises(Http404):
view.po_file_path
@ -901,7 +901,7 @@ class RosettaTestCase(TestCase):
# Recycle request, even though url kwargs conflict with ones below.
request=request,
**new_kwargs
)
)
with self.assertRaises(Http404):
view.po_file_path

View file

@ -11,14 +11,18 @@ from . import views
urlpatterns = [
url(r'^$',
RedirectView.as_view(url=reverse_lazy('rosetta-file-list',
kwargs={'po_filter': 'project'})),
RedirectView.as_view(
url=reverse_lazy('rosetta-file-list', kwargs={'po_filter': 'project'}),
permanent=False
),
name='rosetta-old-home-redirect',
),
url(r'^files/$',
RedirectView.as_view(url=reverse_lazy('rosetta-file-list',
kwargs={'po_filter': 'project'})),
RedirectView.as_view(
url=reverse_lazy('rosetta-file-list', kwargs={'po_filter': 'project'}),
permanent=False
),
name='rosetta-file-list-redirect',
),
@ -41,5 +45,4 @@ urlpatterns = [
views.translate_text,
name='translate_text',
),
]

View file

@ -1,5 +1,4 @@
import hashlib
import json
import os
import os.path
import re
@ -15,7 +14,7 @@ from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required, user_passes_test
from django.core.paginator import Paginator
from django.http import Http404, HttpResponseRedirect, HttpResponse
from django.http import Http404, HttpResponseRedirect, HttpResponse, JsonResponse
from django.views.decorators.cache import never_cache
from django.views.generic import TemplateView, View
try:
@ -66,7 +65,7 @@ class RosettaBaseMixin(object):
If the filter isn't in this list, throw a 404.
"""
po_filter = self.kwargs['po_filter']
po_filter = self.kwargs.get('po_filter')
if po_filter not in {'all', 'django', 'third-party', 'project'}:
raise Http404
return po_filter
@ -155,7 +154,7 @@ class RosettaFileLevelMixin(RosettaBaseMixin):
six.text_type(entry.msgid) +
six.text_type(entry.msgstr) +
six.text_type(entry.msgctxt or '')
).encode('utf8')
).encode('utf8')
entry.md5hash = hashlib.md5(str_to_hash).hexdigest()
else:
storage = get_storage(self.request)
@ -171,7 +170,7 @@ class RosettaFileLevelMixin(RosettaBaseMixin):
six.text_type(entry.msgid) +
six.text_type(entry.msgstr) +
six.text_type(entry.msgctxt or '')
).encode('utf8')
).encode('utf8')
entry.md5hash = hashlib.new('md5', str_to_hash).hexdigest()
storage.set(self.po_file_cache_key, po_file)
return po_file
@ -326,13 +325,11 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
if plural_id is not None: # 0 is ok!
entry.msgstr_plural[plural_id] = self.fix_nls(
entry.msgid_plural, new_msgstr
)
)
else:
entry.msgstr = self.fix_nls(entry.msgid, new_msgstr)
is_fuzzy = bool(
self.request.POST.get('f_%s' % md5hash, False)
)
is_fuzzy = bool(self.request.POST.get('f_%s' % md5hash, False))
old_fuzzy = 'fuzzy' in entry.flags
if old_fuzzy and not is_fuzzy:
@ -356,7 +353,7 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
_("Some items in your last translation block couldn't "
"be saved: this usually happens when the catalog file "
"changes on disk after you last loaded it."),
)
)
if file_change and self.po_file_is_writable:
try:
@ -365,14 +362,14 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
getattr(self.request.user, 'first_name', 'Anonymous'),
getattr(self.request.user, 'last_name', 'User'),
getattr(self.request.user, 'email', 'anonymous@user.tld')
)
).encode('ascii', 'ignore')
self.po_file.metadata['X-Translated-Using'] = u"django-rosetta %s" % (
get_rosetta_version(False)
)
).encode('ascii', 'ignore')
self.po_file.metadata['X-Translated-Using'] = u"django-rosetta %s" % (
get_rosetta_version(False))
self.po_file.metadata['PO-Revision-Date'] = timestamp_with_timezone()
except UnicodeDecodeError:
pass
try:
self.po_file.save()
po_filepath, ext = os.path.splitext(self.po_file_path)
@ -390,7 +387,7 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
self.request.environ.get('mod_wsgi.process_group', None) and
'SCRIPT_FILENAME' in self.request.environ and
int(self.request.environ.get('mod_wsgi.script_reloading', 0))
)
)
if should_try_wsgi_reload:
try:
os.utime(self.request.environ.get('SCRIPT_FILENAME'), None)
@ -428,13 +425,13 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
'query': self.query,
'ref_lang': self.ref_lang,
'page': page,
}
}
# Winnow down the query string args to non-blank ones
query_string_args = {k: v for k, v in query_string_args.items() if v}
return HttpResponseRedirect("{url}?{qs}".format(
url=reverse('rosetta-form', kwargs=self.kwargs),
qs=urlencode(query_string_args),
))
))
def get_context_data(self, **kwargs):
context = super(TranslationFormView, self).get_context_data(**kwargs)
@ -491,7 +488,7 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
main_lang_po_path = self.po_file_path.replace(
'/%s/' % self.language_id,
'/%s/' % main_language_id,
)
)
# XXX: brittle; what if this path doesn't exist? Isn't a .po file?
main_lang_po = pofile(main_lang_po_path)
@ -507,7 +504,7 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
ADMIN_IMAGE_DIR = ADMIN_MEDIA_PREFIX + 'img/'
rosetta_i18n_lang_name = six.text_type(
dict(settings.LANGUAGES).get(self.language_id)
)
)
# "bidi" as in "bi-directional"
rosetta_i18n_lang_bidi = self.language_id.split('-')[0] in settings.LANGUAGES_BIDI
query_string_args = {}
@ -523,7 +520,7 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
# numbers in these links. We just pass in ref_lang, if it's set.
filter_query_string_base = urlencode(
{k: v for k, v in query_string_args.items() if k == 'ref_lang'}
)
)
context.update({
'version': get_rosetta_version(True),
@ -548,7 +545,7 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
'paginator': paginator,
'rosetta_i18n_pofile': self.po_file,
'ref_lang': self.ref_lang,
})
})
return context
@ -577,7 +574,7 @@ class TranslationFormView(RosettaFileLevelMixin, TemplateView):
'/locale/[a-z]{2}/',
'/locale/%s/' % (self.ref_lang),
self.po_file_path,
)
)
try:
ref_pofile = pofile(ref_fn)
except IOError:
@ -673,7 +670,7 @@ class TranslationFileDownload(RosettaFileLevelMixin, View):
# XXX: should add a message!
return HttpResponseRedirect(
reverse('rosetta-file-list', kwargs={'po_filter': 'project'})
)
)
@user_passes_test(lambda user: can_translate(user), settings.LOGIN_URL)
@ -699,6 +696,6 @@ def translate_text(request):
data = {
'success': False,
'error': "Translation API Exception: {0}".format(e.message),
}
}
return HttpResponse(json.dumps(data), content_type='application/json')
return JsonResponse(data)

View file

@ -45,8 +45,9 @@ setup(
'Topic :: Software Development :: Internationalization',
'Framework :: Django',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],
include_package_data=True,
zip_safe=False,
@ -54,7 +55,7 @@ setup(
'six >=1.2.0',
'Django >= 1.8',
'requests >= 2.1.0',
'polib >= 1.0.6',
'polib >= 1.1.0',
'microsofttranslator >= 0.7'
],
tests_require=['tox'],

4
testproject/coverage.sh Normal file
View file

@ -0,0 +1,4 @@
#!/bin/sh
coverage run --rcfile .coveragerc manage.py test --failfast rosetta
coverage xml
coverage html

11
tox.ini
View file

@ -1,5 +1,6 @@
[tox]
envlist =
flake8,
{py27,py36}-django{18,19,110,111},
py36-django20,
gettext,docs
@ -26,11 +27,12 @@ deps =
py36-django{17,18,19,110,111,20}: python3-memcached
# py27-django18: pudb
requests
polib>=1.0.6
polib>=1.1.0
microsofttranslator>=0.7
six
goslate
vcrpy
coverage
[testenv:gettext]
basepython = python3
@ -57,3 +59,10 @@ deps = sphinx
changedir = docs
commands=
sphinx-build -W -b html . _build/html
[testenv:flake8]
basepython = python3
deps = flake8==2.4.1
commands=
flake8 {toxinidir}/rosetta