Merge remote-tracking branch 'origin/master'
[idea/community.git] / python / helpers / coveragepy / coverage / control.py
1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
3
4 """Core control stuff for coverage.py."""
5
6 import atexit
7 import inspect
8 import os
9 import platform
10 import re
11 import sys
12 import traceback
13
14 from coverage import env, files
15 from coverage.annotate import AnnotateReporter
16 from coverage.backward import string_class, iitems
17 from coverage.collector import Collector
18 from coverage.config import CoverageConfig
19 from coverage.data import CoverageData, CoverageDataFiles
20 from coverage.debug import DebugControl
21 from coverage.files import TreeMatcher, FnmatchMatcher
22 from coverage.files import PathAliases, find_python_files, prep_patterns
23 from coverage.files import ModuleMatcher, abs_file
24 from coverage.html import HtmlReporter
25 from coverage.misc import CoverageException, bool_or_none, join_regex
26 from coverage.misc import file_be_gone, isolate_module
27 from coverage.multiproc import patch_multiprocessing
28 from coverage.plugin import FileReporter
29 from coverage.plugin_support import Plugins
30 from coverage.python import PythonFileReporter
31 from coverage.results import Analysis, Numbers
32 from coverage.summary import SummaryReporter
33 from coverage.xmlreport import XmlReporter
34
35 os = isolate_module(os)
36
37 # Pypy has some unusual stuff in the "stdlib".  Consider those locations
38 # when deciding where the stdlib is.
39 try:
40     import _structseq
41 except ImportError:
42     _structseq = None
43
44
45 class Coverage(object):
46     """Programmatic access to coverage.py.
47
48     To use::
49
50         from coverage import Coverage
51
52         cov = Coverage()
53         cov.start()
54         #.. call your code ..
55         cov.stop()
56         cov.html_report(directory='covhtml')
57
58     """
59     def __init__(
60         self, data_file=None, data_suffix=None, cover_pylib=None,
61         auto_data=False, timid=None, branch=None, config_file=True,
62         source=None, omit=None, include=None, debug=None,
63         concurrency=None,
64     ):
65         """
66         `data_file` is the base name of the data file to use, defaulting to
67         ".coverage".  `data_suffix` is appended (with a dot) to `data_file` to
68         create the final file name.  If `data_suffix` is simply True, then a
69         suffix is created with the machine and process identity included.
70
71         `cover_pylib` is a boolean determining whether Python code installed
72         with the Python interpreter is measured.  This includes the Python
73         standard library and any packages installed with the interpreter.
74
75         If `auto_data` is true, then any existing data file will be read when
76         coverage measurement starts, and data will be saved automatically when
77         measurement stops.
78
79         If `timid` is true, then a slower and simpler trace function will be
80         used.  This is important for some environments where manipulation of
81         tracing functions breaks the faster trace function.
82
83         If `branch` is true, then branch coverage will be measured in addition
84         to the usual statement coverage.
85
86         `config_file` determines what configuration file to read:
87
88             * If it is ".coveragerc", it is interpreted as if it were True,
89               for backward compatibility.
90
91             * If it is a string, it is the name of the file to read.  If the
92               file can't be read, it is an error.
93
94             * If it is True, then a few standard files names are tried
95               (".coveragerc", "setup.cfg").  It is not an error for these files
96               to not be found.
97
98             * If it is False, then no configuration file is read.
99
100         `source` is a list of file paths or package names.  Only code located
101         in the trees indicated by the file paths or package names will be
102         measured.
103
104         `include` and `omit` are lists of file name patterns. Files that match
105         `include` will be measured, files that match `omit` will not.  Each
106         will also accept a single string argument.
107
108         `debug` is a list of strings indicating what debugging information is
109         desired.
110
111         `concurrency` is a string indicating the concurrency library being used
112         in the measured code.  Without this, coverage.py will get incorrect
113         results if these libraries are in use.  Valid strings are "greenlet",
114         "eventlet", "gevent", "multiprocessing", or "thread" (the default).
115         This can also be a list of these strings.
116
117         .. versionadded:: 4.0
118             The `concurrency` parameter.
119
120         .. versionadded:: 4.2
121             The `concurrency` parameter can now be a list of strings.
122
123         """
124         # Build our configuration from a number of sources:
125         # 1: defaults:
126         self.config = CoverageConfig()
127
128         # 2: from the rcfile, .coveragerc or setup.cfg file:
129         if config_file:
130             # pylint: disable=redefined-variable-type
131             did_read_rc = False
132             # Some API users were specifying ".coveragerc" to mean the same as
133             # True, so make it so.
134             if config_file == ".coveragerc":
135                 config_file = True
136             specified_file = (config_file is not True)
137             if not specified_file:
138                 config_file = ".coveragerc"
139             self.config_file = config_file
140
141             did_read_rc = self.config.from_file(config_file)
142
143             if not did_read_rc:
144                 if specified_file:
145                     raise CoverageException(
146                         "Couldn't read '%s' as a config file" % config_file
147                         )
148                 self.config.from_file("setup.cfg", section_prefix="coverage:")
149
150         # 3: from environment variables:
151         env_data_file = os.environ.get('COVERAGE_FILE')
152         if env_data_file:
153             self.config.data_file = env_data_file
154         debugs = os.environ.get('COVERAGE_DEBUG')
155         if debugs:
156             self.config.debug.extend(debugs.split(","))
157
158         # 4: from constructor arguments:
159         self.config.from_args(
160             data_file=data_file, cover_pylib=cover_pylib, timid=timid,
161             branch=branch, parallel=bool_or_none(data_suffix),
162             source=source, omit=omit, include=include, debug=debug,
163             concurrency=concurrency,
164             )
165
166         self._debug_file = None
167         self._auto_data = auto_data
168         self._data_suffix = data_suffix
169
170         # The matchers for _should_trace.
171         self.source_match = None
172         self.source_pkgs_match = None
173         self.pylib_match = self.cover_match = None
174         self.include_match = self.omit_match = None
175
176         # Is it ok for no data to be collected?
177         self._warn_no_data = True
178         self._warn_unimported_source = True
179
180         # A record of all the warnings that have been issued.
181         self._warnings = []
182
183         # Other instance attributes, set later.
184         self.omit = self.include = self.source = None
185         self.source_pkgs = None
186         self.data = self.data_files = self.collector = None
187         self.plugins = None
188         self.pylib_dirs = self.cover_dirs = None
189         self.data_suffix = self.run_suffix = None
190         self._exclude_re = None
191         self.debug = None
192
193         # State machine variables:
194         # Have we initialized everything?
195         self._inited = False
196         # Have we started collecting and not stopped it?
197         self._started = False
198         # Have we measured some data and not harvested it?
199         self._measured = False
200
201         # If we have sub-process measurement happening automatically, then we
202         # want any explicit creation of a Coverage object to mean, this process
203         # is already coverage-aware, so don't auto-measure it.  By now, the
204         # auto-creation of a Coverage object has already happened.  But we can
205         # find it and tell it not to save its data.
206         if not env.METACOV:
207             _prevent_sub_process_measurement()
208
209     def _init(self):
210         """Set all the initial state.
211
212         This is called by the public methods to initialize state. This lets us
213         construct a :class:`Coverage` object, then tweak its state before this
214         function is called.
215
216         """
217         if self._inited:
218             return
219
220         # Create and configure the debugging controller. COVERAGE_DEBUG_FILE
221         # is an environment variable, the name of a file to append debug logs
222         # to.
223         if self._debug_file is None:
224             debug_file_name = os.environ.get("COVERAGE_DEBUG_FILE")
225             if debug_file_name:
226                 self._debug_file = open(debug_file_name, "a")
227             else:
228                 self._debug_file = sys.stderr
229         self.debug = DebugControl(self.config.debug, self._debug_file)
230
231         # Load plugins
232         self.plugins = Plugins.load_plugins(self.config.plugins, self.config, self.debug)
233
234         # _exclude_re is a dict that maps exclusion list names to compiled
235         # regexes.
236         self._exclude_re = {}
237         self._exclude_regex_stale()
238
239         files.set_relative_directory()
240
241         # The source argument can be directories or package names.
242         self.source = []
243         self.source_pkgs = []
244         for src in self.config.source or []:
245             if os.path.exists(src):
246                 self.source.append(files.canonical_filename(src))
247             else:
248                 self.source_pkgs.append(src)
249
250         self.omit = prep_patterns(self.config.omit)
251         self.include = prep_patterns(self.config.include)
252
253         concurrency = self.config.concurrency or []
254         if "multiprocessing" in concurrency:
255             patch_multiprocessing(rcfile=self.config_file)
256             #concurrency = None
257             # Multi-processing uses parallel for the subprocesses, so also use
258             # it for the main process.
259             self.config.parallel = True
260
261         self.collector = Collector(
262             should_trace=self._should_trace,
263             check_include=self._check_include_omit_etc,
264             timid=self.config.timid,
265             branch=self.config.branch,
266             warn=self._warn,
267             concurrency=concurrency,
268             )
269
270         # Early warning if we aren't going to be able to support plugins.
271         if self.plugins.file_tracers and not self.collector.supports_plugins:
272             self._warn(
273                 "Plugin file tracers (%s) aren't supported with %s" % (
274                     ", ".join(
275                         plugin._coverage_plugin_name
276                             for plugin in self.plugins.file_tracers
277                         ),
278                     self.collector.tracer_name(),
279                     )
280                 )
281             for plugin in self.plugins.file_tracers:
282                 plugin._coverage_enabled = False
283
284         # Suffixes are a bit tricky.  We want to use the data suffix only when
285         # collecting data, not when combining data.  So we save it as
286         # `self.run_suffix` now, and promote it to `self.data_suffix` if we
287         # find that we are collecting data later.
288         if self._data_suffix or self.config.parallel:
289             if not isinstance(self._data_suffix, string_class):
290                 # if data_suffix=True, use .machinename.pid.random
291                 self._data_suffix = True
292         else:
293             self._data_suffix = None
294         self.data_suffix = None
295         self.run_suffix = self._data_suffix
296
297         # Create the data file.  We do this at construction time so that the
298         # data file will be written into the directory where the process
299         # started rather than wherever the process eventually chdir'd to.
300         self.data = CoverageData(debug=self.debug)
301         self.data_files = CoverageDataFiles(basename=self.config.data_file, warn=self._warn)
302
303         # The directories for files considered "installed with the interpreter".
304         self.pylib_dirs = set()
305         if not self.config.cover_pylib:
306             # Look at where some standard modules are located. That's the
307             # indication for "installed with the interpreter". In some
308             # environments (virtualenv, for example), these modules may be
309             # spread across a few locations. Look at all the candidate modules
310             # we've imported, and take all the different ones.
311             for m in (atexit, inspect, os, platform, re, _structseq, traceback):
312                 if m is not None and hasattr(m, "__file__"):
313                     self.pylib_dirs.add(self._canonical_dir(m))
314             if _structseq and not hasattr(_structseq, '__file__'):
315                 # PyPy 2.4 has no __file__ in the builtin modules, but the code
316                 # objects still have the file names.  So dig into one to find
317                 # the path to exclude.
318                 structseq_new = _structseq.structseq_new
319                 try:
320                     structseq_file = structseq_new.func_code.co_filename
321                 except AttributeError:
322                     structseq_file = structseq_new.__code__.co_filename
323                 self.pylib_dirs.add(self._canonical_dir(structseq_file))
324
325         # To avoid tracing the coverage.py code itself, we skip anything
326         # located where we are.
327         self.cover_dirs = [self._canonical_dir(__file__)]
328         if env.TESTING:
329             # When testing, we use PyContracts, which should be considered
330             # part of coverage.py, and it uses six. Exclude those directories
331             # just as we exclude ourselves.
332             import contracts
333             import six
334             for mod in [contracts, six]:
335                 self.cover_dirs.append(self._canonical_dir(mod))
336
337         # Set the reporting precision.
338         Numbers.set_precision(self.config.precision)
339
340         atexit.register(self._atexit)
341
342         self._inited = True
343
344         # Create the matchers we need for _should_trace
345         if self.source or self.source_pkgs:
346             self.source_match = TreeMatcher(self.source)
347             self.source_pkgs_match = ModuleMatcher(self.source_pkgs)
348         else:
349             if self.cover_dirs:
350                 self.cover_match = TreeMatcher(self.cover_dirs)
351             if self.pylib_dirs:
352                 self.pylib_match = TreeMatcher(self.pylib_dirs)
353         if self.include:
354             self.include_match = FnmatchMatcher(self.include)
355         if self.omit:
356             self.omit_match = FnmatchMatcher(self.omit)
357
358         # The user may want to debug things, show info if desired.
359         wrote_any = False
360         if self.debug.should('config'):
361             config_info = sorted(self.config.__dict__.items())
362             self.debug.write_formatted_info("config", config_info)
363             wrote_any = True
364
365         if self.debug.should('sys'):
366             self.debug.write_formatted_info("sys", self.sys_info())
367             for plugin in self.plugins:
368                 header = "sys: " + plugin._coverage_plugin_name
369                 info = plugin.sys_info()
370                 self.debug.write_formatted_info(header, info)
371             wrote_any = True
372
373         if wrote_any:
374             self.debug.write_formatted_info("end", ())
375
376     def _canonical_dir(self, morf):
377         """Return the canonical directory of the module or file `morf`."""
378         morf_filename = PythonFileReporter(morf, self).filename
379         return os.path.split(morf_filename)[0]
380
381     def _source_for_file(self, filename):
382         """Return the source file for `filename`.
383
384         Given a file name being traced, return the best guess as to the source
385         file to attribute it to.
386
387         """
388         if filename.endswith(".py"):
389             # .py files are themselves source files.
390             return filename
391
392         elif filename.endswith((".pyc", ".pyo")):
393             # Bytecode files probably have source files near them.
394             py_filename = filename[:-1]
395             if os.path.exists(py_filename):
396                 # Found a .py file, use that.
397                 return py_filename
398             if env.WINDOWS:
399                 # On Windows, it could be a .pyw file.
400                 pyw_filename = py_filename + "w"
401                 if os.path.exists(pyw_filename):
402                     return pyw_filename
403             # Didn't find source, but it's probably the .py file we want.
404             return py_filename
405
406         elif filename.endswith("$py.class"):
407             # Jython is easy to guess.
408             return filename[:-9] + ".py"
409
410         # No idea, just use the file name as-is.
411         return filename
412
413     def _name_for_module(self, module_globals, filename):
414         """Get the name of the module for a set of globals and file name.
415
416         For configurability's sake, we allow __main__ modules to be matched by
417         their importable name.
418
419         If loaded via runpy (aka -m), we can usually recover the "original"
420         full dotted module name, otherwise, we resort to interpreting the
421         file name to get the module's name.  In the case that the module name
422         can't be determined, None is returned.
423
424         """
425         dunder_name = module_globals.get('__name__', None)
426
427         if isinstance(dunder_name, str) and dunder_name != '__main__':
428             # This is the usual case: an imported module.
429             return dunder_name
430
431         loader = module_globals.get('__loader__', None)
432         for attrname in ('fullname', 'name'):   # attribute renamed in py3.2
433             if hasattr(loader, attrname):
434                 fullname = getattr(loader, attrname)
435             else:
436                 continue
437
438             if isinstance(fullname, str) and fullname != '__main__':
439                 # Module loaded via: runpy -m
440                 return fullname
441
442         # Script as first argument to Python command line.
443         inspectedname = inspect.getmodulename(filename)
444         if inspectedname is not None:
445             return inspectedname
446         else:
447             return dunder_name
448
449     def _should_trace_internal(self, filename, frame):
450         """Decide whether to trace execution in `filename`, with a reason.
451
452         This function is called from the trace function.  As each new file name
453         is encountered, this function determines whether it is traced or not.
454
455         Returns a FileDisposition object.
456
457         """
458         original_filename = filename
459         disp = _disposition_init(self.collector.file_disposition_class, filename)
460
461         def nope(disp, reason):
462             """Simple helper to make it easy to return NO."""
463             disp.trace = False
464             disp.reason = reason
465             return disp
466
467         # Compiled Python files have two file names: frame.f_code.co_filename is
468         # the file name at the time the .pyc was compiled.  The second name is
469         # __file__, which is where the .pyc was actually loaded from.  Since
470         # .pyc files can be moved after compilation (for example, by being
471         # installed), we look for __file__ in the frame and prefer it to the
472         # co_filename value.
473         dunder_file = frame.f_globals.get('__file__')
474         if dunder_file:
475             filename = self._source_for_file(dunder_file)
476             if original_filename and not original_filename.startswith('<'):
477                 orig = os.path.basename(original_filename)
478                 if orig != os.path.basename(filename):
479                     # Files shouldn't be renamed when moved. This happens when
480                     # exec'ing code.  If it seems like something is wrong with
481                     # the frame's file name, then just use the original.
482                     filename = original_filename
483
484         if not filename:
485             # Empty string is pretty useless.
486             return nope(disp, "empty string isn't a file name")
487
488         if filename.startswith('memory:'):
489             return nope(disp, "memory isn't traceable")
490
491         if filename.startswith('<'):
492             # Lots of non-file execution is represented with artificial
493             # file names like "<string>", "<doctest readme.txt[0]>", or
494             # "<exec_function>".  Don't ever trace these executions, since we
495             # can't do anything with the data later anyway.
496             return nope(disp, "not a real file name")
497
498         # pyexpat does a dumb thing, calling the trace function explicitly from
499         # C code with a C file name.
500         if re.search(r"[/\\]Modules[/\\]pyexpat.c", filename):
501             return nope(disp, "pyexpat lies about itself")
502
503         # Jython reports the .class file to the tracer, use the source file.
504         if filename.endswith("$py.class"):
505             filename = filename[:-9] + ".py"
506
507         canonical = files.canonical_filename(filename)
508         disp.canonical_filename = canonical
509
510         # Try the plugins, see if they have an opinion about the file.
511         plugin = None
512         for plugin in self.plugins.file_tracers:
513             if not plugin._coverage_enabled:
514                 continue
515
516             try:
517                 file_tracer = plugin.file_tracer(canonical)
518                 if file_tracer is not None:
519                     file_tracer._coverage_plugin = plugin
520                     disp.trace = True
521                     disp.file_tracer = file_tracer
522                     if file_tracer.has_dynamic_source_filename():
523                         disp.has_dynamic_filename = True
524                     else:
525                         disp.source_filename = files.canonical_filename(
526                             file_tracer.source_filename()
527                         )
528                     break
529             except Exception:
530                 self._warn(
531                     "Disabling plugin %r due to an exception:" % (
532                         plugin._coverage_plugin_name
533                     )
534                 )
535                 traceback.print_exc()
536                 plugin._coverage_enabled = False
537                 continue
538         else:
539             # No plugin wanted it: it's Python.
540             disp.trace = True
541             disp.source_filename = canonical
542
543         if not disp.has_dynamic_filename:
544             if not disp.source_filename:
545                 raise CoverageException(
546                     "Plugin %r didn't set source_filename for %r" %
547                     (plugin, disp.original_filename)
548                 )
549             reason = self._check_include_omit_etc_internal(
550                 disp.source_filename, frame,
551             )
552             if reason:
553                 nope(disp, reason)
554
555         return disp
556
557     def _check_include_omit_etc_internal(self, filename, frame):
558         """Check a file name against the include, omit, etc, rules.
559
560         Returns a string or None.  String means, don't trace, and is the reason
561         why.  None means no reason found to not trace.
562
563         """
564         modulename = self._name_for_module(frame.f_globals, filename)
565
566         # If the user specified source or include, then that's authoritative
567         # about the outer bound of what to measure and we don't have to apply
568         # any canned exclusions. If they didn't, then we have to exclude the
569         # stdlib and coverage.py directories.
570         if self.source_match:
571             if self.source_pkgs_match.match(modulename):
572                 if modulename in self.source_pkgs:
573                     self.source_pkgs.remove(modulename)
574                 return None  # There's no reason to skip this file.
575
576             if not self.source_match.match(filename):
577                 return "falls outside the --source trees"
578         elif self.include_match:
579             if not self.include_match.match(filename):
580                 return "falls outside the --include trees"
581         else:
582             # If we aren't supposed to trace installed code, then check if this
583             # is near the Python standard library and skip it if so.
584             if self.pylib_match and self.pylib_match.match(filename):
585                 return "is in the stdlib"
586
587             # We exclude the coverage.py code itself, since a little of it
588             # will be measured otherwise.
589             if self.cover_match and self.cover_match.match(filename):
590                 return "is part of coverage.py"
591
592         # Check the file against the omit pattern.
593         if self.omit_match and self.omit_match.match(filename):
594             return "is inside an --omit pattern"
595
596         # No reason found to skip this file.
597         return None
598
599     def _should_trace(self, filename, frame):
600         """Decide whether to trace execution in `filename`.
601
602         Calls `_should_trace_internal`, and returns the FileDisposition.
603
604         """
605         disp = self._should_trace_internal(filename, frame)
606         if self.debug.should('trace'):
607             self.debug.write(_disposition_debug_msg(disp))
608         return disp
609
610     def _check_include_omit_etc(self, filename, frame):
611         """Check a file name against the include/omit/etc, rules, verbosely.
612
613         Returns a boolean: True if the file should be traced, False if not.
614
615         """
616         reason = self._check_include_omit_etc_internal(filename, frame)
617         if self.debug.should('trace'):
618             if not reason:
619                 msg = "Including %r" % (filename,)
620             else:
621                 msg = "Not including %r: %s" % (filename, reason)
622             self.debug.write(msg)
623
624         return not reason
625
626     def _warn(self, msg):
627         """Use `msg` as a warning."""
628         self._warnings.append(msg)
629         if self.debug.should('pid'):
630             msg = "[%d] %s" % (os.getpid(), msg)
631         sys.stderr.write("Coverage.py warning: %s\n" % msg)
632
633     def get_option(self, option_name):
634         """Get an option from the configuration.
635
636         `option_name` is a colon-separated string indicating the section and
637         option name.  For example, the ``branch`` option in the ``[run]``
638         section of the config file would be indicated with `"run:branch"`.
639
640         Returns the value of the option.
641
642         .. versionadded:: 4.0
643
644         """
645         return self.config.get_option(option_name)
646
647     def set_option(self, option_name, value):
648         """Set an option in the configuration.
649
650         `option_name` is a colon-separated string indicating the section and
651         option name.  For example, the ``branch`` option in the ``[run]``
652         section of the config file would be indicated with ``"run:branch"``.
653
654         `value` is the new value for the option.  This should be a Python
655         value where appropriate.  For example, use True for booleans, not the
656         string ``"True"``.
657
658         As an example, calling::
659
660             cov.set_option("run:branch", True)
661
662         has the same effect as this configuration file::
663
664             [run]
665             branch = True
666
667         .. versionadded:: 4.0
668
669         """
670         self.config.set_option(option_name, value)
671
672     def use_cache(self, usecache):
673         """Obsolete method."""
674         self._init()
675         if not usecache:
676             self._warn("use_cache(False) is no longer supported.")
677
678     def load(self):
679         """Load previously-collected coverage data from the data file."""
680         self._init()
681         self.collector.reset()
682         self.data_files.read(self.data)
683
684     def start(self):
685         """Start measuring code coverage.
686
687         Coverage measurement actually occurs in functions called after
688         :meth:`start` is invoked.  Statements in the same scope as
689         :meth:`start` won't be measured.
690
691         Once you invoke :meth:`start`, you must also call :meth:`stop`
692         eventually, or your process might not shut down cleanly.
693
694         """
695         self._init()
696         if self.run_suffix:
697             # Calling start() means we're running code, so use the run_suffix
698             # as the data_suffix when we eventually save the data.
699             self.data_suffix = self.run_suffix
700         if self._auto_data:
701             self.load()
702
703         self.collector.start()
704         self._started = True
705         self._measured = True
706
707     def stop(self):
708         """Stop measuring code coverage."""
709         if self._started:
710             self.collector.stop()
711         self._started = False
712
713     def _atexit(self):
714         """Clean up on process shutdown."""
715         if self._started:
716             self.stop()
717         if self._auto_data:
718             self.save()
719
720     def erase(self):
721         """Erase previously-collected coverage data.
722
723         This removes the in-memory data collected in this session as well as
724         discarding the data file.
725
726         """
727         self._init()
728         self.collector.reset()
729         self.data.erase()
730         self.data_files.erase(parallel=self.config.parallel)
731
732     def clear_exclude(self, which='exclude'):
733         """Clear the exclude list."""
734         self._init()
735         setattr(self.config, which + "_list", [])
736         self._exclude_regex_stale()
737
738     def exclude(self, regex, which='exclude'):
739         """Exclude source lines from execution consideration.
740
741         A number of lists of regular expressions are maintained.  Each list
742         selects lines that are treated differently during reporting.
743
744         `which` determines which list is modified.  The "exclude" list selects
745         lines that are not considered executable at all.  The "partial" list
746         indicates lines with branches that are not taken.
747
748         `regex` is a regular expression.  The regex is added to the specified
749         list.  If any of the regexes in the list is found in a line, the line
750         is marked for special treatment during reporting.
751
752         """
753         self._init()
754         excl_list = getattr(self.config, which + "_list")
755         excl_list.append(regex)
756         self._exclude_regex_stale()
757
758     def _exclude_regex_stale(self):
759         """Drop all the compiled exclusion regexes, a list was modified."""
760         self._exclude_re.clear()
761
762     def _exclude_regex(self, which):
763         """Return a compiled regex for the given exclusion list."""
764         if which not in self._exclude_re:
765             excl_list = getattr(self.config, which + "_list")
766             self._exclude_re[which] = join_regex(excl_list)
767         return self._exclude_re[which]
768
769     def get_exclude_list(self, which='exclude'):
770         """Return a list of excluded regex patterns.
771
772         `which` indicates which list is desired.  See :meth:`exclude` for the
773         lists that are available, and their meaning.
774
775         """
776         self._init()
777         return getattr(self.config, which + "_list")
778
779     def save(self):
780         """Save the collected coverage data to the data file."""
781         self._init()
782         self.get_data()
783         self.data_files.write(self.data, suffix=self.data_suffix)
784
785     def combine(self, data_paths=None):
786         """Combine together a number of similarly-named coverage data files.
787
788         All coverage data files whose name starts with `data_file` (from the
789         coverage() constructor) will be read, and combined together into the
790         current measurements.
791
792         `data_paths` is a list of files or directories from which data should
793         be combined. If no list is passed, then the data files from the
794         directory indicated by the current data file (probably the current
795         directory) will be combined.
796
797         .. versionadded:: 4.0
798             The `data_paths` parameter.
799
800         """
801         self._init()
802         self.get_data()
803
804         aliases = None
805         if self.config.paths:
806             aliases = PathAliases()
807             for paths in self.config.paths.values():
808                 result = paths[0]
809                 for pattern in paths[1:]:
810                     aliases.add(pattern, result)
811
812         self.data_files.combine_parallel_data(self.data, aliases=aliases, data_paths=data_paths)
813
814     def get_data(self):
815         """Get the collected data and reset the collector.
816
817         Also warn about various problems collecting data.
818
819         Returns a :class:`coverage.CoverageData`, the collected coverage data.
820
821         .. versionadded:: 4.0
822
823         """
824         self._init()
825         if not self._measured:
826             return self.data
827
828         self.collector.save_data(self.data)
829
830         # If there are still entries in the source_pkgs list, then we never
831         # encountered those packages.
832         if self._warn_unimported_source:
833             for pkg in self.source_pkgs:
834                 if pkg not in sys.modules:
835                     self._warn("Module %s was never imported." % pkg)
836                 elif not (
837                     hasattr(sys.modules[pkg], '__file__') and
838                     os.path.exists(sys.modules[pkg].__file__)
839                 ):
840                     self._warn("Module %s has no Python source." % pkg)
841                 else:
842                     self._warn("Module %s was previously imported, but not measured." % pkg)
843
844         # Find out if we got any data.
845         if not self.data and self._warn_no_data:
846             self._warn("No data was collected.")
847
848         # Find files that were never executed at all.
849         for src in self.source:
850             for py_file in find_python_files(src):
851                 py_file = files.canonical_filename(py_file)
852
853                 if self.omit_match and self.omit_match.match(py_file):
854                     # Turns out this file was omitted, so don't pull it back
855                     # in as unexecuted.
856                     continue
857
858                 self.data.touch_file(py_file)
859
860         if self.config.note:
861             self.data.add_run_info(note=self.config.note)
862
863         self._measured = False
864         return self.data
865
866     # Backward compatibility with version 1.
867     def analysis(self, morf):
868         """Like `analysis2` but doesn't return excluded line numbers."""
869         f, s, _, m, mf = self.analysis2(morf)
870         return f, s, m, mf
871
872     def analysis2(self, morf):
873         """Analyze a module.
874
875         `morf` is a module or a file name.  It will be analyzed to determine
876         its coverage statistics.  The return value is a 5-tuple:
877
878         * The file name for the module.
879         * A list of line numbers of executable statements.
880         * A list of line numbers of excluded statements.
881         * A list of line numbers of statements not run (missing from
882           execution).
883         * A readable formatted string of the missing line numbers.
884
885         The analysis uses the source file itself and the current measured
886         coverage data.
887
888         """
889         self._init()
890         analysis = self._analyze(morf)
891         return (
892             analysis.filename,
893             sorted(analysis.statements),
894             sorted(analysis.excluded),
895             sorted(analysis.missing),
896             analysis.missing_formatted(),
897             )
898
899     def _analyze(self, it):
900         """Analyze a single morf or code unit.
901
902         Returns an `Analysis` object.
903
904         """
905         self.get_data()
906         if not isinstance(it, FileReporter):
907             it = self._get_file_reporter(it)
908
909         return Analysis(self.data, it)
910
911     def _get_file_reporter(self, morf):
912         """Get a FileReporter for a module or file name."""
913         plugin = None
914         file_reporter = "python"
915
916         if isinstance(morf, string_class):
917             abs_morf = abs_file(morf)
918             plugin_name = self.data.file_tracer(abs_morf)
919             if plugin_name:
920                 plugin = self.plugins.get(plugin_name)
921
922         if plugin:
923             file_reporter = plugin.file_reporter(abs_morf)
924             if file_reporter is None:
925                 raise CoverageException(
926                     "Plugin %r did not provide a file reporter for %r." % (
927                         plugin._coverage_plugin_name, morf
928                     )
929                 )
930
931         if file_reporter == "python":
932             # pylint: disable=redefined-variable-type
933             file_reporter = PythonFileReporter(morf, self)
934
935         return file_reporter
936
937     def _get_file_reporters(self, morfs=None):
938         """Get a list of FileReporters for a list of modules or file names.
939
940         For each module or file name in `morfs`, find a FileReporter.  Return
941         the list of FileReporters.
942
943         If `morfs` is a single module or file name, this returns a list of one
944         FileReporter.  If `morfs` is empty or None, then the list of all files
945         measured is used to find the FileReporters.
946
947         """
948         if not morfs:
949             morfs = self.data.measured_files()
950
951         # Be sure we have a list.
952         if not isinstance(morfs, (list, tuple)):
953             morfs = [morfs]
954
955         file_reporters = []
956         for morf in morfs:
957             file_reporter = self._get_file_reporter(morf)
958             file_reporters.append(file_reporter)
959
960         return file_reporters
961
962     def report(
963         self, morfs=None, show_missing=None, ignore_errors=None,
964         file=None,                  # pylint: disable=redefined-builtin
965         omit=None, include=None, skip_covered=None,
966     ):
967         """Write a summary report to `file`.
968
969         Each module in `morfs` is listed, with counts of statements, executed
970         statements, missing statements, and a list of lines missed.
971
972         `include` is a list of file name patterns.  Files that match will be
973         included in the report. Files matching `omit` will not be included in
974         the report.
975
976         Returns a float, the total percentage covered.
977
978         """
979         self.get_data()
980         self.config.from_args(
981             ignore_errors=ignore_errors, omit=omit, include=include,
982             show_missing=show_missing, skip_covered=skip_covered,
983             )
984         reporter = SummaryReporter(self, self.config)
985         return reporter.report(morfs, outfile=file)
986
987     def annotate(
988         self, morfs=None, directory=None, ignore_errors=None,
989         omit=None, include=None,
990     ):
991         """Annotate a list of modules.
992
993         Each module in `morfs` is annotated.  The source is written to a new
994         file, named with a ",cover" suffix, with each line prefixed with a
995         marker to indicate the coverage of the line.  Covered lines have ">",
996         excluded lines have "-", and missing lines have "!".
997
998         See :meth:`report` for other arguments.
999
1000         """
1001         self.get_data()
1002         self.config.from_args(
1003             ignore_errors=ignore_errors, omit=omit, include=include
1004             )
1005         reporter = AnnotateReporter(self, self.config)
1006         reporter.report(morfs, directory=directory)
1007
1008     def html_report(self, morfs=None, directory=None, ignore_errors=None,
1009                     omit=None, include=None, extra_css=None, title=None):
1010         """Generate an HTML report.
1011
1012         The HTML is written to `directory`.  The file "index.html" is the
1013         overview starting point, with links to more detailed pages for
1014         individual modules.
1015
1016         `extra_css` is a path to a file of other CSS to apply on the page.
1017         It will be copied into the HTML directory.
1018
1019         `title` is a text string (not HTML) to use as the title of the HTML
1020         report.
1021
1022         See :meth:`report` for other arguments.
1023
1024         Returns a float, the total percentage covered.
1025
1026         """
1027         self.get_data()
1028         self.config.from_args(
1029             ignore_errors=ignore_errors, omit=omit, include=include,
1030             html_dir=directory, extra_css=extra_css, html_title=title,
1031             )
1032         reporter = HtmlReporter(self, self.config)
1033         return reporter.report(morfs)
1034
1035     def xml_report(
1036         self, morfs=None, outfile=None, ignore_errors=None,
1037         omit=None, include=None,
1038     ):
1039         """Generate an XML report of coverage results.
1040
1041         The report is compatible with Cobertura reports.
1042
1043         Each module in `morfs` is included in the report.  `outfile` is the
1044         path to write the file to, "-" will write to stdout.
1045
1046         See :meth:`report` for other arguments.
1047
1048         Returns a float, the total percentage covered.
1049
1050         """
1051         self.get_data()
1052         self.config.from_args(
1053             ignore_errors=ignore_errors, omit=omit, include=include,
1054             xml_output=outfile,
1055             )
1056         file_to_close = None
1057         delete_file = False
1058         if self.config.xml_output:
1059             if self.config.xml_output == '-':
1060                 outfile = sys.stdout
1061             else:
1062                 # Ensure that the output directory is created; done here
1063                 # because this report pre-opens the output file.
1064                 # HTMLReport does this using the Report plumbing because
1065                 # its task is more complex, being multiple files.
1066                 output_dir = os.path.dirname(self.config.xml_output)
1067                 if output_dir and not os.path.isdir(output_dir):
1068                     os.makedirs(output_dir)
1069                 open_kwargs = {}
1070                 if env.PY3:
1071                     open_kwargs['encoding'] = 'utf8'
1072                 outfile = open(self.config.xml_output, "w", **open_kwargs)
1073                 file_to_close = outfile
1074         try:
1075             reporter = XmlReporter(self, self.config)
1076             return reporter.report(morfs, outfile=outfile)
1077         except CoverageException:
1078             delete_file = True
1079             raise
1080         finally:
1081             if file_to_close:
1082                 file_to_close.close()
1083                 if delete_file:
1084                     file_be_gone(self.config.xml_output)
1085
1086     def sys_info(self):
1087         """Return a list of (key, value) pairs showing internal information."""
1088
1089         import coverage as covmod
1090
1091         self._init()
1092
1093         ft_plugins = []
1094         for ft in self.plugins.file_tracers:
1095             ft_name = ft._coverage_plugin_name
1096             if not ft._coverage_enabled:
1097                 ft_name += " (disabled)"
1098             ft_plugins.append(ft_name)
1099
1100         info = [
1101             ('version', covmod.__version__),
1102             ('coverage', covmod.__file__),
1103             ('cover_dirs', self.cover_dirs),
1104             ('pylib_dirs', self.pylib_dirs),
1105             ('tracer', self.collector.tracer_name()),
1106             ('plugins.file_tracers', ft_plugins),
1107             ('config_files', self.config.attempted_config_files),
1108             ('configs_read', self.config.config_files),
1109             ('data_path', self.data_files.filename),
1110             ('python', sys.version.replace('\n', '')),
1111             ('platform', platform.platform()),
1112             ('implementation', platform.python_implementation()),
1113             ('executable', sys.executable),
1114             ('cwd', os.getcwd()),
1115             ('path', sys.path),
1116             ('environment', sorted(
1117                 ("%s = %s" % (k, v))
1118                 for k, v in iitems(os.environ)
1119                 if k.startswith(("COV", "PY"))
1120             )),
1121             ('command_line', " ".join(getattr(sys, 'argv', ['???']))),
1122             ]
1123
1124         matcher_names = [
1125             'source_match', 'source_pkgs_match',
1126             'include_match', 'omit_match',
1127             'cover_match', 'pylib_match',
1128             ]
1129
1130         for matcher_name in matcher_names:
1131             matcher = getattr(self, matcher_name)
1132             if matcher:
1133                 matcher_info = matcher.info()
1134             else:
1135                 matcher_info = '-none-'
1136             info.append((matcher_name, matcher_info))
1137
1138         return info
1139
1140
1141 # FileDisposition "methods": FileDisposition is a pure value object, so it can
1142 # be implemented in either C or Python.  Acting on them is done with these
1143 # functions.
1144
1145 def _disposition_init(cls, original_filename):
1146     """Construct and initialize a new FileDisposition object."""
1147     disp = cls()
1148     disp.original_filename = original_filename
1149     disp.canonical_filename = original_filename
1150     disp.source_filename = None
1151     disp.trace = False
1152     disp.reason = ""
1153     disp.file_tracer = None
1154     disp.has_dynamic_filename = False
1155     return disp
1156
1157
1158 def _disposition_debug_msg(disp):
1159     """Make a nice debug message of what the FileDisposition is doing."""
1160     if disp.trace:
1161         msg = "Tracing %r" % (disp.original_filename,)
1162         if disp.file_tracer:
1163             msg += ": will be traced by %r" % disp.file_tracer
1164     else:
1165         msg = "Not tracing %r: %s" % (disp.original_filename, disp.reason)
1166     return msg
1167
1168
1169 def process_startup():
1170     """Call this at Python start-up to perhaps measure coverage.
1171
1172     If the environment variable COVERAGE_PROCESS_START is defined, coverage
1173     measurement is started.  The value of the variable is the config file
1174     to use.
1175
1176     There are two ways to configure your Python installation to invoke this
1177     function when Python starts:
1178
1179     #. Create or append to sitecustomize.py to add these lines::
1180
1181         import coverage
1182         coverage.process_startup()
1183
1184     #. Create a .pth file in your Python installation containing::
1185
1186         import coverage; coverage.process_startup()
1187
1188     Returns the :class:`Coverage` instance that was started, or None if it was
1189     not started by this call.
1190
1191     """
1192     cps = os.environ.get("COVERAGE_PROCESS_START")
1193     if not cps:
1194         # No request for coverage, nothing to do.
1195         return None
1196
1197     # This function can be called more than once in a process. This happens
1198     # because some virtualenv configurations make the same directory visible
1199     # twice in sys.path.  This means that the .pth file will be found twice,
1200     # and executed twice, executing this function twice.  We set a global
1201     # flag (an attribute on this function) to indicate that coverage.py has
1202     # already been started, so we can avoid doing it twice.
1203     #
1204     # https://bitbucket.org/ned/coveragepy/issue/340/keyerror-subpy has more
1205     # details.
1206
1207     if hasattr(process_startup, "coverage"):
1208         # We've annotated this function before, so we must have already
1209         # started coverage.py in this process.  Nothing to do.
1210         return None
1211
1212     cov = Coverage(config_file=cps, auto_data=True)
1213     process_startup.coverage = cov
1214     cov.start()
1215     cov._warn_no_data = False
1216     cov._warn_unimported_source = False
1217
1218     return cov
1219
1220
1221 def _prevent_sub_process_measurement():
1222     """Stop any subprocess auto-measurement from writing data."""
1223     auto_created_coverage = getattr(process_startup, "coverage", None)
1224     if auto_created_coverage is not None:
1225         auto_created_coverage._auto_data = False