1 """Compatibility code for using CherryPy with various versions of Python.
3 CherryPy 3.2 is compatible with Python versions 2.3+. This module provides a
4 useful abstraction over the differences between Python versions, sometimes by
5 preferring a newer idiom, sometimes an older one, and sometimes a custom one.
7 In particular, Python 2 uses str and '' for byte strings, while Python 3
8 uses str and '' for unicode strings. We will call each of these the 'native
9 string' type for each version. Because of this major difference, this module
10 provides new 'bytestr', 'unicodestr', and 'nativestr' attributes, as well as
11 two functions: 'ntob', which translates native strings (of type 'str') into
12 byte strings regardless of Python version, and 'ntou', which translates native
13 strings to unicode strings. This also provides a 'BytesIO' name for dealing
14 specifically with bytes, and a 'StringIO' name for dealing with native strings.
15 It also provides a 'base64_decode' function with native strings as input and
21 if sys
.version_info
>= (3, 0):
24 nativestr
= unicodestr
25 basestring
= (bytes
, str)
26 def ntob(n
, encoding
='ISO-8859-1'):
27 """Return the given native string as a byte string in the given encoding."""
28 # In Python 3, the native string type is unicode
29 return n
.encode(encoding
)
30 def ntou(n
, encoding
='ISO-8859-1'):
31 """Return the given native string as a unicode string with the given encoding."""
32 # In Python 3, the native string type is unicode
35 from io
import StringIO
37 from io
import BytesIO
as BytesIO
43 basestring
= basestring
44 def ntob(n
, encoding
='ISO-8859-1'):
45 """Return the given native string as a byte string in the given encoding."""
46 # In Python 2, the native string type is bytes. Assume it's already
47 # in the given encoding, which for ISO-8859-1 is almost always what
50 def ntou(n
, encoding
='ISO-8859-1'):
51 """Return the given native string as a unicode string with the given encoding."""
52 # In Python 2, the native string type is bytes. Assume it's already
53 # in the given encoding, which for ISO-8859-1 is almost always what
55 return n
.decode(encoding
)
58 from cStringIO
import StringIO
61 from StringIO
import StringIO
68 from sets
import Set
as set
72 from base64
import decodebytes
as _base64_decodebytes
75 # since CherryPy claims compability with Python 2.3, we must use
76 # the legacy API of base64
77 from base64
import decodestring
as _base64_decodebytes
79 def base64_decode(n
, encoding
='ISO-8859-1'):
80 """Return the native string base64-decoded (as a native string)."""
81 if isinstance(n
, unicodestr
):
82 b
= n
.encode(encoding
)
85 b
= _base64_decodebytes(b
)
86 if nativestr
is unicodestr
:
87 return b
.decode(encoding
)
93 from hashlib
import md5
95 from md5
import new
as md5
99 from hashlib
import sha1
as sha
101 from sha
import new
as sha
122 from urllib
.parse
import urljoin
, urlencode
123 from urllib
.parse
import quote
, quote_plus
124 from urllib
.request
import unquote
, urlopen
125 from urllib
.request
import parse_http_list
, parse_keqv_list
128 from urlparse
import urljoin
129 from urllib
import urlencode
, urlopen
130 from urllib
import quote
, quote_plus
131 from urllib
import unquote
132 from urllib2
import parse_http_list
, parse_keqv_list
135 from threading
import local
as threadlocal
137 from cherrypy
._cpthreadinglocal
import local
as threadlocal
142 iteritems
= lambda d
: d
.iteritems()
143 copyitems
= lambda d
: d
.items()
144 except AttributeError:
146 iteritems
= lambda d
: d
.items()
147 copyitems
= lambda d
: list(d
.items())
152 iterkeys
= lambda d
: d
.iterkeys()
153 copykeys
= lambda d
: d
.keys()
154 except AttributeError:
156 iterkeys
= lambda d
: d
.keys()
157 copykeys
= lambda d
: list(d
.keys())
162 itervalues
= lambda d
: d
.itervalues()
163 copyvalues
= lambda d
: d
.values()
164 except AttributeError:
166 itervalues
= lambda d
: d
.values()
167 copyvalues
= lambda d
: list(d
.values())
174 import __builtin__
as builtins
177 # Python 2. We have to do it in this order so Python 2 builds
178 # don't try to import the 'http' module from cherrypy.lib
179 from Cookie
import SimpleCookie
, CookieError
180 from httplib
import BadStatusLine
, HTTPConnection
, HTTPSConnection
, IncompleteRead
, NotConnected
181 from BaseHTTPServer
import BaseHTTPRequestHandler
184 from http
.cookies
import SimpleCookie
, CookieError
185 from http
.client
import BadStatusLine
, HTTPConnection
, HTTPSConnection
, IncompleteRead
, NotConnected
186 from http
.server
import BaseHTTPRequestHandler
196 if hasattr(threading
.Thread
, "daemon"):
200 def set_daemon(t
, val
):
205 def set_daemon(t
, val
):
209 from email
.utils
import formatdate
210 def HTTPDate(timeval
=None):
211 return formatdate(timeval
, usegmt
=True)
213 from rfc822
import formatdate
as HTTPDate
217 from urllib
.parse
import unquote
as parse_unquote
218 def unquote_qs(atom
, encoding
, errors
='strict'):
219 return parse_unquote(atom
.replace('+', ' '), encoding
=encoding
, errors
=errors
)
222 from urllib
import unquote
as parse_unquote
223 def unquote_qs(atom
, encoding
, errors
='strict'):
224 return parse_unquote(atom
.replace('+', ' ')).decode(encoding
, errors
)
227 # Prefer simplejson, which is usually more advanced than the builtin module.
228 import simplejson
as json
229 json_decode
= json
.JSONDecoder().decode
230 json_encode
= json
.JSONEncoder().iterencode
232 if sys
.version_info
>= (3, 0):
233 # Python 3.0: json is part of the standard library,
234 # but outputs unicode. We need bytes.
236 json_decode
= json
.JSONDecoder().decode
237 _json_encode
= json
.JSONEncoder().iterencode
238 def json_encode(value
):
239 for chunk
in _json_encode(value
):
240 yield chunk
.encode('utf8')
241 elif sys
.version_info
>= (2, 6):
242 # Python 2.6: json is part of the standard library
244 json_decode
= json
.JSONDecoder().decode
245 json_encode
= json
.JSONEncoder().iterencode
249 raise ValueError('No JSON library is available')
251 raise ValueError('No JSON library is available')
254 import cPickle
as pickle
256 # In Python 2, pickle is a Python version.
257 # In Python 3, pickle is the sped-up C version.
264 return binascii
.hexlify(os
.urandom(20)).decode('ascii')
265 except (AttributeError, NotImplementedError):
267 # os.urandom not available until Python 2.4. Fall back to random.random.
269 return sha('%s' % random
.random()).hexdigest()
272 from _thread
import get_ident
as get_thread_ident
274 from thread
import get_ident
as get_thread_ident