Skip to content
This repository was archived by the owner on Jun 17, 2021. It is now read-only.

Commit dc271d0

Browse files
committed
Tweak some details of how the tests are run so that better coverage reports can be collected.
1 parent 6b79465 commit dc271d0

File tree

4 files changed

+96
-17
lines changed

4 files changed

+96
-17
lines changed

.coveragerc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[run]
2+
source = setup/cfg
3+
omit =
4+
setup/cfg/extern/*
5+
setup/cfg/tests/*
6+
7+
[report]
8+
exclude_lines =
9+
# Have to re-enable the standard pragma
10+
pragma: no cover
11+
12+
# Don't complain about packages we have installed
13+
except ImportError
14+
15+
# Don't complain if tests don't hit assertions
16+
raise AssertionError
17+
raise NotImplementedError
18+
19+
# Don't complain about script hooks
20+
def main\(.*\):
21+
22+
# Ignore branches that don't pertain to this version of Python
23+
pragma: py{ignore_python_version}
24+
six.PY{ignore_python_version}

setup/cfg/tests/__init__.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from __future__ import with_statement
2+
3+
import io
24
import os
35
import shutil
46
import subprocess
@@ -8,7 +10,10 @@
810

911
import pkg_resources
1012

13+
from setuptools.sandbox import run_setup
14+
1115
from .util import rmtree, open_config
16+
from ..util import monkeypatch_method
1217

1318

1419
SETUP_CFG_DIR = os.path.abspath(
@@ -68,14 +73,25 @@ def teardown(self):
6873
del sys.modules[k]
6974
rmtree(self.temp_dir)
7075

76+
# Undo all monkey-patching that occurred during the test
77+
monkeypatch_method.unpatch_all()
78+
7179
def run_setup(self, *args):
72-
cmd = ('-c',
73-
'import sys;sys.path.insert(0, %r);'
74-
'from setup.cfg.tests import fake_setup_cfg_dist;'
75-
'from setup.cfg.extern.six import exec_;'
76-
'fake_setup_cfg_dist();exec_(open("setup.py").read())' %
77-
SETUP_CFG_DIR)
78-
return self._run_cmd(sys.executable, cmd + args)
80+
old_stdout = sys.stdout
81+
old_stderr = sys.stderr
82+
stdout = sys.stdout = io.StringIO()
83+
stderr = sys.stderr = io.StringIO()
84+
try:
85+
run_setup('setup.py', args)
86+
returncode = 0
87+
except SystemExit as e:
88+
returncode = e.args[0]
89+
finally:
90+
sys.stdout = old_stdout
91+
sys.stderr = old_stderr
92+
93+
return (stdout.getvalue().strip(), stderr.getvalue().strip(),
94+
returncode)
7995

8096
def run_svn(self, *args):
8197
return self._run_cmd('svn', args)

setup/cfg/tests/test_core.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import glob
22
import os
33
import tarfile
4+
import sys
45

56
from . import D2to1TestCase
67

@@ -9,6 +10,21 @@
910

1011

1112
class TestCore(D2to1TestCase):
13+
def test_import_setup_cfg(self):
14+
"""
15+
Test importing the main modules of setup.cfg.
16+
17+
This both tests that importing it is possible, but is also kind
18+
of necessary for coverage.py to pick up the fact that those modules
19+
were imported.
20+
"""
21+
22+
modules = ['setup.cfg', 'setup.cfg.core', 'setup.cfg.util']
23+
for module in modules:
24+
if module in sys.modules:
25+
del sys.modules[module]
26+
__import__(module)
27+
1228
def test_setup_py_version(self):
1329
"""
1430
Test that the `./setup.py --version` command returns the correct

setup/cfg/util.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ def cfg_to_args(path='setup.cfg'):
213213
raise DistutilsFileError(
214214
'%s from the extra_files option in setup.cfg does not '
215215
'exist' % filename)
216+
216217
# Unfortunately the only really sensible way to do this is to
217218
# monkey-patch the manifest_maker class
218219
@monkeypatch_method(manifest_maker)
@@ -536,19 +537,41 @@ def split_csv(value):
536537
return value
537538

538539

539-
def monkeypatch_method(cls):
540-
"""A function decorator to monkey-patch a method of the same name on the
541-
given class.
542-
"""
540+
class MonkeyPatcher(object):
541+
def __init__(self):
542+
self._patched = set()
543+
544+
def __call__(self, cls):
545+
"""
546+
A function decorator to monkey-patch a method of the same name on the
547+
given class.
548+
"""
543549

544-
def wrapper(func):
545-
orig = getattr(cls, func.__name__, None)
546-
if orig and not hasattr(orig, '_orig'): # Already patched
547-
setattr(func, '_orig', orig)
550+
def wrapper(func):
551+
orig = getattr(cls, func.__name__, None)
552+
if hasattr(orig, '_orig'): # Already patched
553+
return orig
554+
555+
func._orig = orig
548556
setattr(cls, func.__name__, func)
549-
return func
557+
self._patched.add((cls, orig))
558+
559+
return func
560+
561+
return wrapper
562+
563+
def unpatch_all(self):
564+
"""
565+
Remove all monkey-patches.
566+
"""
567+
568+
for cls, func in self._patched:
569+
setattr(cls, func.__name__, func)
570+
571+
self._patched.clear()
572+
550573

551-
return wrapper
574+
monkeypatch_method = MonkeyPatcher()
552575

553576

554577
# The following classes are used to hack Distribution.command_options a bit

0 commit comments

Comments
 (0)