1
0
mirror of https://github.com/django/django.git synced 2025-11-07 07:15:35 +00:00

[py3] Ported django.utils.encoding.

* Renamed smart_unicode to smart_text (but kept the old name under
  Python 2 for backwards compatibility).
* Renamed smart_str to smart_bytes.
* Re-introduced smart_str as an alias for smart_text under Python 3
  and smart_bytes under Python 2 (which is backwards compatible).
  Thus smart_str always returns a str objects.
* Used the new smart_str in a few places where both Python 2 and 3
  want a str.
This commit is contained in:
Aymeric Augustin
2012-07-21 10:00:10 +02:00
parent ee191715ea
commit c5ef65bcf3
125 changed files with 629 additions and 583 deletions

View File

@@ -3,7 +3,7 @@
import warnings
from django.core.exceptions import ImproperlyConfigured, DjangoRuntimeWarning
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils.importlib import import_module
class InvalidCacheBackendError(ImproperlyConfigured):
@@ -23,7 +23,7 @@ def default_key_func(key, key_prefix, version):
the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
function with custom key making behavior.
"""
return ':'.join([key_prefix, str(version), smart_str(key)])
return ':'.join([key_prefix, str(version), smart_bytes(key)])
def get_key_func(key_func):
"""
@@ -62,7 +62,7 @@ class BaseCache(object):
except (ValueError, TypeError):
self._cull_frequency = 3
self.key_prefix = smart_str(params.get('KEY_PREFIX', ''))
self.key_prefix = smart_bytes(params.get('KEY_PREFIX', ''))
self.version = params.get('VERSION', 1)
self.key_func = get_key_func(params.get('KEY_FUNCTION', None))

View File

@@ -9,7 +9,7 @@ RequestContext.
from django.conf import settings
from django.middleware.csrf import get_token
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils.functional import lazy
def csrf(request):
@@ -25,7 +25,7 @@ def csrf(request):
# instead of returning an empty dict.
return b'NOTPROVIDED'
else:
return smart_str(token)
return smart_bytes(token)
_get_val = lazy(_get_val, str)
return {'csrf_token': _get_val() }

View File

@@ -43,7 +43,7 @@ class ValidationError(Exception):
"""An error while validating data."""
def __init__(self, message, code=None, params=None):
import operator
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
"""
ValidationError can be passed any object that can be printed (usually
a string), a list of objects or a dictionary.
@@ -54,11 +54,11 @@ class ValidationError(Exception):
message = reduce(operator.add, message.values())
if isinstance(message, list):
self.messages = [force_unicode(msg) for msg in message]
self.messages = [force_text(msg) for msg in message]
else:
self.code = code
self.params = params
message = force_unicode(message)
message = force_text(message)
self.messages = [message]
def __str__(self):

View File

@@ -3,7 +3,7 @@ from __future__ import unicode_literals
import os
from io import BytesIO
from django.utils.encoding import smart_str, smart_unicode
from django.utils.encoding import smart_bytes, smart_text
from django.core.files.utils import FileProxyMixin
class File(FileProxyMixin):
@@ -18,10 +18,10 @@ class File(FileProxyMixin):
self.mode = file.mode
def __str__(self):
return smart_str(self.name or '')
return smart_bytes(self.name or '')
def __unicode__(self):
return smart_unicode(self.name or '')
return smart_text(self.name or '')
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self or "None")

View File

@@ -11,7 +11,7 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.core.files import locks, File
from django.core.files.move import file_move_safe
from django.utils.encoding import force_unicode, filepath_to_uri
from django.utils.encoding import force_text, filepath_to_uri
from django.utils.functional import LazyObject
from django.utils.importlib import import_module
from django.utils.text import get_valid_filename
@@ -48,7 +48,7 @@ class Storage(object):
name = self._save(name, content)
# Store filenames with forward slashes, even on Windows
return force_unicode(name.replace('\\', '/'))
return force_text(name.replace('\\', '/'))
# These methods are part of the public API, with default implementations.

View File

@@ -8,7 +8,7 @@ from io import BytesIO
from django.conf import settings
from django.core.files.base import File
from django.core.files import temp as tempfile
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
__all__ = ('UploadedFile', 'TemporaryUploadedFile', 'InMemoryUploadedFile',
'SimpleUploadedFile')
@@ -30,7 +30,7 @@ class UploadedFile(File):
self.charset = charset
def __repr__(self):
return smart_str("<%s: %s (%s)>" % (
return smart_bytes("<%s: %s (%s)>" % (
self.__class__.__name__, self.name, self.content_type))
def _get_name(self):

View File

@@ -4,7 +4,7 @@ import sys
from django import http
from django.core import signals
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils.importlib import import_module
from django.utils.log import getLogger
from django.utils import six
@@ -250,7 +250,7 @@ def get_script_name(environ):
"""
from django.conf import settings
if settings.FORCE_SCRIPT_NAME is not None:
return force_unicode(settings.FORCE_SCRIPT_NAME)
return force_text(settings.FORCE_SCRIPT_NAME)
# If Apache's mod_rewrite had a whack at the URL, Apache set either
# SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any
@@ -261,5 +261,5 @@ def get_script_name(environ):
if not script_url:
script_url = environ.get('REDIRECT_URL', '')
if script_url:
return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
return force_unicode(environ.get('SCRIPT_NAME', ''))
return force_text(script_url[:-len(environ.get('PATH_INFO', ''))])
return force_text(environ.get('SCRIPT_NAME', ''))

View File

@@ -9,7 +9,7 @@ from django.core import signals
from django.core.handlers import base
from django.core.urlresolvers import set_script_prefix
from django.utils import datastructures
from django.utils.encoding import force_unicode, smart_str, iri_to_uri
from django.utils.encoding import force_text, smart_bytes, iri_to_uri
from django.utils.log import getLogger
logger = getLogger('django.request')
@@ -127,7 +127,7 @@ class LimitedStream(object):
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
script_name = base.get_script_name(environ)
path_info = force_unicode(environ.get('PATH_INFO', '/'))
path_info = force_text(environ.get('PATH_INFO', '/'))
if not path_info or path_info == script_name:
# Sometimes PATH_INFO exists, but is empty (e.g. accessing
# the SCRIPT_NAME URL without a trailing slash). We really need to
@@ -246,5 +246,5 @@ class WSGIHandler(base.BaseHandler):
response_headers = [(str(k), str(v)) for k, v in response.items()]
for c in response.cookies.values():
response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
start_response(smart_str(status), response_headers)
start_response(smart_bytes(status), response_headers)
return response

View File

@@ -15,7 +15,7 @@ from io import BytesIO
from django.conf import settings
from django.core.mail.utils import DNS_NAME
from django.utils.encoding import smart_str, force_unicode
from django.utils.encoding import smart_bytes, force_text
from django.utils import six
@@ -79,7 +79,7 @@ ADDRESS_HEADERS = set([
def forbid_multi_line_headers(name, val, encoding):
"""Forbids multi-line headers, to prevent header injection."""
encoding = encoding or settings.DEFAULT_CHARSET
val = force_unicode(val)
val = force_text(val)
if '\n' in val or '\r' in val:
raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name))
try:
@@ -93,12 +93,12 @@ def forbid_multi_line_headers(name, val, encoding):
else:
if name.lower() == 'subject':
val = Header(val)
return smart_str(name), val
return smart_bytes(name), val
def sanitize_address(addr, encoding):
if isinstance(addr, six.string_types):
addr = parseaddr(force_unicode(addr))
addr = parseaddr(force_text(addr))
nm, addr = addr
nm = str(Header(nm, encoding))
try:
@@ -210,7 +210,7 @@ class EmailMessage(object):
def message(self):
encoding = self.encoding or settings.DEFAULT_CHARSET
msg = SafeMIMEText(smart_str(self.body, encoding),
msg = SafeMIMEText(smart_bytes(self.body, encoding),
self.content_subtype, encoding)
msg = self._create_message(msg)
msg['Subject'] = self.subject
@@ -293,7 +293,7 @@ class EmailMessage(object):
basetype, subtype = mimetype.split('/', 1)
if basetype == 'text':
encoding = self.encoding or settings.DEFAULT_CHARSET
attachment = SafeMIMEText(smart_str(content, encoding), subtype, encoding)
attachment = SafeMIMEText(smart_bytes(content, encoding), subtype, encoding)
else:
# Encode non-text attachments with base64.
attachment = MIMEBase(basetype, subtype)

View File

@@ -4,7 +4,7 @@ from django.core.cache.backends.db import BaseDatabaseCache
from django.core.management.base import LabelCommand, CommandError
from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
from django.db.utils import DatabaseError
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
class Command(LabelCommand):
@@ -60,7 +60,7 @@ class Command(LabelCommand):
transaction.rollback_unless_managed(using=db)
raise CommandError(
"Cache table '%s' could not be created.\nThe error was: %s." %
(tablename, force_unicode(e)))
(tablename, force_text(e)))
for statement in index_output:
curs.execute(statement)
transaction.commit_unless_managed(using=db)

View File

@@ -14,7 +14,7 @@ from django.core.management.color import no_style
from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
IntegrityError, DatabaseError)
from django.db.models import get_apps
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from itertools import product
try:
@@ -189,7 +189,7 @@ class Command(BaseCommand):
'app_label': obj.object._meta.app_label,
'object_name': obj.object._meta.object_name,
'pk': obj.object.pk,
'error_msg': force_unicode(e)
'error_msg': force_text(e)
},)
raise

View File

@@ -5,7 +5,7 @@ Module for abstract serializer/unserializer base classes.
from io import BytesIO
from django.db import models
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils import six
class SerializerDoesNotExist(KeyError):

View File

@@ -12,7 +12,7 @@ import json
from django.core.serializers.base import DeserializationError
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.python import Deserializer as PythonDeserializer
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils import six
from django.utils.timezone import is_aware

View File

@@ -8,7 +8,7 @@ from __future__ import unicode_literals
from django.conf import settings
from django.core.serializers import base
from django.db import models, DEFAULT_DB_ALIAS
from django.utils.encoding import smart_unicode, is_protected_type
from django.utils.encoding import smart_text, is_protected_type
from django.utils import six
class Serializer(base.Serializer):
@@ -34,8 +34,8 @@ class Serializer(base.Serializer):
def get_dump_object(self, obj):
return {
"pk": smart_unicode(obj._get_pk_val(), strings_only=True),
"model": smart_unicode(obj._meta),
"pk": smart_text(obj._get_pk_val(), strings_only=True),
"model": smart_text(obj._meta),
"fields": self._current
}
@@ -65,7 +65,7 @@ class Serializer(base.Serializer):
if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'):
m2m_value = lambda value: value.natural_key()
else:
m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True)
m2m_value = lambda value: smart_text(value._get_pk_val(), strings_only=True)
self._current[field.name] = [m2m_value(related)
for related in getattr(obj, field.name).iterator()]
@@ -90,7 +90,7 @@ def Deserializer(object_list, **options):
# Handle each field
for (field_name, field_value) in six.iteritems(d["fields"]):
if isinstance(field_value, str):
field_value = smart_unicode(field_value, options.get("encoding", settings.DEFAULT_CHARSET), strings_only=True)
field_value = smart_text(field_value, options.get("encoding", settings.DEFAULT_CHARSET), strings_only=True)
field = Model._meta.get_field(field_name)
@@ -101,9 +101,9 @@ def Deserializer(object_list, **options):
if hasattr(value, '__iter__'):
return field.rel.to._default_manager.db_manager(db).get_by_natural_key(*value).pk
else:
return smart_unicode(field.rel.to._meta.pk.to_python(value))
return smart_text(field.rel.to._meta.pk.to_python(value))
else:
m2m_convert = lambda v: smart_unicode(field.rel.to._meta.pk.to_python(v))
m2m_convert = lambda v: smart_text(field.rel.to._meta.pk.to_python(v))
m2m_data[field.name] = [m2m_convert(pk) for pk in field_value]
# Handle FK fields

View File

@@ -12,7 +12,7 @@ from django.db import models
from django.core.serializers.base import DeserializationError
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.python import Deserializer as PythonDeserializer
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils import six

View File

@@ -8,7 +8,7 @@ from django.conf import settings
from django.core.serializers import base
from django.db import models, DEFAULT_DB_ALIAS
from django.utils.xmlutils import SimplerXMLGenerator
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from xml.dom import pulldom
class Serializer(base.Serializer):
@@ -46,11 +46,11 @@ class Serializer(base.Serializer):
self.indent(1)
obj_pk = obj._get_pk_val()
if obj_pk is None:
attrs = {"model": smart_unicode(obj._meta),}
attrs = {"model": smart_text(obj._meta),}
else:
attrs = {
"pk": smart_unicode(obj._get_pk_val()),
"model": smart_unicode(obj._meta),
"pk": smart_text(obj._get_pk_val()),
"model": smart_text(obj._meta),
}
self.xml.startElement("object", attrs)
@@ -96,10 +96,10 @@ class Serializer(base.Serializer):
# Iterable natural keys are rolled out as subelements
for key_value in related:
self.xml.startElement("natural", {})
self.xml.characters(smart_unicode(key_value))
self.xml.characters(smart_text(key_value))
self.xml.endElement("natural")
else:
self.xml.characters(smart_unicode(related_att))
self.xml.characters(smart_text(related_att))
else:
self.xml.addQuickElement("None")
self.xml.endElement("field")
@@ -120,13 +120,13 @@ class Serializer(base.Serializer):
self.xml.startElement("object", {})
for key_value in natural:
self.xml.startElement("natural", {})
self.xml.characters(smart_unicode(key_value))
self.xml.characters(smart_text(key_value))
self.xml.endElement("natural")
self.xml.endElement("object")
else:
def handle_m2m(value):
self.xml.addQuickElement("object", attrs={
'pk' : smart_unicode(value._get_pk_val())
'pk' : smart_text(value._get_pk_val())
})
for relobj in getattr(obj, field.name).iterator():
handle_m2m(relobj)
@@ -141,7 +141,7 @@ class Serializer(base.Serializer):
self.xml.startElement("field", {
"name" : field.name,
"rel" : field.rel.__class__.__name__,
"to" : smart_unicode(field.rel.to._meta),
"to" : smart_text(field.rel.to._meta),
})
class Deserializer(base.Deserializer):

View File

@@ -41,7 +41,7 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils import baseconv
from django.utils.crypto import constant_time_compare, salted_hmac
from django.utils.encoding import force_unicode, smart_str
from django.utils.encoding import force_text, smart_bytes
from django.utils.importlib import import_module
@@ -135,7 +135,7 @@ def loads(s, key=None, salt='django.core.signing', serializer=JSONSerializer, ma
"""
Reverse of dumps(), raises BadSignature if signature fails
"""
base64d = smart_str(
base64d = smart_bytes(
TimestampSigner(key, salt=salt).unsign(s, max_age=max_age))
decompress = False
if base64d[0] == '.':
@@ -159,16 +159,16 @@ class Signer(object):
return base64_hmac(self.salt + 'signer', value, self.key)
def sign(self, value):
value = smart_str(value)
value = smart_bytes(value)
return '%s%s%s' % (value, self.sep, self.signature(value))
def unsign(self, signed_value):
signed_value = smart_str(signed_value)
signed_value = smart_bytes(signed_value)
if not self.sep in signed_value:
raise BadSignature('No "%s" found in value' % self.sep)
value, sig = signed_value.rsplit(self.sep, 1)
if constant_time_compare(sig, self.signature(value)):
return force_unicode(value)
return force_text(value)
raise BadSignature('Signature "%s" does not match' % sig)
@@ -178,7 +178,7 @@ class TimestampSigner(Signer):
return baseconv.base62.encode(int(time.time()))
def sign(self, value):
value = smart_str('%s%s%s' % (value, self.sep, self.timestamp()))
value = smart_bytes('%s%s%s' % (value, self.sep, self.timestamp()))
return '%s%s%s' % (value, self.sep, self.signature(value))
def unsign(self, value, max_age=None):

View File

@@ -14,7 +14,7 @@ from threading import local
from django.http import Http404
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import iri_to_uri, force_unicode, smart_str
from django.utils.encoding import iri_to_uri, force_text, smart_bytes
from django.utils.functional import memoize, lazy
from django.utils.importlib import import_module
from django.utils.module_loading import module_has_submodule
@@ -163,7 +163,7 @@ class LocaleRegexProvider(object):
if isinstance(self._regex, six.string_types):
regex = self._regex
else:
regex = force_unicode(self._regex)
regex = force_text(self._regex)
try:
compiled_regex = re.compile(regex, re.UNICODE)
except re.error as e:
@@ -190,7 +190,7 @@ class RegexURLPattern(LocaleRegexProvider):
self.name = name
def __repr__(self):
return smart_str('<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern))
return smart_bytes('<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern))
def add_prefix(self, prefix):
"""
@@ -240,7 +240,7 @@ class RegexURLResolver(LocaleRegexProvider):
self._app_dict = {}
def __repr__(self):
return smart_str('<%s %s (%s:%s) %s>' % (self.__class__.__name__, self.urlconf_name, self.app_name, self.namespace, self.regex.pattern))
return smart_bytes('<%s %s (%s:%s) %s>' % (self.__class__.__name__, self.urlconf_name, self.app_name, self.namespace, self.regex.pattern))
def _populate(self):
lookups = MultiValueDict()
@@ -373,7 +373,7 @@ class RegexURLResolver(LocaleRegexProvider):
if args:
if len(args) != len(params) + len(prefix_args):
continue
unicode_args = [force_unicode(val) for val in args]
unicode_args = [force_text(val) for val in args]
candidate = (prefix_norm + result) % dict(zip(prefix_args + params, unicode_args))
else:
if set(kwargs.keys()) | set(defaults.keys()) != set(params) | set(defaults.keys()) | set(prefix_args):
@@ -385,7 +385,7 @@ class RegexURLResolver(LocaleRegexProvider):
break
if not matches:
continue
unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()])
unicode_kwargs = dict([(k, force_text(v)) for (k, v) in kwargs.items()])
candidate = (prefix_norm + result) % unicode_kwargs
if re.search('^%s%s' % (_prefix, pattern), candidate, re.UNICODE):
return candidate

View File

@@ -8,7 +8,7 @@ except ImportError: # Python 2
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.ipv6 import is_valid_ipv6_address
from django.utils import six
@@ -36,7 +36,7 @@ class RegexValidator(object):
"""
Validates that the input matches the regular expression.
"""
if not self.regex.search(smart_unicode(value)):
if not self.regex.search(smart_text(value)):
raise ValidationError(self.message, code=self.code)
class URLValidator(RegexValidator):
@@ -54,7 +54,7 @@ class URLValidator(RegexValidator):
except ValidationError as e:
# Trivial case failed. Try for possible IDN domain
if value:
value = smart_unicode(value)
value = smart_text(value)
scheme, netloc, path, query, fragment = urlsplit(value)
try:
netloc = netloc.encode('idna') # IDN -> ACE