Merge pull request #860 from avaris/strftime-jinja-filter

Fix for #701: adds a 'strftime' jinja fiter that uses LOCALE
This commit is contained in:
Justin Mayer 2013-04-22 20:01:27 -07:00
commit be511c9ac2
5 changed files with 129 additions and 2 deletions

View file

@ -5,6 +5,7 @@ python:
before_install: before_install:
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -qq --no-install-recommends asciidoc - sudo apt-get install -qq --no-install-recommends asciidoc
- sudo locale-gen fr_FR.UTF-8 tr_TR.UTF-8
install: install:
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then ln -s /usr/share/asciidoc/asciidocapi.py ~/virtualenv/python2.7/lib/python2.7/site-packages/; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then ln -s /usr/share/asciidoc/asciidocapi.py ~/virtualenv/python2.7/lib/python2.7/site-packages/; fi
- pip install mock --use-mirrors - pip install mock --use-mirrors

View file

@ -78,7 +78,7 @@ Sorting
------- -------
URL wrappers (currently categories, tags, and authors), have URL wrappers (currently categories, tags, and authors), have
comparison methods that allow them to be easily sorted by name: comparison methods that allow them to be easily sorted by name::
{% for tag, articles in tags|sort %} {% for tag, articles in tags|sort %}
@ -87,6 +87,24 @@ command`__ has a number of options.
__ http://jinja.pocoo.org/docs/templates/#sort __ http://jinja.pocoo.org/docs/templates/#sort
Date Formatting
---------------
Pelican formats the date with according to your settings and locale
(``DATE_FORMATS``/``DEFAULT_DATE_FORMAT``) and provides a
``locale_date`` attribute. On the other hand, ``date`` attribute will
be a `datetime`_ object. If you need custom formatting for a date
different than your settings, use the Jinja filter ``strftime``
that comes with Pelican. Usage is same as Python `strftime`_ format,
but the filter will do the right thing and format your date according
to the locale given in your settings::
{{ article.date|strftime('%d %B %Y') }}
.. _datetime: http://docs.python.org/2/library/datetime.html#datetime-objects
.. _strftime: http://docs.python.org/2/library/datetime.html#strftime-strptime-behavior
index.html index.html
---------- ----------

View file

@ -23,7 +23,7 @@ from pelican.contents import (
Article, Page, Category, Static, is_valid_content Article, Page, Category, Static, is_valid_content
) )
from pelican.readers import read_file from pelican.readers import read_file
from pelican.utils import copy, process_translations, mkdir_p from pelican.utils import copy, process_translations, mkdir_p, DateFormatter
from pelican import signals from pelican import signals
import pelican.utils import pelican.utils
@ -65,6 +65,9 @@ class Generator(object):
logger.debug('template list: {0}'.format(self.env.list_templates())) logger.debug('template list: {0}'.format(self.env.list_templates()))
# provide utils.strftime as a jinja filter
self.env.filters.update({'strftime': DateFormatter()})
# get custom Jinja filters from user settings # get custom Jinja filters from user settings
custom_filters = self.settings.get('JINJA_FILTERS', {}) custom_filters = self.settings.get('JINJA_FILTERS', {})
self.env.filters.update(custom_filters) self.env.filters.update(custom_filters)

View file

@ -7,7 +7,11 @@ import datetime
import time import time
import locale import locale
from sys import platform from sys import platform
from tempfile import mkdtemp
from pelican.generators import TemplatePagesGenerator
from pelican.writers import Writer
from pelican.settings import read_settings
from pelican import utils from pelican import utils
from .support import get_article, LoggedTestCase, locale_available, unittest from .support import get_article, LoggedTestCase, locale_available, unittest
@ -283,3 +287,84 @@ class TestUtils(LoggedTestCase):
# restore locale back # restore locale back
locale.setlocale(locale.LC_TIME, old_locale) locale.setlocale(locale.LC_TIME, old_locale)
class TestDateFormatter(unittest.TestCase):
'''Tests that the output of DateFormatter jinja filter is same as
utils.strftime'''
def setUp(self):
# prepare a temp content and output folder
self.temp_content = mkdtemp(prefix='pelicantests.')
self.temp_output = mkdtemp(prefix='pelicantests.')
# prepare a template file
template_dir = os.path.join(self.temp_content, 'template')
template_path = os.path.join(template_dir, 'source.html')
os.makedirs(template_dir)
with open(template_path, 'w') as template_file:
template_file.write('date = {{ date|strftime("%A, %d %B %Y") }}')
self.date = datetime.date(2012, 8, 29)
def tearDown(self):
shutil.rmtree(self.temp_content)
shutil.rmtree(self.temp_output)
# reset locale to default
locale.setlocale(locale.LC_ALL, '')
@unittest.skipUnless(locale_available('fr_FR.UTF-8') or
locale_available('French'),
'French locale needed')
def test_french_locale(self):
settings = read_settings(
override = {'LOCALE': locale.normalize('fr_FR.UTF-8'),
'TEMPLATE_PAGES': {'template/source.html':
'generated/file.html'}})
generator = TemplatePagesGenerator({'date': self.date}, settings,
self.temp_content, '', self.temp_output, None)
generator.env.filters.update({'strftime': utils.DateFormatter()})
writer = Writer(self.temp_output, settings=settings)
generator.generate_output(writer)
output_path = os.path.join(
self.temp_output, 'generated', 'file.html')
# output file has been generated
self.assertTrue(os.path.exists(output_path))
# output content is correct
with utils.pelican_open(output_path) as output_file:
self.assertEqual(output_file,
utils.strftime(self.date, 'date = %A, %d %B %Y'))
@unittest.skipUnless(locale_available('tr_TR.UTF-8') or
locale_available('Turkish'),
'Turkish locale needed')
def test_turkish_locale(self):
settings = read_settings(
override = {'LOCALE': locale.normalize('tr_TR.UTF-8'),
'TEMPLATE_PAGES': {'template/source.html':
'generated/file.html'}})
generator = TemplatePagesGenerator({'date': self.date}, settings,
self.temp_content, '', self.temp_output, None)
generator.env.filters.update({'strftime': utils.DateFormatter()})
writer = Writer(self.temp_output, settings=settings)
generator.generate_output(writer)
output_path = os.path.join(
self.temp_output, 'generated', 'file.html')
# output file has been generated
self.assertTrue(os.path.exists(output_path))
# output content is correct
with utils.pelican_open(output_path) as output_file:
self.assertEqual(output_file,
utils.strftime(self.date, 'date = %A, %d %B %Y'))

View file

@ -65,6 +65,26 @@ def strftime(date, date_format):
return template % tuple(formatted_candidates) return template % tuple(formatted_candidates)
class DateFormatter(object):
'''A date formatter object used as a jinja filter
Uses the `strftime` implementation and makes sure jinja uses the locale
defined in LOCALE setting
'''
def __init__(self):
self.locale = locale.setlocale(locale.LC_TIME)
def __call__(self, date, date_format):
old_locale = locale.setlocale(locale.LC_TIME)
locale.setlocale(locale.LC_TIME, self.locale)
formatted = strftime(date, date_format)
locale.setlocale(locale.LC_TIME, old_locale)
return formatted
def python_2_unicode_compatible(klass): def python_2_unicode_compatible(klass):
""" """
A decorator that defines __unicode__ and __str__ methods under Python 2. A decorator that defines __unicode__ and __str__ methods under Python 2.