contents: Convert StaticContent to Static, a Page subclass

Static needs a lot of the same handling as other pages, so make it a
subclass of Page.  The rename from StaticContent to Static makes for
cleaner configuration settings (STATIC_URL instead of
STATICCONTENT_URL).

All currently generated Static instances override the save_as
attribute explicitly on initialization, but it isn't hard to imagine
wanting to adjust STATIC file output based on metadata (e.g. extracted
from their source filename).  With this union, the framework for
manipulating URLs and filenames is shared between all source file
types.
This commit is contained in:
W. Trevor King 2013-01-04 13:54:08 -05:00 committed by Alexis Métaireau
commit 49bf80ec39
3 changed files with 109 additions and 27 deletions

View file

@ -85,8 +85,7 @@ class Content(object):
if not hasattr(self, 'slug') and hasattr(self, 'title'):
self.slug = slugify(self.title)
if source_path:
self.source_path = source_path
self.source_path = source_path
# manage the date format
if not hasattr(self, 'date_format'):
@ -119,6 +118,14 @@ class Content(object):
signals.content_object_init.send(self)
def __str__(self):
if self.source_path is None:
return repr(self)
elif six.PY3:
return self.source_path or repr(self)
else:
return str(self.source_path.encode('utf-8', 'replace'))
def check_properties(self):
"""Test mandatory properties are set."""
for prop in self.mandatory_properties:
@ -130,6 +137,7 @@ class Content(object):
"""Returns the URL, formatted with the proper values"""
metadata = copy.copy(self.metadata)
metadata.update({
'path': self.metadata.get('path', self.get_relative_source_path()),
'slug': getattr(self, 'slug', ''),
'lang': getattr(self, 'lang', 'en'),
'date': getattr(self, 'date', datetime.now()),
@ -250,6 +258,8 @@ class Content(object):
"""
if not source_path:
source_path = self.source_path
if source_path is None:
return None
return os.path.relpath(
os.path.abspath(os.path.join(self.settings['PATH'], source_path)),
@ -279,26 +289,88 @@ class Quote(Page):
@python_2_unicode_compatible
class StaticContent(object):
@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 Static(Page):
@deprecated_attribute(old='filepath', new='source_path', since=(3, 2, 0))
def filepath():
return None
def __init__(self, src, dst=None, settings=None):
if not settings:
settings = copy.deepcopy(_DEFAULT_CONFIG)
self.src = src
self.url = dst or src
@deprecated_attribute(old='src', new='source_path', since=(3, 2, 0))
def src():
return None
# On Windows, make sure we end up with Unix-like paths.
if os.name == 'nt':
self.url = self.url.replace('\\', '/')
self.source_path = os.path.join(settings['PATH'], src)
self.save_as = os.path.join(settings['OUTPUT_PATH'], self.url)
def __str__(self):
return self.source_path
@deprecated_attribute(old='dst', new='save_as', since=(3, 2, 0))
def dst():
return None
def is_valid_content(content, f):

View file

@ -20,7 +20,7 @@ from jinja2 import (
)
from pelican.contents import (
Article, Page, Category, StaticContent, is_valid_content
Article, Page, Category, Static, is_valid_content
)
from pelican.readers import read_file
from pelican.utils import copy, process_translations, mkdir_p
@ -122,8 +122,7 @@ class Generator(object):
return files
def add_source_path(self, content):
location = os.path.relpath(os.path.abspath(content.source_path),
os.path.abspath(self.path))
location = content.get_relative_source_path()
self.context['filenames'][location] = content
def _update_context(self, items):
@ -523,23 +522,32 @@ class StaticGenerator(Generator):
if os.name == 'nt':
f_rel = f_rel.replace('\\', '/')
# TODO remove this hardcoded 'static' subdirectory
sc = StaticContent(f_rel, os.path.join('static', f_rel),
settings=self.settings)
sc = Static(
content=None,
metadata={'save_as': os.path.join('static', f_rel)},
settings=self.settings,
source_path=f_rel)
self.staticfiles.append(sc)
self.context['filenames'][f_rel] = sc
self.add_source_path(sc)
# same thing for FILES_TO_COPY
for src, dest in self.settings['FILES_TO_COPY']:
sc = StaticContent(src, dest, settings=self.settings)
sc = Static(
content=None,
metadata={'save_as': dest},
settings=self.settings,
source_path=src)
self.staticfiles.append(sc)
self.context['filenames'][src] = sc
self.add_source_path(sc)
def generate_output(self, writer):
self._copy_paths(self.settings['THEME_STATIC_PATHS'], self.theme,
'theme', self.output_path, '.')
# copy all StaticContent files
# copy all Static files
for sc in self.staticfiles:
mkdir_p(os.path.dirname(sc.save_as))
shutil.copy(sc.source_path, sc.save_as)
source_path = os.path.join(self.path, sc.source_path)
save_as = os.path.join(self.output_path, sc.save_as)
mkdir_p(os.path.dirname(save_as))
shutil.copy(source_path, save_as)
logger.info('copying {} to {}'.format(sc.source_path, sc.save_as))

View file

@ -52,6 +52,8 @@ _DEFAULT_CONFIG = {'PATH': '.',
'PAGE_SAVE_AS': 'pages/{slug}.html',
'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',
'PAGE_LANG_SAVE_AS': 'pages/{slug}-{lang}.html',
'STATIC_URL': '{path}',
'STATIC_SAVE_AS': '{path}',
'CATEGORY_URL': 'category/{slug}.html',
'CATEGORY_SAVE_AS': 'category/{slug}.html',
'TAG_URL': 'tag/{slug}.html',