Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add svg support #2

Merged
merged 1 commit into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/github-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.9
python-version: 3.11
- run: bash .github/workflows/install_ci_python_dep.sh
- run: pre-commit run -a

Expand All @@ -27,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8, 3.9, "3.10"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
Expand Down
9 changes: 5 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
fail_fast: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v5.0.0
hooks:
- id: check-ast
- id: check-merge-conflict
Expand All @@ -15,14 +15,15 @@ repos:
types: [python]

- repo: https://github.com/pycqa/flake8
rev: 6.0.0
rev: 7.1.1
hooks:
- id: flake8
name: flake8-blocking
args: [ '--isolated', '--select=P,F401,F821,F901', '--ignore=P101,P102' ]
additional_dependencies:
- flake8-string-format

- repo: https://github.com/psf/black
rev: 22.12.0
rev: 24.10.0
hooks:
- id: black
- id: black
20 changes: 17 additions & 3 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,24 @@
language: python
files: '.dot$'
pass_filenames: true
- id: render-dot
name: render dot
- id: render-dot-png
name: render dot to png
description: render all .dot to .dot.png
entry: render-dot
entry: render-dot-png
language: python
files: '.dot$'
pass_filenames: true
- id: render-dot-svg
name: render dot to svg
description: render all .dot to .dot.svg
entry: render-dot-svg
language: python
files: '.dot$'
pass_filenames: true
- id: render-dot
name: render dot to png (legacy hook - switch to render-dot-png)
description: render all .dot to .dot.png
entry: render-dot-png
language: python
files: '.dot$'
pass_filenames: true
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ MAKEFLAGS += --silent

.PHONY: setup-venv test

PYTHON_VERSION = "3.8.6"
PYTHON_VERSION = "3.11.9"
VENV_NAME := $(shell cat .python-version)


Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,25 @@ and we are sure that both version match and developers don't forget to render th
## Hooks available

### `check-dot`
Verify the syntax of .dot files:
Verify the syntax of .dot files


### `render-dot`
Is an alias for `render-dot-png`, kept for backward compatibility


### `render-dot-png`
Render .dot files to png. This command can work in 2 ways

- Called without argument, it will render the .png next to the .dot files (simply appending ".png" to the .dot file path)
- `--only src1,src2` can be used to select the files to be rendered
- `--only src1:target1,src2:target2` can be used to specify custom locations for the PNG (specified per .dot source)


### `render-dot-svg`
Same as `render-dot-png` but renders to svg. Rendering to svg may be more stable as it is less sensitive to fonts and other dependencies.
Discrepancies were observed when using the png hook between ubuntu 22 and ubuntu 24 for instance.

## Pre-commit integration

An example `.pre-commit-config.yaml`:
Expand All @@ -38,7 +46,7 @@ repos:
rev: master
hooks:
- id: check-dot
- id: render-dot
- id: render-dot-png
# args: ["--only=class_diagram.dot:docs/class_diagram.png"]
```

6 changes: 4 additions & 2 deletions graphviz_dot_hooks/check_dot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
def _verify_dot_rendering(dot_filepath: str) -> Tuple[bool, Optional[str]]:
"""Trying to render it would detect syntax error, there are probably cheaper way to check this
but we aren't really looking after performance here"""
with tempfile.NamedTemporaryFile(suffix=".png") as tmpf:
with tempfile.NamedTemporaryFile(suffix=f".{format}") as tmpf:
try:
render("dot", "png", dot_filepath, outfile=tmpf.name)
# arbitrary render as svg (more generic than png)
# but it doesn't matter much as we are mostly interested in .dot syntax
render("dot", "svg", dot_filepath, outfile=tmpf.name)
except CalledProcessError as ex:
return False, str(ex)

Expand Down
119 changes: 0 additions & 119 deletions graphviz_dot_hooks/render_dot.py

This file was deleted.

51 changes: 51 additions & 0 deletions graphviz_dot_hooks/render_dot_png.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import argparse
import sys
from typing import Dict

from graphviz_dot_hooks.utils import render_dotfiles, _parse_only_convert

parser = argparse.ArgumentParser()
parser.add_argument("instancefiles", nargs="+", help=".dot files to check")
parser.add_argument(
"--only",
action="store",
type=str,
default=None,
required=False,
help="string with coma-separated values, target files can be specified as well in the format '--only src1:target1,src2:target2'"
" Example: --only dotfile1.dot,dotfile2.dot"
" --only dotfile1.dot:doc/dotfile1.png,dotfile2.dot",
)


def main():
args = parser.parse_args()

format = "png"

convert_map: Dict[str, str]
if args.only:
# Take the intersection of the instancefiles and the --only
convert_map = _parse_only_convert(args.only, format=format)
convert_map = {
src: target
for src, target in convert_map.items()
if src in args.instancefiles
}
else:
# Take the instancefiles
convert_map = _parse_only_convert(",".join(args.instancefiles), format=format)

success, messages = render_dotfiles(convert_map, format=format)

for message in messages:
print(message)

if success:
sys.exit(0)
else:
sys.exit(1)


if __name__ == "__main__":
main()
51 changes: 51 additions & 0 deletions graphviz_dot_hooks/render_dot_svg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import argparse
import sys
from typing import Dict

from graphviz_dot_hooks.utils import render_dotfiles, _parse_only_convert

parser = argparse.ArgumentParser()
parser.add_argument("instancefiles", nargs="+", help=".dot files to check")
parser.add_argument(
"--only",
action="store",
type=str,
default=None,
required=False,
help="string with coma-separated values, target files can be specified as well in the format '--only src1:target1,src2:target2'"
" Example: --only dotfile1.dot,dotfile2.dot"
" --only dotfile1.dot:doc/dotfile1.svg,dotfile2.dot",
)


def main():
args = parser.parse_args()

format = "svg"

convert_map: Dict[str, str]
if args.only:
# Take the intersection of the instancefiles and the --only
convert_map = _parse_only_convert(args.only, format=format)
convert_map = {
src: target
for src, target in convert_map.items()
if src in args.instancefiles
}
else:
# Take the instancefiles
convert_map = _parse_only_convert(",".join(args.instancefiles), format=format)

success, messages = render_dotfiles(convert_map, format=format)

for message in messages:
print(message)

if success:
sys.exit(0)
else:
sys.exit(1)


if __name__ == "__main__":
main()
Loading
Loading