Merge Debian packaging for release “4.2+dfsg.1-2”.
[debian_python-coverage.git] / setup.py
blobb304864d9d1389cad029ccabadeece6f3735cefa
1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
4 """Code coverage measurement for Python"""
6 # Distutils setup for coverage.py
7 # This file is used unchanged under all versions of Python, 2.x and 3.x.
9 import os
10 import sys
12 from setuptools import setup
13 from distutils.core import Extension # pylint: disable=no-name-in-module, import-error
14 from distutils.command.build_ext import build_ext # pylint: disable=no-name-in-module, import-error
15 from distutils import errors # pylint: disable=no-name-in-module
17 # Get or massage our metadata. We exec coverage/version.py so we can avoid
18 # importing the product code into setup.py.
20 classifiers = """\
21 Environment :: Console
22 Intended Audience :: Developers
23 License :: OSI Approved :: Apache Software License
24 Operating System :: OS Independent
25 Programming Language :: Python :: 2.6
26 Programming Language :: Python :: 2.7
27 Programming Language :: Python :: 3.3
28 Programming Language :: Python :: 3.4
29 Programming Language :: Python :: 3.5
30 Programming Language :: Python :: 3.6
31 Programming Language :: Python :: Implementation :: CPython
32 Programming Language :: Python :: Implementation :: PyPy
33 Topic :: Software Development :: Quality Assurance
34 Topic :: Software Development :: Testing
35 """
37 cov_ver_py = os.path.join(os.path.split(__file__)[0], "coverage/version.py")
38 with open(cov_ver_py) as version_file:
39 # __doc__ will be overwritten by version.py.
40 doc = __doc__
41 # Keep pylint happy.
42 __version__ = __url__ = version_info = ""
43 # Execute the code in version.py.
44 exec(compile(version_file.read(), cov_ver_py, 'exec'))
46 with open("README.rst") as readme:
47 long_description = readme.read().replace("http://coverage.readthedocs.io", __url__)
49 classifier_list = classifiers.splitlines()
51 if version_info[3] == 'alpha':
52 devstat = "3 - Alpha"
53 elif version_info[3] in ['beta', 'candidate']:
54 devstat = "4 - Beta"
55 else:
56 assert version_info[3] == 'final'
57 devstat = "5 - Production/Stable"
58 classifier_list.append("Development Status :: " + devstat)
60 # Create the keyword arguments for setup()
62 setup_args = dict(
63 name='coverage',
64 version=__version__,
66 packages=[
67 'coverage',
70 package_data={
71 'coverage': [
72 'htmlfiles/*.*',
76 entry_points={
77 # Install a script as "coverage", and as "coverage[23]", and as
78 # "coverage-2.7" (or whatever).
79 'console_scripts': [
80 'coverage = coverage.cmdline:main',
81 'coverage%d = coverage.cmdline:main' % sys.version_info[:1],
82 'coverage-%d.%d = coverage.cmdline:main' % sys.version_info[:2],
86 # We need to get HTML assets from our htmlfiles directory.
87 zip_safe=False,
89 author='Ned Batchelder and others',
90 author_email='ned@nedbatchelder.com',
91 description=doc,
92 long_description=long_description,
93 keywords='code coverage testing',
94 license='Apache 2.0',
95 classifiers=classifier_list,
96 url=__url__,
99 # A replacement for the build_ext command which raises a single exception
100 # if the build fails, so we can fallback nicely.
102 ext_errors = (
103 errors.CCompilerError,
104 errors.DistutilsExecError,
105 errors.DistutilsPlatformError,
107 if sys.platform == 'win32':
108 # distutils.msvc9compiler can raise an IOError when failing to
109 # find the compiler
110 ext_errors += (IOError,)
113 class BuildFailed(Exception):
114 """Raise this to indicate the C extension wouldn't build."""
115 def __init__(self):
116 Exception.__init__(self)
117 self.cause = sys.exc_info()[1] # work around py 2/3 different syntax
120 class ve_build_ext(build_ext):
121 """Build C extensions, but fail with a straightforward exception."""
123 def run(self):
124 """Wrap `run` with `BuildFailed`."""
125 try:
126 build_ext.run(self)
127 except errors.DistutilsPlatformError:
128 raise BuildFailed()
130 def build_extension(self, ext):
131 """Wrap `build_extension` with `BuildFailed`."""
132 try:
133 # Uncomment to test compile failure handling:
134 # raise errors.CCompilerError("OOPS")
135 build_ext.build_extension(self, ext)
136 except ext_errors:
137 raise BuildFailed()
138 except ValueError as err:
139 # this can happen on Windows 64 bit, see Python issue 7511
140 if "'path'" in str(err): # works with both py 2/3
141 raise BuildFailed()
142 raise
144 # There are a few reasons we might not be able to compile the C extension.
145 # Figure out if we should attempt the C extension or not.
147 compile_extension = True
149 if sys.platform.startswith('java'):
150 # Jython can't compile C extensions
151 compile_extension = False
153 if '__pypy__' in sys.builtin_module_names:
154 # Pypy can't compile C extensions
155 compile_extension = False
157 if compile_extension:
158 setup_args.update(dict(
159 ext_modules=[
160 Extension(
161 "coverage.tracer",
162 sources=[
163 "coverage/ctracer/datastack.c",
164 "coverage/ctracer/filedisp.c",
165 "coverage/ctracer/module.c",
166 "coverage/ctracer/tracer.c",
170 cmdclass={
171 'build_ext': ve_build_ext,
175 # Py3.x-specific details.
177 if sys.version_info >= (3, 0):
178 setup_args.update(dict(
179 use_2to3=False,
183 def main():
184 """Actually invoke setup() with the arguments we built above."""
185 # For a variety of reasons, it might not be possible to install the C
186 # extension. Try it with, and if it fails, try it without.
187 try:
188 setup(**setup_args)
189 except BuildFailed as exc:
190 msg = "Couldn't install with extension module, trying without it..."
191 exc_msg = "%s: %s" % (exc.__class__.__name__, exc.cause)
192 print("**\n** %s\n** %s\n**" % (msg, exc_msg))
194 del setup_args['ext_modules']
195 setup(**setup_args)
197 if __name__ == '__main__':
198 main()