| Index: third_party/pycoverage/igor.py
|
| diff --git a/third_party/pycoverage/igor.py b/third_party/pycoverage/igor.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..12ec6c8fec4afe1fe482cbcbcda18759135ff60e
|
| --- /dev/null
|
| +++ b/third_party/pycoverage/igor.py
|
| @@ -0,0 +1,262 @@
|
| +"""Helper for building, testing, and linting coverage.py.
|
| +
|
| +To get portability, all these operations are written in Python here instead
|
| +of in shell scripts, batch files, or Makefiles.
|
| +
|
| +"""
|
| +
|
| +import fnmatch
|
| +import glob
|
| +import inspect
|
| +import os
|
| +import platform
|
| +import socket
|
| +import sys
|
| +import zipfile
|
| +
|
| +
|
| +# Functions named do_* are executable from the command line: do_blah is run
|
| +# by "python igor.py blah".
|
| +
|
| +
|
| +def do_remove_extension():
|
| + """Remove the compiled C extension, no matter what its name."""
|
| +
|
| + so_patterns = """
|
| + tracer.so
|
| + tracer.*.so
|
| + tracer.pyd
|
| + """.split()
|
| +
|
| + for pattern in so_patterns:
|
| + pattern = os.path.join("coverage", pattern)
|
| + for filename in glob.glob(pattern):
|
| + try:
|
| + os.remove(filename)
|
| + except OSError:
|
| + pass
|
| +
|
| +def run_tests(tracer, *nose_args):
|
| + """The actual running of tests."""
|
| + import nose.core
|
| + if tracer == "py":
|
| + label = "with Python tracer"
|
| + else:
|
| + label = "with C tracer"
|
| + if os.environ.get("COVERAGE_NO_EXTENSION"):
|
| + print("Skipping tests, no C extension in this environment")
|
| + return
|
| + print_banner(label)
|
| + os.environ["COVERAGE_TEST_TRACER"] = tracer
|
| + nose_args = ["nosetests"] + list(nose_args)
|
| + nose.core.main(argv=nose_args)
|
| +
|
| +def run_tests_with_coverage(tracer, *nose_args):
|
| + """Run tests, but with coverage."""
|
| + import coverage
|
| +
|
| + os.environ['COVERAGE_PROCESS_START'] = os.path.abspath('metacov.ini')
|
| + os.environ['COVERAGE_HOME'] = os.getcwd()
|
| +
|
| + # Create the .pth file that will let us measure coverage in sub-processes.
|
| + import nose
|
| + pth_dir = os.path.dirname(os.path.dirname(nose.__file__))
|
| + pth_path = os.path.join(pth_dir, "covcov.pth")
|
| + pth_file = open(pth_path, "w")
|
| + try:
|
| + pth_file.write("import coverage; coverage.process_startup()\n")
|
| + finally:
|
| + pth_file.close()
|
| +
|
| + version = "%s%s" % sys.version_info[:2]
|
| + suffix = "%s_%s_%s" % (version, tracer, socket.gethostname())
|
| +
|
| + cov = coverage.coverage(config_file="metacov.ini", data_suffix=suffix)
|
| + # Cheap trick: the coverage code itself is excluded from measurement, but
|
| + # if we clobber the cover_prefix in the coverage object, we can defeat the
|
| + # self-detection.
|
| + cov.cover_prefix = "Please measure coverage.py!"
|
| + cov.erase()
|
| + cov.start()
|
| +
|
| + try:
|
| + # Re-import coverage to get it coverage tested! I don't understand all
|
| + # the mechanics here, but if I don't carry over the imported modules
|
| + # (in covmods), then things go haywire (os == None, eventually).
|
| + covmods = {}
|
| + covdir = os.path.split(coverage.__file__)[0]
|
| + # We have to make a list since we'll be deleting in the loop.
|
| + modules = list(sys.modules.items())
|
| + for name, mod in modules:
|
| + if name.startswith('coverage'):
|
| + if getattr(mod, '__file__', "??").startswith(covdir):
|
| + covmods[name] = mod
|
| + del sys.modules[name]
|
| + import coverage # don't warn about re-import: pylint: disable=W0404
|
| + sys.modules.update(covmods)
|
| +
|
| + # Run nosetests, with the arguments from our command line.
|
| + try:
|
| + run_tests(tracer, *nose_args)
|
| + except SystemExit:
|
| + # nose3 seems to raise SystemExit, not sure why?
|
| + pass
|
| + finally:
|
| + cov.stop()
|
| + os.remove(pth_path)
|
| +
|
| + cov.save()
|
| +
|
| +def do_combine_html():
|
| + """Combine data from a meta-coverage run, and make the HTML report."""
|
| + import coverage
|
| + os.environ['COVERAGE_HOME'] = os.getcwd()
|
| + cov = coverage.coverage(config_file="metacov.ini")
|
| + cov.load()
|
| + cov.combine()
|
| + cov.save()
|
| + cov.html_report()
|
| +
|
| +def do_test_with_tracer(tracer, *noseargs):
|
| + """Run nosetests with a particular tracer."""
|
| + if os.environ.get("COVERAGE_COVERAGE", ""):
|
| + return run_tests_with_coverage(tracer, *noseargs)
|
| + else:
|
| + return run_tests(tracer, *noseargs)
|
| +
|
| +def do_zip_mods():
|
| + """Build the zipmods.zip file."""
|
| + zf = zipfile.ZipFile("tests/zipmods.zip", "w")
|
| + zf.write("tests/covmodzip1.py", "covmodzip1.py")
|
| + zf.close()
|
| +
|
| +def do_install_egg():
|
| + """Install the egg1 egg for tests."""
|
| + # I am pretty certain there are easier ways to install eggs...
|
| + # pylint: disable=F0401,E0611,E1101
|
| + import distutils.core
|
| + cur_dir = os.getcwd()
|
| + os.chdir("tests/eggsrc")
|
| + distutils.core.run_setup("setup.py", ["--quiet", "bdist_egg"])
|
| + egg = glob.glob("dist/*.egg")[0]
|
| + distutils.core.run_setup(
|
| + "setup.py", ["--quiet", "easy_install", "--no-deps", "--zip-ok", egg]
|
| + )
|
| + os.chdir(cur_dir)
|
| +
|
| +def do_check_eol():
|
| + """Check files for incorrect newlines and trailing whitespace."""
|
| +
|
| + ignore_dirs = [
|
| + '.svn', '.hg', '.tox', '.tox_kits', 'coverage.egg-info',
|
| + '_build', 'covtestegg1.egg-info',
|
| + ]
|
| + checked = set([])
|
| +
|
| + def check_file(fname, crlf=True, trail_white=True):
|
| + """Check a single file for whitespace abuse."""
|
| + fname = os.path.relpath(fname)
|
| + if fname in checked:
|
| + return
|
| + checked.add(fname)
|
| +
|
| + line = None
|
| + for n, line in enumerate(open(fname, "rb")):
|
| + if crlf:
|
| + if "\r" in line:
|
| + print("%s@%d: CR found" % (fname, n+1))
|
| + return
|
| + if trail_white:
|
| + line = line[:-1]
|
| + if not crlf:
|
| + line = line.rstrip('\r')
|
| + if line.rstrip() != line:
|
| + print("%s@%d: trailing whitespace found" % (fname, n+1))
|
| + return
|
| +
|
| + if line is not None and not line.strip():
|
| + print("%s: final blank line" % (fname,))
|
| +
|
| + def check_files(root, patterns, **kwargs):
|
| + """Check a number of files for whitespace abuse."""
|
| + for root, dirs, files in os.walk(root):
|
| + for f in files:
|
| + fname = os.path.join(root, f)
|
| + for p in patterns:
|
| + if fnmatch.fnmatch(fname, p):
|
| + check_file(fname, **kwargs)
|
| + break
|
| + for dir_name in ignore_dirs:
|
| + if dir_name in dirs:
|
| + dirs.remove(dir_name)
|
| +
|
| + check_files("coverage", ["*.py", "*.c"])
|
| + check_files("coverage/htmlfiles", ["*.html", "*.css", "*.js"])
|
| + check_file("tests/farm/html/src/bom.py", crlf=False)
|
| + check_files("tests", ["*.py"])
|
| + check_files("tests", ["*,cover"], trail_white=False)
|
| + check_files("tests/js", ["*.js", "*.html"])
|
| + check_file("setup.py")
|
| + check_file("igor.py")
|
| + check_file("Makefile")
|
| + check_file(".hgignore")
|
| + check_file(".travis.yml")
|
| + check_files("doc", ["*.rst"])
|
| + check_files(".", ["*.txt"])
|
| +
|
| +
|
| +def print_banner(label):
|
| + """Print the version of Python."""
|
| + try:
|
| + impl = platform.python_implementation()
|
| + except AttributeError:
|
| + impl = "Python"
|
| +
|
| + version = platform.python_version()
|
| +
|
| + if '__pypy__' in sys.builtin_module_names:
|
| + pypy_version = sys.pypy_version_info # pylint: disable=E1101
|
| + version += " (pypy %s)" % ".".join([str(v) for v in pypy_version])
|
| +
|
| + print('=== %s %s %s (%s) ===' % (impl, version, label, sys.executable))
|
| +
|
| +
|
| +def do_help():
|
| + """List the available commands"""
|
| + items = list(globals().items())
|
| + items.sort()
|
| + for name, value in items:
|
| + if name.startswith('do_'):
|
| + print("%-20s%s" % (name[3:], value.__doc__))
|
| +
|
| +
|
| +def main(args):
|
| + """Main command-line execution for igor.
|
| +
|
| + Verbs are taken from the command line, and extra words taken as directed
|
| + by the arguments needed by the handler.
|
| +
|
| + """
|
| + while args:
|
| + verb = args.pop(0)
|
| + handler = globals().get('do_'+verb)
|
| + if handler is None:
|
| + print("*** No handler for %r" % verb)
|
| + return 1
|
| + argspec = inspect.getargspec(handler)
|
| + if argspec[1]:
|
| + # Handler has *args, give it all the rest of the command line.
|
| + handler_args = args
|
| + args = []
|
| + else:
|
| + # Handler has specific arguments, give it only what it needs.
|
| + num_args = len(argspec[0])
|
| + handler_args = args[:num_args]
|
| + args = args[num_args:]
|
| + ret = handler(*handler_args)
|
| + # If a handler returns a failure-like value, stop.
|
| + if ret:
|
| + return ret
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(main(sys.argv[1:]))
|
|
|