eric7/DebugClients/Python/coverage/backward.py

branch
eric7
changeset 8312
800c432b34c8
parent 7702
f8b97639deb5
child 8527
2bd1325d727e
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2 # For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
3
4 """Add things to old Pythons so I can pretend they are newer."""
5
6 # This file's purpose is to provide modules to be imported from here.
7 # pylint: disable=unused-import
8
9 import os
10 import sys
11
12 from datetime import datetime
13
14 from coverage import env
15
16
17 # Pythons 2 and 3 differ on where to get StringIO.
18 try:
19 from cStringIO import StringIO
20 except ImportError:
21 from io import StringIO
22
23 # In py3, ConfigParser was renamed to the more-standard configparser.
24 # But there's a py3 backport that installs "configparser" in py2, and I don't
25 # want it because it has annoying deprecation warnings. So try the real py2
26 # import first.
27 try:
28 import ConfigParser as configparser
29 except ImportError:
30 import configparser
31
32 # What's a string called?
33 try:
34 string_class = basestring
35 except NameError:
36 string_class = str
37
38 # What's a Unicode string called?
39 try:
40 unicode_class = unicode
41 except NameError:
42 unicode_class = str
43
44 # range or xrange?
45 try:
46 range = xrange # pylint: disable=redefined-builtin
47 except NameError:
48 range = range
49
50 try:
51 from itertools import zip_longest
52 except ImportError:
53 from itertools import izip_longest as zip_longest
54
55 # Where do we get the thread id from?
56 try:
57 from thread import get_ident as get_thread_id
58 except ImportError:
59 from threading import get_ident as get_thread_id
60
61 try:
62 os.PathLike
63 except AttributeError:
64 # This is Python 2 and 3
65 path_types = (bytes, string_class, unicode_class)
66 else:
67 # 3.6+
68 path_types = (bytes, str, os.PathLike)
69
70 # shlex.quote is new, but there's an undocumented implementation in "pipes",
71 # who knew!?
72 try:
73 from shlex import quote as shlex_quote
74 except ImportError:
75 # Useful function, available under a different (undocumented) name
76 # in Python versions earlier than 3.3.
77 from pipes import quote as shlex_quote
78
79 try:
80 import reprlib
81 except ImportError:
82 import repr as reprlib
83
84 # A function to iterate listlessly over a dict's items, and one to get the
85 # items as a list.
86 try:
87 {}.iteritems
88 except AttributeError:
89 # Python 3
90 def iitems(d):
91 """Produce the items from dict `d`."""
92 return d.items()
93
94 def litems(d):
95 """Return a list of items from dict `d`."""
96 return list(d.items())
97 else:
98 # Python 2
99 def iitems(d):
100 """Produce the items from dict `d`."""
101 return d.iteritems()
102
103 def litems(d):
104 """Return a list of items from dict `d`."""
105 return d.items()
106
107 # Getting the `next` function from an iterator is different in 2 and 3.
108 try:
109 iter([]).next
110 except AttributeError:
111 def iternext(seq):
112 """Get the `next` function for iterating over `seq`."""
113 return iter(seq).__next__
114 else:
115 def iternext(seq):
116 """Get the `next` function for iterating over `seq`."""
117 return iter(seq).next
118
119 # Python 3.x is picky about bytes and strings, so provide methods to
120 # get them right, and make them no-ops in 2.x
121 if env.PY3:
122 def to_bytes(s):
123 """Convert string `s` to bytes."""
124 return s.encode('utf8')
125
126 def to_string(b):
127 """Convert bytes `b` to string."""
128 return b.decode('utf8')
129
130 def binary_bytes(byte_values):
131 """Produce a byte string with the ints from `byte_values`."""
132 return bytes(byte_values)
133
134 def byte_to_int(byte):
135 """Turn a byte indexed from a bytes object into an int."""
136 return byte
137
138 def bytes_to_ints(bytes_value):
139 """Turn a bytes object into a sequence of ints."""
140 # In Python 3, iterating bytes gives ints.
141 return bytes_value
142
143 else:
144 def to_bytes(s):
145 """Convert string `s` to bytes (no-op in 2.x)."""
146 return s
147
148 def to_string(b):
149 """Convert bytes `b` to string."""
150 return b
151
152 def binary_bytes(byte_values):
153 """Produce a byte string with the ints from `byte_values`."""
154 return "".join(chr(b) for b in byte_values)
155
156 def byte_to_int(byte):
157 """Turn a byte indexed from a bytes object into an int."""
158 return ord(byte)
159
160 def bytes_to_ints(bytes_value):
161 """Turn a bytes object into a sequence of ints."""
162 for byte in bytes_value:
163 yield ord(byte)
164
165
166 try:
167 # In Python 2.x, the builtins were in __builtin__
168 BUILTINS = sys.modules['__builtin__']
169 except KeyError:
170 # In Python 3.x, they're in builtins
171 BUILTINS = sys.modules['builtins']
172
173
174 # imp was deprecated in Python 3.3
175 try:
176 import importlib
177 import importlib.util
178 imp = None
179 except ImportError:
180 importlib = None
181
182 # We only want to use importlib if it has everything we need.
183 try:
184 importlib_util_find_spec = importlib.util.find_spec
185 except Exception:
186 import imp
187 importlib_util_find_spec = None
188
189 # What is the .pyc magic number for this version of Python?
190 try:
191 PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER
192 except AttributeError:
193 PYC_MAGIC_NUMBER = imp.get_magic()
194
195
196 def code_object(fn):
197 """Get the code object from a function."""
198 try:
199 return fn.func_code
200 except AttributeError:
201 return fn.__code__
202
203
204 try:
205 from types import SimpleNamespace
206 except ImportError:
207 # The code from https://docs.python.org/3/library/types.html#types.SimpleNamespace
208 class SimpleNamespace:
209 """Python implementation of SimpleNamespace, for Python 2."""
210 def __init__(self, **kwargs):
211 self.__dict__.update(kwargs)
212
213 def __repr__(self):
214 keys = sorted(self.__dict__)
215 items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
216 return "{}({})".format(type(self).__name__, ", ".join(items))
217
218 def __eq__(self, other):
219 return self.__dict__ == other.__dict__
220
221
222 def format_local_datetime(dt):
223 """Return a string with local timezone representing the date.
224 If python version is lower than 3.6, the time zone is not included.
225 """
226 try:
227 return dt.astimezone().strftime('%Y-%m-%d %H:%M %z')
228 except (TypeError, ValueError):
229 # Datetime.astimezone in Python 3.5 can not handle naive datetime
230 return dt.strftime('%Y-%m-%d %H:%M')
231
232
233 def invalidate_import_caches():
234 """Invalidate any import caches that may or may not exist."""
235 if importlib and hasattr(importlib, "invalidate_caches"):
236 importlib.invalidate_caches()
237
238
239 def import_local_file(modname, modfile=None):
240 """Import a local file as a module.
241
242 Opens a file in the current directory named `modname`.py, imports it
243 as `modname`, and returns the module object. `modfile` is the file to
244 import if it isn't in the current directory.
245
246 """
247 try:
248 from importlib.machinery import SourceFileLoader
249 except ImportError:
250 SourceFileLoader = None
251
252 if modfile is None:
253 modfile = modname + '.py'
254 if SourceFileLoader:
255 # pylint: disable=no-value-for-parameter, deprecated-method
256 mod = SourceFileLoader(modname, modfile).load_module()
257 else:
258 for suff in imp.get_suffixes(): # pragma: part covered
259 if suff[0] == '.py':
260 break
261
262 with open(modfile, 'r') as f:
263 # pylint: disable=undefined-loop-variable
264 mod = imp.load_module(modname, f, modfile, suff)
265
266 return mod

eric ide

mercurial