Example #1
0
    def test_input_file_creation(self):
        file_name = "some.filename"
        file_contents = b"some file contents"

        digest = self.request_single_product(
            Digest,
            CreateDigest([FileContent(path=file_name, content=file_contents)]))
        req = Process(
            argv=("/bin/cat", file_name),
            input_digest=digest,
            description="cat the contents of this file",
        )

        result = self.request_single_product(ProcessResult, req)
        self.assertEqual(result.stdout, file_contents)
Example #2
0
async def inject_missing_init_files(
        request: InjectInitRequest) -> InitInjectedSnapshot:
    """Ensure that every package has an `__init__.py` file in it.

    This will preserve any `__init__.py` files already in the input snapshot.
    """
    snapshot = request.stripped_sources_snapshot
    missing_init_files = sorted(identify_missing_init_files(snapshot.files))
    if not missing_init_files:
        return InitInjectedSnapshot(snapshot)
    generated_inits_digest = await Get[Digest](InputFilesContent(
        FileContent(path=fp, content=b"") for fp in missing_init_files))
    result = await Get[Snapshot](MergeDigests(
        (snapshot.digest, generated_inits_digest)))
    return InitInjectedSnapshot(result)
Example #3
0
    def test_relative_import(self) -> None:
        self.create_basic_library()
        source = FileContent(
            path="test_relative_import.py",
            content=dedent("""\
                from .library import add_two

                def test():
                  assert add_two(2) == 4
                """).encode(),
        )
        self.create_python_test_target([source], dependencies=[":library"])
        result = self.run_pytest()
        assert result.status == Status.SUCCESS
        assert "test_relative_import.py ." in result.stdout
Example #4
0
    def test_executable(self):
        file_name = "echo.sh"
        file_contents = b'#!/bin/bash -eu\necho "Hello"\n'

        input_file = InputFilesContent(
            (FileContent(path=file_name, content=file_contents, is_executable=True),)
        )
        digest = self.request_single_product(Digest, input_file)

        req = Process(
            argv=("./echo.sh",), input_digest=digest, description="cat the contents of this file",
        )

        result = self.request_single_product(ProcessResult, req)
        self.assertEqual(result.stdout, b"Hello\n")
Example #5
0
    def test_file_in_directory_creation(self):
        path = "somedir/filename"
        content = b"file contents"

        input_file = InputFilesContent((FileContent(path=path, content=content),))
        digest = self.request_single_product(Digest, input_file)

        req = ExecuteProcessRequest(
            argv=("/bin/cat", "somedir/filename"),
            input_files=digest,
            description="Cat a file in a directory to make sure that doesn't break",
        )

        result = self.request_single_product(ExecuteProcessResult, req)
        self.assertEqual(result.stdout, content)
Example #6
0
    def test_input_file_creation(self):
        file_name = "some.filename"
        file_contents = b"some file contents"

        input_file = InputFilesContent((FileContent(path=file_name, content=file_contents),))
        digest = self.request_single_product(Digest, input_file)

        req = ExecuteProcessRequest(
            argv=("/bin/cat", file_name),
            input_files=digest,
            description="cat the contents of this file",
        )

        result = self.request_single_product(ExecuteProcessResult, req)
        self.assertEqual(result.stdout, file_contents)
Example #7
0
    def test_absolute_import(self) -> None:
        self.create_python_library([self.library_source])
        source = FileContent(
            path="test_absolute_import.py",
            content=dedent("""\
                from pants_test.library import add_two

                def test():
                  assert add_two(2) == 4
                """).encode(),
        )
        self.create_python_test_target([source], dependencies=[":library"])
        result = self.run_pytest()
        assert result.status == Status.SUCCESS
        assert f"{self.package}/test_absolute_import.py ." in result.stdout
Example #8
0
    def test_write_digest(self):
        # TODO(#8336): at some point, this test should require that Workspace only be invoked from
        #  an @goal_rule
        workspace = Workspace(self.scheduler)
        digest = self.request_single_product(
            Digest,
            CreateDigest([
                FileContent("a.txt", b"hello"),
                FileContent("subdir/b.txt", b"goodbye")
            ]),
        )

        path1 = Path(self.build_root, "a.txt")
        path2 = Path(self.build_root, "subdir/b.txt")
        assert not path1.is_file()
        assert not path2.is_file()

        workspace.write_digest(digest)
        assert path1.is_file()
        assert path2.is_file()

        workspace.write_digest(digest, path_prefix="prefix")
        assert Path(self.build_root, "prefix", path1).is_file()
        assert Path(self.build_root, "prefix", path2).is_file()
Example #9
0
    def test_snapshot_subset_globs(self) -> None:
        ss = SnapshotSubset(
            self.generate_original_digest(),
            PathGlobs(("a.txt", "c.txt", "subdir2/**")),
        )

        subset_snapshot = self.request_single_product(Snapshot, ss)
        assert set(subset_snapshot.files) == {
            "a.txt",
            "c.txt",
            "subdir2/a.txt",
            "subdir2/nested_subdir/x.txt",
        }
        assert set(subset_snapshot.dirs) == {"subdir2/nested_subdir"}

        content = b"dummy content"
        subset_input = InputFilesContent((
            FileContent(path="a.txt", content=content),
            FileContent(path="c.txt", content=content),
            FileContent(path="subdir2/a.txt", content=content),
            FileContent(path="subdir2/nested_subdir/x.txt", content=content),
        ))
        subset_digest = self.request_single_product(Digest, subset_input)
        assert subset_snapshot.digest == subset_digest
Example #10
0
    def test_nonexistent_filename_globs(self) -> None:
        # We expect to ignore, rather than error, on files that don't exist in the original snapshot.
        ss = SnapshotSubset(directory_digest=self.generate_original_digest(),
                            globs=PathGlobs(
                                ("some_file_not_in_snapshot.txt", "a.txt")))

        subset_snapshot = self.request_single_product(Snapshot, ss)
        assert set(subset_snapshot.files) == {"a.txt"}

        content = b'dummy content'
        subset_input = InputFilesContent((FileContent(path='a.txt',
                                                      content=content), ))

        subset_digest = self.request_single_product(Digest, subset_input)
        assert subset_snapshot.directory_digest == subset_digest
Example #11
0
def _update_config(fc: FileContent) -> FileContent:
    if PurePath(fc.path).suffix == ".toml":
        all_config = _parse_toml_config(fc)
        tool = all_config.setdefault("tool", {})
        coverage = tool.setdefault("coverage", {})
        run = coverage.setdefault("run", {})
        run["relative_files"] = True
        if "pytest.pex/*" not in run.get("omit", []):
            run["omit"] = [*run.get("omit", []), "pytest.pex/*"]
        return FileContent(fc.path, toml.dumps(all_config).encode())

    cp = _parse_ini_config(fc)
    run_section = "coverage:run" if fc.path in ("tox.ini",
                                                "setup.cfg") else "run"
    if not cp.has_section(run_section):
        cp.add_section(run_section)
    cp.set(run_section, "relative_files", "True")
    omit_elements = cp[run_section].get("omit", "").split("\n") or ["\n"]
    if "pytest.pex/*" not in omit_elements:
        omit_elements.append("pytest.pex/*")
    cp.set(run_section, "omit", "\n".join(omit_elements))
    stream = StringIO()
    cp.write(stream)
    return FileContent(fc.path, stream.getvalue().encode())
Example #12
0
async def create_or_update_coverage_config(coverage: CoverageSubsystem) -> CoverageConfig:
    config_files = await Get(ConfigFiles, ConfigFilesRequest, coverage.config_request)
    if config_files.snapshot.files:
        digest_contents = await Get(DigestContents, Digest, config_files.snapshot.digest)
        file_content = _update_config(digest_contents[0])
    else:
        cp = configparser.ConfigParser()
        cp.add_section("run")
        cp.set("run", "relative_files", "True")
        cp.set("run", "omit", "\npytest.pex/*")
        stream = StringIO()
        cp.write(stream)
        file_content = FileContent(".coveragerc", stream.getvalue().encode())
    digest = await Get(Digest, CreateDigest([file_content]))
    return CoverageConfig(digest, file_content.path)
def test_relative_import(rule_runner: RuleRunner) -> None:
    create_python_library(rule_runner, [LIBRARY_SOURCE])
    source = FileContent(
        path=f"{PACKAGE}/test_relative_import.py",
        content=dedent("""\
            from .library import add_two

            def test():
              assert add_two(2) == 4
            """).encode(),
    )
    tgt = create_test_target(rule_runner, [source], dependencies=[":library"])
    result = run_pytest(rule_runner, tgt)
    assert result.exit_code == 0
    assert f"{PACKAGE}/test_relative_import.py ." in result.stdout
Example #14
0
    def test_add_prefix(self) -> None:
        digest = self.request_product(
            Digest,
            [
                CreateDigest((
                    FileContent(path="main.py", content=b'print("from main")'),
                    FileContent(path="subdir/sub.py",
                                content=b'print("from sub")'),
                ))
            ],
        )

        # Two components.
        output_digest = self.request_product(
            Digest, [AddPrefix(digest, "outer_dir/middle_dir")])
        snapshot = self.request_product(Snapshot, [output_digest])
        assert sorted(snapshot.files) == [
            "outer_dir/middle_dir/main.py",
            "outer_dir/middle_dir/subdir/sub.py",
        ]
        assert sorted(snapshot.dirs) == [
            "outer_dir",
            "outer_dir/middle_dir",
            "outer_dir/middle_dir/subdir",
        ]

        # Empty.
        output_digest = self.request_product(Digest, [AddPrefix(digest, "")])
        assert digest == output_digest

        # Illegal.
        with self.assertRaisesRegex(
                Exception,
                r"Cannot add component .*ParentDir.* of path prefix `../something`."
        ):
            self.request_product(Digest, [AddPrefix(digest, "../something")])
Example #15
0
def test_3rdparty_plugin(rule_runner: RuleRunner) -> None:
    target = make_target(
        rule_runner,
        [FileContent("bad.py", b"aws_key = 'JalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY'\n")],
        # NB: `bandit-aws` does not currently work with Python 3.8. See
        #  https://github.com/pantsbuild/pants/issues/10545.
        interpreter_constraints="CPython>=3.6,<3.8",
    )
    result = run_bandit(
        rule_runner, [target], additional_args=["--bandit-extra-requirements=bandit-aws"]
    )
    assert len(result) == 1
    assert result[0].exit_code == 1
    assert "Issue: [C100:hardcoded_aws_key]" in result[0].stdout
    assert result[0].report is None
Example #16
0
def run_prelude_parsing_rule(prelude_content: str) -> BuildFilePreludeSymbols:
    symbols = run_rule_with_mocks(
        evaluate_preludes,
        rule_args=[BuildFileOptions((), prelude_globs=("prelude",))],
        mock_gets=[
            MockGet(
                output_type=DigestContents,
                input_type=PathGlobs,
                mock=lambda _: DigestContents(
                    [FileContent(path="/dev/null/prelude", content=prelude_content.encode())]
                ),
            ),
        ],
    )
    return cast(BuildFilePreludeSymbols, symbols)
Example #17
0
    def test_file_in_directory_creation(self):
        path = "somedir/filename"
        content = b"file contents"

        digest = self.request(
            Digest, [CreateDigest([FileContent(path=path, content=content)])])
        req = Process(
            argv=("/bin/cat", "somedir/filename"),
            input_digest=digest,
            description=
            "Cat a file in a directory to make sure that doesn't break",
        )

        result = self.request(ProcessResult, [req])
        self.assertEqual(result.stdout, content)
Example #18
0
async def setup_analyzer() -> PackageAnalyzerSetup:
    def get_file(filename: str) -> bytes:
        content = pkgutil.get_data("pants.backend.go.util_rules", filename)
        if not content:
            raise AssertionError(f"Unable to find resource for `{filename}`.")
        return content

    analyer_sources_content = [
        FileContent(filename, get_file(filename))
        for filename in ("analyze_package.go", "read.go")
    ]

    source_digest, import_config = await MultiGet(
        Get(Digest, CreateDigest(analyer_sources_content)),
        Get(ImportConfig, ImportConfigRequest,
            ImportConfigRequest.stdlib_only()),
    )

    built_analyzer_pkg = await Get(
        BuiltGoPackage,
        BuildGoPackageRequest(
            import_path="main",
            subpath="",
            digest=source_digest,
            go_file_names=tuple(fc.path for fc in analyer_sources_content),
            s_file_names=(),
            direct_dependencies=(),
            minimum_go_version=None,
        ),
    )
    main_pkg_a_file_path = built_analyzer_pkg.import_paths_to_pkg_a_files[
        "main"]
    input_digest = await Get(
        Digest, MergeDigests([built_analyzer_pkg.digest,
                              import_config.digest]))

    analyzer = await Get(
        LinkedGoBinary,
        LinkGoBinaryRequest(
            input_digest=input_digest,
            archives=(main_pkg_a_file_path, ),
            import_config_path=import_config.CONFIG_PATH,
            output_filename=PackageAnalyzerSetup.PATH,
            description="Link Go package analyzer",
        ),
    )

    return PackageAnalyzerSetup(analyzer.digest)
def test_works_with_python27(rule_runner: RuleRunner) -> None:
    """A regression test that we can properly handle Python 2-only third-party dependencies.

    There was a bug that this would cause the runner PEX to fail to execute because it did not have
    Python 3 distributions of the requirements.
    """
    rule_runner.add_to_build_file(
        "",
        dedent("""\
            # Both requirements are a) typed and b) compatible with Py2 and Py3. However, `x690`
            # has a distinct wheel for Py2 vs. Py3, whereas libumi has a universal wheel. We expect
            # both to be usable, even though libumi is not compatible with Py3.

            python_requirement_library(
                name="libumi",
                requirements=["libumi==0.0.2"],
            )

            python_requirement_library(
                name="x690",
                requirements=["x690==0.2.0"],
            )
            """),
    )
    source_file = FileContent(
        f"{PACKAGE}/py2.py",
        dedent("""\
            from libumi import hello_world
            from x690 import types

            print "Blast from the past!"
            print hello_world() - 21  # MyPy should fail. You can't subtract an `int` from `bytes`.
            """).encode(),
    )
    target = make_target(rule_runner, [source_file],
                         interpreter_constraints="==2.7.*")
    result = run_mypy(rule_runner, [target], passthrough_args="--py2")
    assert len(result) == 1
    assert result[0].exit_code == 1
    assert "Failed to execute PEX file" not in result[0].stderr
    assert (
        "Cannot find implementation or library stub for module named 'x690'"
        not in result[0].stdout)
    assert (
        "Cannot find implementation or library stub for module named 'libumi'"
        not in result[0].stdout)
    assert f"{PACKAGE}/py2.py:5: error: Unsupported operand types" in result[
        0].stdout
Example #20
0
def test_pex_environment(rule_runner: RuleRunner, pex_type: type[Pex | VenvPex]) -> None:
    sources = rule_runner.request(
        Digest,
        [
            CreateDigest(
                (
                    FileContent(
                        path="main.py",
                        content=textwrap.dedent(
                            """
                            from os import environ
                            print(f"LANG={environ.get('LANG')}")
                            print(f"ftp_proxy={environ.get('ftp_proxy')}")
                            """
                        ).encode(),
                    ),
                )
            ),
        ],
    )
    pex_output = create_pex_and_get_all_data(
        rule_runner,
        pex_type=pex_type,
        main=EntryPoint("main"),
        sources=sources,
        additional_pants_args=(
            "--subprocess-environment-env-vars=LANG",  # Value should come from environment.
            "--subprocess-environment-env-vars=ftp_proxy=dummyproxy",
        ),
        interpreter_constraints=PexInterpreterConstraints(["CPython>=3.6"]),
        env={"LANG": "es_PY.UTF-8"},
    )

    pex = pex_output["pex"]
    pex_process_type = PexProcess if isinstance(pex, Pex) else VenvPexProcess
    process = rule_runner.request(
        Process,
        [
            pex_process_type(
                pex,
                description="Run the pex and check its reported environment",
            ),
        ],
    )

    result = rule_runner.request(ProcessResult, [process])
    assert b"LANG=es_PY.UTF-8" in result.stdout
    assert b"ftp_proxy=dummyproxy" in result.stdout
Example #21
0
def test_additional_inputs(rule_runner: RuleRunner) -> None:
    # We use pex's --preamble-file option to set a custom preamble from a file.
    # This verifies that the file was indeed provided as additional input to the pex call.
    preamble_file = "custom_preamble.txt"
    preamble = "#!CUSTOM PREAMBLE\n"
    additional_inputs = rule_runner.request(
        Digest, [CreateDigest([FileContent(path=preamble_file, content=preamble.encode())])]
    )
    additional_pex_args = (f"--preamble-file={preamble_file}",)
    pex_output = create_pex_and_get_all_data(
        rule_runner, additional_inputs=additional_inputs, additional_pex_args=additional_pex_args
    )
    with zipfile.ZipFile(pex_output["local_path"], "r") as zipfp:
        with zipfp.open("__main__.py", "r") as main:
            main_content = main.read().decode()
    assert main_content[: len(preamble)] == preamble
def test_respects_passthrough_args(rule_runner: RuleRunner) -> None:
    source = FileContent(
        path=f"{PACKAGE}/test_config.py",
        content=dedent("""\
            def test_run_me():
              pass

            def test_ignore_me():
              pass
            """).encode(),
    )
    tgt = create_test_target(rule_runner, [source])
    result = run_pytest(rule_runner, tgt, passthrough_args="-k test_run_me")
    assert result.exit_code == 0
    assert f"{PACKAGE}/test_config.py ." in result.stdout
    assert "collected 2 items / 1 deselected / 1 selected" in result.stdout
def test_thirdparty_dep(rule_runner: RuleRunner) -> None:
    setup_thirdparty_dep(rule_runner)
    source = FileContent(
        path=f"{PACKAGE}/test_3rdparty_dep.py",
        content=dedent("""\
            from ordered_set import OrderedSet

            def test():
              assert OrderedSet((1, 2)) == OrderedSet([1, 2])
            """).encode(),
    )
    tgt = create_test_target(rule_runner, [source],
                             dependencies=["3rdparty/python:ordered-set"])
    result = run_pytest(rule_runner, tgt)
    assert result.exit_code == 0
    assert f"{PACKAGE}/test_3rdparty_dep.py ." in result.stdout
Example #24
0
    def test_not_executable(self):
        file_name = "echo.sh"
        file_contents = b'#!/bin/bash -eu\necho "Hello"\n'

        digest = self.request(Digest, [
            CreateDigest([FileContent(path=file_name, content=file_contents)])
        ])
        req = Process(
            argv=("./echo.sh", ),
            input_digest=digest,
            description="cat the contents of this file",
        )

        with pytest.raises(ExecutionError) as exc:
            self.request(ProcessResult, [req])
        assert "Permission" in str(exc.value)
Example #25
0
def test_digest_entries_handles_empty_directory(
        rule_runner: RuleRunner) -> None:
    digest = rule_runner.request(Digest, [
        CreateDigest([Directory("a/b"),
                      FileContent("a/foo.txt", b"four\n")])
    ])
    entries = rule_runner.request(DigestEntries, [digest])
    assert entries == DigestEntries([
        Directory("a/b"),
        FileEntry(
            "a/foo.txt",
            FileDigest(
                "ab929fcd5594037960792ea0b98caf5fdaf6b60645e4ef248c28db74260f393e",
                5),
        ),
    ])
Example #26
0
def generate_original_digest(rule_runner: RuleRunner) -> Digest:
    files = [
        FileContent(path, b"dummy content") for path in [
            "a.txt",
            "b.txt",
            "c.txt",
            "subdir/a.txt",
            "subdir/b.txt",
            "subdir2/a.txt",
            "subdir2/nested_subdir/x.txt",
        ]
    ]
    return rule_runner.request(
        Digest,
        [CreateDigest(files)],
    )
    def test_thirdparty_dep(self) -> None:
        self.setup_thirdparty_dep()
        source = FileContent(
            path="test_3rdparty_dep.py",
            content=dedent("""\
                from ordered_set import OrderedSet

                def test():
                  assert OrderedSet((1, 2)) == OrderedSet([1, 2])
                """).encode(),
        )
        self.create_python_test_target(
            [source], dependencies=["3rdparty/python:ordered-set"])
        result = self.run_pytest()
        assert result.status == Status.SUCCESS
        assert "test_3rdparty_dep.py ." in result.stdout
Example #28
0
    def test_input_file_creation(self):
        file_name = 'some.filename'
        file_contents = b'some file contents'

        input_file = InputFilesContent((FileContent(path=file_name,
                                                    content=file_contents), ))
        digest, = self.scheduler.product_request(Digest, [input_file])

        req = ExecuteProcessRequest(
            argv=('/bin/cat', file_name),
            input_files=digest,
            description='cat the contents of this file',
        )

        result, = self.scheduler.product_request(ExecuteProcessResult, [req])
        self.assertEqual(result.stdout, file_contents)
    def test_respects_passthrough_args(self) -> None:
        source = FileContent(
            path="test_config.py",
            content=dedent("""\
                def test_run_me():
                  pass

                def test_ignore_me():
                  pass
                """).encode(),
        )
        self.create_python_test_target([source])
        result = self.run_pytest(passthrough_args="-k test_run_me")
        assert result.status == Status.SUCCESS
        assert "test_config.py ." in result.stdout
        assert "collected 2 items / 1 deselected / 1 selected" in result.stdout
Example #30
0
    def test_not_executable(self):
        file_name = "echo.sh"
        file_contents = b'#!/bin/bash -eu\necho "Hello"\n'

        digest = self.request_single_product(
            Digest,
            CreateDigest([FileContent(path=file_name, content=file_contents)]))
        req = Process(
            argv=("./echo.sh", ),
            input_digest=digest,
            description="cat the contents of this file",
        )

        with self.assertRaisesWithMessageContaining(ExecutionError,
                                                    "Permission"):
            self.request_single_product(ProcessResult, req)