1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
# Distutils setup for coverage.py
"""Code coverage measurement for Python
Coverage.py measures code coverage, typically during test execution. It uses
the code analysis tools and tracing hooks provided in the Python standard
library to determine which lines are executable, and which have been executed.
Coverage.py runs on CPython 2.6, 2.7, 3.3, 3.4 or 3.5, PyPy 2.4, and PyPy3 2.4.
Documentation is on `Read the Docs <{docurl}>`_. Code repository and issue
tracker are on `Bitbucket <http://bitbucket.org/ned/coveragepy>`_, with a
mirrored repository on `GitHub <https://github.com/nedbat/coveragepy>`_.
New in 4.0 beta: ``--concurrency``, dropped support for older Pythons,
setup.cfg support, plugins for other file variants, supported data API,
--skip-covered, HTML filtering, and 52 issues closed.
"""
# This file is used unchanged under all versions of Python, 2.x and 3.x.
# Pull in the tools we need.
import os, sys
from setuptools import setup
from distutils.core import Extension # pylint: disable=no-name-in-module, import-error
from distutils.command.build_ext import build_ext # pylint: disable=no-name-in-module, import-error
from distutils import errors # pylint: disable=no-name-in-module
# Get or massage our metadata. We exec coverage/version.py so we can avoid
# importing the product code into setup.py.
classifiers = """\
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: Apache Software License
Operating System :: OS Independent
Programming Language :: Python :: 2
Programming Language :: Python :: 3
Topic :: Software Development :: Quality Assurance
Topic :: Software Development :: Testing
"""
doc = __doc__ # __doc__ will be overwritten by version.py.
__version__ = __url__ = "" # Keep pylint happy.
cov_ver_py = os.path.join(os.path.split(__file__)[0], "coverage/version.py")
with open(cov_ver_py) as version_file:
exec(compile(version_file.read(), cov_ver_py, 'exec'))
doclines = (doc.format(docurl=__url__)).splitlines()
classifier_list = classifiers.splitlines()
if 'a' in __version__:
devstat = "3 - Alpha"
elif 'b' in __version__:
devstat = "4 - Beta"
else:
devstat = "5 - Production/Stable"
classifier_list.append("Development Status :: " + devstat)
# Install a script as "coverage", and as "coverage[23]", and as
# "coverage-2.7" (or whatever).
scripts = [
'coverage = coverage.cmdline:main',
'coverage%d = coverage.cmdline:main' % sys.version_info[:1],
'coverage-%d.%d = coverage.cmdline:main' % sys.version_info[:2],
]
# Create the keyword arguments for setup()
setup_args = dict(
name = 'coverage',
version = __version__,
packages = [
'coverage',
],
package_data = {
'coverage': [
'htmlfiles/*.*',
]
},
entry_points = {'console_scripts': scripts},
# We need to get HTML assets from our htmlfiles directory.
zip_safe = False,
author = 'Ned Batchelder and others',
author_email = 'ned@nedbatchelder.com',
description = doclines[0],
long_description = '\n'.join(doclines[2:]),
keywords = 'code coverage testing',
license = 'Apache 2.0',
classifiers = classifier_list,
url = __url__,
)
# A replacement for the build_ext command which raises a single exception
# if the build fails, so we can fallback nicely.
ext_errors = (
errors.CCompilerError,
errors.DistutilsExecError,
errors.DistutilsPlatformError,
)
if sys.platform == 'win32':
# distutils.msvc9compiler can raise an IOError when failing to
# find the compiler
ext_errors += (IOError,)
class BuildFailed(Exception):
"""Raise this to indicate the C extension wouldn't build."""
def __init__(self):
Exception.__init__(self)
self.cause = sys.exc_info()[1] # work around py 2/3 different syntax
class ve_build_ext(build_ext):
"""Build C extensions, but fail with a straightforward exception."""
def run(self):
"""Wrap `run` with `BuildFailed`."""
try:
build_ext.run(self)
except errors.DistutilsPlatformError:
raise BuildFailed()
def build_extension(self, ext):
"""Wrap `build_extension` with `BuildFailed`."""
try:
# Uncomment to test compile failures:
# raise errors.CCompilerError("OOPS")
build_ext.build_extension(self, ext)
except ext_errors:
raise BuildFailed()
except ValueError as err:
# this can happen on Windows 64 bit, see Python issue 7511
if "'path'" in str(err): # works with both py 2/3
raise BuildFailed()
raise
# There are a few reasons we might not be able to compile the C extension.
# Figure out if we should attempt the C extension or not.
compile_extension = True
if sys.platform.startswith('java'):
# Jython can't compile C extensions
compile_extension = False
if '__pypy__' in sys.builtin_module_names:
# Pypy can't compile C extensions
compile_extension = False
if compile_extension:
setup_args.update(dict(
ext_modules = [
Extension(
"coverage.tracer",
sources=[
"coverage/ctracer/datastack.c",
"coverage/ctracer/filedisp.c",
"coverage/ctracer/module.c",
"coverage/ctracer/tracer.c",
]
)
],
cmdclass = {
'build_ext': ve_build_ext,
},
))
# Py3.x-specific details.
if sys.version_info >= (3, 0):
setup_args.update(dict(
use_2to3 = False,
))
def main():
"""Actually invoke setup() with the arguments we built above."""
# For a variety of reasons, it might not be possible to install the C
# extension. Try it with, and if it fails, try it without.
try:
setup(**setup_args)
except BuildFailed as exc:
msg = "Couldn't install with extension module, trying without it..."
exc_msg = "%s: %s" % (exc.__class__.__name__, exc.cause)
print("**\n** %s\n** %s\n**" % (msg, exc_msg))
del setup_args['ext_modules']
setup(**setup_args)
if __name__ == '__main__':
main()
|