stale-truck-36011
08/23/2024, 7:41 AM!!//path/to:target
. I'm not sure if the behavior I'm seeing is a bug, or if I'm misunderstanding something.
I'm running pants 2.21.0
There's an example BUILD
and run steps in the thread
I basically have a structure like in this graph. We use transitive dependencies to figure out which unit tests to run depending on changes in our code base. The test depends on a utility function, that in turn depends on two sets of other dependencies A
and B
. A
and B
are files of the same type, but consider A
as test/mock data, and B
as real data. I would like to exclude B
, and transitively exclude B.1
and B.2
from the dependencies of test
, so that changes to these do not trigger the test. It's still necessary that utils
depend on these.
Here's the issue:
Let's say all files are in src/ex
.
test
is a python_test
, A
and B
are target
, the rest are python_source
I add !!:B
to the dependencies of test
I run pants dependencies --transitive src/ex:test
and see that B
is indeed not a dependency anymore.
However, B.1
and B.2
are listed.
But if I run pants paths --from='src/ex:test' --to='src/ex:B.1'
it returns an empty list, showing that there's no path from test
to B.1
. Removing the !!
line makes this command return the expected path via utils
and B
.
it returns an empty list. Removing thestale-truck-36011
08/23/2024, 7:46 AMtarget(
name="A",
dependencies=[
":A.1",
],
)
target(
name="B",
dependencies=[
":B.1",
":B.2",
],
)
python_source(
name="A.1",
source="A.1.py",
)
python_source(
name="B.1",
source="B.1.py",
)
python_source(
name="B.2",
source="B.2.py",
)
python_source(
name="utils",
source="utils.py",
dependencies=[
":A",
":B",
],
)
python_test(
name="tests",
source="tests.py",
dependencies=[
":utils",
"!!:B",
],
)
Create empty files with
mkdir -p src/ex
cd src/ex
touch tests.py utils.py A.1.py B.1.py B.2.py
cd -
Then you can run
pants dependencies --format=json --transitive src/ex:tests
stale-truck-36011
08/23/2024, 9:03 AMpants --changed-since=HEAD~1 --changed-dependees=transitive test
I want this command to not trigger tests
to run when B.1.py
or B.2.py
are changed. Only when A.1.py
is changed.stale-truck-36011
08/23/2024, 9:15 AM!!:B.1
and !!:B.2
in tests
dependencies
doesn't exclude them at all.
If I do that, edit B.1.py
, and then run
pants --changed-since=HEAD~1 --changed-dependees=transitive list
I see both tests
and B.1
- indicating that the tests would run when changing one of the excluded dependencies. I'm leaning towards this being a bug.
Nevertheless it's very confusing that pants paths
, pants --changed-dependees=transitive test/list
, and pants dependencies --transitive
all produce different results from each other regarding transitive dependencies so I will probably look for another approach.stale-truck-36011
08/26/2024, 7:52 AMsquare-psychiatrist-19087
08/26/2024, 6:07 PMtests
util
and b
right? it will be much easier to understandstale-truck-36011
08/26/2024, 6:45 PMtests
, utils
, A
and B
existed, with this graph:
tests --> utils ----> A
|------> B
Adding`!!:utils` in the dependencies list for tests
would still have A
and B
show up as a transitive dependence. The first example is designed after my already existing dependency graph.square-psychiatrist-19087
08/26/2024, 9:20 PM!:utils
work for you?stale-truck-36011
08/27/2024, 11:30 AMsrc/backend/ex
, and src
and src/backend
are configured as pants roots. There are empty __init__.py
files in the source dirs.
test.py
imports a function from utils.py
utils.py
imports functions from A.py
and B.py
A.py
imports a function from C.py
No excludes in the dependencies for tests
reports
➜ ./pants dependencies --transitive --format=json src/backend/ex:tests
Checking Pants installation...
{
"src/backend/ex:tests": [
"src/backend/ex:A",
"src/backend/ex:B",
"src/backend/ex:C",
"src/backend/ex:utils"
]
}
If I do !:utils
or !!:utils
{
"src/backend/ex:tests": []
}
If I do !:A
I get
{
"src/backend/ex:tests": [
"src/backend/ex:A",
"src/backend/ex:B",
"src/backend/ex:C",
"src/backend/ex:utils"
]
}
If I do !!:A
I get
{
"src/backend/ex:tests": [
"src/backend/ex:B",
"src/backend/ex:C",
"src/backend/ex:utils"
]
}
In the last case, I also expect :C
to be excluded from the dependencies, not only :A
.stale-truck-36011
08/27/2024, 11:31 AM:utils
completely is not preferable, I want to depend on utils but only part of its dependencies. But maybe this is straight up a poor design choice.square-psychiatrist-19087
08/27/2024, 11:38 AMstale-truck-36011
08/27/2024, 11:42 AM:A
, and :B
depended on :C
as well, then :B
and :C
should be included in the dependencies yeah.
To be a bit more concrete about why we have this setup:
A
and B
are configuration files (written in python) for specific use cases, and utils
contains helper functions for loading these from disk. A
can be seen as real data, and B
as mock data, and we don't want to depend on the real data in our unit tests.square-psychiatrist-19087
08/27/2024, 11:43 AMsquare-psychiatrist-19087
08/27/2024, 11:43 AMsquare-psychiatrist-19087
08/27/2024, 11:43 AMtransitive_excludes = await Get(Targets, Addresses(transitive_exclude_addresses))
return TransitiveTargets(
tuple(dependency_mapping.roots_as_targets),
FrozenOrderedSet(dependency_mapping.visited.difference(transitive_excludes)),
)
square-psychiatrist-19087
08/27/2024, 11:44 AMsquare-psychiatrist-19087
08/27/2024, 11:44 AMstale-truck-36011
08/27/2024, 11:47 AMsquare-psychiatrist-19087
08/27/2024, 11:48 AM~:B
to do the real subgraph excludes, I guess somewhere around here
https://github.com/pantsbuild/pants/blob/fb1c6a381520d511c9c12b0598561fb7fe8afb4d/src/python/pants/engine/internals/graph.py#L762-L816square-psychiatrist-19087
08/27/2024, 11:50 AMstale-truck-36011
08/27/2024, 11:51 AMsquare-psychiatrist-19087
08/27/2024, 11:51 AMdef load_resource_a()
def load_resource_b()
def process_resource(r: A | B)
and move load_resource_a
to A and load_resource_b
to Bsquare-psychiatrist-19087
08/27/2024, 11:52 AMstale-truck-36011
08/27/2024, 12:05 PM