diff --git a/.gitignore b/.gitignore index 0025831b..ec6f7b23 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ pip-wheel-metadata # ipython */.ipynb_checkpoints +# jupytext +.ipynb_checkpoints/ # autover */.version @@ -26,3 +28,5 @@ site/builtdocs/ site/.venv/ build/ + +.venv/ diff --git a/nbsite/pyodide/__init__.py b/nbsite/pyodide/__init__.py index a7b9467a..4472de92 100644 --- a/nbsite/pyodide/__init__.py +++ b/nbsite/pyodide/__init__.py @@ -18,7 +18,7 @@ from bokeh.embed.util import standalone_docs_json_and_render_items from bokeh.model import Model from docutils import nodes -from docutils.parsers.rst import Directive, roles +from docutils.parsers.rst import roles from jinja2.environment import Environment from jinja2.loaders import FileSystemLoader from packaging.version import Version @@ -183,14 +183,23 @@ def _option_boolean(arg): else: raise ValueError('"%s" unknown boolean' % arg) -class PyodideDirective(Directive): + +from docutils.parsers.rst import directives +from sphinx.directives.code import CodeBlock + + +# class PyodideDirective(Directive): +class PyodideCodeBlock(CodeBlock): has_content = True option_spec = { - 'skip-embed': _option_boolean + **CodeBlock.option_spec, + 'skip-embed': _option_boolean, + 'pyodide': directives.flag, } + _current_source = None _current_context = {} _current_count = 0 @@ -263,10 +272,15 @@ def _kill(cls): cls._current_process = None def run(self): + if 'pyodide' not in self.options: + return super().run() + return self.run_pyodide() + + def run_pyodide(self): current_source = self.state_machine.get_source() if self._current_source != current_source or self._current_process is None: - PyodideDirective._current_count = 0 - PyodideDirective._current_source = current_source + PyodideCodeBlock._current_count = 0 + PyodideCodeBlock._current_source = current_source self._launch_process() classes = 'pyodide' @@ -279,7 +293,7 @@ def run(self): doctree_node = nodes.literal_block(code, code, **self.options) doctree_node['language'] = 'python' - PyodideDirective._current_count += 1 + PyodideCodeBlock._current_count += 1 if self.options.get('skip-embed'): return [doctree_node] @@ -466,16 +480,28 @@ def html_page_context( ] +def replace_code_cell_for_block(app: Sphinx, docname: str, source: list) -> None: + env = app.env + docpath = env.doc2path(docname, base=False) + if docpath.endswith('.md'): + source[0] = source[0].replace('{code-cell}', '{code-block}') + + def setup(app): """Setup sphinx-gallery sphinx extension""" app.add_config_value('nbsite_pyodide_conf', DEFAULT_PYODIDE_CONF, 'html') app.connect('builder-inited', init_conf) + app.connect('source-read', replace_code_cell_for_block) app.connect('build-finished', write_worker) app.connect('html-page-context', html_page_context) - app.connect('build-finished', PyodideDirective.terminate) + app.connect('build-finished', PyodideCodeBlock.terminate) + + # app.add_directive('pyodide', PyodideDirective) - app.add_directive('pyodide', PyodideDirective) + # Code block with customisable indent size. + app.add_directive("code-block", PyodideCodeBlock, override=True) + app.add_directive("sourcecode", PyodideCodeBlock, override=True) app.add_css_file('runbutton.css') app.add_js_file('run_cell.js') diff --git a/site/doc/playground/pyodide/holoviz.md b/site/doc/playground/pyodide/holoviz.md index 913889b2..9b2a7baa 100644 --- a/site/doc/playground/pyodide/holoviz.md +++ b/site/doc/playground/pyodide/holoviz.md @@ -2,7 +2,9 @@ ## HoloViews -```{pyodide} +```{code-block} python +:pyodide: null + import holoviews as hv import pandas as pd @@ -17,7 +19,9 @@ TODO: Matplotlib + Plotly ## hvPlot -```{pyodide} +```{code-block} python +:pyodide: null + import hvplot.pandas # noqa df.hvplot.scatter(x='x', y='y') @@ -28,7 +32,9 @@ TODO: Matplotlib + Plotly ## Panel -```{pyodide} +```{code-block} python +:pyodide: null + import panel as pn pn.widgets.IntInput() diff --git a/site/doc/playground/pyodide/index.md b/site/doc/playground/pyodide/index.md index d07489bf..7e8ac8bd 100644 --- a/site/doc/playground/pyodide/index.md +++ b/site/doc/playground/pyodide/index.md @@ -2,7 +2,9 @@ Using the `pyodide` directive. -```{pyodide} +```{code-block} python +:pyodide: null + print('hello') ``` @@ -13,4 +15,5 @@ print('hello') Intro holoviz +jupytext ``` diff --git a/site/doc/playground/pyodide/jupytext.md b/site/doc/playground/pyodide/jupytext.md new file mode 100644 index 00000000..f2d760b3 --- /dev/null +++ b/site/doc/playground/pyodide/jupytext.md @@ -0,0 +1,66 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.0 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +# Jupytext + +This Markdown file can be opened as a Notebook in JupyterLab with Jupytext installed. New code cells are created with the `code-cell` directive. + +## HoloViews + +```{code-cell} ipython3 +print('code-cells are turned into code-blocks') +``` + +```{code-cell} ipython3 +:pyodide: null + +print('pyodide code-cell are turned into code-blocks and parsed with the PyodideCodeBlock directive') +``` + +```{code-cell} ipython3 +:pyodide: null + +import holoviews as hv +import pandas as pd + +hv.extension('bokeh') + +df = pd.DataFrame({'x': [0, 10, 20], 'y': [5, 1, 20]}) + +hv.Curve(df, kdims='x', vdims='y') +``` + +TODO: Matplotlib + Plotly + +## hvPlot + +```{code-cell} ipython3 +:pyodide: null + +import hvplot.pandas # noqa + +df.hvplot.scatter(x='x', y='y') +``` + +TODO: Matplotlib + Plotly + + +## Panel + +```{code-cell} ipython3 +:pyodide: null + +import panel as pn + +pn.widgets.IntInput() +``` diff --git a/site/requirements.txt b/site/requirements.txt index c8e0df2f..34511476 100644 --- a/site/requirements.txt +++ b/site/requirements.txt @@ -7,3 +7,6 @@ matplotlib plotly -e .. -e ./dummy_package +jupyterlab +jupyterlab_myst +jupytext