Some doc + various enhancements

This commit is contained in:
Alexis Métaireau 2013-03-10 20:11:36 -07:00
commit 14cf5f014c
5 changed files with 146 additions and 118 deletions

View file

@ -13,34 +13,36 @@ import sys
from datetime import datetime
from pelican.settings import _DEFAULT_CONFIG
from pelican.utils import (slugify, truncate_html_words, memoized,
python_2_unicode_compatible, deprecated_attribute)
from pelican import signals
import pelican.utils
from pelican.settings import _DEFAULT_CONFIG
from pelican.utils import (slugify, truncate_html_words, memoized, strftime,
python_2_unicode_compatible, deprecated_attribute)
# Import these so that they're avalaible when you import from pelican.contents.
from pelican.urlwrappers import (URLWrapper, Author, Category, Tag) # NOQA
logger = logging.getLogger(__name__)
class Page(object):
"""Represents a page
Given a content, and metadata, create an adequate object.
class Content(object):
"""Represents a content.
:param content: the string to parse, containing the original content.
"""
mandatory_properties = ('title',)
default_template = 'page'
:param metadata: the metadata associated to this page (optional).
:param settings: the settings dictionary (optional).
:param source_path: The location of the source of this content (if any).
:param context: The shared context between generators.
"""
@deprecated_attribute(old='filename', new='source_path', since=(3, 2, 0))
def filename():
return None
def __init__(self, content, metadata=None, settings=None,
source_path=None, context=None):
# init parameters
if not metadata:
if metadata is None:
metadata = {}
if not settings:
if settings is None:
settings = copy.deepcopy(_DEFAULT_CONFIG)
self.settings = settings
@ -68,6 +70,8 @@ class Page(object):
if 'AUTHOR' in settings:
self.author = Author(settings['AUTHOR'], settings)
# XXX Split all the following code into pieces, there is too much here.
# manage languages
self.in_default_lang = True
if 'DEFAULT_LANG' in settings:
@ -100,8 +104,7 @@ class Page(object):
self.date_format = self.date_format[1]
if hasattr(self, 'date'):
self.locale_date = pelican.utils.strftime(self.date,
self.date_format)
self.locale_date = strftime(self.date, self.date_format)
# manage status
if not hasattr(self, 'status'):
@ -117,13 +120,14 @@ class Page(object):
signals.content_object_init.send(self)
def check_properties(self):
"""test that each mandatory property is set."""
"""Test mandatory properties are set."""
for prop in self.mandatory_properties:
if not hasattr(self, prop):
raise NameError(prop)
@property
def url_format(self):
"""Returns the URL, formatted with the proper values"""
metadata = copy.copy(self.metadata)
metadata.update({
'slug': getattr(self, 'slug', ''),
@ -146,12 +150,14 @@ class Page(object):
return self._expand_settings(key)
def _update_content(self, content, siteurl):
"""Change all the relative paths of the content to relative paths
"""Update the content attribute.
Change all the relative paths of the content to relative paths
suitable for the ouput content.
:param content: content resource that will be passed to the templates.
:param siteurl: siteurl which is locally generated by the writer in
case of RELATIVE_URLS.
case of RELATIVE_URLS.
"""
hrefs = re.compile(r"""
(?P<markup><\s*[^\>]* # match tag with src and href attr
@ -165,9 +171,12 @@ class Page(object):
what = m.group('what')
value = m.group('value')
origin = m.group('path')
# we support only filename for now. the plan is to support
# categories, tags, etc. in the future, but let's keep things
# simple for now.
# XXX Put this in a different location.
if what == 'filename':
if value.startswith('/'):
value = value[1:]
@ -191,18 +200,23 @@ class Page(object):
@memoized
def get_content(self, siteurl):
return self._update_content(
self._get_content() if hasattr(self, "_get_content")
else self._content,
siteurl)
if hasattr(self, '_get_content'):
content = self._get_content()
else:
content = self._content
return self._update_content(content, siteurl)
@property
def content(self):
return self.get_content(self._context['localsiteurl'])
def _get_summary(self):
"""Returns the summary of an article, based on the summary metadata
if it is set, else truncate the content."""
"""Returns the summary of an article.
This is based on the summary metadata if set, otherwise truncate the
content.
"""
if hasattr(self, '_summary'):
return self._summary
@ -217,7 +231,6 @@ class Page(object):
summary = property(_get_summary, _set_summary, "Summary of the article."
"Based on the content. Can't be set")
url = property(functools.partial(get_url_setting, key='url'))
save_as = property(functools.partial(get_url_setting, key='save_as'))
@ -250,6 +263,11 @@ class Page(object):
)
class Page(Content):
mandatory_properties = ('title',)
default_template = 'page'
class Article(Page):
mandatory_properties = ('title', 'date', 'category')
default_template = 'article'
@ -259,78 +277,9 @@ class Quote(Page):
base_properties = ('author', 'date')
@python_2_unicode_compatible
@functools.total_ordering
class URLWrapper(object):
def __init__(self, name, settings):
self.name = name
self.slug = slugify(self.name)
self.settings = settings
def as_dict(self):
return self.__dict__
def __hash__(self):
return hash(self.name)
def _key(self):
return self.name
def _normalize_key(self, key):
return six.text_type(key)
def __eq__(self, other):
return self._key() == self._normalize_key(other)
def __ne__(self, other):
return self._key() != self._normalize_key(other)
def __lt__(self, other):
return self._key() < self._normalize_key(other)
def __str__(self):
return self.name
def _from_settings(self, key, get_page_name=False):
"""Returns URL information as defined in settings.
When get_page_name=True returns URL without anything after {slug} e.g.
if in settings: CATEGORY_URL="cat/{slug}.html" this returns
"cat/{slug}" Useful for pagination.
"""
setting = "%s_%s" % (self.__class__.__name__.upper(), key)
value = self.settings[setting]
if not isinstance(value, six.string_types):
logger.warning('%s is set to %s' % (setting, value))
return value
else:
if get_page_name:
return os.path.splitext(value)[0].format(**self.as_dict())
else:
return value.format(**self.as_dict())
page_name = property(functools.partial(_from_settings, key='URL',
get_page_name=True))
url = property(functools.partial(_from_settings, key='URL'))
save_as = property(functools.partial(_from_settings, key='SAVE_AS'))
class Category(URLWrapper):
pass
class Tag(URLWrapper):
def __init__(self, name, *args, **kwargs):
super(Tag, self).__init__(name.strip(), *args, **kwargs)
class Author(URLWrapper):
pass
@python_2_unicode_compatible
class StaticContent(object):
@deprecated_attribute(old='filepath', new='source_path', since=(3, 2, 0))
def filepath():
return None
@ -340,6 +289,7 @@ class StaticContent(object):
settings = copy.deepcopy(_DEFAULT_CONFIG)
self.src = src
self.url = dst or src
# On Windows, make sure we end up with Unix-like paths.
if os.name == 'nt':
self.url = self.url.replace('\\', '/')
@ -355,6 +305,6 @@ def is_valid_content(content, f):
content.check_properties()
return True
except NameError as e:
logger.warning("Skipping %s: impossible to find informations about "
"'%s'" % (f, e))
logger.error("Skipping %s: impossible to find informations about "
"'%s'" % (f, e))
return False