Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)

Merge pull request #52523 from dotlambda/graphviz-hardcode

python.pkgs.graphviz: hardcode path to graphviz's bin/

authored by

Robert Schütz and committed by
GitHub
9f3d9915 f0f7531d

+249 -18
+35 -9
pkgs/development/python-modules/graphviz/default.nix
··· 1 - { stdenv 2 , buildPythonPackage 3 - , fetchPypi 4 - , pkgs 5 }: 6 7 buildPythonPackage rec { 8 pname = "graphviz"; 9 version = "0.10.1"; 10 11 - src = fetchPypi { 12 - inherit pname version; 13 - extension = "zip"; 14 - sha256 = "d311be4fddfe832a56986ac5e1d6e8715d7fcb0208560da79d1bb0f72abef41f"; 15 }; 16 17 - propagatedBuildInputs = [ pkgs.graphviz ]; 18 19 - meta = with stdenv.lib; { 20 description = "Simple Python interface for Graphviz"; 21 homepage = https://github.com/xflr6/graphviz; 22 license = licenses.mit; 23 }; 24 25 }
··· 1 + { lib 2 , buildPythonPackage 3 + , fetchFromGitHub 4 + , substituteAll 5 + , graphviz 6 + , makeFontsConf 7 + , freefont_ttf 8 + , mock 9 + , pytest 10 + , pytest-mock 11 + , pytestcov 12 }: 13 14 buildPythonPackage rec { 15 pname = "graphviz"; 16 version = "0.10.1"; 17 18 + # patch does not apply to PyPI tarball due to different line endings 19 + src = fetchFromGitHub { 20 + owner = "xflr6"; 21 + repo = "graphviz"; 22 + rev = version; 23 + sha256 = "1vqk4xy45c72la56j24z9jmjp5a0aa2k32fybnlbkzqjvvbl72d8"; 24 }; 25 26 + patches = [ 27 + (substituteAll { 28 + src = ./hardcode-graphviz-path.patch; 29 + inherit graphviz; 30 + }) 31 + ]; 32 33 + # Fontconfig error: Cannot load default config file 34 + FONTCONFIG_FILE = makeFontsConf { 35 + fontDirectories = [ freefont_ttf ]; 36 + }; 37 + 38 + checkInputs = [ mock pytest pytest-mock pytestcov ]; 39 + 40 + checkPhase = '' 41 + pytest 42 + ''; 43 + 44 + meta = with lib; { 45 description = "Simple Python interface for Graphviz"; 46 homepage = https://github.com/xflr6/graphviz; 47 license = licenses.mit; 48 + maintainers = with maintainers; [ dotlambda ]; 49 }; 50 51 }
+95
pkgs/development/python-modules/graphviz/hardcode-graphviz-path.patch
···
··· 1 + diff --git a/graphviz/backend.py b/graphviz/backend.py 2 + index 704017b..fe4aefe 100644 3 + --- a/graphviz/backend.py 4 + +++ b/graphviz/backend.py 5 + @@ -114,7 +114,7 @@ def command(engine, format, filepath=None, renderer=None, formatter=None): 6 + suffix = '.'.join(reversed(format_arg)) 7 + format_arg = ':'.join(format_arg) 8 + 9 + - cmd = [engine, '-T%s' % format_arg] 10 + + cmd = [os.path.join('@graphviz@/bin', engine), '-T%s' % format_arg] 11 + rendered = None 12 + if filepath is not None: 13 + cmd.extend(['-O', filepath]) 14 + @@ -217,7 +217,7 @@ def version(): 15 + subprocess.CalledProcessError: If the exit status is non-zero. 16 + RuntimmeError: If the output cannot be parsed into a version number. 17 + """ 18 + - cmd = ['dot', '-V'] 19 + + cmd = ['@graphviz@/bin/dot', '-V'] 20 + out, _ = run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 21 + 22 + info = out.decode('ascii') 23 + diff --git a/tests/test_backend.py b/tests/test_backend.py 24 + index 7ec12f7..2e8550d 100644 25 + --- a/tests/test_backend.py 26 + +++ b/tests/test_backend.py 27 + @@ -47,6 +47,7 @@ def test_render_formatter_unknown(): 28 + render('dot', 'ps', 'nonfilepath', 'ps', '') 29 + 30 + 31 + +@pytest.mark.skip(reason='empty $PATH has no effect') 32 + @pytest.mark.usefixtures('empty_path') 33 + def test_render_missing_executable(): 34 + with pytest.raises(ExecutableNotFound, match=r'execute'): 35 + @@ -85,7 +86,7 @@ def test_render_mocked(capsys, mocker, Popen, quiet): 36 + 37 + assert render('dot', 'pdf', 'nonfilepath', quiet=quiet) == 'nonfilepath.pdf' 38 + 39 + - Popen.assert_called_once_with(['dot', '-Tpdf', '-O', 'nonfilepath'], 40 + + Popen.assert_called_once_with(['@graphviz@/bin/dot', '-Tpdf', '-O', 'nonfilepath'], 41 + stdout=subprocess.PIPE, 42 + stderr=subprocess.PIPE, 43 + startupinfo=mocker.ANY) 44 + @@ -94,6 +95,7 @@ def test_render_mocked(capsys, mocker, Popen, quiet): 45 + assert capsys.readouterr() == ('', '' if quiet else 'stderr') 46 + 47 + 48 + +@pytest.mark.skip(reason='empty $PATH has no effect') 49 + @pytest.mark.usefixtures('empty_path') 50 + def test_pipe_missing_executable(): 51 + with pytest.raises(ExecutableNotFound, match=r'execute'): 52 + @@ -143,7 +145,7 @@ def test_pipe_pipe_invalid_data_mocked(mocker, py2, Popen, quiet): # noqa: N803 53 + assert e.value.returncode is mocker.sentinel.returncode 54 + assert e.value.stdout is mocker.sentinel.out 55 + assert e.value.stderr is err 56 + - Popen.assert_called_once_with(['dot', '-Tpng'], 57 + + Popen.assert_called_once_with(['@graphviz@/bin/dot', '-Tpng'], 58 + stdin=subprocess.PIPE, 59 + stdout=subprocess.PIPE, 60 + stderr=subprocess.PIPE, 61 + @@ -166,7 +168,7 @@ def test_pipe_mocked(capsys, mocker, Popen, quiet): # noqa: N803 62 + 63 + assert pipe('dot', 'png', b'nongraph', quiet=quiet) is mocker.sentinel.out 64 + 65 + - Popen.assert_called_once_with(['dot', '-Tpng'], 66 + + Popen.assert_called_once_with(['@graphviz@/bin/dot', '-Tpng'], 67 + stdin=subprocess.PIPE, 68 + stdout=subprocess.PIPE, 69 + stderr=subprocess.PIPE, 70 + @@ -176,6 +178,7 @@ def test_pipe_mocked(capsys, mocker, Popen, quiet): # noqa: N803 71 + assert capsys.readouterr() == ('', '' if quiet else 'stderr') 72 + 73 + 74 + +@pytest.mark.skip(reason='empty $PATH has no effect') 75 + @pytest.mark.usefixtures('empty_path') 76 + def test_version_missing_executable(): 77 + with pytest.raises(ExecutableNotFound, match=r'execute'): 78 + @@ -196,7 +199,7 @@ def test_version_parsefail_mocked(mocker, Popen): 79 + with pytest.raises(RuntimeError): 80 + version() 81 + 82 + - Popen.assert_called_once_with(['dot', '-V'], 83 + + Popen.assert_called_once_with(['@graphviz@/bin/dot', '-V'], 84 + stdout=subprocess.PIPE, 85 + stderr=subprocess.STDOUT, 86 + startupinfo=mocker.ANY) 87 + @@ -211,7 +214,7 @@ def test_version_mocked(mocker, Popen): 88 + 89 + assert version() == (1, 2, 3) 90 + 91 + - Popen.assert_called_once_with(['dot', '-V'], 92 + + Popen.assert_called_once_with(['@graphviz@/bin/dot', '-V'], 93 + stdout=subprocess.PIPE, 94 + stderr=subprocess.STDOUT, 95 + startupinfo=mocker.ANY)
+9
pkgs/development/python-modules/objgraph/default.nix
··· 2 , buildPythonPackage 3 , fetchPypi 4 , isPyPy 5 , graphviz 6 , mock 7 }: ··· 17 18 # Tests fail with PyPy. 19 disabled = isPyPy; 20 21 propagatedBuildInputs = [ graphviz ]; 22
··· 2 , buildPythonPackage 3 , fetchPypi 4 , isPyPy 5 + , substituteAll 6 + , graphvizPkg 7 , graphviz 8 , mock 9 }: ··· 19 20 # Tests fail with PyPy. 21 disabled = isPyPy; 22 + 23 + patches = [ 24 + (substituteAll { 25 + src = ./hardcode-graphviz-path.patch; 26 + graphviz = graphvizPkg; 27 + }) 28 + ]; 29 30 propagatedBuildInputs = [ graphviz ]; 31
+61
pkgs/development/python-modules/objgraph/hardcode-graphviz-path.patch
···
··· 1 + diff --git a/objgraph.py b/objgraph.py 2 + index 88e307b..0369f49 100755 3 + --- a/objgraph.py 4 + +++ b/objgraph.py 5 + @@ -1045,12 +1045,12 @@ def _present_graph(dot_filename, filename=None): 6 + if not filename and _program_in_path('xdot'): 7 + print("Spawning graph viewer (xdot)") 8 + subprocess.Popen(['xdot', dot_filename], close_fds=True) 9 + - elif _program_in_path('dot'): 10 + + elif True: # path to dot is hardcoded and hence always in $PATH 11 + if not filename: 12 + print("Graph viewer (xdot) not found, generating a png instead") 13 + filename = dot_filename[:-4] + '.png' 14 + stem, ext = os.path.splitext(filename) 15 + - cmd = ['dot', '-T' + ext[1:], '-o' + filename, dot_filename] 16 + + cmd = ['@graphviz@/bin/dot', '-T' + ext[1:], '-o' + filename, dot_filename] 17 + dot = subprocess.Popen(cmd, close_fds=False) 18 + dot.wait() 19 + if dot.returncode != 0: 20 + diff --git a/tests.py b/tests.py 21 + index 7db2888..bdb666e 100755 22 + --- a/tests.py 23 + +++ b/tests.py 24 + @@ -557,7 +557,7 @@ class PresentGraphTest(CaptureMixin, TemporaryDirectoryMixin, 25 + self.programsInPath(['dot']) 26 + objgraph._present_graph('foo.dot', 'bar.png') 27 + self.assertOutput(""" 28 + - subprocess.Popen(['dot', '-Tpng', '-obar.png', 'foo.dot']) 29 + + subprocess.Popen(['@graphviz@/bin/dot', '-Tpng', '-obar.png', 'foo.dot']) 30 + Image generated as bar.png 31 + """) 32 + 33 + @@ -566,11 +566,12 @@ class PresentGraphTest(CaptureMixin, TemporaryDirectoryMixin, 34 + objgraph.subprocess.should_fail = True 35 + objgraph._present_graph('f.dot', 'b.png') 36 + self.assertOutput(""" 37 + - subprocess.Popen(['dot', '-Tpng', '-ob.png', 'f.dot']) 38 + - dot failed (exit code 1) while executing "dot -Tpng -ob.png f.dot" 39 + + subprocess.Popen(['@graphviz@/bin/dot', '-Tpng', '-ob.png', 'f.dot']) 40 + + dot failed (exit code 1) while executing "@graphviz@/bin/dot -Tpng -ob.png f.dot" 41 + """) 42 + 43 + - def test_present_png_no_dot(self): 44 + + @unittest.skip("empty $PATH has no effect") 45 + + def no_test_present_png_no_dot(self): 46 + self.programsInPath([]) 47 + objgraph._present_graph('foo.dot', 'bar.png') 48 + self.assertOutput(""" 49 + @@ -591,10 +592,11 @@ class PresentGraphTest(CaptureMixin, TemporaryDirectoryMixin, 50 + objgraph._present_graph('foo.dot') 51 + self.assertOutput(""" 52 + Graph viewer (xdot) not found, generating a png instead 53 + - subprocess.Popen(['dot', '-Tpng', '-ofoo.png', 'foo.dot']) 54 + + subprocess.Popen(['@graphviz@/bin/dot', '-Tpng', '-ofoo.png', 'foo.dot']) 55 + Image generated as foo.png 56 + """) 57 + 58 + + @unittest.skip("empty $PATH has no effect") 59 + def test_present_no_xdot_and_no_not(self): 60 + self.programsInPath([]) 61 + objgraph._present_graph('foo.dot')
+27 -6
pkgs/development/python-modules/pydot/default.nix
··· 1 { lib 2 , buildPythonPackage 3 , fetchPypi 4 , chardet 5 , pyparsing 6 - , graphviz 7 }: 8 9 buildPythonPackage rec { 10 pname = "pydot"; 11 - version = "1.4.0"; 12 13 src = fetchPypi { 14 inherit pname version; 15 - sha256 = "02yp2k7p1kh0azwd932jhvfc3nxxdv9dimh7hdgwdnmp05yms6cq"; 16 }; 17 checkInputs = [ chardet ]; 18 - # No tests in archive 19 - doCheck = false; 20 - propagatedBuildInputs = [pyparsing graphviz]; 21 meta = { 22 homepage = https://github.com/erocarrera/pydot; 23 description = "Allows to easily create both directed and non directed graphs from Python";
··· 1 { lib 2 , buildPythonPackage 3 , fetchPypi 4 + , substituteAll 5 + , graphviz 6 + , python 7 , chardet 8 , pyparsing 9 }: 10 11 buildPythonPackage rec { 12 pname = "pydot"; 13 + version = "1.4.1"; 14 15 src = fetchPypi { 16 inherit pname version; 17 + sha256 = "d49c9d4dd1913beec2a997f831543c8cbd53e535b1a739e921642fe416235f01"; 18 }; 19 + 20 + patches = [ 21 + (substituteAll { 22 + src = ./hardcode-graphviz-path.patch; 23 + inherit graphviz; 24 + }) 25 + ]; 26 + 27 + postPatch = '' 28 + # test_graphviz_regression_tests also fails upstream: https://github.com/pydot/pydot/pull/198 29 + substituteInPlace test/pydot_unittest.py \ 30 + --replace "test_graphviz_regression_tests" "no_test_graphviz_regression_tests" 31 + ''; 32 + 33 + propagatedBuildInputs = [ pyparsing ]; 34 + 35 checkInputs = [ chardet ]; 36 + 37 + checkPhase = '' 38 + cd test 39 + ${python.interpreter} pydot_unittest.py 40 + ''; 41 + 42 meta = { 43 homepage = https://github.com/erocarrera/pydot; 44 description = "Allows to easily create both directed and non directed graphs from Python";
+13
pkgs/development/python-modules/pydot/hardcode-graphviz-path.patch
···
··· 1 + diff --git a/pydot.py b/pydot.py 2 + index 3c7da4d..582c5bc 100644 3 + --- a/pydot.py 4 + +++ b/pydot.py 5 + @@ -124,7 +124,7 @@ def call_graphviz(program, arguments, working_dir, **kwargs): 6 + 'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''), 7 + } 8 + 9 + - program_with_args = [program, ] + arguments 10 + + program_with_args = ['@graphviz@/bin/' + program, ] + arguments 11 + 12 + process = subprocess.Popen( 13 + program_with_args,
+9 -3
pkgs/top-level/python-packages.nix
··· 3107 3108 pyte = callPackage ../development/python-modules/pyte { }; 3109 3110 - graphviz = callPackage ../development/python-modules/graphviz { }; 3111 3112 pygraphviz = callPackage ../development/python-modules/pygraphviz { 3113 graphviz = pkgs.graphviz; # not the python package ··· 3243 3244 obfsproxy = callPackage ../development/python-modules/obfsproxy { }; 3245 3246 - objgraph = callPackage ../development/python-modules/objgraph { }; 3247 3248 odo = callPackage ../development/python-modules/odo { }; 3249 ··· 3550 3551 pydispatcher = callPackage ../development/python-modules/pydispatcher { }; 3552 3553 - pydot = callPackage ../development/python-modules/pydot { }; 3554 3555 pydot_ng = callPackage ../development/python-modules/pydot_ng { }; 3556
··· 3107 3108 pyte = callPackage ../development/python-modules/pyte { }; 3109 3110 + graphviz = callPackage ../development/python-modules/graphviz { 3111 + inherit (pkgs) graphviz; 3112 + }; 3113 3114 pygraphviz = callPackage ../development/python-modules/pygraphviz { 3115 graphviz = pkgs.graphviz; # not the python package ··· 3245 3246 obfsproxy = callPackage ../development/python-modules/obfsproxy { }; 3247 3248 + objgraph = callPackage ../development/python-modules/objgraph { 3249 + graphvizPkg = pkgs.graphviz; 3250 + }; 3251 3252 odo = callPackage ../development/python-modules/odo { }; 3253 ··· 3554 3555 pydispatcher = callPackage ../development/python-modules/pydispatcher { }; 3556 3557 + pydot = callPackage ../development/python-modules/pydot { 3558 + inherit (pkgs) graphviz; 3559 + }; 3560 3561 pydot_ng = callPackage ../development/python-modules/pydot_ng { }; 3562