Skip to content
Snippets Groups Projects
Unverified Commit b9b62f37 authored by Florian Maurer's avatar Florian Maurer Committed by GitHub
Browse files

Allow having either graphviz or pygraphviz installed (#126)

parents ec80be3b 3bc8daf3
No related branches found
No related tags found
No related merge requests found
......@@ -18,6 +18,21 @@ To install eralchemy, just do:
$ pip install eralchemy
### Graph library flavors
To create Pictures and PDFs, eralchemy relies on either graphviz or pygraphviz.
You can use either
$ pip install eralchemy[graphviz]
or
$ pip install eralchemy[pygraphviz]
to retrieve the correct dependencies.
The `graphviz` library is the default if both are installed.
`eralchemy` requires [GraphViz](http://www.graphviz.org/download) to generate the graphs and Python. Both are available for Windows, Mac and Linux.
For Debian based systems, run:
......
import argparse
import base64
import copy
import logging
import re
import sys
from importlib.metadata import PackageNotFoundError, version
from pygraphviz.agraph import AGraph
from sqlalchemy.engine.url import make_url
from sqlalchemy.exc import ArgumentError
......@@ -22,6 +22,22 @@ from .sqla import (
metadata_to_intermediary,
)
USE_PYGRAPHVIZ = True
GRAPHVIZ_AVAILABLE = True
try:
from pygraphviz.agraph import AGraph
logging.debug("using pygraphviz")
except ImportError:
USE_PYGRAPHVIZ = False
try:
from graphviz import Source
logging.debug("using graphviz")
except ImportError:
logging.error("either pygraphviz or graphviz should be installed")
GRAPHVIZ_AVAILABLE = False
try:
__version__ = version(__package__)
except PackageNotFoundError:
......@@ -138,11 +154,18 @@ def intermediary_to_dot(tables, relationships, output, title=""):
def intermediary_to_schema(tables, relationships, output, title=""):
"""Transforms and save the intermediary representation to the file chosen."""
if not GRAPHVIZ_AVAILABLE:
raise Exception("neither graphviz or pygraphviz are available. Install either library!")
dot_file = _intermediary_to_dot(tables, relationships, title)
extension = output.split(".")[-1]
if USE_PYGRAPHVIZ:
graph = AGraph()
graph = graph.from_string(dot_file)
extension = output.split(".")[-1]
graph.draw(path=output, prog="dot", format=extension)
else:
graph = Source(dot_file, engine="dot", format=extension)
graph.render(outfile=output, cleanup=True)
return graph
def _intermediary_to_markdown(tables, relationships):
......@@ -372,7 +395,7 @@ def render_er(
exclude_columns=exclude_columns,
)
intermediary_to_output = get_output_mode(output, mode)
intermediary_to_output(tables, relationships, output, title)
return intermediary_to_output(tables, relationships, output)
except ImportError as e:
module_name = e.message.split()[-1]
print(f'Please install {module_name} using "pip install {module_name}".')
......
......@@ -26,8 +26,7 @@ classifiers=[
]
requires-python = ">=3.8"
dependencies = [
"sqlalchemy >= 1.4",
"pygraphviz >= 1.9",
"sqlalchemy >= 1.4"
]
[project.urls]
......@@ -35,10 +34,14 @@ homepage = "https://github.com/eralchemy/eralchemy"
repository = "https://github.com/eralchemy/eralchemy"
[project.optional-dependencies]
graphviz = ["graphviz >= 0.20.3"]
pygraphviz = ["pygraphviz >= 1.9"]
ci = [
"flask-sqlalchemy >= 2.5.1",
"psycopg2 >= 2.9.3",
"pytest >= 7.4.3",
"pygraphviz >= 1.9",
"graphviz >= 0.20.3",
]
dev = [
"nox",
......@@ -103,7 +106,7 @@ show_error_codes = true
pretty = true
[[tool.mypy.overrides]]
module = ["pygraphviz.*", "sqlalchemy.*"]
module = ["graphviz.*", "pygraphviz.*", "sqlalchemy.*"]
ignore_missing_imports = true
......
......@@ -31,6 +31,7 @@ column_inside = re.compile(
)
# This test needs fixing with move to graphviz
def assert_is_dot_format(dot):
"""Checks that the dot is usable by graphviz."""
......
......@@ -115,6 +115,7 @@ def test_flask_sqlalchemy():
check_intermediary_representation_simple_all_table(tables, relationships)
@pytest.mark.external_db
def test_table_names_in_relationships(pg_db_uri):
tables, relationships = database_to_intermediary(pg_db_uri)
table_names = [t.name for t in tables]
......@@ -133,6 +134,7 @@ def test_table_names_in_relationships(pg_db_uri):
assert l_name.find(".") == -1
@pytest.mark.external_db
def test_table_names_in_relationships_with_schema(pg_db_uri):
schema_name = "test"
matcher = re.compile(rf"{schema_name}\.[\S+]", re.I)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment