summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coverage/backward.py64
-rw-r--r--coverage/execfile.py90
-rw-r--r--coverage/html.py2
-rw-r--r--coverage/inorout.py40
-rw-r--r--coverage/misc.py25
-rw-r--r--perf/perf_measure.py2
-rw-r--r--tests/coveragetest.py2
-rw-r--r--tests/mixins.py6
-rw-r--r--tests/test_api.py3
-rw-r--r--tests/test_concurrency.py2
-rw-r--r--tests/test_mixins.py2
-rw-r--r--tests/test_oddball.py2
-rw-r--r--tests/test_plugins.py3
-rw-r--r--tests/test_xml.py2
14 files changed, 68 insertions, 177 deletions
diff --git a/coverage/backward.py b/coverage/backward.py
deleted file mode 100644
index 1169ff46..00000000
--- a/coverage/backward.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
-# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
-
-"""Add things to old Pythons so I can pretend they are newer."""
-
-import sys
-
-# imp was deprecated in Python 3.3
-try:
- import importlib
- import importlib.util
- imp = None
-except ImportError:
- importlib = None
-
-# We only want to use importlib if it has everything we need.
-try:
- importlib_util_find_spec = importlib.util.find_spec
-except Exception:
- import imp
- importlib_util_find_spec = None
-
-
-def format_local_datetime(dt):
- """Return a string with local timezone representing the date.
- If python version is lower than 3.6, the time zone is not included.
- """
- try:
- return dt.astimezone().strftime('%Y-%m-%d %H:%M %z')
- except (TypeError, ValueError):
- # Datetime.astimezone in Python 3.5 can not handle naive datetime
- return dt.strftime('%Y-%m-%d %H:%M')
-
-
-def import_local_file(modname, modfile=None):
- """Import a local file as a module.
-
- Opens a file in the current directory named `modname`.py, imports it
- as `modname`, and returns the module object. `modfile` is the file to
- import if it isn't in the current directory.
-
- """
- try:
- import importlib.util as importlib_util
- except ImportError:
- importlib_util = None
-
- if modfile is None:
- modfile = modname + '.py'
- if importlib_util:
- spec = importlib_util.spec_from_file_location(modname, modfile)
- mod = importlib_util.module_from_spec(spec)
- sys.modules[modname] = mod
- spec.loader.exec_module(mod)
- else:
- for suff in imp.get_suffixes(): # pragma: part covered
- if suff[0] == '.py':
- break
-
- with open(modfile, 'r') as f:
- # pylint: disable=undefined-loop-variable
- mod = imp.load_module(modname, f, modfile, suff)
-
- return mod
diff --git a/coverage/execfile.py b/coverage/execfile.py
index 338fb477..e96a5265 100644
--- a/coverage/execfile.py
+++ b/coverage/execfile.py
@@ -13,7 +13,6 @@ import sys
import types
from coverage import env
-from coverage.backward import imp, importlib_util_find_spec
from coverage.files import canonical_filename, python_reported_file
from coverage.misc import CoverageException, ExceptionDuringRun, NoCode, NoSource, isolate_module
from coverage.phystokens import compile_unicode
@@ -33,76 +32,33 @@ class DummyLoader(object):
self.fullname = fullname
-if importlib_util_find_spec:
- def find_module(modulename):
- """Find the module named `modulename`.
+def find_module(modulename):
+ """Find the module named `modulename`.
- Returns the file path of the module, the name of the enclosing
- package, and the spec.
- """
- try:
- spec = importlib_util_find_spec(modulename)
- except ImportError as err:
- raise NoSource(str(err))
+ Returns the file path of the module, the name of the enclosing
+ package, and the spec.
+ """
+ try:
+ spec = importlib.util.find_spec(modulename)
+ except ImportError as err:
+ raise NoSource(str(err))
+ if not spec:
+ raise NoSource("No module named %r" % (modulename,))
+ pathname = spec.origin
+ packagename = spec.name
+ if spec.submodule_search_locations:
+ mod_main = modulename + ".__main__"
+ spec = importlib.util.find_spec(mod_main)
if not spec:
- raise NoSource("No module named %r" % (modulename,))
+ raise NoSource(
+ "No module named %s; "
+ "%r is a package and cannot be directly executed"
+ % (mod_main, modulename)
+ )
pathname = spec.origin
packagename = spec.name
- if spec.submodule_search_locations:
- mod_main = modulename + ".__main__"
- spec = importlib_util_find_spec(mod_main)
- if not spec:
- raise NoSource(
- "No module named %s; "
- "%r is a package and cannot be directly executed"
- % (mod_main, modulename)
- )
- pathname = spec.origin
- packagename = spec.name
- packagename = packagename.rpartition(".")[0]
- return pathname, packagename, spec
-else:
- def find_module(modulename):
- """Find the module named `modulename`.
-
- Returns the file path of the module, the name of the enclosing
- package, and None (where a spec would have been).
- """
- openfile = None
- glo, loc = globals(), locals()
- try:
- # Search for the module - inside its parent package, if any - using
- # standard import mechanics.
- if '.' in modulename:
- packagename, name = modulename.rsplit('.', 1)
- package = __import__(packagename, glo, loc, ['__path__'])
- searchpath = package.__path__
- else:
- packagename, name = None, modulename
- searchpath = None # "top-level search" in imp.find_module()
- openfile, pathname, _ = imp.find_module(name, searchpath)
-
- # Complain if this is a magic non-file module.
- if openfile is None and pathname is None:
- raise NoSource(
- "module does not live in a file: %r" % modulename
- )
-
- # If `modulename` is actually a package, not a mere module, then we
- # pretend to be Python 2.7 and try running its __main__.py script.
- if openfile is None:
- packagename = modulename
- name = '__main__'
- package = __import__(packagename, glo, loc, ['__path__'])
- searchpath = package.__path__
- openfile, pathname, _ = imp.find_module(name, searchpath)
- except ImportError as err:
- raise NoSource(str(err))
- finally:
- if openfile:
- openfile.close()
-
- return pathname, packagename, None
+ packagename = packagename.rpartition(".")[0]
+ return pathname, packagename, spec
class PyRunner(object):
diff --git a/coverage/html.py b/coverage/html.py
index aea1aa25..f4670caf 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -11,10 +11,10 @@ import shutil
import types
import coverage
-from coverage.backward import format_local_datetime
from coverage.data import add_data_to_hash
from coverage.files import flat_rootname
from coverage.misc import CoverageException, ensure_dir, file_be_gone, Hasher, isolate_module
+from coverage.misc import format_local_datetime
from coverage.report import get_analysis_to_report
from coverage.results import Numbers
from coverage.templite import Templite
diff --git a/coverage/inorout.py b/coverage/inorout.py
index 554d34c4..f4d99772 100644
--- a/coverage/inorout.py
+++ b/coverage/inorout.py
@@ -3,6 +3,7 @@
"""Determining whether files are being measured/reported or not."""
+import importlib.util
import inspect
import itertools
import os
@@ -13,7 +14,6 @@ import sysconfig
import traceback
from coverage import env
-from coverage.backward import importlib_util_find_spec
from coverage.disposition import FileDisposition, disposition_init
from coverage.files import TreeMatcher, FnmatchMatcher, ModuleMatcher
from coverage.files import prep_patterns, find_python_files, canonical_filename
@@ -109,37 +109,15 @@ def module_has_file(mod):
def file_for_module(modulename):
"""Find the file for `modulename`, or return None."""
- if importlib_util_find_spec:
- filename = None
- try:
- spec = importlib_util_find_spec(modulename)
- except ImportError:
- pass
- else:
- if spec is not None:
- filename = spec.origin
- return filename
+ filename = None
+ try:
+ spec = importlib.util.find_spec(modulename)
+ except ImportError:
+ pass
else:
- import imp
- openfile = None
- glo, loc = globals(), locals()
- try:
- # Search for the module - inside its parent package, if any - using
- # standard import mechanics.
- if '.' in modulename:
- packagename, name = modulename.rsplit('.', 1)
- package = __import__(packagename, glo, loc, ['__path__'])
- searchpath = package.__path__
- else:
- packagename, name = None, modulename
- searchpath = None # "top-level search" in imp.find_module()
- openfile, pathname, _ = imp.find_module(name, searchpath)
- return pathname
- except ImportError:
- return None
- finally:
- if openfile:
- openfile.close()
+ if spec is not None:
+ filename = spec.origin
+ return filename
def add_stdlib_paths(paths):
diff --git a/coverage/misc.py b/coverage/misc.py
index 7182d385..6f104ac0 100644
--- a/coverage/misc.py
+++ b/coverage/misc.py
@@ -5,6 +5,7 @@
import errno
import hashlib
+import importlib.util
import inspect
import locale
import os
@@ -315,6 +316,30 @@ def substitute_variables(text, variables):
return text
+def format_local_datetime(dt):
+ """Return a string with local timezone representing the date.
+ """
+ return dt.astimezone().strftime('%Y-%m-%d %H:%M %z')
+
+
+def import_local_file(modname, modfile=None):
+ """Import a local file as a module.
+
+ Opens a file in the current directory named `modname`.py, imports it
+ as `modname`, and returns the module object. `modfile` is the file to
+ import if it isn't in the current directory.
+
+ """
+ if modfile is None:
+ modfile = modname + '.py'
+ spec = importlib.util.spec_from_file_location(modname, modfile)
+ mod = importlib.util.module_from_spec(spec)
+ sys.modules[modname] = mod
+ spec.loader.exec_module(mod)
+
+ return mod
+
+
class BaseCoverageException(Exception):
"""The base of all Coverage exceptions."""
pass
diff --git a/perf/perf_measure.py b/perf/perf_measure.py
index b903567c..652f0fa8 100644
--- a/perf/perf_measure.py
+++ b/perf/perf_measure.py
@@ -14,7 +14,7 @@ import time
from unittest_mixins.mixins import make_file
import coverage
-from coverage.backward import import_local_file
+from coverage.misc import import_local_file
from tests.helpers import SuperModuleCleaner
diff --git a/tests/coveragetest.py b/tests/coveragetest.py
index 2a55cf8b..1163e349 100644
--- a/tests/coveragetest.py
+++ b/tests/coveragetest.py
@@ -19,8 +19,8 @@ import pytest
import coverage
from coverage import env
-from coverage.backward import import_local_file
from coverage.cmdline import CoverageScript
+from coverage.misc import import_local_file
from tests.helpers import arcs_to_arcz_repr, arcz_to_arcs, assert_count_equal
from tests.helpers import nice_file, run_command
diff --git a/tests/mixins.py b/tests/mixins.py
index ff47a4da..44b16f6c 100644
--- a/tests/mixins.py
+++ b/tests/mixins.py
@@ -7,6 +7,7 @@ Test class mixins
Some of these are transitional while working toward pure-pytest style.
"""
+import importlib
import os
import os.path
import shutil
@@ -14,8 +15,6 @@ import sys
import pytest
-from coverage.backward import importlib
-
from tests.helpers import change_dir, make_file, remove_files
@@ -130,8 +129,7 @@ class SysPathModulesMixin:
if os.path.exists("__pycache__"):
shutil.rmtree("__pycache__")
- if importlib and hasattr(importlib, "invalidate_caches"):
- importlib.invalidate_caches()
+ importlib.invalidate_caches()
class StdStreamCapturingMixin:
diff --git a/tests/test_api.py b/tests/test_api.py
index b17f9ee0..57154d64 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -17,10 +17,9 @@ import pytest
import coverage
from coverage import env
-from coverage.backward import import_local_file
from coverage.data import line_counts
from coverage.files import abs_file, relative_filename
-from coverage.misc import CoverageException
+from coverage.misc import CoverageException, import_local_file
from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin
from tests.helpers import assert_count_equal, change_dir, nice_file
diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py
index fa482f91..9cc1f3b6 100644
--- a/tests/test_concurrency.py
+++ b/tests/test_concurrency.py
@@ -16,9 +16,9 @@ import pytest
import coverage
from coverage import env
-from coverage.backward import import_local_file
from coverage.data import line_counts
from coverage.files import abs_file
+from coverage.misc import import_local_file
from tests.coveragetest import CoverageTest
from tests.helpers import remove_files
diff --git a/tests/test_mixins.py b/tests/test_mixins.py
index 028a19fd..aab1242a 100644
--- a/tests/test_mixins.py
+++ b/tests/test_mixins.py
@@ -6,7 +6,7 @@
import pytest
-from coverage.backward import import_local_file
+from coverage.misc import import_local_file
from tests.mixins import TempDirMixin, SysPathModulesMixin
diff --git a/tests/test_oddball.py b/tests/test_oddball.py
index a63719ea..2e438396 100644
--- a/tests/test_oddball.py
+++ b/tests/test_oddball.py
@@ -11,8 +11,8 @@ import pytest
import coverage
from coverage import env
-from coverage.backward import import_local_file
from coverage.files import abs_file
+from coverage.misc import import_local_file
from tests.coveragetest import CoverageTest
from tests import osinfo
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index 5a8d92ee..fec92749 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -12,10 +12,9 @@ import pytest
import coverage
from coverage import env
-from coverage.backward import import_local_file
from coverage.data import line_counts
from coverage.control import Plugins
-from coverage.misc import CoverageException
+from coverage.misc import CoverageException, import_local_file
import coverage.plugin
diff --git a/tests/test_xml.py b/tests/test_xml.py
index 94669cdc..334abb4c 100644
--- a/tests/test_xml.py
+++ b/tests/test_xml.py
@@ -12,8 +12,8 @@ from xml.etree import ElementTree
import pytest
import coverage
-from coverage.backward import import_local_file
from coverage.files import abs_file
+from coverage.misc import import_local_file
from tests.coveragetest import CoverageTest
from tests.goldtest import compare, gold_path