1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 |
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 |
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt |
3 |
3 |
4 """Add things to old Pythons so I can pretend they are newer.""" |
4 """Add things to old Pythons so I can pretend they are newer.""" |
5 |
5 |
6 # This file does lots of tricky stuff, so disable a bunch of pylint warnings. |
6 # This file does tricky stuff, so disable a pylint warning. |
7 # pylint: disable=redefined-builtin |
|
8 # pylint: disable=unused-import |
7 # pylint: disable=unused-import |
9 # pylint: disable=no-name-in-module |
|
10 |
8 |
11 import sys |
9 import sys |
12 |
10 |
13 from coverage import env |
11 from coverage import env |
14 |
12 |
17 try: |
15 try: |
18 from cStringIO import StringIO |
16 from cStringIO import StringIO |
19 except ImportError: |
17 except ImportError: |
20 from io import StringIO |
18 from io import StringIO |
21 |
19 |
22 # In py3, ConfigParser was renamed to the more-standard configparser |
20 # In py3, ConfigParser was renamed to the more-standard configparser. |
|
21 # But there's a py3 backport that installs "configparser" in py2, and I don't |
|
22 # want it because it has annoying deprecation warnings. So try the real py2 |
|
23 # import first. |
23 try: |
24 try: |
|
25 import ConfigParser as configparser |
|
26 except ImportError: |
24 import configparser |
27 import configparser |
25 except ImportError: |
|
26 import ConfigParser as configparser |
|
27 |
28 |
28 # What's a string called? |
29 # What's a string called? |
29 try: |
30 try: |
30 string_class = basestring |
31 string_class = basestring |
31 except NameError: |
32 except NameError: |
56 except ImportError: |
57 except ImportError: |
57 # Useful function, available under a different (undocumented) name |
58 # Useful function, available under a different (undocumented) name |
58 # in Python versions earlier than 3.3. |
59 # in Python versions earlier than 3.3. |
59 from pipes import quote as shlex_quote |
60 from pipes import quote as shlex_quote |
60 |
61 |
61 # A function to iterate listlessly over a dict's items. |
62 # A function to iterate listlessly over a dict's items, and one to get the |
|
63 # items as a list. |
62 try: |
64 try: |
63 {}.iteritems |
65 {}.iteritems |
64 except AttributeError: |
66 except AttributeError: |
|
67 # Python 3 |
65 def iitems(d): |
68 def iitems(d): |
66 """Produce the items from dict `d`.""" |
69 """Produce the items from dict `d`.""" |
67 return d.items() |
70 return d.items() |
|
71 |
|
72 def litems(d): |
|
73 """Return a list of items from dict `d`.""" |
|
74 return list(d.items()) |
68 else: |
75 else: |
|
76 # Python 2 |
69 def iitems(d): |
77 def iitems(d): |
70 """Produce the items from dict `d`.""" |
78 """Produce the items from dict `d`.""" |
71 return d.iteritems() |
79 return d.iteritems() |
|
80 |
|
81 def litems(d): |
|
82 """Return a list of items from dict `d`.""" |
|
83 return d.items() |
72 |
84 |
73 # Getting the `next` function from an iterator is different in 2 and 3. |
85 # Getting the `next` function from an iterator is different in 2 and 3. |
74 try: |
86 try: |
75 iter([]).next |
87 iter([]).next |
76 except AttributeError: |
88 except AttributeError: |
141 PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER |
153 PYC_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER |
142 except AttributeError: |
154 except AttributeError: |
143 PYC_MAGIC_NUMBER = imp.get_magic() |
155 PYC_MAGIC_NUMBER = imp.get_magic() |
144 |
156 |
145 |
157 |
|
158 def invalidate_import_caches(): |
|
159 """Invalidate any import caches that may or may not exist.""" |
|
160 if importlib and hasattr(importlib, "invalidate_caches"): |
|
161 importlib.invalidate_caches() |
|
162 |
|
163 |
146 def import_local_file(modname, modfile=None): |
164 def import_local_file(modname, modfile=None): |
147 """Import a local file as a module. |
165 """Import a local file as a module. |
148 |
166 |
149 Opens a file in the current directory named `modname`.py, imports it |
167 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 |
168 as `modname`, and returns the module object. `modfile` is the file to |