#latex_appendices = []
# If false, no module index is generated.
-#latex_use_modindex = True
+latex_use_modindex = False
intro
api
templates
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
with HTML are generated each paragraph between 20 and 100 words. If html
is disabled regular text is returned. This is useful to generate simple
contents for layout testing.
+
+.. function:: dict(**items)
+
+ A convenient alternative to dict literals. ``{'foo': 'bar'}`` is the same
+ as ``dict(foo='bar')``.
DEFAULT_NAMESPACE = {
'range': xrange,
+ 'dict': lambda **kw: kw,
'lipsum': generate_lorem_ipsum
}
from jinja2.exceptions import FilterArgumentError
-_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
_word_re = re.compile(r'\w+')
"""
if hasattr(value, '__html__'):
value = value.__html__()
- return u' '.join(_striptags_re.sub('', value).split())
+ return Markup(unicode(value)).striptags()
def do_slice(value, slices, fill_with=None):
#: maximum number of items a range may produce
MAX_RANGE = 100000
+#: attributes of function objects that are considered unsafe.
+UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
+ 'func_defaults', 'func_globals'])
+
+#: unsafe method attributes. function attributes are unsafe for methods too
+UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
+
def safe_range(*args):
"""A range that can't generate ranges with a length of more than
"""
rng = xrange(*args)
if len(rng) > MAX_RANGE:
- raise OverflowError('range too big')
+ raise OverflowError('range too big, maximum size for range is %d' %
+ MAX_RANGE)
return rng
if attr.startswith('_'):
return False
if isinstance(obj, FunctionType):
- return not attr.startswith('func_')
+ return attr not in UNSAFE_FUNCTION_ATTRIBUTES
if isinstance(obj, MethodType):
- return not attr.startswith('im_')
+ return attr not in UNSAFE_FUNCTION_ATTRIBUTES and \
+ attr not in UNSAFE_METHOD_ATTRIBUTES
return True
def is_safe_callable(self, obj):
from thread import allocate_lock
except ImportError:
from dummy_thread import allocate_lock
+from htmlentitydefs import name2codepoint
from collections import deque
from copy import deepcopy
from itertools import imap
)
)
_simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
-
+_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
+_entity_re = re.compile(r'&([^;]+);')
+_entities = name2codepoint.copy()
+_entities['apos'] = 39
# special singleton representing missing values for the runtime
missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
splitlines.__doc__ = unicode.splitlines.__doc__
+ def unescape(self):
+ """Unescape markup."""
+ def handle_match(m):
+ name = m.group(1)
+ if name in _entities:
+ return unichr(_entities[name])
+ try:
+ if name[:2] in ('#x', '#X'):
+ return unichr(int(name[2:], 16))
+ elif name.startswith('#'):
+ return unichr(int(name[1:]))
+ except ValueError:
+ pass
+ return u''
+ return _entity_re.sub(handle_match, unicode(self))
+
+ def striptags(self):
+ """Strip tags and resolve enities."""
+ stripped = u' '.join(_striptags_re.sub('', self).split())
+ return Markup(stripped).unescape()
+
def make_wrapper(name):
orig = getattr(unicode, name)
def func(self, *args, **kwargs):