Merge pull request #21 from compose-viz/dev

feat: new supported output formats
This commit is contained in:
Xyphuz 2022-05-26 11:13:32 +08:00 committed by GitHub
commit 5495f3cd1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 283 additions and 33 deletions

View file

@ -56,7 +56,7 @@
## About The Project ## About The Project
`compose-viz` is a compose file visualization tool that supports [compose-spec](https://github.com/compose-spec/compose-spec/blob/master/spec.md) and allows you to gernerate graph in [DOT](https://graphviz.org/doc/info/lang.html) format or `.png`. `compose-viz` is a compose file visualization tool that supports [compose-spec](https://github.com/compose-spec/compose-spec/blob/master/spec.md) and allows you to gernerate graph in several formats.
If you are looking for a compose file vizualization tool, and you are using one of the [compose-spec](https://github.com/compose-spec/compose-spec/blob/master/spec.md) implementations (e.g. [docker-compose](https://github.com/docker/compose)/[podman-compose](https://github.com/containers/podman-compose)), then `compose-viz` is a great choice for you. If you are looking for a compose file vizualization tool, and you are using one of the [compose-spec](https://github.com/compose-spec/compose-spec/blob/master/spec.md) implementations (e.g. [docker-compose](https://github.com/docker/compose)/[podman-compose](https://github.com/containers/podman-compose)), then `compose-viz` is a great choice for you.
@ -70,7 +70,7 @@ If you are looking for a compose file vizualization tool, and you are using one
#### Graphviz #### Graphviz
If you want to generate PNG (which is the default option), you need to install [Graphviz](https://graphviz.org/download/). You need to install [Graphviz](https://graphviz.org/download/) to generate graphs.
### Installation ### Installation
@ -88,14 +88,14 @@ This example yml is from [docker compose beginner tutorial](https://github.com/d
```bash ```bash
cd examples/voting-app/ cd examples/voting-app/
cpv docker-compose.yml cpv -m svg docker-compose.yml
``` ```
And this is what the result looks like: And this is what the result looks like:
![compose-viz.png](https://github.com/compose-viz/compose-viz/blob/main/examples/voting-app/compose-viz.png) ![compose-viz.svg](https://github.com/compose-viz/compose-viz/blob/main/examples/voting-app/compose-viz.svg)
Check out the result [here](https://github.com/compose-viz/compose-viz/blob/main/examples/voting-app/compose-viz.png). Check out the result [here](https://github.com/compose-viz/compose-viz/blob/main/examples/voting-app).
### Usage ### Usage
@ -104,9 +104,9 @@ Check out the result [here](https://github.com/compose-viz/compose-viz/blob/main
### Options ### Options
| Option | Description | | Option | Description |
| ------------------------ | ------------------------------------------------------------------------------ | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-o, --output-path` | Output path for the generated visualization file. [default: ./compose-viz.png] | | `-o, --output-filename` | Output filename for the generated visualization file. [default: compose-viz] |
| `-m, --format [PNG,DOT]` | Output format for the generated visualization file. [default: PNG] | | `-m, --format` | Output format for the generated visualization file. See [supported formats](https://github.com/compose-viz/compose-viz/blob/main/compose_viz/viz_formats.py). [default: png] |
| `-v, --version` | Show the version of compose-viz. | | `-v, --version` | Show the version of compose-viz. |
| `--help` | Show help and exit. | | `--help` | Show help and exit. |

View file

@ -1,2 +1,2 @@
__app_name__ = "compose_viz" __app_name__ = "compose_viz"
__version__ = "0.1.1" __version__ = "0.1.2"

View file

@ -1,4 +1,3 @@
from enum import Enum
from typing import Optional from typing import Optional
import typer import typer
@ -6,12 +5,7 @@ import typer
from compose_viz import __app_name__, __version__ from compose_viz import __app_name__, __version__
from compose_viz.graph import Graph from compose_viz.graph import Graph
from compose_viz.parser import Parser from compose_viz.parser import Parser
from compose_viz.viz_formats import VizFormats
class VisualizationFormats(str, Enum):
png = "PNG"
dot = "DOT"
app = typer.Typer( app = typer.Typer(
invoke_without_command=True, invoke_without_command=True,
@ -30,14 +24,14 @@ def _version_callback(value: bool) -> None:
@app.callback() @app.callback()
def compose_viz( def compose_viz(
input_path: str, input_path: str,
output_path: str = typer.Option( output_filename: str = typer.Option(
"./compose-viz.png", "compose-viz",
"--output-path", "--output-filename",
"-o", "-o",
help="Output path for the generated visualization file.", help="Output filename for the generated visualization file.",
), ),
format: VisualizationFormats = typer.Option( format: VizFormats = typer.Option(
"PNG", "png",
"--format", "--format",
"-m", "-m",
help="Output format for the generated visualization file.", help="Output format for the generated visualization file.",
@ -57,7 +51,7 @@ def compose_viz(
if compose: if compose:
typer.echo(f"Successfully parsed {input_path}") typer.echo(f"Successfully parsed {input_path}")
Graph(compose, output_path).render(format) Graph(compose, output_filename).render(format)
raise typer.Exit() raise typer.Exit()

View file

@ -93,4 +93,4 @@ class Graph:
for depends_on in service.depends_on: for depends_on in service.depends_on:
self.add_edge(service.name, depends_on, "depends_on") self.add_edge(service.name, depends_on, "depends_on")
self.dot.render(outfile=self.filename, format=format, cleanup=cleanup) self.dot.render(outfile=f"{self.filename}.{format}", format=format, cleanup=cleanup)

View file

@ -0,0 +1,45 @@
from enum import Enum
class VizFormats(str, Enum):
png = "png"
dot = "dot"
jpeg = "jpeg"
json = "json"
svg = "svg"
bmp = "bmp"
canon = "canon"
cmap = "cmap"
cmapx = "cmapx"
cmapx_np = "cmapx_np"
dot_json = "dot_json"
emf = "emf"
emfplus = "emfplus"
eps = "eps"
fig = "fig"
gif = "gif"
gv = "gv"
imap = "imap"
imap_np = "imap_np"
ismap = "ismap"
jpe = "jpe"
jpg = "jpg"
json0 = "json0"
metafile = "metafile"
mp = "mp"
pdf = "pdf"
pic = "pic"
plain = "plain"
plain_ext = "plain-ext"
pov = "pov"
ps = "ps"
ps2 = "ps2"
tif = "tif"
tiff = "tiff"
tk = "tk"
vml = "vml"
xdot = "xdot"
xdot1_2 = "xdot1.2"
xdot1_4 = "xdot1.4"
xdot_json = "xdot_json"

View file

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 3.0.0 (20220226.1711)
-->
<!-- Pages: 1 -->
<svg width="1049pt" height="520pt"
viewBox="0.00 0.00 1049.25 519.98" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(36 483.98)">
<polygon fill="white" stroke="transparent" points="-36,36 -36,-483.98 1013.25,-483.98 1013.25,36 -36,36"/>
<!-- redis -->
<g id="node1" class="node">
<title>redis</title>
<polygon fill="none" stroke="black" points="243.25,-125 155.25,-125 155.25,-121 151.25,-121 151.25,-117 155.25,-117 155.25,-95 151.25,-95 151.25,-91 155.25,-91 155.25,-87 243.25,-87 243.25,-125"/>
<polyline fill="none" stroke="black" points="155.25,-121 159.25,-121 159.25,-117 155.25,-117 "/>
<polyline fill="none" stroke="black" points="155.25,-95 159.25,-95 159.25,-91 155.25,-91 "/>
<text text-anchor="middle" x="199.25" y="-109.8" font-family="Times New Roman,serif" font-size="14.00">redis</text>
<text text-anchor="middle" x="199.25" y="-94.8" font-family="Times New Roman,serif" font-size="14.00">(redis:alpine)</text>
</g>
<!-- frontend -->
<g id="node2" class="node">
<title>frontend</title>
<polygon fill="none" stroke="black" points="338.11,-23.56 271.25,-36 204.38,-23.56 229.92,-3.44 312.57,-3.44 338.11,-23.56"/>
<text text-anchor="middle" x="271.25" y="-14.3" font-family="Times New Roman,serif" font-size="14.00">net:frontend</text>
</g>
<!-- redis&#45;&gt;frontend -->
<g id="edge1" class="edge">
<title>redis&#45;&gt;frontend</title>
<path fill="none" stroke="black" d="M214.51,-86.76C225.56,-73.57 240.55,-55.67 252.34,-41.58"/>
<polygon fill="black" stroke="black" points="255.13,-43.7 258.87,-33.78 249.76,-39.2 255.13,-43.7"/>
</g>
<!-- 0.0.0.06379 -->
<g id="node3" class="node">
<title>0.0.0.06379</title>
<ellipse fill="none" stroke="black" cx="55.25" cy="-231.25" rx="55.49" ry="55.49"/>
<text text-anchor="middle" x="55.25" y="-227.55" font-family="Times New Roman,serif" font-size="14.00">0.0.0.0:6379</text>
</g>
<!-- 0.0.0.06379&#45;&gt;redis -->
<g id="edge2" class="edge">
<title>0.0.0.06379&#45;&gt;redis</title>
<path fill="none" stroke="black" d="M104.53,-188.06C126.48,-169.27 151.57,-147.8 170.41,-131.68"/>
<polygon fill="black" stroke="black" points="102.22,-185.44 96.9,-194.6 106.77,-190.75 102.22,-185.44"/>
<polygon fill="black" stroke="black" points="172.75,-134.28 178.07,-125.12 168.2,-128.96 172.75,-134.28"/>
<text text-anchor="middle" x="171.25" y="-146.8" font-family="Times New Roman,serif" font-size="14.00">6379</text>
</g>
<!-- db -->
<g id="node4" class="node">
<title>db</title>
<polygon fill="none" stroke="black" points="711.25,-125 617.25,-125 617.25,-121 613.25,-121 613.25,-117 617.25,-117 617.25,-95 613.25,-95 613.25,-91 617.25,-91 617.25,-87 711.25,-87 711.25,-125"/>
<polyline fill="none" stroke="black" points="617.25,-121 621.25,-121 621.25,-117 617.25,-117 "/>
<polyline fill="none" stroke="black" points="617.25,-95 621.25,-95 621.25,-91 617.25,-91 "/>
<text text-anchor="middle" x="664.25" y="-109.8" font-family="Times New Roman,serif" font-size="14.00">db</text>
<text text-anchor="middle" x="664.25" y="-94.8" font-family="Times New Roman,serif" font-size="14.00">(postgres:9.4)</text>
</g>
<!-- backend -->
<g id="node5" class="node">
<title>backend</title>
<polygon fill="none" stroke="black" points="624.11,-23.56 557.25,-36 490.38,-23.56 515.92,-3.44 598.57,-3.44 624.11,-23.56"/>
<text text-anchor="middle" x="557.25" y="-14.3" font-family="Times New Roman,serif" font-size="14.00">net:backend</text>
</g>
<!-- db&#45;&gt;backend -->
<g id="edge3" class="edge">
<title>db&#45;&gt;backend</title>
<path fill="none" stroke="black" d="M642.99,-86.82C631.36,-76.97 616.63,-64.67 603.25,-54 597.1,-49.1 590.4,-43.91 584.07,-39.08"/>
<polygon fill="black" stroke="black" points="585.83,-36.03 575.75,-32.77 581.6,-41.6 585.83,-36.03"/>
</g>
<!-- db&#45;data -->
<g id="node6" class="node">
<title>db&#45;data</title>
<polygon fill="none" stroke="black" points="700.75,-36 697.75,-40 676.75,-40 673.75,-36 641.75,-36 641.75,0 700.75,0 700.75,-36"/>
<text text-anchor="middle" x="671.25" y="-14.3" font-family="Times New Roman,serif" font-size="14.00">db&#45;data</text>
</g>
<!-- db&#45;&gt;db&#45;data -->
<g id="edge4" class="edge">
<title>db&#45;&gt;db&#45;data</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M666.56,-76.58C667.35,-66.83 668.24,-55.95 669.02,-46.3"/>
<polygon fill="black" stroke="black" points="663.05,-76.51 665.73,-86.76 670.03,-77.08 663.05,-76.51"/>
<polygon fill="black" stroke="black" points="672.54,-46.29 669.86,-36.04 665.56,-45.73 672.54,-46.29"/>
<text text-anchor="middle" x="733.25" y="-57.8" font-family="Times New Roman,serif" font-size="14.00">/var/lib/postgresql/data</text>
</g>
<!-- vote -->
<g id="node7" class="node">
<title>vote</title>
<polygon fill="none" stroke="black" points="413.75,-250.25 128.75,-250.25 128.75,-246.25 124.75,-246.25 124.75,-242.25 128.75,-242.25 128.75,-220.25 124.75,-220.25 124.75,-216.25 128.75,-216.25 128.75,-212.25 413.75,-212.25 413.75,-250.25"/>
<polyline fill="none" stroke="black" points="128.75,-246.25 132.75,-246.25 132.75,-242.25 128.75,-242.25 "/>
<polyline fill="none" stroke="black" points="128.75,-220.25 132.75,-220.25 132.75,-216.25 128.75,-216.25 "/>
<text text-anchor="middle" x="271.25" y="-235.05" font-family="Times New Roman,serif" font-size="14.00">vote</text>
<text text-anchor="middle" x="271.25" y="-220.05" font-family="Times New Roman,serif" font-size="14.00">(dockersamples/examplevotingapp_vote:before)</text>
</g>
<!-- vote&#45;&gt;redis -->
<g id="edge7" class="edge">
<title>vote&#45;&gt;redis</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M260.62,-212.06C248.6,-191.49 228.91,-157.78 215.08,-134.1"/>
<polygon fill="black" stroke="black" points="217.98,-132.13 209.91,-125.26 211.93,-135.66 217.98,-132.13"/>
</g>
<!-- vote&#45;&gt;frontend -->
<g id="edge5" class="edge">
<title>vote&#45;&gt;frontend</title>
<path fill="none" stroke="black" d="M271.25,-212.23C271.25,-175.17 271.25,-90.15 271.25,-46.29"/>
<polygon fill="black" stroke="black" points="274.75,-46.08 271.25,-36.08 267.75,-46.08 274.75,-46.08"/>
</g>
<!-- 0.0.0.05000 -->
<g id="node8" class="node">
<title>0.0.0.05000</title>
<ellipse fill="none" stroke="black" cx="271.25" cy="-392.74" rx="55.49" ry="55.49"/>
<text text-anchor="middle" x="271.25" y="-389.04" font-family="Times New Roman,serif" font-size="14.00">0.0.0.0:5000</text>
</g>
<!-- 0.0.0.05000&#45;&gt;vote -->
<g id="edge6" class="edge">
<title>0.0.0.05000&#45;&gt;vote</title>
<path fill="none" stroke="black" d="M271.25,-327.24C271.25,-304.1 271.25,-279.18 271.25,-260.67"/>
<polygon fill="black" stroke="black" points="267.75,-327.29 271.25,-337.29 274.75,-327.29 267.75,-327.29"/>
<polygon fill="black" stroke="black" points="274.75,-260.58 271.25,-250.58 267.75,-260.58 274.75,-260.58"/>
<text text-anchor="middle" x="278.25" y="-308.29" font-family="Times New Roman,serif" font-size="14.00">80</text>
</g>
<!-- result -->
<g id="node9" class="node">
<title>result</title>
<polygon fill="none" stroke="black" points="759.75,-250.25 468.75,-250.25 468.75,-246.25 464.75,-246.25 464.75,-242.25 468.75,-242.25 468.75,-220.25 464.75,-220.25 464.75,-216.25 468.75,-216.25 468.75,-212.25 759.75,-212.25 759.75,-250.25"/>
<polyline fill="none" stroke="black" points="468.75,-246.25 472.75,-246.25 472.75,-242.25 468.75,-242.25 "/>
<polyline fill="none" stroke="black" points="468.75,-220.25 472.75,-220.25 472.75,-216.25 468.75,-216.25 "/>
<text text-anchor="middle" x="614.25" y="-235.05" font-family="Times New Roman,serif" font-size="14.00">result</text>
<text text-anchor="middle" x="614.25" y="-220.05" font-family="Times New Roman,serif" font-size="14.00">(dockersamples/examplevotingapp_result:before)</text>
</g>
<!-- result&#45;&gt;db -->
<g id="edge10" class="edge">
<title>result&#45;&gt;db</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M621.62,-212.06C629.89,-191.67 643.4,-158.37 652.99,-134.73"/>
<polygon fill="black" stroke="black" points="656.32,-135.84 656.84,-125.26 649.83,-133.21 656.32,-135.84"/>
</g>
<!-- result&#45;&gt;backend -->
<g id="edge8" class="edge">
<title>result&#45;&gt;backend</title>
<path fill="none" stroke="black" d="M609.39,-212.23C599.29,-174.81 576,-88.52 564.27,-45.04"/>
<polygon fill="black" stroke="black" points="567.6,-43.95 561.62,-35.21 560.84,-45.78 567.6,-43.95"/>
</g>
<!-- 0.0.0.05001 -->
<g id="node10" class="node">
<title>0.0.0.05001</title>
<ellipse fill="none" stroke="black" cx="614.25" cy="-392.74" rx="55.49" ry="55.49"/>
<text text-anchor="middle" x="614.25" y="-389.04" font-family="Times New Roman,serif" font-size="14.00">0.0.0.0:5001</text>
</g>
<!-- 0.0.0.05001&#45;&gt;result -->
<g id="edge9" class="edge">
<title>0.0.0.05001&#45;&gt;result</title>
<path fill="none" stroke="black" d="M614.25,-327.24C614.25,-304.1 614.25,-279.18 614.25,-260.67"/>
<polygon fill="black" stroke="black" points="610.75,-327.29 614.25,-337.29 617.75,-327.29 610.75,-327.29"/>
<polygon fill="black" stroke="black" points="617.75,-260.58 614.25,-250.58 610.75,-260.58 617.75,-260.58"/>
<text text-anchor="middle" x="621.25" y="-308.29" font-family="Times New Roman,serif" font-size="14.00">80</text>
</g>
<!-- worker -->
<g id="node11" class="node">
<title>worker</title>
<polygon fill="none" stroke="black" points="560.75,-125 299.75,-125 299.75,-121 295.75,-121 295.75,-117 299.75,-117 299.75,-95 295.75,-95 295.75,-91 299.75,-91 299.75,-87 560.75,-87 560.75,-125"/>
<polyline fill="none" stroke="black" points="299.75,-121 303.75,-121 303.75,-117 299.75,-117 "/>
<polyline fill="none" stroke="black" points="299.75,-95 303.75,-95 303.75,-91 299.75,-91 "/>
<text text-anchor="middle" x="430.25" y="-109.8" font-family="Times New Roman,serif" font-size="14.00">worker</text>
<text text-anchor="middle" x="430.25" y="-94.8" font-family="Times New Roman,serif" font-size="14.00">(dockersamples/examplevotingapp_worker)</text>
</g>
<!-- worker&#45;&gt;frontend -->
<g id="edge11" class="edge">
<title>worker&#45;&gt;frontend</title>
<path fill="none" stroke="black" d="M396.91,-86.97C369.54,-72.17 331,-51.32 303.84,-36.63"/>
<polygon fill="black" stroke="black" points="305.2,-33.39 294.74,-31.71 301.87,-39.54 305.2,-33.39"/>
</g>
<!-- worker&#45;&gt;backend -->
<g id="edge12" class="edge">
<title>worker&#45;&gt;backend</title>
<path fill="none" stroke="black" d="M456.87,-86.97C477.96,-72.69 507.37,-52.77 528.9,-38.19"/>
<polygon fill="black" stroke="black" points="530.99,-41 537.31,-32.5 527.07,-35.21 530.99,-41"/>
</g>
<!-- visualizer -->
<g id="node12" class="node">
<title>visualizer</title>
<polygon fill="none" stroke="black" points="942.25,-250.25 778.25,-250.25 778.25,-246.25 774.25,-246.25 774.25,-242.25 778.25,-242.25 778.25,-220.25 774.25,-220.25 774.25,-216.25 778.25,-216.25 778.25,-212.25 942.25,-212.25 942.25,-250.25"/>
<polyline fill="none" stroke="black" points="778.25,-246.25 782.25,-246.25 782.25,-242.25 778.25,-242.25 "/>
<polyline fill="none" stroke="black" points="778.25,-220.25 782.25,-220.25 782.25,-216.25 778.25,-216.25 "/>
<text text-anchor="middle" x="860.25" y="-235.05" font-family="Times New Roman,serif" font-size="14.00">visualizer</text>
<text text-anchor="middle" x="860.25" y="-220.05" font-family="Times New Roman,serif" font-size="14.00">(dockersamples/visualizer)</text>
</g>
<!-- /var/run/docker.sock -->
<g id="node13" class="node">
<title>/var/run/docker.sock</title>
<polygon fill="none" stroke="black" points="926.75,-124 923.75,-128 902.75,-128 899.75,-124 793.75,-124 793.75,-88 926.75,-88 926.75,-124"/>
<text text-anchor="middle" x="860.25" y="-102.3" font-family="Times New Roman,serif" font-size="14.00">/var/run/docker.sock</text>
</g>
<!-- visualizer&#45;&gt;/var/run/docker.sock -->
<g id="edge13" class="edge">
<title>visualizer&#45;&gt;/var/run/docker.sock</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M860.25,-201.78C860.25,-181.41 860.25,-154.15 860.25,-134.1"/>
<polygon fill="black" stroke="black" points="856.75,-202.06 860.25,-212.06 863.75,-202.06 856.75,-202.06"/>
<polygon fill="black" stroke="black" points="863.75,-134.07 860.25,-124.07 856.75,-134.07 863.75,-134.07"/>
<text text-anchor="middle" x="918.75" y="-146.8" font-family="Times New Roman,serif" font-size="14.00">/var/run/docker.sock</text>
</g>
<!-- 0.0.0.08080 -->
<g id="node14" class="node">
<title>0.0.0.08080</title>
<ellipse fill="none" stroke="black" cx="860.25" cy="-392.74" rx="55.49" ry="55.49"/>
<text text-anchor="middle" x="860.25" y="-389.04" font-family="Times New Roman,serif" font-size="14.00">0.0.0.0:8080</text>
</g>
<!-- 0.0.0.08080&#45;&gt;visualizer -->
<g id="edge14" class="edge">
<title>0.0.0.08080&#45;&gt;visualizer</title>
<path fill="none" stroke="black" d="M860.25,-327.24C860.25,-304.1 860.25,-279.18 860.25,-260.67"/>
<polygon fill="black" stroke="black" points="856.75,-327.29 860.25,-337.29 863.75,-327.29 856.75,-327.29"/>
<polygon fill="black" stroke="black" points="863.75,-260.58 860.25,-250.58 856.75,-260.58 863.75,-260.58"/>
<text text-anchor="middle" x="874.25" y="-308.29" font-family="Times New Roman,serif" font-size="14.00">8080</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -1,7 +1,7 @@
[tool.poetry] [tool.poetry]
name = "compose-viz" name = "compose-viz"
version = "0.1.1" version = "0.1.2"
description = "A compose file visualization tool that supports compose-spec and allows you to gernerate graph in DOT format or PNG." description = "A compose file visualization tool that supports compose-spec and allows you to gernerate graph in several formats."
authors = ["Xyphuz Wu <xyphuzwu@gmail.com>"] authors = ["Xyphuz Wu <xyphuzwu@gmail.com>"]
readme = "README.md" readme = "README.md"
license = "MIT" license = "MIT"

View file

@ -24,11 +24,12 @@ runner = CliRunner()
) )
def test_cli(test_file_path: str) -> None: def test_cli(test_file_path: str) -> None:
input_path = f"{test_file_path}" input_path = f"{test_file_path}"
output_path = "compose-viz-test.png" output_filename = "compose-viz-test"
result = runner.invoke(cli.app, ["-o", output_path, input_path]) default_format = "png"
result = runner.invoke(cli.app, ["-o", output_filename, input_path])
assert result.exit_code == 0 assert result.exit_code == 0
assert f"Successfully parsed {input_path}\n" in result.stdout assert f"Successfully parsed {input_path}\n" in result.stdout
assert os.path.exists(output_path) assert os.path.exists(f"{output_filename}.{default_format}")
os.remove(output_path) os.remove(f"{output_filename}.{default_format}")