Skip to content

Commit f26f530

Browse files
docs: export dependency graph as adjacency list
1 parent d782c03 commit f26f530

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

docs/docs/using-pants/project-introspection.mdx

+66
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,72 @@ To include the original target itself, use `--closed`:
127127
helloworld/main.py:lib
128128
```
129129

130+
## Export dependency graph
131+
132+
Both `dependencies` and `dependents` goals have the `--format` option allowing you to export data in multiple formats.
133+
Exporting information about the dependencies and dependents in JSON format will produce the
134+
[adjacency list](https://en.wikipedia.org/wiki/Adjacency_list) of your dependency graph:
135+
136+
```bash
137+
$ pants dependencies --format=json \
138+
helloworld/greet/greeting.py \
139+
helloworld/translator/translator_test.py
140+
141+
{
142+
"helloworld/greet/greeting.py:lib": [
143+
"//:reqs#setuptools",
144+
"//:reqs#types-setuptools",
145+
"helloworld/greet:translations",
146+
"helloworld/translator/translator.py:lib"
147+
],
148+
"helloworld/translator/translator_test.py:tests": [
149+
"//:reqs#pytest",
150+
"helloworld/translator/translator.py:lib"
151+
]
152+
}
153+
```
154+
155+
This has various applications, and you could analyze, visualize, and process the data further. Sometimes, a fairly
156+
straightforward `jq` query would suffice, but for anything more complex, it may make sense to write a small program
157+
to process the exported graph. For instance, you could:
158+
159+
* find tests with most transitive dependencies
160+
161+
```bash
162+
$ pants dependencies --filter-target-type=python_test --format=json :: \
163+
| jq -r 'to_entries[] | "\(.key)\t\(.value | length)"' \
164+
| sort -k2
165+
```
166+
167+
* find build targets that no one depends on
168+
169+
```bash
170+
$ pants dependents --filter-target-type=resource --format=json :: \
171+
jq -r 'to_entries[] | select(.value | length == 0)'
172+
```
173+
174+
* find project source files that transitively lead to most tests
175+
176+
```python
177+
# depgraph.py
178+
import json
179+
180+
with open("data.json") as fh:
181+
data = json.load(fh)
182+
183+
for source, dependents in data.items():
184+
print(source, len([d for d in dependents if d.startswith("tests/")]))
185+
```
186+
187+
```bash
188+
$ pants dependents --transitive --format=json cheeseshop:: > data.json
189+
$ python3 depgraph.py | sort -k2
190+
```
191+
192+
For more sophisticated graph querying, you may want to look into graph libraries such as [`networkx`](https://networkx.org/).
193+
In a larger repository, it may make sense to track the health of the dependency graph and use the output
194+
of the graph export to identify parts of your codebase that would benefit from refactoring.
195+
130196
## `filedeps` - find which files a target owns
131197

132198
`filedeps` outputs all of the files belonging to a target, based on its `sources` field.

0 commit comments

Comments
 (0)