Skip to content

Commit

Permalink
improved sandbox, added proper striptags and updated documentation to…
Browse files Browse the repository at this point in the history
… latest sphinx changes

--HG--
branch : trunk
  • Loading branch information
mitsuhiko committed May 4, 2008
1 parent 4dc9578 commit 76c280b
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 14 deletions.
2 changes: 1 addition & 1 deletion docs/conf.py
Expand Up @@ -145,4 +145,4 @@
#latex_appendices = []

# If false, no module index is generated.
#latex_use_modindex = True
latex_use_modindex = False
7 changes: 0 additions & 7 deletions docs/index.rst
Expand Up @@ -9,10 +9,3 @@ Contents:
intro
api
templates

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
5 changes: 5 additions & 0 deletions docs/templates.rst
Expand Up @@ -838,3 +838,8 @@ The following functions are available in the global scope by default:
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')``.
1 change: 1 addition & 0 deletions jinja2/defaults.py
Expand Up @@ -24,6 +24,7 @@

DEFAULT_NAMESPACE = {
'range': xrange,
'dict': lambda **kw: kw,
'lipsum': generate_lorem_ipsum
}

Expand Down
3 changes: 1 addition & 2 deletions jinja2/filters.py
Expand Up @@ -19,7 +19,6 @@
from jinja2.exceptions import FilterArgumentError


_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
_word_re = re.compile(r'\w+')


Expand Down Expand Up @@ -428,7 +427,7 @@ def do_striptags(value):
"""
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):
Expand Down
15 changes: 12 additions & 3 deletions jinja2/sandbox.py
Expand Up @@ -20,14 +20,22 @@
#: 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
MAX_RANGE items.
"""
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


Expand All @@ -54,9 +62,10 @@ def is_safe_attribute(self, obj, attr, value):
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):
Expand Down
27 changes: 26 additions & 1 deletion jinja2/utils.py
Expand Up @@ -15,6 +15,7 @@
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
Expand All @@ -28,7 +29,10 @@
)
)
_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'})()
Expand Down Expand Up @@ -278,6 +282,27 @@ def splitlines(self, *args, **kwargs):
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):
Expand Down

0 comments on commit 76c280b

Please sign in to comment.