about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--pkgs/development/python-modules/graphviz/default.nix44
-rw-r--r--pkgs/development/python-modules/graphviz/hardcode-graphviz-path.patch95
-rw-r--r--pkgs/development/python-modules/objgraph/default.nix9
-rw-r--r--pkgs/development/python-modules/objgraph/hardcode-graphviz-path.patch61
-rw-r--r--pkgs/development/python-modules/pydot/default.nix33
-rw-r--r--pkgs/development/python-modules/pydot/hardcode-graphviz-path.patch13
-rw-r--r--pkgs/top-level/python-packages.nix12
7 files changed, 249 insertions, 18 deletions
diff --git a/pkgs/development/python-modules/graphviz/default.nix b/pkgs/development/python-modules/graphviz/default.nix
index 3e9ee8b17f7c..572fdcaee51a 100644
--- a/pkgs/development/python-modules/graphviz/default.nix
+++ b/pkgs/development/python-modules/graphviz/default.nix
@@ -1,25 +1,51 @@
-{ stdenv
+{ lib
 , buildPythonPackage
-, fetchPypi
-, pkgs
+, fetchFromGitHub
+, substituteAll
+, graphviz
+, makeFontsConf
+, freefont_ttf
+, mock
+, pytest
+, pytest-mock
+, pytestcov
 }:
 
 buildPythonPackage rec {
   pname = "graphviz";
   version = "0.10.1";
 
-  src = fetchPypi {
-    inherit pname version;
-    extension = "zip";
-    sha256 = "d311be4fddfe832a56986ac5e1d6e8715d7fcb0208560da79d1bb0f72abef41f";
+  # patch does not apply to PyPI tarball due to different line endings
+  src = fetchFromGitHub {
+    owner = "xflr6";
+    repo = "graphviz";
+    rev = version;
+    sha256 = "1vqk4xy45c72la56j24z9jmjp5a0aa2k32fybnlbkzqjvvbl72d8";
   };
 
-  propagatedBuildInputs = [ pkgs.graphviz ];
+  patches = [
+    (substituteAll {
+      src = ./hardcode-graphviz-path.patch;
+      inherit graphviz;
+    })
+  ];
 
-  meta = with stdenv.lib; {
+  # Fontconfig error: Cannot load default config file 
+  FONTCONFIG_FILE = makeFontsConf { 
+    fontDirectories = [ freefont_ttf ]; 
+  };
+
+  checkInputs = [ mock pytest pytest-mock pytestcov ];
+
+  checkPhase = ''
+    pytest
+  '';
+
+  meta = with lib; {
     description = "Simple Python interface for Graphviz";
     homepage = https://github.com/xflr6/graphviz;
     license = licenses.mit;
+    maintainers = with maintainers; [ dotlambda ];
   };
 
 }
diff --git a/pkgs/development/python-modules/graphviz/hardcode-graphviz-path.patch b/pkgs/development/python-modules/graphviz/hardcode-graphviz-path.patch
new file mode 100644
index 000000000000..ad632974c28c
--- /dev/null
+++ b/pkgs/development/python-modules/graphviz/hardcode-graphviz-path.patch
@@ -0,0 +1,95 @@
+diff --git a/graphviz/backend.py b/graphviz/backend.py
+index 704017b..fe4aefe 100644
+--- a/graphviz/backend.py
++++ b/graphviz/backend.py
+@@ -114,7 +114,7 @@ def command(engine, format, filepath=None, renderer=None, formatter=None):
+     suffix = '.'.join(reversed(format_arg))
+     format_arg = ':'.join(format_arg)
+ 
+-    cmd = [engine, '-T%s' % format_arg]
++    cmd = [os.path.join('@graphviz@/bin', engine), '-T%s' % format_arg]
+     rendered = None
+     if filepath is not None:
+         cmd.extend(['-O', filepath])
+@@ -217,7 +217,7 @@ def version():
+         subprocess.CalledProcessError: If the exit status is non-zero.
+         RuntimmeError: If the output cannot be parsed into a version number.
+     """
+-    cmd = ['dot', '-V']
++    cmd = ['@graphviz@/bin/dot', '-V']
+     out, _ = run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ 
+     info = out.decode('ascii')
+diff --git a/tests/test_backend.py b/tests/test_backend.py
+index 7ec12f7..2e8550d 100644
+--- a/tests/test_backend.py
++++ b/tests/test_backend.py
+@@ -47,6 +47,7 @@ def test_render_formatter_unknown():
+         render('dot', 'ps', 'nonfilepath', 'ps', '')
+ 
+ 
++@pytest.mark.skip(reason='empty $PATH has no effect')
+ @pytest.mark.usefixtures('empty_path')
+ def test_render_missing_executable():
+     with pytest.raises(ExecutableNotFound, match=r'execute'):
+@@ -85,7 +86,7 @@ def test_render_mocked(capsys, mocker, Popen, quiet):
+ 
+     assert render('dot', 'pdf', 'nonfilepath', quiet=quiet) == 'nonfilepath.pdf'
+ 
+-    Popen.assert_called_once_with(['dot', '-Tpdf', '-O', 'nonfilepath'],
++    Popen.assert_called_once_with(['@graphviz@/bin/dot', '-Tpdf', '-O', 'nonfilepath'],
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE,
+                                   startupinfo=mocker.ANY)
+@@ -94,6 +95,7 @@ def test_render_mocked(capsys, mocker, Popen, quiet):
+     assert capsys.readouterr() == ('', '' if quiet else 'stderr')
+ 
+ 
++@pytest.mark.skip(reason='empty $PATH has no effect')
+ @pytest.mark.usefixtures('empty_path')
+ def test_pipe_missing_executable():
+     with pytest.raises(ExecutableNotFound, match=r'execute'):
+@@ -143,7 +145,7 @@ def test_pipe_pipe_invalid_data_mocked(mocker, py2, Popen, quiet):  # noqa: N803
+     assert e.value.returncode is mocker.sentinel.returncode
+     assert e.value.stdout is mocker.sentinel.out
+     assert e.value.stderr is err
+-    Popen.assert_called_once_with(['dot', '-Tpng'],
++    Popen.assert_called_once_with(['@graphviz@/bin/dot', '-Tpng'],
+                                   stdin=subprocess.PIPE,
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE,
+@@ -166,7 +168,7 @@ def test_pipe_mocked(capsys, mocker, Popen, quiet):  # noqa: N803
+ 
+     assert pipe('dot', 'png', b'nongraph', quiet=quiet) is mocker.sentinel.out
+ 
+-    Popen.assert_called_once_with(['dot', '-Tpng'],
++    Popen.assert_called_once_with(['@graphviz@/bin/dot', '-Tpng'],
+                                   stdin=subprocess.PIPE,
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE,
+@@ -176,6 +178,7 @@ def test_pipe_mocked(capsys, mocker, Popen, quiet):  # noqa: N803
+     assert capsys.readouterr() == ('', '' if quiet else 'stderr')
+ 
+ 
++@pytest.mark.skip(reason='empty $PATH has no effect')
+ @pytest.mark.usefixtures('empty_path')
+ def test_version_missing_executable():
+     with pytest.raises(ExecutableNotFound, match=r'execute'):
+@@ -196,7 +199,7 @@ def test_version_parsefail_mocked(mocker, Popen):
+     with pytest.raises(RuntimeError):
+         version()
+ 
+-    Popen.assert_called_once_with(['dot', '-V'],
++    Popen.assert_called_once_with(['@graphviz@/bin/dot', '-V'],
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.STDOUT,
+                                   startupinfo=mocker.ANY)
+@@ -211,7 +214,7 @@ def test_version_mocked(mocker, Popen):
+ 
+     assert version() == (1, 2, 3)
+ 
+-    Popen.assert_called_once_with(['dot', '-V'],
++    Popen.assert_called_once_with(['@graphviz@/bin/dot', '-V'],
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.STDOUT,
+                                   startupinfo=mocker.ANY)
diff --git a/pkgs/development/python-modules/objgraph/default.nix b/pkgs/development/python-modules/objgraph/default.nix
index 16dc60fc28a3..0eb1deee0d39 100644
--- a/pkgs/development/python-modules/objgraph/default.nix
+++ b/pkgs/development/python-modules/objgraph/default.nix
@@ -2,6 +2,8 @@
 , buildPythonPackage
 , fetchPypi
 , isPyPy
+, substituteAll
+, graphvizPkg
 , graphviz
 , mock
 }:
@@ -18,6 +20,13 @@ buildPythonPackage rec {
   # Tests fail with PyPy.
   disabled = isPyPy;
 
+  patches = [
+    (substituteAll {
+      src = ./hardcode-graphviz-path.patch;
+      graphviz = graphvizPkg;
+    })
+  ];
+
   propagatedBuildInputs = [ graphviz ];
 
   checkInputs = [ mock ];
diff --git a/pkgs/development/python-modules/objgraph/hardcode-graphviz-path.patch b/pkgs/development/python-modules/objgraph/hardcode-graphviz-path.patch
new file mode 100644
index 000000000000..c5be5de64eed
--- /dev/null
+++ b/pkgs/development/python-modules/objgraph/hardcode-graphviz-path.patch
@@ -0,0 +1,61 @@
+diff --git a/objgraph.py b/objgraph.py
+index 88e307b..0369f49 100755
+--- a/objgraph.py
++++ b/objgraph.py
+@@ -1045,12 +1045,12 @@ def _present_graph(dot_filename, filename=None):
+     if not filename and _program_in_path('xdot'):
+         print("Spawning graph viewer (xdot)")
+         subprocess.Popen(['xdot', dot_filename], close_fds=True)
+-    elif _program_in_path('dot'):
++    elif True: # path to dot is hardcoded and hence always in $PATH
+         if not filename:
+             print("Graph viewer (xdot) not found, generating a png instead")
+             filename = dot_filename[:-4] + '.png'
+         stem, ext = os.path.splitext(filename)
+-        cmd = ['dot', '-T' + ext[1:], '-o' + filename, dot_filename]
++        cmd = ['@graphviz@/bin/dot', '-T' + ext[1:], '-o' + filename, dot_filename]
+         dot = subprocess.Popen(cmd, close_fds=False)
+         dot.wait()
+         if dot.returncode != 0:
+diff --git a/tests.py b/tests.py
+index 7db2888..bdb666e 100755
+--- a/tests.py
++++ b/tests.py
+@@ -557,7 +557,7 @@ class PresentGraphTest(CaptureMixin, TemporaryDirectoryMixin,
+         self.programsInPath(['dot'])
+         objgraph._present_graph('foo.dot', 'bar.png')
+         self.assertOutput("""
+-            subprocess.Popen(['dot', '-Tpng', '-obar.png', 'foo.dot'])
++            subprocess.Popen(['@graphviz@/bin/dot', '-Tpng', '-obar.png', 'foo.dot'])
+             Image generated as bar.png
+         """)
+ 
+@@ -566,11 +566,12 @@ class PresentGraphTest(CaptureMixin, TemporaryDirectoryMixin,
+         objgraph.subprocess.should_fail = True
+         objgraph._present_graph('f.dot', 'b.png')
+         self.assertOutput("""
+-            subprocess.Popen(['dot', '-Tpng', '-ob.png', 'f.dot'])
+-            dot failed (exit code 1) while executing "dot -Tpng -ob.png f.dot"
++            subprocess.Popen(['@graphviz@/bin/dot', '-Tpng', '-ob.png', 'f.dot'])
++            dot failed (exit code 1) while executing "@graphviz@/bin/dot -Tpng -ob.png f.dot"
+         """)
+ 
+-    def test_present_png_no_dot(self):
++    @unittest.skip("empty $PATH has no effect")
++    def no_test_present_png_no_dot(self):
+         self.programsInPath([])
+         objgraph._present_graph('foo.dot', 'bar.png')
+         self.assertOutput("""
+@@ -591,10 +592,11 @@ class PresentGraphTest(CaptureMixin, TemporaryDirectoryMixin,
+         objgraph._present_graph('foo.dot')
+         self.assertOutput("""
+             Graph viewer (xdot) not found, generating a png instead
+-            subprocess.Popen(['dot', '-Tpng', '-ofoo.png', 'foo.dot'])
++            subprocess.Popen(['@graphviz@/bin/dot', '-Tpng', '-ofoo.png', 'foo.dot'])
+             Image generated as foo.png
+         """)
+ 
++    @unittest.skip("empty $PATH has no effect")
+     def test_present_no_xdot_and_no_not(self):
+         self.programsInPath([])
+         objgraph._present_graph('foo.dot')
diff --git a/pkgs/development/python-modules/pydot/default.nix b/pkgs/development/python-modules/pydot/default.nix
index ddbc0a5bfdd7..021043d9e9db 100644
--- a/pkgs/development/python-modules/pydot/default.nix
+++ b/pkgs/development/python-modules/pydot/default.nix
@@ -1,23 +1,44 @@
 { lib
 , buildPythonPackage
 , fetchPypi
+, substituteAll
+, graphviz
+, python
 , chardet
 , pyparsing
-, graphviz
 }:
 
 buildPythonPackage rec {
   pname = "pydot";
-  version = "1.4.0";
+  version = "1.4.1";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "02yp2k7p1kh0azwd932jhvfc3nxxdv9dimh7hdgwdnmp05yms6cq";
+    sha256 = "d49c9d4dd1913beec2a997f831543c8cbd53e535b1a739e921642fe416235f01";
   };
+
+  patches = [
+    (substituteAll {
+      src = ./hardcode-graphviz-path.patch;
+      inherit graphviz;
+    })
+  ];
+
+  postPatch = ''
+    # test_graphviz_regression_tests also fails upstream: https://github.com/pydot/pydot/pull/198
+    substituteInPlace test/pydot_unittest.py \
+      --replace "test_graphviz_regression_tests" "no_test_graphviz_regression_tests"
+  '';
+
+  propagatedBuildInputs = [ pyparsing ];
+
   checkInputs = [ chardet ];
-  # No tests in archive
-  doCheck = false;
-  propagatedBuildInputs = [pyparsing graphviz];
+
+  checkPhase = ''
+    cd test
+    ${python.interpreter} pydot_unittest.py
+  '';
+
   meta = {
     homepage = https://github.com/erocarrera/pydot;
     description = "Allows to easily create both directed and non directed graphs from Python";
diff --git a/pkgs/development/python-modules/pydot/hardcode-graphviz-path.patch b/pkgs/development/python-modules/pydot/hardcode-graphviz-path.patch
new file mode 100644
index 000000000000..e862f1e7c2c3
--- /dev/null
+++ b/pkgs/development/python-modules/pydot/hardcode-graphviz-path.patch
@@ -0,0 +1,13 @@
+diff --git a/pydot.py b/pydot.py
+index 3c7da4d..582c5bc 100644
+--- a/pydot.py
++++ b/pydot.py
+@@ -124,7 +124,7 @@ def call_graphviz(program, arguments, working_dir, **kwargs):
+         'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''),
+     }
+ 
+-    program_with_args = [program, ] + arguments
++    program_with_args = ['@graphviz@/bin/' + program, ] + arguments
+ 
+     process = subprocess.Popen(
+         program_with_args,
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index 167888b325df..950fc1c9cdef 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -3107,7 +3107,9 @@ in {
 
   pyte = callPackage ../development/python-modules/pyte { };
 
-  graphviz = callPackage ../development/python-modules/graphviz { };
+  graphviz = callPackage ../development/python-modules/graphviz {
+    inherit (pkgs) graphviz;
+  };
 
   pygraphviz = callPackage ../development/python-modules/pygraphviz {
     graphviz = pkgs.graphviz; # not the python package
@@ -3243,7 +3245,9 @@ in {
 
   obfsproxy = callPackage ../development/python-modules/obfsproxy { };
 
-  objgraph = callPackage ../development/python-modules/objgraph { };
+  objgraph = callPackage ../development/python-modules/objgraph {
+    graphvizPkg = pkgs.graphviz;
+  };
 
   odo = callPackage ../development/python-modules/odo { };
 
@@ -3550,7 +3554,9 @@ in {
 
   pydispatcher = callPackage ../development/python-modules/pydispatcher { };
 
-  pydot = callPackage ../development/python-modules/pydot { };
+  pydot = callPackage ../development/python-modules/pydot {
+    inherit (pkgs) graphviz;
+  };
 
   pydot_ng = callPackage ../development/python-modules/pydot_ng { };