def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.py": BAD_FILE, "BUILD": "python_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) lint_results, fmt_result = run_black(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "1 file would be reformatted" in lint_results[0].stderr assert "1 file reformatted" in fmt_result.stderr assert fmt_result.output == get_snapshot(rule_runner, {"f.py": FIXED_BAD_FILE}) assert fmt_result.did_change is True
def test_stub_files(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "good.pyi": GOOD_FILE, "bad.pyi": BAD_FILE, "BUILD": "python_sources(name='t')" }) good_tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="good.pyi")) lint_results, fmt_result = run_docformatter(rule_runner, [good_tgt]) assert len(lint_results) == 1 and lint_results[0].exit_code == 0 assert lint_results[0].stderr == "" and fmt_result.stdout == "" assert fmt_result.output == get_digest(rule_runner, {"good.pyi": GOOD_FILE}) assert not fmt_result.did_change bad_tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="bad.pyi")) lint_results, fmt_result = run_docformatter(rule_runner, [bad_tgt]) assert len(lint_results) == 1 and lint_results[0].exit_code == 3 assert "bad.pyi" in lint_results[0].stderr assert fmt_result.output == get_digest(rule_runner, {"bad.pyi": FIXED_BAD_FILE}) assert fmt_result.did_change
def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "Bar.scala": BAD_FILE, "BUILD": "scala_sources(name='t')", ".scalafmt.conf": BASIC_SCALAFMT_CONF, }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="Bar.scala")) lint_results, fmt_result = run_scalafmt(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "Bar.scala\n" == lint_results[0].stdout assert fmt_result.output == get_snapshot(rule_runner, {"Bar.scala": FIXED_BAD_FILE}) assert fmt_result.did_change is True
def test_passthrough_args(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "some_file_name.py": PY_38_BAD_FILE, "BUILD": "python_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="some_file_name.py")) fmt_result = run_pyupgrade( rule_runner, [tgt], pyupgrade_arg="--py38-plus", ) assert fmt_result.output == get_snapshot( rule_runner, {"some_file_name.py": PY_38_FIXED_BAD_FILE}) assert fmt_result.did_change is True
def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.go": BAD_FILE, "go.mod": GO_MOD, "BUILD": "go_mod(name='mod')\ngo_package(name='pkg')\n", }) tgt = rule_runner.get_target(Address("", target_name="pkg")) lint_results = run_go_vet(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 2 assert ("./f.go:4:5: Printf format %s reads arg #1, but call has 0 args" in lint_results[0].stderr)
def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ f"{PACKAGE}/tests.py": dedent("""\ def test(): assert False """), f"{PACKAGE}/BUILD": "python_tests()", }) tgt = rule_runner.get_target( Address(PACKAGE, relative_file_path="tests.py")) result = run_pytest(rule_runner, tgt) assert result.exit_code == 1 assert f"{PACKAGE}/tests.py F" in result.stdout
def test_infer_java_imports_same_target(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "BUILD": dedent("""\ java_sources(name = 't') """), "A.java": dedent("""\ package org.pantsbuild.a; public class A {} """), "B.java": dedent("""\ package org.pantsbuild.b; public class B {} """), }) target_a = rule_runner.get_target( Address("", target_name="t", relative_file_path="A.java")) target_b = rule_runner.get_target( Address("", target_name="t", relative_file_path="B.java")) print([target_a, target_b]) assert (rule_runner.request( InferredDependencies, [InferJavaImportDependencies(target_a[JavaSourceField])], ) == InferredDependencies(dependencies=[])) assert (rule_runner.request( InferredDependencies, [InferJavaImportDependencies(target_b[JavaSourceField])], ) == InferredDependencies(dependencies=[]))
def test_run_only_on_specified_files(rule_runner: RuleRunner) -> None: rule_runner.write_files({ f"{PACKAGE}/good.py": GOOD_FILE, f"{PACKAGE}/bad.py": BAD_FILE, f"{PACKAGE}/BUILD": dedent("""\ python_sources(name='good', sources=['good.py'], dependencies=[':bad']) python_sources(name='bad', sources=['bad.py']) """), }) tgt = rule_runner.get_target( Address(PACKAGE, target_name="good", relative_file_path="good.py")) assert_success(rule_runner, tgt)
def test_respects_passthrough_args(rule_runner: RuleRunner) -> None: content = '"""\nOne line docstring acting like it\'s multiline.\n"""\n' rule_runner.write_files({ "f.py": content, "BUILD": "python_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) fmt_result = run_docformatter( rule_runner, [tgt], extra_args=["--docformatter-args='--make-summary-multi-line'"], ) assert fmt_result.output == get_snapshot(rule_runner, {"f.py": content}) assert fmt_result.did_change is False
def test_works_with_python39(rule_runner: RuleRunner) -> None: """MyPy's typed-ast dependency does not understand Python 3.9, so we must instead run MyPy with Python 3.9 when relevant.""" rule_runner.write_files({ f"{PACKAGE}/f.py": dedent("""\ @lambda _: int def replaced(x: bool) -> str: return "42" if x is True else "1/137" """), f"{PACKAGE}/BUILD": "python_sources(interpreter_constraints=['>=3.9'])", }) tgt = rule_runner.get_target(Address(PACKAGE, relative_file_path="f.py")) assert_success(rule_runner, tgt)
def test_config_files(rule_runner: RuleRunner) -> None: rule_runner.write_files({ ".hadolint.yaml": "ignored: [DL3006, DL3011]", "a/Dockerfile": BAD_FILE, "a/BUILD": "docker_image()", "b/Dockerfile": BAD_FILE, "b/BUILD": "docker_image()", "c/BUILD": "docker_image()", "c/Dockerfile": "EXPOSE 123456", }) tgts = [ rule_runner.get_target(Address("a")), rule_runner.get_target(Address("b")), ] result = run_hadolint(rule_runner, tgts) assert len(result) == 1 assert result[0].exit_code == 0 assert "a/Dockerfile" not in result[0].stdout assert "b/Dockerfile " not in result[0].stdout tgt = rule_runner.get_target(Address("c")) assert_success(rule_runner, tgt, extra_args=["--hadolint-config=.hadolint.yaml"])
def test_passing(rule_runner: RuleRunner, major_minor_interpreter: str) -> None: rule_runner.write_files({ "f.py": GOOD_FILE, "BUILD": "python_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) assert_success( rule_runner, tgt, extra_args=[ f"--python-interpreter-constraints=['=={major_minor_interpreter}.*']" ], )
def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.py": PY_36_BAD_FILE, "BUILD": "python_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) lint_results, fmt_result = run_pyupgrade(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "Rewriting f.py" in lint_results[0].stderr assert fmt_result.skipped is False assert fmt_result.output == get_snapshot(rule_runner, {"f.py": PY_36_FIXED_BAD_FILE}) assert fmt_result.did_change is True
def assert_pants_requirement( rule_runner: RuleRunner, build_file_entry: str, *, expected_target_name: str, expected_dist: str = "pantsbuild.pants", expected_module: str = "pants", ) -> None: rule_runner.add_to_build_file("3rdparty/python", f"{build_file_entry}\n") target = rule_runner.get_target( Address("3rdparty/python", target_name=expected_target_name)) assert isinstance(target, PythonRequirementTarget) assert target[PythonRequirementsField].value == ( PipRequirement.parse(f"{expected_dist}=={pants_version()}"), ) assert target[PythonRequirementModulesField].value == (expected_module, )
def test_failing_source(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.py": BAD_FILE, "BUILD": "python_library(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) lint_results, fmt_result = run_isort(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "f.py Imports are incorrectly sorted" in lint_results[0].stderr assert fmt_result.stdout == "Fixing f.py\n" assert fmt_result.output == get_digest(rule_runner, {"f.py": FIXED_BAD_FILE}) assert fmt_result.did_change is True
def test_success_on_unformatted_file(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "main.cpp": UNFORMATTED_FILE, "BUILD": "cc_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="main.cpp")) fmt_result = run_clangformat( rule_runner, [tgt], ) assert fmt_result.skipped is False assert fmt_result.output == get_snapshot( rule_runner, {"main.cpp": DEFAULT_FORMATTED_FILE}) assert fmt_result.did_change is True
def test_skip(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.go": BAD_FILE, "go.mod": GO_MOD, "BUILD": "go_mod(name='mod')\ngo_package(name='pkg')" }) tgt = rule_runner.get_target(Address("", target_name="pkg")) lint_results, fmt_result = run_gofmt(rule_runner, [tgt], extra_args=["--gofmt-skip"]) assert not lint_results assert fmt_result.skipped is True assert fmt_result.did_change is False
def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "Bar.java": BAD_FILE, "BUILD": "java_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="Bar.java")) lint_results, fmt_result = run_google_java_format(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "The following Java files require formatting:\nBar.java\n\n" == lint_results[ 0].stdout assert fmt_result.output == get_snapshot(rule_runner, {"Bar.java": FIXED_BAD_FILE}) assert fmt_result.did_change is True
def test_report_file(rule_runner: RuleRunner) -> None: rule_runner.write_files({ f"{PACKAGE}/f.py": BAD_FILE, f"{PACKAGE}/BUILD": "python_sources()" }) tgt = rule_runner.get_target(Address(PACKAGE, relative_file_path="f.py")) result = run_pylint( rule_runner, [tgt], extra_args=["--pylint-args='--output=reports/output.txt'"]) assert len(result) == 1 assert result[0].exit_code == PYLINT_CONVENTION_FAILURE_RETURN_CODE assert result[0].stdout.strip() == "" report_files = rule_runner.request(DigestContents, [result[0].report]) assert len(report_files) == 1 assert f"{PACKAGE}/f.py:2:0: C0103" in report_files[0].content.decode()
def test_works_with_python38(rule_runner: RuleRunner) -> None: """MyPy's typed-ast dependency does not understand Python 3.8, so we must instead run MyPy with Python 3.8 when relevant.""" rule_runner.write_files({ f"{PACKAGE}/f.py": dedent("""\ x = 0 if y := x: print("x is truthy and now assigned to y") """), f"{PACKAGE}/BUILD": "python_sources(interpreter_constraints=['>=3.8'])", }) tgt = rule_runner.get_target(Address(PACKAGE, relative_file_path="f.py")) assert_success(rule_runner, tgt)
def test_protobuf_mypy(rule_runner: RuleRunner) -> None: rule_runner = RuleRunner( rules=[ *rule_runner.rules, *protobuf_rules(), *protobuf_subsystem_rules() ], target_types=[*rule_runner.target_types, ProtobufSourceTarget], ) rule_runner.write_files({ "BUILD": ("python_requirement(name='protobuf', requirements=['protobuf==3.13.0'])" ), f"{PACKAGE}/__init__.py": "", f"{PACKAGE}/proto.proto": dedent("""\ syntax = "proto3"; package project; message Person { string name = 1; int32 id = 2; string email = 3; } """), f"{PACKAGE}/f.py": dedent("""\ from project.proto_pb2 import Person x = Person(name=123, id="abc", email=None) """), f"{PACKAGE}/BUILD": dedent("""\ python_sources(dependencies=[':proto']) protobuf_source(name='proto', source='proto.proto') """), }) tgt = rule_runner.get_target(Address(PACKAGE, relative_file_path="f.py")) result = run_mypy( rule_runner, [tgt], extra_args=["--python-protobuf-mypy-plugin"], ) assert len(result) == 1 assert 'Argument "name" to "Person" has incompatible type "int"' in result[ 0].stdout assert 'Argument "id" to "Person" has incompatible type "str"' in result[ 0].stdout assert result[0].exit_code == 1
def test_generate_source_targets() -> None: rule_runner = RuleRunner( rules=[ *target_types.rules(), QueryRule(GeneratedTargets, [GenerateTargetsFromProtobufSources]), ], target_types=[ProtobufSourcesGeneratorTarget], ) rule_runner.write_files({ "src/proto/BUILD": dedent("""\ protobuf_sources( name='lib', sources=['**/*.proto'], overrides={'f1.proto': {'tags': ['overridden']}}, ) """), "src/proto/f1.proto": "", "src/proto/f2.proto": "", "src/proto/subdir/f.proto": "", }) generator = rule_runner.get_target(Address("src/proto", target_name="lib")) def gen_tgt(rel_fp: str, tags: list[str] | None = None) -> ProtobufSourceTarget: return ProtobufSourceTarget( { SingleSourceField.alias: rel_fp, Tags.alias: tags }, Address("src/proto", target_name="lib", relative_file_path=rel_fp), residence_dir=os.path.dirname(os.path.join("src/proto", rel_fp)), ) generated = rule_runner.request( GeneratedTargets, [GenerateTargetsFromProtobufSources(generator)]) assert generated == GeneratedTargets( generator, { gen_tgt("f1.proto", tags=["overridden"]), gen_tgt("f2.proto"), gen_tgt("subdir/f.proto"), }, )
def assert_chroot( rule_runner: RuleRunner, expected_files: list[str], expected_setup_script: str, expected_setup_kwargs, addr: Address, ) -> None: tgt = rule_runner.get_target(addr) chroot = rule_runner.request( SetupPyChroot, [SetupPyChrootRequest(ExportedTarget(tgt), py2=False)], ) snapshot = rule_runner.request(Snapshot, [chroot.digest]) assert sorted(expected_files) == sorted(snapshot.files) assert chroot.setup_script == expected_setup_script assert expected_setup_kwargs == chroot.setup_kwargs.kwargs
def test_passthrough_args(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.sh": NEEDS_CONFIG_FILE, "BUILD": "shell_library(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.sh")) lint_results, fmt_result = run_shfmt(rule_runner, [tgt], extra_args=["--shfmt-args=-ci"]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "f.sh.orig" in lint_results[0].stdout assert fmt_result.stdout == "f.sh\n" assert fmt_result.output == get_digest(rule_runner, {"f.sh": FIXED_NEEDS_CONFIG_FILE}) assert fmt_result.did_change is True
def test_config_file(rule_runner: RuleRunner, path: str, extra_args: list[str]) -> None: rule_runner.write_files( { "f.py": NEEDS_CONFIG_FILE, "BUILD": "python_library(name='t', interpreter_constraints=['==3.9.*'])", path: "[isort]\ncombine_as_imports=True\n", } ) tgt = rule_runner.get_target(Address("", target_name="t", relative_file_path="f.py")) lint_results, fmt_result = run_isort(rule_runner, [tgt], extra_args=extra_args) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "f.py Imports are incorrectly sorted" in lint_results[0].stderr assert fmt_result.stdout == "Fixing f.py\n" assert fmt_result.output == get_digest(rule_runner, {"f.py": FIXED_NEEDS_CONFIG_FILE}) assert fmt_result.did_change is True
def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.go": BAD_FILE, "go.mod": GO_MOD, "BUILD": "go_mod(name='mod')" }) tgt = rule_runner.get_target( Address("", target_name="mod", generated_name="./")) lint_results, fmt_result = run_gofmt(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "f.go" in lint_results[0].stdout assert fmt_result.stderr == "" assert fmt_result.output == get_digest(rule_runner, {"f.go": FIXED_BAD_FILE}) assert fmt_result.did_change is True
def test_failing(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.py": BAD_FILE, "BUILD": "python_sources(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) lint_results, fmt_result = run_yapf(rule_runner, [tgt]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert all(msg in lint_results[0].stdout for msg in ("reformatted", "original")) assert fmt_result.skipped is False assert fmt_result.output == get_snapshot(rule_runner, {"f.py": FIXED_BAD_FILE}) assert fmt_result.did_change is True
def test_report_file(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.py": BAD_FILE, "BUILD": "python_library(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) result = run_flake8( rule_runner, [tgt], extra_args=["--flake8-args='--output-file=reports/foo.txt'"]) assert len(result) == 1 assert result[0].exit_code == 1 assert result[0].stdout.strip() == "" report_files = rule_runner.request(DigestContents, [result[0].report]) assert len(report_files) == 1 assert "f.py:1:1: F401" in report_files[0].content.decode()
def test_config(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "main.cpp": UNFORMATTED_FILE, ".clang-format": CLANG_FORMAT_FILE, "BUILD": "cc_sources(name='t')", }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="main.cpp")) fmt_result = run_clangformat( rule_runner, [tgt], ) assert fmt_result.skipped is False assert fmt_result.output == get_snapshot( rule_runner, {"main.cpp": MOZILLA_FORMATTED_FILE}) assert fmt_result.did_change is True
def test_passthrough_args(rule_runner: RuleRunner) -> None: rule_runner.write_files({ "f.py": NEEDS_CONFIG_FILE, "BUILD": "python_library(name='t')" }) tgt = rule_runner.get_target( Address("", target_name="t", relative_file_path="f.py")) lint_results, fmt_result = run_isort( rule_runner, [tgt], extra_args=["--isort-args='--combine-as'"]) assert len(lint_results) == 1 assert lint_results[0].exit_code == 1 assert "f.py Imports are incorrectly sorted" in lint_results[0].stderr assert fmt_result.stdout == "Fixing f.py\n" assert fmt_result.output == get_digest(rule_runner, {"f.py": FIXED_NEEDS_CONFIG_FILE}) assert fmt_result.did_change is True