def start(self): if self.run_suffix: self.data_suffix = self.run_suffix if self.auto_data: self.load() if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) else: if self.cover_dir: self.cover_match = TreeMatcher([self.cover_dir]) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) if self.debug.should('config'): self.debug.write('Configuration values:') config_info = sorted(self.config.__dict__.items()) self.debug.write_formatted_info(config_info) if self.debug.should('sys'): self.debug.write('Debugging info:') self.debug.write_formatted_info(self.sysinfo()) self.collector.start() self._started = True self._measured = True
def start(self): """Start measuring code coverage.""" if self.run_suffix: # Calling start() means we're running code, so use the run_suffix # as the data_suffix when we eventually save the data. self.data_suffix = self.run_suffix if self.auto_data: self.load() # Save coverage data when Python exits. if not self.atexit_registered: atexit.register(self.save) self.atexit_registered = True # Create the matchers we need for _should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) else: if self.cover_dir: self.cover_match = TreeMatcher([self.cover_dir]) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) self._harvested = False self.collector.start()
def start(self): """Start measuring code coverage. Coverage measurement actually occurs in functions called after `start` is invoked. Statements in the same scope as `start` won't be measured. Once you invoke `start`, you must also call `stop` eventually, or your process might not shut down cleanly. """ if self.run_suffix: # Calling start() means we're running code, so use the run_suffix # as the data_suffix when we eventually save the data. self.data_suffix = self.run_suffix if self.auto_data: self.load() # Create the matchers we need for _should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) else: if self.cover_dir: self.cover_match = TreeMatcher([self.cover_dir]) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) self._harvested = False self.collector.start() self._started = True
def find_file_reporters(self, morfs): """Find the FileReporters we'll report on. `morfs` is a list of modules or file names. """ self.file_reporters = self.coverage._get_file_reporters(morfs) if self.config.include: patterns = prep_patterns(self.config.include) matcher = FnmatchMatcher(patterns) filtered = [] for fr in self.file_reporters: if matcher.match(fr.filename): filtered.append(fr) self.file_reporters = filtered if self.config.omit: patterns = prep_patterns(self.config.omit) matcher = FnmatchMatcher(patterns) filtered = [] for fr in self.file_reporters: if not matcher.match(fr.filename): filtered.append(fr) self.file_reporters = filtered self.file_reporters.sort()
def find_code_units(self, morfs): """Find the code units we'll report on. `morfs` is a list of modules or filenames. """ morfs = morfs or self.coverage.data.measured_files() file_locator = self.coverage.file_locator get_ext = self.coverage.data.extension_data().get self.code_units = code_unit_factory(morfs, file_locator, get_ext) if self.config.include: patterns = prep_patterns(self.config.include) matcher = FnmatchMatcher(patterns) filtered = [] for cu in self.code_units: if matcher.match(cu.filename): filtered.append(cu) self.code_units = filtered if self.config.omit: patterns = prep_patterns(self.config.omit) matcher = FnmatchMatcher(patterns) filtered = [] for cu in self.code_units: if not matcher.match(cu.filename): filtered.append(cu) self.code_units = filtered self.code_units.sort()
def test_fnmatch_windows_paths(self): # We should be able to match Windows paths even if we are running on # a non-Windows OS. fnm = FnmatchMatcher(["*/foo.py"]) self.assertMatches(fnm, r"dir\foo.py", True) fnm = FnmatchMatcher([r"*\foo.py"]) self.assertMatches(fnm, r"dir\foo.py", True)
def start(self): """Start measuring code coverage. Coverage measurement actually occurs in functions called after `start` is invoked. Statements in the same scope as `start` won't be measured. Once you invoke `start`, you must also call `stop` eventually, or your process might not shut down cleanly. """ if self.run_suffix: self.data_suffix = self.run_suffix if self.auto_data: self.load() if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) else: if self.cover_dir: self.cover_match = TreeMatcher([self.cover_dir]) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) if self.debug.should('config'): self.debug.write('Configuration values:') config_info = sorted(self.config.__dict__.items()) self.debug.write_formatted_info(config_info) if self.debug.should('sys'): self.debug.write('Debugging info:') self.debug.write_formatted_info(self.sysinfo()) self.collector.start() self._started = True self._measured = True
def run(self, edit): view = self.view fname = view.file_name() if not fname: return cov_file = find(fname, '.coverage') if not cov_file: print 'Could not find .coverage file.' return # run analysis and find uncovered lines cov = coverage(data_file=cov_file) outlines = [] omit_matcher = FnmatchMatcher(cov.omit) if not omit_matcher.match(fname): cov_dir = os.path.dirname(cov_file) os.chdir(cov_dir) relpath = os.path.relpath(fname, cov_dir) cov.load() f, s, excluded, missing, m = cov.analysis2(relpath) for line in missing: outlines.append(view.full_line(view.text_point(line - 1, 0))) # update highlighted regions view.erase_regions('SublimePythonCoverage') if outlines: view.add_regions('SublimePythonCoverage', outlines, 'markup.inserted', 'bookmark', sublime.HIDDEN)
def run(self, edit): view = self.view view.erase_regions('SublimePythonCoverage') fname = view.file_name() if not fname: return cov_file = find(fname, '.coverage') if not cov_file: return False config_file = os.path.join(os.path.dirname(cov_file), '.coveragerc') flags = sublime.DRAW_EMPTY | sublime.DRAW_STIPPLED_UNDERLINE # run analysis and find uncovered lines cov = coverage(data_file=cov_file, config_file=config_file) outlines = [] omit_matcher = FnmatchMatcher(cov.omit) if not omit_matcher.match(fname): cov.load() f, s, excluded, missing, m = cov.analysis2(fname) for line in missing: outlines.append(view.full_line(view.text_point(line - 1, 0))) # update highlighted regions if outlines: view.add_regions('SublimePythonCoverage', outlines, 'coverage.missing', 'bookmark', flags)
def get_analysis_to_report(coverage, morfs): """Get the files to report on. For each morf in `morfs`, if it should be reported on (based on the omit and include configuration options), yield a pair, the `FileReporter` and `Analysis` for the morf. """ file_reporters = coverage._get_file_reporters(morfs) config = coverage.config if config.report_include: matcher = FnmatchMatcher(prep_patterns(config.report_include), "report_include") file_reporters = [ fr for fr in file_reporters if matcher.match(fr.filename) ] if config.report_omit: matcher = FnmatchMatcher(prep_patterns(config.report_omit), "report_omit") file_reporters = [ fr for fr in file_reporters if not matcher.match(fr.filename) ] if not file_reporters: raise CoverageException("No data to report.") for fr in sorted(file_reporters): try: analysis = coverage._analyze(fr) except NoSource: if not config.ignore_errors: raise except NotPython: # Only report errors for .py files, and only if we didn't # explicitly suppress those errors. # NotPython is only raised by PythonFileReporter, which has a # should_be_python() method. if fr.should_be_python(): if config.ignore_errors: msg = "Couldn't parse Python file '{}'".format(fr.filename) coverage._warn(msg, slug="couldnt-parse") else: raise else: yield (fr, analysis)
def start(self): """Start measuring code coverage. Coverage measurement actually occurs in functions called after `start` is invoked. Statements in the same scope as `start` won't be measured. Once you invoke `start`, you must also call `stop` eventually, or your process might not shut down cleanly. """ if self.run_suffix: # Calling start() means we're running code, so use the run_suffix # as the data_suffix when we eventually save the data. self.data_suffix = self.run_suffix if self.auto_data: self.load() # Create the matchers we need for _should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) else: if self.cover_dir: self.cover_match = TreeMatcher([self.cover_dir]) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) # The user may want to debug things, show info if desired. if self.debug.should('config'): self.debug.write("Configuration values:") config_info = sorted(self.config.__dict__.items()) self.debug.write_formatted_info(config_info) if self.debug.should('sys'): self.debug.write("Debugging info:") self.debug.write_formatted_info(self.sysinfo()) self.collector.start() self._started = True self._measured = True
def find_file_reporters(self, morfs): """Find the FileReporters we'll report on. `morfs` is a list of modules or file names. Returns a list of FileReporters. """ reporters = self.coverage._get_file_reporters(morfs) if self.config.include: matcher = FnmatchMatcher(prep_patterns(self.config.include)) reporters = [fr for fr in reporters if matcher.match(fr.filename)] if self.config.omit: matcher = FnmatchMatcher(prep_patterns(self.config.omit)) reporters = [fr for fr in reporters if not matcher.match(fr.filename)] self._file_reporters = sorted(reporters) return self._file_reporters
def test_fnmatch_matcher(self): matches_to_try = [ (self.make_file("sub/file1.py"), True), (self.make_file("sub/file2.c"), False), (self.make_file("sub2/file3.h"), True), (self.make_file("sub3/file4.py"), True), (self.make_file("sub3/file5.c"), False), ] fnm = FnmatchMatcher(["*.py", "*/sub2/*"]) self.assertEqual(fnm.info(), ["*.py", "*/sub2/*"]) for filepath, matches in matches_to_try: self.assertMatches(fnm, filepath, matches)
def test_fnmatch_matcher(self): file1 = self.make_file("sub/file1.py") file2 = self.make_file("sub/file2.c") file3 = self.make_file("sub2/file3.h") file4 = self.make_file("sub3/file4.py") file5 = self.make_file("sub3/file5.c") fl = FileLocator() fnm = FnmatchMatcher(["*.py", "*/sub2/*"]) self.assertTrue(fnm.match(fl.canonical_filename(file1))) self.assertFalse(fnm.match(fl.canonical_filename(file2))) self.assertTrue(fnm.match(fl.canonical_filename(file3))) self.assertTrue(fnm.match(fl.canonical_filename(file4))) self.assertFalse(fnm.match(fl.canonical_filename(file5)))
def filter_files(omit): """Read files from stdin, filter and yield passing ones.""" omit = prep_patterns(omit) omit_match = FnmatchMatcher(omit) while True: # Read filenames src = sys.stdin.readline() if src == '': break if omit_match.match(src): continue yield src.rstrip()
def get_lcov(self) -> str: """Get LCOV output This is shamelessly adapted from https://github.com/nedbat/coveragepy/blob/master/coverage/report.py """ output = "" file_reporters = self.cov_obj._get_file_reporters(None) config = self.cov_obj.config if config.report_include: matcher = FnmatchMatcher(prep_patterns(config.report_include), "report_include") file_reporters = [ fr for fr in file_reporters if matcher.match(fr.filename) ] if config.report_omit: matcher = FnmatchMatcher(prep_patterns(config.report_omit), "report_omit") file_reporters = [ fr for fr in file_reporters if not matcher.match(fr.filename) ] if not file_reporters: raise CoverageException("No data to report.") for fr in sorted(file_reporters): try: analysis = self.cov_obj._analyze(fr) token_lines = analysis.file_reporter.source_token_lines() if self.relative_path: filename = fr.relative_filename() else: filename = fr.filename output += "TN:\n" output += f"SF:{filename}\n" lines_hit = 0 for i, _ in enumerate(token_lines, 1): hits = get_hits(i, analysis) if hits is not None: if hits > 0: lines_hit += 1 output += f"DA:{i},{hits}\n" output += f"LF:{len(analysis.statements)}\n" output += f"LH:{lines_hit}\n" output += "end_of_record\n" except NoSource: if not config.ignore_errors: raise except NotPython: if fr.should_be_python(): if config.ignore_errors: msg = "Couldn't parse Python file '{}'".format( fr.filename) self.cov_obj._warn(msg, slug="couldnt-parse") else: raise return output
def configure(self, config): """Apply the configuration to get ready for decision-time.""" self.source_pkgs.extend(config.source_pkgs) for src in config.source or []: if os.path.isdir(src): self.source.append(canonical_filename(src)) else: self.source_pkgs.append(src) self.source_pkgs_unmatched = self.source_pkgs[:] self.omit = prep_patterns(config.run_omit) self.include = prep_patterns(config.run_include) # The directories for files considered "installed with the interpreter". self.pylib_paths = set() if not config.cover_pylib: # Look at where some standard modules are located. That's the # indication for "installed with the interpreter". In some # environments (virtualenv, for example), these modules may be # spread across a few locations. Look at all the candidate modules # we've imported, and take all the different ones. for m in (atexit, inspect, os, platform, _pypy_irc_topic, re, _structseq, traceback): if m is not None and hasattr(m, "__file__"): self.pylib_paths.add(canonical_path(m, directory=True)) if _structseq and not hasattr(_structseq, '__file__'): # PyPy 2.4 has no __file__ in the builtin modules, but the code # objects still have the file names. So dig into one to find # the path to exclude. The "filename" might be synthetic, # don't be fooled by those. structseq_file = code_object(_structseq.structseq_new).co_filename if not structseq_file.startswith("<"): self.pylib_paths.add(canonical_path(structseq_file)) # To avoid tracing the coverage.py code itself, we skip anything # located where we are. self.cover_paths = [canonical_path(__file__, directory=True)] if env.TESTING: # Don't include our own test code. self.cover_paths.append(os.path.join(self.cover_paths[0], "tests")) # When testing, we use PyContracts, which should be considered # part of coverage.py, and it uses six. Exclude those directories # just as we exclude ourselves. import contracts import six for mod in [contracts, six]: self.cover_paths.append(canonical_path(mod)) def debug(msg): if self.debug: self.debug.write(msg) # Create the matchers we need for should_trace if self.source or self.source_pkgs: against = [] if self.source: self.source_match = TreeMatcher(self.source) against.append("trees {!r}".format(self.source_match)) if self.source_pkgs: self.source_pkgs_match = ModuleMatcher(self.source_pkgs) against.append("modules {!r}".format(self.source_pkgs_match)) debug("Source matching against " + " and ".join(against)) else: if self.cover_paths: self.cover_match = TreeMatcher(self.cover_paths) debug("Coverage code matching: {!r}".format(self.cover_match)) if self.pylib_paths: self.pylib_match = TreeMatcher(self.pylib_paths) debug("Python stdlib matching: {!r}".format(self.pylib_match)) if self.include: self.include_match = FnmatchMatcher(self.include) debug("Include matching: {!r}".format(self.include_match)) if self.omit: self.omit_match = FnmatchMatcher(self.omit) debug("Omit matching: {!r}".format(self.omit_match))
def _init(self): """Set all the initial state. This is called by the public methods to initialize state. This lets us construct a :class:`Coverage` object, then tweak its state before this function is called. """ if self._inited: return # Create and configure the debugging controller. COVERAGE_DEBUG_FILE # is an environment variable, the name of a file to append debug logs # to. if self._debug_file is None: debug_file_name = os.environ.get("COVERAGE_DEBUG_FILE") if debug_file_name: self._debug_file = open(debug_file_name, "a") else: self._debug_file = sys.stderr self.debug = DebugControl(self.config.debug, self._debug_file) # Load plugins self.plugins = Plugins.load_plugins(self.config.plugins, self.config, self.debug) # _exclude_re is a dict that maps exclusion list names to compiled # regexes. self._exclude_re = {} self._exclude_regex_stale() files.set_relative_directory() # The source argument can be directories or package names. self.source = [] self.source_pkgs = [] for src in self.config.source or []: if os.path.exists(src): self.source.append(files.canonical_filename(src)) else: self.source_pkgs.append(src) self.omit = prep_patterns(self.config.omit) self.include = prep_patterns(self.config.include) concurrency = self.config.concurrency if concurrency == "multiprocessing": patch_multiprocessing() concurrency = None self.collector = Collector( should_trace=self._should_trace, check_include=self._check_include_omit_etc, timid=self.config.timid, branch=self.config.branch, warn=self._warn, concurrency=concurrency, ) # Early warning if we aren't going to be able to support plugins. if self.plugins.file_tracers and not self.collector.supports_plugins: self._warn("Plugin file tracers (%s) aren't supported with %s" % ( ", ".join(plugin._coverage_plugin_name for plugin in self.plugins.file_tracers), self.collector.tracer_name(), )) for plugin in self.plugins.file_tracers: plugin._coverage_enabled = False # Suffixes are a bit tricky. We want to use the data suffix only when # collecting data, not when combining data. So we save it as # `self.run_suffix` now, and promote it to `self.data_suffix` if we # find that we are collecting data later. if self._data_suffix or self.config.parallel: if not isinstance(self._data_suffix, string_class): # if data_suffix=True, use .machinename.pid.random self._data_suffix = True else: self._data_suffix = None self.data_suffix = None self.run_suffix = self._data_suffix # Create the data file. We do this at construction time so that the # data file will be written into the directory where the process # started rather than wherever the process eventually chdir'd to. self.data = CoverageData(debug=self.debug) self.data_files = CoverageDataFiles(basename=self.config.data_file) # The directories for files considered "installed with the interpreter". self.pylib_dirs = set() if not self.config.cover_pylib: # Look at where some standard modules are located. That's the # indication for "installed with the interpreter". In some # environments (virtualenv, for example), these modules may be # spread across a few locations. Look at all the candidate modules # we've imported, and take all the different ones. for m in (atexit, inspect, os, platform, _structseq, traceback): if m is not None and hasattr(m, "__file__"): self.pylib_dirs.add(self._canonical_dir(m)) if _structseq and not hasattr(_structseq, '__file__'): # PyPy 2.4 has no __file__ in the builtin modules, but the code # objects still have the file names. So dig into one to find # the path to exclude. structseq_new = _structseq.structseq_new try: structseq_file = structseq_new.func_code.co_filename except AttributeError: structseq_file = structseq_new.__code__.co_filename self.pylib_dirs.add(self._canonical_dir(structseq_file)) # To avoid tracing the coverage.py code itself, we skip anything # located where we are. self.cover_dirs = [self._canonical_dir(__file__)] if env.TESTING: # When testing, we use PyContracts, which should be considered # part of coverage.py, and it uses six. Exclude those directories # just as we exclude ourselves. import contracts, six for mod in [contracts, six]: self.cover_dirs.append(self._canonical_dir(mod)) # Set the reporting precision. Numbers.set_precision(self.config.precision) atexit.register(self._atexit) self._inited = True # Create the matchers we need for _should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) self.source_pkgs_match = ModuleMatcher(self.source_pkgs) else: if self.cover_dirs: self.cover_match = TreeMatcher(self.cover_dirs) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) # The user may want to debug things, show info if desired. wrote_any = False if self.debug.should('config'): config_info = sorted(self.config.__dict__.items()) self.debug.write_formatted_info("config", config_info) wrote_any = True if self.debug.should('sys'): self.debug.write_formatted_info("sys", self.sys_info()) for plugin in self.plugins: header = "sys: " + plugin._coverage_plugin_name info = plugin.sys_info() self.debug.write_formatted_info(header, info) wrote_any = True if wrote_any: self.debug.write_formatted_info("end", ())
def configure(self, config): """Apply the configuration to get ready for decision-time.""" self.source_pkgs.extend(config.source_pkgs) for src in config.source or []: if os.path.isdir(src): self.source.append(canonical_filename(src)) else: self.source_pkgs.append(src) self.source_pkgs_unmatched = self.source_pkgs[:] self.omit = prep_patterns(config.run_omit) self.include = prep_patterns(config.run_include) # The directories for files considered "installed with the interpreter". self.pylib_paths = set() if not config.cover_pylib: add_stdlib_paths(self.pylib_paths) # To avoid tracing the coverage.py code itself, we skip anything # located where we are. self.cover_paths = set() add_coverage_paths(self.cover_paths) # Find where third-party packages are installed. self.third_paths = set() add_third_party_paths(self.third_paths) def debug(msg): if self.debug: self.debug.write(msg) # Generally useful information debug("sys.path:" + "".join(f"\n {p}" for p in sys.path)) # Create the matchers we need for should_trace if self.source or self.source_pkgs: against = [] if self.source: self.source_match = TreeMatcher(self.source, "source") against.append(f"trees {self.source_match!r}") if self.source_pkgs: self.source_pkgs_match = ModuleMatcher(self.source_pkgs, "source_pkgs") against.append(f"modules {self.source_pkgs_match!r}") debug("Source matching against " + " and ".join(against)) else: if self.pylib_paths: self.pylib_match = TreeMatcher(self.pylib_paths, "pylib") debug(f"Python stdlib matching: {self.pylib_match!r}") if self.include: self.include_match = FnmatchMatcher(self.include, "include") debug(f"Include matching: {self.include_match!r}") if self.omit: self.omit_match = FnmatchMatcher(self.omit, "omit") debug(f"Omit matching: {self.omit_match!r}") self.cover_match = TreeMatcher(self.cover_paths, "coverage") debug(f"Coverage code matching: {self.cover_match!r}") self.third_match = TreeMatcher(self.third_paths, "third") debug(f"Third-party lib matching: {self.third_match!r}") # Check if the source we want to measure has been installed as a # third-party package. with sys_modules_saved(): for pkg in self.source_pkgs: try: modfile, path = file_and_path_for_module(pkg) debug(f"Imported source package {pkg!r} as {modfile!r}") except CoverageException as exc: debug(f"Couldn't import source package {pkg!r}: {exc}") continue if modfile: if self.third_match.match(modfile): debug( f"Source is in third-party because of source_pkg {pkg!r} at {modfile!r}" ) self.source_in_third = True else: for pathdir in path: if self.third_match.match(pathdir): debug( f"Source is in third-party because of {pkg!r} path directory " + f"at {pathdir!r}") self.source_in_third = True for src in self.source: if self.third_match.match(src): debug( f"Source is in third-party because of source directory {src!r}" ) self.source_in_third = True
def report5(self, cov): # N.B. this method is 99% copied from the coverage source code; # unfortunately, the coverage v5 style of `get_analysis_to_report` # errors out entirely if any source file has issues -- which would be a # breaking change for us. In the interest of backwards compatibility, # I've copied their code here so we can maintain the same `coveralls` # API regardless of which `coverage` version is being used. # # TODO: deprecate the relevant APIs so we can just use the coverage # public API directly. # # from coverage.report import get_analysis_to_report # try: # for cu, analyzed in get_analysis_to_report(cov, None): # self.parse_file(cu, analyzed) # except NoSource: # # Note that this behavior must necessarily change between # # coverage<5 and coverage>=5, as we are no longer interweaving # # with get_analysis_to_report (a single exception breaks the # # whole loop) # log.warning('No source for at least one file') # except NotPython: # # Note that this behavior must necessarily change between # # coverage<5 and coverage>=5, as we are no longer interweaving # # with get_analysis_to_report (a single exception breaks the # # whole loop) # log.warning('A source file is not python') # except CoverageException as e: # if str(e) != 'No data to report.': # raise from coverage.files import FnmatchMatcher, prep_patterns # pylint: disable=import-outside-toplevel # get_analysis_to_report starts here; changes marked with TODOs file_reporters = cov._get_file_reporters(None) # pylint: disable=W0212 config = cov.config if config.report_include: matcher = FnmatchMatcher(prep_patterns(config.report_include)) file_reporters = [ fr for fr in file_reporters if matcher.match(fr.filename) ] if config.report_omit: matcher = FnmatchMatcher(prep_patterns(config.report_omit)) file_reporters = [ fr for fr in file_reporters if not matcher.match(fr.filename) ] # TODO: deprecate changes # if not file_reporters: # raise CoverageException("No data to report.") for fr in sorted(file_reporters): try: analysis = cov._analyze(fr) # pylint: disable=W0212 except NoSource: if not config.ignore_errors: # TODO: deprecate changes # raise log.warning('No source for %s', fr.filename) except NotPython: # Only report errors for .py files, and only if we didn't # explicitly suppress those errors. # NotPython is only raised by PythonFileReporter, which has a # should_be_python() method. if fr.should_be_python(): if config.ignore_errors: msg = "Couldn't parse Python file '{}'".format( fr.filename) cov._warn( msg, # pylint: disable=W0212 slug='couldnt-parse') else: # TODO: deprecate changes # raise log.warning('Source file is not python %s', fr.filename) else: # TODO: deprecate changes (well, this one is fine /shrug) # yield (fr, analysis) self.parse_file(fr, analysis)
def configure(self, config): for src in config.source or []: if os.path.isdir(src): self.source.append(canonical_filename(src)) else: self.source_pkgs.append(src) self.source_pkgs_unmatched = self.source_pkgs[:] self.omit = prep_patterns(config.run_omit) self.include = prep_patterns(config.run_include) # The directories for files considered "installed with the interpreter". self.pylib_paths = set() if not config.cover_pylib: # Look at where some standard modules are located. That's the # indication for "installed with the interpreter". In some # environments (virtualenv, for example), these modules may be # spread across a few locations. Look at all the candidate modules # we've imported, and take all the different ones. for m in (atexit, inspect, os, platform, _pypy_irc_topic, re, _structseq, traceback): if m is not None and hasattr(m, "__file__"): self.pylib_paths.add(canonical_path(m, directory=True)) if _structseq and not hasattr(_structseq, '__file__'): # PyPy 2.4 has no __file__ in the builtin modules, but the code # objects still have the file names. So dig into one to find # the path to exclude. structseq_new = _structseq.structseq_new try: structseq_file = structseq_new.func_code.co_filename except AttributeError: structseq_file = structseq_new.__code__.co_filename self.pylib_paths.add(canonical_path(structseq_file)) # To avoid tracing the coverage.py code itself, we skip anything # located where we are. self.cover_paths = [canonical_path(__file__, directory=True)] if env.TESTING: # Don't include our own test code. self.cover_paths.append(os.path.join(self.cover_paths[0], "tests")) # When testing, we use PyContracts, which should be considered # part of coverage.py, and it uses six. Exclude those directories # just as we exclude ourselves. import contracts import six for mod in [contracts, six]: self.cover_paths.append(canonical_path(mod)) # Create the matchers we need for should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) self.source_pkgs_match = ModuleMatcher(self.source_pkgs) else: if self.cover_paths: self.cover_match = TreeMatcher(self.cover_paths) if self.pylib_paths: self.pylib_match = TreeMatcher(self.pylib_paths) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit)
def configure(self, config): """Apply the configuration to get ready for decision-time.""" self.source_pkgs.extend(config.source_pkgs) for src in config.source or []: if os.path.isdir(src): self.source.append(canonical_filename(src)) else: self.source_pkgs.append(src) self.source_pkgs_unmatched = self.source_pkgs[:] self.omit = prep_patterns(config.run_omit) self.include = prep_patterns(config.run_include) # The directories for files considered "installed with the interpreter". self.pylib_paths = set() if not config.cover_pylib: add_stdlib_paths(self.pylib_paths) # To avoid tracing the coverage.py code itself, we skip anything # located where we are. self.cover_paths = set() add_coverage_paths(self.cover_paths) # Find where third-party packages are installed. self.third_paths = set() add_third_party_paths(self.third_paths) def debug(msg): if self.debug: self.debug.write(msg) # Create the matchers we need for should_trace if self.source or self.source_pkgs: against = [] if self.source: self.source_match = TreeMatcher(self.source, "source") against.append("trees {!r}".format(self.source_match)) if self.source_pkgs: self.source_pkgs_match = ModuleMatcher(self.source_pkgs, "source_pkgs") against.append("modules {!r}".format(self.source_pkgs_match)) debug("Source matching against " + " and ".join(against)) else: if self.pylib_paths: self.pylib_match = TreeMatcher(self.pylib_paths, "pylib") debug("Python stdlib matching: {!r}".format(self.pylib_match)) if self.include: self.include_match = FnmatchMatcher(self.include, "include") debug("Include matching: {!r}".format(self.include_match)) if self.omit: self.omit_match = FnmatchMatcher(self.omit, "omit") debug("Omit matching: {!r}".format(self.omit_match)) self.cover_match = TreeMatcher(self.cover_paths, "coverage") debug("Coverage code matching: {!r}".format(self.cover_match)) self.third_match = TreeMatcher(self.third_paths, "third") debug("Third-party lib matching: {!r}".format(self.third_match)) # Check if the source we want to measure has been installed as a # third-party package. for pkg in self.source_pkgs: try: modfile = file_for_module(pkg) debug("Imported {} as {}".format(pkg, modfile)) except CoverageException as exc: debug("Couldn't import {}: {}".format(pkg, exc)) continue if modfile and self.third_match.match(modfile): self.source_in_third = True for src in self.source: if self.third_match.match(src): self.source_in_third = True
def _init(self): """Set all the initial state. This is called by the public methods to initialize state. This lets us construct a Coverage object, then tweak its state before this function is called. """ from coverage import __version__ if self._inited: return # Create and configure the debugging controller. if self._debug_file is None: self._debug_file = sys.stderr self.debug = DebugControl(self.config.debug, self._debug_file) # Load plugins self.plugins = Plugins.load_plugins(self.config.plugins, self.config) # TEMPORARY, because the plugin support is implemented in PyTracer. # This will be removed when that support is moved into CTracer. if self.plugins: self._warn("Setting timid=True to support plugins.") self.config.timid = True self.file_tracers = [] for plugin in self.plugins: if overrides(plugin, "file_tracer", CoveragePlugin): self.file_tracers.append(plugin) self.file_tracers.append(None) # The Python case. # _exclude_re is a dict mapping exclusion list names to compiled # regexes. self._exclude_re = {} self._exclude_regex_stale() self.file_locator = FileLocator() # The source argument can be directories or package names. self.source = [] self.source_pkgs = [] for src in self.config.source or []: if os.path.exists(src): self.source.append(self.file_locator.canonical_filename(src)) else: self.source_pkgs.append(src) self.omit = prep_patterns(self.config.omit) self.include = prep_patterns(self.config.include) self.collector = Collector( should_trace=self._should_trace, check_include=self._check_include_omit_etc, timid=self.config.timid, branch=self.config.branch, warn=self._warn, concurrency=self.config.concurrency, ) # Suffixes are a bit tricky. We want to use the data suffix only when # collecting data, not when combining data. So we save it as # `self.run_suffix` now, and promote it to `self.data_suffix` if we # find that we are collecting data later. if self._data_suffix or self.config.parallel: if not isinstance(self._data_suffix, string_class): # if data_suffix=True, use .machinename.pid.random self._data_suffix = True else: self._data_suffix = None self.data_suffix = None self.run_suffix = self._data_suffix # Create the data file. We do this at construction time so that the # data file will be written into the directory where the process # started rather than wherever the process eventually chdir'd to. self.data = CoverageData( basename=self.config.data_file, collector="coverage v%s" % __version__, debug=self.debug, ) # The dirs for files considered "installed with the interpreter". self.pylib_dirs = set() if not self.config.cover_pylib: # Look at where some standard modules are located. That's the # indication for "installed with the interpreter". In some # environments (virtualenv, for example), these modules may be # spread across a few locations. Look at all the candidate modules # we've imported, and take all the different ones. for m in (atexit, os, platform, random, socket, _structseq): if m is not None and hasattr(m, "__file__"): self.pylib_dirs.add(self._canonical_dir(m)) if _structseq and not hasattr(_structseq, '__file__'): # PyPy 2.4 has no __file__ in the builtin modules, but the code # objects still have the filenames. So dig into one to find # the path to exclude. structseq_new = _structseq.structseq_new try: structseq_file = structseq_new.func_code.co_filename except AttributeError: structseq_file = structseq_new.__code__.co_filename self.pylib_dirs.add(self._canonical_dir(structseq_file)) # To avoid tracing the coverage code itself, we skip anything located # where we are. self.cover_dir = self._canonical_dir(__file__) # Set the reporting precision. Numbers.set_precision(self.config.precision) atexit.register(self._atexit) self._inited = True # Create the matchers we need for _should_trace if self.source or self.source_pkgs: self.source_match = TreeMatcher(self.source) self.source_pkgs_match = ModuleMatcher(self.source_pkgs) else: if self.cover_dir: self.cover_match = TreeMatcher([self.cover_dir]) if self.pylib_dirs: self.pylib_match = TreeMatcher(self.pylib_dirs) if self.include: self.include_match = FnmatchMatcher(self.include) if self.omit: self.omit_match = FnmatchMatcher(self.omit) # The user may want to debug things, show info if desired. wrote_any = False if self.debug.should('config'): config_info = sorted(self.config.__dict__.items()) self.debug.write_formatted_info("config", config_info) wrote_any = True if self.debug.should('sys'): self.debug.write_formatted_info("sys", self.sys_info()) for plugin in self.plugins: header = "sys: " + plugin.plugin_name info = plugin.sys_info() self.debug.write_formatted_info(header, info) wrote_any = True if wrote_any: self.debug.write_formatted_info("end", ())
def test_fnmatch_matcher_overload(self): fnm = FnmatchMatcher(["*x%03d*.txt" % i for i in range(500)]) self.assertMatches(fnm, "x007foo.txt", True) self.assertMatches(fnm, "x123foo.txt", True) self.assertMatches(fnm, "x798bar.txt", False)