diff --git a/docs/contribute.rst b/docs/contribute.rst index 02af695f..0aaa5771 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -25,6 +25,7 @@ To create the virtualenv environment, you have to do:: Then you would have to install all the dependencies:: $ pip install -r dev_requirements.txt + $ python setup.py develop Running the test suite ====================== diff --git a/docs/settings.rst b/docs/settings.rst index 0fd8652e..d8ce9b8a 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -31,7 +31,8 @@ Setting name (default value) what does it do? `.html`, so you will have to setup URL rewriting on your web server. `DATE_FORMATS` (``{}``) If you do manage multiple languages, you can - set the date formatting here. + set the date formatting here. See "Date format and locales" + section below for details. `DEFAULT_CATEGORY` (``'misc'``) The default category to fallback on. `DEFAULT_DATE_FORMAT` (``'%a %d %B %Y'``) The default date format you want to use. `DISPLAY_PAGES_ON_MENU` (``True``) Display or not the pages on the menu of the @@ -43,7 +44,7 @@ Setting name (default value) what does it do? `JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use. `DELETE_OUTPUT_DIRECTORY` (``False``) Delete the output directory and just the generated files. -`LOCALE` (''[1]_) Change the locale. A list of locales can be provided +`LOCALE` (''[#]_) Change the locale. A list of locales can be provided here or a single string representing one locale. When providing a list, all the locales will be tried until one works. @@ -75,7 +76,7 @@ Setting name (default value) what does it do? section below for more info. ================================================ ===================================================== -.. [1] Default is the system locale. Default is to delete the output directory. +.. [#] Default is the system locale. Default is to delete the output directory. Article permalink structure --------------------------- @@ -119,6 +120,53 @@ timezone. .. _the wikipedia page: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +Date format and locale +---------------------- + +If no DATE_FORMAT is set, failback to DEFAULT_DATE_FORMAT. If you need to +maintain multiple languages with different date format, you can set this dict +using language name( ``lang`` in your posts) as key. About available format +codes, see `strftime document of python`_ : + + DATE_FORMAT = { + 'en': '%a, %d %b %Y', + 'jp': '%Y-%m-%d(%a)', + } + +You can set locale to further control date format: + + LOCALE = ('usa', 'jpn', # On Windows + 'en_US', 'ja_JP' # On Unix/Linux + ) + +Also, it is possible to set different locale settings for each language, if you +put (locale, format) tuple in dict, and this will override the LOCALE setting +above: + + # On Unix/Linux + DATE_FORMAT = { + 'en': ('en_US','%a, %d %b %Y'), + 'jp': ('ja_JP','%Y-%m-%d(%a)'), + } + + # On Windows + DATE_FORMAT = { + 'en': ('usa','%a, %d %b %Y'), + 'jp': ('jpn','%Y-%m-%d(%a)'), + } + +For available list of `locales on Windows` . On Unix/Linux usually you can get +a list of available locales with command ``locale -a``, see manpage `locale(1)` +for help. + + +.. _strftime document of python: http://docs.python.org/library/datetime.html#strftime-strptime-behavior + +.. _locales on Windows: http://msdn.microsoft.com/en-us/library/cdax410z%28VS.71%29.aspx + +.. _locale(1): http://linux.die.net/man/1/locale + Feed settings ============= diff --git a/pelican/contents.py b/pelican/contents.py index bdf3c9f0..f3a692c0 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -15,7 +15,8 @@ class Page(object): """ mandatory_properties = ('title',) - def __init__(self, content, metadata=None, settings=None, filename=None): + def __init__(self, content, metadata=None, settings=None, + filename=None): # init parameters if not metadata: metadata = {} @@ -31,7 +32,7 @@ class Page(object): # set metadata as attributes for key, value in local_metadata.items(): setattr(self, key.lower(), value) - + # default author to the one in settings if not defined if not hasattr(self, 'author'): if 'AUTHOR' in settings: @@ -86,23 +87,23 @@ class Page(object): else: self.date_format = settings['DEFAULT_DATE_FORMAT'] - if isinstance(self.date_format, tuple): - locale.setlocale(locale.LC_ALL, self.date_format[0]) - self.date_format = self.date_format[1] + if isinstance(self.date_format, tuple): + locale.setlocale(locale.LC_ALL, self.date_format[0]) + self.date_format = self.date_format[1] if hasattr(self, 'date'): if platform == 'win32': self.locale_date = self.date.strftime(self.date_format.encode('ascii','xmlcharrefreplace')).decode(stdin.encoding) else: self.locale_date = self.date.strftime(self.date_format.encode('ascii','xmlcharrefreplace')).decode('utf') - + # manage status if not hasattr(self, 'status'): self.status = settings['DEFAULT_STATUS'] if not settings['WITH_FUTURE_DATES']: if hasattr(self, 'date') and self.date > datetime.now(): self.status = 'draft' - + # set summary if not hasattr(self, 'summary'): self.summary = truncate_html_words(self.content, 50) diff --git a/tests/default_conf.py b/tests/default_conf.py index 2796d561..acb7d9da 100755 --- a/tests/default_conf.py +++ b/tests/default_conf.py @@ -2,6 +2,7 @@ AUTHOR = u'Alexis M̩taireau' SITENAME = u"Alexis' log" SITEURL = 'http://blog.notmyidea.org' +TIMEZONE = 'UTC' GITHUB_URL = 'http://github.com/ametaireau/' DISQUS_SITENAME = "blog-notmyidea" diff --git a/tests/test_contents.py b/tests/test_contents.py index df2c00e6..d5648f62 100644 --- a/tests/test_contents.py +++ b/tests/test_contents.py @@ -1,53 +1,100 @@ from __future__ import with_statement -from unittest2 import TestCase +try: + from unittest2 import TestCase +except ImportError, e: + from unittest import TestCase from pelican.contents import Page from pelican.settings import _DEFAULT_CONFIG class TestPage(TestCase): + def setUp(self): + super(TestPage, self).setUp() + self.page_kwargs = { + 'content': 'content', + 'metadata':{ + 'title': 'foo bar', + 'author': 'Blogger', + }, + } + def test_use_args(self): - # creating a page with arguments passed to the connstructor should use - # them to initialise object's attributes - metadata = {'foo': 'bar', 'foobar': 'baz'} + """Creating a page with arguments passed to the constructor should use + them to initialise object's attributes. + + """ + metadata = {'foo': 'bar', 'foobar': 'baz', 'title': 'foobar', } page = Page('content', metadata=metadata) for key, value in metadata.items(): self.assertTrue(hasattr(page, key)) self.assertEqual(value, getattr(page, key)) - self.assertEqual(page.content, "content") + self.assertEqual(page.content, 'content') def test_mandatory_properties(self): - # if the title is not set, must throw an exception - page = Page('content') - with self.assertRaises(NameError) as cm: - page.check_properties() - - page = Page('content', metadata={'title': 'foobar'}) + """If the title is not set, must throw an exception.""" + self.assertRaises(AttributeError, Page, 'content') + page = Page(**self.page_kwargs) page.check_properties() def test_slug(self): - # if a title is given, it should be used to generate the slug - page = Page('content', {'title': 'foobar is foo'}) - self.assertEqual(page.slug, 'foobar-is-foo') + """If a title is given, it should be used to generate the slug.""" + page = Page(**self.page_kwargs) + self.assertEqual(page.slug, 'foo-bar') def test_defaultlang(self): - # if no lang is given, default to the default one - page = Page('content') + """If no lang is given, default to the default one.""" + page = Page(**self.page_kwargs) self.assertEqual(page.lang, _DEFAULT_CONFIG['DEFAULT_LANG']) # it is possible to specify the lang in the metadata infos - page = Page('content', {'lang': 'fr'}) + self.page_kwargs['metadata'].update({'lang': 'fr', }) + page = Page(**self.page_kwargs) self.assertEqual(page.lang, 'fr') def test_save_as(self): - # if a lang is not the default lang, save_as should be set accordingly - page = Page('content', {'title': 'foobar', 'lang': 'fr'}) #default lang is en - self.assertEqual(page.save_as, "foobar-fr.html") + """If a lang is not the default lang, save_as should be set + accordingly. + + """ + # if a title is defined, save_as should be set + page = Page(**self.page_kwargs) + page.save_as = 'foo-bar.html' + + # if a language is defined, save_as should include it accordingly + self.page_kwargs['metadata'].update({'lang': 'fr', }) + page = Page(**self.page_kwargs) + self.assertEqual(page.save_as, "foo-bar-fr.html") + + def test_datetime(self): + """If DATETIME is set to a tuple, it should be used to override LOCALE + """ + from datetime import datetime + from sys import platform + dt = datetime(2015,9,13) + # make a deep copy of page_kawgs + page_kwargs = {key:self.page_kwargs[key] for key in self.page_kwargs} + for key in page_kwargs: + if not isinstance(page_kwargs[key], dict): break + page_kwargs[key] = {subkey:page_kwargs[key][subkey] for subkey in page_kwargs[key]} + # set its date to dt + page_kwargs['metadata']['date'] = dt + page = Page( **page_kwargs) + + self.assertEqual(page.locale_date, dt.strftime(_DEFAULT_CONFIG['DEFAULT_DATE_FORMAT'])) + + + page_kwargs['settings'] = {x:_DEFAULT_CONFIG[x] for x in _DEFAULT_CONFIG} + # I doubt this can work on all platforms ... + if platform == "win32": + locale = 'jpn' + else: + locale = 'ja_JP' + page_kwargs['settings']['DATE_FORMATS'] = {'jp':(locale,'%Y-%m-%d(%a)')} + page_kwargs['metadata']['lang'] = 'jp' + page = Page( **page_kwargs) + self.assertEqual(page.locale_date, u'2015-09-13(\u65e5)') + # above is unicode in Japanese: 2015-09-13(Ҝ) + - # otherwise, if a title is defined, save_as should be set - page = Page('content', {'title': 'foobar'}) - page.save_as = 'foobar.html' - # if no title is given, there is no save_as - page = Page('content') - self.assertFalse(hasattr(page, 'save_as')) diff --git a/tests/test_readers.py b/tests/test_readers.py index bf7504fb..211fb9be 100644 --- a/tests/test_readers.py +++ b/tests/test_readers.py @@ -1,5 +1,9 @@ # coding: utf-8 -import unittest2 +try: + import unittest2 +except ImportError, e: + import unittest as unittest2 + import os import datetime from pelican import readers diff --git a/tests/test_settings.py b/tests/test_settings.py index e32fcef4..571f66a1 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,4 +1,8 @@ -import unittest2 +try: + import unittest2 +except ImportError, e: + import unittest as unittest2 + from os.path import dirname, abspath, join from pelican.settings import read_settings, _DEFAULT_CONFIG