diff options
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/__init__.py | 16 | ||||
-rw-r--r-- | coverage/backward.py | 2 | ||||
-rw-r--r-- | coverage/cmdline.py | 27 | ||||
-rw-r--r-- | coverage/collector.py | 47 | ||||
-rw-r--r-- | coverage/config.py | 13 | ||||
-rw-r--r-- | coverage/control.py | 20 | ||||
-rw-r--r-- | coverage/misc.py | 2 | ||||
-rw-r--r-- | coverage/parser.py | 4 | ||||
-rw-r--r-- | coverage/tracer.c | 20 | ||||
-rw-r--r-- | coverage/version.py | 2 |
10 files changed, 74 insertions, 79 deletions
diff --git a/coverage/__init__.py b/coverage/__init__.py index 5ae32ab..67dd6e8 100644 --- a/coverage/__init__.py +++ b/coverage/__init__.py @@ -17,9 +17,9 @@ from coverage.plugin import CoveragePlugin coverage = Coverage # Module-level functions. The original API to this module was based on -# functions defined directly in the module, with a singleton of the coverage() +# functions defined directly in the module, with a singleton of the Coverage() # class. That design hampered programmability, so the current api uses -# explicitly-created coverage objects. But for backward compatibility, here we +# explicitly-created Coverage objects. But for backward compatibility, here we # define the top-level functions to create the singleton when they are first # called. @@ -28,7 +28,7 @@ coverage = Coverage _the_coverage = None def _singleton_method(name): - """Return a function to the `name` method on a singleton `coverage` object. + """Return a function to the `name` method on a singleton `Coverage` object. The singleton object is created the first time one of these functions is called. @@ -42,19 +42,19 @@ def _singleton_method(name): """Singleton wrapper around a coverage method.""" global _the_coverage if not _the_coverage: - _the_coverage = coverage(auto_data=True) + _the_coverage = Coverage(auto_data=True) return getattr(_the_coverage, name)(*args, **kwargs) import inspect - meth = getattr(coverage, name) + meth = getattr(Coverage, name) args, varargs, kw, defaults = inspect.getargspec(meth) argspec = inspect.formatargspec(args[1:], varargs, kw, defaults) docstring = meth.__doc__ wrapper.__doc__ = ("""\ - A first-use-singleton wrapper around coverage.%(name)s. + A first-use-singleton wrapper around Coverage.%(name)s. This wrapper is provided for backward compatibility with legacy code. - New code should use coverage.%(name)s directly. + New code should use Coverage.%(name)s directly. %(name)s%(argspec)s: @@ -96,7 +96,7 @@ except KeyError: # COPYRIGHT AND LICENSE # # Copyright 2001 Gareth Rees. All rights reserved. -# Copyright 2004-2013 Ned Batchelder. All rights reserved. +# Copyright 2004-2014 Ned Batchelder. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are diff --git a/coverage/backward.py b/coverage/backward.py index 9597449..e839f6b 100644 --- a/coverage/backward.py +++ b/coverage/backward.py @@ -148,7 +148,7 @@ def import_local_file(modname): if SourceFileLoader: mod = SourceFileLoader(modname, modfile).load_module() else: - for suff in imp.get_suffixes(): + for suff in imp.get_suffixes(): # pragma: part covered if suff[0] == '.py': break diff --git a/coverage/cmdline.py b/coverage/cmdline.py index bd10d5a..58f4817 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -19,9 +19,12 @@ class Opts(object): '', '--branch', action='store_true', help="Measure branch coverage in addition to statement coverage." ) - coroutine = optparse.make_option( - '', '--coroutine', action='store', metavar="LIB", - help="Properly measure code using coroutines." + CONCURRENCY_CHOICES = ["thread", "gevent", "greenlet", "eventlet"] + concurrency = optparse.make_option( + '', '--concurrency', action='store', metavar="LIB", + choices=CONCURRENCY_CHOICES, + help="Properly measure code using a concurrency library. " + "Valid values are: %s." % ", ".join(CONCURRENCY_CHOICES) ) debug = optparse.make_option( '', '--debug', action='store', metavar="OPTS", @@ -46,8 +49,8 @@ class Opts(object): include = optparse.make_option( '', '--include', action='store', metavar="PAT1,PAT2,...", - help="Include files only when their filename path matches one of " - "these patterns. Usually needs quoting on the command line." + help="Include only files whose paths match one of these patterns." + "Accepts shell-style wildcards, which must be quoted." ) pylib = optparse.make_option( '-L', '--pylib', action='store_true', @@ -62,14 +65,14 @@ class Opts(object): old_omit = optparse.make_option( '-o', '--omit', action='store', metavar="PAT1,PAT2,...", - help="Omit files when their filename matches one of these patterns. " - "Usually needs quoting on the command line." + help="Omit files whose paths match one of these patterns. " + "Accepts shell-style wildcards, which must be quoted." ) omit = optparse.make_option( '', '--omit', action='store', metavar="PAT1,PAT2,...", - help="Omit files when their filename matches one of these patterns. " - "Usually needs quoting on the command line." + help="Omit files whose paths match one of these patterns. " + "Accepts shell-style wildcards, which must be quoted." ) output_xml = optparse.make_option( '-o', '', action='store', dest="outfile", @@ -125,7 +128,7 @@ class CoverageOptionParser(optparse.OptionParser, object): self.set_defaults( actions=[], branch=None, - coroutine=None, + concurrency=None, debug=None, directory=None, fail_under=None, @@ -320,7 +323,7 @@ CMDS = { [ Opts.append, Opts.branch, - Opts.coroutine, + Opts.concurrency, Opts.debug, Opts.pylib, Opts.parallel_mode, @@ -429,7 +432,7 @@ class CoverageScript(object): omit = omit, include = include, debug = debug, - coroutine = options.coroutine, + concurrency = options.concurrency, ) if 'debug' in options.actions: diff --git a/coverage/collector.py b/coverage/collector.py index c571cb0..66de8b6 100644 --- a/coverage/collector.py +++ b/coverage/collector.py @@ -51,7 +51,7 @@ class Collector(object): _collectors = [] def __init__(self, - should_trace, check_include, timid, branch, warn, coroutine, + should_trace, check_include, timid, branch, warn, concurrency, ): """Create a collector. @@ -73,7 +73,9 @@ class Collector(object): `warn` is a warning function, taking a single string message argument, to be used if a warning needs to be issued. - TODO: `coroutine` + `concurrency` is a string indicating the concurrency library in use. + Valid values are "greenlet", "eventlet", "gevent", or "thread" (the + default). """ self.should_trace = should_trace @@ -81,21 +83,21 @@ class Collector(object): self.warn = warn self.branch = branch self.threading = None - self.coroutine = coroutine + self.concurrency = concurrency - self.coroutine_id_func = None + self.concur_id_func = None try: - if coroutine == "greenlet": - import greenlet - self.coroutine_id_func = greenlet.getcurrent - elif coroutine == "eventlet": - import eventlet.greenthread - self.coroutine_id_func = eventlet.greenthread.getcurrent - elif coroutine == "gevent": - import gevent - self.coroutine_id_func = gevent.getcurrent - elif coroutine == "thread" or not coroutine: + if concurrency == "greenlet": + import greenlet # pylint: disable=import-error + self.concur_id_func = greenlet.getcurrent + elif concurrency == "eventlet": + import eventlet.greenthread # pylint: disable=import-error + self.concur_id_func = eventlet.greenthread.getcurrent + elif concurrency == "gevent": + import gevent # pylint: disable=import-error + self.concur_id_func = gevent.getcurrent + elif concurrency == "thread" or not concurrency: # It's important to import threading only if we need it. If # it's imported early, and the program being measured uses # gevent, then gevent's monkey-patching won't work properly. @@ -103,12 +105,12 @@ class Collector(object): self.threading = threading else: raise CoverageException( - "Don't understand coroutine=%s" % coroutine + "Don't understand concurrency=%s" % concurrency ) except ImportError: raise CoverageException( - "Couldn't trace with coroutine=%s, " - "the module isn't installed." % coroutine + "Couldn't trace with concurrency=%s, " + "the module isn't installed." % concurrency ) self.reset() @@ -156,13 +158,13 @@ class Collector(object): tracer.should_trace_cache = self.should_trace_cache tracer.warn = self.warn - if hasattr(tracer, 'coroutine_id_func'): - tracer.coroutine_id_func = self.coroutine_id_func - elif self.coroutine_id_func: + if hasattr(tracer, 'concur_id_func'): + tracer.concur_id_func = self.concur_id_func + elif self.concur_id_func: raise CoverageException( - "Can't support coroutine=%s with %s, " + "Can't support concurrency=%s with %s, " "only threads are supported" % ( - self.coroutine, self.tracer_name(), + self.concurrency, self.tracer_name(), ) ) @@ -212,6 +214,7 @@ class Collector(object): # Install the tracer on this thread. fn = self._start_tracer() + # Replay all the events from fullcoverage into the new trace function. for args in traces0: (frame, event, arg), lineno = args try: diff --git a/coverage/config.py b/coverage/config.py index c671ef7..ece68ba 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -140,7 +140,7 @@ class CoverageConfig(object): # Defaults for [run] self.branch = False - self.coroutine = None + self.concurrency = None self.cover_pylib = False self.data_file = ".coverage" self.parallel = False @@ -173,15 +173,6 @@ class CoverageConfig(object): # Options for plugins self.plugin_options = {} - def from_environment(self, env_var): - """Read configuration from the `env_var` environment variable.""" - # Timidity: for nose users, read an environment variable. This is a - # cheap hack, since the rest of the command line arguments aren't - # recognized, but it solves some users' problems. - env = os.environ.get(env_var, '') - if env: - self.timid = ('--timid' in env) - MUST_BE_LIST = ["omit", "include", "debug", "plugins"] def from_args(self, **kwargs): @@ -235,7 +226,7 @@ class CoverageConfig(object): # [run] ('branch', 'run:branch', 'boolean'), - ('coroutine', 'run:coroutine'), + ('concurrency', 'run:concurrency'), ('cover_pylib', 'run:cover_pylib', 'boolean'), ('data_file', 'run:data_file'), ('debug', 'run:debug', 'list'), diff --git a/coverage/control.py b/coverage/control.py index 86a2ae2..b2ec64a 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -45,7 +45,7 @@ class Coverage(object): def __init__(self, data_file=None, data_suffix=None, cover_pylib=None, auto_data=False, timid=None, branch=None, config_file=True, source=None, omit=None, include=None, debug=None, - debug_file=None, coroutine=None, plugins=None): + debug_file=None, concurrency=None, plugins=None): """ `data_file` is the base name of the data file to use, defaulting to ".coverage". `data_suffix` is appended (with a dot) to `data_file` to @@ -84,10 +84,10 @@ class Coverage(object): desired. `debug_file` is the file to write debug messages to, defaulting to stderr. - `coroutine` is a string indicating the coroutining library being used + `concurrency` is a string indicating the concurrency library being used in the measured code. Without this, coverage.py will get incorrect - results. Valid strings are "greenlet", "eventlet", or "gevent", which - are all equivalent. TODO: really? + results. Valid strings are "greenlet", "eventlet", "gevent", or + "thread" (the default). `plugins` TODO. @@ -118,7 +118,6 @@ class Coverage(object): self.config.from_file("setup.cfg", section_prefix="coverage:") # 3: from environment variables: - self.config.from_environment('COVERAGE_OPTIONS') env_data_file = os.environ.get('COVERAGE_FILE') if env_data_file: self.config.data_file = env_data_file @@ -128,7 +127,7 @@ class Coverage(object): data_file=data_file, cover_pylib=cover_pylib, timid=timid, branch=branch, parallel=bool_or_none(data_suffix), source=source, omit=omit, include=include, debug=debug, - coroutine=coroutine, plugins=plugins, + concurrency=concurrency, plugins=plugins, ) # Create and configure the debugging controller. @@ -170,7 +169,7 @@ class Coverage(object): timid=self.config.timid, branch=self.config.branch, warn=self._warn, - coroutine=self.config.coroutine, + concurrency=self.config.concurrency, ) # Suffixes are a bit tricky. We want to use the data suffix only when @@ -551,10 +550,9 @@ class Coverage(object): # `save()` at the last minute so that the pid will be correct even # if the process forks. extra = "" - if _TEST_NAME_FILE: - f = open(_TEST_NAME_FILE) - test_name = f.read() - f.close() + if _TEST_NAME_FILE: # pragma: debugging + with open(_TEST_NAME_FILE) as f: + test_name = f.read() extra = "." + test_name data_suffix = "%s%s.%s.%06d" % ( socket.gethostname(), extra, os.getpid(), diff --git a/coverage/misc.py b/coverage/misc.py index 6962ae3..a653bb6 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -55,7 +55,7 @@ def format_lines(statements, lines): return ret -def short_stack(): +def short_stack(): # pragma: debugging """Return a string summarizing the call stack.""" stack = inspect.stack()[:0:-1] return "\n".join("%30s : %s @%d" % (t[3],t[1],t[2]) for t in stack) diff --git a/coverage/parser.py b/coverage/parser.py index c5e95ba..e7b9c02 100644 --- a/coverage/parser.py +++ b/coverage/parser.py @@ -413,7 +413,7 @@ class ByteParser(object): for _, l in bp._bytes_lines(): yield l - def _block_stack_repr(self, block_stack): + def _block_stack_repr(self, block_stack): # pragma: debugging """Get a string version of `block_stack`, for debugging.""" blocks = ", ".join( "(%s, %r)" % (dis.opname[b[0]], b[1]) for b in block_stack @@ -552,7 +552,7 @@ class ByteParser(object): #self.validate_chunks(chunks) return chunks - def validate_chunks(self, chunks): + def validate_chunks(self, chunks): # pragma: debugging """Validate the rule that chunks have a single entrance.""" # starts is the entrances to the chunks starts = set(ch.byte for ch in chunks) diff --git a/coverage/tracer.c b/coverage/tracer.c index 5bf5c46..dcc3b72 100644 --- a/coverage/tracer.c +++ b/coverage/tracer.c @@ -81,7 +81,7 @@ typedef struct { /* Python objects manipulated directly by the Collector class. */ PyObject * should_trace; PyObject * warn; - PyObject * coroutine_id_func; + PyObject * concur_id_func; PyObject * data; PyObject * plugin_data; PyObject * should_trace_cache; @@ -104,8 +104,8 @@ typedef struct { (None). */ - DataStack data_stack; /* Used if we aren't doing coroutines. */ - PyObject * data_stack_index; /* Used if we are doing coroutines. */ + DataStack data_stack; /* Used if we aren't doing concurrency. */ + PyObject * data_stack_index; /* Used if we are doing concurrency. */ DataStack * data_stacks; int data_stacks_alloc; int data_stacks_used; @@ -191,7 +191,7 @@ CTracer_init(CTracer *self, PyObject *args_unused, PyObject *kwds_unused) self->should_trace = NULL; self->warn = NULL; - self->coroutine_id_func = NULL; + self->concur_id_func = NULL; self->data = NULL; self->plugin_data = NULL; self->should_trace_cache = NULL; @@ -234,7 +234,7 @@ CTracer_dealloc(CTracer *self) Py_XDECREF(self->should_trace); Py_XDECREF(self->warn); - Py_XDECREF(self->coroutine_id_func); + Py_XDECREF(self->concur_id_func); Py_XDECREF(self->data); Py_XDECREF(self->plugin_data); Py_XDECREF(self->should_trace_cache); @@ -327,18 +327,18 @@ CTracer_record_pair(CTracer *self, int l1, int l2) static int CTracer_set_pdata_stack(CTracer *self) { - if (self->coroutine_id_func != Py_None) { + if (self->concur_id_func != Py_None) { PyObject * co_obj = NULL; PyObject * stack_index = NULL; long the_index = 0; - co_obj = PyObject_CallObject(self->coroutine_id_func, NULL); + co_obj = PyObject_CallObject(self->concur_id_func, NULL); if (co_obj == NULL) { return RET_ERROR; } stack_index = PyDict_GetItem(self->data_stack_index, co_obj); if (stack_index == NULL) { - /* A new coroutine object. Make a new data stack. */ + /* A new concurrency object. Make a new data stack. */ the_index = self->data_stacks_used; stack_index = MyInt_FromLong(the_index); if (PyDict_SetItem(self->data_stack_index, co_obj, stack_index) < 0) { @@ -781,8 +781,8 @@ CTracer_members[] = { { "warn", T_OBJECT, offsetof(CTracer, warn), 0, PyDoc_STR("Function for issuing warnings.") }, - { "coroutine_id_func", T_OBJECT, offsetof(CTracer, coroutine_id_func), 0, - PyDoc_STR("Function for determining coroutine context") }, + { "concur_id_func", T_OBJECT, offsetof(CTracer, concur_id_func), 0, + PyDoc_STR("Function for determining concurrency context") }, { "data", T_OBJECT, offsetof(CTracer, data), 0, PyDoc_STR("The raw dictionary of trace data.") }, diff --git a/coverage/version.py b/coverage/version.py index 27c2f6b..fe3f44f 100644 --- a/coverage/version.py +++ b/coverage/version.py @@ -1,7 +1,7 @@ """The version and URL for coverage.py""" # This file is exec'ed in setup.py, don't import anything! -__version__ = "4.0a0" # see detailed history in CHANGES.txt +__version__ = "4.0a1" # see detailed history in CHANGES.txt __url__ = "http://nedbatchelder.com/code/coverage" if max(__version__).isalpha(): |