-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmodulegraph.py
54 lines (44 loc) · 1.78 KB
/
modulegraph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import re
from pathlib import Path
from glob import iglob
from typing import List, Tuple
class ModuleDeps:
"""
Generate a graph of all modules and their dependencies.
By inspecting the graph you can check the dependencies of each module. This
way, you can check indented and unintented relations between your modules.
Ideally, this would be a DAG (directed acyclic graph), since then you don't
need forward refs or other 'hacks'.
The class is quite dumb, which is on purpose. It just looks at every
*.module.ts file in your src directory and looks for any occurence of
<Name>Module anywhere in the file. It doesn't even respect comments
currently. This way it's mostly correct and doesn't depend on actual module
resolution mechanisms.
Example usage:
>>> m = ModuleDeps()
>>> m.build()
>>> print(m.graph)
>>> m.write_dot()
"""
dir: str = "src"
graph: List[Tuple[str, str]] = []
suffix_length = len(".module.ts")
def __init__(self, dir: str = "src") -> None:
self.dir = dir
def build(self) -> None:
for module in (Path(p) for p in iglob(f"{self.dir}/**/*.module.ts", recursive=True)):
name = module.name[:-self.suffix_length]
with open(module) as f:
for match in set(m.lower() for m in re.findall(r"\b(\w+)Module\b", f.read())):
if match != name:
self.graph.append((name, match))
def write_dot(self, output: str = "modules.dot") -> None:
with open(output, "w") as f:
f.write("digraph Modules {\n")
for (src, dest) in self.graph:
f.write(f" {src} -> {dest};\n")
f.write("}\n")
if __name__ == "__main__":
m = ModuleDeps()
m.build()
m.write_dot()