def get_bootstrap_options(self): """Returns an Options instance that only knows about the bootstrap options.""" if not self._bootstrap_options: flags = set() def capture_the_flags(*args, **kwargs): for flag in Parser.expand_flags(*args, **kwargs): flags.add(flag.name) if flag.inverse_name: flags.add(flag.inverse_name) register_bootstrap_options(capture_the_flags, buildroot=self._buildroot) # Take just the bootstrap args, so we don't choke on other global-scope args on the cmd line. bargs = filter(lambda x: x.partition('=')[0] in flags, self._args or []) self._bootstrap_options = Options(env=self._env, config=self._pre_bootstrap_config, known_scopes=[GLOBAL_SCOPE], args=bargs) register_bootstrap_options(self._bootstrap_options.register_global, buildroot=self._buildroot) bootstrap_option_values = self._bootstrap_options.for_global_scope() Config.reset_default_bootstrap_option_values(values=bootstrap_option_values) # Now re-read the config, post-bootstrapping. Note the order: First whatever we bootstrapped # from (typically pants.ini), then config override, then rcfiles. configpaths = list(self._pre_bootstrap_config.sources()) if bootstrap_option_values.config_override: configpaths.append(bootstrap_option_values.config_override) if bootstrap_option_values.pantsrc: rcfiles = [os.path.expanduser(rcfile) for rcfile in bootstrap_option_values.pantsrc_files] existing_rcfiles = filter(os.path.exists, rcfiles) configpaths.extend(existing_rcfiles) self._post_bootstrap_config = Config.load(configpaths) Config.cache(self._post_bootstrap_config) return self._bootstrap_options
def create_bootstrapped_options(known_scopes, env=None, configpath=None, args=None, buildroot=None): """Create an Options instance with appropriate bootstrapping.""" env = env or os.environ.copy() pre_bootstrap_config = Config.load(configpath) args = args or sys.argv buildroot = buildroot or get_buildroot() bootstrap_option_values = get_bootstrap_option_values( env, pre_bootstrap_config, args, buildroot) Config.reset_default_bootstrap_option_values(bootstrap_option_values) # Ensure that we cache the post-bootstrap version. Config.clear_cache() post_bootstrap_config = Config.from_cache(configpath) opts = Options(env, post_bootstrap_config, known_scopes, args=args, bootstrap_option_values=bootstrap_option_values) # The bootstrap options need to be registered on the post-bootstrap Options instance, so it won't # choke on them if specified on the command line, and also so we can access their values as # regular global-scope options, if needed. register_bootstrap_options(opts.register_global, buildroot=buildroot) return opts
def prepare_task(self, config=None, args=None, targets=None, build_graph=None, build_file_parser=None, address_mapper=None, console_outstream=None, workspace=None): """Prepares a Task for execution. task_type: The class of the Task to create. config: An optional string representing the contents of a pants.ini config. args: optional list of command line flags, these should be prefixed with '--test-'. targets: optional list of Target objects passed on the command line. Returns a new Task ready to execute. """ task_type = self.task_type() assert issubclass( task_type, Task), 'task_type must be a Task subclass, got %s' % task_type config = create_config(config or '') workdir = os.path.join(config.getdefault('pants_workdir'), 'test', task_type.__name__) bootstrap_options = OptionsBootstrapper().get_bootstrap_options() options = Options(env={}, config=config, known_scopes=['', 'test'], args=args or []) # A lot of basic code uses these options, so always register them. register_bootstrap_options(options.register_global) # We need to wrap register_global (can't set .bootstrap attr on the bound instancemethod). def register_global_wrapper(*args, **kwargs): return options.register_global(*args, **kwargs) register_global_wrapper.bootstrap = bootstrap_options.for_global_scope( ) register_global_options(register_global_wrapper) task_type.options_scope = 'test' task_type.register_options_on_scope(options) run_tracker = create_run_tracker() context = Context(config, options, run_tracker, targets or [], build_graph=build_graph, build_file_parser=build_file_parser, address_mapper=address_mapper, console_outstream=console_outstream, workspace=workspace) return task_type(context, workdir)
def test_deprecated_option_past_removal(self): with self.assertRaises(PastRemovalVersionError): options = Options({}, FakeConfig({}), OptionsTest._known_scope_infos, "./pants") options.register( Options.GLOBAL_SCOPE, '--too-old-option', deprecated_version='0.0.24', deprecated_hint='The semver for this option has already passed.' )
def bootstrap_options_from_config(config): bootstrap_options = Options( env=self._env, config=config, known_scope_infos=[ScopeInfo.for_global_scope()], args=bargs) def register_global(*args, **kwargs): bootstrap_options.register(GLOBAL_SCOPE, *args, **kwargs) GlobalOptionsRegistrar.register_bootstrap_options( register_global) return bootstrap_options
def _parse(self, args_str, env=None, config=None, bootstrap_option_values=None): args = shlex.split(str(args_str)) options = Options(env or {}, FakeConfig(config or {}), OptionsTest._known_scope_infos, args, bootstrap_option_values=bootstrap_option_values) self._register(options) return options
def get_bootstrap_options(self): """Returns an Options instance that only knows about the bootstrap options.""" if not self._bootstrap_options: flags = set() short_flags = set() def capture_the_flags(*args, **kwargs): for flag in Parser.expand_flags(*args, **kwargs): flags.add(flag.name) if len(flag.name) == 2: short_flags.add(flag.name) if flag.inverse_name: flags.add(flag.inverse_name) register_bootstrap_options(capture_the_flags, buildroot=self._buildroot) def is_bootstrap_option(arg): components = arg.split('=', 1) if components[0] in flags: return True for flag in short_flags: if arg.startswith(flag): return True return False # Take just the bootstrap args, so we don't choke on other global-scope args on the cmd line. # Stop before '--' since args after that are pass-through and may have duplicate names to our # bootstrap options. bargs = filter(is_bootstrap_option, itertools.takewhile(lambda arg: arg != '--', self._args)) self._bootstrap_options = Options(env=self._env, config=self._pre_bootstrap_config, known_scopes=[GLOBAL_SCOPE], args=bargs) register_bootstrap_options(self._bootstrap_options.register_global, buildroot=self._buildroot) bootstrap_option_values = self._bootstrap_options.for_global_scope() Config.reset_default_bootstrap_option_values(values=bootstrap_option_values) # Now re-read the config, post-bootstrapping. Note the order: First whatever we bootstrapped # from (typically pants.ini), then config override, then rcfiles. configpaths = list(self._pre_bootstrap_config.sources()) if bootstrap_option_values.config_override: configpaths.append(bootstrap_option_values.config_override) if bootstrap_option_values.pantsrc: rcfiles = [os.path.expanduser(rcfile) for rcfile in bootstrap_option_values.pantsrc_files] existing_rcfiles = filter(os.path.exists, rcfiles) configpaths.extend(existing_rcfiles) self._post_bootstrap_config = Config.load(configpaths) Config.cache(self._post_bootstrap_config) return self._bootstrap_options
def get_full_options(self, known_scope_infos): """Get the full Options instance bootstrapped by this object. :param known_scope_infos: ScopeInfos for all scopes that may be encountered. """ if not self._full_options: # Note: Don't inline this into the Options() call, as this populates # self._post_bootstrap_config, which is another argument to that call. bootstrap_options = self.get_bootstrap_options() self._full_options = Options( self._env, self._post_bootstrap_config, known_scope_infos, args=self._args, bootstrap_option_values=bootstrap_options.for_global_scope()) return self._full_options
def get_full_options(self, known_scopes): if not self._full_options: # Note: Don't inline this into the Options() call, as this populates # self._post_bootstrap_config, which is another argument to that call. bootstrap_options = self.get_bootstrap_options() self._full_options = Options(self._env, self._post_bootstrap_config, known_scopes, args=self._args, bootstrap_option_values=bootstrap_options.for_global_scope()) # The bootstrap options need to be registered on the post-bootstrap Options instance, so it # won't choke on them on the command line, and also so we can access their values as regular # global-scope options, for convenience. register_bootstrap_options(self._full_options.register_global, buildroot=self._buildroot) return self._full_options
def get_bootstrap_option_values(env=None, config=None, args=None, buildroot=None): """Get the values of just the bootstrap options.""" # Filter just the bootstrap args, so we don't choke on other global-scope args on the cmd line. flags = set() def capture_the_flags(*args, **kwargs): flags.update(args) register_bootstrap_options(capture_the_flags, buildroot=buildroot) bargs = filter(lambda x: x.partition('=')[0] in flags, args) bootstrap_options = Options(env=env, config=config, known_scopes=[GLOBAL_SCOPE], args=bargs) register_bootstrap_options(bootstrap_options.register_global, buildroot=buildroot) return bootstrap_options.for_global_scope()
def _parse(self, args_str, env=None, config=None): args = shlex.split(str(args_str)) options = Options(env or {}, config or OptionsTest.FakeConfig({}), OptionsTest._known_scopes, args) self._register(options) return options