eric7/DebugClients/Python/coverage/backward.py

branch
eric7
changeset 8775
0802ae193343
parent 8774
d728227e8ebb
child 8776
07b8c13b0607
equal deleted inserted replaced
8774:d728227e8ebb 8775:0802ae193343
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: # pragma: not covered
82 # We need this on Python 2, but in testing environments, a backport is
83 # installed, so this import isn't used.
84 import repr as reprlib
85
86 # A function to iterate listlessly over a dict's items, and one to get the
87 # items as a list.
88 try:
89 {}.iteritems
90 except AttributeError:
91 # Python 3
92 def iitems(d):
93 """Produce the items from dict `d`."""
94 return d.items()
95
96 def litems(d):
97 """Return a list of items from dict `d`."""
98 return list(d.items())
99 else:
100 # Python 2
101 def iitems(d):
102 """Produce the items from dict `d`."""
103 return d.iteritems()
104
105 def litems(d):
106 """Return a list of items from dict `d`."""
107 return d.items()
108
109 # Getting the `next` function from an iterator is different in 2 and 3.
110 try:
111 iter([]).next
112 except AttributeError:
113 def iternext(seq):
114 """Get the `next` function for iterating over `seq`."""
115 return iter(seq).__next__
116 else:
117 def iternext(seq):
118 """Get the `next` function for iterating over `seq`."""
119 return iter(seq).next
120
121 # Python 3.x is picky about bytes and strings, so provide methods to
122 # get them right, and make them no-ops in 2.x
123 if env.PY3:
124 def to_bytes(s):
125 """Convert string `s` to bytes."""
126 return s.encode('utf8')
127
128 def to_string(b):
129 """Convert bytes `b` to string."""
130 return b.decode('utf8')
131
132 def binary_bytes(byte_values):
133 """Produce a byte string with the ints from `byte_values`."""
134 return bytes(byte_values)
135
136 def byte_to_int(byte):
137 """Turn a byte indexed from a bytes object into an int."""
138 return byte
139
140 def bytes_to_ints(bytes_value):
141 """Turn a bytes object into a sequence of ints."""
142 # In Python 3, iterating bytes gives ints.
143 return bytes_value
144
145 else:
146 def to_bytes(s):
147 """Convert string `s` to bytes (no-op in 2.x)."""
148 return s
149
150 def to_string(b):
151 """Convert bytes `b` to string."""
152 return b
153
154 def binary_bytes(byte_values):
155 """Produce a byte string with the ints from `byte_values`."""
156 return "".join(chr(b) for b in byte_values)
157
158 def byte_to_int(byte):
159 """Turn a byte indexed from a bytes object into an int."""
160 return ord(byte)
161
162 def bytes_to_ints(bytes_value):
163 """Turn a bytes object into a sequence of ints."""
164 for byte in bytes_value:
165 yield ord(byte)
166
167
168 try:
169 # In Python 2.x, the builtins were in __builtin__
170 BUILTINS = sys.modules['__builtin__']
171 except KeyError:
172 # In Python 3.x, they're in builtins
173 BUILTINS = sys.modules['builtins']
174
175
176 # imp was deprecated in Python 3.3
177 try:
178 import importlib
179 import importlib.util
180 imp = None
181 except ImportError:
182 importlib = None
183
184 # We only want to use importlib if it has everything we need.
185 try:
186 importlib_util_find_spec = importlib.util.find_spec
187 except Exception:
188 import imp
189 importlib_util_find_spec = None
190
191 # What is the .pyc magic number for this version of Python?
192 try:
193 PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER
194 except AttributeError:
195 PYC_MAGIC_NUMBER = imp.get_magic()
196
197
198 def code_object(fn):
199 """Get the code object from a function."""
200 try:
201 return fn.func_code
202 except AttributeError:
203 return fn.__code__
204
205
206 try:
207 from types import SimpleNamespace
208 except ImportError:
209 # The code from https://docs.python.org/3/library/types.html#types.SimpleNamespace
210 class SimpleNamespace:
211 """Python implementation of SimpleNamespace, for Python 2."""
212 def __init__(self, **kwargs):
213 self.__dict__.update(kwargs)
214
215 def __repr__(self):
216 keys = sorted(self.__dict__)
217 items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
218 return "{}({})".format(type(self).__name__, ", ".join(items))
219
220
221 def format_local_datetime(dt):
222 """Return a string with local timezone representing the date.
223 If python version is lower than 3.6, the time zone is not included.
224 """
225 try:
226 return dt.astimezone().strftime('%Y-%m-%d %H:%M %z')
227 except (TypeError, ValueError):
228 # Datetime.astimezone in Python 3.5 can not handle naive datetime
229 return dt.strftime('%Y-%m-%d %H:%M')
230
231
232 def invalidate_import_caches():
233 """Invalidate any import caches that may or may not exist."""
234 if importlib and hasattr(importlib, "invalidate_caches"):
235 importlib.invalidate_caches()
236
237
238 def import_local_file(modname, modfile=None):
239 """Import a local file as a module.
240
241 Opens a file in the current directory named `modname`.py, imports it
242 as `modname`, and returns the module object. `modfile` is the file to
243 import if it isn't in the current directory.
244
245 """
246 try:
247 import importlib.util as importlib_util
248 except ImportError:
249 importlib_util = None
250
251 if modfile is None:
252 modfile = modname + '.py'
253 if importlib_util:
254 spec = importlib_util.spec_from_file_location(modname, modfile)
255 mod = importlib_util.module_from_spec(spec)
256 sys.modules[modname] = mod
257 spec.loader.exec_module(mod)
258 else:
259 for suff in imp.get_suffixes(): # pragma: part covered
260 if suff[0] == '.py':
261 break
262
263 with open(modfile, 'r') as f:
264 # pylint: disable=undefined-loop-variable
265 mod = imp.load_module(modname, f, modfile, suff)
266
267 return mod

eric ide

mercurial