1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 |
|
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt |
|
3 |
|
4 """Add things to old Pythons so I can pretend they are newer.""" |
|
5 |
|
6 # This file does lots of tricky stuff, so disable a bunch of pylint warnings. |
|
7 # pylint: disable=redefined-builtin |
|
8 # pylint: disable=unused-import |
|
9 # pylint: disable=no-name-in-module |
|
10 |
|
11 import sys |
|
12 |
|
13 from coverage import env |
|
14 |
|
15 |
|
16 # Pythons 2 and 3 differ on where to get StringIO. |
|
17 try: |
|
18 from cStringIO import StringIO |
|
19 except ImportError: |
|
20 from io import StringIO |
|
21 |
|
22 # In py3, ConfigParser was renamed to the more-standard configparser |
|
23 try: |
|
24 import configparser |
|
25 except ImportError: |
|
26 import ConfigParser as configparser |
|
27 |
|
28 # What's a string called? |
|
29 try: |
|
30 string_class = basestring |
|
31 except NameError: |
|
32 string_class = str |
|
33 |
|
34 # What's a Unicode string called? |
|
35 try: |
|
36 unicode_class = unicode |
|
37 except NameError: |
|
38 unicode_class = str |
|
39 |
|
40 # Where do pickles come from? |
|
41 try: |
|
42 import cPickle as pickle |
|
43 except ImportError: |
|
44 import pickle |
|
45 |
|
46 # range or xrange? |
|
47 try: |
|
48 range = xrange |
|
49 except NameError: |
|
50 range = range |
|
51 |
|
52 # shlex.quote is new, but there's an undocumented implementation in "pipes", |
|
53 # who knew!? |
|
54 try: |
|
55 from shlex import quote as shlex_quote |
|
56 except ImportError: |
|
57 # Useful function, available under a different (undocumented) name |
|
58 # in Python versions earlier than 3.3. |
|
59 from pipes import quote as shlex_quote |
|
60 |
|
61 # A function to iterate listlessly over a dict's items. |
|
62 try: |
|
63 {}.iteritems |
|
64 except AttributeError: |
|
65 def iitems(d): |
|
66 """Produce the items from dict `d`.""" |
|
67 return d.items() |
|
68 else: |
|
69 def iitems(d): |
|
70 """Produce the items from dict `d`.""" |
|
71 return d.iteritems() |
|
72 |
|
73 # Getting the `next` function from an iterator is different in 2 and 3. |
|
74 try: |
|
75 iter([]).next |
|
76 except AttributeError: |
|
77 def iternext(seq): |
|
78 """Get the `next` function for iterating over `seq`.""" |
|
79 return iter(seq).__next__ |
|
80 else: |
|
81 def iternext(seq): |
|
82 """Get the `next` function for iterating over `seq`.""" |
|
83 return iter(seq).next |
|
84 |
|
85 # Python 3.x is picky about bytes and strings, so provide methods to |
|
86 # get them right, and make them no-ops in 2.x |
|
87 if env.PY3: |
|
88 def to_bytes(s): |
|
89 """Convert string `s` to bytes.""" |
|
90 return s.encode('utf8') |
|
91 |
|
92 def binary_bytes(byte_values): |
|
93 """Produce a byte string with the ints from `byte_values`.""" |
|
94 return bytes(byte_values) |
|
95 |
|
96 def bytes_to_ints(bytes_value): |
|
97 """Turn a bytes object into a sequence of ints.""" |
|
98 # In Python 3, iterating bytes gives ints. |
|
99 return bytes_value |
|
100 |
|
101 else: |
|
102 def to_bytes(s): |
|
103 """Convert string `s` to bytes (no-op in 2.x).""" |
|
104 return s |
|
105 |
|
106 def binary_bytes(byte_values): |
|
107 """Produce a byte string with the ints from `byte_values`.""" |
|
108 return "".join(chr(b) for b in byte_values) |
|
109 |
|
110 def bytes_to_ints(bytes_value): |
|
111 """Turn a bytes object into a sequence of ints.""" |
|
112 for byte in bytes_value: |
|
113 yield ord(byte) |
|
114 |
|
115 |
|
116 try: |
|
117 # In Python 2.x, the builtins were in __builtin__ |
|
118 BUILTINS = sys.modules['__builtin__'] |
|
119 except KeyError: |
|
120 # In Python 3.x, they're in builtins |
|
121 BUILTINS = sys.modules['builtins'] |
|
122 |
|
123 |
|
124 # imp was deprecated in Python 3.3 |
|
125 try: |
|
126 import importlib |
|
127 import importlib.util |
|
128 imp = None |
|
129 except ImportError: |
|
130 importlib = None |
|
131 |
|
132 # We only want to use importlib if it has everything we need. |
|
133 try: |
|
134 importlib_util_find_spec = importlib.util.find_spec |
|
135 except Exception: |
|
136 import imp |
|
137 importlib_util_find_spec = None |
|
138 |
|
139 # What is the .pyc magic number for this version of Python? |
|
140 try: |
|
141 PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER |
|
142 except AttributeError: |
|
143 PYC_MAGIC_NUMBER = imp.get_magic() |
|
144 |
|
145 |
|
146 def import_local_file(modname, modfile=None): |
|
147 """Import a local file as a module. |
|
148 |
|
149 Opens a file in the current directory named `modname`.py, imports it |
|
150 as `modname`, and returns the module object. `modfile` is the file to |
|
151 import if it isn't in the current directory. |
|
152 |
|
153 """ |
|
154 try: |
|
155 from importlib.machinery import SourceFileLoader |
|
156 except ImportError: |
|
157 SourceFileLoader = None |
|
158 |
|
159 if modfile is None: |
|
160 modfile = modname + '.py' |
|
161 if SourceFileLoader: |
|
162 mod = SourceFileLoader(modname, modfile).load_module() |
|
163 else: |
|
164 for suff in imp.get_suffixes(): # pragma: part covered |
|
165 if suff[0] == '.py': |
|
166 break |
|
167 |
|
168 with open(modfile, 'r') as f: |
|
169 # pylint: disable=undefined-loop-variable |
|
170 mod = imp.load_module(modname, f, modfile, suff) |
|
171 |
|
172 return mod |
|
173 |
|
174 # |
|
175 # eflag: FileType = Python2 |
|