cool-easter-32542
07/18/2023, 10:57 AMoverrides field of a target in a BUILD file. This is because the later key would override whatever was set before, very likely this is undesired.
python_sources(
name="lib",
overrides={
"main.py": {"dependencies": ["//:reqs#pytest"]},
},
)
yields
$ pants dependencies helloworld/main.py
//:reqs#ansicolors
//:reqs#pytest
helloworld/greet/greeting.py:lib
helloworld/main.py:lib
and
python_sources(
name="lib",
overrides={
"main.py": {"dependencies": ["//:reqs#pytest"]},
"main.py": {"dependencies": []},
},
)
yields
$ pants dependencies helloworld/main.py
//:reqs#ansicolors
helloworld/greet/greeting.py:lib
helloworld/main.py:lib
Describe the solution you'd like
I believe a user would never want to have a second key in the dictionary of the overrides field and we should fail if we find one.
Describe alternatives you've considered
Pants already fails when a field in the target declaration is passed twice which is helpful:
pants dependencies helloworld/main.py
11:16:53.00 [ERROR] 1 Exception encountered:
Engine traceback:
in `dependencies` goal
in Find targets from input specs
MappingError: Failed to parse ./helloworld/BUILD:
SyntaxError: keyword argument repeated: name (<string>, line 5)
We should have something similar but for the overrides field as well.
This may be not trivial as the dictionary is evaluated when loaded into Python so by nature there are no duplicate keys in the dictionary once it's loaded. I wonder whether we'll have to construct an AST and inspect the keys.
Additional context
One can currently use custom tooling to query the overrides, e.g.
Given
python_sources(
name="lib",
overrides={
"main.py": {"dependencies": ["//:reqs#pytest"]},
"main.py": {"dependencies": []},
},
)
one can do
$ echo $(~/Applications/buildozer-linux-amd64 -stdout 'print name overrides' -:%python_sources < helloworld/BUILD) | grep -o '{.*' > overrides.json
$ cat overrides.json
{ "main.py": {"dependencies": ["//:reqs#pytest"]}, "main.py": {"dependencies": []}, }
# now in Python
from pprint import pprint
import ast
with open("overrides.json") as fh:
data = ast.parse(fh.read())
pprint(ast.dump(data))
("Module(body=[Expr(value=Dict(keys=[Constant(value='main.py'), "
"Constant(value='main.py')], "
"values=[Dict(keys=[Constant(value='dependencies')], "
"values=[List(elts=[Constant(value='//:reqs#pytest')], ctx=Load())]), "
"Dict(keys=[Constant(value='dependencies')], values=[List(elts=[], "
'ctx=Load())])]))], type_ignores=[])')
for i in data.body[0].value.keys:
print(i.value)
main.py
main.py
however, it may be very expensive to construct AST for every overrides field.
pantsbuild/pants