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
='/#%[]=:;$&()+,!?*')