def test_global_options_validation(self):
   # Specify an invalid combination of options.
   ob = OptionsBootstrapper.create(args=['--loop', '--v1'])
   build_config = BuildConfigInitializer.get(ob)
   with self.assertRaises(OptionsError) as exc:
     OptionsInitializer.create(ob, build_config)
   self.assertIn('loop option only works with', str(exc.exception))
Ejemplo n.º 2
0
  def _run(self):
    # Bootstrap options and logging.
    options_bootstrapper = self._options_bootstrapper or OptionsBootstrapper(env=self._env,
                                                                             args=self._args)
    options, build_config = OptionsInitializer(options_bootstrapper, exiter=self._exiter).setup()
    global_options = options.for_global_scope()

    # Apply exiter options.
    self._exiter.apply_options(options)

    # 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():
      options.for_scope(scope)

    # Verify the configs here.
    if global_options.verify_config:
      options_bootstrapper.verify_configs_against_options(options)

    # Launch RunTracker as early as possible (just after Subsystem options are initialized).
    run_tracker = RunTracker.global_instance()
    reporting = Reporting.global_instance()
    reporting.initialize(run_tracker, self._run_start_time)

    try:
      # Determine the build root dir.
      root_dir = get_buildroot()

      # Capture a repro of the 'before' state for this build, if needed.
      repro = Reproducer.global_instance().create_repro()
      if repro:
        repro.capture(run_tracker.run_info.get_as_dict())

      # Record the preceding product graph size.
      run_tracker.pantsd_stats.set_preceding_graph_size(self._preceding_graph_size)

      # Setup and run GoalRunner.
      goal_runner = GoalRunner.Factory(root_dir,
                                       options,
                                       build_config,
                                       run_tracker,
                                       reporting,
                                       self._target_roots,
                                       self._daemon_build_graph,
                                       self._exiter).setup()

      goal_runner_result = goal_runner.run()

      if repro:
        # TODO: Have Repro capture the 'after' state (as a diff) as well?
        repro.log_location_of_repro_file()
    finally:
      run_tracker_result = run_tracker.end()

    # Take the exit code with higher abs value in case of negative values.
    final_exit_code = goal_runner_result if abs(goal_runner_result) > abs(run_tracker_result) else run_tracker_result
    self._exiter.exit(final_exit_code)
Ejemplo n.º 3
0
Archivo: util.py Proyecto: benjyw/pants
def clean_global_runtime_state(reset_subsystem=False):
  """Resets the global runtime state of a pants runtime for cleaner forking.

  :param bool reset_subsystem: Whether or not to clean Subsystem global state.
  """
  if reset_subsystem:
    # Reset subsystem state.
    Subsystem.reset()

  # Reset Goals and Tasks.
  Goal.clear()

  # Reset backend/plugins state.
  OptionsInitializer.reset()
Ejemplo n.º 4
0
 def parse_options(args, env, setup_logging=False, options_bootstrapper=None):
   options_bootstrapper = options_bootstrapper or OptionsBootstrapper(args=args, env=env)
   bootstrap_options = options_bootstrapper.get_bootstrap_options().for_global_scope()
   if setup_logging:
     # Bootstrap logging and then fully initialize options.
     setup_logging_from_options(bootstrap_options)
   build_config = BuildConfigInitializer.get(options_bootstrapper)
   options = OptionsInitializer.create(options_bootstrapper, build_config)
   return options, build_config, options_bootstrapper
Ejemplo n.º 5
0
  def create(cls, options=None, args=None, build_root=None, change_calculator=None):
    """
    :param Options options: An `Options` instance to use, if available.
    :param string args: Raw cli args to use for parsing if an `Options` instance isn't available.
    :param string build_root: The build root.
    :param ChangeCalculator change_calculator: A `ChangeCalculator` for calculating changes.
    """
    if not options:
      assert args is not None, 'must pass `args` if not passing `options`'
      options, _ = OptionsInitializer(OptionsBootstrapper(args=args)).setup(init_logging=False)

    # Determine the literal target roots.
    spec_roots = cls.parse_specs(options.target_specs, build_root)

    # Determine `Changed` arguments directly from options to support pre-`Subsystem`
    # initialization paths.
    changed_options = options.for_scope('changed')
    changed_request = ChangedRequest.from_options(changed_options)

    logger.debug('args are: %s', args)
    logger.debug('spec_roots are: %s', spec_roots)
    logger.debug('changed_request is: %s', changed_request)

    if change_calculator and changed_request.is_actionable():
      if spec_roots:
        # We've been provided spec roots (e.g. `./pants list ::`) AND a changed request. Error out.
        raise InvalidSpecConstraint('cannot provide changed parameters and target specs!')

      # We've been provided no spec roots (e.g. `./pants list`) AND a changed request. Compute
      # alternate target roots.
      changed_addresses = change_calculator.changed_target_addresses(changed_request)
      logger.debug('changed addresses: %s', changed_addresses)
      return ChangedTargetRoots(tuple(SingleAddress(a.spec_path, a.target_name)
                                      for a in changed_addresses))

    return LiteralTargetRoots(spec_roots)
Ejemplo n.º 6
0
    def runner_factory(sock, arguments, environment):
      exiter = self._exiter_class(sock)
      graph_helper = None
      deferred_exc = None

      self._logger.debug('execution commandline: %s', arguments)
      options_bootstrapper = OptionsBootstrapper(args=arguments)
      build_config = BuildConfigInitializer.get(options_bootstrapper)
      options = OptionsInitializer.create(options_bootstrapper, build_config)

      graph_helper, target_roots = None, None
      try:
        self._logger.debug('warming the product graph via %s', self._scheduler_service)
        # N.B. This call is made in the pre-fork daemon context for reach and reuse of the
        # resident scheduler.
        graph_helper, target_roots = self._scheduler_service.warm_product_graph(
          options,
          self._target_roots_calculator
        )
      except Exception:
        deferred_exc = sys.exc_info()
        self._logger.warning(
          'encountered exception during SchedulerService.warm_product_graph(), deferring:\n%s',
          ''.join(traceback.format_exception(*deferred_exc))
        )

      return self._runner_class(
        sock,
        exiter,
        arguments,
        environment,
        target_roots,
        graph_helper,
        self.fork_lock,
        deferred_exc
      )
  def test_invalid_version(self):
    options_bootstrapper = OptionsBootstrapper(args=['--pants-version=99.99.9999'])
    initializer = OptionsInitializer(options_bootstrapper, WorkingSet())

    with self.assertRaises(BuildConfigurationError):
      initializer.setup()
  def test_invalid_version(self):
    options_bootstrapper = OptionsBootstrapper(args=['--pants-version=99.99.9999'])
    build_config = BuildConfigInitializer(options_bootstrapper)

    with self.assertRaises(BuildConfigurationError):
      OptionsInitializer.create(options_bootstrapper, build_config)
Ejemplo n.º 9
0
def parse_options(options_bootstrapper, build_config):
  options = OptionsInitializer.create(options_bootstrapper, build_config)
  options.freeze()
  return Options(options, build_config)
Ejemplo n.º 10
0
 def parse_options(args, env, options_bootstrapper=None):
   options_bootstrapper = options_bootstrapper or OptionsBootstrapper.create(args=args, env=env)
   build_config = BuildConfigInitializer.get(options_bootstrapper)
   options = OptionsInitializer.create(options_bootstrapper, build_config)
   return options, build_config, options_bootstrapper
Ejemplo n.º 11
0
 def parse_options(
     options_bootstrapper: OptionsBootstrapper,
 ) -> Tuple[Options, BuildConfiguration]:
     build_config = BuildConfigInitializer.get(options_bootstrapper)
     options = OptionsInitializer.create(options_bootstrapper, build_config)
     return options, build_config
Ejemplo n.º 12
0
def parse_options(options_bootstrapper):
  # TODO: Because _OptionsBootstapper is currently provided as a Param, this @rule relies on options
  # remaining relatively stable in order to be efficient. See #6845 for a discussion of how to make
  # minimize the size of that value.
  build_config = BuildConfigInitializer.get(options_bootstrapper)
  return _Options(OptionsInitializer.create(options_bootstrapper, build_config, init_subsystems=False))
Ejemplo n.º 13
0
    def setup_legacy_graph(
        native: Native,
        options_bootstrapper: OptionsBootstrapper,
        build_configuration: BuildConfiguration,
    ) -> LegacyGraphScheduler:
        """Construct and return the components necessary for LegacyBuildGraph construction."""
        build_root = get_buildroot()
        bootstrap_options = options_bootstrapper.bootstrap_options.for_global_scope(
        )

        glob_expansion_failure_configured = not bootstrap_options.is_default(
            "glob_expansion_failure")
        files_not_found_behavior_configured = not bootstrap_options.is_default(
            "files_not_found_behavior")
        if glob_expansion_failure_configured and files_not_found_behavior_configured:
            raise ValueError(
                "Conflicting options used. You used the new, preferred `--files-not-found-behavior`, but "
                "also used the deprecated `--glob-expansion-failure`.\n\nPlease "
                "specify only one of these (preferably `--files-not-found-behavior`)."
            )
        glob_match_error_behavior = (bootstrap_options.files_not_found_behavior
                                     .to_glob_match_error_behavior() if
                                     files_not_found_behavior_configured else
                                     bootstrap_options.glob_expansion_failure)

        deprecated_conditional(
            lambda: cast(
                bool, bootstrap_options.build_file_imports ==
                BuildFileImportsBehavior.allow),
            removal_version="1.27.0.dev0",
            entity_description="Using `--build-file-imports=allow`",
            hint_message=
            ("Import statements should be avoided in BUILD files because they can easily break Pants "
             "caching and lead to stale results. It is not safe to ignore warnings of imports, so the "
             "`allow` option is being removed.\n\nTo prepare for this change, either set "
             "`--build-file-imports=warn` or `--build-file-imports=error` (we recommend using `error`)."
             "\n\nIf you still need to keep the functionality you have from the import statement, "
             "consider rewriting your code into a Pants plugin: "
             "https://www.pantsbuild.org/howto_plugin.html"))
        deprecated_conditional(
            lambda: bootstrap_options.is_default("build_file_imports"),
            removal_version="1.27.0.dev0",
            entity_description="Defaulting to `--build-file-imports=warn`",
            hint_message=
            ("Import statements should be avoided in BUILD files because they can easily break Pants "
             "caching and lead to stale results. The default behavior will change from warning to "
             "erroring in 1.27.0.dev0, and the option will be removed in 1.29.0.dev0.\n\nTo prepare for "
             "this change, please explicitly set the option `--build-file-imports=warn` or "
             "`--build-file-imports=error` (we recommend using `error`).\n\nIf you still need to keep "
             "the functionality you have from import statements, consider rewriting your code into a "
             "Pants plugin: https://www.pantsbuild.org/howto_plugin.html"))

        return EngineInitializer.setup_legacy_graph_extended(
            OptionsInitializer.compute_pants_ignore(build_root,
                                                    bootstrap_options),
            bootstrap_options.local_store_dir,
            bootstrap_options.build_file_imports,
            options_bootstrapper,
            build_configuration,
            build_root=build_root,
            native=native,
            glob_match_error_behavior=glob_match_error_behavior,
            build_ignore_patterns=bootstrap_options.build_ignore,
            exclude_target_regexps=bootstrap_options.exclude_target_regexp,
            subproject_roots=bootstrap_options.subproject_roots,
            include_trace_on_error=bootstrap_options.
            print_exception_stacktrace,
            execution_options=ExecutionOptions.from_bootstrap_options(
                bootstrap_options),
        )
Ejemplo n.º 14
0
def parse_options(options_bootstrapper):
  # TODO: Because _OptionsBootstapper is currently provided as a Param, this @rule relies on options
  # remaining relatively stable in order to be efficient. See #6845 for a discussion of how to make
  # minimize the size of that value.
  build_config = BuildConfigInitializer.get(options_bootstrapper)
  return _Options(OptionsInitializer.create(options_bootstrapper, build_config, init_subsystems=False))
Ejemplo n.º 15
0
 def aliases(cls):
   """TODO: This is a nasty escape hatch to pass aliases to LegacyPythonCallbacksParser."""
   _, build_config = OptionsInitializer(OptionsBootstrapper()).setup(init_logging=False)
   return build_config.registered_aliases()
Ejemplo n.º 16
0
 def _default_build_file_aliases(self):
     # TODO: Get default BuildFileAliases by extending BaseTest post
     #   https://github.com/pantsbuild/pants/issues/4401
     _, build_config = OptionsInitializer(
         OptionsBootstrapper()).setup(init_logging=False)
     return build_config.registered_aliases()
Ejemplo n.º 17
0
    def create(
        cls,
        env: CompleteEnvironment,
        options_bootstrapper: OptionsBootstrapper,
        options_initializer: OptionsInitializer | None = None,
        scheduler: GraphScheduler | None = None,
        cancellation_latch: PySessionCancellationLatch | None = 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, values in options.scope_to_flags.items():
                if values:
                    # Only compute values if there were any command line options presented.
                    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,
            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,
        )