4
from django.utils.functional import Promise
6
class DjangoUnicodeDecodeError(UnicodeDecodeError):
7
def __init__(self, obj, *args):
9
UnicodeDecodeError.__init__(self, *args)
12
original = UnicodeDecodeError.__str__(self)
13
return '%s. You passed in %r (%s)' % (original, self.obj,
16
class StrAndUnicode(object):
18
A class whose __str__ returns its __unicode__ as a UTF-8 bytestring.
23
return self.__unicode__().encode('utf-8')
25
def smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
27
Returns a unicode object representing 's'. Treats bytestrings using the
30
If strings_only is True, don't convert (some) non-string-like objects.
32
if isinstance(s, Promise):
33
# The input is the result of a gettext_lazy() call.
35
return force_unicode(s, encoding, strings_only, errors)
37
def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
39
Similar to smart_unicode, except that lazy instances are resolved to
40
strings, rather than kept as lazy objects.
42
If strings_only is True, don't convert (some) non-string-like objects.
44
if strings_only and isinstance(s, (types.NoneType, int, long, datetime.datetime, datetime.date, datetime.time, float)):
47
if not isinstance(s, basestring,):
48
if hasattr(s, '__unicode__'):
52
s = unicode(str(s), encoding, errors)
53
except UnicodeEncodeError:
54
if not isinstance(s, Exception):
56
# If we get to here, the caller has passed in an Exception
57
# subclass populated with non-ASCII data without special
58
# handling to display as a string. We need to handle this
59
# without raising a further exception. We do an
60
# approximation to what the Exception's standard str()
62
s = ' '.join([force_unicode(arg, encoding, strings_only,
63
errors) for arg in s])
64
elif not isinstance(s, unicode):
65
# Note: We use .decode() here, instead of unicode(s, encoding,
66
# errors), so that if s is a SafeString, it ends up being a
67
# SafeUnicode at the end.
68
s = s.decode(encoding, errors)
69
except UnicodeDecodeError, e:
70
raise DjangoUnicodeDecodeError(s, *e.args)
73
def smart_str(s, encoding='utf-8', strings_only=False, errors='strict'):
75
Returns a bytestring version of 's', encoded as specified in 'encoding'.
77
If strings_only is True, don't convert (some) non-string-like objects.
79
if strings_only and isinstance(s, (types.NoneType, int)):
81
if isinstance(s, Promise):
82
return unicode(s).encode(encoding, errors)
83
elif not isinstance(s, basestring):
86
except UnicodeEncodeError:
87
if isinstance(s, Exception):
88
# An Exception subclass containing non-ASCII data that doesn't
89
# know how to print itself properly. We shouldn't raise a
91
return ' '.join([smart_str(arg, encoding, strings_only,
92
errors) for arg in s])
93
return unicode(s).encode(encoding, errors)
94
elif isinstance(s, unicode):
95
return s.encode(encoding, errors)
96
elif s and encoding != 'utf-8':
97
return s.decode('utf-8', errors).encode(encoding, errors)
103
Convert an Internationalized Resource Identifier (IRI) portion to a URI
104
portion that is suitable for inclusion in a URL.
106
This is the algorithm from section 3.1 of RFC 3987. However, since we are
107
assuming input is either UTF-8 or unicode already, we can simplify things a
108
little from the full method.
110
Returns an ASCII string containing the encoded result.
112
# The list of safe characters here is constructed from the printable ASCII
113
# characters that are not explicitly excluded by the list at the end of
114
# section 3.1 of RFC 3987.
117
return urllib.quote(smart_str(iri), safe='/#%[]=:;$&()+,!?*')