diff --git a/pelican/contents.py b/pelican/contents.py index dc05dae4..30477493 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from pelican.utils import slugify, truncate_html_words from pelican.log import * +from pelican.settings import _DEFAULT_CONFIG class Page(object): """Represents a page @@ -10,31 +11,45 @@ class Page(object): """ mandatory_properties = ('title',) - def __init__(self, content, metadata={}, settings={}, filename=None): + def __init__(self, content, metadata=None, settings=None, filename=None): + # init parameters + if not metadata: + metadata = {} + if not settings: + settings = _DEFAULT_CONFIG + self._content = content self.translations = [] self.status = "published" # default value - local_metadata = dict(settings['DEFAULT_METADATA']) + local_metadata = dict(settings.get('DEFAULT_METADATA', ())) local_metadata.update(metadata) + + # 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: self.author = settings['AUTHOR'] - default_lang = settings.get('DEFAULT_LANG').lower() - if not hasattr(self, 'lang'): - self.lang = default_lang + # manage languages + self.in_default_lang = True + if 'DEFAULT_LANG' in settings: + default_lang = settings['DEFAULT_LANG'].lower() + if not hasattr(self, 'lang'): + self.lang = default_lang - self.in_default_lang = (self.lang == default_lang) + self.in_default_lang = (self.lang == default_lang) - if not hasattr(self, 'slug'): + # create the slug if not existing, fro mthe title + if not hasattr(self, 'slug') and hasattr(self, 'title'): self.slug = slugify(self.title) - if not hasattr(self, 'save_as'): + # create save_as from the slug (+lang) + if not hasattr(self, 'save_as') and hasattr(self, 'slug'): if self.in_default_lang: self.save_as = '%s.html' % self.slug clean_url = '%s/' % self.slug @@ -42,16 +57,18 @@ class Page(object): self.save_as = '%s-%s.html' % (self.slug, self.lang) clean_url = '%s-%s/' % (self.slug, self.lang) + # change the save_as regarding the settings if settings.get('CLEAN_URLS', False): self.url = clean_url - else: + elif hasattr(self, 'save_as'): self.url = self.save_as if filename: self.filename = filename + # manage the date format if not hasattr(self, 'date_format'): - if self.lang in settings['DATE_FORMATS']: + if hasattr(self, 'lang') and self.lang in settings['DATE_FORMATS']: self.date_format = settings['DATE_FORMATS'][self.lang] else: self.date_format = settings['DEFAULT_DATE_FORMAT'] @@ -59,15 +76,14 @@ class Page(object): if hasattr(self, 'date'): self.locale_date = self.date.strftime(self.date_format.encode('ascii','xmlcharrefreplace')).decode('utf') + # manage summary if not hasattr(self, 'summary'): self.summary = property(lambda self: truncate_html_words(self.content, 50)).__get__(self, Page) + # manage status if not hasattr(self, 'status'): self.status = settings['DEFAULT_STATUS'] - # store the settings ref. - self._settings = settings - def check_properties(self): """test that each mandatory property is set.""" for prop in self.mandatory_properties: diff --git a/pelican/settings.py b/pelican/settings.py index a63cec3f..55577d84 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -2,10 +2,10 @@ import os import locale -_DEFAULT_THEME = os.sep.join([os.path.dirname(os.path.abspath(__file__)), +DEFAULT_THEME = os.sep.join([os.path.dirname(os.path.abspath(__file__)), "themes/notmyidea"]) _DEFAULT_CONFIG = {'PATH': None, - 'THEME': _DEFAULT_THEME, + 'THEME': DEFAULT_THEME, 'OUTPUT_PATH': 'output/', 'MARKUP': ('rst', 'md'), 'STATIC_PATHS': ['images',], @@ -40,7 +40,7 @@ _DEFAULT_CONFIG = {'PATH': None, 'DEFAULT_METADATA': (), 'FILES_TO_COPY': (), 'DEFAULT_STATUS': 'published', - } + } def read_settings(filename): """Load a Python file into a dictionary. diff --git a/pelican/tests/__init__.py b/pelican/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pelican/tests/test_contents.py b/pelican/tests/test_contents.py new file mode 100644 index 00000000..d013da2f --- /dev/null +++ b/pelican/tests/test_contents.py @@ -0,0 +1,52 @@ +from unittest2 import TestCase + +from pelican.contents import Page +from pelican.settings import _DEFAULT_CONFIG + +class TestPage(TestCase): + + 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'} + 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") + + 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'}) + 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') + + def test_defaultlang(self): + # if no lang is given, default to the default one + page = Page('content') + 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.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") + + # 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/pelican/tests/test_settings.py b/pelican/tests/test_settings.py new file mode 100644 index 00000000..39680a9f --- /dev/null +++ b/pelican/tests/test_settings.py @@ -0,0 +1,34 @@ +from unittest2 import TestCase +import os + +from pelican.settings import read_settings, _DEFAULT_CONFIG + +SETTINGS = os.sep.join([os.path.dirname(os.path.abspath(__file__)), + "../../samples/pelican.conf.py"]) + +class SettingsTest(TestCase): + + + def test_read_settings(self): + # providing a file, it should read it, replace the default values and append + # new values to the settings, if any + settings = read_settings(SETTINGS) + + # overwrite existing settings + self.assertEqual(settings.get('SITENAME'), u"Alexis' log") + + # add new settings + self.assertEqual(settings.get('SITEURL'), 'http://blog.notmyidea.org') + + # keep default settings if not defined + self.assertEqual(settings.get('DEFAULT_CATEGORY'), + _DEFAULT_CONFIG['DEFAULT_CATEGORY']) + + # do not copy keys not in caps + self.assertNotIn('foobar', settings) + + + def test_empty_read_settings(self): + # providing no file should return the default values + settings = read_settings(None) + self.assertDictEqual(settings, _DEFAULT_CONFIG) diff --git a/samples/pelican.conf.py b/samples/pelican.conf.py index 2cb9df27..a3a07fad 100755 --- a/samples/pelican.conf.py +++ b/samples/pelican.conf.py @@ -14,11 +14,11 @@ FEED_RSS = 'feeds/all.rss.xml' CATEGORY_FEED_RSS = 'feeds/%s.rss.xml' LINKS = (('Biologeek', 'http://biologeek.org'), - ('Filyb', "http://filyb.info/"), - ('Libert-fr', "http://www.libert-fr.com"), - ('N1k0', "http://prendreuncafe.com/blog/"), - (u'Tarek Ziadé', "http://ziade.org/blog"), - ('Zubin Mithra', "http://zubin71.wordpress.com/"),) + ('Filyb', "http://filyb.info/"), + ('Libert-fr', "http://www.libert-fr.com"), + ('N1k0', "http://prendreuncafe.com/blog/"), + (u'Tarek Ziadé', "http://ziade.org/blog"), + ('Zubin Mithra', "http://zubin71.wordpress.com/"),) SOCIAL = (('twitter', 'http://twitter.com/ametaireau'), ('lastfm', 'http://lastfm.com/user/akounet'), @@ -32,3 +32,7 @@ STATIC_PATHS = ["pictures",] # A list of files to copy from the source to the destination FILES_TO_COPY = (('extra/robots.txt', 'robots.txt'),) + +# foobar will not be used, because it's not in caps. All configuration keys +# have to be in caps +foobar = "barbaz"