Esempio n. 1
0
  def test_list_goals_graph(self):
    Goal.clear()

    TaskRegistrar(name=self._LIST_GOALS_NAME, action=ListGoals)\
      .install().with_description(self._LIST_GOALS_DESC)
    TaskRegistrar(name=self._LLAMA_NAME, action=ListGoalsTest.LlamaTask)\
      .install().with_description(self._LLAMA_DESC)
    TaskRegistrar(name=self._ALPACA_NAME, action=ListGoalsTest.AlpacaTask, dependencies=[self._LLAMA_NAME])\
      .install()

    self.assert_console_output(
      'digraph G {\n  rankdir=LR;\n  graph [compound=true];',
      '  subgraph cluster_goals {\n    node [style=filled];\n    color = blue;\n    label = "goals";',
      '    goals_goals [label="goals"];',
      '  }',
      '  subgraph cluster_llama {\n    node [style=filled];\n    color = blue;\n    label = "llama";',
      '    llama_llama [label="llama"];',
      '  }',
      '  subgraph cluster_alpaca {\n    node [style=filled];\n    color = blue;\n    label = "alpaca";',
      '    alpaca_alpaca [label="alpaca"];',
      '  }',
      '  alpaca_alpaca -> llama_llama [ltail=cluster_alpaca lhead=cluster_llama];',
      '}',
      args=['--test-graph'],
    )
Esempio n. 2
0
  def _print_help(self):
    """Print a help screen, followed by an optional message.

    Note: Ony useful if called after options have been registered.
    """
    show_all_help = self._help_request and self._help_request.all_scopes
    goals = (Goal.all() if show_all_help else [Goal.by_name(goal_name) for goal_name in self.goals])
    if goals:
      for goal in goals:
        if not goal.ordered_task_names():
          print('\nUnknown goal: {}'.format(goal.name))
        else:
          print('\n{0}: {1}\n'.format(goal.name, goal.description))
          for scope_info in goal.known_scope_infos():
            help_str = self._format_help_for_scope(scope_info.scope)
            if help_str:
              print(help_str)
    else:
      print(pants_release())
      print('\nUsage:')
      print('  ./pants [option ...] [goal ...] [target...]  Attempt the specified goals.')
      print('  ./pants help                                 Get help.')
      print('  ./pants help [goal]                          Get help for a goal.')
      print('  ./pants help-advanced [goal]                 Get help for a goal\'s advanced options.')
      print('  ./pants help-all                             Get help for all goals.')
      print('  ./pants goals                                List all installed goals.')
      print('')
      print('  [target] accepts two special forms:')
      print('    dir:  to include all targets in the specified directory.')
      print('    dir:: to include all targets found recursively under the directory.')
      print('\nFriendly docs:\n  http://pantsbuild.github.io/')

    if show_all_help or not goals:
      print(self.get_parser(GLOBAL_SCOPE).format_help('Global', self._help_request.advanced))
Esempio n. 3
0
    def setUp(self):
        super(EngineTestBase, self).setUp()

        # TODO(John Sirois): Now that the BuildFileParser controls goal registration by iterating
        # over plugin callbacks a GoalRegistry can be constructed by it and handed to all these
        # callbacks in place of having a global Goal registry.  Remove the Goal static cling.
        Goal.clear()
Esempio n. 4
0
  def test_list_goals(self):
    Goal.clear()
    self.assert_console_output(self._INSTALLED_HEADER)

    TaskRegistrar(name=self._LIST_GOALS_NAME, action=ListGoals)\
      .install().with_description(self._LIST_GOALS_DESC)
    self.assert_console_output(
      self._INSTALLED_HEADER,
      '  %s: %s' % (self._LIST_GOALS_NAME, self._LIST_GOALS_DESC),
    )

    TaskRegistrar(name=self._LLAMA_NAME, action=ListGoalsTest.LlamaTask)\
      .install().with_description(self._LLAMA_DESC)
    self.assert_console_output(
      self._INSTALLED_HEADER,
      '  %s: %s' % (self._LIST_GOALS_NAME, self._LIST_GOALS_DESC),
      '  %s: %s' % (self._LLAMA_NAME, self._LLAMA_DESC),
    )

    TaskRegistrar(name=self._ALPACA_NAME, action=ListGoalsTest.AlpacaTask, dependencies=[self._LLAMA_NAME])\
      .install()
    self.assert_console_output(
      self._INSTALLED_HEADER,
      '  %s: %s' % (self._LIST_GOALS_NAME, self._LIST_GOALS_DESC),
      '  %s: %s' % (self._LLAMA_NAME, self._LLAMA_DESC),
    )
Esempio n. 5
0
def print_help(goals=None):
  if goals:
    for goal in goals:
      goal = Goal.by_name(goal)
      if not goal.ordered_task_names():
        print('\nUnknown goal: %s' % goal)
      else:
        parser = OptionParser(add_help_option=False)
        Goal.setup_parser(parser, [], [goal])
        print('\n%s: %s' % (goal.name, goal.description))
        _print_flags(parser, goal.name)
  else:
    print(pants_release())
    print('\nUsage:')
    print('  ./pants goal [option ...] [goal ...] [target...]  Attempt the specified goals.')
    print('  ./pants goal help                                 Get help.')
    print('  ./pants goal help [goal]                          Get help for the specified goal.')
    print('  ./pants goal goals                                List all installed goals.')
    print('')
    print('  [target] accepts two special forms:')
    print('    dir:  to include all targets in the specified directory.')
    print('    dir:: to include all targets found recursively under the directory.')

    print('\nFriendly docs:\n  http://pantsbuild.github.io/')

    _print_global_flags()
Esempio n. 6
0
  def tearDown(self):
    """
    :API: public
    """
    Goal.clear()

    super(EngineTestBase, self).tearDown()
Esempio n. 7
0
def clean_global_runtime_state():
  """Resets the global runtime state of a pants runtime for cleaner forking."""
  # Reset RunTracker state.
  RunTracker.global_instance().reset(reset_options=False)

  # Reset Goals and Tasks.
  Goal.clear()
Esempio n. 8
0
  def _install_options(self, options_bootstrapper, build_configuration):
    """Parse and register options.

    :returns: An Options object representing the full set of runtime options.
    """
    # TODO: This inline import is currently necessary to resolve a ~legitimate cycle between
    # `GoalRunner`->`EngineInitializer`->`OptionsInitializer`->`GoalRunner`.
    from pants.bin.goal_runner import GoalRunner

    # Now that plugins and backends are loaded, we can gather the known scopes.
    known_scope_infos = [GlobalOptionsRegistrar.get_scope_info()]

    # Add scopes for all needed subsystems via a union of all known subsystem sets.
    subsystems = Subsystem.closure(
      GoalRunner.subsystems() | Goal.subsystems() | build_configuration.subsystems()
    )
    for subsystem in subsystems:
      known_scope_infos.append(subsystem.get_scope_info())

    # Add scopes for all tasks in all goals.
    for goal in Goal.all():
      known_scope_infos.extend(filter(None, goal.known_scope_infos()))

    # Now that we have the known scopes we can get the full options.
    options = options_bootstrapper.get_full_options(known_scope_infos)
    self._register_options(subsystems, options)

    # Make the options values available to all subsystems.
    Subsystem.set_options(options)

    return options
Esempio n. 9
0
def gen_tasks_goals_reference_data():
  """Generate the template data for the goals reference rst doc."""
  goal_dict = {}
  goal_names = []
  for goal in Goal.all():
    tasks = []
    for task_name in goal.ordered_task_names():
      task_type = goal.task_type_by_name(task_name)
      doc_rst = indent_docstring_by_n(task_type.__doc__ or '', 2)
      doc_html = rst_to_html(dedent_docstring(task_type.__doc__))
      option_parser = Parser(env={}, config={}, scope='', parent_parser=None)
      task_type.register_options(option_parser.register)
      argparser = option_parser._help_argparser
      scope = Goal.scope(goal.name, task_name)
      # task_type may actually be a synthetic subclass of the authored class from the source code.
      # We want to display the authored class's name in the docs (but note that we must use the
      # subclass for registering options above)
      for authored_task_type in task_type.mro():
        if authored_task_type.__module__ != 'abc':
          break
      impl = '{0}.{1}'.format(authored_task_type.__module__, authored_task_type.__name__)
      tasks.append(TemplateData(
          impl=impl,
          doc_html=doc_html,
          doc_rst=doc_rst,
          ogroup=gref_template_data_from_options(scope, argparser)))
    goal_dict[goal.name] = TemplateData(goal=goal, tasks=tasks)
    goal_names.append(goal.name)

  goals = [goal_dict[name] for name in sorted(goal_names, key=lambda x: x.lower())]
  return goals
Esempio n. 10
0
  def setUp(self):
    Goal.clear()
    super(ConsoleTaskTest, self).setUp()

    task_type = self.task_type()
    assert issubclass(task_type, ConsoleTask), \
        'task_type() must return a ConsoleTask subclass, got %s' % task_type
Esempio n. 11
0
  def setUp(self):
    super(BaseTest, self).setUp()
    Goal.clear()
    Subsystem.reset()

    self.real_build_root = BuildRoot().path

    self.build_root = os.path.realpath(mkdtemp(suffix='_BUILD_ROOT'))
    self.addCleanup(safe_rmtree, self.build_root)

    self.pants_workdir = os.path.join(self.build_root, '.pants.d')
    safe_mkdir(self.pants_workdir)

    self.options = defaultdict(dict)  # scope -> key-value mapping.
    self.options[''] = {
      'pants_workdir': self.pants_workdir,
      'pants_supportdir': os.path.join(self.build_root, 'build-support'),
      'pants_distdir': os.path.join(self.build_root, 'dist'),
      'pants_configdir': os.path.join(self.build_root, 'config'),
      'cache_key_gen_version': '0-test',
    }

    BuildRoot().path = self.build_root
    self.addCleanup(BuildRoot().reset)

    # We need a pants.ini, even if empty. get_buildroot() uses its presence.
    self.create_file('pants.ini')
    self._build_configuration = BuildConfiguration()
    self._build_configuration.register_aliases(self.alias_groups)
    self.build_file_parser = BuildFileParser(self._build_configuration, self.build_root)
    self.address_mapper = BuildFileAddressMapper(self.build_file_parser, FilesystemBuildFile)
    self.build_graph = BuildGraph(address_mapper=self.address_mapper)
Esempio n. 12
0
def register_goals():
  # Spindle has a circular dependency, in that Spindle is required to build Spindle :(
  # The build_spindle task bootstraps a Spindle binary in order to allow sane iteration on the Spindle source code.
  task(name='build-spindle', action=BuildSpindle).install()
  task(name='spindle', action=SpindleGen).install('gen')

  Goal.register('ide-gen', 'Generate stub interfaces for IDE integration.')
  task(name='spindle-stubs', action=SpindleStubsGen).install('ide-gen')
Esempio n. 13
0
def register_goals():
    Goal.register(
        "invalidate-fingerprint-dependees",
        "Hack to make sure that java libraries are recompiled when a resource is changed.",
    )
    task(name="invalidate-fingerprint-dependees", action=InvalidateFingerpintDependees).install(
        "invalidate-fingerprint-dependees"
    )
Esempio n. 14
0
  def _clean_runtime_state(self):
    """Resets the runtime state from running ./pants -> running in the fork()'d daemon context."""
    # TODO(kwlzn): Make this logic available to PantsRunner et al for inline state reset before
    # pants runs to improve testability and avoid potential bitrot.

    # Reset RunTracker state.
    RunTracker.global_instance().reset(reset_options=False)

    # Reset Goals and Tasks.
    Goal.clear()
Esempio n. 15
0
 def test_task_subclass_singletons(self):
   # Install the same task class twice (before/after Goal.clear()) and confirm that the
   # resulting task is equal.
   class MyTask(Task):
     pass
   def install():
     reg = super(RoundEngineTest, self).install_task(name='task1', action=MyTask, goal='goal1')
     return reg.task_types()
   task1_pre, = install()
   Goal.clear()
   task1_post, = install()
   self.assertEquals(task1_pre, task1_post)
Esempio n. 16
0
  def setUp(self):
    Goal.clear()
    self.real_build_root = BuildRoot().path
    self.build_root = os.path.realpath(mkdtemp(suffix='_BUILD_ROOT'))
    BuildRoot().path = self.build_root

    self.create_file('pants.ini')
    build_configuration = BuildConfiguration()
    build_configuration.register_aliases(self.alias_groups)
    self.build_file_parser = BuildFileParser(build_configuration, self.build_root)
    self.address_mapper = BuildFileAddressMapper(self.build_file_parser)
    self.build_graph = BuildGraph(address_mapper=self.address_mapper)
Esempio n. 17
0
  def register_options(self):
    # Standalone global options.
    register_global_options(self.options.registration_function_for_global_scope())

    # Options for global-level subsystems.
    for subsystem_type in set(self.subsystems) | Goal.global_subsystem_types():
      subsystem_type.register_options_on_scope(self.options, Options.GLOBAL_SCOPE)

    # TODO(benjy): Should Goals be subsystems? Or should the entire goal-running mechanism
    # be a subsystem?
    for goal in Goal.all():
      # Register task options (including per-task subsystem options).
      goal.register_options(self.options)
Esempio n. 18
0
  def _setup_options(self, options_bootstrapper, working_set):
    # TODO: This inline import is currently necessary to resolve a ~legitimate cycle between
    # `GoalRunner`->`EngineInitializer`->`OptionsInitializer`->`GoalRunner`.
    from pants.bin.goal_runner import GoalRunner

    bootstrap_options = options_bootstrapper.get_bootstrap_options()
    global_bootstrap_options = bootstrap_options.for_global_scope()

    if global_bootstrap_options.pants_version != pants_version():
      raise BuildConfigurationError(
        'Version mismatch: Requested version was {}, our version is {}.'.format(
          global_bootstrap_options.pants_version, pants_version()
        )
      )

    # Get logging setup prior to loading backends so that they can log as needed.
    if self._init_logging:
      self._setup_logging(global_bootstrap_options)

    # Add any extra paths to python path (e.g., for loading extra source backends).
    for path in global_bootstrap_options.pythonpath:
      sys.path.append(path)
      pkg_resources.fixup_namespace_packages(path)

    # Load plugins and backends.
    plugins = global_bootstrap_options.plugins
    backend_packages = global_bootstrap_options.backend_packages
    build_configuration = load_plugins_and_backends(plugins, working_set, backend_packages)

    # Now that plugins and backends are loaded, we can gather the known scopes.
    known_scope_infos = [GlobalOptionsRegistrar.get_scope_info()]

    # Add scopes for all needed subsystems via a union of all known subsystem sets.
    subsystems = Subsystem.closure(
      GoalRunner.subsystems() | Goal.subsystems() | build_configuration.subsystems()
    )
    for subsystem in subsystems:
      known_scope_infos.append(subsystem.get_scope_info())

    # Add scopes for all tasks in all goals.
    for goal in Goal.all():
      known_scope_infos.extend(filter(None, goal.known_scope_infos()))

    # Now that we have the known scopes we can get the full options.
    options = options_bootstrapper.get_full_options(known_scope_infos)
    self._register_options(subsystems, options)

    # Make the options values available to all subsystems.
    Subsystem.set_options(options)

    return options, build_configuration
Esempio n. 19
0
  def test_plugin_installs_goal(self):
    def reg_goal():
      Goal.by_name('plugindemo').install(TaskRegistrar('foo', DummyTask))
    self.working_set.add(self.get_mock_plugin('regdemo', '0.0.1', reg=reg_goal))

    # Start without the custom goal.
    self.assertEqual(0, len(Goal.by_name('plugindemo').ordered_task_names()))

    # Load plugin which registers custom goal.
    self.load_plugins(['regdemo'])

    # Now the custom goal exists.
    self.assertEqual(1, len(Goal.by_name('plugindemo').ordered_task_names()))
    self.assertEqual('foo', Goal.by_name('plugindemo').ordered_task_names()[0])
Esempio n. 20
0
File: util.py Progetto: 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()
Esempio n. 21
0
  def DISABLED_test_gen_tasks_options_reference_data(self):
    # TODO(Eric Ayers) Not really part of the test, just to detect the cache poisoning
    before_support_dir = Config.from_cache().getdefault('pants_supportdir')

    # can we run our reflection-y goal code without crashing? would be nice
    Goal.by_name('jack').install(TaskRegistrar('jill', DummyTask))
    oref_data = reflect.gen_tasks_options_reference_data()

    # TODO(Eric Ayers) Not really part of the test, just to detect the cache poisoning
    after_support_dir = Config.from_cache().getdefault('pants_supportdir')
    self.assertEquals(before_support_dir, after_support_dir)

    self.assertTrue(len(oref_data) > 0,
                    'Tried to generate data for options reference, got emptiness')
Esempio n. 22
0
  def setUp(self):
    super(BaseTest, self).setUp()
    Goal.clear()
    self.real_build_root = BuildRoot().path
    self.build_root = os.path.realpath(mkdtemp(suffix='_BUILD_ROOT'))
    self.new_options = defaultdict(dict)  # scope -> key-value mapping.
    BuildRoot().path = self.build_root

    self.create_file('pants.ini')
    build_configuration = BuildConfiguration()
    build_configuration.register_aliases(self.alias_groups)
    self.build_file_parser = BuildFileParser(build_configuration, self.build_root)
    self.address_mapper = BuildFileAddressMapper(self.build_file_parser)
    self.build_graph = BuildGraph(address_mapper=self.address_mapper)
Esempio n. 23
0
  def _expand_goals_and_specs(self):
    goals = self.options.goals
    specs = self.options.target_specs
    fail_fast = self.options.for_global_scope().fail_fast

    for goal in goals:
      if BuildFile.from_cache(get_buildroot(), goal, must_exist=False).exists():
        logger.warning(" Command-line argument '{0}' is ambiguous and was assumed to be "
                       "a goal. If this is incorrect, disambiguate it with ./{0}.".format(goal))

    if self.options.print_help_if_requested():
      sys.exit(0)

    self.requested_goals = goals

    with self.run_tracker.new_workunit(name='setup', labels=[WorkUnit.SETUP]):
      spec_parser = CmdLineSpecParser(self.root_dir, self.address_mapper,
                                      spec_excludes=self.spec_excludes,
                                      exclude_target_regexps=self.global_options.exclude_target_regexp)
      with self.run_tracker.new_workunit(name='parse', labels=[WorkUnit.SETUP]):
        for spec in specs:
          for address in spec_parser.parse_addresses(spec, fail_fast):
            self.build_graph.inject_address_closure(address)
            self.targets.append(self.build_graph.get_target(address))
    self.goals = [Goal.by_name(goal) for goal in goals]
Esempio n. 24
0
  def _expand_goals_and_specs(self):
    goals = self.options.goals
    specs = self.options.target_specs
    fail_fast = self.options.for_global_scope().fail_fast

    for goal in goals:
      if self.address_mapper.from_cache(get_buildroot(), goal, must_exist=False).file_exists():
        logger.warning(" Command-line argument '{0}' is ambiguous and was assumed to be "
                       "a goal. If this is incorrect, disambiguate it with ./{0}.".format(goal))

    if self.options.help_request:
      help_printer = HelpPrinter(self.options)
      help_printer.print_help()
      self._exiter(0)

    self.requested_goals = goals

    with self.run_tracker.new_workunit(name='setup', labels=[WorkUnitLabel.SETUP]):
      spec_parser = CmdLineSpecParser(self.root_dir, self.address_mapper,
                                      spec_excludes=self.spec_excludes,
                                      exclude_target_regexps=self.global_options.exclude_target_regexp)
      with self.run_tracker.new_workunit(name='parse', labels=[WorkUnitLabel.SETUP]):
        def filter_for_tag(tag):
          return lambda target: tag in map(str, target.tags)
        tag_filter = wrap_filters(create_filters(self.global_options.tag, filter_for_tag))
        for spec in specs:
          for address in spec_parser.parse_addresses(spec, fail_fast):
            self.build_graph.inject_address_closure(address)
            tgt = self.build_graph.get_target(address)
            if tag_filter(tgt):
              self.targets.append(tgt)
    self.goals = [Goal.by_name(goal) for goal in goals]
Esempio n. 25
0
  def _install_options(self, options_bootstrapper, build_configuration):
    """Parse and register options.

    :returns: An Options object representing the full set of runtime options.
    """
    # TODO: This inline import is currently necessary to resolve a ~legitimate cycle between
    # `GoalRunner`->`EngineInitializer`->`OptionsInitializer`->`GoalRunner`.
    from pants.bin.goal_runner import GoalRunner

    # Now that plugins and backends are loaded, we can gather the known scopes.

    # Gather the optionables that are not scoped to any other.  All known scopes are reachable
    # via these optionables' known_scope_infos() methods.
    top_level_optionables = ({GlobalOptionsRegistrar} |
                             GoalRunner.subsystems() |
                             build_configuration.subsystems() |
                             set(Goal.get_optionables()))

    known_scope_infos = sorted({
      si for optionable in top_level_optionables for si in optionable.known_scope_infos()
    })

    # Now that we have the known scopes we can get the full options.
    options = options_bootstrapper.get_full_options(known_scope_infos)

    distinct_optionable_classes = sorted({si.optionable_cls for si in known_scope_infos},
                                         key=lambda o: o.options_scope)
    for optionable_cls in distinct_optionable_classes:
      optionable_cls.register_options_on_scope(options)

    # Make the options values available to all subsystems.
    Subsystem.set_options(options)

    return options
Esempio n. 26
0
  def _gen_reference(self):
    def get_scope_data(scope):
      ret = []
      for si in ScopeInfoIterator(self.context.options.known_scope_to_info).iterate([scope]):
        help_info = HelpInfoExtracter(si.scope).get_option_scope_help_info_from_parser(
          self.context.options.get_parser(si.scope))
        ret.append({
          # We don't use _asdict(), because then .description wouldn't be available.
          'scope_info': si,
          # We do use _asdict() here, so our mustache library can do property expansion.
          'help_info': help_info._asdict(),
        })
      return ret

    all_global_data = get_scope_data(GLOBAL_SCOPE)
    global_scope_data = all_global_data[0:1]
    global_subsystem_data = all_global_data[1:]

    goal_scopes = sorted([si.scope for si in self.context.options.known_scope_to_info.values()
    if si.scope and '.' not in si.scope and si.category != ScopeInfo.SUBSYSTEM])
    # TODO: Make goals Optionable and get their description via their ScopeInfo?
    goal_data = []
    for scope in goal_scopes:
      goal_data.append({
        'goal': scope,
        'goal_description': Goal.by_name(scope).description,
        'task_data': get_scope_data(scope)[1:]
      })

    ref_page = self._do_render(self.get_options().pants_reference_template, {
      'global_scope_data': global_scope_data,
      'global_subsystem_data': global_subsystem_data,
      'goal_data': goal_data
    })
    self.context.products.register_data(self.PANTS_REFERENCE_PRODUCT, ref_page)
Esempio n. 27
0
  def _construct_options(options_bootstrapper, build_configuration):
    """Parse and register options.

    :returns: An Options object representing the full set of runtime options.
    """
    # Now that plugins and backends are loaded, we can gather the known scopes.

    # Gather the optionables that are not scoped to any other.  All known scopes are reachable
    # via these optionables' known_scope_infos() methods.
    top_level_optionables = (
      {GlobalOptionsRegistrar} |
      GlobalSubsystems.get() |
      build_configuration.subsystems() |
      set(Goal.get_optionables())
    )

    known_scope_infos = sorted({
      si for optionable in top_level_optionables for si in optionable.known_scope_infos()
    })

    # Now that we have the known scopes we can get the full options.
    options = options_bootstrapper.get_full_options(known_scope_infos)

    distinct_optionable_classes = sorted({si.optionable_cls for si in known_scope_infos},
                                         key=lambda o: o.options_scope)
    for optionable_cls in distinct_optionable_classes:
      optionable_cls.register_options_on_scope(options)

    return options
Esempio n. 28
0
def gen_tasks_options_reference_data(options):
  """Generate the template data for the options reference rst doc."""
  goal_dict = {}
  goal_names = []
  for goal in Goal.all():
    tasks = []
    for task_name in goal.ordered_task_names():
      task_type = goal.task_type_by_name(task_name)
      # task_type may actually be a synthetic subclass of the authored class from the source code.
      # We want to display the authored class's name in the docs.
      for authored_task_type in task_type.mro():
        if authored_task_type.__module__ != 'abc':
          break

      doc_rst = indent_docstring_by_n(authored_task_type.__doc__ or '', 2)
      doc_html = rst_to_html(dedent_docstring(authored_task_type.__doc__))
      parser = options.get_parser(task_type.options_scope)
      oschi = HelpInfoExtracter.get_option_scope_help_info_from_parser(parser)
      impl = '{0}.{1}'.format(authored_task_type.__module__, authored_task_type.__name__)
      tasks.append(TemplateData(
          impl=impl,
          doc_html=doc_html,
          doc_rst=doc_rst,
          ogroup=oref_template_data_from_help_info(oschi)))
    goal_dict[goal.name] = TemplateData(goal=goal, tasks=tasks)
    goal_names.append(goal.name)

  goals = [goal_dict[name] for name in sorted(goal_names, key=lambda x: x.lower())]
  return goals
Esempio n. 29
0
  def setup(self):
    options_bootstrapper = OptionsBootstrapper()

    # Force config into the cache so we (and plugin/backend loading code) can use it.
    # TODO: Plumb options in explicitly.
    options_bootstrapper.get_bootstrap_options()
    self.config = Config.from_cache()

    # Add any extra paths to python path (eg for loading extra source backends)
    extra_paths = self.config.getlist('backends', 'python-path', [])
    if extra_paths:
      sys.path.extend(extra_paths)

    # Load plugins and backends.
    backend_packages = self.config.getlist('backends', 'packages', [])
    plugins = self.config.getlist('backends', 'plugins', [])
    build_configuration = load_plugins_and_backends(plugins, backend_packages)

    # Now that plugins and backends are loaded, we can gather the known scopes.
    self.targets = []
    known_scopes = ['']
    for goal in Goal.all():
      # Note that enclosing scopes will appear before scopes they enclose.
      known_scopes.extend(filter(None, goal.known_scopes()))

    # Now that we have the known scopes we can get the full options.
    self.options = options_bootstrapper.get_full_options(known_scopes=known_scopes)
    self.register_options()

    self.run_tracker = RunTracker.from_config(self.config)
    report = initial_reporting(self.config, self.run_tracker)
    self.run_tracker.start(report)
    url = self.run_tracker.run_info.get_info('report_url')
    if url:
      self.run_tracker.log(Report.INFO, 'See a report at: %s' % url)
    else:
      self.run_tracker.log(Report.INFO, '(To run a reporting server: ./pants server)')

    self.build_file_parser = BuildFileParser(build_configuration=build_configuration,
                                             root_dir=self.root_dir,
                                             run_tracker=self.run_tracker)
    self.address_mapper = BuildFileAddressMapper(self.build_file_parser)
    self.build_graph = BuildGraph(run_tracker=self.run_tracker,
                                  address_mapper=self.address_mapper)

    with self.run_tracker.new_workunit(name='bootstrap', labels=[WorkUnit.SETUP]):
      # construct base parameters to be filled in for BuildGraph
      for path in self.config.getlist('goals', 'bootstrap_buildfiles', default=[]):
        build_file = BuildFile.from_cache(root_dir=self.root_dir, relpath=path)
        # TODO(pl): This is an unfortunate interface leak, but I don't think
        # in the long run that we should be relying on "bootstrap" BUILD files
        # that do nothing except modify global state.  That type of behavior
        # (e.g. source roots, goal registration) should instead happen in
        # project plugins, or specialized configuration files.
        self.build_file_parser.parse_build_file_family(build_file)

    # Now that we've parsed the bootstrap BUILD files, and know about the SCM system.
    self.run_tracker.run_info.add_scm_info()

    self._expand_goals_and_specs()
Esempio n. 30
0
  def test_load_valid_partial_goals(self):
    def register_goals():
      Goal.by_name('jack').install(TaskRegistrar('jill', DummyTask))

    with self.create_register(register_goals=register_goals) as backend_package:
      Goal.clear()
      self.assertEqual(0, len(Goal.all()))

      load_backend(self.build_configuration, backend_package)
      self.assert_empty_aliases()
      self.assertEqual(1, len(Goal.all()))

      task_names = Goal.by_name('jack').ordered_task_names()
      self.assertEqual(1, len(task_names))

      task_name = task_names[0]
      self.assertEqual('jill', task_name)
Esempio n. 31
0
    def test_load_valid_partial_goals(self):
        def register_goals():
            Goal.by_name('jack').install(TaskRegistrar('jill', DummyTask))

        with self.create_register(
                register_goals=register_goals) as backend_package:
            Goal.clear()
            self.assertEqual(0, len(Goal.all()))

            load_backend(self.build_configuration, backend_package)
            self.assert_empty_aliases()
            self.assertEqual(1, len(Goal.all()))

            task_names = Goal.by_name('jack').ordered_task_names()
            self.assertEqual(1, len(task_names))

            task_name = task_names[0]
            self.assertEqual('jill', task_name)
Esempio n. 32
0
 def _index_products():
     producer_info_by_product_type = defaultdict(OrderedSet)
     for goal in Goal.all():
         for task_type in goal.task_types():
             for product_type in task_type.product_types():
                 producer_info = ProducerInfo(product_type, task_type, goal)
                 producer_info_by_product_type[product_type].add(
                     producer_info)
     return producer_info_by_product_type
Esempio n. 33
0
    def setUp(self):
        """
    :API: public
    """
        super(BaseTest, self).setUp()
        Goal.clear()
        Subsystem.reset()

        self.real_build_root = BuildRoot().path

        self.build_root = os.path.realpath(mkdtemp(suffix='_BUILD_ROOT'))
        self.addCleanup(safe_rmtree, self.build_root)

        self.pants_workdir = os.path.join(self.build_root, '.pants.d')
        safe_mkdir(self.pants_workdir)

        self.options = defaultdict(dict)  # scope -> key-value mapping.
        self.options[''] = {
            'pants_workdir': self.pants_workdir,
            'pants_supportdir': os.path.join(self.build_root, 'build-support'),
            'pants_distdir': os.path.join(self.build_root, 'dist'),
            'pants_configdir': os.path.join(self.build_root, 'config'),
            'cache_key_gen_version': '0-test',
        }
        self.options['cache'] = {
            'read_from': [],
            'write_to': [],
        }

        BuildRoot().path = self.build_root
        self.addCleanup(BuildRoot().reset)

        # We need a pants.ini, even if empty. get_buildroot() uses its presence.
        self.create_file('pants.ini')
        self._build_configuration = BuildConfiguration()
        self._build_configuration.register_aliases(self.alias_groups)
        self.build_file_parser = BuildFileParser(self._build_configuration,
                                                 self.build_root)
        self.project_tree = FileSystemProjectTree(self.build_root)
        self.address_mapper = BuildFileAddressMapper(
            self.build_file_parser,
            self.project_tree,
            build_ignore_patterns=self.build_ignore_patterns)
        self.build_graph = BuildGraph(address_mapper=self.address_mapper)
Esempio n. 34
0
    def register_options(self):
        # Add a 'bootstrap' attribute to the register function, so that register_global can
        # access the bootstrap option values.
        def register_global(*args, **kwargs):
            return self.new_options.register_global(*args, **kwargs)

        register_global.bootstrap = self.new_options.bootstrap_option_values()
        register_global_options(register_global)
        for goal in Goal.all():
            goal.register_options(self.new_options)
Esempio n. 35
0
    def test_list_goals_all(self):
        Goal.clear()

        TaskRegistrar(name=self._LIST_GOALS_NAME, action=ListGoals)\
          .install().with_description(self._LIST_GOALS_DESC)
        TaskRegistrar(name=self._LLAMA_NAME, action=ListGoalsTest.LlamaTask)\
          .install().with_description(self._LLAMA_DESC)
        TaskRegistrar(name=self._ALPACA_NAME, action=ListGoalsTest.AlpacaTask, dependencies=[self._LLAMA_NAME])\
          .install()

        self.assert_console_output(self._INSTALLED_HEADER,
                                   '  {0}: {1}'.format(self._LIST_GOALS_NAME,
                                                       self._LIST_GOALS_DESC),
                                   '  {0}: {1}'.format(self._LLAMA_NAME,
                                                       self._LLAMA_DESC),
                                   '',
                                   self._UNDOCUMENTED_HEADER,
                                   '  {0}'.format(self._ALPACA_NAME),
                                   options={'all': True})
Esempio n. 36
0
    def test_plugin_installs_goal(self):
        def reg_goal():
            Goal.by_name('plugindemo').install(TaskRegistrar('foo', DummyTask))

        self.working_set.add(
            self.get_mock_plugin('regdemo', '0.0.1', reg=reg_goal))

        # Start without the custom goal.
        self.assertEqual(0,
                         len(Goal.by_name('plugindemo').ordered_task_names()))

        # Load plugin which registers custom goal.
        self.load_plugins(['regdemo'])

        # Now the custom goal exists.
        self.assertEqual(1,
                         len(Goal.by_name('plugindemo').ordered_task_names()))
        self.assertEqual('foo',
                         Goal.by_name('plugindemo').ordered_task_names()[0])
Esempio n. 37
0
def clean_global_runtime_state(reset_runtracker=True, reset_subsystem=False):
    """Resets the global runtime state of a pants runtime for cleaner forking.

  :param bool reset_runtracker: Whether or not to clean RunTracker global state.
  :param bool reset_subsystem: Whether or not to clean Subsystem global state.
  """
    if reset_runtracker:
        # Reset RunTracker state.
        RunTracker.global_instance().reset(reset_options=False)

    if reset_subsystem:
        # Reset subsystem state.
        Subsystem.reset()

    # Reset Goals and Tasks.
    Goal.clear()

    # Reset backend/plugins state.
    OptionsInitializer.reset()
Esempio n. 38
0
        def graph():
            def get_cluster_name(goal):
                return 'cluster_%s' % goal.name.replace('-', '_')

            def get_node_name(goal, task_name):
                name = '%s_%s' % (goal.name, task_name)
                return name.replace('-', '_')

            yield '\n'.join([
                'digraph G {',
                '  rankdir=LR;',
                '  graph [compound=true];',
            ])
            for goal in Goal.all():
                yield '\n'.join([
                    '  subgraph %s {' % get_cluster_name(goal),
                    '    node [style=filled];',
                    '    color = blue;',
                    '    label = "%s";' % goal.name,
                ])
                for name in goal.ordered_task_names():
                    yield '    %s [label="%s"];' % (get_node_name(goal,
                                                                  name), name)
                yield '  }'

            edges = set()
            for goal in Goal.all():
                tail_task_name = goal.ordered_task_names()[-1]
                for dep in goal.dependencies:
                    edge = 'ltail=%s lhead=%s' % (get_cluster_name(goal),
                                                  get_cluster_name(dep))
                    if edge not in edges:
                        # We display edges between clusters (representing goals), but dot still requires
                        # us to specify them between nodes (representing tasks) and then add ltail, lhead
                        # annotations.  We connect the last task in the dependee to the first task in
                        # the dependency, as this leads to the neatest-looking graph.
                        yield '  %s -> %s [%s];' % (
                            get_node_name(goal, tail_task_name),
                            get_node_name(dep,
                                          dep.ordered_task_names()[0]), edge)
                    edges.add(edge)
            yield '}'
Esempio n. 39
0
def register_goals():
  Goal.by_name('idea').uninstall_task('idea')
  Goal.register('old-idea',
    'The old, deprecated task to generate an IntelliJ project (this is the task used in '
    'open-source pants).')
  Goal.register('idea', 
    'Generates an IntelliJ project for the specified targets and transitive dependencies. This is '
    'Square\'s internal version of the idea goal, implemented as a plugin.')
  Goal.register('new-idea', 'This has been renamed to just "idea".')

  task(name='old-idea', action=IdeaGen).install('old-idea')
  task(name='idea', action=SquareIdea).install('idea')
  task(name='new-idea', action=ShowNewIdeaMovedMessage).install('new-idea')
Esempio n. 40
0
    def test_register_duplicate_task_name_is_error(self):
        Goal.clear()

        class NoopTask(Task):
            def execute(self):
                pass

        class OtherNoopTask(Task):
            def execute(self):
                pass

        goal = Goal.register(self._LIST_GOALS_NAME, self._LIST_GOALS_DESC)
        task_name = 'foo'
        goal.install(TaskRegistrar(task_name, NoopTask))

        with self.assertRaises(GoalError) as ctx:
            goal.install(TaskRegistrar(task_name, OtherNoopTask))

        self.assertIn('foo', ctx.exception.message)
        self.assertIn(self._LIST_GOALS_NAME, ctx.exception.message)
Esempio n. 41
0
    def _get_all_cmd_line_scopes():
        """Return all scopes that may be explicitly specified on the cmd line, in no particular order.

    Note that this includes only task scope, and not, say, subsystem scopes,
    as those aren't specifiable on the cmd line.
    """
        all_scopes = {GLOBAL_SCOPE}
        for goal in Goal.all():
            for task in goal.task_types():
                all_scopes.add(task.get_scope_info().scope)
        return all_scopes
Esempio n. 42
0
    def setUp(self):
        super(BaseTest, self).setUp()
        Goal.clear()
        self.real_build_root = BuildRoot().path
        self.build_root = os.path.realpath(mkdtemp(suffix='_BUILD_ROOT'))
        self.new_options = defaultdict(dict)  # scope -> key-value mapping.
        self.new_options[''] = {
            'pants_workdir': os.path.join(self.build_root, '.pants.d'),
            'pants_supportdir': os.path.join(self.build_root, 'build-support'),
            'pants_distdir': os.path.join(self.build_root, 'dist')
        }
        BuildRoot().path = self.build_root

        self.create_file('pants.ini')
        build_configuration = BuildConfiguration()
        build_configuration.register_aliases(self.alias_groups)
        self.build_file_parser = BuildFileParser(build_configuration,
                                                 self.build_root)
        self.address_mapper = BuildFileAddressMapper(self.build_file_parser)
        self.build_graph = BuildGraph(address_mapper=self.address_mapper)
Esempio n. 43
0
  def _determine_goals(self, requested_goals):
    """Check and populate the requested goals for a given run."""

    spec_parser = CmdLineSpecParser(self._root_dir)
    for goal in requested_goals:
      if self._address_mapper.is_valid_single_address(spec_parser.parse_spec(goal)):
        logger.warning("Command-line argument '{0}' is ambiguous and was assumed to be "
                       "a goal. If this is incorrect, disambiguate it with ./{0}.".format(goal))

    goals = [Goal.by_name(goal) for goal in requested_goals]
    return goals
Esempio n. 44
0
    def get_all_cmd_line_scopes(self):
        """Return all scopes that may be explicitly specified on the cmd line, in no particular order.

    Note that this includes only task scope, and not, say, subsystem scopes,
    as those aren't specifiable on the cmd line.
    """
        all_scopes = set([''])
        for goal in Goal.all():
            for scope_info in goal.known_scope_infos():
                if scope_info.category == ScopeInfo.TASK:
                    all_scopes.add(scope_info.scope)
        return all_scopes
Esempio n. 45
0
def gen_tasks_goals_reference_data():
  """Generate the template data for the goals reference rst doc."""
  goal_dict = {}
  goal_names = []
  for goal in Goal.all():
    parser = optparse.OptionParser(add_help_option=False)
    Goal.setup_parser(parser, [], [goal])
    options_by_title = defaultdict(lambda: None)
    for group in parser.option_groups:
      options_by_title[group.title] = group
    found_option_groups = set()
    tasks = []
    for task_name in goal.ordered_task_names():
      task_type = goal.task_type_by_name(task_name)
      doc = indent_docstring_by_n(task_type.__doc__ or '', 2)
      options_title = Goal.option_group_title(goal, task_name)
      og = options_by_title[options_title]
      if og:
        found_option_groups.add(options_title)
      impl = '{0}.{1}'.format(task_type.__module__, task_type.__name__)
      tasks.append(TemplateData(
          impl=impl,
          doc=doc,
          ogroup=gref_template_data_from_options(og)))

    leftover_option_groups = []
    for group in parser.option_groups:
      if group.title in found_option_groups: continue
      leftover_option_groups.append(gref_template_data_from_options(group))
    leftover_options = []
    for option in parser.option_list:
      leftover_options.append(TemplateData(st=str(option)))
    goal_dict[goal.name] = TemplateData(goal=goal,
                                        tasks=tasks,
                                        leftover_opts=leftover_options,
                                        leftover_ogs=leftover_option_groups)
    goal_names.append(goal.name)

  goals = [goal_dict[name] for name in sorted(goal_names, key=_lower)]
  return goals
Esempio n. 46
0
    def _register_options(self, subsystems, options):
        """Registers global options."""
        # Standalone global options.
        GlobalOptionsRegistrar.register_options_on_scope(options)

        # Options for subsystems.
        for subsystem in subsystems:
            subsystem.register_options_on_scope(options)

        # TODO(benjy): Should Goals or the entire goal-running mechanism be a Subsystem?
        for goal in Goal.all():
            # Register task options.
            goal.register_options(options)
Esempio n. 47
0
  def add_member(cls, group_member):
    """Enlists a member in this group.

    A group task delegates all its work to group members who act cooperatively on targets they
    claim. The order members are added affects the target claim process by setting the order the
    group members are asked to claim targets in on a first-come, first-served basis.
    """
    if not issubclass(group_member, GroupMember):
      raise ValueError('Only GroupMember subclasses can join a GroupTask, '
                       'given %s of type %s' % (group_member, type(group_member)))

    group_member.options_scope = Goal.scope(cls.parent_options_scope, group_member.name())
    cls._member_types().append(group_member)
Esempio n. 48
0
    def __init__(self, *args, **kwargs):
        self.targets = []
        known_scopes = ['']
        for goal in Goal.all():
            # Note that enclosing scopes will appear before scopes they enclose.
            known_scopes.extend(filter(None, goal.known_scopes()))

        self.new_options = create_bootstrapped_options(
            known_scopes=known_scopes)
        self.config = Config.from_cache()  # Get the bootstrapped version.
        super(GoalRunner, self).__init__(*args,
                                         needs_old_options=False,
                                         **kwargs)
Esempio n. 49
0
def clean_global_runtime_state(reset_runtracker=True, reset_subsystem=False):
    """Resets the global runtime state of a pants runtime for cleaner forking.

  :param bool reset_runtracker: Whether or not to clean RunTracker global state.
  :param bool reset_subsystem: Whether or not to clean Subsystem global state.
  """
    if reset_runtracker:
        # Reset RunTracker state.
        RunTracker.global_instance().reset(reset_options=False)

    if reset_subsystem:
        # Reset subsystem state.
        Subsystem.reset()

    #TODO: Think of an alternative for IntermediateTargetFactoryBase._targets to avoid this call
    IntermediateTargetFactoryBase.reset()

    # Reset Goals and Tasks.
    Goal.clear()

    # Reset backend/plugins state.
    OptionsInitializer.reset()
Esempio n. 50
0
  def register_options(self, subsystems):
    # Standalone global options.
    GlobalOptionsRegistrar.register_options_on_scope(self.options)

    # Options for subsystems.
    for subsystem in subsystems:
      subsystem.register_options_on_scope(self.options)

    # TODO(benjy): Should Goals be subsystems? Or should the entire goal-running mechanism
    # be a subsystem?
    for goal in Goal.all():
      # Register task options.
      goal.register_options(self.options)
Esempio n. 51
0
  def _expand_goals(self, goals):
    """Check and populate the requested goals for a given run."""
    for goal in goals:
      if self._address_mapper.from_cache(self._root_dir, goal, must_exist=False).file_exists():
        logger.warning("Command-line argument '{0}' is ambiguous and was assumed to be "
                       "a goal. If this is incorrect, disambiguate it with ./{0}.".format(goal))

    if self._help_request:
      help_printer = HelpPrinter(self._options)
      help_printer.print_help()
      self._exiter(0)

    self._goals.extend([Goal.by_name(goal) for goal in goals])
Esempio n. 52
0
    def print_help(self, msg=None, goals=None):
        """Print a help screen, followed by an optional message.

    Note: Ony useful if called after options have been registered.
    """
        def _maybe_help(scope):
            s = self.format_help(scope)
            if s != '':  # Avoid printing scope name for scope with empty options.
                print(scope)
                for line in s.split('\n'):
                    if line != '':  # Avoid superfluous blank lines for empty strings.
                        print('  {0}'.format(line))

        goals = goals or self.goals
        if goals:
            for goal_name in goals:
                goal = Goal.by_name(goal_name)
                if not goal.ordered_task_names():
                    print('\nUnknown goal: %s' % goal_name)
                else:
                    print('\n{0}: {1}\n'.format(goal.name, goal.description))
                    for scope in goal.known_scopes():
                        _maybe_help(scope)
        else:
            print(pants_release())
            print('\nUsage:')
            print(
                '  ./pants [option ...] [goal ...] [target...]  Attempt the specified goals.'
            )
            print('  ./pants help                                 Get help.')
            print(
                '  ./pants help [goal]                          Get help for the specified goal.'
            )
            print(
                '  ./pants goal goals                           List all installed goals.'
            )
            print('')
            print('  [target] accepts two special forms:')
            print(
                '    dir:  to include all targets in the specified directory.')
            print(
                '    dir:: to include all targets found recursively under the directory.'
            )

            print('\nFriendly docs:\n  http://pantsbuild.github.io/')

            print('\nGlobal options:')
            print(self.format_global_help())

        if msg is not None:
            print(msg)
Esempio n. 53
0
    def print_help(self, msg=None, goals=None, legacy=False):
        """Print a help screen, followed by an optional message.

    Note: Ony useful if called after options have been registered.
    """
        def _maybe_print(s):
            if s != '':  # Avoid superfluous blank lines for empty strings.
                print(s)

        goals = goals or self.goals
        if goals:
            for goal_name in goals:
                goal = Goal.by_name(goal_name)
                if not goal.ordered_task_names():
                    print('\nUnknown goal: %s' % goal_name)
                else:
                    _maybe_print(
                        self.format_help('%s' % goal.name, legacy=legacy))
                    for task_name in goal.ordered_task_names():
                        if task_name != goal.name:  # Otherwise we registered on the goal scope.
                            scope = '%s.%s' % (goal.name, task_name)
                            _maybe_print(self.format_help(scope,
                                                          legacy=legacy))
        else:
            print(pants_release())
            print('\nUsage:')
            print(
                '  ./pants [option ...] [goal ...] [target...]  Attempt the specified goals.'
            )
            print('  ./pants help                                 Get help.')
            print(
                '  ./pants help [goal]                          Get help for the specified goal.'
            )
            print(
                '  ./pants goals                                List all installed goals.'
            )
            print('')
            print('  [target] accepts two special forms:')
            print(
                '    dir:  to include all targets in the specified directory.')
            print(
                '    dir:: to include all targets found recursively under the directory.'
            )

            print('\nFriendly docs:\n  http://pantsbuild.github.io/')

            print('\nGlobal options:')
            print(self.format_global_help())

        if msg is not None:
            print(msg)
Esempio n. 54
0
def gen_tasks_goals_reference_data():
    """Generate the template data for the goals reference rst doc."""
    goal_dict = {}
    goal_names = []
    for goal in Goal.all():
        tasks = []
        for task_name in goal.ordered_task_names():
            task_type = goal.task_type_by_name(task_name)
            doc_rst = indent_docstring_by_n(task_type.__doc__ or '', 2)
            doc_html = rst_to_html(dedent_docstring(task_type.__doc__))
            option_parser = Parser(env={},
                                   config={},
                                   scope='',
                                   parent_parser=None)
            task_type.register_options(option_parser.register)
            argparser = option_parser._help_argparser
            scope = Goal.scope(goal.name, task_name)
            # task_type may actually be a synthetic subclass of the authored class from the source code.
            # We want to display the authored class's name in the docs (but note that we must use the
            # subclass for registering options above)
            for authored_task_type in task_type.mro():
                if authored_task_type.__module__ != 'abc':
                    break
            impl = '{0}.{1}'.format(authored_task_type.__module__,
                                    authored_task_type.__name__)
            tasks.append(
                TemplateData(impl=impl,
                             doc_html=doc_html,
                             doc_rst=doc_rst,
                             ogroup=gref_template_data_from_options(
                                 scope, argparser)))
        goal_dict[goal.name] = TemplateData(goal=goal, tasks=tasks)
        goal_names.append(goal.name)

    goals = [
        goal_dict[name] for name in sorted(goal_names, key=lambda x: x.lower())
    ]
    return goals
Esempio n. 55
0
    def test_list_goals_all(self):
        Goal.clear()

        Goal.register(self._LIST_GOALS_NAME, self._LIST_GOALS_DESC)
        Goal.register(self._LLAMA_NAME, self._LLAMA_DESC)
        Goal.register(self._ALPACA_NAME, description='')

        self.assert_console_output(self._INSTALLED_HEADER,
                                   '  {0}: {1}'.format(self._LIST_GOALS_NAME,
                                                       self._LIST_GOALS_DESC),
                                   '  {0}: {1}'.format(self._LLAMA_NAME,
                                                       self._LLAMA_DESC),
                                   '',
                                   self._UNDOCUMENTED_HEADER,
                                   '  {0}'.format(self._ALPACA_NAME),
                                   options={'all': True})
Esempio n. 56
0
  def install(self, goal=None, first=False, replace=False, before=None, after=None):
    """Install the task in the specified goal (or a new goal with the same name as the task).

    The placement of the task in the execution list of the goal defaults to the end but can be
    influence by specifying exactly one of the following arguments:

    :param first: Places this task 1st in the goal's execution list.
    :param replace: Replaces any existing tasks in the goal with this goal.
    :param before: Places this task before the named task in the goal's execution list.
    :param after: Places this task after the named task in the goal's execution list.
    """
    goal = Goal.by_name(goal or self.name)
    goal.install(self, first, replace, before, after)
    return goal
Esempio n. 57
0
    def parse_args(args):
        goals = OrderedSet()
        specs = OrderedSet()
        explicit_multi = False
        logger = logging.getLogger(__name__)
        has_double_dash = u'--' in args
        goal_names = [goal.name for goal in Goal.all()]
        if not goal_names:
            raise GoalError(
                'Arguments cannot be parsed before the list of goals from Goal.all() is populated.'
            )

        def is_spec(spec):
            if os.sep in spec or ':' in spec:
                return True  # Definitely not a goal.
            if not (spec in goal_names):
                return True  # Definitely not a (known) goal.
            if has_double_dash:
                # This means that we're parsing the half of the expression before a --, so assume it's a
                # goal without warning.
                return False
            # Here, it's possible we have a goal and target with the same name. For now, always give
            # priority to the goal, but give a warning if they might have meant the target (if the BUILD
            # file exists).
            if BuildFile.from_cache(get_buildroot(), spec,
                                    must_exist=False).exists():
                logger.warning(
                    ' Command-line argument "{spec}" is ambiguous, and was assumed to be a '
                    'goal.  If this is incorrect, disambiguate it with the "--" argument to '
                    'separate goals from targets.'.format(spec=spec))
            return False

        for i, arg in enumerate(args):
            if not arg.startswith('-'):
                specs.add(arg) if is_spec(arg) else goals.add(arg)
            elif '--' == arg:
                if specs:
                    raise GoalRunner.IntermixedArgumentsError(
                        'Cannot intermix targets with goals when using --. Targets should appear on the right'
                    )
                explicit_multi = True
                del args[i]
                break

        if explicit_multi:
            specs.update(arg for arg in args[len(goals):]
                         if not arg.startswith('-'))

        return goals, specs
Esempio n. 58
0
    def test_list_goals_graph(self):
        Goal.clear()

        TaskRegistrar(name=self._LIST_GOALS_NAME, action=ListGoals)\
          .install().with_description(self._LIST_GOALS_DESC)
        TaskRegistrar(name=self._LLAMA_NAME, action=ListGoalsTest.LlamaTask)\
          .install().with_description(self._LLAMA_DESC)
        TaskRegistrar(name=self._ALPACA_NAME, action=ListGoalsTest.AlpacaTask, dependencies=[self._LLAMA_NAME])\
          .install()

        self.assert_console_output(
            'digraph G {\n  rankdir=LR;\n  graph [compound=true];',
            '  subgraph cluster_goals {\n    node [style=filled];\n    color = blue;\n    label = "goals";',
            '    goals_goals [label="goals"];',
            '  }',
            '  subgraph cluster_llama {\n    node [style=filled];\n    color = blue;\n    label = "llama";',
            '    llama_llama [label="llama"];',
            '  }',
            '  subgraph cluster_alpaca {\n    node [style=filled];\n    color = blue;\n    label = "alpaca";',
            '    alpaca_alpaca [label="alpaca"];',
            '  }',
            '  alpaca_alpaca -> llama_llama [ltail=cluster_alpaca lhead=cluster_llama];',
            '}',
            options={'graph': True})
Esempio n. 59
0
    def test_plugin_installs_goal(self):
        def reg_goal():
            Goal.by_name("plugindemo").install(TaskRegistrar("foo", DummyTask))

        self.working_set.add(
            self.get_mock_plugin("regdemo", "0.0.1", reg=reg_goal))

        # Start without the custom goal.
        self.assertEqual(0,
                         len(Goal.by_name("plugindemo").ordered_task_names()))

        # Ensure goal isn't created in a v2 world.
        self.load_plugins(["regdemo"], is_v1_plugin=False)
        self.assertEqual(0,
                         len(Goal.by_name("plugindemo").ordered_task_names()))

        # Load plugin which registers custom goal.
        self.load_plugins(["regdemo"], is_v1_plugin=True)

        # Now the custom goal exists.
        self.assertEqual(1,
                         len(Goal.by_name("plugindemo").ordered_task_names()))
        self.assertEqual("foo",
                         Goal.by_name("plugindemo").ordered_task_names()[0])
Esempio n. 60
0
    def _print_goals_help(self):
        print('\nUse `pants help $goal` to get help for a particular goal.\n')
        goal_descriptions = {}
        for scope_info in self._options.known_scope_to_info.values():
            if scope_info.category not in (ScopeInfo.GOAL, ScopeInfo.GOAL_V1):
                continue
            goal_descriptions[scope_info.scope] = scope_info.description
        goal_descriptions.update({
            goal.name: goal.description_first_line
            for goal in Goal.all() if goal.description
        })

        max_width = max(len(name) for name in goal_descriptions.keys())
        for name, description in sorted(goal_descriptions.items()):
            print('  {}: {}'.format(name.rjust(max_width), description))
        print()