Index: third_party/cherrypy/_cpcompat.py |
=================================================================== |
--- third_party/cherrypy/_cpcompat.py (revision 0) |
+++ third_party/cherrypy/_cpcompat.py (revision 0) |
@@ -0,0 +1,318 @@ |
+"""Compatibility code for using CherryPy with various versions of Python. |
+ |
+CherryPy 3.2 is compatible with Python versions 2.3+. This module provides a |
+useful abstraction over the differences between Python versions, sometimes by |
+preferring a newer idiom, sometimes an older one, and sometimes a custom one. |
+ |
+In particular, Python 2 uses str and '' for byte strings, while Python 3 |
+uses str and '' for unicode strings. We will call each of these the 'native |
+string' type for each version. Because of this major difference, this module |
+provides new 'bytestr', 'unicodestr', and 'nativestr' attributes, as well as |
+two functions: 'ntob', which translates native strings (of type 'str') into |
+byte strings regardless of Python version, and 'ntou', which translates native |
+strings to unicode strings. This also provides a 'BytesIO' name for dealing |
+specifically with bytes, and a 'StringIO' name for dealing with native strings. |
+It also provides a 'base64_decode' function with native strings as input and |
+output. |
+""" |
+import os |
+import re |
+import sys |
+ |
+if sys.version_info >= (3, 0): |
+ py3k = True |
+ bytestr = bytes |
+ unicodestr = str |
+ nativestr = unicodestr |
+ basestring = (bytes, str) |
+ def ntob(n, encoding='ISO-8859-1'): |
+ """Return the given native string as a byte string in the given encoding.""" |
+ # In Python 3, the native string type is unicode |
+ return n.encode(encoding) |
+ def ntou(n, encoding='ISO-8859-1'): |
+ """Return the given native string as a unicode string with the given encoding.""" |
+ # In Python 3, the native string type is unicode |
+ return n |
+ def tonative(n, encoding='ISO-8859-1'): |
+ """Return the given string as a native string in the given encoding.""" |
+ # In Python 3, the native string type is unicode |
+ if isinstance(n, bytes): |
+ return n.decode(encoding) |
+ return n |
+ # type("") |
+ from io import StringIO |
+ # bytes: |
+ from io import BytesIO as BytesIO |
+else: |
+ # Python 2 |
+ py3k = False |
+ bytestr = str |
+ unicodestr = unicode |
+ nativestr = bytestr |
+ basestring = basestring |
+ def ntob(n, encoding='ISO-8859-1'): |
+ """Return the given native string as a byte string in the given encoding.""" |
+ # In Python 2, the native string type is bytes. Assume it's already |
+ # in the given encoding, which for ISO-8859-1 is almost always what |
+ # was intended. |
+ return n |
+ def ntou(n, encoding='ISO-8859-1'): |
+ """Return the given native string as a unicode string with the given encoding.""" |
+ # In Python 2, the native string type is bytes. |
+ # First, check for the special encoding 'escape'. The test suite uses this |
+ # to signal that it wants to pass a string with embedded \uXXXX escapes, |
+ # but without having to prefix it with u'' for Python 2, but no prefix |
+ # for Python 3. |
+ if encoding == 'escape': |
+ return unicode( |
+ re.sub(r'\\u([0-9a-zA-Z]{4})', |
+ lambda m: unichr(int(m.group(1), 16)), |
+ n.decode('ISO-8859-1'))) |
+ # Assume it's already in the given encoding, which for ISO-8859-1 is almost |
+ # always what was intended. |
+ return n.decode(encoding) |
+ def tonative(n, encoding='ISO-8859-1'): |
+ """Return the given string as a native string in the given encoding.""" |
+ # In Python 2, the native string type is bytes. |
+ if isinstance(n, unicode): |
+ return n.encode(encoding) |
+ return n |
+ try: |
+ # type("") |
+ from cStringIO import StringIO |
+ except ImportError: |
+ # type("") |
+ from StringIO import StringIO |
+ # bytes: |
+ BytesIO = StringIO |
+ |
+try: |
+ set = set |
+except NameError: |
+ from sets import Set as set |
+ |
+try: |
+ # Python 3.1+ |
+ from base64 import decodebytes as _base64_decodebytes |
+except ImportError: |
+ # Python 3.0- |
+ # since CherryPy claims compability with Python 2.3, we must use |
+ # the legacy API of base64 |
+ from base64 import decodestring as _base64_decodebytes |
+ |
+def base64_decode(n, encoding='ISO-8859-1'): |
+ """Return the native string base64-decoded (as a native string).""" |
+ if isinstance(n, unicodestr): |
+ b = n.encode(encoding) |
+ else: |
+ b = n |
+ b = _base64_decodebytes(b) |
+ if nativestr is unicodestr: |
+ return b.decode(encoding) |
+ else: |
+ return b |
+ |
+try: |
+ # Python 2.5+ |
+ from hashlib import md5 |
+except ImportError: |
+ from md5 import new as md5 |
+ |
+try: |
+ # Python 2.5+ |
+ from hashlib import sha1 as sha |
+except ImportError: |
+ from sha import new as sha |
+ |
+try: |
+ sorted = sorted |
+except NameError: |
+ def sorted(i): |
+ i = i[:] |
+ i.sort() |
+ return i |
+ |
+try: |
+ reversed = reversed |
+except NameError: |
+ def reversed(x): |
+ i = len(x) |
+ while i > 0: |
+ i -= 1 |
+ yield x[i] |
+ |
+try: |
+ # Python 3 |
+ from urllib.parse import urljoin, urlencode |
+ from urllib.parse import quote, quote_plus |
+ from urllib.request import unquote, urlopen |
+ from urllib.request import parse_http_list, parse_keqv_list |
+except ImportError: |
+ # Python 2 |
+ from urlparse import urljoin |
+ from urllib import urlencode, urlopen |
+ from urllib import quote, quote_plus |
+ from urllib import unquote |
+ from urllib2 import parse_http_list, parse_keqv_list |
+ |
+try: |
+ from threading import local as threadlocal |
+except ImportError: |
+ from cherrypy._cpthreadinglocal import local as threadlocal |
+ |
+try: |
+ dict.iteritems |
+ # Python 2 |
+ iteritems = lambda d: d.iteritems() |
+ copyitems = lambda d: d.items() |
+except AttributeError: |
+ # Python 3 |
+ iteritems = lambda d: d.items() |
+ copyitems = lambda d: list(d.items()) |
+ |
+try: |
+ dict.iterkeys |
+ # Python 2 |
+ iterkeys = lambda d: d.iterkeys() |
+ copykeys = lambda d: d.keys() |
+except AttributeError: |
+ # Python 3 |
+ iterkeys = lambda d: d.keys() |
+ copykeys = lambda d: list(d.keys()) |
+ |
+try: |
+ dict.itervalues |
+ # Python 2 |
+ itervalues = lambda d: d.itervalues() |
+ copyvalues = lambda d: d.values() |
+except AttributeError: |
+ # Python 3 |
+ itervalues = lambda d: d.values() |
+ copyvalues = lambda d: list(d.values()) |
+ |
+try: |
+ # Python 3 |
+ import builtins |
+except ImportError: |
+ # Python 2 |
+ import __builtin__ as builtins |
+ |
+try: |
+ # Python 2. We have to do it in this order so Python 2 builds |
+ # don't try to import the 'http' module from cherrypy.lib |
+ from Cookie import SimpleCookie, CookieError |
+ from httplib import BadStatusLine, HTTPConnection, HTTPSConnection, IncompleteRead, NotConnected |
+ from BaseHTTPServer import BaseHTTPRequestHandler |
+except ImportError: |
+ # Python 3 |
+ from http.cookies import SimpleCookie, CookieError |
+ from http.client import BadStatusLine, HTTPConnection, HTTPSConnection, IncompleteRead, NotConnected |
+ from http.server import BaseHTTPRequestHandler |
+ |
+try: |
+ # Python 2. We have to do it in this order so Python 2 builds |
+ # don't try to import the 'http' module from cherrypy.lib |
+ from httplib import HTTPSConnection |
+except ImportError: |
+ try: |
+ # Python 3 |
+ from http.client import HTTPSConnection |
+ except ImportError: |
+ # Some platforms which don't have SSL don't expose HTTPSConnection |
+ HTTPSConnection = None |
+ |
+try: |
+ # Python 2 |
+ xrange = xrange |
+except NameError: |
+ # Python 3 |
+ xrange = range |
+ |
+import threading |
+if hasattr(threading.Thread, "daemon"): |
+ # Python 2.6+ |
+ def get_daemon(t): |
+ return t.daemon |
+ def set_daemon(t, val): |
+ t.daemon = val |
+else: |
+ def get_daemon(t): |
+ return t.isDaemon() |
+ def set_daemon(t, val): |
+ t.setDaemon(val) |
+ |
+try: |
+ from email.utils import formatdate |
+ def HTTPDate(timeval=None): |
+ return formatdate(timeval, usegmt=True) |
+except ImportError: |
+ from rfc822 import formatdate as HTTPDate |
+ |
+try: |
+ # Python 3 |
+ from urllib.parse import unquote as parse_unquote |
+ def unquote_qs(atom, encoding, errors='strict'): |
+ return parse_unquote(atom.replace('+', ' '), encoding=encoding, errors=errors) |
+except ImportError: |
+ # Python 2 |
+ from urllib import unquote as parse_unquote |
+ def unquote_qs(atom, encoding, errors='strict'): |
+ return parse_unquote(atom.replace('+', ' ')).decode(encoding, errors) |
+ |
+try: |
+ # Prefer simplejson, which is usually more advanced than the builtin module. |
+ import simplejson as json |
+ json_decode = json.JSONDecoder().decode |
+ json_encode = json.JSONEncoder().iterencode |
+except ImportError: |
+ if py3k: |
+ # Python 3.0: json is part of the standard library, |
+ # but outputs unicode. We need bytes. |
+ import json |
+ json_decode = json.JSONDecoder().decode |
+ _json_encode = json.JSONEncoder().iterencode |
+ def json_encode(value): |
+ for chunk in _json_encode(value): |
+ yield chunk.encode('utf8') |
+ elif sys.version_info >= (2, 6): |
+ # Python 2.6: json is part of the standard library |
+ import json |
+ json_decode = json.JSONDecoder().decode |
+ json_encode = json.JSONEncoder().iterencode |
+ else: |
+ json = None |
+ def json_decode(s): |
+ raise ValueError('No JSON library is available') |
+ def json_encode(s): |
+ raise ValueError('No JSON library is available') |
+ |
+try: |
+ import cPickle as pickle |
+except ImportError: |
+ # In Python 2, pickle is a Python version. |
+ # In Python 3, pickle is the sped-up C version. |
+ import pickle |
+ |
+try: |
+ os.urandom(20) |
+ import binascii |
+ def random20(): |
+ return binascii.hexlify(os.urandom(20)).decode('ascii') |
+except (AttributeError, NotImplementedError): |
+ import random |
+ # os.urandom not available until Python 2.4. Fall back to random.random. |
+ def random20(): |
+ return sha('%s' % random.random()).hexdigest() |
+ |
+try: |
+ from _thread import get_ident as get_thread_ident |
+except ImportError: |
+ from thread import get_ident as get_thread_ident |
+ |
+try: |
+ # Python 3 |
+ next = next |
+except NameError: |
+ # Python 2 |
+ def next(i): |
+ return i.next() |
Property changes on: third_party/cherrypy/_cpcompat.py |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |