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:])) |