#!/usr/bin/env python
import sys
from pathlib import Path
import subprocess
from dataclasses import dataclass
import webbrowser
COLOR_REVERSE = '#eebb44'
COLOR_PACKAGE = '#7BE141'
@dataclass
class Package:
item: int
label: str
value: int
color: str
def get_weight(pkgname) ->int:
proc = subprocess.run(["pactree", pkgname, "-rld1"], capture_output=True, text=True)
return len(proc.stdout.split("\n")) -2
def set_reverse(pkgname, pkgs, links):
proc = subprocess.run(["pactree", pkgname, "-ulr"], capture_output=True, text=True)
ls = proc.stdout.split("\n")
print(ls)
try:
ls.remove(pkgname)
except ValueError:
print("paquet non installé")
exit(2)
mainid = get_id(pkgs, pkgname)
pkgs[mainid].value = len(ls)
for pkg in ls:
if not pkg:
continue
weight = get_weight(pkg)
i = len(pkgs)+2
pkgs.append(Package(i, pkg, weight, COLOR_REVERSE))
links.append((i, mainid))
return pkgs, links
def print_pkgs(pkgs):
result = "nodes = ["
for pkg in pkgs:
color = f",color:'{pkg.color}'" if pkg.color else ''
result = f"{result}{{id:{pkg.item},value:{pkg.value},label:'{pkg.label}'{color}}},"
result = f"{result} ];"
return result
def print_links(links, pkgname):
mainid = get_id(pkgs, pkgname)
result = "edges = ["
for link in links:
color = f",color:'{COLOR_REVERSE}',arrows:'from'" if link[1] == mainid else ''
result = f"{result}{{from:{link[0]},to:{link[1]}{color}}},"
result = f"{result} ];"
return result
def get_id(pkgs, pkgname):
for pkg in pkgs:
if pkg.label == pkgname:
return pkg.item
return 0
if len(sys.argv) < 2:
print("pas de paquet en paramètre")
exit(1)
template = r'''<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis-network.min.js"></script>
</head>
<body><div id="mynetwork" style="with:99%; height:99vh;"></div></body>
<script>
var nodes = null; var edges = null; var network = null;
function draw() {
{{nodes}}
{{edges}}
var container = document.getElementById("mynetwork");
var data = { nodes: nodes, edges: edges };
var options = {
nodes: {
shape: "dot",
scaling: {
customScalingFunction: function (min,max,total,value) { return value/total; },
min:5,
max:120
}
},
physics: {
enabled: true,
timestep: 0.3,
minVelocity: 0.5,
solver: "barnesHut",
}
};
network = new vis.Network(container, data, options);
}
window.addEventListener("load", () => { draw(); });
</script>
</html>
'''
main_package = sys.argv[1].lower()
proc = subprocess.run(["pactree", main_package, "-ul"], capture_output=True, text=True)
#print(proc.stdout)
pkgs = []
for i, pkg in enumerate((p for p in proc.stdout.split("\n") if p)):
weight = get_weight(pkg)
color = COLOR_PACKAGE if main_package == pkg else ''
pkgs.append(Package(i, pkg, weight, color))
links = []
for pkg in pkgs:
proc = subprocess.run(["pactree", pkg.label, "-uld1"], capture_output=True, text=True)
ls = proc.stdout.split("\n")
ls.remove(pkg.label)
if len(ls) < 1:
continue
for subpkg in ls:
subid = get_id(pkgs, subpkg)
if subid > 0:
a, b = pkg.item, subid
if a > b:
a, b = b, a
links.append((a, b))
pkgs, links = set_reverse(main_package, pkgs, links)
template = template.replace('{{title}}', main_package, 1)
template = template.replace('{{nodes}}', print_pkgs(pkgs), 1)
template = template.replace('{{edges}}', print_links(links, main_package), 1)
Path("/tmp/pacman-graph.html").write_text(template)
webbrowser.open_new_tab("/tmp/pacman-graph.html")
#print(template)