• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 20826906489

08 Jan 2026 06:09PM UTC coverage: 80.192% (-0.08%) from 80.274%
20826906489

Pull #22987

github

web-flow
Merge aa52dd80f into 0d471f924
Pull Request #22987: WIP DRAFT: Pex 2.77.1 tests

3 of 3 new or added lines in 1 file covered. (100.0%)

90 existing lines in 15 files now uncovered.

78714 of 98157 relevant lines covered (80.19%)

3.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.33
/src/python/pants/base/specs_integration_test.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
1✔
5

6
from textwrap import dedent
1✔
7

8
from pants.testutil.pants_integration_test import PantsResult, run_pants, setup_tmpdir
1✔
9
from pants.testutil.python_interpreter_selection import skip_unless_python39_present
1✔
10

11
SOURCES = {
1✔
12
    # NB: This uses recursive globs for the `python_sources` and `python_tests` target generators,
13
    # even though we recommend 1:1:1, because it tests out our handling of where a generated
14
    # target is "resident" to.
15
    "py/BUILD": dedent(
16
        """\
17
        pex_binary(name="bin", entry_point="app.py")
18
        python_sources(name="lib", sources=["**/*.py", "!**/*_test.py"])
19
        python_tests(name="tests", sources=["**/*_test.py"])
20
        """
21
    ),
22
    "py/app.py": dedent(
23
        """\
24
        from {tmpdir}.py.base.common import NAME
25
        from {tmpdir}.py.base.strutil import capitalize
26

27
        if __name__ == "__main__":
28
            print(capitalize(NAME))
29
        """
30
    ),
31
    "py/base/common.py": "NAME = 'pantsbuild'",
32
    "py/base/common_test.py": dedent(
33
        """\
34
        from {tmpdir}.py.base.common import NAME
35

36
        def test_name():
37
            assert NAME == "pantsbuild"
38
        """
39
    ),
40
    "py/utils/strutil.py": dedent(
41
        """\
42
        def capitalize(s):
43
            return s.capitalize()
44
        """
45
    ),
46
    "py/utils/strutil_test.py": dedent(
47
        """\
48
        from {tmpdir}.py.utils.strutil import capitalize
49

50
        def test_capitalize():
51
            assert capitalize("hello") == "Hello"
52
        """
53
    ),
54
}
55

56

57
def run(args: list[str]) -> PantsResult:
1✔
58
    result = run_pants(
1✔
59
        [
60
            "--backend-packages=pants.backend.python",
61
            "--backend-packages=pants.backend.experimental.go",
62
            "--python-interpreter-constraints=['==3.9.*']",
63
            "--pants-ignore=__pycache__",
64
            *args,
65
        ]
66
    )
67
    result.assert_success()
1✔
68
    return result
1✔
69

70

71
@skip_unless_python39_present
1✔
72
def test_address_literal() -> None:
1✔
73
    """Semantics:
74

75
    * project introspection: do not replace target generators with generated.
76
    * "build" goals: replace target generators with generated.
77
    """
78
    with setup_tmpdir(SOURCES) as tmpdir:
1✔
79
        list_specs = [f"{tmpdir}/py:bin", f"{tmpdir}/py:tests", f"{tmpdir}/py/app.py:lib"]
1✔
80
        assert run(["list", *list_specs]).stdout.splitlines() == list_specs
1✔
81

82
        test_result = run(["test", f"{tmpdir}/py:tests"]).stderr
1✔
UNCOV
83
        assert f"{tmpdir}/py/utils/strutil_test.py:../tests - succeeded." in test_result
×
UNCOV
84
        assert f"{tmpdir}/py/base/common_test.py:../tests - succeeded." in test_result
×
UNCOV
85
        assert f"{tmpdir}/py:tests" not in test_result
×
86

87

88
@skip_unless_python39_present
1✔
89
def test_sibling_addresses() -> None:
1✔
90
    """Semantics:
91

92
    * project introspection: include all targets that are "resident" to the directory, i.e.
93
        defined there or generated and reside there.
94
    * "build" goals: match all targets that are resident to the directory, but replace any
95
        target generators with their generated targets, even if those generated targets are resident to another directory!
96
    """
97
    with setup_tmpdir(SOURCES) as tmpdir:
1✔
98
        assert run(["list", f"{tmpdir}/py/utils:"]).stdout.splitlines() == [
1✔
99
            f"{tmpdir}/py/utils/strutil.py:../lib",
100
            f"{tmpdir}/py/utils/strutil_test.py:../tests",
101
        ]
102
        assert run(["list", f"{tmpdir}/py:"]).stdout.splitlines() == [
1✔
103
            f"{tmpdir}/py:bin",
104
            f"{tmpdir}/py:lib",
105
            f"{tmpdir}/py:tests",
106
            f"{tmpdir}/py/app.py:lib",
107
        ]
108

109
        # Even though no `python_test` targets are explicitly defined in `util/`, a generated
110
        # target is resident there.
111
        test_result = run(["test", f"{tmpdir}/py/utils:"]).stderr
1✔
UNCOV
112
        assert f"{tmpdir}/py/utils/strutil_test.py:../tests - succeeded." in test_result
×
UNCOV
113
        assert f"{tmpdir}/py/base/common_test.py:../tests" not in test_result
×
UNCOV
114
        assert f"{tmpdir}/py:tests" not in test_result
×
115

116
        # Even though no `_test.py` files live in this dir, we match the `python_tests` target
117
        # and replace it with its generated targets.
UNCOV
118
        test_result = run(["test", f"{tmpdir}/py:"]).stderr
×
UNCOV
119
        assert f"{tmpdir}/py/utils/strutil_test.py:../tests - succeeded." in test_result
×
UNCOV
120
        assert f"{tmpdir}/py/base/common_test.py:../tests" in test_result
×
UNCOV
121
        assert f"{tmpdir}/py:tests" not in test_result
×
122

123

124
@skip_unless_python39_present
1✔
125
def test_descendent_addresses() -> None:
1✔
126
    """Semantics are the same as sibling addresses, only recursive."""
127
    with setup_tmpdir(SOURCES) as tmpdir:
1✔
128
        assert run(["list", f"{tmpdir}/py::"]).stdout.splitlines() == [
1✔
129
            f"{tmpdir}/py:bin",
130
            f"{tmpdir}/py:lib",
131
            f"{tmpdir}/py:tests",
132
            f"{tmpdir}/py/app.py:lib",
133
            f"{tmpdir}/py/base/common.py:../lib",
134
            f"{tmpdir}/py/base/common_test.py:../tests",
135
            f"{tmpdir}/py/utils/strutil.py:../lib",
136
            f"{tmpdir}/py/utils/strutil_test.py:../tests",
137
        ]
138

139
        test_result = run(["test", f"{tmpdir}/py::"]).stderr
1✔
UNCOV
140
        assert f"{tmpdir}/py/utils/strutil_test.py:../tests - succeeded." in test_result
×
UNCOV
141
        assert f"{tmpdir}/py/base/common_test.py:../tests" in test_result
×
UNCOV
142
        assert f"{tmpdir}/py:tests" not in test_result
×
143

144

145
@skip_unless_python39_present
1✔
146
def test_file_arg() -> None:
1✔
147
    """Semantics: find the 'owning' target, using generated target rather than target generator
148
    when possible (regardless of project introspection vs. "build" goal).
149
    """
150
    with setup_tmpdir(SOURCES) as tmpdir:
1✔
151
        assert run(
1✔
152
            ["list", f"{tmpdir}/py/app.py", f"{tmpdir}/py/utils/strutil_test.py"]
153
        ).stdout.splitlines() == [
154
            f"{tmpdir}/py/app.py:lib",
155
            f"{tmpdir}/py/utils/strutil_test.py:../tests",
156
        ]
157

158

159
def test_build_ignore_list() -> None:
1✔
160
    with setup_tmpdir({"dir/BUILD": "target()"}) as tmpdir:
1✔
161
        ignore_result = run_pants([f"--build-ignore={tmpdir}/dir", "list", f"{tmpdir}/dir:dir"])
1✔
162
        no_ignore_result = run_pants(["list", f"{tmpdir}/dir:dir"])
1✔
163
    ignore_result.assert_failure()
1✔
164
    assert f"{tmpdir}/dir" in ignore_result.stderr
1✔
165
    no_ignore_result.assert_success()
1✔
166
    assert f"{tmpdir}/dir" in no_ignore_result.stdout
1✔
167

168

169
def test_build_ignore_dependency() -> None:
1✔
170
    sources = {
1✔
171
        "dir1/f.txt": "",
172
        "dir1/BUILD": "files(sources=['*.txt'])",
173
        "dir2/f.txt": "",
174
        "dir2/BUILD": "files(sources=['*.txt'], dependencies=['{tmpdir}/dir1'])",
175
    }
176
    with setup_tmpdir(sources) as tmpdir:
1✔
177
        ignore_result = run_pants(
1✔
178
            [f"--build-ignore={tmpdir}/dir1", "dependencies", f"{tmpdir}/dir2/f.txt"]
179
        )
180
        no_ignore_result = run_pants(["dependencies", f"{tmpdir}/dir2/f.txt"])
1✔
181
    ignore_result.assert_failure()
1✔
182
    assert f"{tmpdir}/dir1" in ignore_result.stderr
1✔
183
    no_ignore_result.assert_success()
1✔
184
    assert f"{tmpdir}/dir1" in no_ignore_result.stdout
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc