def test_run_information(exit_code, expected, **kwargs) -> None: with temporary_dir() as buildroot: with environment_as(PANTS_BUILDROOT_OVERRIDE=buildroot): run_tracker = RunTracker( create_options_bootstrapper([]).bootstrap_options) specs = ["src/python/pants/goal/run_tracker_test.py"] run_tracker.start(run_start_time=time.time(), specs=specs) run_information = run_tracker.run_information() assert run_information["buildroot"] == get_buildroot() assert run_information["path"] == get_buildroot() # freezegun doesn't seem to accurately mock the time zone, # (i.e. the time zone used depends on that of the machine that # executes the test), so we can only safely assert that the # month and year appear in the human-readable string contained # in the "datetime" key assert "Jan" in run_information["datetime"] assert "2020" in run_information["datetime"] assert run_information["timestamp"] == 1578657601.0 assert run_information["user"] == getpass.getuser() assert run_information["version"] == VERSION assert re.match("pants.*run_tracker_test.py", run_information["cmd_line"]) assert run_information["specs_from_command_line"] == [ "src/python/pants/goal/run_tracker_test.py" ] frozen_time = kwargs["frozen_time"] frozen_time.tick(delta=datetime.timedelta(seconds=1)) run_tracker.end_run(exit_code) run_information_after_ended = run_tracker.run_information() assert run_information_after_ended["outcome"] == expected
def test_run_information(exit_code: ExitCode, expected: str, tmp_path: Path, **kwargs) -> None: frozen_time = kwargs["frozen_time"] buildroot = tmp_path.as_posix() with environment_as(PANTS_BUILDROOT_OVERRIDE=buildroot): spec = "test/example.py" ob = create_options_bootstrapper(["list", spec]) run_tracker = RunTracker(ob.args, ob.bootstrap_options) specs = [spec] run_tracker.start(run_start_time=time.time(), specs=specs) run_information = run_tracker.run_information() assert run_information["buildroot"] == get_buildroot() assert run_information["path"] == get_buildroot() # freezegun doesn't seem to accurately mock the time zone, # (i.e. the time zone used depends on that of the machine that # executes the test), so we can only safely assert that the # month and year appear in the human-readable string contained # in the "datetime" key assert "Jan" in run_information["datetime"] assert "2020" in run_information["datetime"] assert run_information["timestamp"] == 1578657601.0 assert run_information["user"] == getpass.getuser() assert run_information["version"] == VERSION assert re.match(f"pants.*{spec}", run_information["cmd_line"]) assert run_information["specs_from_command_line"] == [spec] frozen_time.tick(delta=datetime.timedelta(seconds=1)) run_tracker.end_run(exit_code) run_information_after_ended = run_tracker.run_information() assert run_information_after_ended["outcome"] == expected
def test_anonymous_telemetry_with_no_repo_id() -> None: with temporary_dir() as buildroot: with environment_as(PANTS_BUILDROOT_OVERRIDE=buildroot): opts = create_options_bootstrapper([]).bootstrap_options run_tracker = RunTracker(opts) run_tracker.start(run_start_time=time.time(), specs=[]) run_tracker.end_run(PANTS_SUCCEEDED_EXIT_CODE) repo_id = "" telemetry = run_tracker.get_anonymous_telemetry_data(repo_id) # Check that these keys have non-trivial values. for key in ( "run_id", "timestamp", "duration", "outcome", "platform", "python_implementation", "python_version", "pants_version", ): assert bool(telemetry.get(key)) for key in ("repo_id", "machine_id", "user_id"): assert telemetry.get(key) == ""
def test_run_tracker_timing_output(**kwargs) -> None: with temporary_dir() as buildroot: with environment_as(PANTS_BUILDROOT_OVERRIDE=buildroot): run_tracker = RunTracker(create_options_bootstrapper([]).bootstrap_options) run_tracker.start(run_start_time=time.time(), specs=["::"]) frozen_time = kwargs["frozen_time"] frozen_time.tick(delta=datetime.timedelta(seconds=1)) run_tracker.end_run(PANTS_SUCCEEDED_EXIT_CODE) timings = run_tracker.get_cumulative_timings() assert timings[0]["label"] == "main" assert timings[0]["timing"] == 1.0
def test_run_tracker_timing_output(tmp_path: Path, **kwargs) -> None: frozen_time = kwargs["frozen_time"] buildroot = tmp_path.as_posix() with environment_as(PANTS_BUILDROOT_OVERRIDE=buildroot): ob = create_options_bootstrapper([]) run_tracker = RunTracker(ob.args, ob.bootstrap_options) run_tracker.start(run_start_time=time.time(), specs=["::"]) frozen_time.tick(delta=datetime.timedelta(seconds=1)) run_tracker.end_run(PANTS_SUCCEEDED_EXIT_CODE) timings = run_tracker.get_cumulative_timings() assert timings[0]["label"] == "main" assert timings[0]["timing"] == 1.0
def create_run_tracker(info_dir=None): """Creates a ``RunTracker`` and starts it. :param string info_dir: An optional director for the run tracker to store state; defaults to a new temp dir that will be be cleaned up on interpreter exit. """ # TODO(John Sirois): Rework uses around a context manager for cleanup of the info_dir in a more # disciplined manner info_dir = info_dir or safe_mkdtemp() run_tracker = RunTracker(info_dir) report = Report() settings = PlainTextReporter.Settings(outfile=sys.stdout, log_level=Report.INFO, color=False, indent=True, timing=False, cache_stats=False) report.add_reporter('test_debug', PlainTextReporter(run_tracker, settings)) run_tracker.start(report) return run_tracker
def test_anonymous_telemetry(monkeypatch, tmp_path: Path, **kwargs) -> None: frozen_time = kwargs["frozen_time"] buildroot = tmp_path.as_posix() with environment_as(PANTS_BUILDROOT_OVERRIDE=buildroot): ob = create_options_bootstrapper([]) opts = ob.bootstrap_options monkeypatch.setattr(opts, "_goals", ["test", "customgoal", "lint"]) run_tracker = RunTracker(ob.args, opts) run_tracker.start(run_start_time=time.time(), specs=[]) frozen_time.tick(delta=datetime.timedelta(seconds=1)) run_tracker.end_run(PANTS_SUCCEEDED_EXIT_CODE) repo_id = "A" * 36 telemetry = run_tracker.get_anonymous_telemetry_data(repo_id) # Check that all keys have non-trivial values. for key in ( "run_id", "timestamp", "duration", "outcome", "platform", "python_implementation", "python_version", "pants_version", "repo_id", "machine_id", "user_id", "standard_goals", "num_goals", ): assert bool(telemetry.get(key)) # Verify a few easy-to-check values. assert telemetry["timestamp"] == "1578657601.0" assert telemetry["duration"] == "1.0" assert telemetry["outcome"] == "SUCCESS" assert telemetry["standard_goals"] == ["test", "lint"] assert telemetry["num_goals"] == "3"
def new_run_tracker() -> RunTracker: # NB: A RunTracker usually observes "all options" (`full_options_for_scopes`), but it only # actually directly consumes bootstrap options. ob = create_options_bootstrapper([]) return RunTracker(ob.args, ob.bootstrap_options)
def create( cls, env: Mapping[str, str], options_bootstrapper: OptionsBootstrapper, scheduler: Optional[GraphScheduler] = None, cancellation_latch: Optional[PySessionCancellationLatch] = None, ) -> LocalPantsRunner: """Creates a new LocalPantsRunner instance by parsing options. By the time this method runs, logging will already have been initialized in either PantsRunner or DaemonPantsRunner. :param env: The environment (e.g. os.environ) for this run. :param options_bootstrapper: The OptionsBootstrapper instance to reuse. :param scheduler: If being called from the daemon, a warmed scheduler to use. """ build_root = get_buildroot() global_bootstrap_options = options_bootstrapper.bootstrap_options.for_global_scope() build_config = BuildConfigInitializer.get(options_bootstrapper) try: options = OptionsInitializer.create(options_bootstrapper, build_config) except UnknownFlagsError as err: cls._handle_unknown_flags(err, options_bootstrapper) raise run_tracker = RunTracker(options) union_membership = UnionMembership.from_rules(build_config.union_rules) # If we're running with the daemon, we'll be handed a warmed Scheduler, which we use # to initialize a session here. graph_session = cls._init_graph_session( options_bootstrapper, build_config, run_tracker.run_id, options, scheduler, cancellation_latch, ) # Option values are usually computed lazily on demand, # but command line options are eagerly computed for validation. for scope in options.scope_to_flags.keys(): try: options.for_scope(scope) except UnknownFlagsError as err: cls._handle_unknown_flags(err, options_bootstrapper) raise # Verify configs. if global_bootstrap_options.verify_config: options.verify_configs(options_bootstrapper.config) specs = calculate_specs( options_bootstrapper=options_bootstrapper, options=options, build_root=build_root, session=graph_session.scheduler_session, ) profile_path = env.get("PANTS_PROFILE") return cls( build_root=build_root, options=options, build_config=build_config, run_tracker=run_tracker, specs=specs, graph_session=graph_session, union_membership=union_membership, profile_path=profile_path, )
def create( cls, env: CompleteEnvironment, options_bootstrapper: OptionsBootstrapper, options_initializer: Optional[OptionsInitializer] = None, scheduler: Optional[GraphScheduler] = None, cancellation_latch: Optional[PySessionCancellationLatch] = None, ) -> LocalPantsRunner: """Creates a new LocalPantsRunner instance by parsing options. By the time this method runs, logging will already have been initialized in either PantsRunner or DaemonPantsRunner. :param env: The environment for this run. :param options_bootstrapper: The OptionsBootstrapper instance to reuse. :param scheduler: If being called from the daemon, a warmed scheduler to use. """ options_initializer = options_initializer or OptionsInitializer(options_bootstrapper) build_config, options = options_initializer.build_config_and_options( options_bootstrapper, env, raise_=True ) stdio_destination_use_color(options.for_global_scope().colors) run_tracker = RunTracker(options_bootstrapper.args, options) union_membership = UnionMembership.from_rules(build_config.union_rules) # Option values are usually computed lazily on demand, but command line options are # eagerly computed for validation. with options_initializer.handle_unknown_flags(options_bootstrapper, env, raise_=True): for scope in options.scope_to_flags.keys(): options.for_scope(scope) # Verify configs. global_bootstrap_options = options_bootstrapper.bootstrap_options.for_global_scope() if global_bootstrap_options.verify_config: options.verify_configs(options_bootstrapper.config) # If we're running with the daemon, we'll be handed a warmed Scheduler, which we use # to initialize a session here. graph_session = cls._init_graph_session( options_initializer, options_bootstrapper, build_config, env, run_tracker.run_id, options, scheduler, cancellation_latch, ) specs = calculate_specs( options_bootstrapper=options_bootstrapper, options=options, build_root=get_buildroot(), session=graph_session.scheduler_session, ) profile_path = env.get("PANTS_PROFILE") return cls( options=options, options_bootstrapper=options_bootstrapper, build_config=build_config, run_tracker=run_tracker, specs=specs, graph_session=graph_session, union_membership=union_membership, profile_path=profile_path, )
def new_run_tracker() -> RunTracker: # NB: A RunTracker usually observes "all options" (`get_full_options`), but it only actually # directly consumes bootstrap options. return RunTracker(create_options_bootstrapper([]).bootstrap_options)