Skip to content

Commit 241b220

Browse files
author
Buck Golemon
committed
v0
1 parent d498abc commit 241b220

2 files changed

Lines changed: 169 additions & 0 deletions

File tree

demo.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
rm -rf tmp
2+
mkdir tmp
3+
cd tmp
4+
set -ex
5+
6+
virtualenv tmpenv
7+
. tmpenv/bin/activate
8+
pip install coverage-enable-subprocess --extra-index-url https://testpypi.python.org/pypi
9+
touch .coveragerc
10+
export COVERAGE_PROCESS_START=$PWD/.coveragerc
11+
echo 'print("oh, hi!")' > ohhi.py
12+
python ohhi.py
13+
coverage report

setup.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
"""
2+
This package installs a pth file that enables the coveragepy process_startup
3+
feature in this python prefix/virtualenv in subsequent runs.
4+
5+
See: http://nedbatchelder.com/code/coverage/subprocess.html
6+
7+
8+
Demo::
9+
10+
$ virtualenv tmpenv
11+
$ . tmpenv/bin/activate
12+
$ pip install coverage-enable-subprocess
13+
$ touch .coveragerc
14+
$ export COVERAGE_PROCESS_START=$PWD/.coveragerc
15+
$ echo 'print("oh, hi!")' > ohhi.py
16+
$ python ohhi.py
17+
oh, hi!
18+
19+
$ coverage report
20+
Name Stmts Miss Cover
21+
-----------------------------------------------------
22+
/etc/python2.6/sitecustomize.py 5 1 80%
23+
ohhi.py 1 0 100%
24+
tmpenv/lib/python2.6/site.py 433 392 9%
25+
-----------------------------------------------------
26+
TOTAL 439 393 10%
27+
28+
29+
For projects that need to cd during their test runs, and run many processes in parallel,
30+
I ensure a ``$TOP`` variable is exported, and I use this .coveragerc::
31+
32+
[run]
33+
parallel = True
34+
branch = True
35+
data_file = $TOP/.coverage
36+
37+
[report]
38+
exclude_lines =
39+
# Have to re-enable the standard pragma
40+
\\#.*pragma:\\s*no.?cover
41+
42+
# we can't get coverage for functions that don't return:
43+
\\#.*never returns
44+
\\#.*doesn't return
45+
46+
# Don't complain if tests don't hit defensive assertion code:
47+
^\\s*raise Impossible\\b
48+
^\\s*raise AssertionError\\b
49+
^\\s*raise NotImplementedError\\b
50+
^\\s*return NotImplemented\\b
51+
52+
# Don't complain if tests don't hit re-raise of unexpected errors:
53+
^\\s*raise$
54+
55+
# if main is covered, we're good:
56+
^\\s*exit\\(main\\(\\)\\)$
57+
show_missing = True
58+
59+
[html]
60+
directory = $TOP/coverage-html
61+
62+
# vim:ft=dosini
63+
"""
64+
from __future__ import absolute_import
65+
from __future__ import print_function
66+
from __future__ import unicode_literals
67+
68+
from distutils import log
69+
70+
from setuptools import setup
71+
from setuptools.command.install import install as orig_install
72+
73+
PTH = '''\
74+
try:
75+
import coverage
76+
except ImportError:
77+
pass
78+
else:
79+
coverage.process_startup()
80+
'''
81+
82+
DOC = __doc__
83+
84+
85+
class Install(orig_install):
86+
"""
87+
default semantics for install.extra_path cause all installed modules to go
88+
into a directory whose name is equal to the contents of the .pth file.
89+
90+
All that was necessary was to remove that one behavior to get what you'd
91+
generally want.
92+
"""
93+
# pylint:disable=no-member,attribute-defined-outside-init,access-member-before-definition
94+
95+
def initialize_options(self):
96+
orig_install.initialize_options(self)
97+
name = self.distribution.metadata.name
98+
99+
contents = 'import sys; exec(%r)\n' % PTH
100+
self.extra_path = (name, contents)
101+
102+
def finalize_options(self):
103+
orig_install.finalize_options(self)
104+
105+
from os.path import relpath, join
106+
install_suffix = relpath(self.install_lib, self.install_libbase)
107+
if install_suffix == '.':
108+
log.info('skipping install of .pth during easy-install')
109+
elif install_suffix == self.extra_path[1]:
110+
self.install_lib = self.install_libbase
111+
log.info(
112+
"will install .pth to '%s.pth'",
113+
join(self.install_lib, self.extra_path[0]),
114+
)
115+
else:
116+
raise AssertionError(
117+
'unexpected install_suffix',
118+
self.install_lib, self.install_libbase, install_suffix,
119+
)
120+
121+
122+
def main():
123+
"""the entry point"""
124+
setup(
125+
name=str('coverage_enable_subprocess'),
126+
version='0',
127+
url="https://github.com/bukzor/python-coverage-enable-subprocess",
128+
license="MIT",
129+
author="Buck Evan",
130+
author_email="buck.2019@gmail.com",
131+
description="enable python coverage for subprocesses",
132+
long_description=DOC,
133+
zip_safe=False,
134+
classifiers=[
135+
'Programming Language :: Python :: 2.6',
136+
'Programming Language :: Python :: 2.7',
137+
'Programming Language :: Python :: 3.3',
138+
'Programming Language :: Python :: 3.4',
139+
'License :: OSI Approved :: MIT License',
140+
],
141+
install_requires=[
142+
'coverage',
143+
],
144+
cmdclass={
145+
'install': Install,
146+
},
147+
options={
148+
'bdist_wheel': {
149+
'universal': 1,
150+
},
151+
},
152+
)
153+
154+
155+
if __name__ == '__main__':
156+
exit(main())

0 commit comments

Comments
 (0)