jupyter_sphinx-0.3.2/ 0000755 0001751 0000164 00000000000 13732162726 015421 5 ustar runner docker 0000000 0000000 jupyter_sphinx-0.3.2/LICENSE 0000644 0001751 0000164 00000003055 13732162721 016424 0 ustar runner docker 0000000 0000000 Copyright (c) 2015-2016, Brian E. Granger and Jake Vanderplas
Copyright (c) 2016-2019, Project Jupyter Contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jupyter_sphinx-0.3.2/MANIFEST.in 0000644 0001751 0000164 00000000074 13732162721 017153 0 ustar runner docker 0000000 0000000 include LICENSE
recursive-include jupyter_sphinx/thebelab/*
jupyter_sphinx-0.3.2/PKG-INFO 0000644 0001751 0000164 00000002745 13732162726 016526 0 ustar runner docker 0000000 0000000 Metadata-Version: 2.1
Name: jupyter_sphinx
Version: 0.3.2
Summary: Jupyter Sphinx Extensions
Home-page: https://github.com/jupyter/jupyter-sphinx/
Author: Jupyter Development Team
Author-email: jupyter@googlegroups.com
License: BSD
Project-URL: Bug Tracker, https://github.com/jupyter/jupyter-sphinx/issues/
Project-URL: Documentation, https://jupyter-sphinx.readthedocs.io
Project-URL: Source Code, https://github.com/jupyter/jupyter-sphinx/
Description: # Jupyter Sphinx Extensions
``jupyter-sphinx`` enables running code embedded in Sphinx documentation and
embedding output of that code into the resulting document. It has support
for rich output such as images and even Jupyter interactive widgets.
## Installation
With pip:
```bash
pip install jupyter_sphinx
```
with conda:
```bash
conda install jupyter_sphinx -c conda-forge
```
## Usage
You can check out the documentation on https://jupyter-sphinx.readthedocs.io for up to date
usage information and examples.
## License
We use a shared copyright model that enables all contributors to maintain the
copyright on their contributions.
All code is licensed under the terms of the revised BSD license.
Platform: UNKNOWN
Requires-Python: >= 3.6
Description-Content-Type: text/markdown
jupyter_sphinx-0.3.2/README.md 0000644 0001751 0000164 00000001312 13732162721 016670 0 ustar runner docker 0000000 0000000 # Jupyter Sphinx Extensions
``jupyter-sphinx`` enables running code embedded in Sphinx documentation and
embedding output of that code into the resulting document. It has support
for rich output such as images and even Jupyter interactive widgets.
## Installation
With pip:
```bash
pip install jupyter_sphinx
```
with conda:
```bash
conda install jupyter_sphinx -c conda-forge
```
## Usage
You can check out the documentation on https://jupyter-sphinx.readthedocs.io for up to date
usage information and examples.
## License
We use a shared copyright model that enables all contributors to maintain the
copyright on their contributions.
All code is licensed under the terms of the revised BSD license.
jupyter_sphinx-0.3.2/jupyter_sphinx/ 0000755 0001751 0000164 00000000000 13732162726 020514 5 ustar runner docker 0000000 0000000 jupyter_sphinx-0.3.2/jupyter_sphinx/__init__.py 0000644 0001751 0000164 00000021002 13732162721 022613 0 ustar runner docker 0000000 0000000 """Simple sphinx extension that executes code in jupyter and inserts output."""
from ._version import version_info, __version__
from sphinx.util import logging
import docutils
import ipywidgets
import os
from sphinx.util.fileutil import copy_asset
from sphinx.errors import ExtensionError
from IPython.lib.lexers import IPythonTracebackLexer, IPython3Lexer
from pathlib import Path
from .ast import (
JupyterCell,
JupyterCellNode,
CellInputNode,
CellOutputNode,
CellOutputBundleNode,
JupyterKernelNode,
JupyterWidgetViewNode,
JupyterWidgetStateNode,
WIDGET_VIEW_MIMETYPE,
JupyterDownloadRole,
CellOutputsToNodes,
)
from .execute import JupyterKernel, ExecuteJupyterCells
from .thebelab import ThebeButton, ThebeButtonNode, ThebeOutputNode, ThebeSourceNode
REQUIRE_URL_DEFAULT = (
"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"
)
THEBELAB_URL_DEFAULT = "https://unpkg.com/thebelab@^0.4.0"
logger = logging.getLogger(__name__)
##############################################################################
# Constants and functions we'll use later
# Used for nodes that do not need to be rendered
def skip(self, node):
raise docutils.nodes.SkipNode
# Used for nodes that should be gone by rendering time (OutputMimeBundleNode)
def halt(self, node):
raise ExtensionError(
(
"Rendering encountered a node type that should "
"have been removed before rendering: %s" % type(node)
)
)
# Renders the children of a container
render_container = (
lambda self, node: self.visit_container(node),
lambda self, node: self.depart_container(node),
)
# Used to render the container and its children as HTML
def visit_container_html(self, node):
self.body.append(node.visit_html())
self.visit_container(node)
def depart_container_html(self, node):
self.depart_container(node)
self.body.append(node.depart_html())
# Used to render an element node as HTML
def visit_element_html(self, node):
self.body.append(node.html())
raise docutils.nodes.SkipNode
# Used to render the ThebeSourceNode conditionally for non-HTML builders
def visit_thebe_source(self, node):
if node["hide_code"]:
raise docutils.nodes.SkipNode
else:
self.visit_container(node)
render_thebe_source = (
visit_thebe_source,
lambda self, node: self.depart_container(node),
)
##############################################################################
# Sphinx callback functions
def builder_inited(app):
"""
2 cases
case 1: ipywidgets 7, with require
case 2: ipywidgets 7, no require
"""
require_url = app.config.jupyter_sphinx_require_url
if require_url:
app.add_js_file(require_url)
embed_url = (
app.config.jupyter_sphinx_embed_url
or ipywidgets.embed.DEFAULT_EMBED_REQUIREJS_URL
)
else:
embed_url = (
app.config.jupyter_sphinx_embed_url
or ipywidgets.embed.DEFAULT_EMBED_SCRIPT_URL
)
if embed_url:
app.add_js_file(embed_url)
def build_finished(app, env):
if app.builder.format != "html":
return
module_dir = Path(__file__).parent
outdir = Path(app.outdir)
# Copy stylesheet
src = module_dir / "css"
dst = outdir / "_static"
copy_asset(src, dst)
thebe_config = app.config.jupyter_sphinx_thebelab_config
if not thebe_config:
return
# Copy all thebelab related assets
src = module_dir / "thebelab"
copy_asset(src, dst)
##############################################################################
# Main setup
def setup(app):
"""A temporary setup function so that we can use it here and in execute.
This should be removed and converted into `setup` after a deprecation
cycle.
"""
# Configuration
app.add_config_value(
"jupyter_execute_kwargs",
dict(timeout=-1, allow_errors=True, store_widget_state=True),
"env",
)
app.add_config_value("jupyter_execute_default_kernel", "python3", "env")
app.add_config_value(
"jupyter_execute_data_priority",
[
WIDGET_VIEW_MIMETYPE,
"application/javascript",
"text/html",
"image/svg+xml",
"image/png",
"image/jpeg",
"text/latex",
"text/plain",
],
"env",
)
# ipywidgets config
app.add_config_value("jupyter_sphinx_require_url", REQUIRE_URL_DEFAULT, "html")
app.add_config_value("jupyter_sphinx_embed_url", None, "html")
# thebelab config, can be either a filename or a dict
app.add_config_value("jupyter_sphinx_thebelab_config", None, "html")
app.add_config_value("jupyter_sphinx_thebelab_url", THEBELAB_URL_DEFAULT, "html")
# linenos config
app.add_config_value("jupyter_sphinx_linenos", False, "env")
app.add_config_value("jupyter_sphinx_continue_linenos", False, "env")
# JupyterKernelNode is just a doctree marker for the
# ExecuteJupyterCells transform, so we don't actually render it.
app.add_node(
JupyterKernelNode,
html=(skip, None),
latex=(skip, None),
textinfo=(skip, None),
text=(skip, None),
man=(skip, None),
)
# Register our container nodes, these should behave just like a regular container
for node in [JupyterCellNode, CellInputNode, CellOutputNode]:
app.add_node(
node,
override=True,
html=(render_container),
latex=(render_container),
textinfo=(render_container),
text=(render_container),
man=(render_container),
)
# Register the output bundle node.
# No translators should touch this node because we'll replace it in a post-transform
app.add_node(
CellOutputBundleNode,
override=True,
html=(halt, None),
latex=(halt, None),
textinfo=(halt, None),
text=(halt, None),
man=(halt, None),
)
# JupyterWidgetViewNode holds widget view JSON,
# but is only rendered properly in HTML documents.
app.add_node(
JupyterWidgetViewNode,
html=(visit_element_html, None),
latex=(skip, None),
textinfo=(skip, None),
text=(skip, None),
man=(skip, None),
)
# JupyterWidgetStateNode holds the widget state JSON,
# but is only rendered in HTML documents.
app.add_node(
JupyterWidgetStateNode,
html=(visit_element_html, None),
latex=(skip, None),
textinfo=(skip, None),
text=(skip, None),
man=(skip, None),
)
# ThebeSourceNode holds the source code and is rendered if
# hide-code is not specified. For HTML it is always rendered,
# but hidden using the stylesheet
app.add_node(
ThebeSourceNode,
html=(visit_container_html, depart_container_html),
latex=render_thebe_source,
textinfo=render_thebe_source,
text=render_thebe_source,
man=render_thebe_source,
)
# ThebeOutputNode holds the output of the Jupyter cells
# and is rendered if hide-output is not specified.
app.add_node(
ThebeOutputNode,
html=(visit_container_html, depart_container_html),
latex=render_container,
textinfo=render_container,
text=render_container,
man=render_container,
)
# ThebeButtonNode is the button that activates thebelab
# and is only rendered for the HTML builder
app.add_node(
ThebeButtonNode,
html=(visit_element_html, None),
latex=(skip, None),
textinfo=(skip, None),
text=(skip, None),
man=(skip, None),
)
app.add_directive("jupyter-execute", JupyterCell)
app.add_directive("jupyter-kernel", JupyterKernel)
app.add_directive("thebe-button", ThebeButton)
app.add_role("jupyter-download:notebook", JupyterDownloadRole())
app.add_role("jupyter-download:nb", JupyterDownloadRole())
app.add_role("jupyter-download:script", JupyterDownloadRole())
app.add_transform(ExecuteJupyterCells)
app.add_transform(CellOutputsToNodes)
# For syntax highlighting
app.add_lexer("ipythontb", IPythonTracebackLexer)
app.add_lexer("ipython", IPython3Lexer)
app.connect("builder-inited", builder_inited)
app.connect("build-finished", build_finished)
# add jupyter-sphinx and thebelab js and css
app.add_css_file("jupyter-sphinx.css")
app.add_js_file("thebelab-helper.js")
app.add_css_file("thebelab.css")
return {"version": __version__, "parallel_read_safe": True}
jupyter_sphinx-0.3.2/jupyter_sphinx/_version.py 0000644 0001751 0000164 00000000465 13732162721 022712 0 ustar runner docker 0000000 0000000 version_info = (0, 3, 2, "final")
_specifier_ = {"alpha": "a", "beta": "b", "candidate": "rc", "final": ""}
__version__ = "%s.%s.%s%s" % (
version_info[0],
version_info[1],
version_info[2],
""
if version_info[3] == "final"
else _specifier_[version_info[3]] + str(version_info[4]),
)
jupyter_sphinx-0.3.2/jupyter_sphinx/ast.py 0000644 0001751 0000164 00000041615 13732162721 021657 0 ustar runner docker 0000000 0000000 """Manipulating the Sphinx AST with Jupyter objects"""
import os
import json
from pathlib import Path
import docutils
from docutils.parsers.rst import Directive, directives
from docutils.nodes import math_block, image, literal
from sphinx.util import parselinenos
from sphinx.util.docutils import ReferenceRole
from sphinx.addnodes import download_reference
from sphinx.transforms import SphinxTransform
from sphinx.environment.collectors.asset import ImageCollector
import ipywidgets.embed
import nbconvert
from .utils import strip_latex_delimiters, sphinx_abs_dir
from .thebelab import ThebeSourceNode, ThebeOutputNode
WIDGET_VIEW_MIMETYPE = "application/vnd.jupyter.widget-view+json"
WIDGET_STATE_MIMETYPE = "application/vnd.jupyter.widget-state+json"
def csv_option(s):
return [p.strip() for p in s.split(",")] if s else []
class JupyterCell(Directive):
"""Define a code cell to be later executed in a Jupyter kernel.
The content of the directive is the code to execute. Code is not
executed when the directive is parsed, but later during a doctree
transformation.
Arguments
---------
filename : str (optional)
If provided, a path to a file containing code.
Options
-------
hide-code : bool
If provided, the code will not be displayed in the output.
hide-output : bool
If provided, the cell output will not be displayed in the output.
code-below : bool
If provided, the code will be shown below the cell output.
linenos : bool
If provided, the code will be shown with line numbering.
lineno-start: nonnegative int
If provided, the code will be show with line numbering beginning from
specified line.
emphasize-lines : comma separated list of line numbers
If provided, the specified lines will be highlighted.
raises : comma separated list of exception types
If provided, a comma-separated list of exception type names that
the cell may raise. If one of the listed execption types is raised
then the traceback is printed in place of the cell output. If an
exception of another type is raised then we raise a RuntimeError
when executing.
Content
-------
code : str
A code cell.
"""
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
has_content = True
option_spec = {
"hide-code": directives.flag,
"hide-output": directives.flag,
"code-below": directives.flag,
"linenos": directives.flag,
"lineno-start": directives.nonnegative_int,
"emphasize-lines": directives.unchanged_required,
"raises": csv_option,
"stderr": directives.flag,
}
def run(self):
# This only works lazily because the logger is inited by Sphinx
from . import logger
location = self.state_machine.get_source_and_line(self.lineno)
if self.arguments:
# As per 'sphinx.directives.code.LiteralInclude'
env = self.state.document.settings.env
rel_filename, filename = env.relfn2path(self.arguments[0])
env.note_dependency(rel_filename)
if self.content:
logger.warning(
'Ignoring inline code in Jupyter cell included from "{}"'.format(
rel_filename
),
location=location,
)
try:
with Path(filename).open() as f:
content = [line.rstrip() for line in f.readlines()]
except (IOError, OSError):
raise IOError("File {} not found or reading it failed".format(filename))
else:
self.assert_has_content()
content = self.content
# The code fragment is taken from CodeBlock directive almost unchanged:
# https://github.com/sphinx-doc/sphinx/blob/0319faf8f1503453b6ce19020819a8cf44e39f13/sphinx/directives/code.py#L134-L148
emphasize_linespec = self.options.get("emphasize-lines")
if emphasize_linespec:
try:
nlines = len(content)
hl_lines = parselinenos(emphasize_linespec, nlines)
if any(i >= nlines for i in hl_lines):
logger.warning(
"Line number spec is out of range(1-{}): {}".format(
nlines, emphasize_linespec
),
location=location,
)
hl_lines = [i + 1 for i in hl_lines if i < nlines]
except ValueError as err:
return [self.state.document.reporter.warning(err, line=self.lineno)]
else:
hl_lines = []
# A top-level placeholder for our cell
cell_node = JupyterCellNode(
hide_code=("hide-code" in self.options),
hide_output=("hide-output" in self.options),
code_below=("code-below" in self.options),
emphasize_lines=hl_lines,
raises=self.options.get("raises"),
stderr=("stderr" in self.options),
classes=["jupyter_cell"],
)
# Add the input section of the cell, we'll add output at execution time
cell_input = CellInputNode(classes=["cell_input"])
cell_input += docutils.nodes.literal_block(
text="\n".join(content),
linenos=("linenos" in self.options),
linenostart=(self.options.get("lineno-start")),
)
cell_node += cell_input
return [cell_node]
class JupyterCellNode(docutils.nodes.container):
"""Inserted into doctree whever a JupyterCell directive is encountered.
Contains code that will be executed in a Jupyter kernel at a later
doctree-transformation step.
"""
class CellInputNode(docutils.nodes.container):
"""Represent an input cell in the Sphinx AST."""
def __init__(self, rawsource="", *children, **attributes):
super().__init__("", **attributes)
class CellOutputNode(docutils.nodes.container):
"""Represent an output cell in the Sphinx AST."""
def __init__(self, rawsource="", *children, **attributes):
super().__init__("", **attributes)
class CellOutputBundleNode(docutils.nodes.container):
"""Represent a MimeBundle in the Sphinx AST, to be transformed later."""
def __init__(self, outputs, rawsource="", *children, **attributes):
self.outputs = outputs
super().__init__("", **attributes)
class JupyterKernelNode(docutils.nodes.Element):
"""Inserted into doctree whenever a JupyterKernel directive is encountered.
Used as a marker to signal that the following JupyterCellNodes (until the
next, if any, JupyterKernelNode) should be executed in a separate kernel.
"""
class JupyterWidgetViewNode(docutils.nodes.Element):
"""Inserted into doctree whenever a Jupyter cell produces a widget as output.
Contains a unique ID for this widget; enough information for the widget
embedding javascript to render it, given the widget state. For non-HTML
outputs this doctree node is rendered generically.
"""
def __init__(self, rawsource="", *children, **attributes):
super().__init__("", view_spec=attributes["view_spec"])
def html(self):
return ipywidgets.embed.widget_view_template.format(
view_spec=json.dumps(self["view_spec"])
)
class JupyterWidgetStateNode(docutils.nodes.Element):
"""Appended to doctree if any Jupyter cell produced a widget as output.
Contains the state needed to render a collection of Jupyter widgets.
Per doctree there is 1 JupyterWidgetStateNode per kernel that produced
Jupyter widgets when running. This is fine as (presently) the
'html-manager' Javascript library, which embeds widgets, loads the state
from all script tags on the page of the correct mimetype.
"""
def __init__(self, rawsource="", *children, **attributes):
super().__init__("", state=attributes["state"])
def html(self):
# TODO: render into a separate file if 'html-manager' starts fully
# parsing script tags, and not just grabbing their innerHTML
# https://github.com/jupyter-widgets/ipywidgets/blob/master/packages/html-manager/src/libembed.ts#L36
return ipywidgets.embed.snippet_template.format(
load="", widget_views="", json_data=json.dumps(self["state"])
)
def cell_output_to_nodes(outputs, data_priority, write_stderr, out_dir,
thebe_config, inline=False):
"""Convert a jupyter cell with outputs and filenames to doctree nodes.
Parameters
----------
outputs : a list of outputs from a Jupyter cell
data_priority : list of mime types
Which media types to prioritize.
write_stderr : bool
If True include stderr in cell output
out_dir : string
Sphinx "absolute path" to the output folder, so it is a relative path
to the source folder prefixed with ``/``.
thebe_config: dict
Thebelab configuration object or None
inline: False
Whether the nodes will be placed in-line with the text.
Returns
-------
to_add : list of docutils nodes
Each output, converted into a docutils node.
"""
# If we're in `inline` mode, ensure that we don't add block-level nodes
if inline:
literal_node = docutils.nodes.literal
math_node = docutils.nodes.math
else:
literal_node = docutils.nodes.literal_block
math_node = math_block
to_add = []
for output in outputs:
output_type = output["output_type"]
if output_type == "stream":
if output["name"] == "stderr":
if not write_stderr:
continue
else:
# Output a container with an unhighlighted literal block for
# `stderr` messages.
#
# Adds a "stderr" class that can be customized by the user for both
# the container and the literal_block.
#
# Not setting "rawsource" disables Pygment hightlighting, which
# would otherwise add a
.
literal = literal_node(
text=output["text"],
rawsource="", # disables Pygment highlighting
language="none",
classes=["stderr"],
)
if inline:
# In this case, we don't wrap the text in containers
to_add.append(literal)
else:
container = docutils.nodes.container(classes=["stderr"])
container.append(literal)
to_add.append(container)
else:
to_add.append(
literal_node(
text=output["text"],
rawsource=output["text"],
language="none",
classes=["output", "stream"],
)
)
elif output_type == "error":
traceback = "\n".join(output["traceback"])
text = nbconvert.filters.strip_ansi(traceback)
to_add.append(
literal_node(
text=text,
rawsource=text,
language="ipythontb",
classes=["output", "traceback"],
)
)
elif output_type in ("display_data", "execute_result"):
try:
# First mime_type by priority that occurs in output.
mime_type = next(x for x in data_priority if x in output["data"])
except StopIteration:
continue
data = output["data"][mime_type]
if mime_type.startswith("image"):
file_path = Path(output.metadata["filenames"][mime_type])
out_dir = Path(out_dir)
# Sphinx treats absolute paths as being rooted at the source
# directory, so make a relative path, which Sphinx treats
# as being relative to the current working directory.
filename = file_path.name
if out_dir in file_path.parents:
out_dir = file_path.parent
uri = (out_dir / filename).as_posix()
to_add.append(docutils.nodes.image(uri=uri))
elif mime_type == "text/html":
to_add.append(
docutils.nodes.raw(
text=data, format="html", classes=["output", "text_html"]
)
)
elif mime_type == "text/latex":
to_add.append(
math_node(
text=strip_latex_delimiters(data),
nowrap=False,
number=None,
classes=["output", "text_latex"],
)
)
elif mime_type == "text/plain":
to_add.append(
literal_node(
text=data,
rawsource=data,
language="none",
classes=["output", "text_plain"],
)
)
elif mime_type == "application/javascript":
to_add.append(
docutils.nodes.raw(
text=''.format(
mime_type=mime_type, data=data
),
format="html",
)
)
elif mime_type == WIDGET_VIEW_MIMETYPE:
to_add.append(JupyterWidgetViewNode(view_spec=data))
return to_add
def attach_outputs(output_nodes, node, thebe_config):
if not node.attributes["hide_code"]: # only add css if code is displayed
classes = node.attributes.get("classes", [])
classes += ["jupyter_container"]
(input_node,) = node.traverse(CellInputNode)
(outputbundle_node,) = node.traverse(CellOutputBundleNode)
output_node = CellOutputNode(classes=["cell_output"])
if thebe_config:
# Move the source from the input node into the thebe_source node
source = input_node.children.pop(0)
thebe_source = ThebeSourceNode(
hide_code=node.attributes["hide_code"],
code_below=node.attributes["code_below"],
language=node.attributes["cm_language"],
)
thebe_source.children = [source]
input_node.children = [thebe_source]
if not node.attributes["hide_output"]:
thebe_output = ThebeOutputNode()
thebe_output.children = output_nodes
output_node += thebe_output
else:
if node.attributes["hide_code"]:
node.children.pop(0)
if not node.attributes["hide_output"]:
output_node.children = output_nodes
# Now replace the bundle with our OutputNode
outputbundle_node.replace_self(output_node)
# Swap inputs and outputs if we want the code below
if node.attributes["code_below"]:
node.children = node.children[::-1]
class JupyterDownloadRole(ReferenceRole):
def run(self):
_, filetype = self.name.split(":")
assert filetype in ("notebook", "nb", "script")
ext = ".ipynb" if filetype in ("notebook", "nb") else ".py"
download_file = self.target + ext
reftarget = sphinx_abs_dir(self.env, download_file)
node = download_reference(self.rawtext, reftarget=reftarget)
self.set_source_info(node)
title = self.title if self.has_explicit_title else download_file
node += literal(self.rawtext, title, classes=["xref", "download"])
return [node], []
def get_widgets(notebook):
try:
return notebook.metadata.widgets[WIDGET_STATE_MIMETYPE]
except AttributeError:
# Don't catch KeyError, as it's a bug if 'widgets' does
# not contain 'WIDGET_STATE_MIMETYPE'
return None
class CellOutputsToNodes(SphinxTransform):
"""Use the builder context to transform a CellOutputNode into Sphinx nodes."""
default_priority = 700
def apply(self):
thebe_config = self.config.jupyter_sphinx_thebelab_config
for cell_node in self.document.traverse(JupyterCellNode):
(output_bundle_node,) = cell_node.traverse(CellOutputBundleNode)
# Create doctree nodes for cell outputs.
output_nodes = cell_output_to_nodes(
output_bundle_node.outputs,
self.config.jupyter_execute_data_priority,
bool(cell_node.attributes["stderr"]),
sphinx_abs_dir(self.env),
thebe_config,
)
# Remove the outputbundlenode and we'll attach the outputs next
attach_outputs(output_nodes, cell_node, thebe_config)
jupyter_sphinx-0.3.2/jupyter_sphinx/css/ 0000755 0001751 0000164 00000000000 13732162726 021304 5 ustar runner docker 0000000 0000000 jupyter_sphinx-0.3.2/jupyter_sphinx/css/jupyter-sphinx.css 0000644 0001751 0000164 00000005713 13732162721 025030 0 ustar runner docker 0000000 0000000 /* Stylesheet for jupyter-sphinx
These styles mimic the Jupyter HTML styles.
The default CSS (Cascading Style Sheet) class structure of jupyter-sphinx
is the following:
jupyter_container
code_cell (optional)
stderr (optional)
output (optional)
If the code_cell is not displayed, then there is not a jupyter_container, and
the output is provided without CSS.
This stylesheet attempts to override the defaults of all packaged Sphinx themes
to display jupter-sphinx cells in a Jupyter-like style.
If you want to adjust the styles, add additional custom CSS to override these
styles.
After a build, this stylesheet is loaded from ./_static/jupyter-sphinx.css .
*/
div.jupyter_container {
padding: .4em;
margin: 0 0 .4em 0;
background-color: #FFFF;
border: 1px solid #CCC;
-moz-box-shadow: 2px 2px 4px rgba(87, 87, 87, 0.2);
-webkit-box-shadow: 2px 2px 4px rgba(87, 87, 87, 0.2);
box-shadow: 2px 2px 4px rgba(87, 87, 87, 0.2);
}
.jupyter_container div.code_cell {
border: 1px solid #cfcfcf;
border-radius: 2px;
background-color: #f7f7f7;
margin: 0 0;
overflow: auto;
}
.jupyter_container div.code_cell pre {
padding: 4px;
margin: 0 0;
background-color: #f7f7f7;
border: none;
background: none;
box-shadow: none;
-webkit-box-shadow: none; /* for nature */
-moz-box-shadow: none; /* for nature */
}
.jupyter_container div.code_cell * {
margin: 0 0;
}
div.jupyter_container div.highlight {
background-color: #f7f7f7; /* for haiku */
}
div.jupyter_container {
padding: 0;
margin: 0;
}
/* Prevent alabaster breaking highlight alignment */
div.jupyter_container .hll {
padding: 0;
margin: 0;
}
/* overrides for sphinx_rtd_theme */
.rst-content .jupyter_container div[class^='highlight'],
.document .jupyter_container div[class^='highlight'],
.rst-content .jupyter_container pre.literal-block {
border:none;
margin: 0;
padding: 0;
background: none;
padding: 3px;
background-color: transparent;
}
/* restore Mathjax CSS, as it assumes a vertical margin. */
.jupyter_container .MathJax_Display {
margin: 1em 0em;
text-align: center;
}
.jupyter_container .stderr {
background-color: #FCC;
border: none;
padding: 3px;
}
.jupyter_container .output {
border: none;
}
.jupyter_container div.output pre {
background-color: white;
background: none;
padding: 4px;
border: none;
box-shadow: none;
-webkit-box-shadow: none; /* for nature */
-moz-box-shadow: none; /* for nature */
}
.jupyter_container .code_cell td.linenos {
text-align: right;
padding: 4px 4px 4px 8px;
border-right: 1px solid #cfcfcf;
color: #999;
}
.jupyter_container .output .highlight {
background-color: #ffffff;
}
/* combine sequential jupyter cells,
by moving sequential ones up higher on y-axis */
div.jupyter_container + div.jupyter_container {
margin: -.5em 0 .4em 0;
}
/* Fix for sphinx_rtd_theme spacing after jupyter_container #91 */
.rst-content .jupyter_container {
margin: 0 0 24px 0;
}
jupyter_sphinx-0.3.2/jupyter_sphinx/execute.py 0000644 0001751 0000164 00000026127 13732162721 022533 0 ustar runner docker 0000000 0000000 """Execution and managing kernels."""
import os
import warnings
from pathlib import Path
from logging import Logger
from sphinx.transforms import SphinxTransform
from sphinx.errors import ExtensionError
import docutils
from docutils.parsers.rst import Directive, directives
import nbconvert
from nbconvert.preprocessors import ExtractOutputPreprocessor
from nbconvert.writers import FilesWriter
if nbconvert.version_info < (6,):
from nbconvert.preprocessors.execute import executenb
else:
from nbclient.client import execute as executenb
import traitlets
# Workaround of https://github.com/ipython/traitlets/issues/606
if traitlets.version_info < (5, 1):
class LoggerAdapterWrapper(Logger):
"""Wrap a logger adapter, while pretending to be a logger."""
def __init__(self, wrapped):
self._wrapped = wrapped
def __getattribute__(self, attr):
if attr == "_wrapped":
return object.__getattribute__(self, attr)
return self._wrapped.__getattribute__(attr)
else:
def LoggerAdapterWrapper(logger_adapter):
return logger_adapter
import nbformat
import jupyter_sphinx as js
from .thebelab import ThebeButtonNode, add_thebelab_library
from ._version import __version__
from .utils import (
default_notebook_names,
output_directory,
split_on,
blank_nb,
)
from .ast import (
JupyterCellNode,
CellOutputBundleNode,
JupyterKernelNode,
cell_output_to_nodes,
JupyterWidgetStateNode,
attach_outputs,
get_widgets,
)
class JupyterKernel(Directive):
"""Specify a new Jupyter Kernel.
Arguments
---------
kernel_name : str (optional)
The name of the kernel in which to execute future Jupyter cells, as
reported by executing 'jupyter kernelspec list' on the command line.
Options
-------
id : str
An identifier for *this kernel instance*. Used to name any output
files generated when executing the Jupyter cells (e.g. images
produced by cells, or a script containing the cell inputs).
Content
-------
None
"""
optional_arguments = 1
final_argument_whitespace = False
has_content = False
option_spec = {"id": directives.unchanged}
def run(self):
return [
JupyterKernelNode(
"",
kernel_name=self.arguments[0].strip() if self.arguments else "",
kernel_id=self.options.get("id", "").strip(),
)
]
### Doctree transformations
class ExecuteJupyterCells(SphinxTransform):
"""Execute code cells in Jupyter kernels.
Traverses the doctree to find JupyterKernel and JupyterCell nodes,
then executes the code in the JupyterCell nodes in sequence, starting
a new kernel every time a JupyterKernel node is encountered. The output
from each code cell is inserted into the doctree.
"""
default_priority = 180 # An early transform, idk
def apply(self):
doctree = self.document
docname_path = Path(self.env.docname)
doc_dir_relpath = docname_path.parent # relative to src dir
docname = docname_path.name
default_kernel = self.config.jupyter_execute_default_kernel
default_names = default_notebook_names(docname)
thebe_config = self.config.jupyter_sphinx_thebelab_config
linenos_config = self.config.jupyter_sphinx_linenos
continue_linenos = self.config.jupyter_sphinx_continue_linenos
# Check if we have anything to execute.
if not doctree.traverse(JupyterCellNode):
return
if thebe_config:
# Add the button at the bottom if it is not present
if not doctree.traverse(ThebeButtonNode):
doctree.append(ThebeButtonNode())
add_thebelab_library(doctree, self.env)
js.logger.info("executing {}".format(docname))
output_dir = Path(output_directory(self.env)) / doc_dir_relpath
# Start new notebook whenever a JupyterKernelNode is encountered
jupyter_nodes = (JupyterCellNode, JupyterKernelNode)
nodes_by_notebook = split_on(
lambda n: isinstance(n, JupyterKernelNode),
doctree.traverse(lambda n: isinstance(n, jupyter_nodes)),
)
for first, *nodes in nodes_by_notebook:
if isinstance(first, JupyterKernelNode):
kernel_name = first["kernel_name"] or default_kernel
file_name = first["kernel_id"] or next(default_names)
else:
nodes = (first, *nodes)
kernel_name = default_kernel
file_name = next(default_names)
notebook = execute_cells(
kernel_name,
[nbformat.v4.new_code_cell(node.astext()) for node in nodes],
self.config.jupyter_execute_kwargs,
)
# Raise error if cells raised exceptions and were not marked as doing so
for node, cell in zip(nodes, notebook.cells):
errors = [
output
for output in cell.outputs
if output["output_type"] == "error"
]
allowed_errors = node.attributes.get("raises") or []
raises_provided = node.attributes["raises"] is not None
if (
raises_provided and not allowed_errors
): # empty 'raises': supress all errors
pass
elif errors and not any(e["ename"] in allowed_errors for e in errors):
raise ExtensionError(
"Cell raised uncaught exception:\n{}".format(
"\n".join(errors[0]["traceback"])
)
)
# Raise error if cells print to stderr
for node, cell in zip(nodes, notebook.cells):
stderr = [
output
for output in cell.outputs
if output["output_type"] == "stream" and output["name"] == "stderr"
]
if stderr and not node.attributes["stderr"]:
js.logger.warning(
"Cell printed to stderr:\n{}".format(stderr[0]["text"])
)
try:
lexer = notebook.metadata.language_info.pygments_lexer
except AttributeError:
lexer = notebook.metadata.kernelspec.language
# Highlight the code cells now that we know what language they are
for node in nodes:
source = node.children[0]
source.attributes["language"] = lexer
# Add line numbering
linenostart = 1
for node in nodes:
# The literal_block node with the source
source = node.children[0].children[0]
nlines = source.rawsource.count("\n") + 1
show_numbering = (
linenos_config or source["linenos"] or source["linenostart"]
)
if show_numbering:
source["linenos"] = True
if source["linenostart"]:
linenostart = source["linenostart"]
if source["linenostart"] or continue_linenos:
source["highlight_args"] = {"linenostart": linenostart}
else:
linenostart = 1
linenostart += nlines
hl_lines = node["emphasize_lines"]
if hl_lines:
highlight_args = source.setdefault("highlight_args", {})
highlight_args["hl_lines"] = hl_lines
# Add code cell CSS class
for node in nodes:
source = node.children[0]
source.attributes["classes"].append("code_cell")
# Write certain cell outputs (e.g. images) to separate files, and
# modify the metadata of the associated cells in 'notebook' to
# include the path to the output file.
write_notebook_output(notebook, str(output_dir), file_name, self.env.docname)
try:
cm_language = notebook.metadata.language_info.codemirror_mode.name
except AttributeError:
cm_language = notebook.metadata.kernelspec.language
for node in nodes:
node.attributes["cm_language"] = cm_language
# Add doctree nodes for cell outputs.
for node, cell in zip(nodes, notebook.cells):
node += CellOutputBundleNode(cell.outputs)
if contains_widgets(notebook):
doctree.append(JupyterWidgetStateNode(state=get_widgets(notebook)))
### Roles
def execute_cells(kernel_name, cells, execute_kwargs):
"""Execute Jupyter cells in the specified kernel and return the notebook."""
notebook = blank_nb(kernel_name)
notebook.cells = cells
# Modifies 'notebook' in-place
try:
executenb(notebook, **execute_kwargs)
except Exception as e:
raise ExtensionError("Notebook execution failed", orig_exc=e)
return notebook
def write_notebook_output(notebook, output_dir, notebook_name, location=None):
"""Extract output from notebook cells and write to files in output_dir.
This also modifies 'notebook' in-place, adding metadata to each cell that
maps output mime-types to the filenames the output was saved under.
"""
resources = dict(unique_key=os.path.join(output_dir, notebook_name), outputs={})
# Modifies 'resources' in-place
ExtractOutputPreprocessor().preprocess(notebook, resources)
# Write the cell outputs to files where we can (images and PDFs),
# as well as the notebook file.
FilesWriter(build_directory=output_dir).write(
nbformat.writes(notebook),
resources,
os.path.join(output_dir, notebook_name + ".ipynb"),
)
exporter = nbconvert.exporters.ScriptExporter(
log=LoggerAdapterWrapper(js.logger)
)
with warnings.catch_warnings():
# See https://github.com/jupyter/nbconvert/issues/1388
warnings.simplefilter('ignore', DeprecationWarning)
contents, resources = exporter.from_notebook_node(notebook)
notebook_file = notebook_name + resources['output_extension']
output_dir = Path(output_dir)
# utf-8 is the de-facto standard encoding for notebooks.
(output_dir / notebook_file).write_text(contents, encoding="utf8")
def contains_widgets(notebook):
widgets = get_widgets(notebook)
return widgets and widgets["state"]
def setup(app):
"""A temporary setup function so that we can use it for
backwards compatability.
This should be removed after a deprecation cycle.
"""
# To avoid circular imports we'll lazily import
from . import setup as jssetup
js.logger.warning(
(
"`jupyter-sphinx` was initialized with the "
"`jupyter_sphinx.execute` sub-module. Replace this with "
"`jupyter_sphinx`. Initializing with "
"`jupyter_sphinx.execute` will be removed in "
"version 0.3"
)
)
out = jssetup(app)
return out
jupyter_sphinx-0.3.2/jupyter_sphinx/thebelab/ 0000755 0001751 0000164 00000000000 13732162726 022262 5 ustar runner docker 0000000 0000000 jupyter_sphinx-0.3.2/jupyter_sphinx/thebelab/thebelab-helper.js 0000644 0001751 0000164 00000001542 13732162721 025640 0 ustar runner docker 0000000 0000000 function initThebelab() {
let activateButton = document.getElementById("thebelab-activate-button");
if (activateButton.classList.contains('thebelab-active')) {
return;
}
// Place all outputs below the source where this was not the case
// to make them recognizable by thebelab
let codeBelows = document.getElementsByClassName('thebelab-below');
for(var i = 0; i < codeBelows.length; i++) {
let prev = codeBelows[i]
// Find previous sibling element, compatible with IE8
do prev = prev.previousSibling; while(prev && prev.nodeType !== 1);
swapSibling(prev, codeBelows[i])
}
thebelab.bootstrap();
activateButton.classList.add('thebelab-active')
}
function swapSibling(node1, node2) {
node1.parentNode.replaceChild(node1, node2);
node1.parentNode.insertBefore(node2, node1);
}
jupyter_sphinx-0.3.2/jupyter_sphinx/thebelab/thebelab.css 0000644 0001751 0000164 00000001354 13732162721 024540 0 ustar runner docker 0000000 0000000 .thebelab-cell .thebelab-input pre {
z-index: 0;
}
.thebelab-hidden {
display: none;
}
.thebelab-button {
position: relative;
display: inline-block;
box-sizing: border-box;
border: none;
border-radius: .1rem;
padding: 0 2rem;
margin: .5rem .1rem;
min-width: 64px;
height: 1.6rem;
vertical-align: middle;
text-align: center;
font-size: 0.8rem;
color: rgba(0, 0, 0, 0.8);
background-color: rgba(0, 0, 0, 0.07);
overflow: hidden;
outline: none;
cursor: pointer;
transition: background-color 0.2s;
}
.thebelab-button:hover {
background-color: rgba(0, 0, 0, 0.12);
}
.thebelab-button:active {
background-color: rgba(0, 0, 0, 0.15);
color: rgba(0, 0, 0, 1)
} jupyter_sphinx-0.3.2/jupyter_sphinx/thebelab.py 0000644 0001751 0000164 00000007642 13732162721 022640 0 ustar runner docker 0000000 0000000 """Inserting interactive links with Thebelab."""
import os
import json
import docutils
from docutils.parsers.rst import Directive
from pathlib import Path
import jupyter_sphinx as js
class ThebeSourceNode(docutils.nodes.container):
"""Container that holds the cell source when thebelab is enabled"""
def __init__(self, rawsource="", *children, **attributes):
super().__init__("", **attributes)
def visit_html(self):
code_class = "thebelab-code"
if self["hide_code"]:
code_class += " thebelab-hidden"
if self["code_below"]:
code_class += " thebelab-below"
language = self["language"]
return '
'.format(
code_class, language
)
def depart_html(self):
return "
"
class ThebeOutputNode(docutils.nodes.container):
"""Container that holds all the output nodes when thebelab is enabled"""
def visit_html(self):
return '
'
def depart_html(self):
return "
"
class ThebeButtonNode(docutils.nodes.Element):
"""Appended to the doctree by the ThebeButton directive
Renders as a button to enable thebelab on the page.
If no ThebeButton directive is found in the document but thebelab
is enabled, the node is added at the bottom of the document.
"""
def __init__(self, rawsource="", *children, text="Make live", **attributes):
super().__init__("", text=text)
def html(self):
text = self["text"]
return (
''.format(text=text)
)
class ThebeButton(Directive):
"""Specify a button to activate thebelab on the page
Arguments
---------
text : str (optional)
If provided, the button text to display
Content
-------
None
"""
optional_arguments = 1
final_argument_whitespace = True
has_content = False
def run(self):
kwargs = {"text": self.arguments[0]} if self.arguments else {}
return [ThebeButtonNode(**kwargs)]
def add_thebelab_library(doctree, env):
"""Adds the thebelab configuration and library to the doctree"""
thebe_config = env.config.jupyter_sphinx_thebelab_config
if isinstance(thebe_config, dict):
pass
elif isinstance(thebe_config, str):
thebe_config = Path(thebe_config)
if thebe_config.is_absolute():
filename = thebe_config
else:
filename = Path(env.app.srcdir).resolve() / thebe_config
if not filename.exists():
js.logger.warning("The supplied thebelab configuration file does not exist")
return
try:
thebe_config = json.loads(filename.read_text())
except ValueError:
js.logger.warning(
"The supplied thebelab configuration file is not in JSON format."
)
return
else:
js.logger.warning(
"The supplied thebelab configuration should be either a filename or a dictionary."
)
return
# Force config values to make thebelab work correctly
thebe_config["predefinedOutput"] = True
thebe_config["requestKernel"] = True
# Specify the thebelab config inline, a separate file is not supported
doctree.append(
docutils.nodes.raw(
text='\n'.format(
json.dumps(thebe_config)
),
format="html",
)
)
# Add thebelab library after the config is specified
doctree.append(
docutils.nodes.raw(
text='\n'.format(
env.config.jupyter_sphinx_thebelab_url
),
format="html",
)
)
jupyter_sphinx-0.3.2/jupyter_sphinx/utils.py 0000644 0001751 0000164 00000006273 13732162721 022231 0 ustar runner docker 0000000 0000000 """Utility functions and helpers."""
import os
from itertools import groupby, count
from sphinx.errors import ExtensionError
import nbformat
from jupyter_client.kernelspec import get_kernel_spec, NoSuchKernel
from pathlib import Path
def blank_nb(kernel_name):
try:
spec = get_kernel_spec(kernel_name)
except NoSuchKernel as e:
raise ExtensionError("Unable to find kernel", orig_exc=e)
return nbformat.v4.new_notebook(
metadata={
"kernelspec": {
"display_name": spec.display_name,
"language": spec.language,
"name": kernel_name,
}
}
)
def split_on(pred, it):
"""Split an iterator wherever a predicate is True."""
counter = 0
def count(x):
nonlocal counter
if pred(x):
counter += 1
return counter
# Return iterable of lists to ensure that we don't lose our
# place in the iterator
return (list(x) for _, x in groupby(it, count))
def strip_latex_delimiters(source):
"""Remove LaTeX math delimiters that would be rendered by the math block.
These are: ``\(…\)``, ``\[…\]``, ``$…$``, and ``$$…$$``.
This is necessary because sphinx does not have a dedicated role for
generic LaTeX, while Jupyter only defines generic LaTeX output, see
https://github.com/jupyter/jupyter-sphinx/issues/90 for discussion.
"""
source = source.strip()
delimiter_pairs = (pair.split() for pair in r"\( \),\[ \],$$ $$,$ $".split(","))
for start, end in delimiter_pairs:
if source.startswith(start) and source.endswith(end):
return source[len(start) : -len(end)]
return source
def default_notebook_names(basename):
"""Return an interator yielding notebook names based off 'basename'"""
yield basename
for i in count(1):
yield "_".join((basename, str(i)))
def language_info(executor):
# Can only run this function inside 'setup_preprocessor'
assert hasattr(executor, "kc")
info_msg = executor._wait_for_reply(executor.kc.kernel_info())
return info_msg["content"]["language_info"]
def sphinx_abs_dir(env, *paths):
# We write the output files into
# output_directory / jupyter_execute / path relative to source directory
# Sphinx expects download links relative to source file or relative to
# source dir and prepended with '/'. We use the latter option.
out_path = (output_directory(env) / Path(env.docname).parent / Path(*paths)).resolve()
if os.name == "nt":
# Can't get relative path between drives on Windows
return out_path.as_posix()
# Path().relative_to() doesn't work when not a direct subpath
return "/" + os.path.relpath(out_path, env.app.srcdir)
def output_directory(env):
# Put output images inside the sphinx build directory to avoid
# polluting the current working directory. We don't use a
# temporary directory, as sphinx may cache the doctree with
# references to the images that we write
# Note: we are using an implicit fact that sphinx output directories are
# direct subfolders of the build directory.
return (Path(env.app.outdir) / os.path.pardir / "jupyter_execute").resolve()
jupyter_sphinx-0.3.2/jupyter_sphinx.egg-info/ 0000755 0001751 0000164 00000000000 13732162726 022206 5 ustar runner docker 0000000 0000000 jupyter_sphinx-0.3.2/jupyter_sphinx.egg-info/PKG-INFO 0000644 0001751 0000164 00000002745 13732162726 023313 0 ustar runner docker 0000000 0000000 Metadata-Version: 2.1
Name: jupyter-sphinx
Version: 0.3.2
Summary: Jupyter Sphinx Extensions
Home-page: https://github.com/jupyter/jupyter-sphinx/
Author: Jupyter Development Team
Author-email: jupyter@googlegroups.com
License: BSD
Project-URL: Bug Tracker, https://github.com/jupyter/jupyter-sphinx/issues/
Project-URL: Documentation, https://jupyter-sphinx.readthedocs.io
Project-URL: Source Code, https://github.com/jupyter/jupyter-sphinx/
Description: # Jupyter Sphinx Extensions
``jupyter-sphinx`` enables running code embedded in Sphinx documentation and
embedding output of that code into the resulting document. It has support
for rich output such as images and even Jupyter interactive widgets.
## Installation
With pip:
```bash
pip install jupyter_sphinx
```
with conda:
```bash
conda install jupyter_sphinx -c conda-forge
```
## Usage
You can check out the documentation on https://jupyter-sphinx.readthedocs.io for up to date
usage information and examples.
## License
We use a shared copyright model that enables all contributors to maintain the
copyright on their contributions.
All code is licensed under the terms of the revised BSD license.
Platform: UNKNOWN
Requires-Python: >= 3.6
Description-Content-Type: text/markdown
jupyter_sphinx-0.3.2/jupyter_sphinx.egg-info/SOURCES.txt 0000644 0001751 0000164 00000000774 13732162726 024102 0 ustar runner docker 0000000 0000000 LICENSE
MANIFEST.in
README.md
setup.cfg
setup.py
jupyter_sphinx/__init__.py
jupyter_sphinx/_version.py
jupyter_sphinx/ast.py
jupyter_sphinx/execute.py
jupyter_sphinx/thebelab.py
jupyter_sphinx/utils.py
jupyter_sphinx.egg-info/PKG-INFO
jupyter_sphinx.egg-info/SOURCES.txt
jupyter_sphinx.egg-info/dependency_links.txt
jupyter_sphinx.egg-info/requires.txt
jupyter_sphinx.egg-info/top_level.txt
jupyter_sphinx/css/jupyter-sphinx.css
jupyter_sphinx/thebelab/thebelab-helper.js
jupyter_sphinx/thebelab/thebelab.css jupyter_sphinx-0.3.2/jupyter_sphinx.egg-info/dependency_links.txt 0000644 0001751 0000164 00000000001 13732162726 026254 0 ustar runner docker 0000000 0000000
jupyter_sphinx-0.3.2/jupyter_sphinx.egg-info/requires.txt 0000644 0001751 0000164 00000000074 13732162726 024607 0 ustar runner docker 0000000 0000000 Sphinx>=2
ipywidgets>=7.0.0
IPython
nbconvert>=5.5
nbformat
jupyter_sphinx-0.3.2/jupyter_sphinx.egg-info/top_level.txt 0000644 0001751 0000164 00000000017 13732162726 024736 0 ustar runner docker 0000000 0000000 jupyter_sphinx
jupyter_sphinx-0.3.2/setup.cfg 0000644 0001751 0000164 00000000111 13732162726 017233 0 ustar runner docker 0000000 0000000 [metadata]
license_file = LICENSE
[egg_info]
tag_build =
tag_date = 0
jupyter_sphinx-0.3.2/setup.py 0000644 0001751 0000164 00000002206 13732162721 017126 0 ustar runner docker 0000000 0000000 from setuptools import setup
import os
here = os.path.abspath(os.path.dirname(__file__))
name = "jupyter_sphinx"
version_ns = {}
with open(os.path.join(here, name, "_version.py")) as f:
exec(f.read(), {}, version_ns)
with open(os.path.join(here, "README.md")) as f:
description = f.read()
setup(
name=name,
version=version_ns["__version__"],
author="Jupyter Development Team",
author_email="jupyter@googlegroups.com",
description="Jupyter Sphinx Extensions",
long_description=description,
long_description_content_type='text/markdown',
url="https://github.com/jupyter/jupyter-sphinx/",
project_urls={
"Bug Tracker": "https://github.com/jupyter/jupyter-sphinx/issues/",
"Documentation": "https://jupyter-sphinx.readthedocs.io",
"Source Code": "https://github.com/jupyter/jupyter-sphinx/",
},
license="BSD",
packages=["jupyter_sphinx"],
install_requires=[
"Sphinx>=2",
"ipywidgets>=7.0.0",
"IPython",
"nbconvert>=5.5",
"nbformat",
],
python_requires=">= 3.6",
package_data={"jupyter_sphinx": ["thebelab/*", "css/*"]},
)