[add] graphviz

This commit is contained in:
Andy Bunce 2025-05-21 16:12:37 +01:00
parent e195c3a9f1
commit 999c503294
6 changed files with 98 additions and 0 deletions

10
graphviz/Dockerfile Normal file
View file

@ -0,0 +1,10 @@
FROM alpine:3
RUN apk add --no-cache \
graphviz python3 py-pip
ADD requirements.txt ./
RUN pip3 install -r requirements.txt --break-system-packages
ADD server.py ./
CMD hug -f server.py

7
graphviz/compose.yml Normal file
View file

@ -0,0 +1,7 @@
name: graphviz
services:
graphviz:
ports:
- 8000:8000
image: graphviz
restart: unless-stopped

7
graphviz/readme.md Normal file
View file

@ -0,0 +1,7 @@
```
docker build -t graphviz .
docker run -p8000:8000 graphviz
```
Based on https://github.com/sseemayer/docker-graphviz

View file

@ -0,0 +1,3 @@
hug==2.6.1
hug-middleware-cors==1.0.0
six==1.16.0

60
graphviz/server.py Normal file
View file

@ -0,0 +1,60 @@
import hug
from hug.middleware import CORSMiddleware
from six import BytesIO
import subprocess
import logging
from tempfile import NamedTemporaryFile as ntf
logging.basicConfig()
api = hug.API(__name__)
api.http.add_middleware(CORSMiddleware(api, allow_credentials=True))
@hug.not_found()
def not_found_handler():
return "Not Found"
@hug.get_post('/viz.svg', output=hug.output_format.image("svg+xml"))
@hug.get_post('/viz.png', output=hug.output_format.image("png"))
@hug.get_post('/viz.dot', output=hug.output_format.text)
@hug.get_post('/viz.xdot', output=hug.output_format.text)
def demo(
dot: 'A Graphviz dot document',
request,
response,
algorithm: hug.types.one_of(['dot', 'neato', 'twopi', 'circo', 'fdp', 'sfdp', 'patchwork', 'osage'])='dot',
):
suffix = request.path.split(".")[-1]
# Enforce unicode strings
try:
dot = dot.decode("utf-8")
except AttributeError:
pass
with ntf(suffix=".dot", mode="w") as f_dot, ntf(mode="r+b") as f_out, ntf(mode="r") as f_err:
f_dot.write(dot)
f_dot.flush()
cmd = [
algorithm,
'-T',
suffix,
f_dot.name,
'-o',
f_out.name
]
proc = subprocess.Popen(cmd, stdout=f_err, stderr=subprocess.STDOUT)
ret = proc.wait()
if ret != 0:
response.status = hug.HTTP_500
f_err.seek(0)
return {"status_code": ret, "message": f_err.read()}
f_out.seek(0)
out_data = f_out.read()
return BytesIO(out_data)

11
graphviz/test.dot Normal file
View file

@ -0,0 +1,11 @@
digraph D {
node [fontname="Arial"];
node_A [shape=record label="shape=record|{above|middle|below}|right"];
node_B [shape=plaintext label="shape=plaintext|{curly|braces and|bars without}|effect"];
}