"""
import re
import sys
-import string
+import errno
try:
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
+_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+_digits = '0123456789'
# special singleton representing missing values for the runtime
missing = type('MissingType', (), {'__repr__': lambda x: 'missing'})()
del _test_gen_bug, _error
+# ironpython without stdlib doesn't have keyword
+try:
+ from keyword import iskeyword as is_python_keyword
+except ImportError:
+ _py_identifier_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9]*$')
+ def is_python_keyword(name):
+ if _py_identifier_re.search(name) is None:
+ return False
+ try:
+ exec name + " = 42"
+ except SyntaxError:
+ return False
+ return True
+
+
+# common types. These do exist in the special types module too which however
+# does not exist in IronPython out of the box.
+class _C(object):
+ def method(self): pass
+def _func():
+ yield None
+FunctionType = type(_func)
+GeneratorType = type(_func())
+MethodType = type(_C.method)
+CodeType = type(_C.method.func_code)
+try:
+ raise TypeError()
+except TypeError:
+ _tb = sys.exc_info()[2]
+ TracebackType = type(_tb)
+ FrameType = type(_tb.tb_frame)
+del _C, _tb, _func
+
+
def contextfunction(f):
"""This decorator can be used to mark a function or method context callable.
A context callable is passed the active :class:`Context` as first argument when
raise
+def open_if_exists(filename, mode='r'):
+ """Returns a file descriptor for the filename if that file exists,
+ otherwise `None`.
+ """
+ try:
+ return file(filename, mode)
+ except IOError, e:
+ if e.errno not in (errno.ENOENT, errno.EISDIR):
+ raise
+
+
def pformat(obj, verbose=False):
"""Prettyprint an object. Either use the `pretty` library or the
builtin `pprint`.
'@' not in middle and
not middle.startswith('http://') and
len(middle) > 0 and
- middle[0] in string.letters + string.digits and (
+ middle[0] in _letters + _digits and (
middle.endswith('.org') or
middle.endswith('.net') or
middle.endswith('.com')
it escapes arguments passed and always returns `Markup`.
The `escape` function returns markup objects so that double escaping can't
- happen. If you want to use autoescaping in Jinja just set the finalizer
- of the environment to `escape`.
+ happen. If you want to use autoescaping in Jinja just enable the
+ autoescaping feature in the environment.
The constructor of the :class:`Markup` class can be used for three
different things: When passed an unicode object it's assumed to be safe,
"""
__slots__ = ()
- def __new__(cls, base=u''):
+ def __new__(cls, base=u'', encoding=None, errors='strict'):
if hasattr(base, '__html__'):
base = base.__html__()
- return unicode.__new__(cls, base)
+ if encoding is None:
+ return unicode.__new__(cls, base)
+ return unicode.__new__(cls, base, encoding, errors)
def __html__(self):
return self
>>> Markup("Main » <em>About</em>").unescape()
u'Main \xbb <em>About</em>'
"""
+ from jinja2.constants import HTML_ENTITIES
def handle_match(m):
name = m.group(1)
- if name in _entities:
- return unichr(_entities[name])
+ if name in HTML_ENTITIES:
+ return unichr(HTML_ENTITIES[name])
try:
if name[:2] in ('#x', '#X'):
return unichr(int(name[2:], 16))
__getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x])
__unicode__ = lambda s: unicode(escape(s.obj))
__str__ = lambda s: str(escape(s.obj))
- __repr__ = lambda s: str(repr(escape(s.obj)))
+ __repr__ = lambda s: str(escape(repr(s.obj)))
__int__ = lambda s: int(s.obj)
__float__ = lambda s: float(s.obj)
pass
+class Cycler(object):
+ """A cycle helper for templates."""
+
+ def __init__(self, *items):
+ if not items:
+ raise RuntimeError('at least one item has to be provided')
+ self.items = items
+ self.reset()
+
+ def reset(self):
+ """Resets the cycle."""
+ self.pos = 0
+
+ @property
+ def current(self):
+ """Returns the current item."""
+ return self.items[self.pos]
+
+ def next(self):
+ """Goes one item ahead and returns it."""
+ rv = self.current
+ self.pos = (self.pos + 1) % len(self.items)
+ return rv
+
+
# we have to import it down here as the speedups module imports the
# markup type which is define above.
try: