1 """Compatibility code for using CherryPy with various versions of Python.
2
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.
6
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
16 output.
17 """
18 import os
19 import re
20 import sys
21
22 if sys.version_info >= (3, 0):
23 py3k = True
24 bytestr = bytes
25 unicodestr = str
26 nativestr = unicodestr
27 basestring = (bytes, str)
28 - def ntob(n, encoding='ISO-8859-1'):
29 """Return the given native string as a byte string in the given encoding."""
30
31 return n.encode(encoding)
32 - def ntou(n, encoding='ISO-8859-1'):
33 """Return the given native string as a unicode string with the given encoding."""
34
35 return n
37 """Return the given string as a native string in the given encoding."""
38
39 if isinstance(n, bytes):
40 return n.decode(encoding)
41 return n
42
43 from io import StringIO
44
45 from io import BytesIO as BytesIO
46 else:
47
48 py3k = False
49 bytestr = str
50 unicodestr = unicode
51 nativestr = bytestr
52 basestring = basestring
53 - def ntob(n, encoding='ISO-8859-1'):
54 """Return the given native string as a byte string in the given encoding."""
55
56
57
58 return n
59 - def ntou(n, encoding='ISO-8859-1'):
60 """Return the given native string as a unicode string with the given encoding."""
61
62
63
64
65
66 if encoding == 'escape':
67 return unicode(
68 re.sub(r'\\u([0-9a-zA-Z]{4})',
69 lambda m: unichr(int(m.group(1), 16)),
70 n.decode('ISO-8859-1')))
71
72
73 return n.decode(encoding)
75 """Return the given string as a native string in the given encoding."""
76
77 if isinstance(n, unicode):
78 return n.encode(encoding)
79 return n
80 try:
81
82 from cStringIO import StringIO
83 except ImportError:
84
85 from StringIO import StringIO
86
87 BytesIO = StringIO
88
89 try:
90 set = set
91 except NameError:
92 from sets import Set as set
93
94 try:
95
96 from base64 import decodebytes as _base64_decodebytes
97 except ImportError:
98
99
100
101 from base64 import decodestring as _base64_decodebytes
102
104 """Return the native string base64-decoded (as a native string)."""
105 if isinstance(n, unicodestr):
106 b = n.encode(encoding)
107 else:
108 b = n
109 b = _base64_decodebytes(b)
110 if nativestr is unicodestr:
111 return b.decode(encoding)
112 else:
113 return b
114
115 try:
116
117 from hashlib import md5
118 except ImportError:
119 from md5 import new as md5
120
121 try:
122
123 from hashlib import sha1 as sha
124 except ImportError:
125 from sha import new as sha
126
127 try:
128 sorted = sorted
129 except NameError:
131 i = i[:]
132 i.sort()
133 return i
134
135 try:
136 reversed = reversed
137 except NameError:
139 i = len(x)
140 while i > 0:
141 i -= 1
142 yield x[i]
143
144 try:
145
146 from urllib.parse import urljoin, urlencode
147 from urllib.parse import quote, quote_plus
148 from urllib.request import unquote, urlopen
149 from urllib.request import parse_http_list, parse_keqv_list
150 except ImportError:
151
152 from urlparse import urljoin
153 from urllib import urlencode, urlopen
154 from urllib import quote, quote_plus
155 from urllib import unquote
156 from urllib2 import parse_http_list, parse_keqv_list
157
158 try:
159 from threading import local as threadlocal
160 except ImportError:
161 from cherrypy._cpthreadinglocal import local as threadlocal
162
163 try:
164 dict.iteritems
165
166 iteritems = lambda d: d.iteritems()
167 copyitems = lambda d: d.items()
168 except AttributeError:
169
170 iteritems = lambda d: d.items()
171 copyitems = lambda d: list(d.items())
172
173 try:
174 dict.iterkeys
175
176 iterkeys = lambda d: d.iterkeys()
177 copykeys = lambda d: d.keys()
178 except AttributeError:
179
180 iterkeys = lambda d: d.keys()
181 copykeys = lambda d: list(d.keys())
182
183 try:
184 dict.itervalues
185
186 itervalues = lambda d: d.itervalues()
187 copyvalues = lambda d: d.values()
188 except AttributeError:
189
190 itervalues = lambda d: d.values()
191 copyvalues = lambda d: list(d.values())
192
193 try:
194
195 import builtins
196 except ImportError:
197
198 import __builtin__ as builtins
199
200 try:
201
202
203 from Cookie import SimpleCookie, CookieError
204 from httplib import BadStatusLine, HTTPConnection, HTTPSConnection, IncompleteRead, NotConnected
205 from BaseHTTPServer import BaseHTTPRequestHandler
206 except ImportError:
207
208 from http.cookies import SimpleCookie, CookieError
209 from http.client import BadStatusLine, HTTPConnection, HTTPSConnection, IncompleteRead, NotConnected
210 from http.server import BaseHTTPRequestHandler
211
212 try:
213
214
215 from httplib import HTTPSConnection
216 except ImportError:
217 try:
218
219 from http.client import HTTPSConnection
220 except ImportError:
221
222 HTTPSConnection = None
223
224 try:
225
226 xrange = xrange
227 except NameError:
228
229 xrange = range
230
231 import threading
232 if hasattr(threading.Thread, "daemon"):
233
238 else:
243
244 try:
245 from email.utils import formatdate
247 return formatdate(timeval, usegmt=True)
248 except ImportError:
249 from rfc822 import formatdate as HTTPDate
250
251 try:
252
253 from urllib.parse import unquote as parse_unquote
256 except ImportError:
257
258 from urllib import unquote as parse_unquote
261
262 try:
263
264 import simplejson as json
265 json_decode = json.JSONDecoder().decode
266 json_encode = json.JSONEncoder().iterencode
267 except ImportError:
268 if py3k:
269
270
271 import json
272 json_decode = json.JSONDecoder().decode
273 _json_encode = json.JSONEncoder().iterencode
277 elif sys.version_info >= (2, 6):
278
279 import json
280 json_decode = json.JSONDecoder().decode
281 json_encode = json.JSONEncoder().iterencode
282 else:
283 json = None
285 raise ValueError('No JSON library is available')
287 raise ValueError('No JSON library is available')
288
289 try:
290 import cPickle as pickle
291 except ImportError:
292
293
294 import pickle
295
296 try:
297 os.urandom(20)
298 import binascii
300 return binascii.hexlify(os.urandom(20)).decode('ascii')
301 except (AttributeError, NotImplementedError):
302 import random
303
305 return sha('%s' % random.random()).hexdigest()
306
307 try:
308 from _thread import get_ident as get_thread_ident
309 except ImportError:
310 from thread import get_ident as get_thread_ident
311
312 try:
313
314 next = next
315 except NameError:
316
319