Skip to content
This repository has been archived by the owner on Nov 19, 2018. It is now read-only.

Support Graphviz installed from Anaconda #52

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
49 changes: 31 additions & 18 deletions pydot_ng/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,25 @@ def graph_from_incidence_matrix(matrix, node_prefix='', directed=False):
return graph


def is_quoted(path):
return path.startswith('"') and path.endswith('"')


def is_windows():
return os.name == 'nt'


def is_anacoda():
return os.path.exists(os.path.join(sys.prefix, 'conda-meta'))


def get_executable_extension():
if is_windows():
return '.bat' if is_anacoda() else '.exe'
else:
return ''


def __find_executables(path):
"""Used by find_graphviz

Expand All @@ -409,7 +428,8 @@ def __find_executables(path):
Otherwise returns None
"""

success = False
any_found = False

progs = {
"dot": "",
"twopi": "",
Expand All @@ -419,11 +439,12 @@ def __find_executables(path):
"sfdp": "",
}

was_quoted = False
path = path.strip()
if path.startswith('"') and path.endswith('"'):
path_template = "{}"

if is_quoted(path):
path = path[1:-1]
was_quoted = True
path_template = "\"{}\""

if not os.path.isdir(path):
return None
Expand All @@ -432,22 +453,14 @@ def __find_executables(path):
if progs[prg]:
continue

prg_path = os.path.join(path, prg)
prg_exe_path = prg_path + ".exe"
ext = get_executable_extension()
prg_path = os.path.join(path, prg + ext)

if os.path.exists(prg_path):
if was_quoted:
prg_path = "\"{}\"".format(prg_path)
progs[prg] = prg_path
success = True

elif os.path.exists(prg_exe_path):
if was_quoted:
prg_exe_path = "\"{}\"".format(prg_exe_path)
progs[prg] = prg_exe_path
success = True

if success:
any_found = True
progs[prg] = path_template.format(prg_path)

if any_found:
return progs

return None
Expand Down
81 changes: 81 additions & 0 deletions test/test_find_executables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import mock
import pytest

import pydot_ng as pydot


def touch(path):
f = open(path, "w")
f.close()


def test_find_executables_fake_path():
assert pydot.__find_executables("/fake/path/") is None


def test_find_executables_real_path_no_programs(tmpdir):
assert pydot.__find_executables(str(tmpdir)) is None


def test_find_executables_path_needs_strip(tmpdir):
path = tmpdir.mkdir("subdir")
prog_path = str(path.join("dot"))

path_with_spaces = " {} ".format(path)

with open(prog_path, "w"):
progs = pydot.__find_executables(path_with_spaces)
assert progs["dot"] == prog_path
assert sorted(
("dot", "twopi", "neato", "circo", "fdp", "sfdp")
) == sorted(progs)


@pytest.mark.parametrize("quoted", (True, False), ids=("quoted", "unqoted"))
@pytest.mark.parametrize(
"windows,conda,extension",
(
(True, True, "bat"),
(True, False, "exe"),
(False, False, "unix"),
(False, True, "unix"),
),
)
@pytest.mark.parametrize(
"program", ("dot", "twopi", "neato", "circo", "fdp", "sfdp")
)
@mock.patch.object(pydot, "is_anacoda")
@mock.patch.object(pydot, "is_windows")
def test_f_e(
mock_win, mock_conda, tmpdir, windows, conda, extension, program, quoted
):
path = tmpdir.mkdir("PYDOT is_da best!")

mock_win.return_value = windows
mock_conda.return_value = conda

unix_path = str(path.join(program))
touch(unix_path)

exe_path = str(path.join(program + ".exe"))
touch(exe_path)

bat_path = str(path.join(program + ".bat"))
touch(bat_path)

if quoted:
path = '"{}"'.format(path)
unix_path = '"{}"'.format(unix_path)
bat_path = '"{}"'.format(bat_path)
exe_path = '"{}"'.format(exe_path)

progs = pydot.__find_executables(str(path))

if extension == "bat":
assert progs[program] == bat_path
elif extension == "exe":
assert progs[program] == exe_path
elif extension == "unix":
assert progs[program] == unix_path
else:
raise Exception("Unknown extension {}".format(extension))
57 changes: 1 addition & 56 deletions test/test_pydot.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import warnings
from textwrap import dedent

import mock
import pytest
import mock

import pydot_ng as pydot

Expand Down Expand Up @@ -279,58 +279,3 @@ def test_dotparser_import_warning():
del sys.modules["pydot_ng"]
warnings.simplefilter("always")
import pydot_ng # noqa: F401


def test_find_executables_fake_path():
assert pydot.__find_executables("/fake/path/") is None


def test_find_executables_real_path_no_programs(tmpdir):
assert pydot.__find_executables(str(tmpdir)) is None


def test_find_executables_path_needs_strip(tmpdir):
path = tmpdir.mkdir("subdir")
prog_path = str(path.join("dot"))

path_with_spaces = " {} ".format(path)

with open(prog_path, "w"):
progs = pydot.__find_executables(path_with_spaces)
assert progs["dot"] == prog_path
assert sorted(
("dot", "twopi", "neato", "circo", "fdp", "sfdp")
) == sorted(progs)


def test_find_executables_unix_and_exe_exists(tmpdir):
path = str(tmpdir)
prog_unix_path = str(tmpdir.join("dot"))
prog_exe_path = str(tmpdir.join("dot.exe"))

with open(prog_unix_path, "w"):
with open(prog_exe_path, "w"):
progs = pydot.__find_executables(path)
assert progs["dot"] == prog_unix_path
assert progs["dot"] != prog_exe_path


@pytest.mark.parametrize("quoted", (True, False), ids=("quoted", "unqoted"))
@pytest.mark.parametrize("extension", ("", ".exe"))
@pytest.mark.parametrize(
"program", ("dot", "twopi", "neato", "circo", "fdp", "sfdp")
)
def test_find_executables(tmpdir, program, extension, quoted):
path = tmpdir.mkdir("PYDOT is_da best!")
prog_path = str(path.join(program + extension))

with open(prog_path, "w"):
if quoted:
path = "\"{}\"".format(path)
prog_path = "\"{}\"".format(prog_path)

progs = pydot.__find_executables(str(path))
assert progs[program] == prog_path
assert sorted(
("dot", "twopi", "neato", "circo", "fdp", "sfdp")
) == sorted(progs)