Exemplo n.º 1
0
    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()
Exemplo n.º 2
0
    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
        self.code_units = code_unit_factory(morfs, file_locator)

        if self.config.include:
            patterns = prep_patterns(self.config.include)
            filtered = []
            for cu in self.code_units:
                for pattern in patterns:
                    if fnmatch.fnmatch(cu.filename, pattern):
                        filtered.append(cu)
                        break
            self.code_units = filtered

        if self.config.omit:
            patterns = prep_patterns(self.config.omit)
            filtered = []
            for cu in self.code_units:
                for pattern in patterns:
                    if fnmatch.fnmatch(cu.filename, pattern):
                        break
                else:
                    filtered.append(cu)
            self.code_units = filtered

        self.code_units.sort()
Exemplo n.º 3
0
    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
        self.code_units = code_unit_factory(morfs, file_locator)

        if self.config.include:
            patterns = prep_patterns(self.config.include)
            filtered = []
            for cu in self.code_units:
                for pattern in patterns:
                    if fnmatch.fnmatch(cu.filename, pattern):
                        filtered.append(cu)
                        break
            self.code_units = filtered

        if self.config.omit:
            patterns = prep_patterns(self.config.omit)
            filtered = []
            for cu in self.code_units:
                for pattern in patterns:
                    if fnmatch.fnmatch(cu.filename, pattern):
                        break
                else:
                    filtered.append(cu)
            self.code_units = filtered

        self.code_units.sort()
Exemplo n.º 4
0
    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()
Exemplo n.º 5
0
    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()
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
    def find_file_reporters(self, morfs):
        """Find the FileReporters we'll report on.

        `morfs` is a list of modules or file names.

        """
        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)
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
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()
Exemplo n.º 10
0
    def __init__(self, data_file=None, data_suffix=None, cover_pylib=None,
                auto_data=False, timid=None, branch=None, config_file=True,
                source=None, omit=None, include=None, debug=None,
                debug_file=None, concurrency=None, plugins=None):
        """
        `data_file` is the base name of the data file to use, defaulting to
        ".coverage".  `data_suffix` is appended (with a dot) to `data_file` to
        create the final file name.  If `data_suffix` is simply True, then a
        suffix is created with the machine and process identity included.

        `cover_pylib` is a boolean determining whether Python code installed
        with the Python interpreter is measured.  This includes the Python
        standard library and any packages installed with the interpreter.

        If `auto_data` is true, then any existing data file will be read when
        coverage measurement starts, and data will be saved automatically when
        measurement stops.

        If `timid` is true, then a slower and simpler trace function will be
        used.  This is important for some environments where manipulation of
        tracing functions breaks the faster trace function.

        If `branch` is true, then branch coverage will be measured in addition
        to the usual statement coverage.

        `config_file` determines what config file to read.  If it is a string,
        it is the name of the config file to read.  If it is True, then a
        standard file is read (".coveragerc").  If it is False, then no file is
        read.

        `source` is a list of file paths or package names.  Only code located
        in the trees indicated by the file paths or package names will be
        measured.

        `include` and `omit` are lists of filename patterns. Files that match
        `include` will be measured, files that match `omit` will not.  Each
        will also accept a single string argument.

        `debug` is a list of strings indicating what debugging information is
        desired. `debug_file` is the file to write debug messages to,
        defaulting to stderr.

        `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", or
        "thread" (the default).

        `plugins` TODO.

        """
        from coverage import __version__

        # A record of all the warnings that have been issued.
        self._warnings = []

        # Build our configuration from a number of sources:
        # 1: defaults:
        self.config = CoverageConfig()

        # 2: from the .coveragerc or setup.cfg file:
        if config_file:
            did_read_rc = should_read_setupcfg = False
            if config_file is True:
                config_file = ".coveragerc"
                should_read_setupcfg = True
            try:
                did_read_rc = self.config.from_file(config_file)
            except ValueError as err:
                raise CoverageException(
                    "Couldn't read config file %s: %s" % (config_file, err)
                    )

            if not did_read_rc and should_read_setupcfg:
                self.config.from_file("setup.cfg", section_prefix="coverage:")

        # 3: from environment variables:
        self.config.from_environment('COVERAGE_OPTIONS')
        env_data_file = os.environ.get('COVERAGE_FILE')
        if env_data_file:
            self.config.data_file = env_data_file

        # 4: from constructor arguments:
        self.config.from_args(
            data_file=data_file, cover_pylib=cover_pylib, timid=timid,
            branch=branch, parallel=bool_or_none(data_suffix),
            source=source, omit=omit, include=include, debug=debug,
            concurrency=concurrency, plugins=plugins,
            )

        # Create and configure the debugging controller.
        self.debug = DebugControl(self.config.debug, debug_file or sys.stderr)

        # Load plugins
        self.plugins = Plugins.load_plugins(self.config.plugins, self.config)

        self.trace_judges = []
        for plugin in self.plugins:
            if plugin_implements(plugin, "trace_judge"):
                self.trace_judges.append(plugin)
        self.trace_judges.append(None)      # The Python case.

        self.auto_data = auto_data

        # _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._tracing_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 data_suffix or self.config.parallel:
            if not isinstance(data_suffix, string_class):
                # if data_suffix=True, use .machinename.pid.random
                data_suffix = True
        else:
            data_suffix = None
        self.data_suffix = None
        self.run_suffix = 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))

        # To avoid tracing the coverage code itself, we skip anything located
        # where we are.
        self.cover_dir = self._canonical_dir(__file__)

        # The matchers for _should_trace.
        self.source_match = None
        self.pylib_match = self.cover_match = None
        self.include_match = self.omit_match = None

        # Set the reporting precision.
        Numbers.set_precision(self.config.precision)

        # Is it ok for no data to be collected?
        self._warn_no_data = True
        self._warn_unimported_source = True

        # State machine variables:
        # Have we started collecting and not stopped it?
        self._started = False
        # Have we measured some data and not harvested it?
        self._measured = False

        atexit.register(self._atexit)
Exemplo n.º 11
0
    def __init__(self,
                 data_file=None,
                 data_suffix=None,
                 cover_pylib=None,
                 auto_data=False,
                 timid=None,
                 branch=None,
                 config_file=True,
                 source=None,
                 omit=None,
                 include=None):
        """
        `data_file` is the base name of the data file to use, defaulting to
        ".coverage".  `data_suffix` is appended (with a dot) to `data_file` to
        create the final file name.  If `data_suffix` is simply True, then a
        suffix is created with the machine and process identity included.

        `cover_pylib` is a boolean determining whether Python code installed
        with the Python interpreter is measured.  This includes the Python
        standard library and any packages installed with the interpreter.

        If `auto_data` is true, then any existing data file will be read when
        coverage measurement starts, and data will be saved automatically when
        measurement stops.

        If `timid` is true, then a slower and simpler trace function will be
        used.  This is important for some environments where manipulation of
        tracing functions breaks the faster trace function.

        If `branch` is true, then branch coverage will be measured in addition
        to the usual statement coverage.

        `config_file` determines what config file to read.  If it is a string,
        it is the name of the config file to read.  If it is True, then a
        standard file is read (".coveragerc").  If it is False, then no file is
        read.

        `source` is a list of file paths or package names.  Only code located
        in the trees indicated by the file paths or package names will be
        measured.

        `include` and `omit` are lists of filename patterns. Files that match
        `include` will be measured, files that match `omit` will not.  Each
        will also accept a single string argument.

        """
        from coverage import __version__

        # A record of all the warnings that have been issued.
        self._warnings = []

        # Build our configuration from a number of sources:
        # 1: defaults:
        self.config = CoverageConfig()

        # 2: from the coveragerc file:
        if config_file:
            if config_file is True:
                config_file = ".coveragerc"
            try:
                self.config.from_file(config_file)
            except ValueError:
                _, err, _ = sys.exc_info()
                raise CoverageException("Couldn't read config file %s: %s" %
                                        (config_file, err))

        # 3: from environment variables:
        self.config.from_environment('COVERAGE_OPTIONS')
        env_data_file = os.environ.get('COVERAGE_FILE')
        if env_data_file:
            self.config.data_file = env_data_file

        # 4: from constructor arguments:
        self.config.from_args(data_file=data_file,
                              cover_pylib=cover_pylib,
                              timid=timid,
                              branch=branch,
                              parallel=bool_or_none(data_suffix),
                              source=source,
                              omit=omit,
                              include=include)

        self.auto_data = auto_data

        # _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(self._should_trace,
                                   timid=self.config.timid,
                                   branch=self.config.branch,
                                   warn=self._warn)

        # 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 data_suffix or self.config.parallel:
            if not isinstance(data_suffix, string_class):
                # if data_suffix=True, use .machinename.pid.random
                data_suffix = True
        else:
            data_suffix = None
        self.data_suffix = None
        self.run_suffix = 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__)

        # The dirs for files considered "installed with the interpreter".
        self.pylib_dirs = []
        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, random, socket):
                if hasattr(m, "__file__"):
                    m_dir = self._canonical_dir(m)
                    if m_dir not in self.pylib_dirs:
                        self.pylib_dirs.append(m_dir)

        # To avoid tracing the coverage code itself, we skip anything located
        # where we are.
        self.cover_dir = self._canonical_dir(__file__)

        # The matchers for _should_trace, created when tracing starts.
        self.source_match = None
        self.pylib_match = self.cover_match = None
        self.include_match = self.omit_match = None

        # Only _harvest_data once per measurement cycle.
        self._harvested = False

        # Set the reporting precision.
        Numbers.set_precision(self.config.precision)

        # Is it ok for no data to be collected?
        self._warn_no_data = True
        self._started = False

        atexit.register(self._atexit)
Exemplo n.º 12
0
    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", ())
Exemplo n.º 13
0
    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
Exemplo n.º 14
0
    def __init__(self,
                 data_file=None,
                 data_suffix=None,
                 cover_pylib=None,
                 auto_data=False,
                 timid=None,
                 branch=None,
                 config_file=True,
                 source=None,
                 omit=None,
                 include=None,
                 debug=None,
                 debug_file=None):
        from coverage import __version__
        self._warnings = []
        self.config = CoverageConfig()
        if config_file:
            if config_file is True:
                config_file = '.coveragerc'
            try:
                self.config.from_file(config_file)
            except ValueError:
                _, err, _ = sys.exc_info()
                raise CoverageException("Couldn't read config file %s: %s" %
                                        (config_file, err))

        self.config.from_environment('COVERAGE_OPTIONS')
        env_data_file = os.environ.get('COVERAGE_FILE')
        if env_data_file:
            self.config.data_file = env_data_file
        self.config.from_args(data_file=data_file,
                              cover_pylib=cover_pylib,
                              timid=timid,
                              branch=branch,
                              parallel=bool_or_none(data_suffix),
                              source=source,
                              omit=omit,
                              include=include,
                              debug=debug)
        self.debug = DebugControl(self.config.debug, debug_file or sys.stderr)
        self.auto_data = auto_data
        self._exclude_re = {}
        self._exclude_regex_stale()
        self.file_locator = FileLocator()
        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(self._should_trace,
                                   timid=self.config.timid,
                                   branch=self.config.branch,
                                   warn=self._warn)
        if data_suffix or self.config.parallel:
            if not isinstance(data_suffix, string_class):
                data_suffix = True
        else:
            data_suffix = None
        self.data_suffix = None
        self.run_suffix = data_suffix
        self.data = CoverageData(basename=self.config.data_file,
                                 collector='coverage v%s' % __version__,
                                 debug=self.debug)
        self.pylib_dirs = []
        if not self.config.cover_pylib:
            for m in (atexit, os, random, socket, _structseq):
                if m is not None and hasattr(m, '__file__'):
                    m_dir = self._canonical_dir(m)
                    if m_dir not in self.pylib_dirs:
                        self.pylib_dirs.append(m_dir)

        self.cover_dir = self._canonical_dir(__file__)
        self.source_match = None
        self.pylib_match = self.cover_match = None
        self.include_match = self.omit_match = None
        Numbers.set_precision(self.config.precision)
        self._warn_no_data = True
        self._warn_unimported_source = True
        self._started = False
        self._measured = False
        atexit.register(self._atexit)
Exemplo n.º 15
0
    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", ())
Exemplo n.º 16
0
    def __init__(self, data_file = None, data_suffix = None, cover_pylib = None, auto_data = False, timid = None, branch = None, config_file = True, source = None, omit = None, include = None, debug = None, debug_file = None):
        from coverage import __version__
        self._warnings = []
        self.config = CoverageConfig()
        if config_file:
            if config_file is True:
                config_file = '.coveragerc'
            try:
                self.config.from_file(config_file)
            except ValueError:
                _, err, _ = sys.exc_info()
                raise CoverageException("Couldn't read config file %s: %s" % (config_file, err))

        self.config.from_environment('COVERAGE_OPTIONS')
        env_data_file = os.environ.get('COVERAGE_FILE')
        if env_data_file:
            self.config.data_file = env_data_file
        self.config.from_args(data_file=data_file, cover_pylib=cover_pylib, timid=timid, branch=branch, parallel=bool_or_none(data_suffix), source=source, omit=omit, include=include, debug=debug)
        self.debug = DebugControl(self.config.debug, debug_file or sys.stderr)
        self.auto_data = auto_data
        self._exclude_re = {}
        self._exclude_regex_stale()
        self.file_locator = FileLocator()
        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(self._should_trace, timid=self.config.timid, branch=self.config.branch, warn=self._warn)
        if data_suffix or self.config.parallel:
            if not isinstance(data_suffix, string_class):
                data_suffix = True
        else:
            data_suffix = None
        self.data_suffix = None
        self.run_suffix = data_suffix
        self.data = CoverageData(basename=self.config.data_file, collector='coverage v%s' % __version__, debug=self.debug)
        self.pylib_dirs = []
        if not self.config.cover_pylib:
            for m in (atexit,
             os,
             random,
             socket,
             _structseq):
                if m is not None and hasattr(m, '__file__'):
                    m_dir = self._canonical_dir(m)
                    if m_dir not in self.pylib_dirs:
                        self.pylib_dirs.append(m_dir)

        self.cover_dir = self._canonical_dir(__file__)
        self.source_match = None
        self.pylib_match = self.cover_match = None
        self.include_match = self.omit_match = None
        Numbers.set_precision(self.config.precision)
        self._warn_no_data = True
        self._warn_unimported_source = True
        self._started = False
        self._measured = False
        atexit.register(self._atexit)
Exemplo n.º 17
0
    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)
Exemplo n.º 18
0
    def configure(self, config):
        """Apply the configuration to get ready for decision-time."""
        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_new = _structseq.structseq_new
                try:
                    structseq_file = structseq_new.func_code.co_filename
                except AttributeError:
                    structseq_file = structseq_new.__code__.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))

        # 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)
Exemplo n.º 19
0
    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
Exemplo n.º 20
0
    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, warn=self._warn)

        # 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, re, _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", ())
Exemplo n.º 21
0
    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))
Exemplo n.º 22
0
    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)
Exemplo n.º 23
0
    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
Exemplo n.º 24
0
    def __init__(self,
                 data_file=None,
                 data_suffix=None,
                 cover_pylib=None,
                 auto_data=False,
                 timid=None,
                 branch=None,
                 config_file=True,
                 source=None,
                 omit=None,
                 include=None,
                 debug=None,
                 debug_file=None):
        """
        `data_file` is the base name of the data file to use, defaulting to
        ".coverage".  `data_suffix` is appended (with a dot) to `data_file` to
        create the final file name.  If `data_suffix` is simply True, then a
        suffix is created with the machine and process identity included.
        
        `cover_pylib` is a boolean determining whether Python code installed
        with the Python interpreter is measured.  This includes the Python
        standard library and any packages installed with the interpreter.
        
        If `auto_data` is true, then any existing data file will be read when
        coverage measurement starts, and data will be saved automatically when
        measurement stops.
        
        If `timid` is true, then a slower and simpler trace function will be
        used.  This is important for some environments where manipulation of
        tracing functions breaks the faster trace function.
        
        If `branch` is true, then branch coverage will be measured in addition
        to the usual statement coverage.
        
        `config_file` determines what config file to read.  If it is a string,
        it is the name of the config file to read.  If it is True, then a
        standard file is read (".coveragerc").  If it is False, then no file is
        read.
        
        `source` is a list of file paths or package names.  Only code located
        in the trees indicated by the file paths or package names will be
        measured.
        
        `include` and `omit` are lists of filename patterns. Files that match
        `include` will be measured, files that match `omit` will not.  Each
        will also accept a single string argument.
        
        `debug` is a list of strings indicating what debugging information is
        desired. `debug_file` is the file to write debug messages to,
        defaulting to stderr.
        
        """
        from coverage import __version__
        self._warnings = []
        self.config = CoverageConfig()
        if config_file:
            if config_file is True:
                config_file = '.coveragerc'
            try:
                self.config.from_file(config_file)
            except ValueError:
                _, err, _ = sys.exc_info()
                raise CoverageException("Couldn't read config file %s: %s" %
                                        (config_file, err))

        self.config.from_environment('COVERAGE_OPTIONS')
        env_data_file = os.environ.get('COVERAGE_FILE')
        if env_data_file:
            self.config.data_file = env_data_file
        self.config.from_args(data_file=data_file,
                              cover_pylib=cover_pylib,
                              timid=timid,
                              branch=branch,
                              parallel=bool_or_none(data_suffix),
                              source=source,
                              omit=omit,
                              include=include,
                              debug=debug)
        self.debug = DebugControl(self.config.debug, debug_file or sys.stderr)
        self.auto_data = auto_data
        self._exclude_re = {}
        self._exclude_regex_stale()
        self.file_locator = FileLocator()
        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(self._should_trace,
                                   timid=self.config.timid,
                                   branch=self.config.branch,
                                   warn=self._warn)
        if data_suffix or self.config.parallel:
            if not isinstance(data_suffix, string_class):
                data_suffix = True
        else:
            data_suffix = None
        self.data_suffix = None
        self.run_suffix = data_suffix
        self.data = CoverageData(basename=self.config.data_file,
                                 collector='coverage v%s' % __version__,
                                 debug=self.debug)
        self.pylib_dirs = []
        if not self.config.cover_pylib:
            for m in (atexit, os, random, socket, _structseq):
                if m is not None and hasattr(m, '__file__'):
                    m_dir = self._canonical_dir(m)
                    if m_dir not in self.pylib_dirs:
                        self.pylib_dirs.append(m_dir)

        self.cover_dir = self._canonical_dir(__file__)
        self.source_match = None
        self.pylib_match = self.cover_match = None
        self.include_match = self.omit_match = None
        Numbers.set_precision(self.config.precision)
        self._warn_no_data = True
        self._warn_unimported_source = True
        self._started = False
        self._measured = False
        atexit.register(self._atexit)