summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2013-05-20 19:11:32 +0100
committerArmin Ronacher <armin.ronacher@active-4.com>2013-05-20 19:11:32 +0100
commit08c34a3315ec94b237100dd42d4ddd7f406942d9 (patch)
treef58f4db3470f70d6a9a598927c5731119b3de592
parent7415f6f8816e8eae1e34db76504062e98e5e6ab0 (diff)
downloadmarkupsafe-08c34a3315ec94b237100dd42d4ddd7f406942d9.tar.gz
Switch to native port and remove 2to3
-rw-r--r--markupsafe/__init__.py60
-rw-r--r--markupsafe/_native.py7
-rw-r--r--markupsafe/tests.py52
-rw-r--r--setup.py6
4 files changed, 45 insertions, 80 deletions
diff --git a/markupsafe/__init__.py b/markupsafe/__init__.py
index 480252c..6a8dc5e 100644
--- a/markupsafe/__init__.py
+++ b/markupsafe/__init__.py
@@ -9,7 +9,7 @@
:license: BSD, see LICENSE for more details.
"""
import re
-from itertools import imap
+from markupsafe._compat import text_type, string_types, imap, unichr, PY2
__all__ = ['Markup', 'soft_unicode', 'escape', 'escape_silent']
@@ -19,7 +19,7 @@ _striptags_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
_entity_re = re.compile(r'&([^;]+);')
-class Markup(unicode):
+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
@@ -68,25 +68,25 @@ class Markup(unicode):
if hasattr(base, '__html__'):
base = base.__html__()
if encoding is None:
- return unicode.__new__(cls, base)
- return unicode.__new__(cls, base, encoding, errors)
+ 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, basestring) or hasattr(other, '__html__'):
+ 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, basestring):
+ 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, long)):
- return self.__class__(unicode.__mul__(self, num))
+ return self.__class__(text_type.__mul__(self, num))
return NotImplemented
__rmul__ = __mul__
@@ -95,32 +95,32 @@ class Markup(unicode):
arg = tuple(imap(_MarkupEscapeHelper, arg, self.escape))
else:
arg = _MarkupEscapeHelper(arg, self.escape)
- return self.__class__(unicode.__mod__(self, arg))
+ return self.__class__(text_type.__mod__(self, arg))
def __repr__(self):
return '%s(%s)' % (
self.__class__.__name__,
- unicode.__repr__(self)
+ text_type.__repr__(self)
)
def join(self, seq):
- return self.__class__(unicode.join(self, imap(self.escape, seq)))
- join.__doc__ = unicode.join.__doc__
+ return self.__class__(text_type.join(self, imap(self.escape, seq)))
+ join.__doc__ = text_type.join.__doc__
def split(self, *args, **kwargs):
- return map(self.__class__, unicode.split(self, *args, **kwargs))
- split.__doc__ = unicode.split.__doc__
+ return map(self.__class__, text_type.split(self, *args, **kwargs))
+ split.__doc__ = text_type.split.__doc__
def rsplit(self, *args, **kwargs):
- return map(self.__class__, unicode.rsplit(self, *args, **kwargs))
- rsplit.__doc__ = unicode.rsplit.__doc__
+ return map(self.__class__, text_type.rsplit(self, *args, **kwargs))
+ rsplit.__doc__ = text_type.rsplit.__doc__
def splitlines(self, *args, **kwargs):
- return map(self.__class__, unicode.splitlines(self, *args, **kwargs))
- splitlines.__doc__ = unicode.splitlines.__doc__
+ return map(self.__class__, text_type.splitlines(self, *args, **kwargs))
+ splitlines.__doc__ = text_type.splitlines.__doc__
def unescape(self):
- r"""Unescape markup again into an unicode string. This also resolves
+ r"""Unescape markup again into an text_type string. This also resolves
known HTML4 and XHTML entities:
>>> Markup("Main &raquo; <em>About</em>").unescape()
@@ -139,10 +139,10 @@ class Markup(unicode):
except ValueError:
pass
return u''
- return _entity_re.sub(handle_match, unicode(self))
+ return _entity_re.sub(handle_match, text_type(self))
def striptags(self):
- r"""Unescape markup into an unicode string and strip all tags. This
+ 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:
@@ -164,7 +164,7 @@ class Markup(unicode):
return rv
def make_wrapper(name):
- orig = getattr(unicode, name)
+ orig = getattr(text_type, name)
def func(self, *args, **kwargs):
args = _escape_argspec(list(args), enumerate(args), self.escape)
#_escape_argspec(kwargs, kwargs.iteritems(), None)
@@ -180,20 +180,20 @@ class Markup(unicode):
locals()[method] = make_wrapper(method)
# new in python 2.5
- if hasattr(unicode, 'partition'):
+ if hasattr(text_type, 'partition'):
def partition(self, sep):
return tuple(map(self.__class__,
- unicode.partition(self, self.escape(sep))))
+ text_type.partition(self, self.escape(sep))))
def rpartition(self, sep):
return tuple(map(self.__class__,
- unicode.rpartition(self, self.escape(sep))))
+ text_type.rpartition(self, self.escape(sep))))
# new in python 2.6
- if hasattr(unicode, 'format'):
+ if hasattr(text_type, 'format'):
format = make_wrapper('format')
# not in python 3
- if hasattr(unicode, '__getslice__'):
+ if hasattr(text_type, '__getslice__'):
__getslice__ = make_wrapper('__getslice__')
del method, make_wrapper
@@ -202,7 +202,7 @@ class Markup(unicode):
def _escape_argspec(obj, iterable, escape):
"""Helper for various string-wrapped functions."""
for key, value in iterable:
- if hasattr(value, '__html__') or isinstance(value, basestring):
+ if hasattr(value, '__html__') or isinstance(value, string_types):
obj[key] = escape(value)
return obj
@@ -215,7 +215,7 @@ class _MarkupEscapeHelper(object):
self.escape = escape
__getitem__ = lambda s, x: _MarkupEscapeHelper(s.obj[x], s.escape)
- __unicode__ = lambda s: unicode(s.escape(s.obj))
+ __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)
@@ -228,4 +228,6 @@ try:
except ImportError:
from markupsafe._native import escape, escape_silent, soft_unicode
-# vim:sts=4:sw=4:et:
+if not PY2:
+ soft_str = soft_unicode
+ __all__.append('soft_str')
diff --git a/markupsafe/_native.py b/markupsafe/_native.py
index 3acf91b..5e83f10 100644
--- a/markupsafe/_native.py
+++ b/markupsafe/_native.py
@@ -9,6 +9,7 @@
:license: BSD, see LICENSE for more details.
"""
from markupsafe import Markup
+from markupsafe._compat import text_type
def escape(s):
@@ -18,7 +19,7 @@ def escape(s):
"""
if hasattr(s, '__html__'):
return s.__html__()
- return Markup(unicode(s)
+ return Markup(text_type(s)
.replace('&', '&amp;')
.replace('>', '&gt;')
.replace('<', '&lt;')
@@ -40,6 +41,6 @@ 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, unicode):
- s = unicode(s)
+ if not isinstance(s, text_type):
+ s = text_type(s)
return s
diff --git a/markupsafe/tests.py b/markupsafe/tests.py
index dbb3125..12cd69b 100644
--- a/markupsafe/tests.py
+++ b/markupsafe/tests.py
@@ -2,16 +2,18 @@
import gc
import unittest
from markupsafe import Markup, escape, escape_silent
+from markupsafe._compat import text_type
class MarkupTestCase(unittest.TestCase):
- def test_markup_operations(self):
+ 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 == unicode(escape(unsafe)) + unicode(safe)
+ 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>&lt;bad user&gt;</em>'
@@ -22,6 +24,7 @@ class MarkupTestCase(unittest.TestCase):
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
@@ -29,16 +32,19 @@ class MarkupTestCase(unittest.TestCase):
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_escaping(self):
# escaping and unescaping
assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
@@ -59,8 +65,8 @@ class MarkupLeakTestCase(unittest.TestCase):
def test_markup_leaks(self):
counts = set()
- for count in xrange(20):
- for item in xrange(1000):
+ for count in range(20):
+ for item in range(1000):
escape("foo")
escape("<foo>")
escape(u"foo")
@@ -68,48 +74,10 @@ class MarkupLeakTestCase(unittest.TestCase):
counts.add(len(gc.get_objects()))
assert len(counts) == 1, 'ouch, c extension seems to leak objects'
-class EncodedMarkup(Markup):
- __slots__ = ()
- encoding = 'utf8'
-
- @classmethod
- def escape(cls, s):
- if isinstance(s, str):
- s = s.decode('utf8')
- return super(EncodedMarkup, cls).escape(s)
-
-class MarkupSubclassTestCase(unittest.TestCase):
- # The Russian name of Russia (Rossija)
- russia = u'Россия'
- utf8 = russia.encode('utf8')
-
- def test_escape(self):
- myval = EncodedMarkup.escape(self.utf8)
- assert myval == self.russia, repr(myval)
- def test_add(self):
- myval = EncodedMarkup() + self.utf8
- assert myval == self.russia, repr(myval)
- def test_radd(self):
- myval = self.utf8 + EncodedMarkup()
- assert myval == self.russia, repr(myval)
- def test_join(self):
- myval = EncodedMarkup().join([self.utf8])
- assert myval == self.russia, repr(myval)
- def test_partition(self):
- assert EncodedMarkup(self.russia).partition(self.utf8)[1] == self.russia
- assert EncodedMarkup(self.russia).rpartition(self.utf8)[1] == self.russia
- def test_mod(self):
- assert EncodedMarkup('%s') % self.utf8 == self.russia
- assert EncodedMarkup('%r') % self.utf8 == escape(repr(self.utf8))
- def test_strip(self):
- assert EncodedMarkup(self.russia).strip(self.utf8) == u''
- assert EncodedMarkup(self.russia).rstrip(self.utf8) == u''
-
def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(MarkupTestCase))
- suite.addTest(unittest.makeSuite(MarkupSubclassTestCase))
# this test only tests the c extension
if not hasattr(escape, 'func_code'):
diff --git a/setup.py b/setup.py
index 65fa171..b594d7b 100644
--- a/setup.py
+++ b/setup.py
@@ -28,11 +28,6 @@ if sys.platform == 'win32' and sys.version_info > (2, 6):
ext_errors += (IOError,)
-extra = {}
-if sys.version_info >= (3, 0):
- extra['use_2to3'] = True
-
-
class BuildFailed(Exception):
pass
@@ -96,7 +91,6 @@ def run_setup(with_binary):
include_package_data=True,
cmdclass={'build_ext': ve_build_ext},
features=features,
- **extra
)