summaryrefslogtreecommitdiff
path: root/coverage
diff options
context:
space:
mode:
Diffstat (limited to 'coverage')
-rw-r--r--coverage/__init__.py16
-rw-r--r--coverage/backward.py2
-rw-r--r--coverage/cmdline.py27
-rw-r--r--coverage/collector.py47
-rw-r--r--coverage/config.py13
-rw-r--r--coverage/control.py20
-rw-r--r--coverage/misc.py2
-rw-r--r--coverage/parser.py4
-rw-r--r--coverage/tracer.c20
-rw-r--r--coverage/version.py2
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():