def run()

in _ext/sphinx_plotly_directive.py [0:0]


def run(arguments, content, options, state_machine, state, lineno):
    document = state_machine.document
    config = document.settings.env.config
    nofigs = "nofigs" in options

    formats = get_plot_formats(config)
    default_fmt = formats[0][0]

    options_copy = copy.deepcopy(options)

    options.setdefault("include-source", config.plotly_include_source)
    options.setdefault("iframe-width", config.plotly_iframe_width)
    options.setdefault("iframe-height", config.plotly_iframe_height)
    keep_context = "context" in options
    context_opt = None if not keep_context else options["context"]

    rst_file = document.attributes["source"]
    rst_dir = os.path.dirname(rst_file)

    if len(arguments):
        if not config.plotly_basedir:
            source_file_name = os.path.join(setup.app.builder.srcdir, directives.uri(arguments[0]))
        else:
            source_file_name = os.path.join(
                setup.confdir, config.plotly_basedir, directives.uri(arguments[0])
            )

        # If there is content, it will be passed as a caption.
        caption = "\n".join(content)

        # Enforce unambiguous use of captions.
        if "caption" in options:
            if caption:
                raise ValueError(
                    "Caption specified in both content and options." " Please remove ambiguity."
                )
            # Use caption option
            caption = options["caption"]

        # If the optional function name is provided, use it
        if len(arguments) == 2:
            function_name = arguments[1]
        else:
            function_name = None

        code = Path(source_file_name).read_text(encoding="utf-8")
        output_base = os.path.basename(source_file_name)
    else:
        source_file_name = rst_file
        code = textwrap.dedent("\n".join(map(str, content)))
        counter = document.attributes.get("_plot_counter", 0) + 1
        document.attributes["_plot_counter"] = counter
        base, ext = os.path.splitext(os.path.basename(source_file_name))
        output_base = "%s-%d.py" % (base, counter)
        function_name = None
        caption = options.get("caption", "")

    base, source_ext = os.path.splitext(output_base)
    if source_ext in (".py", ".rst", ".txt"):
        output_base = base
    else:
        source_ext = ""

    # ensure that LaTeX includegraphics doesn't choke in foo.bar.pdf filenames
    output_base = output_base.replace(".", "-")

    # is it in doctest format?
    is_doctest = contains_doctest(code)
    if "format" in options:
        if options["format"] == "python":
            is_doctest = False
        else:
            is_doctest = True

    # determine output directory name fragment
    source_rel_name = relpath(source_file_name, setup.confdir)
    source_rel_dir = os.path.dirname(source_rel_name)
    while source_rel_dir.startswith(os.path.sep):
        source_rel_dir = source_rel_dir[1:]

    # build_dir: where to place output files (temporarily)
    build_dir = os.path.join(
        os.path.dirname(setup.app.doctreedir), "plot_directive", source_rel_dir
    )
    # get rid of .. in paths, also changes pathsep
    # see note in Python docs for warning about symbolic links on Windows.
    # need to compare source and dest paths at end
    build_dir = os.path.normpath(build_dir)

    if not os.path.exists(build_dir):
        os.makedirs(build_dir)

    # output_dir: final location in the builder's directory
    dest_dir = os.path.abspath(os.path.join(setup.app.builder.outdir, source_rel_dir))
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)  # no problem here for me, but just use built-ins

    # how to link to files from the RST file
    dest_dir_link = os.path.join(relpath(setup.confdir, rst_dir), source_rel_dir).replace(
        os.path.sep, "/"
    )
    try:
        build_dir_link = relpath(build_dir, rst_dir).replace(os.path.sep, "/")
    except ValueError:
        # on Windows, relpath raises ValueError when path and start are on
        # different mounts/drives
        build_dir_link = build_dir
    source_link = dest_dir_link + "/" + output_base + source_ext

    # make figures
    try:
        results = render_figures(
            code,
            source_file_name,
            build_dir,
            output_base,
            keep_context,
            function_name,
            config,
            context_reset=context_opt == "reset",
            close_figs=context_opt == "close-figs",
            fig_vars=options.get("fig-vars"),
        )
        errors = []
    except PlotError as err:
        reporter = state.memo.reporter
        sm = reporter.system_message(
            2,
            "Exception occurred in plotting {}\n from {}:\n{}".format(
                output_base, source_file_name, err
            ),
            line=lineno,
        )
        results = [(code, [])]
        errors = [sm]

    # Properly indent the caption
    caption = "\n".join("      " + line.strip() for line in caption.split("\n"))

    # generate output restructuredtext
    total_lines = []
    for j, (code_piece, figures) in enumerate(results):
        if options["include-source"]:
            if is_doctest:
                lines = ["", *code_piece.splitlines()]
            else:
                lines = [
                    ".. code-block:: python",
                    "",
                    *textwrap.indent(code_piece, "    ").splitlines(),
                ]
            source_code = "\n".join(lines)
        else:
            source_code = ""

        if nofigs:
            figures = []

        opts = [
            ":%s: %s" % (key, val)
            for key, val in options.items()
            if key in ("alt", "height", "width", "scale", "align", "class")
        ]

        # Not-None src_link signals the need for a source link in the generated
        # html
        if j == 0 and config.plotly_html_show_source_link:
            src_link = source_link
        else:
            src_link = None

        if config.plotly_include_directive_source:
            directive_source = create_directive_block("plotly", arguments, options_copy, content)
            directive_source = create_code_block(directive_source, "text")
        else:
            directive_source = ""

        result = jinja2.Template(config.plotly_template or TEMPLATE).render(
            directive_source=directive_source,
            default_fmt=default_fmt,
            dest_dir=dest_dir_link,
            build_dir=build_dir_link,
            source_link=src_link,
            multi_figure=len(figures) > 1,
            options=opts,
            figures=figures,
            iframe_width=options["iframe-width"],
            iframe_height=options["iframe-height"],
            source_code=source_code,
            html_show_formats=config.plotly_html_show_formats and len(figures),
            caption=caption,
        )

        total_lines.extend(result.split("\n"))
        total_lines.extend("\n")

    if total_lines:
        state_machine.insert_input(total_lines, source=source_file_name)

    # copy image files to builder's output directory, if necessary
    Path(dest_dir).mkdir(parents=True, exist_ok=True)

    for code_piece, figures in results:
        for fig in figures:
            for fn in fig.filenames():
                destfig = os.path.join(dest_dir, os.path.basename(fn))
                if fn != destfig:
                    shutil.copyfile(fn, destfig)

    # copy script (if necessary)
    Path(dest_dir, output_base + source_ext).write_text(
        unescape_doctest(code) if source_file_name == rst_file else code,
        encoding="utf-8",
    )

    return errors