pax_global_header00006660000000000000000000000064145607023110014511gustar00rootroot0000000000000052 comment=60aa219f0a69939337510776b12fb3e54c444454 sphinx-thebe-0.3.1/000077500000000000000000000000001456070231100141105ustar00rootroot00000000000000sphinx-thebe-0.3.1/.git_archival.txt000066400000000000000000000001751456070231100173660ustar00rootroot00000000000000node: $Format:%H$ node-date: $Format:%cI$ describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ ref-names: $Format:%D$ sphinx-thebe-0.3.1/.github/000077500000000000000000000000001456070231100154505ustar00rootroot00000000000000sphinx-thebe-0.3.1/.github/workflows/000077500000000000000000000000001456070231100175055ustar00rootroot00000000000000sphinx-thebe-0.3.1/.github/workflows/release.yml000066400000000000000000000027421456070231100216550ustar00rootroot00000000000000# This will run every time a tag is created and pushed to the repository. # It calls our tests workflow via a `workflow_call`, and if tests pass # then it triggers our upload to PyPI for a new release. name: Make a new release on: push: tags: - "v[0-9]+.[0-9]+.[0-9]+" - "v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+" jobs: tests: uses: ./.github/workflows/tests.yml dist: name: publish needs: [tests] # require tests to pass before deploy runs runs-on: ubuntu-latest steps: - name: Checkout source uses: actions/checkout@v3 - name: Set up Python 3.11 uses: actions/setup-python@v4 with: python-version: 3.11 - name: Build package run: pipx run build - uses: actions/upload-artifact@v3 with: path: dist/* upload_pypi: name: publish needs: [dist] runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v3 with: name: artifact path: dist - name: Publish uses: pypa/gh-action-pypi-publish@v1.6.4 with: user: __token__ password: ${{ secrets.PYPI_KEY }} release: needs: [ upload_pypi ] name: Create release runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: softprops/action-gh-release@v1 with: name: Sphinx thebe ${{ github.ref_name }} prerelease: ${{ contains(github.ref, 'rc') }} generate_release_notes: true sphinx-thebe-0.3.1/.github/workflows/tests.yml000066400000000000000000000014451456070231100213760ustar00rootroot00000000000000name: continuous-integration on: push: branches: [main] tags: - 'v*' pull_request: workflow_call: jobs: docs: runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: ["3.8", "3.9", "3.10", "3.11"] # Latest and 2 major releases earlier sphinx: [ "~=5.0", "~=7.0" ] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} cache: pip - name: Install sphinx-thebe with sphinx ${{ matrix.sphinx }} run: | pip install --upgrade pip pip install --upgrade "Sphinx${{ matrix.sphinx }}" -e .[testing] - name: Run tests run: | pytest sphinx-thebe-0.3.1/.gitignore000066400000000000000000000034651456070231100161100ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ ### Project specific docs/_build _version.py sphinx-thebe-0.3.1/CHANGELOG.md000066400000000000000000000042741456070231100157300ustar00rootroot00000000000000# Changelog ## v0.2.1 - 2023-01-27 - FIX: Add name to the kernelOptions [#60](https://github.com/executablebooks/sphinx-thebe/pull/60) (@joergbrech) ## v0.2.0 - 2023-01-05 Minor improvements to support up to Sphinx 6. See https://github.com/executablebooks/sphinx-thebe/pull/57 for more details. ## v0.1.2 - 2022-04-29 This is a minor patch release to fix a JSON metadata bug with myst-nb notebooks. ## v0.1.1 - 2022-02-06 A minor feature addition release to add default CSS selectors for MyST-NB cells. ([full changelog](https://github.com/executablebooks/sphinx-thebe/compare/v0.1.0...ff1fd4b40615c32e6c9d0a60b98434cc1fe2f084)) - ENH: Add defaults for MyST-NB [#48](https://github.com/executablebooks/sphinx-thebe/pull/48) ([@choldgraf](https://github.com/choldgraf)) ## v0.1.0 - 2022-02-05 ([full changelog](https://github.com/executablebooks/sphinx-thebe/compare/v0.0.10...4d1a60c5126ce633b1a36de43b4990b2f4d08730)) **Lazy load thebe javascript** [#41](https://github.com/executablebooks/sphinx-thebe/pull/41) ([@choldgraf](https://github.com/choldgraf)) `thebe` will now "lazily load" its javascript only when a bootstrap button is pressed, rather than loading the Javascript on each page. This saves on bandwidth and pageload speed, since Thebe is generally _not_ used on a page even if it _could_ be used. ## v0.0.10 - 2021-08-24 ([full changelog](https://github.com/executablebooks/sphinx-thebe/compare/v0.0.9...e18d1bf94a8fa79476f035a349bd63d03bba83e7)) This is a minor release to conditionally load the JS on pages that have a "launch button". This will save some load time on non-interactive pages. ### Enhancements made - Option to conditionally load on pages, see [documentation for details](https://sphinx-thebe.readthedocs.io/en/latest/configure.html#only-load-js-on-certain-pages) [#30](https://github.com/executablebooks/sphinx-thebe/pull/30) ([@choldgraf](https://github.com/choldgraf)) ### Other merged PRs - PIN: thebe v0.5.1 [#31](https://github.com/executablebooks/sphinx-thebe/pull/31) ([@choldgraf](https://github.com/choldgraf)) ## v0.0.9 - 2021-08-21 ### Updates - `sphinx-thebe` now uses the correct and latest version of thebe, since it has been renamed from `thebelab` to `thebe`. sphinx-thebe-0.3.1/LICENSE000066400000000000000000000020571456070231100151210ustar00rootroot00000000000000MIT License Copyright (c) 2018 Chris Holdgraf Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. sphinx-thebe-0.3.1/README.md000066400000000000000000000013771456070231100153770ustar00rootroot00000000000000# sphinx-thebe [![Documentation](https://readthedocs.org/projects/sphinx-thebe/badge/?version=latest)](https://sphinx-thebe.readthedocs.io/en/latest/?badge=latest) [![PyPI](https://img.shields.io/pypi/v/sphinx-thebe.svg)](https://pypi.org/project/sphinx-thebe) Integrate interactive code blocks into your documentation with Thebe and Binder. See [the sphinx-thebe documentation](https://sphinx-thebe.readthedocs.io/en/latest/) for more details! ## Install To install `sphinx-thebe` first clonse and install it: ``` pip install sphinx-thebe ``` Then, add it to your Sphinx site's `conf.py` file: ``` extensions = [ ... "sphinx_thebe" ... ] ``` See [the sphinx-thebe documentation](https://sphinx-thebe.readthedocs.io/en/latest/) for more details! sphinx-thebe-0.3.1/RELEASES.md000066400000000000000000000030561456070231100156410ustar00rootroot00000000000000# Instructions for creating a new release Spinx-Copybutton is [hosted on the pypi repository](https://pypi.org/project/sphinx-thebe/). To create a new release of sphinx-thebe, you need to do these things: ## Before you start 1. Ensure that you have push access to the [sphinx-thebe pypi repository](https://pypi.org/project/sphinx-thebe/) 2. Install [the twine package](https://twine.readthedocs.io/en/latest/). This is a package that helps you bundle and push new Python package distributions to pip. ## To create the release To create a new release, [open an issue](https://github.com/executablebooks/sphinx-thebe/issues/new) to keep track of the to-do list for the release. Copy/paste the following markdown into the issue and check off the boxes as you complete items: ``` - [ ] Ensure that the [sphinx-thebe version number](https://github.com/executablebooks/sphinx-thebe/blob/master/jupyter_book/__init__.py) is correct, and remove the `dev0` part of the version number. Make a PR with the new number and merge into master. - [ ] Create a new distribution for sphinx-thebe by [following the twine release instructions](https://twine.readthedocs.io/en/latest/#using-twine) - [ ] Confirm that the new version of sphinx-thebe [is posted to pypi](https://pypi.org/project/sphinx-thebe/) - [ ] Bump the [sphinx-thebe version number](https://github.com/executablebooks/sphinx-thebe/blob/master/jupyter_book/__init__.py) to the next minor (or major) release and append `dev0` to the end. - [ ] Celebrate! You've just released a new version of sphinx-thebe! ``` sphinx-thebe-0.3.1/docs/000077500000000000000000000000001456070231100150405ustar00rootroot00000000000000sphinx-thebe-0.3.1/docs/Makefile000066400000000000000000000011451456070231100165010ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXPROJ = SphinxCopybutton SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)sphinx-thebe-0.3.1/docs/changelog.md000066400000000000000000000000401456070231100173030ustar00rootroot00000000000000```{include} ../CHANGELOG.md ```sphinx-thebe-0.3.1/docs/conf.py000066400000000000000000000113371456070231100163440ustar00rootroot00000000000000# -- Project information ----------------------------------------------------- project = "Sphinx Thebe" copyright = "2020, Executable Book Project" author = "Executable Book Project" # The short X.Y version version = "" # The full version, including alpha/beta/rc tags release = "" # -- 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 = ["myst_nb", "sphinx_copybutton", "sphinx_design", "sphinx_thebe"] thebe_config = { "repository_url": "https://github.com/binder-examples/jupyter-stacks-datascience", "path_to_docs": "docs", # "repository_branch": "master", # "selector": ".thebe", # "selector_input": "", # "selector_output": "", # "codemirror-theme": "blackboard", # Doesn't currently work # "always_load": True, # To load thebe on every page } myst_enable_extensions = ["colon_fence"] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # 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" # 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 # Not recommended sphinx >=5. https://github.com/sphinx-doc/sphinx/issues/10474 # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path . exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = "sphinx_book_theme" html_title = "sphinx-thebe" # 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 = { "repository_url": "https://github.com/executablebooks/sphinx-thebe", "path_to_docs": "docs", "use_repository_button": True, "use_issues_button": True, "launch_buttons": {"thebelab": True}, "navigation_with_keys": False, # To prevent an unnecessary warning } # CopyButton configuration copybutton_prompt_text = ">>> " # Switches for testing but shouldn't be activated in the live docs # copybutton_only_copy_prompt_lines = False # copybutton_remove_prompts = False # copybutton_image_path = "test/TEST_COPYBUTTON.png" # copybutton_selector = "div" # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = "SphinxCopybuttondoc" # -- 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, "SphinxCopybutton.tex", "Sphinx Copybutton Documentation", "Chris Holdgraf", "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, "sphinxcopybutton", "Sphinx Copybutton Documentation", [author], 1) ] # -- 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, "SphinxCopybutton", "Sphinx Copybutton Documentation", author, "SphinxCopybutton", "One line description of project.", "Miscellaneous", ), ] sphinx-thebe-0.3.1/docs/configure.md000066400000000000000000000141721456070231100173500ustar00rootroot00000000000000--- thebe-kernel: ir --- # Configuration (configure:selector)= ## Change the HTML selector to mark interactive cells By default, `sphinx-thebe` will be run on any cells with the `thebe` class. However, you can customize the HTML selector to use other classes, elements, etc. For example, if you wanted to convert **all code cells**, you could use the following selector: ```python thebe_config = { "selector": "div.highlight" } ``` ```{note} `sphinx-thebe` will subsequently look for any `pre` blocks inside of elements it finds with the `selector` configuration value. These are the blocks that will be converted to interactive with `thebe`. ``` ## Including outputs with your code If you'd like to include outputs in the *static* version of your page, and only overwrite them once the user has run that Thebe cell, you can configure `sphinx-thebe` to detect and keep the outputs associated with some code. To do so, use the `selector_output` configuration. This is a selector that is searched for *within* any items discovered by `selector`. If an output is found, it will be placed just after the code and Thebe will detect it. For example, the following code: ``````{tab-set} `````{tab-item} Myst Markdown ````{container} thebe ```{code-block} r print("hi") ``` ```{container} output "hi" ``` ```` ````` `````{tab-item} reStructuredText ```{code-block} rst .. container:: thebe .. code-block:: r print("hi") .. container:: output "hi" ``` ````` `````` Defines a *parent container* in which we'll put both code and the output of the code. We'll use a `code-block` for the code, and another `container` node with our `output` class for the output. `sphinx-gallery` will detect the parent container because it has a `thebe` class. It will detect the `pre` block inside the container as the code, and it will detect the `
` block with the `output` class as the output. The result is that initializing Thebe *retains* the output until the cell is executed, like so: ```{thebe-button} ``` ````{container} thebe ```{code-block} r print("hi") ``` ```{container} output "hi" ``` ```` ## Setting the Kernel You can set the kernel that Thebe uses on a page by adding metadata to your page. To do so, add the following metadata to the top of your page: ``` thebe-kernel: ``` For example, this page had the following metadata in it: ``` thebe-kernel: ir ``` In addition, this website is configured to use the [Binder R example repository](https://github.com/binder-examples/r) for its environment. As a result, we can now run R code interactively with Thebe: ```{thebe-button} Launch thebe in R ``` ```{code-block} :class: thebe, thebe-init # Load ggplot - this will be automatically-run library(ggplot2) ``` ```{code-block} :class: thebe, thebe-init # create factors with value labels mtcars$gear <- factor(mtcars$gear,levels=c(3,4,5), labels=c("3gears","4gears","5gears")) mtcars$am <- factor(mtcars$am,levels=c(0,1), labels=c("Automatic","Manual")) mtcars$cyl <- factor(mtcars$cyl,levels=c(4,6,8), labels=c("4cyl","6cyl","8cyl")) ``` ```{code-block} :class: thebe, thebe-init # Kernel density plots for mpg # grouped by number of gears (indicated by color) qplot(mpg, data=mtcars, geom="density", fill=gear, alpha=I(.5), main="Distribution of Gas Milage", xlab="Miles Per Gallon", ylab="Density") ``` ```{code-block} :class: thebe # Scatterplot of mpg vs. hp for each combination of gears and cylinders # in each facet, transmittion type is represented by shape and color qplot(hp, mpg, data=mtcars, shape=am, color=am, facets=gear~cyl, size=I(3), xlab="Horsepower", ylab="Miles per Gallon") ``` ## Automatically running some code You can tag code blocks to run as soon as the kernel is ready (i.e., without any user input) by adding the `thebe-init` class to the code blocks. For example: `````{tab-set} ````{tab-item} MyST Markdown ```{code-block} :class: thebe, thebe-init print("hi") ``` ```` ````{tab-item} reStructuredText ```rst .. code-block:: :class: thebe, thebe-init print("hi") ``` ```` ````` These code blocks will be run automatically once the kernel is ready, and their outputs will be displayed below. (add-custom-button)= ## Adding your own button to start Thebe By default, Thebe encourages users to use the `thebe-button` directive to insert a thebe button into their documentation. However, you can add your own buttons wherever you wish. Simply ensure that an HTML element has this attribute: ```js onclick="initThebe()" ``` and it will be able to initialize Thebe on that page on its own. For example, here is the HTML for the Thebe button generated by the `thebe-button` directive: ```html ``` ## Choose a codemirror theme You can customize `sphinx-thebe` to use the codemirror theme of your choice. To do so, use the following configuration: ```python thebe_config = { "codemirror-theme": "" } ``` See [the CodeMirror theme demo](https://codemirror.net/demo/theme.html) for a list of themes that you can use, and what they look like. ## Load `thebe` automatically on all pages By default, `sphinx-thebe` will lazily load the JS/CSS from `thebe` when the `sphinx-thebe` initialization button is pressed. This means that no Javascript is loaded until a person explicitly tries to start thebe, which reduces page load times. If you want `thebe` to be loaded on every page, in an "eager" fashion, you may do so with the following configuration: ```python thebe_config = { "always_load": True } ``` ## Configuration reference Here's a reference of all of the configuration values avialable to `sphinx-thebe`. Many of these eventually make their was into the `thebe` configuration. You can find a [reference for `thebe` configuration here](https://thebe.readthedocs.io/en/latest/config_reference.html). ```python thebe_config = { "always_load": bool (default True) "repository_url": "", "repository_branch": "", "selector": "", "selector_input": "", "selector_output": "", } ``` sphinx-thebe-0.3.1/docs/contribute.md000066400000000000000000000047341456070231100175500ustar00rootroot00000000000000# Contribute to `sphinx-thebe` Thanks for your interest in contributing to `sphinx-thebe`, your contributions are welcome and appreciated 🎉. This page contains some information to help you get started. ## Design philosophy `sphinx-thebe` is designed to be a simple bridge between Sphinx and `thebe`. It should not add a lot of extra functionality on top of Thebe, beyond special-casing its configuration for Sphinx objects and its build system. It's primary goal is to make it pain-free to load `thebe.js` and apply it to websites generated by Sphinx with reasonable default choices. `sphinx-thebe` adds default configuration to support major Jupyter Notebook extensions in the Sphinx ecosystem. Currently this means [MyST-NB](https://myst-nb.readthedocs.io/), but in the future we'd also like to support [nbsphinx](https://nbsphinx.readthedocs.io/) by default. ## Contributing guide See the [ExecutableBooks developer guidelines](https://executablebooks.org/en/latest/contributing.html) for conventions and practices around developing `sphinx-thebe`. ## Repository structure `sphinx-thebe` is a lightweight extensions for Sphinx to activate and configure the [thebe javascript package](https://thebe.readthedocs.io/en/latest/). Most of the heavy lifting is done by that package, while this package mostly just integrates it with Sphinx and provides a button that can activate `thebe` under the hood. - The sphinx package is contained in `sphinx_thebe/`. The `__init__.py` file contains the code that activates and loads the proper CSS and JS when Sphinx is run. - CSS and Javascript assets are in `sphinx_thebe/_static`. These handle the activation of `thebe` on a page via a button-click, and also make minor modification to the page's DOM to make it work well with `thebe`. ## Code style The JavaScript and CSS assets for this repository follow the default values for [prettier](https://prettier.io/). Python code follows `black` and `pep8` as described in [the EBP contributing guide](https://executablebooks.org/en/latest/contributing.html#coding-style). ## Installation for development To install `sphinx-thebe` for development clone and install `sphinx-thebe` locally: ```bash git clone https://github.com/executablebooks/sphinx-thebe cd sphinx-thebe pip install -e .[sphinx,testing] ``` When you build Sphinx documentation with `sphinx-thebe` activated, it should now use the local development version. You can try this by building the `sphin-thebe` documentation: ```bash cd docs make html ```sphinx-thebe-0.3.1/docs/examples/000077500000000000000000000000001456070231100166565ustar00rootroot00000000000000sphinx-thebe-0.3.1/docs/examples/notebooks.md000066400000000000000000000027051456070231100212070ustar00rootroot00000000000000--- jupytext: formats: md:myst text_representation: extension: .md format_name: myst kernelspec: display_name: Python 3 language: python name: python3 --- # Jupyter Notebooks This page was written for [MyST-NB](https://myst-nb.readthedocs.io/). It demonstrates `sphinx-thebe`'s usage with Jupyter Notebooks. Activate Thebe by clicking the launch button below. You should then be able to run and edit the code cell in the notebook. ```{thebe-button} Launch thebe ``` The outputs should be displayed below, but they will be collected by `sphinx-thebe` when it is activated so that they are cleared when you first run the cell. ```{code-cell} import numpy as np import matplotlib.pyplot as plt # Create some fake data data = np.random.randn(3, 1000) # Create a figure fig, ax = plt.subplots() # Plot data ax.scatter(data[0], data[1], c=np.abs(data[2]), s=np.abs(data[2])*100) ``` ## Code style Thebe uses CodeMirror in the background, which uses different styles than pygments, which is used for static code syntax highlighting. The below code block is **static** and will not be converted with `thebe`. We include it in order to compare the active Thebe cell's syntax highlighting with an inactive cell. ``` import numpy as np import matplotlib.pyplot as plt # Create some fake data data = np.random.randn(3, 1000) # Create a figure fig, ax = plt.subplots() # Plot data ax.scatter(data[0], data[1], c=np.abs(data[2]), s=np.abs(data[2])*100) ``` sphinx-thebe-0.3.1/docs/index.md000066400000000000000000000026121456070231100164720ustar00rootroot00000000000000# sphinx-thebe ```{image} https://readthedocs.org/projects/sphinx-thebe/badge/?version=latest :target: https://sphinx-thebe.readthedocs.io/en/latest/?badge=latest :alt: Documentation ``` ```{image} https://img.shields.io/pypi/v/sphinx-thebe.svg :target: https://pypi.org/project/sphinx_thebe :alt: PyPi page ``` Make your code cells interactive with a kernel provided by [Thebe](http://thebe.readthedocs.org/) and [Binder](https://mybinder.org). It uses the excellent [thebe project](http://thebe.readthedocs.org/), and pre-configures `thebe` to be compatible with common Jupyter-related patterns in the Sphinx ecosystem, such as [MyST-NB](https://myst-nb.readthedocs.io/). For example, click the button below. Notice that the code block beneath becomes editable and runnable! ```{thebe-button} Launch thebe ``` ```{code-block} python :class: thebe print("hi") ``` See [](use.md) for more information about what you can do with `sphinx-thebe`. ## Install To install `sphinx-thebe` first clone and install it: ``` pip install sphinx-thebe ``` Then, add it to your Sphinx site's `conf.py` file: ``` extensions = [ ... "sphinx_thebe" ... ] ``` ## Configure and use For more information about how to configure `sphinx-thebe`, see [](configure.md). For more information on using `sphinx-thebe`, see [](use.md). ```{toctree} :hidden: use configure examples/notebooks contribute changelog ``` sphinx-thebe-0.3.1/docs/use.md000066400000000000000000000111071456070231100161560ustar00rootroot00000000000000# Use `sphinx-thebe` `sphinx-thebe` uses remote Jupyter kernels to execute your page's code and return the results, and [Binder](https://mybinder.org) to run the infrastructure for execution. You can do nearly anything with `sphinx-thebe` that you could do from within a Jupyter Notebook cell. ## Get started There are two steps to using `sphinx-thebe`. First, you must mark certain parts of your page as "ready for thebe". Next, you must insert a button onto the page to tell Thebe to initialize. ### Mark elements for thebe By default, thebe will be run on any elements in your documentation that contain the class `thebe` and that have a ` element underneath them. You can add code blocks like so: ```` ```{code-block} python :class: thebe print("hello world!") ``` ```` By default, `sphinx-thebe` will look for any HTML `
` element *inside* the code
block. Thebe will run on that element.

### Add an activate button to your page

Next, insert an "activate" button in your documentation with the following
directive:

````
```{thebe-button}
```
````

### An example

Here is what it looks like when you add the two snippets above in one example:

First the code block:

```{code-block} python
:class: thebe
print("hello world!")
```

And now the Thebe button:

```{thebe-button}
```

Clicking this button will activate Thebe on the page.
If you'd like to manually add your own button (e.g. with your own extension or theme), see [](add-custom-button).

### Customize your environment

By default, `sphinx-thebe` will serve the Binder environment for the
[jupyter-stacks-datascience repository](https://github.com/binder-examples/jupyter-stacks-datascience).
See [](configure.md) for information on choosing your own environment.

## A few examples

For example, click the button below (if you have not already clicked the button at the top of the page) and see the sections underneath to watch `sphinx-thebe` in action:

```{thebe-button} Launch examples below!
```

### Code outputs

```{code-block}
:class: thebe, thebe-init

import numpy as np
np.random.seed(1337)
data = np.random.randn(2, 100)
print(data[1, :10])
```

### DataFrames

```{code-block}
:class: thebe

import pandas as pd
df = pd.DataFrame(data.T, columns=["a", "b"])
df.head(5)
```

### PNG outputs

```{code-block}
:class: thebe
import matplotlib.pyplot as plt
plt.scatter(*data, c=data[0], s=200)
```

## Structure of a `thebe` cell

`sphinx-thebe` can work with two basic code cell structures:

1. **A single code cell**. In this case, there is just a single code cell that has content that should be made executable, like so:
   
   ```html
   
print("hi!")
``` 2. **An input/output cell**. Jupyter tools define code cells as a combination of inputs and outputs. For example: ```html
print("hi!")
...outputs here...
``` In this case, `sphinx-thebe` will treat the `cell_output` in a special fashion, so that it is cleared when you first run its corresponding input code. (use:selectors)= ## Selectors `sphinx-thebe` looks for by default By default `sphinx-thebe` will look for two types of code blocks to turn into interactive cells: - Cells that match a custom class you can add manually. It will match: - Whole cells: match `.thebe` - Cell inputs: match `pre` - Cell outputs: match `.output` - Cells that match [MyST-NB code cells](https://myst-nb.readthedocs.io/). It will match: - Whole cells: match `.cell` - Cell inputs: match `.cell_input` - Cell outputs: match `.cell_output` To customize the selectors that `sphinx-thebe` looks for, see [](configure:selector). ## Interactive outputs Interactive outputs work with `sphinx-thebe` **if their web dependencies are loaded**. Many interactive libraries assume that some javascript packages are pre-loaded in a notebook environment. For example, both Jupyter Lab and Notebook come bundled with `require.js`. To use visualization libraries that depend on this, **you must load these libraries on your own in Sphinx**. To do so, you can add the following to your `conf.py`: ```python def setup(app): app.add_js_file("url-of-package.js") ``` Note that some visualization libraries output *bundles of JavaScript/HTML* that will work out-of-the-box. You should consult the documentation of the library you wish to use in order to figure out how to configure it properly. See [the `thebe` examples](https://thebe.readthedocs.io/en/latest/) for examples of some popular visualization libraries. sphinx-thebe-0.3.1/pyproject.toml000066400000000000000000000035131456070231100170260ustar00rootroot00000000000000[build-system] requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" [project] name = "sphinx-thebe" authors = [ { name = "Executable Books Team", email = "executablebooks@gmail.com" }, ] maintainers = [ # TODO: Add an actual maintainer { name = "Executable Books Team", email = "executablebooks@gmail.com" }, ] description = "Integrate interactive code blocks into your documentation with Thebe and Binder." readme = "README.md" license = "MIT" license-files = { paths = ["LICENSE"] } requires-python = ">=3.8" classifiers = [ "Development Status :: 4 - Beta", "Framework :: Sphinx :: Extension", "Intended Audience :: Developers", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules", ] dynamic = ["version"] keywords = [ "development", "docutils", "sphinx", ] dependencies = [ "sphinx>=4", ] [project.urls] Homepage = "https://github.com/executablebooks/sphinx-thebe" [project.optional-dependencies] sphinx = [ "myst-nb", "sphinx-book-theme", "sphinx-copybutton", "sphinx-design", ] testing = [ "myst-nb>=1.0.0rc0", "sphinx-copybutton", "sphinx-design", "matplotlib", "pytest", "pytest-regressions", "beautifulsoup4", ] # TODO: Add pre-commits dev = [ "sphinx-thebe[testing]", ] [tool.hatch] version.source = "vcs" build.hooks.vcs.version-file = "src/sphinx_thebe/_version.py" [tool.pytest.ini_options] testpaths = [ "tests", ] sphinx-thebe-0.3.1/readthedocs.yml000066400000000000000000000002511456070231100171160ustar00rootroot00000000000000version: 2 build: os: "ubuntu-22.04" tools: python: "3.12" python: install: - method: pip path: . extra_requirements: - sphinx sphinx-thebe-0.3.1/src/000077500000000000000000000000001456070231100146775ustar00rootroot00000000000000sphinx-thebe-0.3.1/src/sphinx_thebe/000077500000000000000000000000001456070231100173575ustar00rootroot00000000000000sphinx-thebe-0.3.1/src/sphinx_thebe/__init__.py000066400000000000000000000177551456070231100215070ustar00rootroot00000000000000"""A sphinx extension to enable interactive computations using thebe.""" import json import os from pathlib import Path from textwrap import dedent from docutils.parsers.rst import Directive, directives from docutils import nodes from sphinx.util import logging from ._version import version as __version__ logger = logging.getLogger(__name__) THEBE_VERSION = "0.8.2" def st_static_path(app): static_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "_static")) app.config.html_static_path.append(static_path) def init_thebe_default_config(app, env, docnames): """Create a default config for fields that aren't given by the user.""" thebe_config = app.config.thebe_config defaults = { "always_load": False, "selector": ".thebe,.cell", "selector_input": "pre", "selector_output": ".output, .cell_output", } for key, val in defaults.items(): if key not in thebe_config: thebe_config[key] = val # Standardize types for certain values BOOL_KEYS = ["always_load"] for key in BOOL_KEYS: thebe_config[key] = _bool(thebe_config[key]) def _bool(b): if isinstance(b, bool): return b else: return b in ["true", "True"] def _do_load_thebe(doctree, config_thebe): """Decide whether to load thebe based on the page's context.""" # No doctree means there's no page content at all if not doctree: return False # If we aren't properly configured if not config_thebe: logger.warning( "[sphinx-thebe]: Didn't find `thebe_config` in conf.py, add to use thebe" ) return False return True def init_thebe_core(app, env, docnames): """Add scripts to configure thebe, and optionally add thebe itself. By default, defer loading the `thebe` JS bundle until bootstrap is called in order to speed up page load times. """ config_thebe = app.config["thebe_config"] # Add configuration variables THEBE_JS_URL = f"https://unpkg.com/thebe@{THEBE_VERSION}/lib/index.js" thebe_config_lines = [ f"const THEBE_JS_URL = \"{ THEBE_JS_URL }\"", f"const thebe_selector = \"{ app.config.thebe_config['selector'] }\"", f"const thebe_selector_input = \"{ app.config.thebe_config['selector_input'] }\"", f"const thebe_selector_output = \"{ app.config.thebe_config['selector_output'] }\"" ] app.add_js_file(None, body='; '.join(thebe_config_lines)) app.add_js_file(filename="sphinx-thebe.js", **{"async": "async"}) if config_thebe.get("always_load") is True: # If we've got `always load` on, then load thebe on every page. app.add_js_file(THEBE_JS_URL, **{"async": "async"}) def update_thebe_context(app, doctree, docname): """Add thebe config nodes to this doctree using page-dependent information.""" config_thebe = app.config["thebe_config"] # Skip modifying the doctree if we don't need to load thebe if not _do_load_thebe(doctree, config_thebe): return # Thebe configuration if config_thebe is True: config_thebe = {} if not isinstance(config_thebe, dict): raise ValueError( "thebe configuration must be `True` or a dictionary for configuration." ) codemirror_theme = config_thebe.get("codemirror-theme", "abcdef") # Choose the kernel we'll use meta = app.env.metadata.get(docname, {}) kernel_name = meta.get("thebe-kernel") if kernel_name is None: if meta.get("kernelspec"): if isinstance(meta.get("kernelspec"), str): kernel_name = json.loads(meta["kernelspec"]).get("name") else: kernel_name = meta["kernelspec"].get("name") else: kernel_name = "python3" # Codemirror syntax cm_language = kernel_name if "python" in cm_language: cm_language = "python" elif cm_language == "ir": cm_language = "r" # Create the URL for the kernel request repo_url = config_thebe.get( "repository_url", "https://github.com/binder-examples/jupyter-stacks-datascience", ) branch = config_thebe.get("repository_branch", "master") path_to_docs = config_thebe.get("path_to_docs", ".").strip("/") + "/" org, repo = _split_repo_url(repo_url) # Update the doctree with some nodes for the thebe configuration thebe_html_config = f""" """ # Append to the docutils doctree so it makes it into the build outputs doctree.append(nodes.raw(text=thebe_html_config, format="html")) doctree.append( nodes.raw(text=f"", format="html") ) def _split_repo_url(url): """Split a repository URL into an org / repo combination.""" if "github.com/" in url: end = url.split("github.com/")[-1] org, repo = end.split("/")[:2] else: logger.warning( f"[sphinx-thebe]: Currently Thebe repositories must be on GitHub, got {url}" ) org = repo = None return org, repo class ThebeButtonNode(nodes.Element): """Appended to the doctree by the ThebeButton directive Renders as a button to enable thebe on the page. If no ThebeButton directive is found in the document but thebe is enabled, the node is added at the bottom of the document. """ def __init__(self, rawsource="", *children, text="Run code", **attributes): super().__init__("", text=text) def html(self): text = self["text"] return ( ''.format(text=text) ) class ThebeButton(Directive): """Specify a button to activate thebe 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)] # Used to render an element node as HTML def visit_element_html(self, node): self.body.append(node.html()) raise nodes.SkipNode # Used for nodes that do not need to be rendered def skip(self, node): raise nodes.SkipNode def setup(app): logger.verbose("Adding copy buttons to code blocks...") # Add our static path app.connect("builder-inited", st_static_path) # Set default values for the configuration app.connect("env-before-read-docs", init_thebe_default_config) # Load the JS/CSS assets for thebe if needed app.connect("env-before-read-docs", init_thebe_core) # Update the doctree with thebe-specific information if needed app.connect("doctree-resolved", update_thebe_context) # configuration for this tool app.add_config_value("thebe_config", {}, "html") # override=True in case Jupyter Sphinx has already been loaded app.add_directive("thebe-button", ThebeButton, override=True) # Add relevant code to headers app.add_css_file("sphinx-thebe.css") # ThebeButtonNode is the button that activates thebe # 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), override=True, ) return { "version": __version__, "parallel_read_safe": True, "parallel_write_safe": True, } sphinx-thebe-0.3.1/src/sphinx_thebe/_static/000077500000000000000000000000001456070231100210055ustar00rootroot00000000000000sphinx-thebe-0.3.1/src/sphinx_thebe/_static/play-solid.svg000066400000000000000000000005231456070231100236030ustar00rootroot00000000000000sphinx-thebe-0.3.1/src/sphinx_thebe/_static/sphinx-thebe.css000066400000000000000000000042721456070231100241220ustar00rootroot00000000000000/* Thebelab Buttons */ .thebelab-button { z-index: 999; display: inline-block; padding: 0.35em 1.2em; margin: 0px 1px; border-radius: 0.12em; box-sizing: border-box; text-decoration: none; font-family: "Roboto", sans-serif; font-weight: 300; text-align: center; transition: all 0.2s; background-color: #dddddd; border: 0.05em solid white; color: #000000; } .thebelab-button:hover { border: 0.05em solid black; background-color: #fcfcfc; } .thebe-launch-button { height: 2.2em; font-size: 0.8em; border: 1px black solid; } /* Thebelab Cell */ .thebelab-cell pre { background: none; } .thebelab-cell .thebelab-input { padding-left: 1em; margin-bottom: 0.5em; margin-top: 0.5em; } .thebelab-cell .jp-OutputArea { margin-top: 0.5em; margin-left: 1em; } button.thebelab-button.thebelab-run-button { margin-left: 1.5em; margin-bottom: 0.5em; } /* Loading button */ button.thebe-launch-button div.spinner { float: left; margin-right: 1em; } /* Remove the spinner when thebelab is ready */ .thebe-launch-button.thebe-status-ready .spinner { display: none; } .thebe-launch-button span.status { font-family: monospace; font-weight: bold; } .thebe-launch-button.thebe-status-ready span.status { color: green; } .spinner { height: 2em; text-align: center; font-size: 0.7em; } .spinner > div { background-color: #f37726; height: 100%; width: 6px; display: inline-block; -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out; animation: sk-stretchdelay 1.2s infinite ease-in-out; } .spinner .rect2 { -webkit-animation-delay: -1.1s; animation-delay: -1.1s; } .spinner .rect3 { -webkit-animation-delay: -1s; animation-delay: -1s; } .spinner .rect4 { -webkit-animation-delay: -0.9s; animation-delay: -0.9s; } .spinner .rect5 { -webkit-animation-delay: -0.8s; animation-delay: -0.8s; } @-webkit-keyframes sk-stretchdelay { 0%, 40%, 100% { -webkit-transform: scaleY(0.4); } 20% { -webkit-transform: scaleY(1); } } @keyframes sk-stretchdelay { 0%, 40%, 100% { transform: scaleY(0.4); -webkit-transform: scaleY(0.4); } 20% { transform: scaleY(1); -webkit-transform: scaleY(1); } } sphinx-thebe-0.3.1/src/sphinx_thebe/_static/sphinx-thebe.js000066400000000000000000000100371456070231100237420ustar00rootroot00000000000000/** * Add attributes to Thebe blocks to initialize thebe properly */ var configureThebe = () => { // Load thebe config in case we want to update it as some point console.log("[sphinx-thebe]: Loading thebe config..."); thebe_config = document.querySelector("script[type=\"text/x-thebe-config\"]"); // If we already detect a Thebe cell, don't re-run if (document.querySelectorAll("div.thebe-cell").length > 0) { return; } // Update thebe buttons with loading message document.querySelectorAll(".thebe-launch-button").forEach((button) => { button.innerHTML = `
`; }); // Set thebe event hooks var thebeStatus; thebelab.on("status", function (evt, data) { console.log("Status changed:", data.status, data.message); const button = document.querySelector(".thebe-launch-button "); button.classList.replace( `thebe-status-${thebeStatus}`, `thebe-status-${data.status}` ) button.querySelector(".loading-text") .innerHTML = ( `Launching from mybinder.org: ${data.status}` ); // Now update our thebe status thebeStatus = data.status; // Find any cells with an initialization tag and ask thebe to run them when ready if (data.status === "ready") { var thebeInitCells = document.querySelectorAll( ".thebe-init, .tag_thebe-init" ); thebeInitCells.forEach((cell) => { console.log("Initializing Thebe with cell: " + cell.id); cell.querySelector(".thebelab-run-button").click(); }); } }); }; /** * Update the page DOM to use Thebe elements */ var modifyDOMForThebe = () => { // Find all code cells, replace with Thebe interactive code cells const codeCells = document.querySelectorAll(thebe_selector); codeCells.forEach((codeCell, index) => { const codeCellId = (index) => `codecell${index}`; codeCell.id = codeCellId(index); codeCellText = codeCell.querySelector(thebe_selector_input); codeCellOutput = codeCell.querySelector(thebe_selector_output); // Clean up the language to make it work w/ CodeMirror and add it to the cell dataLanguage = detectLanguage(kernelName); // Re-arrange the cell and add metadata if (codeCellText) { codeCellText.setAttribute("data-language", dataLanguage); codeCellText.setAttribute("data-executable", "true"); // If we had an output, insert it just after the `pre` cell if (codeCellOutput) { codeCellOutput.setAttribute("data-output", ""); codeCellText.insertAdjacentElement('afterend', codeCellOutput); } } // Remove sphinx-copybutton blocks, which are common in Sphinx codeCell.querySelectorAll("button.copybtn").forEach((el) => { el.remove(); }); }); }; var initThebe = () => { // Load thebe dynamically if it's not already loaded if (typeof thebelab === "undefined") { console.log("[sphinx-thebe]: Loading thebe from CDN..."); document.querySelector(".thebe-launch-button ").innerText = "Loading thebe from CDN..."; const script = document.createElement("script"); script.src = `${THEBE_JS_URL}`; document.head.appendChild(script); // Runs once the script has finished loading script.addEventListener("load", () => { console.log("[sphinx-thebe]: Finished loading thebe from CDN..."); configureThebe(); modifyDOMForThebe(); thebelab.bootstrap(); }); } else { console.log( "[sphinx-thebe]: thebe already loaded, not loading from CDN..." ); configureThebe(); modifyDOMForThebe(); thebelab.bootstrap(); } }; // Helper function to munge the language name var detectLanguage = (language) => { if (language.indexOf("python") > -1) { language = "python"; } else if (language === "ir") { language = "r"; } return language; }; sphinx-thebe-0.3.1/tests/000077500000000000000000000000001456070231100152525ustar00rootroot00000000000000sphinx-thebe-0.3.1/tests/test_build.py000066400000000000000000000110401456070231100177560ustar00rootroot00000000000000from bs4 import BeautifulSoup from pathlib import Path from subprocess import run from shutil import copy, copytree, rmtree import pytest path_tests = Path(__file__).parent.resolve() path_docs = path_tests.joinpath("..", "docs") @pytest.fixture(scope="session") def sphinx_build(tmpdir_factory): class SphinxBuild: path_tmp = Path(tmpdir_factory.mktemp("build")) path_tmp_docs = path_tmp.joinpath("docs") path_build = path_tmp_docs.joinpath("_build") path_html = path_build.joinpath("html") path_pg_index = path_html.joinpath("index.html") path_pg_config = path_html.joinpath("configure.html") path_pg_ntbk = path_html.joinpath("examples/notebooks.html") # Test using our documentation but the Alabaster theme # this avoids version pinning clashes with the Book Theme cmd_base = ["sphinx-build", ".", "_build/html", "-D", "html_theme=alabaster", "-a"] def copy(self, path=None): """Copy the specified book to our tests folder for building.""" if path is None: path = path_docs path_changelog = path / "../CHANGELOG.md" if not self.path_tmp_docs.exists(): copytree(path, self.path_tmp_docs) # Copy since it's loaded with an `include` directive copy(path_changelog, self.path_tmp) def build(self, cmd=None): """Build the test book""" cmd = [] if cmd is None else cmd output = run(self.cmd_base + cmd, cwd=self.path_tmp_docs, check=True, capture_output=True) self.output = output def clean(self): """Clean the _build folder so files don't clash with new tests.""" rmtree(self.path_build) return SphinxBuild() def test_sphinx_thebe(file_regression, sphinx_build): """Test building with thebe.""" sphinx_build.copy() # Basic build with defaults sphinx_build.build() # No build warnings that were raised by sphinx-thebe errors = list(sphinx_build.output.stderr.decode().split("\n")) assert all(["[sphinx-thebe]" not in ii for ii in errors]) # Testing index for base config soup_ix = BeautifulSoup(Path(sphinx_build.path_pg_index).read_text(), "html.parser") config = soup_ix("script", {"type": "text/x-thebe-config"}) assert len(config) == 1 config = config[0] file_regression.check(config.prettify(), basename="config_index", extension=".html") # Testing the configure page which has a custom kernel soup_conf = BeautifulSoup( Path(sphinx_build.path_pg_config).read_text(), "html.parser" ) config = soup_conf("script", {"type": "text/x-thebe-config"}) assert len(config) == 1 config = config[0] file_regression.check( config.prettify(), basename="config_custom", extension=".html" ) # Test launch buttons for custom text and structure launch_buttons = soup_conf.select(".thebe-launch-button") lb_text = "\n\n".join([ii.prettify() for ii in launch_buttons]) file_regression.check(lb_text, basename="launch_buttons", extension=".html") # Check for MyST-NB cell structure to make sure it stays the same # If this breaks, we'll need to update our default cell selectors soup_nb = BeautifulSoup( Path(sphinx_build.path_pg_ntbk).read_text(), "html.parser" ) cell = soup_nb.select(".cell")[0] # Remove the *content* of input/output since we only care about the DOM structure cell.select(".cell_input pre")[0].clear() cell.select(".cell_output")[0].clear() file_regression.check( cell.prettify(), basename="myst-nb__cell", extension=".html" ) def test_lazy_load(file_regression, sphinx_build): """Test building with thebe.""" sphinx_build.copy() url = "https://unpkg.com/thebe@0.8.2/lib/index.js" # URL to search for # Thebe JS should not be loaded by default (is loaded lazily) sphinx_build.build() soup_ix = BeautifulSoup(Path(sphinx_build.path_pg_index).read_text(), "html.parser") sources = [ii.attrs.get("src") for ii in soup_ix.select("script")] thebe_source = [ii for ii in sources if ii == url] assert len(thebe_source) == 0 # always_load=True should force this script to load on all pages sphinx_build.build(cmd=["-D", "thebe_config.always_load=true"]) soup_ix = BeautifulSoup(Path(sphinx_build.path_pg_index).read_text(), "html.parser") sources = [ii.attrs.get("src") for ii in soup_ix.select("script")] thebe_source = [ii for ii in sources if ii == url] assert len(thebe_source) == 1 sphinx-thebe-0.3.1/tests/test_build/000077500000000000000000000000001456070231100174105ustar00rootroot00000000000000sphinx-thebe-0.3.1/tests/test_build/config_custom.html000066400000000000000000000006431456070231100231400ustar00rootroot00000000000000 sphinx-thebe-0.3.1/tests/test_build/config_index.html000066400000000000000000000006551456070231100227400ustar00rootroot00000000000000 sphinx-thebe-0.3.1/tests/test_build/launch_buttons.html000066400000000000000000000003641456070231100233310ustar00rootroot00000000000000 sphinx-thebe-0.3.1/tests/test_build/myst-nb__cell.html000066400000000000000000000004051456070231100230240ustar00rootroot00000000000000

   
sphinx-thebe-0.3.1/tox.ini000066400000000000000000000030201456070231100154160ustar00rootroot00000000000000# To use tox, see https://tox.readthedocs.io # Simply pip or conda install tox # If you use conda, you may also want to install tox-conda # then run `tox` or `tox -- {pytest args}` # To run in parallel using `tox -p` (this does not appear to work for this repo) # To rebuild the tox environment, for example when dependencies change, use # `tox -r` # Note: if the following error is encountered: `ImportError while loading conftest` # then then deleting compiled files has been found to fix it: `find . -name \*.pyc -delete` [tox] envlist = py39-sphinx5 [testenv] usedevelop = true passenv = TERM # To make terminal coloring / other variables pass through [testenv:py{38,39}-sphinx{5,6}] extras = testing deps = sphinx5: sphinx>=5,<6 sphinx6: sphinx>=6,<7 commands = pytest {posargs} [testenv:docs-{update,clean}] extras = sphinx passenv = SKIP_CONTRIBUTE SKIP_TEAM whitelist_externals = rm echo commands = clean: rm -rf docs/_build sphinx-build -nW --keep-going -b {posargs:html} docs/ docs/_build/{posargs:html} commands_post = echo "open file://{toxinidir}/docs/_build/{posargs:html}/index.html" [testenv:docs-live] description = Build the documentation and launch browser extras = sphinx deps = sphinx-autobuild setenv = SKIP_CONTRIBUTE = true SKIP_TEAM = true commands = sphinx-autobuild \ --re-ignore _build/.* \ --re-ignore gallery.txt \ --re-ignore contributing.md \ --port 0 --open-browser \ -n -b {posargs:html} docs/ docs/_build/{posargs:html}