Пример #1
0
 def test_single_non_test_target(self):
     bfaddr = BuildFileAddress(None, 'bin', 'some/dir')
     target_adaptor = PythonBinaryAdaptor(type_alias='python_binary')
     with self.captured_logging(logging.INFO):
         # Note that this is not the same error message the end user will see, as we're resolving
         # union Get requests in run_rule, not the real engine.  But this test still asserts that
         # we error when we expect to error.
         with self.assertRaisesRegex(
                 AssertionError,
                 r'Rule requested: .* which cannot be satisfied.'):
             run_rule(
                 coordinator_of_tests,
                 rule_args=[
                     HydratedTarget(bfaddr.to_address(), target_adaptor,
                                    ()),
                     UnionMembership(
                         union_rules={TestTarget: [PythonTestsAdaptor]}),
                     AddressProvenanceMap(
                         bfaddr_to_spec={
                             bfaddr:
                             SingleAddress(directory='some/dir',
                                           name='bin'),
                         }),
                 ],
                 mock_gets=[
                     MockGet(
                         product_type=TestResult,
                         subject_type=PythonTestsAdaptor,
                         mock=lambda _: TestResult(status=Status.SUCCESS,
                                                   stdout='foo',
                                                   stderr=''),
                     ),
                 ],
             )
Пример #2
0
    def test_globbed_non_test_target(self):
        bfaddr = BuildFileAddress(None, 'bin', 'some/dir')
        target_adaptor = PythonBinaryAdaptor(type_alias='python_binary')
        with self.captured_logging(logging.INFO):
            result = run_rule(
                coordinator_of_tests,
                rule_args=[
                    HydratedTarget(bfaddr.to_address(), target_adaptor, ()),
                    UnionMembership(
                        union_rules={TestTarget: [PythonTestsAdaptor]}),
                    AddressProvenanceMap(
                        bfaddr_to_spec={
                            bfaddr: DescendantAddresses(directory='some/dir')
                        }),
                ],
                mock_gets=[
                    MockGet(
                        product_type=TestResult,
                        subject_type=PythonTestsAdaptor,
                        mock=lambda _: TestResult(
                            status=Status.SUCCESS, stdout='foo', stderr=''),
                    ),
                ],
            )

            self.assertEqual(result,
                             AddressAndTestResult(bfaddr.to_address(), None))
Пример #3
0
 def test_coordinator_globbed_non_test_target(self):
     bfaddr = BuildFileAddress(rel_path='some/dir', target_name='bin')
     result = self.run_coordinator_of_tests(
         address=bfaddr.to_address(),
         bfaddr_to_spec={bfaddr: DescendantAddresses(directory='some/dir')},
         test_target_type=False,
     )
     assert result == AddressAndTestResult(bfaddr.to_address(), None)
Пример #4
0
 def test_coordinator_globbed_test_target(self):
     bfaddr = BuildFileAddress(rel_path='some/dir', target_name='tests')
     result = self.run_coordinator_of_tests(
         address=bfaddr.to_address(),
         bfaddr_to_spec={bfaddr: DescendantAddresses(directory='some/dir')})
     assert result == AddressAndTestResult(
         bfaddr.to_address(),
         TestResult(status=Status.SUCCESS, stdout='foo', stderr=''))
 def test_scan_addresses_with_root(self):
   self.add_to_build_file('BUILD', 'target(name="foo")')
   subdir_build_file = self.add_to_build_file('subdir/BUILD', 'target(name="bar")')
   subdir_suffix_build_file = self.add_to_build_file('subdir/BUILD.suffix', 'target(name="baz")')
   subdir = os.path.join(self.build_root, 'subdir')
   self.assertEquals({BuildFileAddress(subdir_build_file, 'bar'),
                      BuildFileAddress(subdir_suffix_build_file, 'baz')},
                     self.address_mapper.scan_addresses(root=subdir))
 def test_scan_addresses(self):
   root_build_file = self.add_to_build_file('BUILD', 'target(name="foo")')
   subdir_build_file = self.add_to_build_file('subdir/BUILD', 'target(name="bar")')
   subdir_suffix_build_file = self.add_to_build_file('subdir/BUILD.suffix', 'target(name="baz")')
   with open(os.path.join(self.build_root, 'BUILD.invalid.suffix'), 'w') as invalid_build_file:
     invalid_build_file.write('target(name="foobar")')
   self.assertEquals({BuildFileAddress(root_build_file, 'foo'),
                      BuildFileAddress(subdir_build_file, 'bar'),
                      BuildFileAddress(subdir_suffix_build_file, 'baz')},
                     self.address_mapper.scan_addresses())
Пример #7
0
 def test_coordinator_single_non_test_target(self):
   bfaddr = BuildFileAddress(None, 'bin', 'some/dir')
   # Note that this is not the same error message the end user will see, as we're resolving
   # union Get requests in run_rule, not the real engine.  But this test still asserts that
   # we error when we expect to error.
   with self.assertRaisesRegex(AssertionError, r'Rule requested: .* which cannot be satisfied.'):
     self.run_coordinator_of_tests(
       address=bfaddr.to_address(),
       bfaddr_to_spec={bfaddr: SingleAddress(directory='some/dir', name='bin')},
       test_target_type=False,
     )
Пример #8
0
  def test_build_file_forms(self):
    with self.workspace('a/b/c/BUILD') as root_dir:
      build_file = BuildFile(FileSystemProjectTree(root_dir), relpath='a/b/c/BUILD')
      self.assert_address('a/b/c', 'c', BuildFileAddress(build_file))
      self.assert_address('a/b/c', 'foo', BuildFileAddress(build_file, target_name='foo'))
      self.assertEqual('a/b/c:foo', BuildFileAddress(build_file, target_name='foo').spec)

    with self.workspace('BUILD') as root_dir:
      build_file = BuildFile(FileSystemProjectTree(root_dir), relpath='BUILD')
      self.assert_address('', 'foo', BuildFileAddress(build_file, target_name='foo'))
      self.assertEqual('//:foo', BuildFileAddress(build_file, target_name='foo').spec)
Пример #9
0
 def test_is_declaring_file(self):
   scheduler = mock.Mock()
   mapper = LegacyAddressMapper(scheduler, '')
   self.assertTrue(mapper.is_declaring_file(Address('path', 'name'), 'path/BUILD'))
   self.assertTrue(mapper.is_declaring_file(Address('path', 'name'), 'path/BUILD.suffix'))
   self.assertFalse(mapper.is_declaring_file(Address('path', 'name'), 'path/not_a_build_file'))
   self.assertFalse(mapper.is_declaring_file(Address('path', 'name'), 'differing-path/BUILD'))
   self.assertFalse(mapper.is_declaring_file(
     BuildFileAddress(target_name='name', rel_path='path/BUILD.new'),
     'path/BUILD'))
   self.assertTrue(mapper.is_declaring_file(
     BuildFileAddress(target_name='name', rel_path='path/BUILD'),
     'path/BUILD'))
 def test_scan_addresses_with_excludes(self):
     root_build_file = self.add_to_build_file('BUILD', 'target(name="foo")')
     self.add_to_build_file('subdir/BUILD', 'target(name="bar")')
     spec_excludes = [os.path.join(self.build_root, 'subdir')]
     self.assertEquals(
         {BuildFileAddress(root_build_file, 'foo')},
         self.address_mapper.scan_addresses(spec_excludes=spec_excludes))
 def run_pytest(self,
                *,
                passthrough_args: Optional[str] = None) -> TestResult:
     args = [
         "--backend-packages2=pants.backend.python",
         "--pytest-version=pytest>=4.6.6,<4.7",  # so that we can run Python 2 tests
     ]
     if passthrough_args:
         args.append(f"--pytest-args='{passthrough_args}'")
     options_bootstrapper = create_options_bootstrapper(args=args)
     target = PythonTestsAdaptor(address=BuildFileAddress(
         rel_path=f"{self.source_root}/BUILD", target_name="target"), )
     test_result = self.request_single_product(
         TestResult, Params(target, options_bootstrapper))
     debug_request = self.request_single_product(
         TestDebugRequest,
         Params(target, options_bootstrapper),
     )
     debug_result = InteractiveRunner(
         self.scheduler).run_local_interactive_process(debug_request.ipr)
     if test_result.status == Status.SUCCESS:
         assert debug_result.process_exit_code == 0
     else:
         assert debug_result.process_exit_code != 0
     return test_result
Пример #12
0
 def build_file_addresses(self) -> Tuple[BuildFileAddress, ...]:
     return tuple(
         BuildFileAddress(
             rel_path=path, address=Address(spec_path=self.namespace, target_name=name)
         )
         for name, (path, _) in self.name_to_target_adaptors.items()
     )
Пример #13
0
  def __init__(self,
               name,
               build_file,
               build_file_source_lines,
               target_source_lines,
               target_interval,
               dependencies,
               dependencies_interval):
    """See BuildFileManipulator.load() for how to construct one as a user."""
    self.name = name
    self.build_file = build_file
    self.target_address = BuildFileAddress(build_file, name)
    self._build_file_source_lines = build_file_source_lines
    self._target_source_lines = target_source_lines
    self._target_interval = target_interval
    self._dependencies_interval = dependencies_interval
    self._dependencies_by_address = {}

    for dep in dependencies:
      dep_address = Address.parse(dep.spec, relative_to=build_file.spec_path)
      if dep_address in self._dependencies_by_address:
        raise BuildTargetParseError('The address {dep_address} occurred multiple times in the '
                                    'dependency specs for target {name} in {build_file}. '
                                    .format(dep_address=dep_address.spec,
                                            name=name,
                                            build_file=build_file))
      self._dependencies_by_address[dep_address] = dep
Пример #14
0
def run(console: Console, workspace: Workspace, runner: InteractiveRunner,
        bfa: BuildFileAddress) -> Run:
    target = bfa.to_address()
    binary = yield Get(CreatedBinary, Address, target)

    with temporary_dir(cleanup=True) as tmpdir:
        dirs_to_materialize = (DirectoryToMaterialize(
            path=str(tmpdir), directory_digest=binary.digest), )
        workspace.materialize_directories(dirs_to_materialize)

        console.write_stdout(f"Running target: {target}\n")
        full_path = str(Path(tmpdir, binary.binary_name))
        run_request = InteractiveProcessRequest(
            argv=[full_path],
            run_in_workspace=True,
        )

        try:
            result = runner.run_local_interactive_process(run_request)
            exit_code = result.process_exit_code
            if result.process_exit_code == 0:
                console.write_stdout(f"{target} ran successfully.\n")
            else:
                console.write_stderr(
                    f"{target} failed with code {result.process_exit_code}!\n")

        except Exception as e:
            console.write_stderr(
                f"Exception when attempting to run {target} : {e}\n")
            exit_code = -1

    yield Run(exit_code)
Пример #15
0
    def test_output_mixed(self):
        console = MockConsole(use_colors=False)
        options = MockOptions(debug=False)
        runner = InteractiveRunner(self.scheduler)
        target1 = self.make_build_target_address(
            "testprojects/tests/python/pants/passes")
        target2 = self.make_build_target_address(
            "testprojects/tests/python/pants/fails")

        def make_result(target):
            if target == target1:
                tr = TestResult(status=Status.SUCCESS,
                                stdout='I passed\n',
                                stderr='')
            elif target == target2:
                tr = TestResult(status=Status.FAILURE,
                                stdout='I failed\n',
                                stderr='')
            else:
                raise Exception("Unrecognised target")
            return AddressAndTestResult(target, tr)

        def make_debug_request(target):
            request = TestDebugRequest(ipr=self.make_successful_ipr(
            ) if target == target1 else self.make_failure_ipr())
            return AddressAndDebugRequest(target, request)

        res = run_rule(
            run_tests,
            rule_args=[console, options, runner, (target1, target2)],
            mock_gets=[
                MockGet(product_type=AddressAndTestResult,
                        subject_type=Address,
                        mock=make_result),
                MockGet(product_type=AddressAndDebugRequest,
                        subject_type=Address,
                        mock=make_debug_request),
                MockGet(product_type=BuildFileAddress,
                        subject_type=BuildFileAddresses,
                        mock=lambda tgt: BuildFileAddress(
                            rel_path=f'{tgt.spec_path}/BUILD',
                            target_name=tgt.target_name,
                        )),
            ],
        )

        self.assertEqual(1, res.exit_code)
        self.assertEquals(
            console.stdout.getvalue(),
            dedent("""\
      testprojects/tests/python/pants/passes stdout:
      I passed

      testprojects/tests/python/pants/fails stdout:
      I failed


      testprojects/tests/python/pants/passes                                          .....   SUCCESS
      testprojects/tests/python/pants/fails                                           .....   FAILURE
      """))
Пример #16
0
 def make_build_target_address(spec):
     address = Address.parse(spec)
     return BuildFileAddress(
         build_file=None,
         target_name=address.target_name,
         rel_path=f'{address.spec_path}/BUILD',
     )
Пример #17
0
 def make_build_target_address(self, spec):
   address = Address.parse(spec)
   return BuildFileAddress(
     build_file=None,
     target_name=address.target_name,
     rel_path='{}/BUILD'.format(address.spec_path),
   )
Пример #18
0
 def single_target_run(
     self,
     *,
     console: MockConsole,
     program_text: bytes,
     address_spec: str,
 ) -> Run:
     workspace = Workspace(self.scheduler)
     interactive_runner = InteractiveRunner(self.scheduler)
     address = Address.parse(address_spec)
     bfa = BuildFileAddress(build_file=None,
                            target_name=address.target_name,
                            rel_path=f'{address.spec_path}/BUILD')
     BuildRoot().path = self.build_root
     res = run_rule(
         run,
         rule_args=[
             console, workspace, interactive_runner,
             BuildRoot(), bfa,
             MockOptions(args=[])
         ],
         mock_gets=[
             MockGet(product_type=CreatedBinary,
                     subject_type=Address,
                     mock=lambda _: self.create_mock_binary(program_text)),
         ],
     )
     return cast(Run, res)
Пример #19
0
 def __call__(self, *args, **kwargs):
     addressable = self._addressable_factory.capture(*args, **kwargs)
     addressable_name = addressable.addressed_name
     if addressable_name:
         address = BuildFileAddress(build_file=self._build_file,
                                    target_name=addressable_name)
         self._registration_callback(address, addressable)
     return addressable
Пример #20
0
 def test_is_declaring_file(self) -> None:
     scheduler = unittest.mock.Mock()
     mapper = LegacyAddressMapper(scheduler, "")
     self.assertTrue(mapper.is_declaring_file(Address("path", "name"), "path/BUILD"))
     self.assertTrue(mapper.is_declaring_file(Address("path", "name"), "path/BUILD.suffix"))
     self.assertFalse(mapper.is_declaring_file(Address("path", "name"), "path/not_a_build_file"))
     self.assertFalse(mapper.is_declaring_file(Address("path", "name"), "differing-path/BUILD"))
     self.assertFalse(
         mapper.is_declaring_file(
             BuildFileAddress(target_name="name", rel_path="path/BUILD.new"), "path/BUILD"
         )
     )
     self.assertTrue(
         mapper.is_declaring_file(
             BuildFileAddress(target_name="name", rel_path="path/BUILD"), "path/BUILD"
         )
     )
Пример #21
0
    def addressables(self) -> Dict[BuildFileAddress, ThinAddressableObject]:
        """Return a mapping from BuildFileAddress to thin addressable objects in this namespace.

        :rtype: dict from `BuildFileAddress` to thin addressable objects.
        """
        return {
            BuildFileAddress(rel_path=path, target_name=name): obj
            for name, (path, obj) in self.objects_by_name.items()
        }
Пример #22
0
def parse_variants(address):
  target_name, at_sign, variants_str = address.target_name.partition('@')
  if not at_sign:
    return address, None
  variants = _extract_variants(address, variants_str) if variants_str else None
  if isinstance(address, BuildFileAddress):
    normalized_address = BuildFileAddress(rel_path=address.rel_path, target_name=target_name)
  else:
    normalized_address = Address(spec_path=address.spec_path, target_name=target_name)
  return normalized_address, variants
Пример #23
0
    def addressables(self):
        """Return a mapping from BuildFileAddress to thin addressable objects in this namespace.

    :rtype: dict from :class:`pants.build_graph.address.BuildFileAddress` to thin addressable
            objects.
    """
        return {
            BuildFileAddress(rel_path=path, target_name=name): obj
            for name, (path, obj) in self.objects_by_name.items()
        }
Пример #24
0
  def test_trivial_target(self):
    self.add_to_build_file('BUILD', 'fake(name="foozle")')
    build_file = self.create_buildfile('BUILD')
    address_map = self.build_file_parser.parse_build_file(build_file)

    self.assertEqual(len(address_map), 1)
    address, proxy = address_map.popitem()
    self.assertEqual(address, BuildFileAddress(build_file=build_file, target_name='foozle'))
    self.assertEqual(proxy.addressed_name, 'foozle')
    self.assertEqual(proxy.addressed_type, ErrorTarget)
Пример #25
0
 def test_empty_target_succeeds(self) -> None:
     # NB: Because this particular edge case should early return, we can avoid providing valid
     # mocked yield gets for most of the rule's body. Future tests added to this file will need to
     # provide valid mocks instead.
     unimplemented_mock = lambda _: NotImplemented
     target = PythonTestsAdaptor(
         address=BuildFileAddress(target_name="target", rel_path="test"))
     result: TestResult = run_rule(
         run_python_test,
         rule_args=[
             target,
             PyTest.global_instance(),
             PythonSetup.global_instance(),
             SubprocessEnvironment.global_instance(),
         ],
         mock_gets=[
             MockGet(product_type=TransitiveHydratedTargets,
                     subject_type=BuildFileAddresses,
                     mock=lambda _: TransitiveHydratedTargets(roots=(),
                                                              closure=())),
             MockGet(
                 product_type=SourceRootStrippedSources,
                 subject_type=Address,
                 mock=lambda _: SourceRootStrippedSources(snapshot=
                                                          EMPTY_SNAPSHOT),
             ),
             MockGet(
                 product_type=SourceRootStrippedSources,
                 subject_type=HydratedTarget,
                 mock=unimplemented_mock,
             ),
             MockGet(
                 product_type=Digest,
                 subject_type=DirectoriesToMerge,
                 mock=unimplemented_mock,
             ),
             MockGet(
                 product_type=InjectedInitDigest,
                 subject_type=Digest,
                 mock=unimplemented_mock,
             ),
             MockGet(
                 product_type=Pex,
                 subject_type=CreatePex,
                 mock=unimplemented_mock,
             ),
             MockGet(
                 product_type=FallibleExecuteProcessResult,
                 subject_type=ExecuteProcessRequest,
                 mock=unimplemented_mock,
             ),
         ],
     )
     self.assertEqual(result.status, Status.SUCCESS)
Пример #26
0
  def test_globbed_test_target(self):
    bfaddr = BuildFileAddress(None, 'tests', 'some/dir')
    target_adaptor = PythonTestsAdaptor(type_alias='python_tests')
    with self.captured_logging(logging.INFO):
      result = run_rule(
        coordinator_of_tests,
        HydratedTarget(bfaddr.to_address(), target_adaptor, ()),
        UnionMembership(union_rules={TestTarget: [PythonTestsAdaptor]}),
        AddressProvenanceMap(bfaddr_to_spec={
          bfaddr: DescendantAddresses(directory='some/dir')
        }),
        {
          (TestResult, PythonTestsAdaptor):
            lambda _: TestResult(status=Status.SUCCESS, stdout='foo', stderr=''),
        })

      self.assertEqual(
        result,
        AddressAndTestResult(bfaddr.to_address(),
                             TestResult(status=Status.SUCCESS, stdout='foo', stderr=''))
      )
Пример #27
0
 def sources_for(
     self, package_relative_path_globs: List[str], package_dir: str = "",
 ) -> EagerFilesetWithSpec:
     sources_field = SourcesField(
         address=BuildFileAddress(
             rel_path=os.path.join(package_dir, "BUILD"), target_name="_bogus_target_for_test",
         ),
         arg="sources",
         source_globs=SourceGlobs(*package_relative_path_globs),
     )
     field = self.scheduler.product_request(HydratedField, [sources_field])[0]
     return cast(EagerFilesetWithSpec, field.value)
Пример #28
0
    def test_build_file_forms(self) -> None:
        with self.workspace("a/b/c/BUILD") as root_dir:
            build_file = BuildFile(FileSystemProjectTree(root_dir),
                                   relpath="a/b/c/BUILD")
            self.assert_address("a/b/c", "c",
                                BuildFileAddress(build_file=build_file))
            self.assert_address(
                "a/b/c", "foo",
                BuildFileAddress(build_file=build_file, target_name="foo"))
            self.assertEqual(
                "a/b/c:foo",
                BuildFileAddress(build_file=build_file,
                                 target_name="foo").spec)

        with self.workspace("BUILD") as root_dir:
            build_file = BuildFile(FileSystemProjectTree(root_dir),
                                   relpath="BUILD")
            self.assert_address(
                "", "foo",
                BuildFileAddress(build_file=build_file, target_name="foo"))
            self.assertEqual(
                "//:foo",
                BuildFileAddress(build_file=build_file,
                                 target_name="foo").spec)
Пример #29
0
 def __call__(self, *args, **kwargs):
   # Let the name default to the name of the directory the BUILD file is in (as long as it's
   # not the root directory), as this is a very common idiom.  If there are multiple targets
   # in the BUILD file,  we'll issue an error saying as much, and the author will have to name all
   # but one of them explicitly.
   if 'name' not in kwargs:
     dirname = os.path.basename(self._build_file.spec_path)
     if dirname:
       kwargs['name'] = dirname
     else:
       raise Addressable.AddressableInitError(
           'Targets in root-level BUILD files must be named explicitly.')
   addressable = self._addressable_factory.capture(*args, **kwargs)
   addressable_name = addressable.addressed_name
   if addressable_name:
     address = BuildFileAddress(build_file=self._build_file, target_name=addressable_name)
     self._registration_callback(address, addressable)
   return addressable
Пример #30
0
async def run(
    console: Console,
    workspace: Workspace,
    runner: InteractiveRunner,
    build_root: BuildRoot,
    bfa: BuildFileAddress,
    options: RunOptions,
) -> Run:
    target = bfa.to_address()
    binary = await Get[CreatedBinary](Address, target)

    with temporary_dir(root_dir=str(Path(build_root.path, ".pants.d")),
                       cleanup=True) as tmpdir:
        path_relative_to_build_root = str(
            Path(tmpdir).relative_to(build_root.path))
        workspace.materialize_directory(
            DirectoryToMaterialize(binary.digest,
                                   path_prefix=path_relative_to_build_root))

        console.write_stdout(f"Running target: {target}\n")
        full_path = str(Path(tmpdir, binary.binary_name))
        run_request = InteractiveProcessRequest(
            argv=(full_path, *options.values.args),
            run_in_workspace=True,
        )

        try:
            result = runner.run_local_interactive_process(run_request)
            exit_code = result.process_exit_code
            if result.process_exit_code == 0:
                console.write_stdout(f"{target} ran successfully.\n")
            else:
                console.write_stderr(
                    f"{target} failed with code {result.process_exit_code}!\n")

        except Exception as e:
            console.write_stderr(
                f"Exception when attempting to run {target} : {e}\n")
            exit_code = -1

    return Run(exit_code)