Jinja2 requires MarkupSafe at runtime, so add it, too.
This commit is contained in:
parent
a1770b4b04
commit
01a15fd9f4
6 changed files with 1055 additions and 0 deletions
298
tools/external/markupsafe/__init__.py
vendored
Normal file
298
tools/external/markupsafe/__init__.py
vendored
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
markupsafe
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Implements a Markup string.
|
||||||
|
|
||||||
|
:copyright: (c) 2010 by Armin Ronacher.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
import string
|
||||||
|
from collections import Mapping
|
||||||
|
from markupsafe._compat import text_type, string_types, int_types, \
|
||||||
|
unichr, iteritems, PY2
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
|
||||||
|
|
||||||
|
|
||||||
|
_striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
|
||||||
|
_entity_re = re.compile(r'&([^;]+);')
|
||||||
|
|
||||||
|
|
||||||
|
class Markup(text_type):
|
||||||
|
r"""Marks a string as being safe for inclusion in HTML/XML output without
|
||||||
|
needing to be escaped. This implements the `__html__` interface a couple
|
||||||
|
of frameworks and web applications use. :class:`Markup` is a direct
|
||||||
|
subclass of `unicode` and provides all the methods of `unicode` just that
|
||||||
|
it escapes arguments passed and always returns `Markup`.
|
||||||
|
|
||||||
|
The `escape` function returns markup objects so that double escaping can't
|
||||||
|
happen.
|
||||||
|
|
||||||
|
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,
|
||||||
|
when passed an object with an HTML representation (has an `__html__`
|
||||||
|
method) that representation is used, otherwise the object passed is
|
||||||
|
converted into a unicode string and then assumed to be safe:
|
||||||
|
|
||||||
|
>>> Markup("Hello <em>World</em>!")
|
||||||
|
Markup(u'Hello <em>World</em>!')
|
||||||
|
>>> class Foo(object):
|
||||||
|
... def __html__(self):
|
||||||
|
... return '<a href="#">foo</a>'
|
||||||
|
...
|
||||||
|
>>> Markup(Foo())
|
||||||
|
Markup(u'<a href="#">foo</a>')
|
||||||
|
|
||||||
|
If you want object passed being always treated as unsafe you can use the
|
||||||
|
:meth:`escape` classmethod to create a :class:`Markup` object:
|
||||||
|
|
||||||
|
>>> Markup.escape("Hello <em>World</em>!")
|
||||||
|
Markup(u'Hello <em>World</em>!')
|
||||||
|
|
||||||
|
Operations on a markup string are markup aware which means that all
|
||||||
|
arguments are passed through the :func:`escape` function:
|
||||||
|
|
||||||
|
>>> em = Markup("<em>%s</em>")
|
||||||
|
>>> em % "foo & bar"
|
||||||
|
Markup(u'<em>foo & bar</em>')
|
||||||
|
>>> strong = Markup("<strong>%(text)s</strong>")
|
||||||
|
>>> strong % {'text': '<blink>hacker here</blink>'}
|
||||||
|
Markup(u'<strong><blink>hacker here</blink></strong>')
|
||||||
|
>>> Markup("<em>Hello</em> ") + "<foo>"
|
||||||
|
Markup(u'<em>Hello</em> <foo>')
|
||||||
|
"""
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def __new__(cls, base=u'', encoding=None, errors='strict'):
|
||||||
|
if hasattr(base, '__html__'):
|
||||||
|
base = base.__html__()
|
||||||
|
if encoding is None:
|
||||||
|
return text_type.__new__(cls, base)
|
||||||
|
return text_type.__new__(cls, base, encoding, errors)
|
||||||
|
|
||||||
|
def __html__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if isinstance(other, string_types) or hasattr(other, '__html__'):
|
||||||
|
return self.__class__(super(Markup, self).__add__(self.escape(other)))
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
if hasattr(other, '__html__') or isinstance(other, string_types):
|
||||||
|
return self.escape(other).__add__(self)
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __mul__(self, num):
|
||||||
|
if isinstance(num, int_types):
|
||||||
|
return self.__class__(text_type.__mul__(self, num))
|
||||||
|
return NotImplemented
|
||||||
|
__rmul__ = __mul__
|
||||||
|
|
||||||
|
def __mod__(self, arg):
|
||||||
|
if isinstance(arg, tuple):
|
||||||
|
arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg)
|
||||||
|
else:
|
||||||
|
arg = _MarkupEscapeHelper(arg, self.escape)
|
||||||
|
return self.__class__(text_type.__mod__(self, arg))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%s(%s)' % (
|
||||||
|
self.__class__.__name__,
|
||||||
|
text_type.__repr__(self)
|
||||||
|
)
|
||||||
|
|
||||||
|
def join(self, seq):
|
||||||
|
return self.__class__(text_type.join(self, map(self.escape, seq)))
|
||||||
|
join.__doc__ = text_type.join.__doc__
|
||||||
|
|
||||||
|
def split(self, *args, **kwargs):
|
||||||
|
return list(map(self.__class__, text_type.split(self, *args, **kwargs)))
|
||||||
|
split.__doc__ = text_type.split.__doc__
|
||||||
|
|
||||||
|
def rsplit(self, *args, **kwargs):
|
||||||
|
return list(map(self.__class__, text_type.rsplit(self, *args, **kwargs)))
|
||||||
|
rsplit.__doc__ = text_type.rsplit.__doc__
|
||||||
|
|
||||||
|
def splitlines(self, *args, **kwargs):
|
||||||
|
return list(map(self.__class__, text_type.splitlines(
|
||||||
|
self, *args, **kwargs)))
|
||||||
|
splitlines.__doc__ = text_type.splitlines.__doc__
|
||||||
|
|
||||||
|
def unescape(self):
|
||||||
|
r"""Unescape markup again into an text_type string. This also resolves
|
||||||
|
known HTML4 and XHTML entities:
|
||||||
|
|
||||||
|
>>> Markup("Main » <em>About</em>").unescape()
|
||||||
|
u'Main \xbb <em>About</em>'
|
||||||
|
"""
|
||||||
|
from markupsafe._constants import HTML_ENTITIES
|
||||||
|
def handle_match(m):
|
||||||
|
name = m.group(1)
|
||||||
|
if name in HTML_ENTITIES:
|
||||||
|
return unichr(HTML_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, text_type(self))
|
||||||
|
|
||||||
|
def striptags(self):
|
||||||
|
r"""Unescape markup into an text_type string and strip all tags. This
|
||||||
|
also resolves known HTML4 and XHTML entities. Whitespace is
|
||||||
|
normalized to one:
|
||||||
|
|
||||||
|
>>> Markup("Main » <em>About</em>").striptags()
|
||||||
|
u'Main \xbb About'
|
||||||
|
"""
|
||||||
|
stripped = u' '.join(_striptags_re.sub('', self).split())
|
||||||
|
return Markup(stripped).unescape()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def escape(cls, s):
|
||||||
|
"""Escape the string. Works like :func:`escape` with the difference
|
||||||
|
that for subclasses of :class:`Markup` this function would return the
|
||||||
|
correct subclass.
|
||||||
|
"""
|
||||||
|
rv = escape(s)
|
||||||
|
if rv.__class__ is not cls:
|
||||||
|
return cls(rv)
|
||||||
|
return rv
|
||||||
|
|
||||||
|
def make_simple_escaping_wrapper(name):
|
||||||
|
orig = getattr(text_type, name)
|
||||||
|
def func(self, *args, **kwargs):
|
||||||
|
args = _escape_argspec(list(args), enumerate(args), self.escape)
|
||||||
|
_escape_argspec(kwargs, iteritems(kwargs), self.escape)
|
||||||
|
return self.__class__(orig(self, *args, **kwargs))
|
||||||
|
func.__name__ = orig.__name__
|
||||||
|
func.__doc__ = orig.__doc__
|
||||||
|
return func
|
||||||
|
|
||||||
|
for method in '__getitem__', 'capitalize', \
|
||||||
|
'title', 'lower', 'upper', 'replace', 'ljust', \
|
||||||
|
'rjust', 'lstrip', 'rstrip', 'center', 'strip', \
|
||||||
|
'translate', 'expandtabs', 'swapcase', 'zfill':
|
||||||
|
locals()[method] = make_simple_escaping_wrapper(method)
|
||||||
|
|
||||||
|
# new in python 2.5
|
||||||
|
if hasattr(text_type, 'partition'):
|
||||||
|
def partition(self, sep):
|
||||||
|
return tuple(map(self.__class__,
|
||||||
|
text_type.partition(self, self.escape(sep))))
|
||||||
|
def rpartition(self, sep):
|
||||||
|
return tuple(map(self.__class__,
|
||||||
|
text_type.rpartition(self, self.escape(sep))))
|
||||||
|
|
||||||
|
# new in python 2.6
|
||||||
|
if hasattr(text_type, 'format'):
|
||||||
|
def format(*args, **kwargs):
|
||||||
|
self, args = args[0], args[1:]
|
||||||
|
formatter = EscapeFormatter(self.escape)
|
||||||
|
kwargs = _MagicFormatMapping(args, kwargs)
|
||||||
|
return self.__class__(formatter.vformat(self, args, kwargs))
|
||||||
|
|
||||||
|
def __html_format__(self, format_spec):
|
||||||
|
if format_spec:
|
||||||
|
raise ValueError('Unsupported format specification '
|
||||||
|
'for Markup.')
|
||||||
|
return self
|
||||||
|
|
||||||
|
# not in python 3
|
||||||
|
if hasattr(text_type, '__getslice__'):
|
||||||
|
__getslice__ = make_simple_escaping_wrapper('__getslice__')
|
||||||
|
|
||||||
|
del method, make_simple_escaping_wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class _MagicFormatMapping(Mapping):
|
||||||
|
"""This class implements a dummy wrapper to fix a bug in the Python
|
||||||
|
standard library for string formatting.
|
||||||
|
|
||||||
|
See http://bugs.python.org/issue13598 for information about why
|
||||||
|
this is necessary.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, args, kwargs):
|
||||||
|
self._args = args
|
||||||
|
self._kwargs = kwargs
|
||||||
|
self._last_index = 0
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if key == '':
|
||||||
|
idx = self._last_index
|
||||||
|
self._last_index += 1
|
||||||
|
try:
|
||||||
|
return self._args[idx]
|
||||||
|
except LookupError:
|
||||||
|
pass
|
||||||
|
key = str(idx)
|
||||||
|
return self._kwargs[key]
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(self._kwargs)
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
if hasattr(text_type, 'format'):
|
||||||
|
class EscapeFormatter(string.Formatter):
|
||||||
|
|
||||||
|
def __init__(self, escape):
|
||||||
|
self.escape = escape
|
||||||
|
|
||||||
|
def format_field(self, value, format_spec):
|
||||||
|
if hasattr(value, '__html_format__'):
|
||||||
|
rv = value.__html_format__(format_spec)
|
||||||
|
elif hasattr(value, '__html__'):
|
||||||
|
if format_spec:
|
||||||
|
raise ValueError('No format specification allowed '
|
||||||
|
'when formatting an object with '
|
||||||
|
'its __html__ method.')
|
||||||
|
rv = value.__html__()
|
||||||
|
else:
|
||||||
|
rv = string.Formatter.format_field(self, value, format_spec)
|
||||||
|
return text_type(self.escape(rv))
|
||||||
|
|
||||||
|
|
||||||
|
def _escape_argspec(obj, iterable, escape):
|
||||||
|
"""Helper for various string-wrapped functions."""
|
||||||
|
for key, value in iterable:
|
||||||
|
if hasattr(value, '__html__') or isinstance(value, string_types):
|
||||||
|
obj[key] = escape(value)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
class _MarkupEscapeHelper(object):
|
||||||
|
"""Helper for Markup.__mod__"""
|
||||||
|
|
||||||
|
def __init__(self, obj, escape):
|
||||||
|
self.obj = obj
|
||||||
|
self.escape = escape
|
||||||
|
|
||||||
|
__getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x], s.escape)
|
||||||
|
__unicode__ = __str__ = lambda s: text_type(s.escape(s.obj))
|
||||||
|
__repr__ = lambda s: str(s.escape(repr(s.obj)))
|
||||||
|
__int__ = lambda s: int(s.obj)
|
||||||
|
__float__ = lambda s: float(s.obj)
|
||||||
|
|
||||||
|
|
||||||
|
# we have to import it down here as the speedups and native
|
||||||
|
# modules imports the markup type which is define above.
|
||||||
|
try:
|
||||||
|
from markupsafe._speedups import escape, escape_silent, soft_unicode
|
||||||
|
except ImportError:
|
||||||
|
from markupsafe._native import escape, escape_silent, soft_unicode
|
||||||
|
|
||||||
|
if not PY2:
|
||||||
|
soft_str = soft_unicode
|
||||||
|
__all__.append('soft_str')
|
26
tools/external/markupsafe/_compat.py
vendored
Normal file
26
tools/external/markupsafe/_compat.py
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
markupsafe._compat
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Compatibility module for different Python versions.
|
||||||
|
|
||||||
|
:copyright: (c) 2013 by Armin Ronacher.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
|
||||||
|
PY2 = sys.version_info[0] == 2
|
||||||
|
|
||||||
|
if not PY2:
|
||||||
|
text_type = str
|
||||||
|
string_types = (str,)
|
||||||
|
unichr = chr
|
||||||
|
int_types = (int,)
|
||||||
|
iteritems = lambda x: iter(x.items())
|
||||||
|
else:
|
||||||
|
text_type = unicode
|
||||||
|
string_types = (str, unicode)
|
||||||
|
unichr = unichr
|
||||||
|
int_types = (int, long)
|
||||||
|
iteritems = lambda x: x.iteritems()
|
267
tools/external/markupsafe/_constants.py
vendored
Normal file
267
tools/external/markupsafe/_constants.py
vendored
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
markupsafe._constants
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Highlevel implementation of the Markup string.
|
||||||
|
|
||||||
|
:copyright: (c) 2010 by Armin Ronacher.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
HTML_ENTITIES = {
|
||||||
|
'AElig': 198,
|
||||||
|
'Aacute': 193,
|
||||||
|
'Acirc': 194,
|
||||||
|
'Agrave': 192,
|
||||||
|
'Alpha': 913,
|
||||||
|
'Aring': 197,
|
||||||
|
'Atilde': 195,
|
||||||
|
'Auml': 196,
|
||||||
|
'Beta': 914,
|
||||||
|
'Ccedil': 199,
|
||||||
|
'Chi': 935,
|
||||||
|
'Dagger': 8225,
|
||||||
|
'Delta': 916,
|
||||||
|
'ETH': 208,
|
||||||
|
'Eacute': 201,
|
||||||
|
'Ecirc': 202,
|
||||||
|
'Egrave': 200,
|
||||||
|
'Epsilon': 917,
|
||||||
|
'Eta': 919,
|
||||||
|
'Euml': 203,
|
||||||
|
'Gamma': 915,
|
||||||
|
'Iacute': 205,
|
||||||
|
'Icirc': 206,
|
||||||
|
'Igrave': 204,
|
||||||
|
'Iota': 921,
|
||||||
|
'Iuml': 207,
|
||||||
|
'Kappa': 922,
|
||||||
|
'Lambda': 923,
|
||||||
|
'Mu': 924,
|
||||||
|
'Ntilde': 209,
|
||||||
|
'Nu': 925,
|
||||||
|
'OElig': 338,
|
||||||
|
'Oacute': 211,
|
||||||
|
'Ocirc': 212,
|
||||||
|
'Ograve': 210,
|
||||||
|
'Omega': 937,
|
||||||
|
'Omicron': 927,
|
||||||
|
'Oslash': 216,
|
||||||
|
'Otilde': 213,
|
||||||
|
'Ouml': 214,
|
||||||
|
'Phi': 934,
|
||||||
|
'Pi': 928,
|
||||||
|
'Prime': 8243,
|
||||||
|
'Psi': 936,
|
||||||
|
'Rho': 929,
|
||||||
|
'Scaron': 352,
|
||||||
|
'Sigma': 931,
|
||||||
|
'THORN': 222,
|
||||||
|
'Tau': 932,
|
||||||
|
'Theta': 920,
|
||||||
|
'Uacute': 218,
|
||||||
|
'Ucirc': 219,
|
||||||
|
'Ugrave': 217,
|
||||||
|
'Upsilon': 933,
|
||||||
|
'Uuml': 220,
|
||||||
|
'Xi': 926,
|
||||||
|
'Yacute': 221,
|
||||||
|
'Yuml': 376,
|
||||||
|
'Zeta': 918,
|
||||||
|
'aacute': 225,
|
||||||
|
'acirc': 226,
|
||||||
|
'acute': 180,
|
||||||
|
'aelig': 230,
|
||||||
|
'agrave': 224,
|
||||||
|
'alefsym': 8501,
|
||||||
|
'alpha': 945,
|
||||||
|
'amp': 38,
|
||||||
|
'and': 8743,
|
||||||
|
'ang': 8736,
|
||||||
|
'apos': 39,
|
||||||
|
'aring': 229,
|
||||||
|
'asymp': 8776,
|
||||||
|
'atilde': 227,
|
||||||
|
'auml': 228,
|
||||||
|
'bdquo': 8222,
|
||||||
|
'beta': 946,
|
||||||
|
'brvbar': 166,
|
||||||
|
'bull': 8226,
|
||||||
|
'cap': 8745,
|
||||||
|
'ccedil': 231,
|
||||||
|
'cedil': 184,
|
||||||
|
'cent': 162,
|
||||||
|
'chi': 967,
|
||||||
|
'circ': 710,
|
||||||
|
'clubs': 9827,
|
||||||
|
'cong': 8773,
|
||||||
|
'copy': 169,
|
||||||
|
'crarr': 8629,
|
||||||
|
'cup': 8746,
|
||||||
|
'curren': 164,
|
||||||
|
'dArr': 8659,
|
||||||
|
'dagger': 8224,
|
||||||
|
'darr': 8595,
|
||||||
|
'deg': 176,
|
||||||
|
'delta': 948,
|
||||||
|
'diams': 9830,
|
||||||
|
'divide': 247,
|
||||||
|
'eacute': 233,
|
||||||
|
'ecirc': 234,
|
||||||
|
'egrave': 232,
|
||||||
|
'empty': 8709,
|
||||||
|
'emsp': 8195,
|
||||||
|
'ensp': 8194,
|
||||||
|
'epsilon': 949,
|
||||||
|
'equiv': 8801,
|
||||||
|
'eta': 951,
|
||||||
|
'eth': 240,
|
||||||
|
'euml': 235,
|
||||||
|
'euro': 8364,
|
||||||
|
'exist': 8707,
|
||||||
|
'fnof': 402,
|
||||||
|
'forall': 8704,
|
||||||
|
'frac12': 189,
|
||||||
|
'frac14': 188,
|
||||||
|
'frac34': 190,
|
||||||
|
'frasl': 8260,
|
||||||
|
'gamma': 947,
|
||||||
|
'ge': 8805,
|
||||||
|
'gt': 62,
|
||||||
|
'hArr': 8660,
|
||||||
|
'harr': 8596,
|
||||||
|
'hearts': 9829,
|
||||||
|
'hellip': 8230,
|
||||||
|
'iacute': 237,
|
||||||
|
'icirc': 238,
|
||||||
|
'iexcl': 161,
|
||||||
|
'igrave': 236,
|
||||||
|
'image': 8465,
|
||||||
|
'infin': 8734,
|
||||||
|
'int': 8747,
|
||||||
|
'iota': 953,
|
||||||
|
'iquest': 191,
|
||||||
|
'isin': 8712,
|
||||||
|
'iuml': 239,
|
||||||
|
'kappa': 954,
|
||||||
|
'lArr': 8656,
|
||||||
|
'lambda': 955,
|
||||||
|
'lang': 9001,
|
||||||
|
'laquo': 171,
|
||||||
|
'larr': 8592,
|
||||||
|
'lceil': 8968,
|
||||||
|
'ldquo': 8220,
|
||||||
|
'le': 8804,
|
||||||
|
'lfloor': 8970,
|
||||||
|
'lowast': 8727,
|
||||||
|
'loz': 9674,
|
||||||
|
'lrm': 8206,
|
||||||
|
'lsaquo': 8249,
|
||||||
|
'lsquo': 8216,
|
||||||
|
'lt': 60,
|
||||||
|
'macr': 175,
|
||||||
|
'mdash': 8212,
|
||||||
|
'micro': 181,
|
||||||
|
'middot': 183,
|
||||||
|
'minus': 8722,
|
||||||
|
'mu': 956,
|
||||||
|
'nabla': 8711,
|
||||||
|
'nbsp': 160,
|
||||||
|
'ndash': 8211,
|
||||||
|
'ne': 8800,
|
||||||
|
'ni': 8715,
|
||||||
|
'not': 172,
|
||||||
|
'notin': 8713,
|
||||||
|
'nsub': 8836,
|
||||||
|
'ntilde': 241,
|
||||||
|
'nu': 957,
|
||||||
|
'oacute': 243,
|
||||||
|
'ocirc': 244,
|
||||||
|
'oelig': 339,
|
||||||
|
'ograve': 242,
|
||||||
|
'oline': 8254,
|
||||||
|
'omega': 969,
|
||||||
|
'omicron': 959,
|
||||||
|
'oplus': 8853,
|
||||||
|
'or': 8744,
|
||||||
|
'ordf': 170,
|
||||||
|
'ordm': 186,
|
||||||
|
'oslash': 248,
|
||||||
|
'otilde': 245,
|
||||||
|
'otimes': 8855,
|
||||||
|
'ouml': 246,
|
||||||
|
'para': 182,
|
||||||
|
'part': 8706,
|
||||||
|
'permil': 8240,
|
||||||
|
'perp': 8869,
|
||||||
|
'phi': 966,
|
||||||
|
'pi': 960,
|
||||||
|
'piv': 982,
|
||||||
|
'plusmn': 177,
|
||||||
|
'pound': 163,
|
||||||
|
'prime': 8242,
|
||||||
|
'prod': 8719,
|
||||||
|
'prop': 8733,
|
||||||
|
'psi': 968,
|
||||||
|
'quot': 34,
|
||||||
|
'rArr': 8658,
|
||||||
|
'radic': 8730,
|
||||||
|
'rang': 9002,
|
||||||
|
'raquo': 187,
|
||||||
|
'rarr': 8594,
|
||||||
|
'rceil': 8969,
|
||||||
|
'rdquo': 8221,
|
||||||
|
'real': 8476,
|
||||||
|
'reg': 174,
|
||||||
|
'rfloor': 8971,
|
||||||
|
'rho': 961,
|
||||||
|
'rlm': 8207,
|
||||||
|
'rsaquo': 8250,
|
||||||
|
'rsquo': 8217,
|
||||||
|
'sbquo': 8218,
|
||||||
|
'scaron': 353,
|
||||||
|
'sdot': 8901,
|
||||||
|
'sect': 167,
|
||||||
|
'shy': 173,
|
||||||
|
'sigma': 963,
|
||||||
|
'sigmaf': 962,
|
||||||
|
'sim': 8764,
|
||||||
|
'spades': 9824,
|
||||||
|
'sub': 8834,
|
||||||
|
'sube': 8838,
|
||||||
|
'sum': 8721,
|
||||||
|
'sup': 8835,
|
||||||
|
'sup1': 185,
|
||||||
|
'sup2': 178,
|
||||||
|
'sup3': 179,
|
||||||
|
'supe': 8839,
|
||||||
|
'szlig': 223,
|
||||||
|
'tau': 964,
|
||||||
|
'there4': 8756,
|
||||||
|
'theta': 952,
|
||||||
|
'thetasym': 977,
|
||||||
|
'thinsp': 8201,
|
||||||
|
'thorn': 254,
|
||||||
|
'tilde': 732,
|
||||||
|
'times': 215,
|
||||||
|
'trade': 8482,
|
||||||
|
'uArr': 8657,
|
||||||
|
'uacute': 250,
|
||||||
|
'uarr': 8593,
|
||||||
|
'ucirc': 251,
|
||||||
|
'ugrave': 249,
|
||||||
|
'uml': 168,
|
||||||
|
'upsih': 978,
|
||||||
|
'upsilon': 965,
|
||||||
|
'uuml': 252,
|
||||||
|
'weierp': 8472,
|
||||||
|
'xi': 958,
|
||||||
|
'yacute': 253,
|
||||||
|
'yen': 165,
|
||||||
|
'yuml': 255,
|
||||||
|
'zeta': 950,
|
||||||
|
'zwj': 8205,
|
||||||
|
'zwnj': 8204
|
||||||
|
}
|
46
tools/external/markupsafe/_native.py
vendored
Normal file
46
tools/external/markupsafe/_native.py
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
markupsafe._native
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Native Python implementation the C module is not compiled.
|
||||||
|
|
||||||
|
:copyright: (c) 2010 by Armin Ronacher.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
from markupsafe import Markup
|
||||||
|
from markupsafe._compat import text_type
|
||||||
|
|
||||||
|
|
||||||
|
def escape(s):
|
||||||
|
"""Convert the characters &, <, >, ' and " in string s to HTML-safe
|
||||||
|
sequences. Use this if you need to display text that might contain
|
||||||
|
such characters in HTML. Marks return value as markup string.
|
||||||
|
"""
|
||||||
|
if hasattr(s, '__html__'):
|
||||||
|
return s.__html__()
|
||||||
|
return Markup(text_type(s)
|
||||||
|
.replace('&', '&')
|
||||||
|
.replace('>', '>')
|
||||||
|
.replace('<', '<')
|
||||||
|
.replace("'", ''')
|
||||||
|
.replace('"', '"')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def escape_silent(s):
|
||||||
|
"""Like :func:`escape` but converts `None` into an empty
|
||||||
|
markup string.
|
||||||
|
"""
|
||||||
|
if s is None:
|
||||||
|
return Markup()
|
||||||
|
return escape(s)
|
||||||
|
|
||||||
|
|
||||||
|
def soft_unicode(s):
|
||||||
|
"""Make a string unicode if it isn't already. That way a markup
|
||||||
|
string is not converted back to unicode.
|
||||||
|
"""
|
||||||
|
if not isinstance(s, text_type):
|
||||||
|
s = text_type(s)
|
||||||
|
return s
|
239
tools/external/markupsafe/_speedups.c
vendored
Normal file
239
tools/external/markupsafe/_speedups.c
vendored
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
/**
|
||||||
|
* markupsafe._speedups
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* This module implements functions for automatic escaping in C for better
|
||||||
|
* performance.
|
||||||
|
*
|
||||||
|
* :copyright: (c) 2010 by Armin Ronacher.
|
||||||
|
* :license: BSD.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
#define ESCAPED_CHARS_TABLE_SIZE 63
|
||||||
|
#define UNICHR(x) (PyUnicode_AS_UNICODE((PyUnicodeObject*)PyUnicode_DecodeASCII(x, strlen(x), NULL)));
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
|
||||||
|
typedef int Py_ssize_t;
|
||||||
|
#define PY_SSIZE_T_MAX INT_MAX
|
||||||
|
#define PY_SSIZE_T_MIN INT_MIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* markup;
|
||||||
|
static Py_ssize_t escaped_chars_delta_len[ESCAPED_CHARS_TABLE_SIZE];
|
||||||
|
static Py_UNICODE *escaped_chars_repl[ESCAPED_CHARS_TABLE_SIZE];
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_constants(void)
|
||||||
|
{
|
||||||
|
PyObject *module;
|
||||||
|
/* happing of characters to replace */
|
||||||
|
escaped_chars_repl['"'] = UNICHR(""");
|
||||||
|
escaped_chars_repl['\''] = UNICHR("'");
|
||||||
|
escaped_chars_repl['&'] = UNICHR("&");
|
||||||
|
escaped_chars_repl['<'] = UNICHR("<");
|
||||||
|
escaped_chars_repl['>'] = UNICHR(">");
|
||||||
|
|
||||||
|
/* lengths of those characters when replaced - 1 */
|
||||||
|
memset(escaped_chars_delta_len, 0, sizeof (escaped_chars_delta_len));
|
||||||
|
escaped_chars_delta_len['"'] = escaped_chars_delta_len['\''] = \
|
||||||
|
escaped_chars_delta_len['&'] = 4;
|
||||||
|
escaped_chars_delta_len['<'] = escaped_chars_delta_len['>'] = 3;
|
||||||
|
|
||||||
|
/* import markup type so that we can mark the return value */
|
||||||
|
module = PyImport_ImportModule("markupsafe");
|
||||||
|
if (!module)
|
||||||
|
return 0;
|
||||||
|
markup = PyObject_GetAttrString(module, "Markup");
|
||||||
|
Py_DECREF(module);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
escape_unicode(PyUnicodeObject *in)
|
||||||
|
{
|
||||||
|
PyUnicodeObject *out;
|
||||||
|
Py_UNICODE *inp = PyUnicode_AS_UNICODE(in);
|
||||||
|
const Py_UNICODE *inp_end = PyUnicode_AS_UNICODE(in) + PyUnicode_GET_SIZE(in);
|
||||||
|
Py_UNICODE *next_escp;
|
||||||
|
Py_UNICODE *outp;
|
||||||
|
Py_ssize_t delta=0, erepl=0, delta_len=0;
|
||||||
|
|
||||||
|
/* First we need to figure out how long the escaped string will be */
|
||||||
|
while (*(inp) || inp < inp_end) {
|
||||||
|
if (*inp < ESCAPED_CHARS_TABLE_SIZE) {
|
||||||
|
delta += escaped_chars_delta_len[*inp];
|
||||||
|
erepl += !!escaped_chars_delta_len[*inp];
|
||||||
|
}
|
||||||
|
++inp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we need to escape anything at all? */
|
||||||
|
if (!erepl) {
|
||||||
|
Py_INCREF(in);
|
||||||
|
return (PyObject*)in;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = (PyUnicodeObject*)PyUnicode_FromUnicode(NULL, PyUnicode_GET_SIZE(in) + delta);
|
||||||
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
outp = PyUnicode_AS_UNICODE(out);
|
||||||
|
inp = PyUnicode_AS_UNICODE(in);
|
||||||
|
while (erepl-- > 0) {
|
||||||
|
/* look for the next substitution */
|
||||||
|
next_escp = inp;
|
||||||
|
while (next_escp < inp_end) {
|
||||||
|
if (*next_escp < ESCAPED_CHARS_TABLE_SIZE &&
|
||||||
|
(delta_len = escaped_chars_delta_len[*next_escp])) {
|
||||||
|
++delta_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++next_escp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_escp > inp) {
|
||||||
|
/* copy unescaped chars between inp and next_escp */
|
||||||
|
Py_UNICODE_COPY(outp, inp, next_escp-inp);
|
||||||
|
outp += next_escp - inp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* escape 'next_escp' */
|
||||||
|
Py_UNICODE_COPY(outp, escaped_chars_repl[*next_escp], delta_len);
|
||||||
|
outp += delta_len;
|
||||||
|
|
||||||
|
inp = next_escp + 1;
|
||||||
|
}
|
||||||
|
if (inp < inp_end)
|
||||||
|
Py_UNICODE_COPY(outp, inp, PyUnicode_GET_SIZE(in) - (inp - PyUnicode_AS_UNICODE(in)));
|
||||||
|
|
||||||
|
return (PyObject*)out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
escape(PyObject *self, PyObject *text)
|
||||||
|
{
|
||||||
|
PyObject *s = NULL, *rv = NULL, *html;
|
||||||
|
|
||||||
|
/* we don't have to escape integers, bools or floats */
|
||||||
|
if (PyLong_CheckExact(text) ||
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
PyInt_CheckExact(text) ||
|
||||||
|
#endif
|
||||||
|
PyFloat_CheckExact(text) || PyBool_Check(text) ||
|
||||||
|
text == Py_None)
|
||||||
|
return PyObject_CallFunctionObjArgs(markup, text, NULL);
|
||||||
|
|
||||||
|
/* if the object has an __html__ method that performs the escaping */
|
||||||
|
html = PyObject_GetAttrString(text, "__html__");
|
||||||
|
if (html) {
|
||||||
|
rv = PyObject_CallObject(html, NULL);
|
||||||
|
Py_DECREF(html);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* otherwise make the object unicode if it isn't, then escape */
|
||||||
|
PyErr_Clear();
|
||||||
|
if (!PyUnicode_Check(text)) {
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
PyObject *unicode = PyObject_Unicode(text);
|
||||||
|
#else
|
||||||
|
PyObject *unicode = PyObject_Str(text);
|
||||||
|
#endif
|
||||||
|
if (!unicode)
|
||||||
|
return NULL;
|
||||||
|
s = escape_unicode((PyUnicodeObject*)unicode);
|
||||||
|
Py_DECREF(unicode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s = escape_unicode((PyUnicodeObject*)text);
|
||||||
|
|
||||||
|
/* convert the unicode string into a markup object. */
|
||||||
|
rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL);
|
||||||
|
Py_DECREF(s);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
escape_silent(PyObject *self, PyObject *text)
|
||||||
|
{
|
||||||
|
if (text != Py_None)
|
||||||
|
return escape(self, text);
|
||||||
|
return PyObject_CallFunctionObjArgs(markup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
soft_unicode(PyObject *self, PyObject *s)
|
||||||
|
{
|
||||||
|
if (!PyUnicode_Check(s))
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
return PyObject_Unicode(s);
|
||||||
|
#else
|
||||||
|
return PyObject_Str(s);
|
||||||
|
#endif
|
||||||
|
Py_INCREF(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyMethodDef module_methods[] = {
|
||||||
|
{"escape", (PyCFunction)escape, METH_O,
|
||||||
|
"escape(s) -> markup\n\n"
|
||||||
|
"Convert the characters &, <, >, ', and \" in string s to HTML-safe\n"
|
||||||
|
"sequences. Use this if you need to display text that might contain\n"
|
||||||
|
"such characters in HTML. Marks return value as markup string."},
|
||||||
|
{"escape_silent", (PyCFunction)escape_silent, METH_O,
|
||||||
|
"escape_silent(s) -> markup\n\n"
|
||||||
|
"Like escape but converts None to an empty string."},
|
||||||
|
{"soft_unicode", (PyCFunction)soft_unicode, METH_O,
|
||||||
|
"soft_unicode(object) -> string\n\n"
|
||||||
|
"Make a string unicode if it isn't already. That way a markup\n"
|
||||||
|
"string is not converted back to unicode."},
|
||||||
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
|
||||||
|
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
|
||||||
|
#define PyMODINIT_FUNC void
|
||||||
|
#endif
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
init_speedups(void)
|
||||||
|
{
|
||||||
|
if (!init_constants())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Py_InitModule3("markupsafe._speedups", module_methods, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* Python 3.x module initialization */
|
||||||
|
|
||||||
|
static struct PyModuleDef module_definition = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
"markupsafe._speedups",
|
||||||
|
NULL,
|
||||||
|
-1,
|
||||||
|
module_methods,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
PyInit__speedups(void)
|
||||||
|
{
|
||||||
|
if (!init_constants())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return PyModule_Create(&module_definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
179
tools/external/markupsafe/tests.py
vendored
Normal file
179
tools/external/markupsafe/tests.py
vendored
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import gc
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from markupsafe import Markup, escape, escape_silent
|
||||||
|
from markupsafe._compat import text_type
|
||||||
|
|
||||||
|
|
||||||
|
class MarkupTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_adding(self):
|
||||||
|
# adding two strings should escape the unsafe one
|
||||||
|
unsafe = '<script type="application/x-some-script">alert("foo");</script>'
|
||||||
|
safe = Markup('<em>username</em>')
|
||||||
|
assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe)
|
||||||
|
|
||||||
|
def test_string_interpolation(self):
|
||||||
|
# string interpolations are safe to use too
|
||||||
|
assert Markup('<em>%s</em>') % '<bad user>' == \
|
||||||
|
'<em><bad user></em>'
|
||||||
|
assert Markup('<em>%(username)s</em>') % {
|
||||||
|
'username': '<bad user>'
|
||||||
|
} == '<em><bad user></em>'
|
||||||
|
|
||||||
|
assert Markup('%i') % 3.14 == '3'
|
||||||
|
assert Markup('%.2f') % 3.14 == '3.14'
|
||||||
|
|
||||||
|
def test_type_behavior(self):
|
||||||
|
# an escaped object is markup too
|
||||||
|
assert type(Markup('foo') + 'bar') is Markup
|
||||||
|
|
||||||
|
# and it implements __html__ by returning itself
|
||||||
|
x = Markup("foo")
|
||||||
|
assert x.__html__() is x
|
||||||
|
|
||||||
|
def test_html_interop(self):
|
||||||
|
# it also knows how to treat __html__ objects
|
||||||
|
class Foo(object):
|
||||||
|
def __html__(self):
|
||||||
|
return '<em>awesome</em>'
|
||||||
|
def __unicode__(self):
|
||||||
|
return 'awesome'
|
||||||
|
__str__ = __unicode__
|
||||||
|
assert Markup(Foo()) == '<em>awesome</em>'
|
||||||
|
assert Markup('<strong>%s</strong>') % Foo() == \
|
||||||
|
'<strong><em>awesome</em></strong>'
|
||||||
|
|
||||||
|
def test_tuple_interpol(self):
|
||||||
|
self.assertEqual(Markup('<em>%s:%s</em>') % (
|
||||||
|
'<foo>',
|
||||||
|
'<bar>',
|
||||||
|
), Markup(u'<em><foo>:<bar></em>'))
|
||||||
|
|
||||||
|
def test_dict_interpol(self):
|
||||||
|
self.assertEqual(Markup('<em>%(foo)s</em>') % {
|
||||||
|
'foo': '<foo>',
|
||||||
|
}, Markup(u'<em><foo></em>'))
|
||||||
|
self.assertEqual(Markup('<em>%(foo)s:%(bar)s</em>') % {
|
||||||
|
'foo': '<foo>',
|
||||||
|
'bar': '<bar>',
|
||||||
|
}, Markup(u'<em><foo>:<bar></em>'))
|
||||||
|
|
||||||
|
def test_escaping(self):
|
||||||
|
# escaping and unescaping
|
||||||
|
assert escape('"<>&\'') == '"<>&''
|
||||||
|
assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar"
|
||||||
|
assert Markup("<test>").unescape() == "<test>"
|
||||||
|
|
||||||
|
def test_formatting(self):
|
||||||
|
for actual, expected in (
|
||||||
|
(Markup('%i') % 3.14, '3'),
|
||||||
|
(Markup('%.2f') % 3.14159, '3.14'),
|
||||||
|
(Markup('%s %s %s') % ('<', 123, '>'), '< 123 >'),
|
||||||
|
(Markup('<em>{awesome}</em>').format(awesome='<awesome>'),
|
||||||
|
'<em><awesome></em>'),
|
||||||
|
(Markup('{0[1][bar]}').format([0, {'bar': '<bar/>'}]),
|
||||||
|
'<bar/>'),
|
||||||
|
(Markup('{0[1][bar]}').format([0, {'bar': Markup('<bar/>')}]),
|
||||||
|
'<bar/>')):
|
||||||
|
assert actual == expected, "%r should be %r!" % (actual, expected)
|
||||||
|
|
||||||
|
# This is new in 2.7
|
||||||
|
if sys.version_info >= (2, 7):
|
||||||
|
def test_formatting_empty(self):
|
||||||
|
formatted = Markup('{}').format(0)
|
||||||
|
assert formatted == Markup('0')
|
||||||
|
|
||||||
|
def test_custom_formatting(self):
|
||||||
|
class HasHTMLOnly(object):
|
||||||
|
def __html__(self):
|
||||||
|
return Markup('<foo>')
|
||||||
|
|
||||||
|
class HasHTMLAndFormat(object):
|
||||||
|
def __html__(self):
|
||||||
|
return Markup('<foo>')
|
||||||
|
def __html_format__(self, spec):
|
||||||
|
return Markup('<FORMAT>')
|
||||||
|
|
||||||
|
assert Markup('{0}').format(HasHTMLOnly()) == Markup('<foo>')
|
||||||
|
assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('<FORMAT>')
|
||||||
|
|
||||||
|
def test_complex_custom_formatting(self):
|
||||||
|
class User(object):
|
||||||
|
def __init__(self, id, username):
|
||||||
|
self.id = id
|
||||||
|
self.username = username
|
||||||
|
def __html_format__(self, format_spec):
|
||||||
|
if format_spec == 'link':
|
||||||
|
return Markup('<a href="/user/{0}">{1}</a>').format(
|
||||||
|
self.id,
|
||||||
|
self.__html__(),
|
||||||
|
)
|
||||||
|
elif format_spec:
|
||||||
|
raise ValueError('Invalid format spec')
|
||||||
|
return self.__html__()
|
||||||
|
def __html__(self):
|
||||||
|
return Markup('<span class=user>{0}</span>').format(self.username)
|
||||||
|
|
||||||
|
user = User(1, 'foo')
|
||||||
|
assert Markup('<p>User: {0:link}').format(user) == \
|
||||||
|
Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>')
|
||||||
|
|
||||||
|
def test_all_set(self):
|
||||||
|
import markupsafe as markup
|
||||||
|
for item in markup.__all__:
|
||||||
|
getattr(markup, item)
|
||||||
|
|
||||||
|
def test_escape_silent(self):
|
||||||
|
assert escape_silent(None) == Markup()
|
||||||
|
assert escape(None) == Markup(None)
|
||||||
|
assert escape_silent('<foo>') == Markup(u'<foo>')
|
||||||
|
|
||||||
|
def test_splitting(self):
|
||||||
|
self.assertEqual(Markup('a b').split(), [
|
||||||
|
Markup('a'),
|
||||||
|
Markup('b')
|
||||||
|
])
|
||||||
|
self.assertEqual(Markup('a b').rsplit(), [
|
||||||
|
Markup('a'),
|
||||||
|
Markup('b')
|
||||||
|
])
|
||||||
|
self.assertEqual(Markup('a\nb').splitlines(), [
|
||||||
|
Markup('a'),
|
||||||
|
Markup('b')
|
||||||
|
])
|
||||||
|
|
||||||
|
def test_mul(self):
|
||||||
|
self.assertEqual(Markup('a') * 3, Markup('aaa'))
|
||||||
|
|
||||||
|
|
||||||
|
class MarkupLeakTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_markup_leaks(self):
|
||||||
|
counts = set()
|
||||||
|
for count in range(20):
|
||||||
|
for item in range(1000):
|
||||||
|
escape("foo")
|
||||||
|
escape("<foo>")
|
||||||
|
escape(u"foo")
|
||||||
|
escape(u"<foo>")
|
||||||
|
counts.add(len(gc.get_objects()))
|
||||||
|
assert len(counts) == 1, 'ouch, c extension seems to leak objects'
|
||||||
|
|
||||||
|
|
||||||
|
def suite():
|
||||||
|
suite = unittest.TestSuite()
|
||||||
|
suite.addTest(unittest.makeSuite(MarkupTestCase))
|
||||||
|
|
||||||
|
# this test only tests the c extension
|
||||||
|
if not hasattr(escape, 'func_code'):
|
||||||
|
suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
|
||||||
|
|
||||||
|
return suite
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main(defaultTest='suite')
|
||||||
|
|
||||||
|
# vim:sts=4:sw=4:et:
|
Loading…
Reference in a new issue