# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 # For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt """Management of core choices.""" from __future__ import annotations import os import sys from typing import Any from coverage import env from coverage.disposition import FileDisposition from coverage.exceptions import ConfigError from coverage.misc import isolate_module from coverage.pytracer import PyTracer from coverage.sysmon import SysMonitor from coverage.types import ( TFileDisposition, Tracer, TWarnFn, ) os = isolate_module(os) try: # Use the C extension code when we can, for speed. from coverage.tracer import CTracer, CFileDisposition HAS_CTRACER = True except ImportError: # Couldn't import the C extension, maybe it isn't built. if os.getenv("COVERAGE_CORE") == "ctrace": # pragma: part covered # During testing, we use the COVERAGE_CORE environment variable # to indicate that we've fiddled with the environment to test this # fallback code. If we thought we had a C tracer, but couldn't import # it, then exit quickly and clearly instead of dribbling confusing # errors. I'm using sys.exit here instead of an exception because an # exception here causes all sorts of other noise in unittest. sys.stderr.write("*** COVERAGE_CORE is 'ctrace' but can't import CTracer!\n") sys.exit(1) HAS_CTRACER = False class Core: """Information about the central technology enabling execution measurement.""" tracer_class: type[Tracer] tracer_kwargs: dict[str, Any] file_disposition_class: type[TFileDisposition] supports_plugins: bool packed_arcs: bool systrace: bool def __init__(self, warn: TWarnFn, timid: bool, metacov: bool, ) -> None: # Defaults self.tracer_kwargs = {} core_name: str | None if timid: core_name = "pytrace" else: core_name = os.getenv("COVERAGE_CORE") if core_name == "sysmon" and not env.PYBEHAVIOR.pep669: warn("sys.monitoring isn't available, using default core", slug="no-sysmon") core_name = None if not core_name: # Once we're comfortable with sysmon as a default: # if env.PYBEHAVIOR.pep669 and self.should_start_context is None: # core_name = "sysmon" if HAS_CTRACER: core_name = "ctrace" else: core_name = "pytrace" if core_name == "sysmon": self.tracer_class = SysMonitor self.tracer_kwargs = {"tool_id": 3 if metacov else 1} self.file_disposition_class = FileDisposition self.supports_plugins = False self.packed_arcs = False self.systrace = False elif core_name == "ctrace": self.tracer_class = CTracer self.file_disposition_class = CFileDisposition self.supports_plugins = True self.packed_arcs = True self.systrace = True elif core_name == "pytrace": self.tracer_class = PyTracer self.file_disposition_class = FileDisposition self.supports_plugins = False self.packed_arcs = False self.systrace = True else: raise ConfigError(f"Unknown core value: {core_name!r}")