Moved common, translation, template, and url code out of util.py and into tools/[file].py

This commit is contained in:
Aaron Williamson 2011-10-01 09:31:42 -04:00
parent 9122a9d047
commit ae3bc7fabf
20 changed files with 636 additions and 303 deletions

View File

@ -21,6 +21,7 @@ import routes
from webob import Request, exc
from mediagoblin import routing, util, middleware
from mediagoblin.tools import translate, template
from mediagoblin.mg_globals import setup_globals
from mediagoblin.init.celery import setup_celery_from_config
from mediagoblin.init import (get_jinja_loader, get_staticdirector,
@ -123,9 +124,9 @@ class MediaGoblinApp(object):
# Attach self as request.app
# Also attach a few utilities from request.app for convenience?
request.app = self
request.locale = util.get_locale_from_request(request)
request.locale = translate.get_locale_from_request(request)
request.template_env = util.get_jinja_env(
request.template_env = template.get_jinja_env(
self.template_loader, request.locale)
request.db = self.db
request.staticdirect = self.staticdirector

View File

@ -17,7 +17,7 @@
import wtforms
import re
from mediagoblin.util import fake_ugettext_passthrough as _
from mediagoblin.tools.translate import fake_ugettext_passthrough as _
class RegistrationForm(wtforms.Form):

View File

@ -19,7 +19,8 @@ import random
import bcrypt
from mediagoblin.util import send_email, render_template
from mediagoblin.util import send_email
from mediagoblin.tools.template import render_template
from mediagoblin import mg_globals

View File

@ -22,7 +22,7 @@ from webob import exc
from mediagoblin import messages
from mediagoblin import mg_globals
from mediagoblin.util import render_to_response, redirect, render_404
from mediagoblin.util import pass_to_ugettext as _
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.db.util import ObjectId, InvalidId
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms

View File

@ -25,7 +25,7 @@ from mediagoblin.db import migrations
from mediagoblin.db.util import ASCENDING, DESCENDING, ObjectId
from mediagoblin.util import Pagination
from mediagoblin.util import DISPLAY_IMAGE_FETCHING_ORDER
from mediagoblin.tools import url
###################
# Custom validators
@ -242,7 +242,7 @@ class MediaEntry(Document):
pass
def generate_slug(self):
self['slug'] = util.slugify(self['title'])
self['slug'] = url.slugify(self['title'])
duplicate = mg_globals.database.media_entries.find_one(
{'slug': self['slug']})

View File

@ -14,7 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.util import lazy_pass_to_ugettext as _
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
class BaseProcessingFail(Exception):
"""

View File

@ -18,7 +18,7 @@
import wtforms
from mediagoblin.util import tag_length_validator
from mediagoblin.util import fake_ugettext_passthrough as _
from mediagoblin.tools.translate import fake_ugettext_passthrough as _
class SubmitStartForm(wtforms.Form):

View File

@ -25,7 +25,7 @@ from mediagoblin.db.util import ObjectId
from mediagoblin.util import (
render_to_response, redirect, cleaned_markdown_conversion, \
convert_to_tag_list_of_dicts)
from mediagoblin.util import pass_to_ugettext as _
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.decorators import require_active_login
from mediagoblin.submit import forms as submit_forms, security
from mediagoblin.process_media import process_media, mark_entry_failed

View File

@ -22,7 +22,7 @@ from nose.tools import assert_equal
from mediagoblin.auth import lib as auth_lib
from mediagoblin.tests.tools import setup_fresh_app
from mediagoblin import mg_globals
from mediagoblin import util
from mediagoblin.tools import template
########################
@ -76,16 +76,16 @@ def test_register_views(test_app):
test_app.get('/auth/register/')
# Make sure it rendered with the appropriate template
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/register.html')
# Try to register without providing anything, should error
# --------------------------------------------------------
util.clear_test_template_context()
template.clear_test_template_context()
test_app.post(
'/auth/register/', {})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [u'This field is required.']
assert form.password.errors == [u'This field is required.']
@ -96,14 +96,14 @@ def test_register_views(test_app):
# --------------------------------------------------------
## too short
util.clear_test_template_context()
template.clear_test_template_context()
test_app.post(
'/auth/register/', {
'username': 'l',
'password': 'o',
'confirm_password': 'o',
'email': 'l'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [
@ -112,12 +112,12 @@ def test_register_views(test_app):
u'Field must be between 6 and 30 characters long.']
## bad form
util.clear_test_template_context()
template.clear_test_template_context()
test_app.post(
'/auth/register/', {
'username': '@_@',
'email': 'lollerskates'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [
@ -126,12 +126,12 @@ def test_register_views(test_app):
u'Invalid email address.']
## mismatching passwords
util.clear_test_template_context()
template.clear_test_template_context()
test_app.post(
'/auth/register/', {
'password': 'herpderp',
'confirm_password': 'derpherp'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/register.html']
form = context['register_form']
assert form.password.errors == [
@ -142,7 +142,7 @@ def test_register_views(test_app):
# Successful register
# -------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/register/', {
'username': 'happygirl',
@ -155,7 +155,7 @@ def test_register_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/u/happygirl/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/user_pages/user.html')
## Make sure user is in place
@ -166,15 +166,15 @@ def test_register_views(test_app):
assert new_user['email_verified'] == False
## Make sure user is logged in
request = util.TEMPLATE_TEST_CONTEXT[
request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
assert request.session['user_id'] == unicode(new_user['_id'])
## Make sure we get email confirmation, and try verifying
assert len(util.EMAIL_TEST_INBOX) == 1
message = util.EMAIL_TEST_INBOX.pop()
assert len(template.EMAIL_TEST_INBOX) == 1
message = template.EMAIL_TEST_INBOX.pop()
assert message['To'] == 'happygrrl@example.org'
email_context = util.TEMPLATE_TEST_CONTEXT[
email_context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/auth/verification_email.txt']
assert email_context['verification_url'] in message.get_payload(decode=True)
@ -190,12 +190,12 @@ def test_register_views(test_app):
new_user['verification_key']]
## Try verifying with bs verification key, shouldn't work
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.get(
"/auth/verify_email/?userid=%s&token=total_bs" % unicode(
new_user['_id']))
response.follow()
context = util.TEMPLATE_TEST_CONTEXT[
context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']
# assert context['verification_successful'] == True
# TODO: Would be good to test messages here when we can do so...
@ -206,10 +206,10 @@ def test_register_views(test_app):
assert new_user['email_verified'] == False
## Verify the email activation works
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.get("%s?%s" % (path, get_params))
response.follow()
context = util.TEMPLATE_TEST_CONTEXT[
context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']
# assert context['verification_successful'] == True
# TODO: Would be good to test messages here when we can do so...
@ -222,7 +222,7 @@ def test_register_views(test_app):
# Uniqueness checks
# -----------------
## We shouldn't be able to register with that user twice
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/register/', {
'username': 'happygirl',
@ -230,7 +230,7 @@ def test_register_views(test_app):
'confirm_password': 'iamsohappy2',
'email': 'happygrrl2@example.org'})
context = util.TEMPLATE_TEST_CONTEXT[
context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/auth/register.html']
form = context['register_form']
assert form.username.errors == [
@ -240,7 +240,7 @@ def test_register_views(test_app):
### Oops, forgot the password
# -------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/forgot_password/',
{'username': 'happygirl'})
@ -250,14 +250,14 @@ def test_register_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/auth/forgot_password/email_sent/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/fp_email_sent.html')
## Make sure link to change password is sent by email
assert len(util.EMAIL_TEST_INBOX) == 1
message = util.EMAIL_TEST_INBOX.pop()
assert len(template.EMAIL_TEST_INBOX) == 1
message = template.EMAIL_TEST_INBOX.pop()
assert message['To'] == 'happygrrl@example.org'
email_context = util.TEMPLATE_TEST_CONTEXT[
email_context = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/auth/fp_verification_email.txt']
#TODO - change the name of verification_url to something forgot-password-ish
assert email_context['verification_url'] in message.get_payload(decode=True)
@ -277,14 +277,14 @@ def test_register_views(test_app):
assert (new_user['fp_token_expire'] - datetime.datetime.now()).days == 9
## Try using a bs password-changing verification key, shouldn't work
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.get(
"/auth/forgot_password/verify/?userid=%s&token=total_bs" % unicode(
new_user['_id']), status=400)
assert response.status == '400 Bad Request'
## Try using an expired token to change password, shouldn't work
util.clear_test_template_context()
template.clear_test_template_context()
real_token_expiration = new_user['fp_token_expire']
new_user['fp_token_expire'] = datetime.datetime.now()
new_user.save()
@ -294,12 +294,12 @@ def test_register_views(test_app):
new_user.save()
## Verify step 1 of password-change works -- can see form to change password
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.get("%s?%s" % (path, get_params))
assert util.TEMPLATE_TEST_CONTEXT.has_key('mediagoblin/auth/change_fp.html')
assert template.TEMPLATE_TEST_CONTEXT.has_key('mediagoblin/auth/change_fp.html')
## Verify step 2.1 of password-change works -- report success to user
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/forgot_password/verify/', {
'userid': parsed_get_params['userid'],
@ -307,11 +307,11 @@ def test_register_views(test_app):
'confirm_password': 'iamveryveryhappy',
'token': parsed_get_params['token']})
response.follow()
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/fp_changed_success.html')
## Verify step 2.2 of password-change works -- login w/ new password success
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'happygirl',
@ -322,7 +322,7 @@ def test_register_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/root.html')
@ -341,61 +341,61 @@ def test_authentication_views(test_app):
# Get login
# ---------
test_app.get('/auth/login/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/auth/login.html')
# Failed login - blank form
# -------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post('/auth/login/')
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
form = context['login_form']
assert form.username.errors == [u'This field is required.']
assert form.password.errors == [u'This field is required.']
# Failed login - blank user
# -------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'password': u'toast'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
form = context['login_form']
assert form.username.errors == [u'This field is required.']
# Failed login - blank password
# -----------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
form = context['login_form']
assert form.password.errors == [u'This field is required.']
# Failed login - bad user
# -----------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'steve',
'password': 'toast'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
assert context['login_failed']
# Failed login - bad password
# ---------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris',
'password': 'jam'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
assert context['login_failed']
# Successful login
# ----------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris',
@ -406,17 +406,17 @@ def test_authentication_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/root.html')
# Make sure user is in the session
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
session = context['request'].session
assert session['user_id'] == unicode(test_user['_id'])
# Successful logout
# -----------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.get('/auth/logout/')
# Should be redirected to index page
@ -424,17 +424,17 @@ def test_authentication_views(test_app):
assert_equal(
urlparse.urlsplit(response.location)[2],
'/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/root.html')
# Make sure the user is not in the session
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
session = context['request'].session
assert session.has_key('user_id') == False
# User is redirected to custom URL if POST['next'] is set
# -------------------------------------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = test_app.post(
'/auth/login/', {
'username': u'chris',

View File

@ -16,7 +16,7 @@
from mediagoblin.messages import fetch_messages, add_message
from mediagoblin.tests.tools import setup_fresh_app
from mediagoblin import util
from mediagoblin.tools import template
@setup_fresh_app
@ -28,7 +28,7 @@ def test_messages(test_app):
"""
# Aquire a request object
test_app.get('/')
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
request = context['request']
# The message queue should be empty

View File

@ -22,7 +22,7 @@ from nose.tools import assert_equal, assert_true, assert_false
from mediagoblin.auth import lib as auth_lib
from mediagoblin.tests.tools import setup_fresh_app, get_test_app
from mediagoblin import mg_globals
from mediagoblin import util
from mediagoblin.tools import template, common
GOOD_JPG = pkg_resources.resource_filename(
'mediagoblin.tests', 'test_submission/good.jpg')
@ -63,20 +63,20 @@ class TestSubmission:
def test_missing_fields(self):
# Test blank form
# ---------------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.file.errors == [u'You must provide a file.']
# Test blank file
# ---------------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'test title'})
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.file.errors == [u'You must provide a file.']
@ -84,7 +84,7 @@ class TestSubmission:
def test_normal_uploads(self):
# Test JPG
# --------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Normal upload 1'
@ -96,12 +96,12 @@ class TestSubmission:
assert_equal(
urlparse.urlsplit(response.location)[2],
'/u/chris/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/user_pages/user.html')
# Test PNG
# --------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Normal upload 2'
@ -112,13 +112,13 @@ class TestSubmission:
assert_equal(
urlparse.urlsplit(response.location)[2],
'/u/chris/')
assert util.TEMPLATE_TEST_CONTEXT.has_key(
assert template.TEMPLATE_TEST_CONTEXT.has_key(
'mediagoblin/user_pages/user.html')
def test_tags(self):
# Good tag string
# --------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Balanced Goblin',
@ -128,7 +128,7 @@ class TestSubmission:
# New media entry with correct tags should be created
response.follow()
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/user_pages/user.html']
request = context['request']
media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
assert_equal(media['tags'],
@ -137,7 +137,7 @@ class TestSubmission:
# Test tags that are too long
# ---------------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Balanced Goblin',
@ -146,14 +146,14 @@ class TestSubmission:
'file', GOOD_JPG)])
# Too long error should be raised
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.tags.errors == [
u'Tags must be shorter than 50 characters. Tags that are too long'\
': ffffffffffffffffffffffffffuuuuuuuuuuuuuuuuuuuuuuuuuu']
def test_delete(self):
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Balanced Goblin',
@ -163,7 +163,7 @@ class TestSubmission:
# Post image
response.follow()
request = util.TEMPLATE_TEST_CONTEXT[
request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
@ -183,7 +183,7 @@ class TestSubmission:
response.follow()
request = util.TEMPLATE_TEST_CONTEXT[
request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
media = request.db.MediaEntry.find({'title': 'Balanced Goblin'})[0]
@ -202,7 +202,7 @@ class TestSubmission:
response.follow()
request = util.TEMPLATE_TEST_CONTEXT[
request = template.TEMPLATE_TEST_CONTEXT[
'mediagoblin/user_pages/user.html']['request']
# Does media entry still exist?
@ -213,14 +213,14 @@ class TestSubmission:
def test_malicious_uploads(self):
# Test non-suppoerted file with non-supported extension
# -----------------------------------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Malicious Upload 1'
}, upload_files=[(
'file', EVIL_FILE)])
context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
context = template.TEMPLATE_TEST_CONTEXT['mediagoblin/submit/start.html']
form = context['submit_form']
assert form.file.errors == ['The file doesn\'t seem to be an image!']
@ -230,7 +230,7 @@ class TestSubmission:
# Test non-supported file with .jpg extension
# -------------------------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Malicious Upload 2'
@ -250,7 +250,7 @@ class TestSubmission:
# Test non-supported file with .png extension
# -------------------------------------------
util.clear_test_template_context()
template.clear_test_template_context()
response = self.test_app.post(
'/submit/', {
'title': 'Malicious Upload 3'

View File

@ -17,7 +17,7 @@
import email
from mediagoblin import util
from mediagoblin.tools import url, translate
util._activate_testing()
@ -71,38 +71,38 @@ I hope you like unit tests JUST AS MUCH AS I DO!"""
I hope you like unit tests JUST AS MUCH AS I DO!"""
def test_slugify():
assert util.slugify('a walk in the park') == 'a-walk-in-the-park'
assert util.slugify('A Walk in the Park') == 'a-walk-in-the-park'
assert util.slugify('a walk in the park') == 'a-walk-in-the-park'
assert util.slugify('a walk in-the-park') == 'a-walk-in-the-park'
assert util.slugify('a w@lk in the park?') == 'a-w-lk-in-the-park'
assert util.slugify(u'a walk in the par\u0107') == 'a-walk-in-the-parc'
assert util.slugify(u'\u00E0\u0042\u00E7\u010F\u00EB\u0066') == 'abcdef'
assert url.slugify('a walk in the park') == 'a-walk-in-the-park'
assert url.slugify('A Walk in the Park') == 'a-walk-in-the-park'
assert url.slugify('a walk in the park') == 'a-walk-in-the-park'
assert url.slugify('a walk in-the-park') == 'a-walk-in-the-park'
assert url.slugify('a w@lk in the park?') == 'a-w-lk-in-the-park'
assert url.slugify(u'a walk in the par\u0107') == 'a-walk-in-the-parc'
assert url.slugify(u'\u00E0\u0042\u00E7\u010F\u00EB\u0066') == 'abcdef'
def test_locale_to_lower_upper():
"""
Test cc.i18n.util.locale_to_lower_upper()
"""
assert util.locale_to_lower_upper('en') == 'en'
assert util.locale_to_lower_upper('en_US') == 'en_US'
assert util.locale_to_lower_upper('en-us') == 'en_US'
assert translate.locale_to_lower_upper('en') == 'en'
assert translate.locale_to_lower_upper('en_US') == 'en_US'
assert translate.locale_to_lower_upper('en-us') == 'en_US'
# crazy renditions. Useful?
assert util.locale_to_lower_upper('en-US') == 'en_US'
assert util.locale_to_lower_upper('en_us') == 'en_US'
assert translate.locale_to_lower_upper('en-US') == 'en_US'
assert translate.locale_to_lower_upper('en_us') == 'en_US'
def test_locale_to_lower_lower():
"""
Test cc.i18n.util.locale_to_lower_lower()
"""
assert util.locale_to_lower_lower('en') == 'en'
assert util.locale_to_lower_lower('en_US') == 'en-us'
assert util.locale_to_lower_lower('en-us') == 'en-us'
assert translate.locale_to_lower_lower('en') == 'en'
assert translate.locale_to_lower_lower('en_US') == 'en-us'
assert translate.locale_to_lower_lower('en-us') == 'en-us'
# crazy renditions. Useful?
assert util.locale_to_lower_lower('en-US') == 'en-us'
assert util.locale_to_lower_lower('en_us') == 'en-us'
assert translate.locale_to_lower_lower('en-US') == 'en-us'
assert translate.locale_to_lower_lower('en_us') == 'en-us'
def test_html_cleaner():

View File

View File

@ -0,0 +1,18 @@
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 Free Software Foundation, Inc
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
global TESTS_ENABLED
TESTS_ENABLED = False

View File

@ -0,0 +1,114 @@
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from math import ceil
import jinja2
from babel.localedata import exists
from babel.support import LazyProxy
from mediagoblin import mg_globals
from mediagoblin import messages
from mediagoblin.tools import common
from mediagoblin.tools.translate import setup_gettext
SETUP_JINJA_ENVS = {}
def get_jinja_env(template_loader, locale):
"""
Set up the Jinja environment,
(In the future we may have another system for providing theming;
for now this is good enough.)
"""
setup_gettext(locale)
# If we have a jinja environment set up with this locale, just
# return that one.
if SETUP_JINJA_ENVS.has_key(locale):
return SETUP_JINJA_ENVS[locale]
template_env = jinja2.Environment(
loader=template_loader, autoescape=True,
extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])
template_env.install_gettext_callables(
mg_globals.translations.ugettext,
mg_globals.translations.ungettext)
# All templates will know how to ...
# ... fetch all waiting messages and remove them from the queue
# ... construct a grid of thumbnails or other media
template_env.globals['fetch_messages'] = messages.fetch_messages
template_env.globals['gridify_list'] = gridify_list
template_env.globals['gridify_cursor'] = gridify_cursor
if exists(locale):
SETUP_JINJA_ENVS[locale] = template_env
return template_env
# We'll store context information here when doing unit tests
TEMPLATE_TEST_CONTEXT = {}
def render_template(request, template_path, context):
"""
Render a template with context.
Always inserts the request into the context, so you don't have to.
Also stores the context if we're doing unit tests. Helpful!
"""
template = request.template_env.get_template(
template_path)
context['request'] = request
rendered = template.render(context)
if common.TESTS_ENABLED:
TEMPLATE_TEST_CONTEXT[template_path] = context
return rendered
def clear_test_template_context():
global TEMPLATE_TEST_CONTEXT
TEMPLATE_TEST_CONTEXT = {}
def gridify_list(this_list, num_cols=5):
"""
Generates a list of lists where each sub-list's length depends on
the number of columns in the list
"""
grid = []
# Figure out how many rows we should have
num_rows = int(ceil(float(len(this_list)) / num_cols))
for row_num in range(num_rows):
slice_min = row_num * num_cols
slice_max = (row_num + 1) * num_cols
row = this_list[slice_min:slice_max]
grid.append(row)
return grid
def gridify_cursor(this_cursor, num_cols=5):
"""
Generates a list of lists where each sub-list's length depends on
the number of columns in the list
"""
return gridify_list(list(this_cursor), num_cols)

View File

@ -0,0 +1,167 @@
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gettext
import pkg_resources
from babel.localedata import exists
from babel.support import LazyProxy
from mediagoblin import mg_globals
###################
# Translation tools
###################
TRANSLATIONS_PATH = pkg_resources.resource_filename(
'mediagoblin', 'i18n')
def locale_to_lower_upper(locale):
"""
Take a locale, regardless of style, and format it like "en-us"
"""
if '-' in locale:
lang, country = locale.split('-', 1)
return '%s_%s' % (lang.lower(), country.upper())
elif '_' in locale:
lang, country = locale.split('_', 1)
return '%s_%s' % (lang.lower(), country.upper())
else:
return locale.lower()
def locale_to_lower_lower(locale):
"""
Take a locale, regardless of style, and format it like "en_US"
"""
if '_' in locale:
lang, country = locale.split('_', 1)
return '%s-%s' % (lang.lower(), country.lower())
else:
return locale.lower()
def get_locale_from_request(request):
"""
Figure out what target language is most appropriate based on the
request
"""
request_form = request.GET or request.POST
if request_form.has_key('lang'):
return locale_to_lower_upper(request_form['lang'])
accept_lang_matches = request.accept_language.best_matches()
# Your routing can explicitly specify a target language
matchdict = request.matchdict or {}
if matchdict.has_key('locale'):
target_lang = matchdict['locale']
elif request.session.has_key('target_lang'):
target_lang = request.session['target_lang']
# Pull the first acceptable language
elif accept_lang_matches:
target_lang = accept_lang_matches[0]
# Fall back to English
else:
target_lang = 'en'
return locale_to_lower_upper(target_lang)
SETUP_GETTEXTS = {}
def setup_gettext(locale):
"""
Setup the gettext instance based on this locale
"""
# Later on when we have plugins we may want to enable the
# multi-translations system they have so we can handle plugin
# translations too
# TODO: fallback nicely on translations from pt_PT to pt if not
# available, etc.
if SETUP_GETTEXTS.has_key(locale):
this_gettext = SETUP_GETTEXTS[locale]
else:
this_gettext = gettext.translation(
'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
if exists(locale):
SETUP_GETTEXTS[locale] = this_gettext
mg_globals.setup_globals(
translations=this_gettext)
# Force en to be setup before anything else so that
# mg_globals.translations is never None
setup_gettext('en')
def pass_to_ugettext(*args, **kwargs):
"""
Pass a translation on to the appropriate ugettext method.
The reason we can't have a global ugettext method is because
mg_globals gets swapped out by the application per-request.
"""
return mg_globals.translations.ugettext(
*args, **kwargs)
def lazy_pass_to_ugettext(*args, **kwargs):
"""
Lazily pass to ugettext.
This is useful if you have to define a translation on a module
level but you need it to not translate until the time that it's
used as a string.
"""
return LazyProxy(pass_to_ugettext, *args, **kwargs)
def pass_to_ngettext(*args, **kwargs):
"""
Pass a translation on to the appropriate ngettext method.
The reason we can't have a global ngettext method is because
mg_globals gets swapped out by the application per-request.
"""
return mg_globals.translations.ngettext(
*args, **kwargs)
def lazy_pass_to_ngettext(*args, **kwargs):
"""
Lazily pass to ngettext.
This is useful if you have to define a translation on a module
level but you need it to not translate until the time that it's
used as a string.
"""
return LazyProxy(pass_to_ngettext, *args, **kwargs)
def fake_ugettext_passthrough(string):
"""
Fake a ugettext call for extraction's sake ;)
In wtforms there's a separate way to define a method to translate
things... so we just need to mark up the text so that it can be
extracted, not so that it's actually run through gettext.
"""
return string

31
mediagoblin/tools/url.py Normal file
View File

@ -0,0 +1,31 @@
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 Free Software Foundation, Inc
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
import translitcodec
_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
def slugify(text, delim=u'-'):
"""
Generates an ASCII-only slug. Taken from http://flask.pocoo.org/snippets/5/
"""
result = []
for word in _punct_re.split(text.lower()):
word = word.encode('translit/long')
if word:
result.append(word)
return unicode(delim.join(result))

View File

@ -16,7 +16,7 @@
import wtforms
from mediagoblin.util import fake_ugettext_passthrough as _
from mediagoblin.tools.translate import fake_ugettext_passthrough as _
class MediaCommentForm(wtforms.Form):

View File

@ -21,7 +21,7 @@ from mediagoblin.db.util import DESCENDING, ObjectId
from mediagoblin.util import (
Pagination, render_to_response, redirect, cleaned_markdown_conversion,
render_404, delete_media_files)
from mediagoblin.util import pass_to_ugettext as _
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.user_pages import forms as user_forms
from mediagoblin.decorators import (uses_pagination, get_user_media_entry,

View File

@ -17,41 +17,42 @@
from __future__ import division
from email.MIMEText import MIMEText
import gettext
import pkg_resources
#import gettext
#import pkg_resources
import smtplib
import sys
import re
#import re
#import translitcodec
import urllib
from math import ceil, floor
import copy
import wtforms
from babel.localedata import exists
from babel.support import LazyProxy
import jinja2
import translitcodec
#from babel.localedata import exists
#from babel.support import LazyProxy
#import jinja2
from webob import Response, exc
from lxml.html.clean import Cleaner
import markdown
from wtforms.form import Form
from mediagoblin import mg_globals
from mediagoblin import messages
#from mediagoblin import messages
from mediagoblin.db.util import ObjectId
from mediagoblin.tools import url
from mediagoblin.tools import common
from mediagoblin.tools.template import TEMPLATE_TEST_CONTEXT, render_template
from itertools import izip, count
DISPLAY_IMAGE_FETCHING_ORDER = [u'medium', u'original', u'thumb']
TESTS_ENABLED = False
def _activate_testing():
"""
Call this to activate testing in util.py
"""
global TESTS_ENABLED
TESTS_ENABLED = True
common.TESTS_ENABLED = True
def clear_test_buckets():
"""
@ -73,64 +74,64 @@ def clear_test_buckets():
clear_test_template_context()
SETUP_JINJA_ENVS = {}
# SETUP_JINJA_ENVS = {}
def get_jinja_env(template_loader, locale):
"""
Set up the Jinja environment,
# def get_jinja_env(template_loader, locale):
# """
# Set up the Jinja environment,
(In the future we may have another system for providing theming;
for now this is good enough.)
"""
setup_gettext(locale)
# (In the future we may have another system for providing theming;
# for now this is good enough.)
# """
# setup_gettext(locale)
# If we have a jinja environment set up with this locale, just
# return that one.
if SETUP_JINJA_ENVS.has_key(locale):
return SETUP_JINJA_ENVS[locale]
# # If we have a jinja environment set up with this locale, just
# # return that one.
# if SETUP_JINJA_ENVS.has_key(locale):
# return SETUP_JINJA_ENVS[locale]
template_env = jinja2.Environment(
loader=template_loader, autoescape=True,
extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])
# template_env = jinja2.Environment(
# loader=template_loader, autoescape=True,
# extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])
template_env.install_gettext_callables(
mg_globals.translations.ugettext,
mg_globals.translations.ungettext)
# template_env.install_gettext_callables(
# mg_globals.translations.ugettext,
# mg_globals.translations.ungettext)
# All templates will know how to ...
# ... fetch all waiting messages and remove them from the queue
# ... construct a grid of thumbnails or other media
template_env.globals['fetch_messages'] = messages.fetch_messages
template_env.globals['gridify_list'] = gridify_list
template_env.globals['gridify_cursor'] = gridify_cursor
# # All templates will know how to ...
# # ... fetch all waiting messages and remove them from the queue
# # ... construct a grid of thumbnails or other media
# template_env.globals['fetch_messages'] = messages.fetch_messages
# template_env.globals['gridify_list'] = gridify_list
# template_env.globals['gridify_cursor'] = gridify_cursor
if exists(locale):
SETUP_JINJA_ENVS[locale] = template_env
# if exists(locale):
# SETUP_JINJA_ENVS[locale] = template_env
return template_env
# return template_env
# We'll store context information here when doing unit tests
TEMPLATE_TEST_CONTEXT = {}
# # We'll store context information here when doing unit tests
# TEMPLATE_TEST_CONTEXT = {}
def render_template(request, template_path, context):
"""
Render a template with context.
# def render_template(request, template_path, context):
# """
# Render a template with context.
Always inserts the request into the context, so you don't have to.
Also stores the context if we're doing unit tests. Helpful!
"""
template = request.template_env.get_template(
template_path)
context['request'] = request
rendered = template.render(context)
# Always inserts the request into the context, so you don't have to.
# Also stores the context if we're doing unit tests. Helpful!
# """
# template = request.template_env.get_template(
# template_path)
# context['request'] = request
# rendered = template.render(context)
if TESTS_ENABLED:
TEMPLATE_TEST_CONTEXT[template_path] = context
# if TESTS_ENABLED:
# TEMPLATE_TEST_CONTEXT[template_path] = context
return rendered
# return rendered
def clear_test_template_context():
@ -195,18 +196,18 @@ def import_component(import_string):
func = getattr(module, func_name)
return func
_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
# _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
def slugify(text, delim=u'-'):
"""
Generates an ASCII-only slug. Taken from http://flask.pocoo.org/snippets/5/
"""
result = []
for word in _punct_re.split(text.lower()):
word = word.encode('translit/long')
if word:
result.append(word)
return unicode(delim.join(result))
# def slugify(text, delim=u'-'):
# """
# Generates an ASCII-only slug. Taken from http://flask.pocoo.org/snippets/5/
# """
# result = []
# for word in _punct_re.split(text.lower()):
# word = word.encode('translit/long')
# if word:
# result.append(word)
# return unicode(delim.join(result))
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Special email test stuff begins HERE
@ -274,7 +275,7 @@ def send_email(from_addr, to_addrs, subject, message_body):
- subject: subject of the email
- message_body: email body text
"""
if TESTS_ENABLED or mg_globals.app_config['email_debug_mode']:
if common.TESTS_ENABLED or mg_globals.app_config['email_debug_mode']:
mhost = FakeMhost()
elif not mg_globals.app_config['email_debug_mode']:
mhost = smtplib.SMTP(
@ -296,7 +297,7 @@ def send_email(from_addr, to_addrs, subject, message_body):
message['From'] = from_addr
message['To'] = ', '.join(to_addrs)
if TESTS_ENABLED:
if common.TESTS_ENABLED:
EMAIL_TEST_INBOX.append(message)
if mg_globals.app_config['email_debug_mode']:
@ -310,67 +311,67 @@ def send_email(from_addr, to_addrs, subject, message_body):
return mhost.sendmail(from_addr, to_addrs, message.as_string())
###################
# Translation tools
###################
# ###################
# # Translation tools
# ###################
TRANSLATIONS_PATH = pkg_resources.resource_filename(
'mediagoblin', 'i18n')
# TRANSLATIONS_PATH = pkg_resources.resource_filename(
# 'mediagoblin', 'i18n')
def locale_to_lower_upper(locale):
"""
Take a locale, regardless of style, and format it like "en-us"
"""
if '-' in locale:
lang, country = locale.split('-', 1)
return '%s_%s' % (lang.lower(), country.upper())
elif '_' in locale:
lang, country = locale.split('_', 1)
return '%s_%s' % (lang.lower(), country.upper())
else:
return locale.lower()
# def locale_to_lower_upper(locale):
# """
# Take a locale, regardless of style, and format it like "en-us"
# """
# if '-' in locale:
# lang, country = locale.split('-', 1)
# return '%s_%s' % (lang.lower(), country.upper())
# elif '_' in locale:
# lang, country = locale.split('_', 1)
# return '%s_%s' % (lang.lower(), country.upper())
# else:
# return locale.lower()
def locale_to_lower_lower(locale):
"""
Take a locale, regardless of style, and format it like "en_US"
"""
if '_' in locale:
lang, country = locale.split('_', 1)
return '%s-%s' % (lang.lower(), country.lower())
else:
return locale.lower()
# def locale_to_lower_lower(locale):
# """
# Take a locale, regardless of style, and format it like "en_US"
# """
# if '_' in locale:
# lang, country = locale.split('_', 1)
# return '%s-%s' % (lang.lower(), country.lower())
# else:
# return locale.lower()
def get_locale_from_request(request):
"""
Figure out what target language is most appropriate based on the
request
"""
request_form = request.GET or request.POST
# def get_locale_from_request(request):
# """
# Figure out what target language is most appropriate based on the
# request
# """
# request_form = request.GET or request.POST
if request_form.has_key('lang'):
return locale_to_lower_upper(request_form['lang'])
# if request_form.has_key('lang'):
# return locale_to_lower_upper(request_form['lang'])
accept_lang_matches = request.accept_language.best_matches()
# accept_lang_matches = request.accept_language.best_matches()
# Your routing can explicitly specify a target language
matchdict = request.matchdict or {}
# # Your routing can explicitly specify a target language
# matchdict = request.matchdict or {}
if matchdict.has_key('locale'):
target_lang = matchdict['locale']
elif request.session.has_key('target_lang'):
target_lang = request.session['target_lang']
# Pull the first acceptable language
elif accept_lang_matches:
target_lang = accept_lang_matches[0]
# Fall back to English
else:
target_lang = 'en'
# if matchdict.has_key('locale'):
# target_lang = matchdict['locale']
# elif request.session.has_key('target_lang'):
# target_lang = request.session['target_lang']
# # Pull the first acceptable language
# elif accept_lang_matches:
# target_lang = accept_lang_matches[0]
# # Fall back to English
# else:
# target_lang = 'en'
return locale_to_lower_upper(target_lang)
# return locale_to_lower_upper(target_lang)
# A super strict version of the lxml.html cleaner class
@ -424,7 +425,7 @@ def convert_to_tag_list_of_dicts(tag_string):
if tag.strip() and tag.strip() not in [t['name'] for t in taglist]:
taglist.append({'name': tag.strip(),
'slug': slugify(tag.strip())})
'slug': url.slugify(tag.strip())})
return taglist
@ -472,88 +473,88 @@ def cleaned_markdown_conversion(text):
return clean_html(MARKDOWN_INSTANCE.convert(text))
SETUP_GETTEXTS = {}
# SETUP_GETTEXTS = {}
def setup_gettext(locale):
"""
Setup the gettext instance based on this locale
"""
# Later on when we have plugins we may want to enable the
# multi-translations system they have so we can handle plugin
# translations too
# def setup_gettext(locale):
# """
# Setup the gettext instance based on this locale
# """
# # Later on when we have plugins we may want to enable the
# # multi-translations system they have so we can handle plugin
# # translations too
# TODO: fallback nicely on translations from pt_PT to pt if not
# available, etc.
if SETUP_GETTEXTS.has_key(locale):
this_gettext = SETUP_GETTEXTS[locale]
else:
this_gettext = gettext.translation(
'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
if exists(locale):
SETUP_GETTEXTS[locale] = this_gettext
# # TODO: fallback nicely on translations from pt_PT to pt if not
# # available, etc.
# if SETUP_GETTEXTS.has_key(locale):
# this_gettext = SETUP_GETTEXTS[locale]
# else:
# this_gettext = gettext.translation(
# 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
# if exists(locale):
# SETUP_GETTEXTS[locale] = this_gettext
mg_globals.setup_globals(
translations=this_gettext)
# mg_globals.setup_globals(
# translations=this_gettext)
# Force en to be setup before anything else so that
# mg_globals.translations is never None
setup_gettext('en')
# # Force en to be setup before anything else so that
# # mg_globals.translations is never None
# setup_gettext('en')
def pass_to_ugettext(*args, **kwargs):
"""
Pass a translation on to the appropriate ugettext method.
# def pass_to_ugettext(*args, **kwargs):
# """
# Pass a translation on to the appropriate ugettext method.
The reason we can't have a global ugettext method is because
mg_globals gets swapped out by the application per-request.
"""
return mg_globals.translations.ugettext(
*args, **kwargs)
# The reason we can't have a global ugettext method is because
# mg_globals gets swapped out by the application per-request.
# """
# return mg_globals.translations.ugettext(
# *args, **kwargs)
def lazy_pass_to_ugettext(*args, **kwargs):
"""
Lazily pass to ugettext.
# def lazy_pass_to_ugettext(*args, **kwargs):
# """
# Lazily pass to ugettext.
This is useful if you have to define a translation on a module
level but you need it to not translate until the time that it's
used as a string.
"""
return LazyProxy(pass_to_ugettext, *args, **kwargs)
# This is useful if you have to define a translation on a module
# level but you need it to not translate until the time that it's
# used as a string.
# """
# return LazyProxy(pass_to_ugettext, *args, **kwargs)
def pass_to_ngettext(*args, **kwargs):
"""
Pass a translation on to the appropriate ngettext method.
# def pass_to_ngettext(*args, **kwargs):
# """
# Pass a translation on to the appropriate ngettext method.
The reason we can't have a global ngettext method is because
mg_globals gets swapped out by the application per-request.
"""
return mg_globals.translations.ngettext(
*args, **kwargs)
# The reason we can't have a global ngettext method is because
# mg_globals gets swapped out by the application per-request.
# """
# return mg_globals.translations.ngettext(
# *args, **kwargs)
def lazy_pass_to_ngettext(*args, **kwargs):
"""
Lazily pass to ngettext.
# def lazy_pass_to_ngettext(*args, **kwargs):
# """
# Lazily pass to ngettext.
This is useful if you have to define a translation on a module
level but you need it to not translate until the time that it's
used as a string.
"""
return LazyProxy(pass_to_ngettext, *args, **kwargs)
# This is useful if you have to define a translation on a module
# level but you need it to not translate until the time that it's
# used as a string.
# """
# return LazyProxy(pass_to_ngettext, *args, **kwargs)
def fake_ugettext_passthrough(string):
"""
Fake a ugettext call for extraction's sake ;)
# def fake_ugettext_passthrough(string):
# """
# Fake a ugettext call for extraction's sake ;)
In wtforms there's a separate way to define a method to translate
things... so we just need to mark up the text so that it can be
extracted, not so that it's actually run through gettext.
"""
return string
# In wtforms there's a separate way to define a method to translate
# things... so we just need to mark up the text so that it can be
# extracted, not so that it's actually run through gettext.
# """
# return string
PAGINATION_DEFAULT_PER_PAGE = 30
@ -646,33 +647,33 @@ class Pagination(object):
request.path_info, request.GET, page_no)
def gridify_list(this_list, num_cols=5):
"""
Generates a list of lists where each sub-list's length depends on
the number of columns in the list
"""
grid = []
# def gridify_list(this_list, num_cols=5):
# """
# Generates a list of lists where each sub-list's length depends on
# the number of columns in the list
# """
# grid = []
# Figure out how many rows we should have
num_rows = int(ceil(float(len(this_list)) / num_cols))
# # Figure out how many rows we should have
# num_rows = int(ceil(float(len(this_list)) / num_cols))
for row_num in range(num_rows):
slice_min = row_num * num_cols
slice_max = (row_num + 1) * num_cols
# for row_num in range(num_rows):
# slice_min = row_num * num_cols
# slice_max = (row_num + 1) * num_cols
row = this_list[slice_min:slice_max]
# row = this_list[slice_min:slice_max]
grid.append(row)
# grid.append(row)
return grid
# return grid
def gridify_cursor(this_cursor, num_cols=5):
"""
Generates a list of lists where each sub-list's length depends on
the number of columns in the list
"""
return gridify_list(list(this_cursor), num_cols)
# def gridify_cursor(this_cursor, num_cols=5):
# """
# Generates a list of lists where each sub-list's length depends on
# the number of columns in the list
# """
# return gridify_list(list(this_cursor), num_cols)
def render_404(request):