summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2015-05-17 18:36:30 -0400
committerNed Batchelder <ned@nedbatchelder.com>2015-05-17 18:36:30 -0400
commitca1a24ac46844ef83a7c1491659a1f36c8df37b1 (patch)
tree8ec4f7348cec7e561b983cb30ee01f8990cc557a
parentccc1b37086e04d65fbac880248fca3f57b42b901 (diff)
downloadpython-coveragepy-git-ca1a24ac46844ef83a7c1491659a1f36c8df37b1.tar.gz
Use PyContracts so we can declare/enforce parameter and return types.
This commit doesn't add any uses of PyContracts, but gets the machinery in place.
-rw-r--r--coverage/control.py15
-rw-r--r--coverage/env.py5
-rw-r--r--coverage/misc.py27
-rw-r--r--igor.py1
-rw-r--r--requirements.txt1
-rw-r--r--tests/test_debug.py2
-rw-r--r--tox.ini1
7 files changed, 45 insertions, 7 deletions
diff --git a/coverage/control.py b/coverage/control.py
index 2c8d384e..defba56c 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -169,7 +169,7 @@ class Coverage(object):
self.source_pkgs = self.file_locator = None
self.data = self.collector = None
self.plugins = self.file_tracing_plugins = None
- self.pylib_dirs = self.cover_dir = None
+ self.pylib_dirs = self.cover_dirs = None
self.data_suffix = self.run_suffix = None
self._exclude_re = None
self.debug = None
@@ -301,7 +301,12 @@ class Coverage(object):
# To avoid tracing the coverage code itself, we skip anything located
# where we are.
- self.cover_dir = self._canonical_dir(__file__)
+ self.cover_dirs = [self._canonical_dir(__file__)]
+ if env.TESTING:
+ # When testing, we use PyContracts, which should be considered
+ # part of coverage.
+ import contracts
+ self.cover_dirs.append(self._canonical_dir(contracts))
# Set the reporting precision.
Numbers.set_precision(self.config.precision)
@@ -315,8 +320,8 @@ class Coverage(object):
self.source_match = TreeMatcher(self.source)
self.source_pkgs_match = ModuleMatcher(self.source_pkgs)
else:
- if self.cover_dir:
- self.cover_match = TreeMatcher([self.cover_dir])
+ if self.cover_dirs:
+ self.cover_match = TreeMatcher(self.cover_dirs)
if self.pylib_dirs:
self.pylib_match = TreeMatcher(self.pylib_dirs)
if self.include:
@@ -1033,7 +1038,7 @@ class Coverage(object):
info = [
('version', covmod.__version__),
('coverage', covmod.__file__),
- ('cover_dir', self.cover_dir),
+ ('cover_dirs', self.cover_dirs),
('pylib_dirs', self.pylib_dirs),
('tracer', self.collector.tracer_name()),
('file_tracing_plugins', ft_plugins),
diff --git a/coverage/env.py b/coverage/env.py
index 85ffa5ff..af78844e 100644
--- a/coverage/env.py
+++ b/coverage/env.py
@@ -15,7 +15,12 @@ PY2 = sys.version_info < (3, 0)
PY3 = sys.version_info >= (3, 0)
# Coverage.py specifics.
+
# Are we using the C-implemented trace function?
C_TRACER = os.getenv('COVERAGE_TEST_TRACER', 'c') == 'c'
+
# Are we coverage-measuring ourselves?
METACOV = os.getenv('COVERAGE_COVERAGE', '') != ''
+
+# Are we running our test suite?
+TESTING = os.getenv('COVERAGE_TESTING', '') != ''
diff --git a/coverage/misc.py b/coverage/misc.py
index d5197ea3..64111358 100644
--- a/coverage/misc.py
+++ b/coverage/misc.py
@@ -6,7 +6,32 @@ import inspect
import os
from coverage import env
-from coverage.backward import string_class, to_bytes
+from coverage.backward import string_class, to_bytes, unicode_class
+
+
+# Use PyContracts for assertion testing on parameters and returns, but only if
+# we are running our own test suite.
+contract = None
+
+if env.TESTING:
+ try:
+ from contracts import contract
+ except ImportError:
+ pass
+ else:
+ from contracts import new_contract
+
+ # Define contract words that PyContract doesn't have.
+ new_contract('bytes', lambda v: isinstance(v, bytes))
+ if env.PY3:
+ new_contract('unicode', lambda v: isinstance(v, unicode_class))
+
+if not contract:
+ # We aren't using real PyContracts, so just define a no-op decorator as a
+ # stunt double.
+ def contract(**unused): # pylint: disable=function-redefined
+ """Dummy no-op implementation of `contract`."""
+ return lambda func: func
def nice_pair(pair):
diff --git a/igor.py b/igor.py
index 17f4114b..dced3d2e 100644
--- a/igor.py
+++ b/igor.py
@@ -60,6 +60,7 @@ def run_tests(tracer, *nose_args):
print(msg)
return
+ os.environ['COVERAGE_TESTING'] = "True"
print_banner(label)
nose_args = ["nosetests"] + list(nose_args)
nose.core.main(argv=nose_args)
diff --git a/requirements.txt b/requirements.txt
index ab84656b..c02502da 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
# PyPI requirements for running tests for coverage.py
nose
mock
+PyContracts
pylint
tox >= 1.9
diff --git a/tests/test_debug.py b/tests/test_debug.py
index 8dd13a57..8576112d 100644
--- a/tests/test_debug.py
+++ b/tests/test_debug.py
@@ -116,7 +116,7 @@ class DebugTraceTest(CoverageTest):
out_lines = self.f1_debug_output(["sys"])
labels = """
- version coverage cover_dir pylib_dirs tracer config_files
+ version coverage cover_dirs pylib_dirs tracer config_files
configs_read data_path python platform implementation executable
cwd path environment command_line cover_match pylib_match
""".split()
diff --git a/tox.ini b/tox.ini
index 37ae451f..69d94a0a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -26,6 +26,7 @@ commands =
deps =
nose
mock
+ PyContracts
py26: unittest2
py26,py27: gevent
py26,py27: eventlet