Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[py3] Ported django.utils.safestring.

Backwards compatibility aliases were created under Python 2.
  • Loading branch information...
commit 547b181046539f548839e42544521503fbe4d821 1 parent e41c308
@aaugustin aaugustin authored
View
8 django/db/backends/mysql/base.py
@@ -38,7 +38,7 @@
from django.db.backends.mysql.introspection import DatabaseIntrospection
from django.db.backends.mysql.validation import DatabaseValidation
from django.utils.functional import cached_property
-from django.utils.safestring import SafeString, SafeUnicode
+from django.utils.safestring import SafeBytes, SafeText
from django.utils import six
from django.utils import timezone
@@ -75,7 +75,7 @@ def adapt_datetime_with_timezone_support(value, conv):
# MySQLdb-1.2.1 returns TIME columns as timedelta -- they are more like
# timedelta in terms of actual behavior as they are signed and include days --
# and Django expects time, so we still need to override that. We also need to
-# add special handling for SafeUnicode and SafeString as MySQLdb's type
+# add special handling for SafeText and SafeBytes as MySQLdb's type
# checking is too tight to catch those (see Django ticket #6052).
# Finally, MySQLdb always returns naive datetime objects. However, when
# timezone support is active, Django expects timezone-aware datetime objects.
@@ -402,8 +402,8 @@ def _cursor(self):
kwargs['client_flag'] = CLIENT.FOUND_ROWS
kwargs.update(settings_dict['OPTIONS'])
self.connection = Database.connect(**kwargs)
- self.connection.encoders[SafeUnicode] = self.connection.encoders[six.text_type]
- self.connection.encoders[SafeString] = self.connection.encoders[bytes]
+ self.connection.encoders[SafeText] = self.connection.encoders[six.text_type]
+ self.connection.encoders[SafeBytes] = self.connection.encoders[bytes]
connection_created.send(sender=self.__class__, connection=self)
cursor = self.connection.cursor()
if new_connection:
View
6 django/db/backends/postgresql_psycopg2/base.py
@@ -14,7 +14,7 @@
from django.db.backends.postgresql_psycopg2.version import get_version
from django.db.backends.postgresql_psycopg2.introspection import DatabaseIntrospection
from django.utils.log import getLogger
-from django.utils.safestring import SafeUnicode, SafeString
+from django.utils.safestring import SafeText, SafeBytes
from django.utils import six
from django.utils.timezone import utc
@@ -29,8 +29,8 @@
IntegrityError = Database.IntegrityError
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
-psycopg2.extensions.register_adapter(SafeString, psycopg2.extensions.QuotedString)
-psycopg2.extensions.register_adapter(SafeUnicode, psycopg2.extensions.QuotedString)
+psycopg2.extensions.register_adapter(SafeBytes, psycopg2.extensions.QuotedString)
+psycopg2.extensions.register_adapter(SafeText, psycopg2.extensions.QuotedString)
logger = getLogger('django.db.backends')
View
4 django/db/backends/sqlite3/base.py
@@ -20,7 +20,7 @@
from django.db.backends.sqlite3.introspection import DatabaseIntrospection
from django.utils.dateparse import parse_date, parse_datetime, parse_time
from django.utils.functional import cached_property
-from django.utils.safestring import SafeString
+from django.utils.safestring import SafeBytes
from django.utils import six
from django.utils import timezone
@@ -80,7 +80,7 @@ def decoder(conv_func):
# slow-down, this adapter is only registered for sqlite3 versions
# needing it (Python 2.6 and up).
Database.register_adapter(str, lambda s: s.decode('utf-8'))
- Database.register_adapter(SafeString, lambda s: s.decode('utf-8'))
+ Database.register_adapter(SafeBytes, lambda s: s.decode('utf-8'))
class DatabaseFeatures(BaseDatabaseFeatures):
# SQLite cannot handle us only partially reading from a cursor's result set
View
4 django/utils/encoding.py
@@ -119,8 +119,8 @@ def force_text(s, encoding='utf-8', strings_only=False, errors='strict'):
errors) for arg in s])
else:
# Note: We use .decode() here, instead of six.text_type(s, encoding,
- # errors), so that if s is a SafeString, it ends up being a
- # SafeUnicode at the end.
+ # errors), so that if s is a SafeBytes, it ends up being a
+ # SafeText at the end.
s = s.decode(encoding, errors)
except UnicodeDecodeError as e:
if not isinstance(s, Exception):
View
74 django/utils/safestring.py
@@ -10,36 +10,43 @@
class EscapeData(object):
pass
-class EscapeString(bytes, EscapeData):
+class EscapeBytes(bytes, EscapeData):
"""
- A string that should be HTML-escaped when output.
+ A byte string that should be HTML-escaped when output.
"""
pass
-class EscapeUnicode(six.text_type, EscapeData):
+class EscapeText(six.text_type, EscapeData):
"""
- A unicode object that should be HTML-escaped when output.
+ A unicode string object that should be HTML-escaped when output.
"""
pass
+if six.PY3:
+ EscapeString = EscapeText
+else:
+ EscapeString = EscapeBytes
+ # backwards compatibility for Python 2
+ EscapeUnicode = EscapeText
+
class SafeData(object):
pass
-class SafeString(bytes, SafeData):
+class SafeBytes(bytes, SafeData):
"""
- A string subclass that has been specifically marked as "safe" (requires no
+ A bytes subclass that has been specifically marked as "safe" (requires no
further escaping) for HTML output purposes.
"""
def __add__(self, rhs):
"""
- Concatenating a safe string with another safe string or safe unicode
- object is safe. Otherwise, the result is no longer safe.
+ Concatenating a safe byte string with another safe byte string or safe
+ unicode string is safe. Otherwise, the result is no longer safe.
"""
- t = super(SafeString, self).__add__(rhs)
- if isinstance(rhs, SafeUnicode):
- return SafeUnicode(t)
- elif isinstance(rhs, SafeString):
- return SafeString(t)
+ t = super(SafeBytes, self).__add__(rhs)
+ if isinstance(rhs, SafeText):
+ return SafeText(t)
+ elif isinstance(rhs, SafeBytes):
+ return SafeBytes(t)
return t
def _proxy_method(self, *args, **kwargs):
@@ -51,25 +58,25 @@ def _proxy_method(self, *args, **kwargs):
method = kwargs.pop('method')
data = method(self, *args, **kwargs)
if isinstance(data, bytes):
- return SafeString(data)
+ return SafeBytes(data)
else:
- return SafeUnicode(data)
+ return SafeText(data)
decode = curry(_proxy_method, method=bytes.decode)
-class SafeUnicode(six.text_type, SafeData):
+class SafeText(six.text_type, SafeData):
"""
- A unicode subclass that has been specifically marked as "safe" for HTML
- output purposes.
+ A unicode (Python 2) / str (Python 3) subclass that has been specifically
+ marked as "safe" for HTML output purposes.
"""
def __add__(self, rhs):
"""
- Concatenating a safe unicode object with another safe string or safe
- unicode object is safe. Otherwise, the result is no longer safe.
+ Concatenating a safe unicode string with another safe byte string or
+ safe unicode string is safe. Otherwise, the result is no longer safe.
"""
- t = super(SafeUnicode, self).__add__(rhs)
+ t = super(SafeText, self).__add__(rhs)
if isinstance(rhs, SafeData):
- return SafeUnicode(t)
+ return SafeText(t)
return t
def _proxy_method(self, *args, **kwargs):
@@ -81,12 +88,19 @@ def _proxy_method(self, *args, **kwargs):
method = kwargs.pop('method')
data = method(self, *args, **kwargs)
if isinstance(data, bytes):
- return SafeString(data)
+ return SafeBytes(data)
else:
- return SafeUnicode(data)
+ return SafeText(data)
encode = curry(_proxy_method, method=six.text_type.encode)
+if six.PY3:
+ SafeString = SafeText
+else:
+ SafeString = SafeBytes
+ # backwards compatibility for Python 2
+ SafeUnicode = SafeText
+
def mark_safe(s):
"""
Explicitly mark a string as safe for (HTML) output purposes. The returned
@@ -97,10 +111,10 @@ def mark_safe(s):
if isinstance(s, SafeData):
return s
if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_bytes):
- return SafeString(s)
+ return SafeBytes(s)
if isinstance(s, (six.text_type, Promise)):
- return SafeUnicode(s)
- return SafeString(bytes(s))
+ return SafeText(s)
+ return SafeString(str(s))
def mark_for_escaping(s):
"""
@@ -113,8 +127,8 @@ def mark_for_escaping(s):
if isinstance(s, (SafeData, EscapeData)):
return s
if isinstance(s, bytes) or (isinstance(s, Promise) and s._delegate_bytes):
- return EscapeString(s)
+ return EscapeBytes(s)
if isinstance(s, (six.text_type, Promise)):
- return EscapeUnicode(s)
- return EscapeString(bytes(s))
+ return EscapeText(s)
+ return EscapeBytes(bytes(s))
View
6 docs/howto/custom-template-tags.txt
@@ -189,7 +189,7 @@ passed around inside the template code:
They're commonly used for output that contains raw HTML that is intended
to be interpreted as-is on the client side.
- Internally, these strings are of type ``SafeString`` or ``SafeUnicode``.
+ Internally, these strings are of type ``SafeBytes`` or ``SafeText``.
They share a common base class of ``SafeData``, so you can test
for them using code like:
@@ -204,8 +204,8 @@ passed around inside the template code:
not. These strings are only escaped once, however, even if auto-escaping
applies.
- Internally, these strings are of type ``EscapeString`` or
- ``EscapeUnicode``. Generally you don't have to worry about these; they
+ Internally, these strings are of type ``EscapeBytes`` or
+ ``EscapeText``. Generally you don't have to worry about these; they
exist for the implementation of the :tfilter:`escape` filter.
Template filter code falls into one of two situations:
View
22 docs/ref/utils.txt
@@ -560,15 +560,29 @@ string" means that the producer of the string has already turned characters
that should not be interpreted by the HTML engine (e.g. '<') into the
appropriate entities.
+.. class:: SafeBytes
+
+ .. versionadded:: 1.5
+
+ A :class:`bytes` subclass that has been specifically marked as "safe"
+ (requires no further escaping) for HTML output purposes.
+
.. class:: SafeString
- A string subclass that has been specifically marked as "safe" (requires no
- further escaping) for HTML output purposes.
+ A :class:`str` subclass that has been specifically marked as "safe"
+ (requires no further escaping) for HTML output purposes. This is
+ :class:`SafeBytes` on Python 2 and :class:`SafeText` on Python 3.
+
+.. class:: SafeText
+
+ .. versionadded:: 1.5
+
+ A :class:`str` (in Python 3) or :class:`unicode` (in Python 2) subclass
+ that has been specifically marked as "safe" for HTML output purposes.
.. class:: SafeUnicode
- A unicode subclass that has been specifically marked as "safe" for HTML
- output purposes.
+ Historical name of :class:`SafeText`. Only available under Python 2.
.. function:: mark_safe(s)
View
12 tests/regressiontests/i18n/tests.py
@@ -18,7 +18,7 @@
number_format)
from django.utils.importlib import import_module
from django.utils.numberformat import format as nformat
-from django.utils.safestring import mark_safe, SafeString, SafeUnicode
+from django.utils.safestring import mark_safe, SafeBytes, SafeString, SafeText
from django.utils import six
from django.utils.six import PY3
from django.utils.translation import (ugettext, ugettext_lazy, activate,
@@ -235,9 +235,9 @@ def test_safe_status(self):
s = mark_safe(str('Password'))
self.assertEqual(SafeString, type(s))
with translation.override('de', deactivate=True):
- self.assertEqual(SafeUnicode, type(ugettext(s)))
- self.assertEqual('aPassword', SafeString('a') + s)
- self.assertEqual('Passworda', s + SafeString('a'))
+ self.assertEqual(SafeText, type(ugettext(s)))
+ self.assertEqual('aPassword', SafeText('a') + s)
+ self.assertEqual('Passworda', s + SafeText('a'))
self.assertEqual('Passworda', s + mark_safe('a'))
self.assertEqual('aPassword', mark_safe('a') + s)
self.assertEqual('as', mark_safe('a') + mark_safe('s'))
@@ -897,9 +897,9 @@ def test_lazy(self):
def test_safestr(self):
c = Company(cents_paid=12, products_delivered=1)
- c.name = SafeUnicode('Iñtërnâtiônàlizætiøn1')
+ c.name = SafeText('Iñtërnâtiônàlizætiøn1')
c.save()
- c.name = SafeString('Iñtërnâtiônàlizætiøn1'.encode('utf-8'))
+ c.name = SafeBytes('Iñtërnâtiônàlizætiøn1'.encode('utf-8'))
c.save()
Please sign in to comment.
Something went wrong with that request. Please try again.