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   
 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 # In Python 3, the native string type is unicode 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 # In Python 3, the native string type is unicode 35 return n
36 - def tonative(n, encoding='ISO-8859-1'):
37 """Return the given string as a native string in the given encoding.""" 38 # In Python 3, the native string type is unicode 39 if isinstance(n, bytes): 40 return n.decode(encoding) 41 return n
42 # type("") 43 from io import StringIO 44 # bytes: 45 from io import BytesIO as BytesIO 46 else: 47 # Python 2 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 # In Python 2, the native string type is bytes. Assume it's already 56 # in the given encoding, which for ISO-8859-1 is almost always what 57 # was intended. 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 # In Python 2, the native string type is bytes. 62 # First, check for the special encoding 'escape'. The test suite uses this 63 # to signal that it wants to pass a string with embedded \uXXXX escapes, 64 # but without having to prefix it with u'' for Python 2, but no prefix 65 # for Python 3. 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 # Assume it's already in the given encoding, which for ISO-8859-1 is almost 72 # always what was intended. 73 return n.decode(encoding)
74 - def tonative(n, encoding='ISO-8859-1'):
75 """Return the given string as a native string in the given encoding.""" 76 # In Python 2, the native string type is bytes. 77 if isinstance(n, unicode): 78 return n.encode(encoding) 79 return n
80 try: 81 # type("") 82 from cStringIO import StringIO 83 except ImportError: 84 # type("") 85 from StringIO import StringIO 86 # bytes: 87 BytesIO = StringIO 88 89 try: 90 set = set 91 except NameError: 92 from sets import Set as set 93 94 try: 95 # Python 3.1+ 96 from base64 import decodebytes as _base64_decodebytes 97 except ImportError: 98 # Python 3.0- 99 # since CherryPy claims compability with Python 2.3, we must use 100 # the legacy API of base64 101 from base64 import decodestring as _base64_decodebytes 102
103 -def base64_decode(n, encoding='ISO-8859-1'):
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 # Python 2.5+ 117 from hashlib import md5 118 except ImportError: 119 from md5 import new as md5 120 121 try: 122 # Python 2.5+ 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:
130 - def sorted(i):
131 i = i[:] 132 i.sort() 133 return i
134 135 try: 136 reversed = reversed 137 except NameError:
138 - def reversed(x):
139 i = len(x) 140 while i > 0: 141 i -= 1 142 yield x[i]
143 144 try: 145 # Python 3 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 # Python 2 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 # Python 2 166 iteritems = lambda d: d.iteritems() 167 copyitems = lambda d: d.items() 168 except AttributeError: 169 # Python 3 170 iteritems = lambda d: d.items() 171 copyitems = lambda d: list(d.items()) 172 173 try: 174 dict.iterkeys 175 # Python 2 176 iterkeys = lambda d: d.iterkeys() 177 copykeys = lambda d: d.keys() 178 except AttributeError: 179 # Python 3 180 iterkeys = lambda d: d.keys() 181 copykeys = lambda d: list(d.keys()) 182 183 try: 184 dict.itervalues 185 # Python 2 186 itervalues = lambda d: d.itervalues() 187 copyvalues = lambda d: d.values() 188 except AttributeError: 189 # Python 3 190 itervalues = lambda d: d.values() 191 copyvalues = lambda d: list(d.values()) 192 193 try: 194 # Python 3 195 import builtins 196 except ImportError: 197 # Python 2 198 import __builtin__ as builtins 199 200 try: 201 # Python 2. We have to do it in this order so Python 2 builds 202 # don't try to import the 'http' module from cherrypy.lib 203 from Cookie import SimpleCookie, CookieError 204 from httplib import BadStatusLine, HTTPConnection, HTTPSConnection, IncompleteRead, NotConnected 205 from BaseHTTPServer import BaseHTTPRequestHandler 206 except ImportError: 207 # Python 3 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 # Python 2. We have to do it in this order so Python 2 builds 214 # don't try to import the 'http' module from cherrypy.lib 215 from httplib import HTTPSConnection 216 except ImportError: 217 try: 218 # Python 3 219 from http.client import HTTPSConnection 220 except ImportError: 221 # Some platforms which don't have SSL don't expose HTTPSConnection 222 HTTPSConnection = None 223 224 try: 225 # Python 2 226 xrange = xrange 227 except NameError: 228 # Python 3 229 xrange = range 230 231 import threading 232 if hasattr(threading.Thread, "daemon"): 233 # Python 2.6+
234 - def get_daemon(t):
235 return t.daemon
236 - def set_daemon(t, val):
237 t.daemon = val
238 else:
239 - def get_daemon(t):
240 return t.isDaemon()
241 - def set_daemon(t, val):
242 t.setDaemon(val)
243 244 try: 245 from email.utils import formatdate
246 - def HTTPDate(timeval=None):
247 return formatdate(timeval, usegmt=True)
248 except ImportError: 249 from rfc822 import formatdate as HTTPDate 250 251 try: 252 # Python 3 253 from urllib.parse import unquote as parse_unquote
254 - def unquote_qs(atom, encoding, errors='strict'):
255 return parse_unquote(atom.replace('+', ' '), encoding=encoding, errors=errors)
256 except ImportError: 257 # Python 2 258 from urllib import unquote as parse_unquote
259 - def unquote_qs(atom, encoding, errors='strict'):
260 return parse_unquote(atom.replace('+', ' ')).decode(encoding, errors)
261 262 try: 263 # Prefer simplejson, which is usually more advanced than the builtin module. 264 import simplejson as json 265 json_decode = json.JSONDecoder().decode 266 json_encode = json.JSONEncoder().iterencode 267 except ImportError: 268 if py3k: 269 # Python 3.0: json is part of the standard library, 270 # but outputs unicode. We need bytes. 271 import json 272 json_decode = json.JSONDecoder().decode 273 _json_encode = json.JSONEncoder().iterencode
274 - def json_encode(value):
275 for chunk in _json_encode(value): 276 yield chunk.encode('utf8')
277 elif sys.version_info >= (2, 6): 278 # Python 2.6: json is part of the standard library 279 import json 280 json_decode = json.JSONDecoder().decode 281 json_encode = json.JSONEncoder().iterencode 282 else: 283 json = None
284 - def json_decode(s):
285 raise ValueError('No JSON library is available')
286 - def json_encode(s):
287 raise ValueError('No JSON library is available')
288 289 try: 290 import cPickle as pickle 291 except ImportError: 292 # In Python 2, pickle is a Python version. 293 # In Python 3, pickle is the sped-up C version. 294 import pickle 295 296 try: 297 os.urandom(20) 298 import binascii
299 - def random20():
300 return binascii.hexlify(os.urandom(20)).decode('ascii')
301 except (AttributeError, NotImplementedError): 302 import random 303 # os.urandom not available until Python 2.4. Fall back to random.random.
304 - def random20():
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 # Python 3 314 next = next 315 except NameError: 316 # Python 2
317 - def next(i):
318 return i.next()
319