Package cherrypy :: Module _cpcompat
[hide private]
[frames] | no frames]

Source Code for Module cherrypy._cpcompat

  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  import threading 
 22   
 23  if sys.version_info >= (3, 0): 
 24      py3k = True 
 25      bytestr = bytes 
 26      unicodestr = str 
 27      nativestr = unicodestr 
 28      basestring = (bytes, str) 
29 - def ntob(n, encoding='ISO-8859-1'):
30 """Return the given native string as a byte string in the given encoding.""" 31 # In Python 3, the native string type is unicode 32 return n.encode(encoding)
33 - def ntou(n, encoding='ISO-8859-1'):
34 """Return the given native string as a unicode string with the given encoding.""" 35 # In Python 3, the native string type is unicode 36 return n
37 - def tonative(n, encoding='ISO-8859-1'):
38 """Return the given string as a native string in the given encoding.""" 39 # In Python 3, the native string type is unicode 40 if isinstance(n, bytes): 41 return n.decode(encoding) 42 return n
43 # type("") 44 from io import StringIO 45 # bytes: 46 from io import BytesIO as BytesIO 47 else: 48 # Python 2 49 py3k = False 50 bytestr = str 51 unicodestr = unicode 52 nativestr = bytestr 53 basestring = basestring
54 - def ntob(n, encoding='ISO-8859-1'):
55 """Return the given native string as a byte string in the given encoding.""" 56 # In Python 2, the native string type is bytes. Assume it's already 57 # in the given encoding, which for ISO-8859-1 is almost always what 58 # was intended. 59 return n
60 - def ntou(n, encoding='ISO-8859-1'):
61 """Return the given native string as a unicode string with the given encoding.""" 62 # In Python 2, the native string type is bytes. 63 # First, check for the special encoding 'escape'. The test suite uses this 64 # to signal that it wants to pass a string with embedded \uXXXX escapes, 65 # but without having to prefix it with u'' for Python 2, but no prefix 66 # for Python 3. 67 if encoding == 'escape': 68 return unicode( 69 re.sub(r'\\u([0-9a-zA-Z]{4})', 70 lambda m: unichr(int(m.group(1), 16)), 71 n.decode('ISO-8859-1'))) 72 # Assume it's already in the given encoding, which for ISO-8859-1 is almost 73 # always what was intended. 74 return n.decode(encoding)
75 - def tonative(n, encoding='ISO-8859-1'):
76 """Return the given string as a native string in the given encoding.""" 77 # In Python 2, the native string type is bytes. 78 if isinstance(n, unicode): 79 return n.encode(encoding) 80 return n
81 try: 82 # type("") 83 from cStringIO import StringIO 84 except ImportError: 85 # type("") 86 from StringIO import StringIO 87 # bytes: 88 BytesIO = StringIO 89 90 try: 91 set = set 92 except NameError: 93 from sets import Set as set 94 95 try: 96 # Python 3.1+ 97 from base64 import decodebytes as _base64_decodebytes 98 except ImportError: 99 # Python 3.0- 100 # since CherryPy claims compability with Python 2.3, we must use 101 # the legacy API of base64 102 from base64 import decodestring as _base64_decodebytes 103
104 -def base64_decode(n, encoding='ISO-8859-1'):
105 """Return the native string base64-decoded (as a native string).""" 106 if isinstance(n, unicodestr): 107 b = n.encode(encoding) 108 else: 109 b = n 110 b = _base64_decodebytes(b) 111 if nativestr is unicodestr: 112 return b.decode(encoding) 113 else: 114 return b
115 116 try: 117 # Python 2.5+ 118 from hashlib import md5 119 except ImportError: 120 from md5 import new as md5 121 122 try: 123 # Python 2.5+ 124 from hashlib import sha1 as sha 125 except ImportError: 126 from sha import new as sha 127 128 try: 129 sorted = sorted 130 except NameError:
131 - def sorted(i):
132 i = i[:] 133 i.sort() 134 return i
135 136 try: 137 reversed = reversed 138 except NameError:
139 - def reversed(x):
140 i = len(x) 141 while i > 0: 142 i -= 1 143 yield x[i]
144 145 try: 146 # Python 3 147 from urllib.parse import urljoin, urlencode 148 from urllib.parse import quote, quote_plus 149 from urllib.request import unquote, urlopen 150 from urllib.request import parse_http_list, parse_keqv_list 151 except ImportError: 152 # Python 2 153 from urlparse import urljoin 154 from urllib import urlencode, urlopen 155 from urllib import quote, quote_plus 156 from urllib import unquote 157 from urllib2 import parse_http_list, parse_keqv_list 158 159 try: 160 from threading import local as threadlocal 161 except ImportError: 162 from cherrypy._cpthreadinglocal import local as threadlocal 163 164 try: 165 dict.iteritems 166 # Python 2 167 iteritems = lambda d: d.iteritems() 168 copyitems = lambda d: d.items() 169 except AttributeError: 170 # Python 3 171 iteritems = lambda d: d.items() 172 copyitems = lambda d: list(d.items()) 173 174 try: 175 dict.iterkeys 176 # Python 2 177 iterkeys = lambda d: d.iterkeys() 178 copykeys = lambda d: d.keys() 179 except AttributeError: 180 # Python 3 181 iterkeys = lambda d: d.keys() 182 copykeys = lambda d: list(d.keys()) 183 184 try: 185 dict.itervalues 186 # Python 2 187 itervalues = lambda d: d.itervalues() 188 copyvalues = lambda d: d.values() 189 except AttributeError: 190 # Python 3 191 itervalues = lambda d: d.values() 192 copyvalues = lambda d: list(d.values()) 193 194 try: 195 # Python 3 196 import builtins 197 except ImportError: 198 # Python 2 199 import __builtin__ as builtins 200 201 try: 202 # Python 2. We have to do it in this order so Python 2 builds 203 # don't try to import the 'http' module from cherrypy.lib 204 from Cookie import SimpleCookie, CookieError 205 from httplib import BadStatusLine, HTTPConnection, HTTPSConnection, IncompleteRead, NotConnected 206 from BaseHTTPServer import BaseHTTPRequestHandler 207 except ImportError: 208 # Python 3 209 from http.cookies import SimpleCookie, CookieError 210 from http.client import BadStatusLine, HTTPConnection, HTTPSConnection, IncompleteRead, NotConnected 211 from http.server import BaseHTTPRequestHandler 212 213 try: 214 # Python 2. We have to do it in this order so Python 2 builds 215 # don't try to import the 'http' module from cherrypy.lib 216 from httplib import HTTPSConnection 217 except ImportError: 218 try: 219 # Python 3 220 from http.client import HTTPSConnection 221 except ImportError: 222 # Some platforms which don't have SSL don't expose HTTPSConnection 223 HTTPSConnection = None 224 225 try: 226 # Python 2 227 xrange = xrange 228 except NameError: 229 # Python 3 230 xrange = range 231 232 import threading 233 if hasattr(threading.Thread, "daemon"): 234 # Python 2.6+
235 - def get_daemon(t):
236 return t.daemon
237 - def set_daemon(t, val):
238 t.daemon = val
239 else:
240 - def get_daemon(t):
241 return t.isDaemon()
242 - def set_daemon(t, val):
243 t.setDaemon(val)
244 245 try: 246 from email.utils import formatdate
247 - def HTTPDate(timeval=None):
248 return formatdate(timeval, usegmt=True)
249 except ImportError: 250 from rfc822 import formatdate as HTTPDate 251 252 try: 253 # Python 3 254 from urllib.parse import unquote as parse_unquote
255 - def unquote_qs(atom, encoding, errors='strict'):
256 return parse_unquote(atom.replace('+', ' '), encoding=encoding, errors=errors)
257 except ImportError: 258 # Python 2 259 from urllib import unquote as parse_unquote
260 - def unquote_qs(atom, encoding, errors='strict'):
261 return parse_unquote(atom.replace('+', ' ')).decode(encoding, errors)
262 263 try: 264 # Prefer simplejson, which is usually more advanced than the builtin module. 265 import simplejson as json 266 json_decode = json.JSONDecoder().decode 267 json_encode = json.JSONEncoder().iterencode 268 except ImportError: 269 if py3k: 270 # Python 3.0: json is part of the standard library, 271 # but outputs unicode. We need bytes. 272 import json 273 json_decode = json.JSONDecoder().decode 274 _json_encode = json.JSONEncoder().iterencode
275 - def json_encode(value):
276 for chunk in _json_encode(value): 277 yield chunk.encode('utf8')
278 elif sys.version_info >= (2, 6): 279 # Python 2.6: json is part of the standard library 280 import json 281 json_decode = json.JSONDecoder().decode 282 json_encode = json.JSONEncoder().iterencode 283 else: 284 json = None
285 - def json_decode(s):
286 raise ValueError('No JSON library is available')
287 - def json_encode(s):
288 raise ValueError('No JSON library is available')
289 290 try: 291 import cPickle as pickle 292 except ImportError: 293 # In Python 2, pickle is a Python version. 294 # In Python 3, pickle is the sped-up C version. 295 import pickle 296 297 try: 298 os.urandom(20) 299 import binascii
300 - def random20():
301 return binascii.hexlify(os.urandom(20)).decode('ascii')
302 except (AttributeError, NotImplementedError): 303 import random 304 # os.urandom not available until Python 2.4. Fall back to random.random.
305 - def random20():
306 return sha('%s' % random.random()).hexdigest()
307 308 try: 309 from _thread import get_ident as get_thread_ident 310 except ImportError: 311 from thread import get_ident as get_thread_ident 312 313 try: 314 # Python 3 315 next = next 316 except NameError: 317 # Python 2
318 - def next(i):
319 return i.next()
320 321 if sys.version_info >= (3,3): 322 Timer = threading.Timer 323 else: 324 # Python 3.2 and earlier 325 Timer = threading._Timer 326