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