diff --git a/docs/source/conf.py b/docs/source/conf.py index 6166198e..7954fc12 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,194 +1,33 @@ -#!/usr/bin/env python3 # -*- coding: utf-8 -*- -# -# ipylab documentation build configuration file -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.viewcode", - "sphinx.ext.intersphinx", - "sphinx.ext.napoleon", - "sphinx.ext.todo", - "nbsphinx", + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'jupyterlite_sphinx' ] -# Ensure our extension is available: -import json -import sys -from os.path import dirname, join as pjoin - -docs = dirname(dirname(__file__)) -root = dirname(docs) -sys.path.insert(0, root) -sys.path.insert(0, pjoin(docs, "sphinxext")) +templates_path = ['_templates'] -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] +# jupyterlite_config = "jupyterlite_config.json" -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = ".rst" - -# The master toctree document. -master_doc = "index" +master_doc = 'index' +source_suffix = '.rst' # General information about the project. -project = "ipylab" -copyright = "2019, ipylab contributors" -author = "ipylab contributors" - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. - - -# get version from python package: -import os - -here = os.path.dirname(__file__) -repo = os.path.join(here, "..", "..") -with open(os.path.join(repo, "package.json")) as f: - package = json.load(f) - _version_js = package["version"] - -# The short X.Y version. -version = "%i.%i" % tuple(int(part) for part in _version_js.split("."))[:2] -# The full version, including alpha/beta/rc tags. -release = ( - _version_js.replace("-alpha.", "a").replace("-beta.", "b").replace("-rc.", "rc") -) - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ["**.ipynb_checkpoints"] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} +project = 'ipylab' +author = 'ipylab contributors' -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["_static"] - - -# -- Options for HTMLHelp output ------------------------------------------ +exclude_patterns = [] +highlight_language = 'python' +pygments_style = 'sphinx' # Output file base name for HTML help builder. -htmlhelp_basename = "ipylabdoc" - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, "ipylab.tex", "ipylab Documentation", "ipylab contributors", "manual"), -] - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "ipylab", "ipylab Documentation", [author], 1)] +html_theme = "pydata_sphinx_theme" +htmlhelp_basename = 'ipylabdoc' +html_theme_options = dict( + github_url='https://github.com/jtpio/ipylab' +) -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "ipylab", - "ipylab Documentation", - author, - "ipylab", - "Python bridge to JupyterLab", - "Miscellaneous", - ), -] - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {"https://docs.python.org/": None} - -# Read The Docs -# on_rtd is whether we are on readthedocs.org, this line of code grabbed from -# docs.readthedocs.org -on_rtd = os.environ.get("READTHEDOCS", None) == "True" - -if not on_rtd: # only import and set the theme if we're building docs locally - import sphinx_rtd_theme - - html_theme = "sphinx_rtd_theme" - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -# otherwise, readthedocs.org uses their theme by default, so no need to specify it - +html_static_path = ['_static'] -# Uncomment this line if you have know exceptions in your included notebooks -# that nbsphinx complains about: -# -nbsphinx_allow_errors = True # exception ipstruct.py ipython_genutils +autodoc_member_order = 'bysource' diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst deleted file mode 100644 index 26b2bd28..00000000 --- a/docs/source/examples/index.rst +++ /dev/null @@ -1,18 +0,0 @@ - -Examples -======== - -This section contains several examples generated from Jupyter notebooks. -The widgets have been embedded into the page for demonstrative pruposes. - -.. todo:: - - Add links to notebooks in examples folder similar to the initial - one. This is a manual step to ensure only those examples that - are suited for inclusion are used. - - -.. toctree:: - :glob: - - * diff --git a/docs/source/examples/introduction.nblink b/docs/source/examples/introduction.nblink deleted file mode 100644 index 258bb0f0..00000000 --- a/docs/source/examples/introduction.nblink +++ /dev/null @@ -1,3 +0,0 @@ -{ - "path": "../../../examples/introduction.ipynb" -} diff --git a/docs/source/ipylab.ipynb b/docs/source/ipylab.ipynb new file mode 100644 index 00000000..41c7e650 --- /dev/null +++ b/docs/source/ipylab.ipynb @@ -0,0 +1,380 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Command Registry" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from ipylab import JupyterFrontEnd\n", + "\n", + "app = JupyterFrontEnd()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.version" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## List all commands" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.commands.list_commands()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a new console" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.commands.execute('console:create', {\n", + " 'insertMode': 'split-right',\n", + " 'kernelPreference': {\n", + " 'shutdownOnClose': True,\n", + " }\n", + "})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Change the theme" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.commands.execute('apputils:change-theme', { 'theme': 'JupyterLab Dark' })" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a new terminal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.commands.execute('terminal:create-new')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Ready event\n", + "\n", + "Some functionalities might require the `JupyterFrontEnd` widget to be ready on the frontend first.\n", + "\n", + "This is for example the case when listing all the available commands, or retrieving the version with `app.version`.\n", + "\n", + "The `on_ready` method can be used to register a callback that will be fired when the frontend is ready." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from ipylab import JupyterFrontEnd\n", + "from ipywidgets import Output\n", + "\n", + "app = JupyterFrontEnd()\n", + "out = Output()\n", + "\n", + "def init():\n", + " # show the first 5 commands\n", + " cmds = app.commands.list_commands()[:5]\n", + " out.append_stdout(cmds)\n", + "\n", + "app.on_ready(init)\n", + "out" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or using `asyncio`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import asyncio\n", + "\n", + "app = JupyterFrontEnd()\n", + "\n", + "out = Output()\n", + "\n", + "async def init():\n", + " await app.ready()\n", + " cmds = app.commands.list_commands()[:5]\n", + " out.append_stdout(cmds)\n", + "\n", + "asyncio.create_task(init())\n", + "out" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add your own command\n", + "\n", + "Let's create a nice plot with `bqlot` and generate some random data.\n", + "\n", + "See https://github.com/bqplot/bqplot/blob/master/examples/Advanced%20Plotting/Animations.ipynb for more details." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "from bqplot import LinearScale, Lines, Bars, Axis, Figure\n", + "from ipywidgets import IntSlider" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xs = LinearScale()\n", + "ys1 = LinearScale()\n", + "ys2 = LinearScale()\n", + "\n", + "x = np.arange(20)\n", + "y = np.cumsum(np.random.randn(20))\n", + "y1 = np.random.rand(20)\n", + "\n", + "line = Lines(x=x, y=y, scales={'x': xs, 'y': ys1}, colors=['magenta'], marker='square')\n", + "bar = Bars(x=x, y=y1, scales={'x': xs, 'y': ys2}, colorpadding=0.2, colors=['steelblue'])\n", + "\n", + "xax = Axis(scale=xs, label='x', grid_lines='solid')\n", + "yax1 = Axis(scale=ys1, orientation='vertical', tick_format='0.1f', label='y', grid_lines='solid')\n", + "yax2 = Axis(scale=ys2, orientation='vertical', side='right', tick_format='0.0%', label='y1', grid_lines='none')\n", + "\n", + "Figure(marks=[bar, line], axes=[xax, yax1, yax2], animation_duration=1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now define a function to update the data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def update_data():\n", + " line.y = np.cumsum(np.random.randn(20))\n", + " bar.y = np.random.rand(20)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "update_data()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This function will now be called when the JupyterLab command is executed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.commands.add_command('update_data', execute=update_data, label=\"Update Data\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Execute it!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.commands.execute('update_data')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The slider should now be moving and taking random values.\n", + "\n", + "Also the list of commands gets updated with the newly added command:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assert 'random' in app.commands.list_commands()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's great, but the command doesn't visually show up in the palette yet. So let's add it!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add the command to the palette" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from ipylab.commands import CommandPalette" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "palette = CommandPalette()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "palette.add_item('update_data', 'Python Commands')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Open the command palette on the left side and the command should show now be visible." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Remove a command\n", + "\n", + "To remove a command that was previously added:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app.commands.remove_command('update_data')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.2" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/readthedocs.yml b/readthedocs.yml index ba61a334..56acd737 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -2,10 +2,15 @@ version: 2 build: os: ubuntu-20.04 tools: - python: mambaforge-4.10 + python: "3.8" + nodejs: "14" + +sphinx: + configuration: docs/source/conf.py + python: install: - method: pip path: . -conda: - environment: docs/environment.yml + extra_requirements: + - docs diff --git a/setup.cfg b/setup.cfg index f854acc8..ee981aac 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,9 +42,10 @@ dev = docs = sphinx>=1.5 recommonmark - sphinx_rtd_theme nbsphinx>=0.2.13,<0.4.0 jupyter_sphinx + jupyterlite-sphinx nbsphinx-link + pydata-sphinx-theme pytest_check_links pypandoc