blob: f0a34ac4ceb10aaaa1bff53a7394df92c81b66b8 [file] [log] [blame]
Tor Norbye3a2425a2013-11-04 10:16:08 -08001"""Add things to old Pythons so I can pretend they are newer."""
2
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
8
9import os, sys
10
11# Python 2.3 doesn't have `set`
12try:
13 set = set # new in 2.4
14except NameError:
15 from sets import Set as set
16
17# Python 2.3 doesn't have `sorted`.
18try:
19 sorted = sorted
20except NameError:
21 def sorted(iterable):
22 """A 2.3-compatible implementation of `sorted`."""
23 lst = list(iterable)
24 lst.sort()
25 return lst
26
27# Pythons 2 and 3 differ on where to get StringIO
28try:
29 from cStringIO import StringIO
30 BytesIO = StringIO
31except ImportError:
32 from io import StringIO, BytesIO
33
34# What's a string called?
35try:
36 string_class = basestring
37except NameError:
38 string_class = str
39
40# Where do pickles come from?
41try:
42 import cPickle as pickle
43except ImportError:
44 import pickle
45
46# range or xrange?
47try:
48 range = xrange
49except NameError:
50 range = range
51
52# Exec is a statement in Py2, a function in Py3
53if sys.version_info >= (3, 0):
54 def exec_code_object(code, global_map):
55 """A wrapper around exec()."""
56 exec(code, global_map)
57else:
58 # OK, this is pretty gross. In Py2, exec was a statement, but that will
59 # be a syntax error if we try to put it in a Py3 file, even if it is never
60 # executed. So hide it inside an evaluated string literal instead.
61 eval(
62 compile(
63 "def exec_code_object(code, global_map):\n"
64 " exec code in global_map\n",
65 "<exec_function>", "exec"
66 )
67 )
68
69# ConfigParser was renamed to the more-standard configparser
70try:
71 import configparser
72except ImportError:
73 import ConfigParser as configparser
74
75# Python 3.2 provides `tokenize.open`, the best way to open source files.
76try:
77 import tokenize
78 open_source = tokenize.open # pylint: disable=E1101
79except AttributeError:
80 def open_source(fname):
81 """Open a source file the best way."""
82 return open(fname, "rU")
83
84# Python 3.x is picky about bytes and strings, so provide methods to
85# get them right, and make them no-ops in 2.x
86if sys.version_info >= (3, 0):
87 def to_bytes(s):
88 """Convert string `s` to bytes."""
89 return s.encode('utf8')
90
91 def to_string(b):
92 """Convert bytes `b` to a string."""
93 return b.decode('utf8')
94
95else:
96 def to_bytes(s):
97 """Convert string `s` to bytes (no-op in 2.x)."""
98 return s
99
100 def to_string(b):
101 """Convert bytes `b` to a string (no-op in 2.x)."""
102 return b
103
104# Md5 is available in different places.
105try:
106 import hashlib
107 md5 = hashlib.md5
108except ImportError:
109 import md5
110 md5 = md5.new