docs: def render_dot(self, code, options, format, prefix='graphviz'):
      # type: (nodes.NodeVisitor, unicode, Dict, unicode, unicode) -> Tuple[unicode, unicode]
      """Render graphviz code into a PNG or PDF output file."""
      graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot)
      hashkey = (code + str(options) + str(graphviz_dot) +
                 str(self.builder.config.graphviz_dot_args)).encode('utf-8')
  
      fname = '%s-%s.%s' % (prefix, sha1(hashkey).hexdigest(), format)
      relfn = posixpath.join(self.builder.imgpath, fname)
      outfn = path.join(self.builder.outdir, self.builder.imagedir, fname)
  
      if path.isfile(outfn):
          return relfn, outfn
  
      if (hasattr(self.builder, '_graphviz_warned_dot') and
         self.builder._graphviz_warned_dot.get(graphviz_dot)):
          return None, None
  
      ensuredir(path.dirname(outfn))
  
      # graphviz expects UTF-8 by default
      if isinstance(code, text_type):
          code = code.encode('utf-8')
  
      dot_args = [graphviz_dot]
      dot_args.extend(self.builder.config.graphviz_dot_args)
      dot_args.extend(['-T' + format, '-o' + outfn])
      if format == 'png':
          dot_args.extend(['-Tcmapx', '-o%s.map' % outfn])
      try:
          p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE)
      except OSError as err:
          if err.errno != ENOENT:   # No such file or directory
              raise
          logger.warning(__('dot command %r cannot be run (needed for graphviz '
                            'output), check the graphviz_dot setting'), graphviz_dot)
          if not hasattr(self.builder, '_graphviz_warned_dot'):
              self.builder._graphviz_warned_dot = {}
          self.builder._graphviz_warned_dot[graphviz_dot] = True
          return None, None
      try:
          # Graphviz may close standard input when an error occurs,
          # resulting in a broken pipe on communicate()
          stdout, stderr = p.communicate(code)
      except (OSError, IOError) as err:
          if err.errno not in (EPIPE, EINVAL):
              raise
          # in this case, read the standard output and standard error streams
          # directly, to get the error message(s)
          stdout, stderr = p.stdout.read(), p.stderr.read()
          p.wait()
      if p.returncode != 0:
          raise GraphvizError(__('dot exited with error:\n[stderr]\n%s\n'
                                 '[stdout]\n%s') % (stderr, stdout))
      if not path.isfile(outfn):
          raise GraphvizError(__('dot did not produce an output file:\n[stderr]\n%s\n'
                                 '[stdout]\n%s') % (stderr, stdout))
      return relfn, outfn