| Index: third_party/pycoverage/coverage/backward.py
|
| diff --git a/third_party/pycoverage/coverage/backward.py b/third_party/pycoverage/coverage/backward.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7d2685459782c85c59ff7b78cf8d02adf4b2ca89
|
| --- /dev/null
|
| +++ b/third_party/pycoverage/coverage/backward.py
|
| @@ -0,0 +1,184 @@
|
| +"""Add things to old Pythons so I can pretend they are newer."""
|
| +
|
| +# This file does lots of tricky stuff, so disable a bunch of lintisms.
|
| +# pylint: disable=F0401,W0611,W0622
|
| +# F0401: Unable to import blah
|
| +# W0611: Unused import blah
|
| +# W0622: Redefining built-in blah
|
| +
|
| +import os, re, sys
|
| +
|
| +# Python 2.3 doesn't have `set`
|
| +try:
|
| + set = set # new in 2.4
|
| +except NameError:
|
| + from sets import Set as set
|
| +
|
| +# Python 2.3 doesn't have `sorted`.
|
| +try:
|
| + sorted = sorted
|
| +except NameError:
|
| + def sorted(iterable):
|
| + """A 2.3-compatible implementation of `sorted`."""
|
| + lst = list(iterable)
|
| + lst.sort()
|
| + return lst
|
| +
|
| +# Python 2.3 doesn't have `reversed`.
|
| +try:
|
| + reversed = reversed
|
| +except NameError:
|
| + def reversed(iterable):
|
| + """A 2.3-compatible implementation of `reversed`."""
|
| + lst = list(iterable)
|
| + return lst[::-1]
|
| +
|
| +# rpartition is new in 2.5
|
| +try:
|
| + "".rpartition
|
| +except AttributeError:
|
| + def rpartition(s, sep):
|
| + """Implement s.rpartition(sep) for old Pythons."""
|
| + i = s.rfind(sep)
|
| + if i == -1:
|
| + return ('', '', s)
|
| + else:
|
| + return (s[:i], sep, s[i+len(sep):])
|
| +else:
|
| + def rpartition(s, sep):
|
| + """A common interface for new Pythons."""
|
| + return s.rpartition(sep)
|
| +
|
| +# Pythons 2 and 3 differ on where to get StringIO
|
| +try:
|
| + from cStringIO import StringIO
|
| + BytesIO = StringIO
|
| +except ImportError:
|
| + from io import StringIO, BytesIO
|
| +
|
| +# What's a string called?
|
| +try:
|
| + string_class = basestring
|
| +except NameError:
|
| + string_class = str
|
| +
|
| +# Where do pickles come from?
|
| +try:
|
| + import cPickle as pickle
|
| +except ImportError:
|
| + import pickle
|
| +
|
| +# range or xrange?
|
| +try:
|
| + range = xrange
|
| +except NameError:
|
| + range = range
|
| +
|
| +# A function to iterate listlessly over a dict's items.
|
| +try:
|
| + {}.iteritems
|
| +except AttributeError:
|
| + def iitems(d):
|
| + """Produce the items from dict `d`."""
|
| + return d.items()
|
| +else:
|
| + def iitems(d):
|
| + """Produce the items from dict `d`."""
|
| + return d.iteritems()
|
| +
|
| +# Exec is a statement in Py2, a function in Py3
|
| +if sys.version_info >= (3, 0):
|
| + def exec_code_object(code, global_map):
|
| + """A wrapper around exec()."""
|
| + exec(code, global_map)
|
| +else:
|
| + # OK, this is pretty gross. In Py2, exec was a statement, but that will
|
| + # be a syntax error if we try to put it in a Py3 file, even if it is never
|
| + # executed. So hide it inside an evaluated string literal instead.
|
| + eval(
|
| + compile(
|
| + "def exec_code_object(code, global_map):\n"
|
| + " exec code in global_map\n",
|
| + "<exec_function>", "exec"
|
| + )
|
| + )
|
| +
|
| +# Reading Python source and interpreting the coding comment is a big deal.
|
| +if sys.version_info >= (3, 0):
|
| + # Python 3.2 provides `tokenize.open`, the best way to open source files.
|
| + import tokenize
|
| + try:
|
| + open_source = tokenize.open # pylint: disable=E1101
|
| + except AttributeError:
|
| + from io import TextIOWrapper
|
| + detect_encoding = tokenize.detect_encoding # pylint: disable=E1101
|
| + # Copied from the 3.2 stdlib:
|
| + def open_source(fname):
|
| + """Open a file in read only mode using the encoding detected by
|
| + detect_encoding().
|
| + """
|
| + buffer = open(fname, 'rb')
|
| + encoding, _ = detect_encoding(buffer.readline)
|
| + buffer.seek(0)
|
| + text = TextIOWrapper(buffer, encoding, line_buffering=True)
|
| + text.mode = 'r'
|
| + return text
|
| +else:
|
| + def open_source(fname):
|
| + """Open a source file the best way."""
|
| + return open(fname, "rU")
|
| +
|
| +
|
| +# Python 3.x is picky about bytes and strings, so provide methods to
|
| +# get them right, and make them no-ops in 2.x
|
| +if sys.version_info >= (3, 0):
|
| + def to_bytes(s):
|
| + """Convert string `s` to bytes."""
|
| + return s.encode('utf8')
|
| +
|
| + def to_string(b):
|
| + """Convert bytes `b` to a string."""
|
| + return b.decode('utf8')
|
| +
|
| + def binary_bytes(byte_values):
|
| + """Produce a byte string with the ints from `byte_values`."""
|
| + return bytes(byte_values)
|
| +
|
| + def byte_to_int(byte_value):
|
| + """Turn an element of a bytes object into an int."""
|
| + return byte_value
|
| +
|
| + def bytes_to_ints(bytes_value):
|
| + """Turn a bytes object into a sequence of ints."""
|
| + # In Py3, iterating bytes gives ints.
|
| + return bytes_value
|
| +
|
| +else:
|
| + def to_bytes(s):
|
| + """Convert string `s` to bytes (no-op in 2.x)."""
|
| + return s
|
| +
|
| + def to_string(b):
|
| + """Convert bytes `b` to a string (no-op in 2.x)."""
|
| + return b
|
| +
|
| + def binary_bytes(byte_values):
|
| + """Produce a byte string with the ints from `byte_values`."""
|
| + return "".join([chr(b) for b in byte_values])
|
| +
|
| + def byte_to_int(byte_value):
|
| + """Turn an element of a bytes object into an int."""
|
| + return ord(byte_value)
|
| +
|
| + def bytes_to_ints(bytes_value):
|
| + """Turn a bytes object into a sequence of ints."""
|
| + for byte in bytes_value:
|
| + yield ord(byte)
|
| +
|
| +# Md5 is available in different places.
|
| +try:
|
| + import hashlib
|
| + md5 = hashlib.md5
|
| +except ImportError:
|
| + import md5
|
| + md5 = md5.new
|
|
|