mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Merge branch 'master' of https://github.com/ametaireau/pelican
This commit is contained in:
commit
5435c55f3e
22 changed files with 164 additions and 102 deletions
|
|
@ -6,3 +6,8 @@ install:
|
|||
- pip install nose unittest2 mock --use-mirrors
|
||||
- pip install . --use-mirrors
|
||||
script: nosetests -s tests
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.org#pelican"
|
||||
on_success: change
|
||||
|
|
|
|||
|
|
@ -2,4 +2,3 @@ include *.rst
|
|||
global-include *.py
|
||||
recursive-include pelican *.html *.css *png
|
||||
include LICENSE
|
||||
global-include *.bat
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import sys, os
|
||||
|
||||
sys.path.append(os.path.abspath('..'))
|
||||
|
||||
from pelican import __version__, __major__
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
templates_path = ['_templates']
|
||||
extensions = ['sphinx.ext.autodoc',]
|
||||
|
|
@ -9,12 +13,11 @@ master_doc = 'index'
|
|||
project = u'Pelican'
|
||||
copyright = u'2010, Alexis Metaireau and contributors'
|
||||
exclude_patterns = ['_build']
|
||||
version = "2"
|
||||
release = version
|
||||
version = __version__
|
||||
release = __major__
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
sys.path.append(os.path.abspath('_themes'))
|
||||
html_theme_path = ['_themes']
|
||||
html_theme = 'pelican'
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Setting name (default value) What does it do?
|
|||
`MARKUP` (``('rst', 'md')``) A list of available markup languages you want
|
||||
to use. For the moment, the only available values
|
||||
are `rst` and `md`.
|
||||
`MD_EXTENSIONS` (``('codehilite','extra')``) A list of the extensions that the Markdown processor
|
||||
`MD_EXTENSIONS` (``['codehilite','extra']``) A list of the extensions that the Markdown processor
|
||||
will use. Refer to the extensions chapter in the
|
||||
Python-Markdown documentation for a complete list of
|
||||
supported extensions.
|
||||
|
|
@ -83,7 +83,7 @@ Setting name (default value) What does it do?
|
|||
.. [#] Default is the system locale.
|
||||
|
||||
|
||||
URL Settings
|
||||
URL settings
|
||||
------------
|
||||
|
||||
You can customize the URL's and locations where files will be saved. The URL's and
|
||||
|
|
@ -160,6 +160,8 @@ maintain multiple languages with different date formats, you can set this dict
|
|||
using language name (``lang`` in your posts) as key. Regarding available format
|
||||
codes, see `strftime document of python`_ :
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
DATE_FORMAT = {
|
||||
'en': '%a, %d %b %Y',
|
||||
'jp': '%Y-%m-%d(%a)',
|
||||
|
|
@ -167,6 +169,8 @@ codes, see `strftime document of python`_ :
|
|||
|
||||
You can set locale to further control date format:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
LOCALE = ('usa', 'jpn', # On Windows
|
||||
'en_US', 'ja_JP' # On Unix/Linux
|
||||
)
|
||||
|
|
@ -175,6 +179,7 @@ Also, it is possible to set different locale settings for each language. If you
|
|||
put (locale, format) tuples in the dict, this will override the LOCALE setting
|
||||
above:
|
||||
|
||||
.. parsed-literal::
|
||||
# On Unix/Linux
|
||||
DATE_FORMAT = {
|
||||
'en': ('en_US','%a, %d %b %Y'),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ from pelican.utils import clean_output_dir, files_changed
|
|||
from pelican.writers import Writer
|
||||
from pelican import log
|
||||
|
||||
__version__ = "3.0"
|
||||
__major__ = 3
|
||||
__minor__ = 0
|
||||
__version__ = "{0}.{1}".format(__major__, __minor__)
|
||||
|
||||
|
||||
class Pelican(object):
|
||||
|
|
@ -135,7 +137,8 @@ class Pelican(object):
|
|||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="""A tool to generate a
|
||||
static blog, with restructured text input files.""")
|
||||
static blog, with restructured text input files.""",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
|
||||
parser.add_argument(dest='path', nargs='?',
|
||||
help='Path where to find the content files.')
|
||||
|
|
@ -145,11 +148,11 @@ def main():
|
|||
parser.add_argument('-o', '--output', dest='output',
|
||||
help='Where to output the generated files. If not specified, a '
|
||||
'directory will be created, named "output" in the current path.')
|
||||
parser.add_argument('-m', '--markup', default=None, dest='markup',
|
||||
parser.add_argument('-m', '--markup', dest='markup',
|
||||
help='The list of markup language to use (rst or md). Please indicate '
|
||||
'them separated by commas.')
|
||||
parser.add_argument('-s', '--settings', dest='settings', default='',
|
||||
help='The settings of the application. Default to False.')
|
||||
parser.add_argument('-s', '--settings', dest='settings',
|
||||
help='The settings of the application.')
|
||||
parser.add_argument('-d', '--delete-output-directory',
|
||||
dest='delete_outputdir',
|
||||
action='store_true', help='Delete the output directory.')
|
||||
|
|
|
|||
|
|
@ -42,9 +42,10 @@ class Page(object):
|
|||
if 'AUTHOR' in settings:
|
||||
self.author = Author(settings['AUTHOR'], settings)
|
||||
else:
|
||||
title = filename.decode('utf-8') if filename else self.title
|
||||
self.author = Author(getenv('USER', 'John Doe'), settings)
|
||||
warning(u"Author of `{0}' unknown, assuming that his name is "
|
||||
"`{1}'".format(filename or self.title, self.author))
|
||||
"`{1}'".format(title, self.author))
|
||||
|
||||
# manage languages
|
||||
self.in_default_lang = True
|
||||
|
|
@ -89,9 +90,9 @@ class Page(object):
|
|||
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)
|
||||
# store the summary metadata if it is set
|
||||
if 'summary' in metadata:
|
||||
self._summary = metadata['summary']
|
||||
|
||||
def check_properties(self):
|
||||
"""test that each mandatory property is set."""
|
||||
|
|
@ -126,8 +127,12 @@ class Page(object):
|
|||
return content
|
||||
|
||||
def _get_summary(self):
|
||||
"""Returns the summary of an article, based on to the content"""
|
||||
return truncate_html_words(self.content, 50)
|
||||
"""Returns the summary of an article, based on the summary metadata
|
||||
if it is set, else troncate the content."""
|
||||
if hasattr(self, '_summary'):
|
||||
return self._summary
|
||||
else:
|
||||
return truncate_html_words(self.content, 50)
|
||||
|
||||
def _set_summary(self, summary):
|
||||
"""Dummy function"""
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ class ArticlesGenerator(Generator):
|
|||
continue
|
||||
|
||||
# if no category is set, use the name of the path as a category
|
||||
if 'category' not in metadata.keys():
|
||||
if 'category' not in metadata:
|
||||
|
||||
if os.path.dirname(f) == self.path:
|
||||
category = self.settings['DEFAULT_CATEGORY']
|
||||
|
|
@ -238,8 +238,7 @@ class ArticlesGenerator(Generator):
|
|||
if category != '':
|
||||
metadata['category'] = Category(category, self.settings)
|
||||
|
||||
if 'date' not in metadata.keys()\
|
||||
and self.settings['FALLBACK_ON_FS_DATE']:
|
||||
if 'date' not in metadata and self.settings['FALLBACK_ON_FS_DATE']:
|
||||
metadata['date'] = datetime.datetime.fromtimestamp(
|
||||
os.stat(f).st_ctime)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,38 +1,32 @@
|
|||
import os
|
||||
import sys
|
||||
from logging import CRITICAL, ERROR, WARN, INFO, DEBUG
|
||||
from logging import CRITICAL, ERROR, WARN, INFO, DEBUG
|
||||
from logging import critical, error, info, warning, warn, debug
|
||||
from logging import Formatter, getLogger, StreamHandler
|
||||
|
||||
|
||||
RESET_TERM = u'\033[1;m'
|
||||
RESET_TERM = u'\033[0;m'
|
||||
|
||||
|
||||
def term_color(code):
|
||||
return lambda text: code + unicode(text) + RESET_TERM
|
||||
def start_color(index):
|
||||
return u'\033[1;{0}m'.format(index)
|
||||
|
||||
|
||||
def term_color(color):
|
||||
code = COLOR_CODES[color]
|
||||
return lambda text: start_color(code) + unicode(text) + RESET_TERM
|
||||
|
||||
|
||||
COLOR_CODES = {
|
||||
'gray': u'\033[1;30m',
|
||||
'red': u'\033[1;31m',
|
||||
'green': u'\033[1;32m',
|
||||
'yellow': u'\033[1;33m',
|
||||
'blue': u'\033[1;34m',
|
||||
'magenta': u'\033[1;35m',
|
||||
'cyan': u'\033[1;36m',
|
||||
'white': u'\033[1;37m',
|
||||
'bgred': u'\033[1;41m',
|
||||
'bggreen': u'\033[1;42m',
|
||||
'bgbrown': u'\033[1;43m',
|
||||
'bgblue': u'\033[1;44m',
|
||||
'bgmagenta': u'\033[1;45m',
|
||||
'bgcyan': u'\033[1;46m',
|
||||
'bggray': u'\033[1;47m',
|
||||
'bgyellow': u'\033[1;43m',
|
||||
'bggrey': u'\033[1;100m',
|
||||
'red': 31,
|
||||
'yellow': 33,
|
||||
'cyan': 36,
|
||||
'white': 37,
|
||||
'bgred': 41,
|
||||
'bggrey': 100,
|
||||
}
|
||||
|
||||
ANSI = dict((col, term_color(code)) for col, code in COLOR_CODES.items())
|
||||
ANSI = dict((col, term_color(col)) for col in COLOR_CODES)
|
||||
|
||||
|
||||
class ANSIFormatter(Formatter):
|
||||
|
|
@ -80,7 +74,7 @@ class DummyFormatter(object):
|
|||
and not sys.platform.startswith('win'):
|
||||
return ANSIFormatter(*args, **kwargs)
|
||||
else:
|
||||
return TextFormatter( *args, **kwargs)
|
||||
return TextFormatter(*args, **kwargs)
|
||||
|
||||
|
||||
def init(level=None, logger=getLogger(), handler=StreamHandler()):
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ class Reader(object):
|
|||
self.settings = settings
|
||||
|
||||
def process_metadata(self, name, value):
|
||||
if name.lower() in _METADATA_PROCESSORS:
|
||||
return _METADATA_PROCESSORS[name.lower()](value, self.settings)
|
||||
if name in _METADATA_PROCESSORS:
|
||||
return _METADATA_PROCESSORS[name](value, self.settings)
|
||||
return value
|
||||
|
||||
|
||||
|
|
@ -71,10 +71,14 @@ class RstReader(Reader):
|
|||
if element.tagname == 'field': # custom fields (e.g. summary)
|
||||
name_elem, body_elem = element.children
|
||||
name = name_elem.astext()
|
||||
value = render_node_to_html(document, body_elem)
|
||||
if name == 'summary':
|
||||
value = render_node_to_html(document, body_elem)
|
||||
else:
|
||||
value = body_elem.astext()
|
||||
else: # standard fields (e.g. address)
|
||||
name = element.tagname
|
||||
value = element.astext()
|
||||
name = name.lower()
|
||||
|
||||
output[name] = self.process_metadata(name, value)
|
||||
return output
|
||||
|
|
@ -144,7 +148,7 @@ def read_file(filename, fmt=None, settings=None):
|
|||
if not fmt:
|
||||
fmt = filename.split('.')[-1]
|
||||
|
||||
if fmt not in _EXTENSIONS.keys():
|
||||
if fmt not in _EXTENSIONS:
|
||||
raise TypeError('Pelican does not know how to parse %s' % filename)
|
||||
|
||||
reader = _EXTENSIONS[fmt](settings)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<dl>
|
||||
{% for article in dates %}
|
||||
<dt>{{ article.locale_date }}</dt>
|
||||
<dd><a href='{{ article.url }}'>{{ article.title }}</a></dd>
|
||||
<dd><a href="{{ article.url }}">{{ article.title }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<h1>Archives for {{ SITENAME }}</h2>
|
||||
<h1>Archives for {{ SITENAME }}</h1>
|
||||
|
||||
<dl>
|
||||
{% for article in dates %}
|
||||
<dt>{{ article.locale_date }}</dt>
|
||||
<dd><a href='{{ article.url }}'>{{ article.title }}</a></dd>
|
||||
<dd><a href="{{ article.url }}">{{ article.title }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
from codecs import open
|
||||
|
|
@ -38,7 +40,7 @@ def wp2fields(xml):
|
|||
|
||||
def dc2fields(file):
|
||||
"""Opens a Dotclear export file, and yield pelican fields"""
|
||||
from BeautifulSoup import BeautifulStoneSoup, BeautifulSoup
|
||||
from BeautifulSoup import BeautifulStoneSoup
|
||||
|
||||
in_cat = False
|
||||
in_post = False
|
||||
|
|
@ -85,10 +87,10 @@ def dc2fields(file):
|
|||
post_creadt = fields[6]
|
||||
# post_upddt = fields[7]
|
||||
# post_password = fields[8]
|
||||
post_type = fields[9]
|
||||
# post_type = fields[9]
|
||||
post_format = fields[10]
|
||||
post_url = fields[11]
|
||||
post_lang = fields[12]
|
||||
# post_url = fields[11]
|
||||
# post_lang = fields[12]
|
||||
post_title = fields[13]
|
||||
post_excerpt = fields[14]
|
||||
post_excerpt_xhtml = fields[15]
|
||||
|
|
@ -216,7 +218,20 @@ def fields2pelican(fields, out_markup, output_path, dircat=False):
|
|||
content = content.replace("\n", "<br />\n")
|
||||
fp.write(content)
|
||||
|
||||
os.system('pandoc --normalize --reference-links --from=html --to=%s -o "%s" "%s"' % (out_markup, out_filename, html_filename))
|
||||
cmd = 'pandoc --normalize --reference-links --from=html --to={0} -o "{1}" "{2}"'.format(
|
||||
out_markup, out_filename, html_filename)
|
||||
|
||||
try:
|
||||
rc = subprocess.call(cmd, shell=True)
|
||||
if rc < 0:
|
||||
print("Child was terminated by signal %d" % -rc)
|
||||
exit()
|
||||
elif rc > 0:
|
||||
print("Please, check your Pandoc installation.")
|
||||
exit()
|
||||
except OSError, e:
|
||||
print("Pandoc execution failed: %s" % e)
|
||||
exit()
|
||||
|
||||
os.remove(html_filename)
|
||||
|
||||
|
|
@ -234,7 +249,8 @@ def fields2pelican(fields, out_markup, output_path, dircat=False):
|
|||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Transform feed, Wordpress or Dotclear files to rst files."
|
||||
"Be sure to have pandoc installed")
|
||||
"Be sure to have pandoc installed",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
|
||||
parser.add_argument(dest='input', help='The input file to read')
|
||||
parser.add_argument('--wpfile', action='store_true', dest='wpfile',
|
||||
|
|
@ -259,24 +275,21 @@ def main():
|
|||
elif args.feed:
|
||||
input_type = 'feed'
|
||||
else:
|
||||
print("you must provide either --wpfile, --dotclear or --feed options")
|
||||
print("You must provide either --wpfile, --dotclear or --feed options")
|
||||
exit()
|
||||
|
||||
if not os.path.exists(args.output):
|
||||
try:
|
||||
os.mkdir(args.output)
|
||||
except OSError:
|
||||
error("Couldn't create the output folder: " + args.output)
|
||||
print("Unable to create the output folder: " + args.output)
|
||||
exit()
|
||||
|
||||
# TODO: refactor this long assignment
|
||||
input_type, input, out_markup, output_path, dircat=False = input_type, args.input, args.markup, args.output, args.dircat
|
||||
|
||||
if input_type == 'wordpress':
|
||||
fields = wp2fields(input)
|
||||
fields = wp2fields(args.input)
|
||||
elif input_type == 'dotclear':
|
||||
fields = dc2fields(input)
|
||||
fields = dc2fields(args.input)
|
||||
elif input_type == 'feed':
|
||||
fields = feed2fields(input)
|
||||
fields = feed2fields(args.input)
|
||||
|
||||
fields2pelican(fields, out_markup, output_path, dircat=dircat)
|
||||
fields2pelican(fields, args.markup, args.output, dircat=args.dircat or False)
|
||||
|
|
@ -1,10 +1,13 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*- #
|
||||
|
||||
import os, sys, argparse, string
|
||||
import os
|
||||
import string
|
||||
import argparse
|
||||
|
||||
from pelican import __version__
|
||||
|
||||
TEMPLATES={
|
||||
TEMPLATES = {
|
||||
'Makefile' : '''
|
||||
PELICAN=$pelican
|
||||
PELICANOPTS=$pelicanopts
|
||||
|
|
@ -60,7 +63,7 @@ github: $$(OUTPUTDIR)/index.html
|
|||
\tgit push origin gh-pages
|
||||
|
||||
.PHONY: html help clean ftp_upload ssh_upload dropbox_upload github
|
||||
''',
|
||||
''',
|
||||
|
||||
'pelican.conf.py': '''#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*- #
|
||||
|
|
@ -87,9 +90,7 @@ SOCIAL = (
|
|||
)
|
||||
|
||||
DEFAULT_PAGINATION = $default_pagination
|
||||
|
||||
|
||||
'''
|
||||
'''
|
||||
}
|
||||
|
||||
CONF = {
|
||||
|
|
@ -108,17 +109,6 @@ CONF = {
|
|||
}
|
||||
|
||||
|
||||
class _dict(dict):
|
||||
def __init__(self, *args, **kwargs):
|
||||
dict.__init__(self, *args, **kwargs)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return dict.get(self,i,None)
|
||||
|
||||
def has_key(k):
|
||||
return True
|
||||
|
||||
|
||||
def ask(question, answer=str, default=None, l=None):
|
||||
if answer == str:
|
||||
r = ''
|
||||
|
|
@ -193,14 +183,16 @@ def ask(question, answer=str, default=None, l=None):
|
|||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="A kickstarter for pelican")
|
||||
parser = argparse.ArgumentParser(
|
||||
description="A kickstarter for pelican",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('-p', '--path', default=".",
|
||||
help="The path to generate the blog into")
|
||||
parser.add_argument('-t', '--title', default=None, metavar="title",
|
||||
parser.add_argument('-t', '--title', metavar="title",
|
||||
help='Set the title of the website')
|
||||
parser.add_argument('-a', '--author', default=None, metavar="author",
|
||||
parser.add_argument('-a', '--author', metavar="author",
|
||||
help='Set the author name of the website')
|
||||
parser.add_argument('-l', '--lang', default=None, metavar="lang",
|
||||
parser.add_argument('-l', '--lang', metavar="lang",
|
||||
help='Set the default lang of the website')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
|
@ -210,9 +210,6 @@ LAST_MTIME = 0
|
|||
def files_changed(path, extensions):
|
||||
"""Return True if the files have changed since the last check"""
|
||||
|
||||
def with_extension(f):
|
||||
return any(f.endswith(ext) for ext in extensions)
|
||||
|
||||
def file_times(path):
|
||||
"""Return the last time files have been modified"""
|
||||
for root, dirs, files in os.walk(path):
|
||||
|
|
|
|||
14
setup.py
14
setup.py
|
|
@ -1,8 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
from setuptools import setup
|
||||
|
||||
VERSION = "3.0" # find a better way to do so.
|
||||
|
||||
requires = ['feedgenerator', 'jinja2', 'pygments', 'docutils', 'pytz']
|
||||
|
||||
try:
|
||||
|
|
@ -13,21 +11,21 @@ except ImportError:
|
|||
entry_points = {
|
||||
'console_scripts': [
|
||||
'pelican = pelican:main',
|
||||
'pelican-import = tools.pelican_import:main',
|
||||
'pelican-quickstart = tools.pelican_quickstart:main',
|
||||
'pelican-themes = tools.pelican_themes:main'
|
||||
]
|
||||
'pelican-import = pelican.tools.pelican_import:main',
|
||||
'pelican-quickstart = pelican.tools.pelican_quickstart:main',
|
||||
'pelican-themes = pelican.tools.pelican_themes:main'
|
||||
]
|
||||
}
|
||||
|
||||
setup(
|
||||
name = "pelican",
|
||||
version = VERSION,
|
||||
version = "3.0",
|
||||
url = 'http://pelican.notmyidea.org/',
|
||||
author = 'Alexis Metaireau',
|
||||
author_email = 'alexis@notmyidea.org',
|
||||
description = "A tool to generate a static blog from reStructuredText or Markdown input files.",
|
||||
long_description=open('README.rst').read(),
|
||||
packages = ['pelican'],
|
||||
packages = ['pelican', 'pelican.tools'],
|
||||
include_package_data = True,
|
||||
install_requires = requires,
|
||||
entry_points = entry_points,
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ This is a super article !
|
|||
:summary:
|
||||
Multi-line metadata should be supported
|
||||
as well as **inline markup**.
|
||||
:custom_field: http://notmyidea.org
|
||||
|
|
|
|||
6
tests/content/article_with_uppercase_metadata.rst
Normal file
6
tests/content/article_with_uppercase_metadata.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
This is a super article !
|
||||
#########################
|
||||
|
||||
:Category: Yeah
|
||||
|
||||
|
|
@ -8,14 +8,20 @@ except ImportError, e:
|
|||
from pelican.contents import Page
|
||||
from pelican.settings import _DEFAULT_CONFIG
|
||||
|
||||
from jinja2.utils import generate_lorem_ipsum
|
||||
|
||||
# generate one paragraph, enclosed with <p>
|
||||
TEST_CONTENT = str(generate_lorem_ipsum(n=1))
|
||||
TEST_SUMMARY = generate_lorem_ipsum(n=1, html=False)
|
||||
|
||||
class TestPage(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPage, self).setUp()
|
||||
self.page_kwargs = {
|
||||
'content': 'content',
|
||||
'content': TEST_CONTENT,
|
||||
'metadata': {
|
||||
'summary': TEST_SUMMARY,
|
||||
'title': 'foo bar',
|
||||
'author': 'Blogger',
|
||||
},
|
||||
|
|
@ -27,11 +33,11 @@ class TestPage(TestCase):
|
|||
|
||||
"""
|
||||
metadata = {'foo': 'bar', 'foobar': 'baz', 'title': 'foobar', }
|
||||
page = Page('content', metadata=metadata)
|
||||
page = Page(TEST_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, TEST_CONTENT)
|
||||
|
||||
def test_mandatory_properties(self):
|
||||
"""If the title is not set, must throw an exception."""
|
||||
|
|
@ -39,6 +45,11 @@ class TestPage(TestCase):
|
|||
page = Page(**self.page_kwargs)
|
||||
page.check_properties()
|
||||
|
||||
def test_summary_from_metadata(self):
|
||||
"""If a :summary: metadata is given, it should be used."""
|
||||
page = Page(**self.page_kwargs)
|
||||
self.assertEqual(page.summary, TEST_SUMMARY)
|
||||
|
||||
def test_slug(self):
|
||||
"""If a title is given, it should be used to generate the slug."""
|
||||
page = Page(**self.page_kwargs)
|
||||
|
|
|
|||
|
|
@ -30,11 +30,20 @@ class RstReaderTest(unittest.TestCase):
|
|||
' <strong>inline markup</strong>.',
|
||||
'date': datetime.datetime(2010, 12, 2, 10, 14),
|
||||
'tags': ['foo', 'bar', 'foobar'],
|
||||
'custom_field': 'http://notmyidea.org',
|
||||
}
|
||||
|
||||
for key, value in expected.items():
|
||||
self.assertEquals(value, metadata[key], key)
|
||||
|
||||
def test_article_metadata_key_lowercase(self):
|
||||
"""Keys of metadata should be lowercase."""
|
||||
reader = readers.RstReader({})
|
||||
content, metadata = reader.read(_filename('article_with_uppercase_metadata.rst'))
|
||||
|
||||
self.assertIn('category', metadata, "Key should be lowercase.")
|
||||
self.assertEquals('Yeah', metadata.get('category'), "Value keeps cases.")
|
||||
|
||||
def test_typogrify(self):
|
||||
# if nothing is specified in the settings, the content should be
|
||||
# unmodified
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ try:
|
|||
import unittest2 as unittest
|
||||
except ImportError:
|
||||
import unittest # NOQA
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from pelican import utils
|
||||
from pelican.contents import Article
|
||||
|
||||
from support import get_article
|
||||
|
||||
|
||||
|
|
@ -73,3 +74,20 @@ class TestUtils(unittest.TestCase):
|
|||
self.assertIn(fr_article1, trans)
|
||||
self.assertNotIn(en_article1, trans)
|
||||
self.assertNotIn(fr_article1, index)
|
||||
|
||||
def test_files_changed(self):
|
||||
"Test if file changes are correctly detected"
|
||||
|
||||
path = os.path.join(os.path.dirname(__file__), 'content')
|
||||
filename = os.path.join(path, 'article_with_metadata.rst')
|
||||
changed = utils.files_changed(path, 'rst')
|
||||
self.assertEquals(changed, True)
|
||||
|
||||
changed = utils.files_changed(path, 'rst')
|
||||
self.assertEquals(changed, False)
|
||||
|
||||
t = time.time()
|
||||
os.utime(filename, (t, t))
|
||||
changed = utils.files_changed(path, 'rst')
|
||||
self.assertEquals(changed, True)
|
||||
self.assertAlmostEqual(utils.LAST_MTIME, t, places=2)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue