示例#1
0
class BokehPlotDirective(Directive):

    has_content = True
    optional_arguments = 2

    option_spec = {
        'source-position': lambda x: choice(x, ('below', 'above', 'none')),
        'linenos': lambda x: True if flag(x) is None else False,
    }

    def run(self):

        env = self.state.document.settings.env

        # filename *or* python code content, but not both
        if self.arguments and self.content:
            raise SphinxError("bokeh-plot:: directive can't have both args and content")

        # need docname not to look like a path
        docname = env.docname.replace("/", "-")

        if self.content:
            log.debug("[bokeh-plot] handling inline example in %r", env.docname)
            path = env.bokeh_plot_auxdir  # code runner just needs any real path
            source = '\n'.join(self.content)
        else:
            log.debug("[bokeh-plot] handling external example in %r: %s", env.docname, self.arguments[0])
            path = self.arguments[0]
            if not path.startswith("/"):
                path = join(env.app.srcdir, path)
            source = open(path).read()

        js_name = "bokeh-plot-%s-external-%s.js" % (uuid4().hex, docname)

        try:
            (script, js, js_path, source) = _process_script(source, path, env, js_name)
        except Exception as e:
            raise RuntimeError("Sphinx bokeh-plot exception: \n\n%s\n\n Failed on:\n\n %s" % (e,source))
        env.bokeh_plot_files[js_name] = (script, js, js_path, source, dirname(env.docname))

        # use the source file name to construct a friendly target_id
        target_id = "%s.%s" % (env.docname, basename(js_path))
        target = nodes.target('', '', ids=[target_id])
        result = [target]

        linenos = self.options.get('linenos', False)
        code = nodes.literal_block(source, source, language="python", linenos=linenos, classes=[])
        set_source_info(self, code)

        source_position = self.options.get('source-position', 'below')

        if source_position == "above": result += [code]

        result += [nodes.raw('', script, format="html")]

        if source_position == "below": result += [code]

        return result
示例#2
0
class BokehPlotDirective(Directive):

    has_content = True
    optional_arguments = 2

    option_spec = {
        'source-position': lambda x: choice(x, ('below', 'above', 'none')),
        'linenos': lambda x: True if flag(x) is None else False,
    }

    def run(self):

        env = self.state.document.settings.env
        app = env.app

        # filename *or* python code content, but not both
        if self.arguments and self.content:
            raise SphinxError(
                "bokeh-plot:: directive can't have both args and content")

        # process inline examples here
        if self.content:
            app.debug("[bokeh-plot] handling inline example in %r",
                      env.docname)
            source = '\n'.join(self.content)
            # need docname not to look like a path
            docname = env.docname.replace("/", "-")
            serialno = env.new_serialno(env.docname)
            js_name = "bokeh-plot-%s-inline-%d.js" % (docname, serialno)
            # the code runner just needs a real path to cd to, this will do
            path = join(env.bokeh_plot_auxdir, js_name)

            (script, js, js_path,
             source) = _process_script(source, path, env.bokeh_plot_auxdir,
                                       js_name)
            env.bokeh_plot_files[js_name] = (script, js, js_path, source)

        # process example files here
        else:
            example_path = self.arguments[0][:-3]  # remove the ".py"

            # if it's an "internal" example, the python parser has already handled it
            if example_path in env.bokeh_plot_files:
                app.debug("[bokeh-plot] handling internal example in %r: %s",
                          env.docname, self.arguments[0])
                (script, js, js_path,
                 source) = env.bokeh_plot_files[example_path]

            # handle examples external to the docs source, e.g. gallery examples
            else:
                app.debug("[bokeh-plot] handling external example in %r: %s",
                          env.docname, self.arguments[0])
                source = open(self.arguments[0]).read()
                source = decode_utf8(source)
                docname = env.docname.replace("/", "-")
                serialno = env.new_serialno(env.docname)
                js_name = "bokeh-plot-%s-external-%d.js" % (docname, serialno)
                (script, js, js_path,
                 source) = _process_script(source, self.arguments[0],
                                           env.bokeh_plot_auxdir, js_name)
                env.bokeh_plot_files[js_name] = (script, js, js_path, source)

        # use the source file name to construct a friendly target_id
        target_id = "%s.%s" % (env.docname, basename(js_path))
        target = nodes.target('', '', ids=[target_id])
        result = [target]

        linenos = self.options.get('linenos', False)
        code = nodes.literal_block(source,
                                   source,
                                   language="python",
                                   linenos=linenos,
                                   classes=[])
        set_source_info(self, code)

        source_position = self.options.get('source-position', 'below')

        if source_position == "above": result += [code]

        result += [nodes.raw('', script, format="html")]

        if source_position == "below": result += [code]

        return result
示例#3
0
class BokehPlotDirective(BokehDirective):

    has_content = True
    optional_arguments = 2

    option_spec = {
        "process-docstring": lambda x: flag(x) is None,
        "source-position": lambda x: choice(x, ("below", "above", "none")),
        "linenos": lambda x: flag(x) is None,
    }

    def run(self):
        source, path = self.process_args_or_content()

        dashed_docname = self.env.docname.replace("/", "-")

        js_filename = f"bokeh-content-{uuid4().hex}-{dashed_docname}.js"

        try:
            (script_tag, js_path, source, docstring,
             height_hint) = self.process_source(source, path, js_filename)
        except Exception as e:
            raise SphinxError(f"Error generating {js_filename}: \n\n{e}")
        self.env.bokeh_plot_files.add((js_path, dirname(self.env.docname)))

        # use the source file name to construct a friendly target_id
        target_id = f"{dashed_docname}.{basename(js_path)}"
        target = [nodes.target("", "", ids=[target_id])]

        process_docstring = self.options.get("process-docstring", False)
        intro = self.parse(
            docstring,
            '<bokeh-content>') if docstring and process_docstring else []

        above, below = self.process_code_block(source, docstring)

        autoload = [
            autoload_script(height_hint=height_hint, script_tag=script_tag)
        ]

        return target + intro + above + autoload + below

    def process_code_block(self, source: str, docstring: str | None):
        source_position = self.options.get("source-position", "below")

        if source_position == "none":
            return [], []

        source = _remove_module_docstring(source, docstring).strip()

        linenos = self.options.get("linenos", False)
        code_block = nodes.literal_block(source,
                                         source,
                                         language="python",
                                         linenos=linenos,
                                         classes=[])
        set_source_info(self, code_block)

        if source_position == "above":
            return [code_block], []

        if source_position == "below":
            return [], [code_block]

    def process_args_or_content(self):
        # filename *or* python code content, but not both
        if self.arguments and self.content:
            raise SphinxError(
                "bokeh-plot:: directive can't have both args and content")

        if self.content:
            log.debug(
                f"[bokeh-plot] handling inline content in {self.env.docname!r}"
            )
            path = self.env.bokeh_plot_auxdir  # code runner just needs any real path
            return "\n".join(self.content), path

        path = self.arguments[0]
        log.debug(
            f"[bokeh-plot] handling external content in {self.env.docname!r}: {path}"
        )
        if not path.startswith("/"):
            path = join(self.env.app.srcdir, path)
        try:
            with open(path) as f:
                return f.read(), path
        except Exception as e:
            raise SphinxError(
                f"bokeh-plot:: error reading source for {self.env.docname!r}: {e!r}"
            )

    def process_source(self, source, path, js_filename):
        Model._clear_extensions()

        root, docstring = _evaluate_source(source, path, self.env)

        height_hint = root._sphinx_height_hint()

        js_path = join(self.env.bokeh_plot_auxdir, js_filename)
        js, script_tag = autoload_static(root, RESOURCES, js_filename)

        with open(js_path, "w") as f:
            f.write(js)

        return (script_tag, js_path, source, docstring, height_hint)
示例#4
0
class BokehPlotDirective(Directive):

    has_content = True
    optional_arguments = 2

    option_spec = {
        "source-position": lambda x: choice(x, ("below", "above", "none")),
        "linenos": lambda x: True if flag(x) is None else False,
    }

    def run(self):

        env = self.state.document.settings.env

        # filename *or* python code content, but not both
        if self.arguments and self.content:
            raise SphinxError(
                "bokeh-plot:: directive can't have both args and content")

        # need docname not to look like a path
        docname = env.docname.replace("/", "-")

        if self.content:
            log.debug(
                f"[bokeh-plot] handling inline example in {env.docname!r}")
            path = env.bokeh_plot_auxdir  # code runner just needs any real path
            source = "\n".join(self.content)
        else:
            try:
                log.debug(
                    f"[bokeh-plot] handling external example in {env.docname!r}: {self.arguments[0]}"
                )
                path = self.arguments[0]
                if not path.startswith("/"):
                    path = join(env.app.srcdir, path)
                source = open(path).read()
            except Exception as e:
                raise SphinxError(f"{env.docname}: {e!r}")

        js_name = f"bokeh-plot-{uuid4().hex}-external-{docname}.js"

        try:
            (script, js, js_path,
             source) = _process_script(source, path, env, js_name)
        except Exception as e:
            raise RuntimeError(
                f"Sphinx bokeh-plot exception: \n\n{e}\n\n Failed on:\n\n {source}"
            )
        env.bokeh_plot_files[js_name] = (script, js, js_path, source,
                                         dirname(env.docname))

        # use the source file name to construct a friendly target_id
        target_id = f"{env.docname}.{basename(js_path)}"
        target = nodes.target("", "", ids=[target_id])
        result = [target]

        linenos = self.options.get("linenos", False)
        code = nodes.literal_block(source,
                                   source,
                                   language="python",
                                   linenos=linenos,
                                   classes=[])
        set_source_info(self, code)

        source_position = self.options.get("source-position", "below")

        if source_position == "above":
            result += [code]

        result += [nodes.raw("", script, format="html")]

        if source_position == "below":
            result += [code]

        return result
示例#5
0
class BokehPlotDirective(BokehDirective):

    has_content = True
    optional_arguments = 2

    option_spec = {
        "process-docstring": lambda x: flag(x) is None,
        "source-position": lambda x: choice(x, ("below", "above", "none")),
        "linenos": lambda x: flag(x) is None,
    }

    def run(self):
        source, path = self.process_args_or_content()

        dashed_docname = self.env.docname.replace("/", "-")

        js_filename = f"bokeh-content-{uuid4().hex}-{dashed_docname}.js"

        try:
            (script_tag, js_path, source, docstring,
             height_hint) = self.process_source(source, path, js_filename)
        except Exception as e:
            raise SphinxError(f"Error generating {js_filename}: \n\n{e}")
        self.env.bokeh_plot_files.add((js_path, dirname(self.env.docname)))

        # use the source file name to construct a friendly target_id
        target_id = f"{dashed_docname}.{basename(js_path)}"
        target = [nodes.target("", "", ids=[target_id])]

        self.process_sampledata(source)

        process_docstring = self.options.get("process-docstring", False)
        intro = self.parse(
            docstring,
            '<bokeh-content>') if docstring and process_docstring else []

        above, below = self.process_code_block(source, docstring)

        autoload = [
            autoload_script(height_hint=height_hint, script_tag=script_tag)
        ]

        return target + intro + above + autoload + below

    def process_code_block(self, source: str, docstring: str | None):
        source_position = self.options.get("source-position", "below")

        if source_position == "none":
            return [], []

        source = _remove_module_docstring(source, docstring).strip()

        linenos = self.options.get("linenos", False)
        code_block = nodes.literal_block(source,
                                         source,
                                         language="python",
                                         linenos=linenos,
                                         classes=[])
        set_source_info(self, code_block)

        if source_position == "above":
            return [code_block], []

        if source_position == "below":
            return [], [code_block]

    def process_args_or_content(self):
        # filename *or* python code content, but not both
        if self.arguments and self.content:
            raise SphinxError(
                "bokeh-plot:: directive can't have both args and content")

        if self.content:
            log.debug(
                f"[bokeh-plot] handling inline content in {self.env.docname!r}"
            )
            path = self.env.bokeh_plot_auxdir  # code runner just needs any real path
            return "\n".join(self.content), path

        path = self.arguments[0]
        log.debug(
            f"[bokeh-plot] handling external content in {self.env.docname!r}: {path}"
        )
        if not path.startswith("/"):
            path = join(self.env.app.srcdir, path)
        try:
            with open(path) as f:
                return f.read(), path
        except Exception as e:
            raise SphinxError(
                f"bokeh-plot:: error reading {path!r} for {self.env.docname!r}: {e!r}"
            )

    def process_source(self, source, path, js_filename):
        Model._clear_extensions()

        root, docstring = _evaluate_source(source, path, self.env)

        height_hint = root._sphinx_height_hint()

        js_path = join(self.env.bokeh_plot_auxdir, js_filename)
        js, script_tag = autoload_static(root, RESOURCES, js_filename)

        with open(js_path, "w") as f:
            f.write(js)

        return (script_tag, js_path, source, docstring, height_hint)

    def process_sampledata(self, source):

        if not hasattr(self.env, 'solved_sampledata'):
            self.env.solved_sampledata = []

        file, lineno = self.get_source_info()
        # collect links to all standalone examples

        if '/docs/examples/' in file and not file in self.env.solved_sampledata:
            self.env.solved_sampledata.append(file)
            if not hasattr(self.env, 'all_sampledata_xrefs'):
                self.env.all_sampledata_xrefs = []
            if not hasattr(self.env, 'all_gallery_overview'):
                self.env.all_gallery_overview = []

            self.env.all_gallery_overview.append({
                'docname': self.env.docname,
            })

            regex = "(:|bokeh\.)sampledata(:|\.| import )\s*(\w+(\,\s*\w+)*)"
            matches = re.findall(regex, source)
            if matches:
                keywords = set()
                for m in matches:
                    keywords.update(m[2].replace(" ", "").split(','))
                for keyword in keywords:
                    self.env.all_sampledata_xrefs.append({
                        'docname': self.env.docname,
                        'keyword': keyword,
                    })
示例#6
0
def du_flag(node):
    " No argument allowed.  "
    return directives.flag(du_astext(node))
示例#7
0
 def test_flag(self):
     # Raise error when there is an argument:
     self.assertEqual(None, directives.flag(''))
     self.assertRaises(ValueError, directives.flag, 'alles')