1 """Add things to old Pythons so I can pretend they are newer."""
3 # This file does lots of tricky stuff, so disable a bunch of lintisms.
4 # pylint: disable=F0401,W0611,W0622
5 # F0401: Unable to import blah
6 # W0611: Unused import blah
7 # W0622: Redefining built-in blah
11 # Python 2.3 doesn't have `set`
13 set = set # new in 2.4
15 from sets
import Set
as set
17 # Python 2.3 doesn't have `sorted`.
22 """A 2.3-compatible implementation of `sorted`."""
27 # Python 2.3 doesn't have `reversed`.
31 def reversed(iterable
):
32 """A 2.3-compatible implementation of `reversed`."""
36 # rpartition is new in 2.5
39 except AttributeError:
40 def rpartition(s
, sep
):
41 """Implement s.rpartition(sep) for old Pythons."""
46 return (s
[:i
], sep
, s
[i
+len(sep
):])
48 def rpartition(s
, sep
):
49 """A common interface for new Pythons."""
50 return s
.rpartition(sep
)
52 # Pythons 2 and 3 differ on where to get StringIO
54 from cStringIO
import StringIO
57 from io
import StringIO
, BytesIO
59 # What's a string called?
61 string_class
= basestring
65 # Where do pickles come from?
67 import cPickle
as pickle
77 # A function to iterate listlessly over a dict's items.
80 except AttributeError:
82 """Produce the items from dict `d`."""
86 """Produce the items from dict `d`."""
89 # Exec is a statement in Py2, a function in Py3
90 if sys
.version_info
>= (3, 0):
91 def exec_code_object(code
, global_map
):
92 """A wrapper around exec()."""
93 exec(code
, global_map
)
95 # OK, this is pretty gross. In Py2, exec was a statement, but that will
96 # be a syntax error if we try to put it in a Py3 file, even if it is never
97 # executed. So hide it inside an evaluated string literal instead.
100 "def exec_code_object(code, global_map):\n"
101 " exec code in global_map\n",
102 "<exec_function>", "exec"
106 # Reading Python source and interpreting the coding comment is a big deal.
107 if sys
.version_info
>= (3, 0):
108 # Python 3.2 provides `tokenize.open`, the best way to open source files.
111 open_source
= tokenize
.open # pylint: disable=E1101
112 except AttributeError:
113 from io
import TextIOWrapper
114 detect_encoding
= tokenize
.detect_encoding
# pylint: disable=E1101
115 # Copied from the 3.2 stdlib:
116 def open_source(fname
):
117 """Open a file in read only mode using the encoding detected by
120 buffer = open(fname
, 'rb')
121 encoding
, _
= detect_encoding(buffer.readline
)
123 text
= TextIOWrapper(buffer, encoding
, line_buffering
=True)
127 def open_source(fname
):
128 """Open a source file the best way."""
129 return open(fname
, "rU")
132 # Python 3.x is picky about bytes and strings, so provide methods to
133 # get them right, and make them no-ops in 2.x
134 if sys
.version_info
>= (3, 0):
136 """Convert string `s` to bytes."""
137 return s
.encode('utf8')
140 """Convert bytes `b` to a string."""
141 return b
.decode('utf8')
143 def binary_bytes(byte_values
):
144 """Produce a byte string with the ints from `byte_values`."""
145 return bytes(byte_values
)
147 def byte_to_int(byte_value
):
148 """Turn an element of a bytes object into an int."""
151 def bytes_to_ints(bytes_value
):
152 """Turn a bytes object into a sequence of ints."""
153 # In Py3, iterating bytes gives ints.
158 """Convert string `s` to bytes (no-op in 2.x)."""
162 """Convert bytes `b` to a string (no-op in 2.x)."""
165 def binary_bytes(byte_values
):
166 """Produce a byte string with the ints from `byte_values`."""
167 return "".join([chr(b
) for b
in byte_values
])
169 def byte_to_int(byte_value
):
170 """Turn an element of a bytes object into an int."""
171 return ord(byte_value
)
173 def bytes_to_ints(bytes_value
):
174 """Turn a bytes object into a sequence of ints."""
175 for byte
in bytes_value
:
178 # Md5 is available in different places.