diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2016-07-04 08:20:11 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2016-07-04 08:20:11 -0400 |
commit | 98539b47a2790255f633260bcd60243dc7b6647c (patch) | |
tree | bb1b2bf11f0a547fda96c8cfb386da953ae7238c /coverage | |
parent | 1fc4c9681034a2123ce27fa336d16df5dc1cee9c (diff) | |
download | python-coveragepy-git-98539b47a2790255f633260bcd60243dc7b6647c.tar.gz |
Let the concurrency option be multi-valued. #484
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/cmdline.py | 1 | ||||
-rw-r--r-- | coverage/collector.py | 29 | ||||
-rw-r--r-- | coverage/config.py | 4 | ||||
-rw-r--r-- | coverage/control.py | 14 |
4 files changed, 31 insertions, 17 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 395e2c44..7b76f590 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -526,7 +526,6 @@ class CoverageScript(object): self.coverage.set_option("report:fail_under", options.fail_under) if self.coverage.get_option("report:fail_under"): - # Total needs to be rounded, but be careful of 0 and 100. if 0 < total < 1: total = 1 diff --git a/coverage/collector.py b/coverage/collector.py index 5668877b..3e28b3b1 100644 --- a/coverage/collector.py +++ b/coverage/collector.py @@ -65,6 +65,9 @@ class Collector(object): # the top, and resumed when they become the top again. _collectors = [] + # The concurrency settings we support here. + SUPPORTED_CONCURRENCIES = set(["greenlet", "eventlet", "gevent", "thread"]) + def __init__(self, should_trace, check_include, timid, branch, warn, concurrency): """Create a collector. @@ -86,9 +89,10 @@ class Collector(object): `warn` is a warning function, taking a single string message argument, to be used if a warning needs to be issued. - `concurrency` is a string indicating the concurrency library in use. - Valid values are "greenlet", "eventlet", "gevent", or "thread" (the - default). + `concurrency` is a list of strings indicating the concurrency libraries + in use. Valid values are "greenlet", "eventlet", "gevent", or "thread" + (the default). Of these four values, only one can be supplied. Other + values are ignored. """ self.should_trace = should_trace @@ -96,21 +100,26 @@ class Collector(object): self.warn = warn self.branch = branch self.threading = None - self.concurrency = concurrency self.concur_id_func = None + # We can handle a few concurrency options here, but only one at a time. + these_concurrencies = self.SUPPORTED_CONCURRENCIES.intersection(concurrency) + if len(these_concurrencies) > 1: + raise CoverageException("Conflicting concurrency settings: %s" % concurrency) + self.concurrency = these_concurrencies.pop() if these_concurrencies else '' + try: - if concurrency == "greenlet": + if self.concurrency == "greenlet": import greenlet self.concur_id_func = greenlet.getcurrent - elif concurrency == "eventlet": + elif self.concurrency == "eventlet": import eventlet.greenthread # pylint: disable=import-error,useless-suppression self.concur_id_func = eventlet.greenthread.getcurrent - elif concurrency == "gevent": + elif self.concurrency == "gevent": import gevent # pylint: disable=import-error,useless-suppression self.concur_id_func = gevent.getcurrent - elif concurrency == "thread" or not concurrency: + elif self.concurrency == "thread" or not self.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. @@ -120,7 +129,9 @@ class Collector(object): raise CoverageException("Don't understand concurrency=%s" % concurrency) except ImportError: raise CoverageException( - "Couldn't trace with concurrency=%s, the module isn't installed." % concurrency + "Couldn't trace with concurrency=%s, the module isn't installed." % ( + self.concurrency, + ) ) # Who-Tests-What is just a hack at the moment, so turn it on with an diff --git a/coverage/config.py b/coverage/config.py index f7b7eb63..23ec2328 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -191,7 +191,7 @@ class CoverageConfig(object): # Options for plugins self.plugin_options = {} - MUST_BE_LIST = ["omit", "include", "debug", "plugins"] + MUST_BE_LIST = ["omit", "include", "debug", "plugins", "concurrency"] def from_args(self, **kwargs): """Read config values from `kwargs`.""" @@ -267,7 +267,7 @@ class CoverageConfig(object): # [run] ('branch', 'run:branch', 'boolean'), - ('concurrency', 'run:concurrency'), + ('concurrency', 'run:concurrency', 'list'), ('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 9bd0def1..41239be0 100644 --- a/coverage/control.py +++ b/coverage/control.py @@ -110,12 +110,16 @@ class Coverage(object): `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", "gevent", - "multiprocessing", or "thread" (the default). + results if these libraries are in use. Valid strings are "greenlet", + "eventlet", "gevent", "multiprocessing", or "thread" (the default). + This can also be a list of these strings. .. versionadded:: 4.0 The `concurrency` parameter. + .. versionadded:: 4.2 + The `concurrency` parameter can now be a list of strings. + """ # Build our configuration from a number of sources: # 1: defaults: @@ -244,10 +248,10 @@ class Coverage(object): self.omit = prep_patterns(self.config.omit) self.include = prep_patterns(self.config.include) - concurrency = self.config.concurrency - if concurrency == "multiprocessing": + concurrency = self.config.concurrency or [] + if "multiprocessing" in concurrency: patch_multiprocessing() - concurrency = None + #concurrency = None # Multi-processing uses parallel for the subprocesses, so also use # it for the main process. self.config.parallel = True |