summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2021-01-18 18:08:56 -0500
committerNed Batchelder <ned@nedbatchelder.com>2021-01-18 18:23:27 -0500
commita09b1714c26cde1542044f44295600679d4368fc (patch)
treeb0330905216c5a80f6c5c675494a95a00b3997a2
parent94239ad30e56f8f4bf01dcaf8700cdecca86e7f1 (diff)
downloadpython-coveragepy-git-a09b1714c26cde1542044f44295600679d4368fc.tar.gz
Simplify the testing of the toml extra, fixing #1084
-rw-r--r--CHANGES.rst4
-rw-r--r--coverage/optional.py76
-rw-r--r--coverage/tomlconfig.py8
-rw-r--r--tests/helpers.py19
-rw-r--r--tests/test_config.py10
-rw-r--r--tests/test_testing.py19
6 files changed, 44 insertions, 92 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 12468ea5..b517c0ce 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -38,12 +38,16 @@ Unreleased
- Combining files on Windows across drives how works properly, fixing `issue
577`_. Thanks, `Valentine Lab <pr1080_>`_.
+- Fix an obscure warning from deep in the _decimal module, as reported in
+ `issue 1084`_.
+
- Update to support Python 3.10 alphas in progress, including `PEP 626: Precise
line numbers for debugging and other tools <pep626_>`_.
.. _issue 577: https://github.com/nedbat/coveragepy/issues/577
.. _issue 732: https://github.com/nedbat/coveragepy/issues/732
.. _issue 922: https://github.com/nedbat/coveragepy/issues/922
+.. _issue 1084: https://github.com/nedbat/coveragepy/issues/1084
.. _issue 1086: https://github.com/nedbat/coveragepy/issues/1086
.. _issue 1090: https://github.com/nedbat/coveragepy/issues/1090
.. _pr1080: https://github.com/nedbat/coveragepy/pull/1080
diff --git a/coverage/optional.py b/coverage/optional.py
deleted file mode 100644
index 507a1ada..00000000
--- a/coverage/optional.py
+++ /dev/null
@@ -1,76 +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
-
-"""
-Imports that we need at runtime, but might not be present.
-
-When importing one of these modules, always do it in the function where you
-need the module. Some tests will need to remove the module. If you import
-it at the top level of your module, then the test won't be able to simulate
-the module being unimportable.
-
-The import will always succeed, but the value will be None if the module is
-unavailable.
-
-Bad::
-
- # MyModule.py
- import unsure
-
- def use_unsure():
- unsure.something()
-
-Also bad::
-
- # MyModule.py
- from coverage.optional import unsure
-
- def use_unsure():
- unsure.something()
-
-Good::
-
- # MyModule.py
-
- def use_unsure():
- from coverage.optional import unsure
- if unsure is None:
- raise Exception("Module unsure isn't available!")
-
- unsure.something()
-
-"""
-
-import contextlib
-
-# This file's purpose is to provide modules to be imported from here.
-# pylint: disable=unused-import
-
-# TOML support is an install-time extra option.
-try:
- import toml
-except ImportError: # pragma: not covered
- toml = None
-
-
-@contextlib.contextmanager
-def without(modname):
- """Hide a module for testing.
-
- Use this in a test function to make an optional module unavailable during
- the test::
-
- with coverage.optional.without('toml'):
- use_toml_somehow()
-
- Arguments:
- modname (str): the name of a module importable from
- `coverage.optional`.
-
- """
- real_module = globals()[modname]
- try:
- globals()[modname] = None
- yield
- finally:
- globals()[modname] = real_module
diff --git a/coverage/tomlconfig.py b/coverage/tomlconfig.py
index 25542f99..3ad58157 100644
--- a/coverage/tomlconfig.py
+++ b/coverage/tomlconfig.py
@@ -11,6 +11,12 @@ from coverage import env
from coverage.backward import configparser, path_types
from coverage.misc import CoverageException, substitute_variables
+# TOML support is an install-time extra option.
+try:
+ import toml
+except ImportError: # pragma: not covered
+ toml = None
+
class TomlDecodeError(Exception):
"""An exception class that exists even when toml isn't installed."""
@@ -29,8 +35,6 @@ class TomlConfigParser:
self.data = None
def read(self, filenames):
- from coverage.optional import toml
-
# RawConfigParser takes a filename or list of filenames, but we only
# ever call this with a single filename.
assert isinstance(filenames, path_types)
diff --git a/tests/helpers.py b/tests/helpers.py
index 9c6a0ad8..0621d7a9 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -10,6 +10,7 @@ import shutil
import subprocess
import sys
+import mock
from unittest_mixins import ModuleCleaner
from coverage import env
@@ -203,3 +204,21 @@ def arcs_to_arcz_repr(arcs):
line += _arcs_to_arcz_repr_one(b)
repr_list.append(line)
return "\n".join(repr_list) + "\n"
+
+
+def without_module(using_module, missing_module_name):
+ """
+ Hide a module for testing.
+
+ Use this in a test function to make an optional module unavailable during
+ the test::
+
+ with without_module(product.something, 'toml'):
+ use_toml_somehow()
+
+ Arguments:
+ using_module: a module in which to hide `missing_module_name`.
+ missing_module_name (str): the name of the module to hide.
+
+ """
+ return mock.patch.object(using_module, missing_module_name, None)
diff --git a/tests/test_config.py b/tests/test_config.py
index dd86303f..4225540c 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -10,9 +10,9 @@ import mock
import coverage
from coverage.misc import CoverageException
-import coverage.optional
from tests.coveragetest import CoverageTest, UsingModulesMixin
+from tests.helpers import without_module
class ConfigTest(CoverageTest):
@@ -712,7 +712,7 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest):
def test_no_toml_installed_no_toml(self):
# Can't read a toml file that doesn't exist.
- with coverage.optional.without('toml'):
+ with without_module(coverage.tomlconfig, 'toml'):
msg = "Couldn't read 'cov.toml' as a config file"
with self.assertRaisesRegex(CoverageException, msg):
coverage.Coverage(config_file="cov.toml")
@@ -720,7 +720,7 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest):
def test_no_toml_installed_explicit_toml(self):
# Can't specify a toml config file if toml isn't installed.
self.make_file("cov.toml", "# A toml file!")
- with coverage.optional.without('toml'):
+ with without_module(coverage.tomlconfig, 'toml'):
msg = "Can't read 'cov.toml' without TOML support"
with self.assertRaisesRegex(CoverageException, msg):
coverage.Coverage(config_file="cov.toml")
@@ -732,7 +732,7 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest):
[tool.coverage.run]
xyzzy = 17
""")
- with coverage.optional.without('toml'):
+ with without_module(coverage.tomlconfig, 'toml'):
msg = "Can't read 'pyproject.toml' without TOML support"
with self.assertRaisesRegex(CoverageException, msg):
coverage.Coverage()
@@ -744,7 +744,7 @@ class ConfigFileTest(UsingModulesMixin, CoverageTest):
[tool.something]
xyzzy = 17
""")
- with coverage.optional.without('toml'):
+ with without_module(coverage.tomlconfig, 'toml'):
cov = coverage.Coverage()
# We get default settings:
self.assertFalse(cov.config.timid)
diff --git a/tests/test_testing.py b/tests/test_testing.py
index c5d46430..34ea3263 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -12,14 +12,16 @@ import sys
import pytest
import coverage
+from coverage import tomlconfig
from coverage.backunittest import TestCase, unittest
from coverage.files import actual_path
from coverage.misc import StopEverything
-import coverage.optional
from tests.coveragetest import CoverageTest, convert_skip_exceptions
-from tests.helpers import arcs_to_arcz_repr, arcz_to_arcs
-from tests.helpers import CheckUniqueFilenames, re_lines, re_line
+from tests.helpers import (
+ arcs_to_arcz_repr, arcz_to_arcs,
+ CheckUniqueFilenames, re_lines, re_line, without_module,
+)
def test_xdist_sys_path_nuttiness_is_fixed():
@@ -323,12 +325,11 @@ def _same_python_executable(e1, e2):
return False # pragma: only failure
-def test_optional_without():
- # pylint: disable=reimported
- from coverage.optional import toml as toml1
- with coverage.optional.without('toml'):
- from coverage.optional import toml as toml2
- from coverage.optional import toml as toml3
+def test_without_module():
+ toml1 = tomlconfig.toml
+ with without_module(tomlconfig, 'toml'):
+ toml2 = tomlconfig.toml
+ toml3 = tomlconfig.toml
assert toml1 is toml3 is not None
assert toml2 is None