mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
140 lines
3.6 KiB
Python
140 lines
3.6 KiB
Python
__all__ = [
|
|
'get_article',
|
|
'unittest',
|
|
]
|
|
|
|
import os
|
|
import subprocess
|
|
import re
|
|
import sys
|
|
import cStringIO
|
|
|
|
from functools import wraps
|
|
from contextlib import contextmanager
|
|
from tempfile import mkdtemp
|
|
from shutil import rmtree
|
|
|
|
from pelican.contents import Article
|
|
|
|
try:
|
|
import unittest2 as unittest
|
|
except ImportError:
|
|
import unittest
|
|
|
|
|
|
@contextmanager
|
|
def temporary_folder():
|
|
"""creates a temporary folder, return it and delete it afterwards.
|
|
|
|
This allows to do something like this in tests:
|
|
|
|
>>> with temporary_folder() as d:
|
|
# do whatever you want
|
|
"""
|
|
tempdir = mkdtemp()
|
|
try:
|
|
yield tempdir
|
|
finally:
|
|
rmtree(tempdir)
|
|
|
|
|
|
def isplit(s, sep=None):
|
|
"""
|
|
Behave like str.split but returns a generator instead of a list.
|
|
|
|
>>> list(isplit('\tUse the force\n')) == '\tUse the force\n'.split()
|
|
True
|
|
>>> list(isplit('\tUse the force\n')) == ['Use', 'the', 'force']
|
|
True
|
|
>>> list(isplit('\tUse the force\n', "e")) == '\tUse the force\n'.split("e")
|
|
True
|
|
>>> list(isplit('Use the force', "e")) == 'Use the force'.split("e")
|
|
True
|
|
>>> list(isplit('Use the force', "e")) == ['Us', ' th', ' forc', '']
|
|
True
|
|
|
|
"""
|
|
sep, hardsep = r'\s+' if sep is None else re.escape(sep), sep is not None
|
|
exp, pos, l = re.compile(sep), 0, len(s)
|
|
while True:
|
|
m = exp.search(s, pos)
|
|
if not m:
|
|
if pos < l or hardsep:
|
|
# ^ mimic "split()": ''.split() returns []
|
|
yield s[pos:]
|
|
break
|
|
start = m.start()
|
|
if pos < start or hardsep:
|
|
# ^ mimic "split()": includes trailing empty string
|
|
yield s[pos:start]
|
|
pos = m.end()
|
|
|
|
|
|
def mute(returns_output=False):
|
|
"""
|
|
Decorate a function that prints to stdout, intercepting the output.
|
|
If "returns_output" is True, the function will return a generator
|
|
yielding the printed lines instead of the return values.
|
|
|
|
The decorator litterally hijack sys.stdout during each function
|
|
execution, so be careful with what you apply it to.
|
|
|
|
>>> def numbers():
|
|
print "42"
|
|
print "1984"
|
|
...
|
|
>>> numbers()
|
|
42
|
|
1984
|
|
>>> mute()(numbers)()
|
|
>>> list(mute(True)(numbers)())
|
|
['42', '1984']
|
|
|
|
"""
|
|
|
|
def decorator(func):
|
|
|
|
@wraps(func)
|
|
def wrapper(*args, **kwargs):
|
|
|
|
saved_stdout = sys.stdout
|
|
sys.stdout = cStringIO.StringIO()
|
|
|
|
try:
|
|
out = func(*args, **kwargs)
|
|
if returns_output:
|
|
out = isplit(sys.stdout.getvalue().strip())
|
|
finally:
|
|
sys.stdout = saved_stdout
|
|
|
|
return out
|
|
|
|
return wrapper
|
|
|
|
return decorator
|
|
|
|
|
|
|
|
def get_article(title, slug, content, lang, extra_metadata=None):
|
|
metadata = {'slug': slug, 'title': title, 'lang': lang}
|
|
if extra_metadata is not None:
|
|
metadata.update(extra_metadata)
|
|
return Article(content, metadata=metadata)
|
|
|
|
|
|
def skipIfNoExecutable(executable, valid_exit_code=1):
|
|
"""Tries to run an executable to make sure it's in the path, Skips the tests
|
|
if not found.
|
|
"""
|
|
|
|
# calling with no params the command should exit with 1
|
|
with open(os.devnull, 'w') as fnull:
|
|
try:
|
|
res = subprocess.call(executable, stdout=fnull, stderr=fnull)
|
|
except OSError:
|
|
res = None
|
|
|
|
if res != valid_exit_code:
|
|
return unittest.skip('{0} compiler not found'.format(executable))
|
|
|
|
return lambda func: func
|