MarkupSafe-1.0/0000755000076500000240000000000013057551173014556 5ustar mitsuhikostaff00000000000000MarkupSafe-1.0/AUTHORS0000644000076500000240000000037012371453456015631 0ustar mitsuhikostaff00000000000000MarkupSafe is written and maintained by Armin Ronacher and various contributors: Development Lead ```````````````` - Armin Ronacher Patches and Suggestions ``````````````````````` - Georg Brandl - Mickaël Guérin MarkupSafe-1.0/CHANGES0000644000076500000240000000153512645541645015562 0ustar mitsuhikostaff00000000000000MarkupSafe Changelog ==================== Version 1.0 ----------- - Fixed custom types not invoking `__unicode__` when used with `format()`. - Added `__version__` module attribute - Improve unescape code to leave lone ampersands alone. Version 0.18 ------------ - Fixed `__mul__` and string splitting on Python 3. Version 0.17 ------------ - Fixed a bug with broken interpolation on tuples. Version 0.16 ------------ - Improved Python 3 Support and removed 2to3 - Removed support for Python 3.2 and 2.5 Version 0.15 ------------ - Fixed a typo that caused the library to fail to install on pypy and jython -.- Version 0.14 ------------ - Release fix for 0.13. Version 0.13 ------------ - Do not attempt to compile extension for PyPy or Jython. - Work around some 64bit Windows issues. Version 0.12 ------------ - improved PyPy compatibility MarkupSafe-1.0/LICENSE0000644000076500000240000000305612371453456015572 0ustar mitsuhikostaff00000000000000Copyright (c) 2010 by Armin Ronacher and contributors. See AUTHORS for more details. Some rights reserved. Redistribution and use in source and binary forms of the software as well as documentation, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MarkupSafe-1.0/MANIFEST.in0000644000076500000240000000011213057551010016274 0ustar mitsuhikostaff00000000000000include AUTHORS CHANGES LICENSE tests.py recursive-include markupsafe *.c MarkupSafe-1.0/markupsafe/0000755000076500000240000000000013057551173016714 5ustar mitsuhikostaff00000000000000MarkupSafe-1.0/markupsafe/__init__.py0000644000076500000240000002471113057551037021031 0ustar mitsuhikostaff00000000000000# -*- 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 __version__ = "1.0" __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 World!") Markup(u'Hello World!') >>> class Foo(object): ... def __html__(self): ... return 'foo' ... >>> Markup(Foo()) Markup(u'foo') 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 World!") 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("%s") >>> em % "foo & bar" Markup(u'foo & bar') >>> strong = Markup("%(text)s") >>> strong % {'text': 'hacker here'} Markup(u'<blink>hacker here</blink>') >>> Markup("Hello ") + "" Markup(u'Hello <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 » About").unescape() u'Main \xbb About' """ 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 # Don't modify unexpected input. return m.group() 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 » About").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: # We need to make sure the format spec is unicode here as # otherwise the wrong callback methods are invoked. For # instance a byte string there would invoke __str__ and # not __unicode__. rv = string.Formatter.format_field( self, value, text_type(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') MarkupSafe-1.0/markupsafe/_compat.py0000644000076500000240000000106512371453456020715 0ustar mitsuhikostaff00000000000000# -*- 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() MarkupSafe-1.0/markupsafe/_constants.py0000644000076500000240000001127312371453456021450 0ustar mitsuhikostaff00000000000000# -*- 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 } MarkupSafe-1.0/markupsafe/_native.py0000644000076500000240000000224312371453456020717 0ustar mitsuhikostaff00000000000000# -*- 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 MarkupSafe-1.0/markupsafe/_speedups.c0000644000076500000240000001346012645541402021047 0ustar mitsuhikostaff00000000000000/** * markupsafe._speedups * ~~~~~~~~~~~~~~~~~~~~ * * This module implements functions for automatic escaping in C for better * performance. * * :copyright: (c) 2010 by Armin Ronacher. * :license: BSD. */ #include #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; /* mapping 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 MarkupSafe-1.0/MarkupSafe.egg-info/0000755000076500000240000000000013057551173020306 5ustar mitsuhikostaff00000000000000MarkupSafe-1.0/MarkupSafe.egg-info/dependency_links.txt0000644000076500000240000000000113057551172024353 0ustar mitsuhikostaff00000000000000 MarkupSafe-1.0/MarkupSafe.egg-info/not-zip-safe0000644000076500000240000000000112371453461022533 0ustar mitsuhikostaff00000000000000 MarkupSafe-1.0/MarkupSafe.egg-info/PKG-INFO0000644000076500000240000001175113057551172021407 0ustar mitsuhikostaff00000000000000Metadata-Version: 1.1 Name: MarkupSafe Version: 1.0 Summary: Implements a XML/HTML/XHTML Markup safe string for Python Home-page: http://github.com/pallets/markupsafe Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD Description: MarkupSafe ========== Implements a unicode subclass that supports HTML strings: .. code-block:: python >>> from markupsafe import Markup, escape >>> escape("") Markup(u'<script>alert(document.cookie);</script>') >>> tmpl = Markup("%s") >>> tmpl % "Peter > Lustig" Markup(u'Peter > Lustig') If you want to make an object unicode that is not yet unicode but don't want to lose the taint information, you can use the ``soft_unicode`` function. (On Python 3 you can also use ``soft_str`` which is a different name for the same function). .. code-block:: python >>> from markupsafe import soft_unicode >>> soft_unicode(42) u'42' >>> soft_unicode(Markup('foo')) Markup(u'foo') HTML Representations -------------------- Objects can customize their HTML markup equivalent by overriding the ``__html__`` function: .. code-block:: python >>> class Foo(object): ... def __html__(self): ... return 'Nice' ... >>> escape(Foo()) Markup(u'Nice') >>> Markup(Foo()) Markup(u'Nice') Silent Escapes -------------- Since MarkupSafe 0.10 there is now also a separate escape function called ``escape_silent`` that returns an empty string for ``None`` for consistency with other systems that return empty strings for ``None`` when escaping (for instance Pylons' webhelpers). If you also want to use this for the escape method of the Markup object, you can create your own subclass that does that: .. code-block:: python from markupsafe import Markup, escape_silent as escape class SilentMarkup(Markup): __slots__ = () @classmethod def escape(cls, s): return cls(escape(s)) New-Style String Formatting --------------------------- Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and 3.x are now fully supported. Previously the escape behavior of those functions was spotty at best. The new implementations operates under the following algorithm: 1. if an object has an ``__html_format__`` method it is called as replacement for ``__format__`` with the format specifier. It either has to return a string or markup object. 2. if an object has an ``__html__`` method it is called. 3. otherwise the default format system of Python kicks in and the result is HTML escaped. Here is how you can implement your own formatting: .. code-block:: python 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('{1}').format( self.id, self.__html__(), ) elif format_spec: raise ValueError('Invalid format spec') return self.__html__() def __html__(self): return Markup('{0}').format(self.username) And to format that user: .. code-block:: python >>> user = User(1, 'foo') >>> Markup('

User: {0:link}').format(user) Markup(u'

User: foo') Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Text Processing :: Markup :: HTML MarkupSafe-1.0/MarkupSafe.egg-info/SOURCES.txt0000644000076500000240000000054613057551173022177 0ustar mitsuhikostaff00000000000000AUTHORS CHANGES LICENSE MANIFEST.in README.rst setup.cfg setup.py tests.py MarkupSafe.egg-info/PKG-INFO MarkupSafe.egg-info/SOURCES.txt MarkupSafe.egg-info/dependency_links.txt MarkupSafe.egg-info/not-zip-safe MarkupSafe.egg-info/top_level.txt markupsafe/__init__.py markupsafe/_compat.py markupsafe/_constants.py markupsafe/_native.py markupsafe/_speedups.cMarkupSafe-1.0/MarkupSafe.egg-info/top_level.txt0000644000076500000240000000001313057551172023031 0ustar mitsuhikostaff00000000000000markupsafe MarkupSafe-1.0/PKG-INFO0000644000076500000240000001175113057551173015660 0ustar mitsuhikostaff00000000000000Metadata-Version: 1.1 Name: MarkupSafe Version: 1.0 Summary: Implements a XML/HTML/XHTML Markup safe string for Python Home-page: http://github.com/pallets/markupsafe Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD Description: MarkupSafe ========== Implements a unicode subclass that supports HTML strings: .. code-block:: python >>> from markupsafe import Markup, escape >>> escape("") Markup(u'<script>alert(document.cookie);</script>') >>> tmpl = Markup("%s") >>> tmpl % "Peter > Lustig" Markup(u'Peter > Lustig') If you want to make an object unicode that is not yet unicode but don't want to lose the taint information, you can use the ``soft_unicode`` function. (On Python 3 you can also use ``soft_str`` which is a different name for the same function). .. code-block:: python >>> from markupsafe import soft_unicode >>> soft_unicode(42) u'42' >>> soft_unicode(Markup('foo')) Markup(u'foo') HTML Representations -------------------- Objects can customize their HTML markup equivalent by overriding the ``__html__`` function: .. code-block:: python >>> class Foo(object): ... def __html__(self): ... return 'Nice' ... >>> escape(Foo()) Markup(u'Nice') >>> Markup(Foo()) Markup(u'Nice') Silent Escapes -------------- Since MarkupSafe 0.10 there is now also a separate escape function called ``escape_silent`` that returns an empty string for ``None`` for consistency with other systems that return empty strings for ``None`` when escaping (for instance Pylons' webhelpers). If you also want to use this for the escape method of the Markup object, you can create your own subclass that does that: .. code-block:: python from markupsafe import Markup, escape_silent as escape class SilentMarkup(Markup): __slots__ = () @classmethod def escape(cls, s): return cls(escape(s)) New-Style String Formatting --------------------------- Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and 3.x are now fully supported. Previously the escape behavior of those functions was spotty at best. The new implementations operates under the following algorithm: 1. if an object has an ``__html_format__`` method it is called as replacement for ``__format__`` with the format specifier. It either has to return a string or markup object. 2. if an object has an ``__html__`` method it is called. 3. otherwise the default format system of Python kicks in and the result is HTML escaped. Here is how you can implement your own formatting: .. code-block:: python 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('{1}').format( self.id, self.__html__(), ) elif format_spec: raise ValueError('Invalid format spec') return self.__html__() def __html__(self): return Markup('{0}').format(self.username) And to format that user: .. code-block:: python >>> user = User(1, 'foo') >>> Markup('

User: {0:link}').format(user) Markup(u'

User: foo') Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher. Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Text Processing :: Markup :: HTML MarkupSafe-1.0/README.rst0000644000076500000240000000650313057551010016237 0ustar mitsuhikostaff00000000000000MarkupSafe ========== Implements a unicode subclass that supports HTML strings: .. code-block:: python >>> from markupsafe import Markup, escape >>> escape("") Markup(u'<script>alert(document.cookie);</script>') >>> tmpl = Markup("%s") >>> tmpl % "Peter > Lustig" Markup(u'Peter > Lustig') If you want to make an object unicode that is not yet unicode but don't want to lose the taint information, you can use the ``soft_unicode`` function. (On Python 3 you can also use ``soft_str`` which is a different name for the same function). .. code-block:: python >>> from markupsafe import soft_unicode >>> soft_unicode(42) u'42' >>> soft_unicode(Markup('foo')) Markup(u'foo') HTML Representations -------------------- Objects can customize their HTML markup equivalent by overriding the ``__html__`` function: .. code-block:: python >>> class Foo(object): ... def __html__(self): ... return 'Nice' ... >>> escape(Foo()) Markup(u'Nice') >>> Markup(Foo()) Markup(u'Nice') Silent Escapes -------------- Since MarkupSafe 0.10 there is now also a separate escape function called ``escape_silent`` that returns an empty string for ``None`` for consistency with other systems that return empty strings for ``None`` when escaping (for instance Pylons' webhelpers). If you also want to use this for the escape method of the Markup object, you can create your own subclass that does that: .. code-block:: python from markupsafe import Markup, escape_silent as escape class SilentMarkup(Markup): __slots__ = () @classmethod def escape(cls, s): return cls(escape(s)) New-Style String Formatting --------------------------- Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and 3.x are now fully supported. Previously the escape behavior of those functions was spotty at best. The new implementations operates under the following algorithm: 1. if an object has an ``__html_format__`` method it is called as replacement for ``__format__`` with the format specifier. It either has to return a string or markup object. 2. if an object has an ``__html__`` method it is called. 3. otherwise the default format system of Python kicks in and the result is HTML escaped. Here is how you can implement your own formatting: .. code-block:: python 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('{1}').format( self.id, self.__html__(), ) elif format_spec: raise ValueError('Invalid format spec') return self.__html__() def __html__(self): return Markup('{0}').format(self.username) And to format that user: .. code-block:: python >>> user = User(1, 'foo') >>> Markup('

User: {0:link}').format(user) Markup(u'

User: foo') Markupsafe supports Python 2.6, 2.7 and Python 3.3 and higher. MarkupSafe-1.0/setup.cfg0000644000076500000240000000013613057551173016377 0ustar mitsuhikostaff00000000000000[metadata] license_file = LICENSE [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 MarkupSafe-1.0/setup.py0000755000076500000240000000753613057551010016274 0ustar mitsuhikostaff00000000000000#!/usr/bin/env python import os import re import ast import sys from setuptools import setup, Extension, Feature from distutils.command.build_ext import build_ext from distutils.errors import CCompilerError, DistutilsExecError, \ DistutilsPlatformError # fail safe compilation shamelessly stolen from the simplejson # setup.py file. Original author: Bob Ippolito is_jython = 'java' in sys.platform is_pypy = hasattr(sys, 'pypy_version_info') with open('markupsafe/__init__.py') as f: version = ast.literal_eval(re.search( '^__version__\s+=\s+(.*?)$(?sm)', f.read()).group(1)) speedups = Feature( 'optional C speed-enhancement module', standard=True, ext_modules=[ Extension('markupsafe._speedups', ['markupsafe/_speedups.c']), ], ) # Known errors when running build_ext.build_extension method ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError) if sys.platform == 'win32' and sys.version_info > (2, 6): # 2.6's distutils.msvc9compiler can raise an IOError when failing to # find the compiler ext_errors += (IOError,) # Known errors when running build_ext.run method run_errors = (DistutilsPlatformError,) if sys.platform == 'darwin': run_errors += (SystemError,) class BuildFailed(Exception): pass class ve_build_ext(build_ext): """This class allows C extension building to fail.""" def run(self): try: build_ext.run(self) except run_errors: raise BuildFailed() def build_extension(self, ext): try: build_ext.build_extension(self, ext) except ext_errors: raise BuildFailed() except ValueError: # this can happen on Windows 64 bit, see Python issue 7511 if "'path'" in str(sys.exc_info()[1]): # works with Python 2 and 3 raise BuildFailed() raise def echo(msg=''): sys.stdout.write(msg + '\n') readme = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read() def run_setup(with_binary): features = {} if with_binary: features['speedups'] = speedups setup( name='MarkupSafe', version=version, url='http://github.com/pallets/markupsafe', license='BSD', author='Armin Ronacher', author_email='armin.ronacher@active-4.com', description='Implements a XML/HTML/XHTML Markup safe string for Python', long_description=readme, zip_safe=False, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Text Processing :: Markup :: HTML' ], packages=['markupsafe'], test_suite='tests.suite', include_package_data=True, cmdclass={'build_ext': ve_build_ext}, features=features, ) def try_building_extension(): try: run_setup(True) except BuildFailed: LINE = '=' * 74 BUILD_EXT_WARNING = 'WARNING: The C extension could not be ' \ 'compiled, speedups are not enabled.' echo(LINE) echo(BUILD_EXT_WARNING) echo('Failure information, if any, is above.') echo('Retrying the build without the C extension now.') echo() run_setup(False) echo(LINE) echo(BUILD_EXT_WARNING) echo('Plain-Python installation succeeded.') echo(LINE) if not (is_pypy or is_jython): try_building_extension() else: run_setup(False) MarkupSafe-1.0/tests.py0000755000076500000240000001574013057551010016272 0ustar mitsuhikostaff00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import gc import sys import unittest from markupsafe import Markup, escape, escape_silent from markupsafe._compat import text_type, PY2 class MarkupTestCase(unittest.TestCase): def test_adding(self): # adding two strings should escape the unsafe one unsafe = '' safe = Markup('username') assert unsafe + safe == text_type(escape(unsafe)) + text_type(safe) def test_string_interpolation(self): # string interpolations are safe to use too assert Markup('%s') % '' == \ '<bad user>' assert Markup('%(username)s') % { 'username': '' } == '<bad user>' 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 'awesome' def __unicode__(self): return 'awesome' __str__ = __unicode__ assert Markup(Foo()) == 'awesome' assert Markup('%s') % Foo() == \ 'awesome' def test_tuple_interpol(self): self.assertEqual(Markup('%s:%s') % ( '', '', ), Markup(u'<foo>:<bar>')) def test_dict_interpol(self): self.assertEqual(Markup('%(foo)s') % { 'foo': '', }, Markup(u'<foo>')) self.assertEqual(Markup('%(foo)s:%(bar)s') % { 'foo': '', 'bar': '', }, Markup(u'<foo>:<bar>')) def test_escaping(self): # escaping assert escape('"<>&\'') == '"<>&'' assert Markup("Foo & Bar").striptags() == "Foo & Bar" def test_unescape(self): assert Markup("<test>").unescape() == "" assert "jack & tavi are cooler than mike & russ" == \ Markup("jack & tavi are cooler than mike & russ").unescape(), \ Markup("jack & tavi are cooler than mike & russ").unescape() # Test that unescape is idempotent original = '&foo;' once = Markup(original).unescape() twice = Markup(once).unescape() expected = "&foo;" assert expected == once == twice, (once, twice) 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('{awesome}').format(awesome=''), '<awesome>'), (Markup('{0[1][bar]}').format([0, {'bar': ''}]), '<bar/>'), (Markup('{0[1][bar]}').format([0, {'bar': Markup('')}]), '')): 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('') class HasHTMLAndFormat(object): def __html__(self): return Markup('') def __html_format__(self, spec): return Markup('') assert Markup('{0}').format(HasHTMLOnly()) == Markup('') assert Markup('{0}').format(HasHTMLAndFormat()) == Markup('') 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('{1}').format( self.id, self.__html__(), ) elif format_spec: raise ValueError('Invalid format spec') return self.__html__() def __html__(self): return Markup('{0}').format(self.username) user = User(1, 'foo') assert Markup('

User: {0:link}').format(user) == \ Markup('

User: foo') def test_formatting_with_objects(self): class Stringable(object): def __unicode__(self): return u'строка' if PY2: def __str__(self): return 'some other value' else: __str__ = __unicode__ assert Markup('{s}').format(s=Stringable()) == \ Markup(u'строка') 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('') == 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("") escape(u"foo") escape(u"") if hasattr(sys, 'pypy_version_info'): gc.collect() counts.add(len(gc.get_objects())) assert len(counts) == 1, 'ouch, c extension seems to ' \ 'leak objects, got: ' + str(len(counts)) 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: