Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/graphviz/rendering.py: 59%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

41 statements  

1"""Save DOT code objects, render with Graphviz ``dot``, and open in viewer.""" 

2 

3import logging 

4import os 

5import pathlib 

6import typing 

7 

8from . import _tools 

9from . import backend 

10from . import saving 

11 

12__all__ = ['Render'] 

13 

14 

15log = logging.getLogger(__name__) 

16 

17 

18class Render(saving.Save, backend.Render, backend.View): 

19 """Write source lines to file and render with Graphviz.""" 

20 

21 @_tools.deprecate_positional_args(supported_number=1, ignore_arg='self') 

22 def render(self, 

23 filename: typing.Union[os.PathLike, str, None] = None, 

24 directory: typing.Union[os.PathLike, str, None] = None, 

25 view: bool = False, 

26 cleanup: bool = False, 

27 format: typing.Optional[str] = None, 

28 renderer: typing.Optional[str] = None, 

29 formatter: typing.Optional[str] = None, 

30 neato_no_op: typing.Union[bool, int, None] = None, 

31 quiet: bool = False, 

32 quiet_view: bool = False, *, 

33 outfile: typing.Union[os.PathLike, str, None] = None, 

34 engine: typing.Optional[str] = None, 

35 raise_if_result_exists: bool = False, 

36 overwrite_source: bool = False) -> str: 

37 r"""Save the source to file and render with the Graphviz engine. 

38 

39 Args: 

40 filename: Filename for saving the source 

41 (defaults to ``name`` + ``'.gv'``).s 

42 directory: (Sub)directory for source saving and rendering. 

43 view (bool): Open the rendered result 

44 with the default application. 

45 cleanup (bool): Delete the source file 

46 after successful rendering. 

47 format: The output format used for rendering 

48 (``'pdf'``, ``'png'``, etc.). 

49 renderer: The output renderer used for rendering 

50 (``'cairo'``, ``'gd'``, ...). 

51 formatter: The output formatter used for rendering 

52 (``'cairo'``, ``'gd'``, ...). 

53 neato_no_op: Neato layout engine no-op flag. 

54 quiet (bool): Suppress ``stderr`` output 

55 from the layout subprocess. 

56 quiet_view (bool): Suppress ``stderr`` output 

57 from the viewer process 

58 (implies ``view=True``, ineffective on Windows platform). 

59 outfile: Path for the rendered output file. 

60 engine: Layout engine for rendering 

61 (``'dot'``, ``'neato'``, ...). 

62 raise_if_result_exists: Raise :exc:`graphviz.FileExistsError` 

63 if the result file exists. 

64 overwrite_source: Allow ``dot`` to write to the file it reads from. 

65 Incompatible with ``raise_if_result_exists``. 

66 

67 Returns: 

68 The (possibly relative) path of the rendered file. 

69 

70 Raises: 

71 ValueError: If ``engine``, ``format``, ``renderer``, or ``formatter`` 

72 are unknown. 

73 graphviz.RequiredArgumentError: If ``formatter`` is given 

74 but ``renderer`` is None. 

75 ValueError: If ``outfile`` is the same file as the source file 

76 unless ``overwite_source=True``. 

77 graphviz.ExecutableNotFound: If the Graphviz ``dot`` executable 

78 is not found. 

79 graphviz.CalledProcessError: If the returncode (exit status) 

80 of the rendering ``dot`` subprocess is non-zero. 

81 RuntimeError: If viewer opening is requested but not supported. 

82 

83 Example: 

84 >>> doctest_mark_exe() 

85 >>> import graphviz 

86 >>> dot = graphviz.Graph(name='spam', directory='doctest-output') 

87 >>> dot.render(format='png').replace('\\', '/') 

88 'doctest-output/spam.gv.png' 

89 >>> dot.render(outfile='spam.svg').replace('\\', '/') 

90 'doctest-output/spam.svg' 

91 

92 Note: 

93 The layout command is started from the directory of ``filepath``, 

94 so that references to external files 

95 (e.g. ``[image=images/camelot.png]``) 

96 can be given as paths relative to the DOT source file. 

97 """ 

98 outfile = _tools.promote_pathlike(outfile) 

99 if outfile is not None: 

100 format = self._get_format(outfile, format=format) 

101 if directory is None: 

102 outfile = pathlib.Path(self.directory, outfile) 

103 

104 args, kwargs = self._get_render_parameters(engine=engine, 

105 format=format, 

106 renderer=renderer, 

107 formatter=formatter, 

108 neato_no_op=neato_no_op, 

109 quiet=quiet, 

110 outfile=outfile, 

111 raise_if_result_exists=raise_if_result_exists, 

112 overwrite_source=overwrite_source, 

113 verify=True) 

114 

115 if outfile is not None and filename is None: 

116 filename = self._get_filepath(outfile) 

117 

118 filepath = self.save(filename, directory=directory, skip_existing=None) 

119 

120 args.append(filepath) 

121 

122 rendered = self._render(*args, **kwargs) 

123 

124 if cleanup: 

125 log.debug('delete %r', filepath) 

126 os.remove(filepath) 

127 

128 if quiet_view or view: 

129 self._view(rendered, format=self._format, quiet=quiet_view) 

130 

131 return rendered 

132 

133 def _view(self, filepath: typing.Union[os.PathLike, str], *, 

134 format: str, quiet: bool) -> None: 

135 """Start the right viewer based on file format and platform.""" 

136 methodnames = [ 

137 f'_view_{format}_{backend.viewing.PLATFORM}', 

138 f'_view_{backend.viewing.PLATFORM}', 

139 ] 

140 for name in methodnames: 

141 view_method = getattr(self, name, None) 

142 if view_method is not None: 

143 break 

144 else: 

145 raise RuntimeError(f'{self.__class__!r} has no built-in viewer' 

146 f' support for {format!r}' 

147 f' on {backend.viewing.PLATFORM!r} platform') 

148 view_method(filepath, quiet=quiet) 

149 

150 @_tools.deprecate_positional_args(supported_number=1, ignore_arg='self') 

151 def view(self, 

152 filename: typing.Union[os.PathLike, str, None] = None, 

153 directory: typing.Union[os.PathLike, str, None] = None, 

154 cleanup: bool = False, 

155 quiet: bool = False, 

156 quiet_view: bool = False) -> str: 

157 """Save the source to file, open the rendered result in a viewer. 

158 

159 Convenience short-cut for running ``.render(view=True)``. 

160 

161 Args: 

162 filename: Filename for saving the source 

163 (defaults to ``name`` + ``'.gv'``). 

164 directory: (Sub)directory for source saving and rendering. 

165 cleanup (bool): Delete the source file after successful rendering. 

166 quiet (bool): Suppress ``stderr`` output from the layout subprocess. 

167 quiet_view (bool): Suppress ``stderr`` output 

168 from the viewer process (ineffective on Windows). 

169 

170 Returns: 

171 The (possibly relative) path of the rendered file. 

172 

173 Raises: 

174 graphviz.ExecutableNotFound: If the Graphviz executable 

175 is not found. 

176 graphviz.CalledProcessError: If the exit status is non-zero. 

177 RuntimeError: If opening the viewer is not supported. 

178 

179 Short-cut method for calling :meth:`.render` with ``view=True``. 

180 

181 Note: 

182 There is no option to wait for the application to close, 

183 and no way to retrieve the application's exit status. 

184 """ 

185 return self.render(filename=filename, directory=directory, view=True, 

186 cleanup=cleanup, quiet=quiet, quiet_view=quiet_view)