├── .gitignore ├── .travis.yml ├── CHANGELOG.rst ├── LICENSE ├── MANIFEST.in ├── README.rst ├── docs ├── Makefile ├── api │ └── sphinx_nbexamples.rst ├── apigen.bash ├── changelog.rst ├── conf.py ├── getting_started.rst ├── index.rst ├── installing.rst ├── linkgalleries.rst └── requirements.txt ├── examples ├── README.rst ├── Subgallery │ ├── README.rst │ ├── bokeh_example.png │ └── example_bokeh.ipynb ├── example_bash.ipynb ├── example_basic.ipynb └── images │ ├── bash.png │ └── select_metadata.png ├── postBuild ├── readthedocs.yml ├── requirements.txt ├── setup.cfg ├── setup.py ├── sphinx_nbexamples ├── __init__.py └── _static │ ├── example_gallery_styles.css │ └── no_image.png └── tests ├── sphinx_supp_py2 ├── conf.py ├── index.rst └── raw_examples │ ├── README.rst │ ├── example_bash.ipynb │ ├── example_code_example.ipynb │ ├── example_failure.ipynb │ ├── example_hello_world.ipynb │ ├── example_magics.ipynb │ ├── example_mpl_test.ipynb │ ├── example_mpl_test_figure_chosen.ipynb │ ├── example_tag_removal.ipynb │ ├── sub │ ├── README.md │ ├── example_supplementary_files.ipynb │ ├── example_toctree.ipynb │ └── test.txt │ ├── test2.txt │ ├── test_image.png │ └── thumb │ └── sphx_glr_test_image_thumb.png ├── sphinx_supp_py3 ├── conf.py ├── index.rst └── raw_examples │ ├── README.rst │ ├── example_bash.ipynb │ ├── example_code_example.ipynb │ ├── example_failure.ipynb │ ├── example_hello_world.ipynb │ ├── example_magics.ipynb │ ├── example_mpl_test.ipynb │ ├── example_mpl_test_figure_chosen.ipynb │ ├── example_tag_removal.ipynb │ ├── sub │ ├── README.md │ ├── example_supplementary_files.ipynb │ ├── example_toctree.ipynb │ └── test.txt │ ├── test2.txt │ ├── test_image.png │ └── thumb │ └── sphx_glr_test_image_thumb.png └── test_sphinx_nbexamples.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | docs/index.doctree 56 | docs/examples 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | # Spyder project 62 | .spyderproject 63 | 64 | # Example ipython notebook checkpoints 65 | *.ipynb_checkpoints/ 66 | .mypy_cache 67 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | # necessary for python 3.7, see https://github.com/travis-ci/travis-ci/issues/9815 4 | dist: xenial 5 | 6 | jobs: 7 | include: 8 | - python: "3.8" 9 | env: SPHINX_VERSION=2.4.* 10 | - python: "3.8" 11 | env: SPHINX_VERSION=3.0.* 12 | - python: "3.8" 13 | env: SPHINX_VERSION="" 14 | - python: "3.7" 15 | env: SPHINX_VERSION=1.7.* 16 | - python: "3.7" 17 | env: SPHINX_VERSION=1.8.* 18 | - python: "3.7" 19 | env: SPHINX_VERSION=2.0.* 20 | - python: "3.7" 21 | env: SPHINX_VERSION=2.1.* 22 | - python: "3.7" 23 | env: SPHINX_VERSION=2.2.* 24 | - python: "3.7" 25 | env: SPHINX_VERSION=2.3.* 26 | - python: "3.7" 27 | env: SPHINX_VERSION=2.4.* 28 | - python: "3.7" 29 | env: SPHINX_VERSION=3.0.* 30 | - python: "3.7" 31 | env: SPHINX_VERSION="" 32 | - python: "2.7" 33 | env: SPHINX_VERSION=1.5.* 34 | - python: "2.7" 35 | env: SPHINX_VERSION=1.6.* 36 | - python: "2.7" 37 | env: SPHINX_VERSION=1.7.* 38 | - python: "2.7" 39 | env: SPHINX_VERSION=1.8.* 40 | - python: "2.7" 41 | env: SPHINX_VERSION="" 42 | addons: 43 | apt: 44 | packages: 45 | - pandoc 46 | install: 47 | - PACKAGES="matplotlib pillow jupyter coveralls bash_kernel sphinx" 48 | - if [[ $SPHINX_VERSION != "" ]]; then PACKAGES="$PACKAGES==$SPHINX_VERSION"; fi 49 | - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then PACKAGES="$PACKAGES pathlib"; fi 50 | - echo $PACKAGES 51 | - pip install $PACKAGES 52 | - python -m bash_kernel.install # install bash kernel 53 | - python -m pip install . --no-deps --ignore-installed -vvv 54 | - pip freeze # show installed packages 55 | 56 | script: 57 | - coverage run --source=sphinx_nbexamples setup.py pytest 58 | 59 | after_success: 60 | coveralls 61 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | v0.4.0 2 | ====== 3 | This release adds support for non-python notebooks and the possibility to 4 | include links to binderhub-services (e.g. https://mybinder.org) in the docs. 5 | 6 | Added 7 | ----- 8 | - Thanks to the efforts of `@effigies `_ in 9 | `#3 `_, 10 | `#4 `_, 11 | `#5 `_, 12 | `#6 `_, 13 | `#7 `_, 14 | `#8 `_, and 15 | `#9 `_, we now support 16 | ``README.md`` files and non-python notebooks (see 17 | `the bash example in the docs `_) 18 | - sphinx-nbexamples now supports including a link to binder services with 19 | buttons like |binder| in the converted notebook. See the `docs on including a link to binder `_ 20 | 21 | .. |binder| image:: https://mybinder.org/badge_logo.svg 22 | :target: https://mybinder.org/v2/gh/Chilipp/sphinx-nbexamples/master 23 | 24 | Changed 25 | ------- 26 | - Bokeh has been marked as not working in the conversion of notebooks (see `#10 `_) 27 | - a bug with the thumbnails in the linkgalleries directive for sphinx>1.8.5 has 28 | been resolved (see `cc402b2 `_) 29 | 30 | v0.3.2 31 | ====== 32 | Fixed compatibility with nbconvert 5.5 33 | 34 | v0.3.1 35 | ====== 36 | This patch fixes some minor logging issues with sphinx >1.7.6 37 | 38 | Changed 39 | ------- 40 | * Minor compatibility fix for using the logger with Sphinx 41 | * Corrected typos `see PR #1 `__ 42 | 43 | v0.3.0 44 | ====== 45 | Added 46 | ----- 47 | * The removal of tags for the converted rst file. With 48 | `nbconvert 5.3 `__ 49 | we have the ``nbconvert.preprocessors.TagRemovePreprocessor`` available 50 | which gave the motivation to 4 new gallery configuration values, namely 51 | 52 | remove_all_outputs_tags: set 53 | Tags indicating cells for which the outputs are to be removed, 54 | matches tags in cell.metadata.tags. 55 | remove_cell_tags: set 56 | Tags indicating which cells are to be removed, matches tags in 57 | cell.metadata.tags. 58 | remove_input_tags: set 59 | Tags indicating cells for which input is to be removed, 60 | matches tags in cell.metadata.tags. 61 | remove_single_output_tags: set 62 | Tags indicating which individual outputs are to be removed, matches 63 | output i tags in cell.outputs[i].metadata.tags. 64 | 65 | The tags specified by these configuration values will be removed in the 66 | rst file. 67 | 68 | v0.2.2 69 | ====== 70 | Added 71 | ----- 72 | * The linkgalleries directive now can also insert links to the current 73 | sphinx project that is build 74 | 75 | Changed 76 | ------- 77 | * the linkgalleries directive uses the styles from the example_gallery_styles.css, 78 | i.e. the same style as it is used in the processed example gallery. 79 | 80 | 81 | v0.2.1 82 | ====== 83 | Changed 84 | ------- 85 | * Minor bug fix in option_spec of LinkGalleriesDirective 86 | 87 | v0.2.0 88 | ====== 89 | Added 90 | ----- 91 | * Added changelog 92 | * Added linkgalleries directive 93 | 94 | Changed 95 | ------- 96 | * The name of a thumbnail is now ``reference + '_thumb.png'`` where 97 | ``reference`` is the section label of the rst file 98 | * Reference labels are now all lower case 99 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Philipp S. Sommer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | include LICENSE 3 | include sphinx_nbexamples/_static/* 4 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ============================================================= 2 | Create an examples gallery with sphinx from Jupyter Notebooks 3 | ============================================================= 4 | 5 | .. image:: http://unmaintained.tech/badge.svg 6 | :target: http://unmaintained.tech/ 7 | :alt: No Maintenance Intended 8 | 9 | **This module is not maintained. Please use** nbsphinx_ **instead!** 10 | 11 | .. _nbsphinx: https://nbsphinx.readthedocs.io 12 | 13 | .. start-badges 14 | 15 | .. list-table:: 16 | :stub-columns: 1 17 | :widths: 10 90 18 | 19 | * - docs 20 | - |docs| 21 | * - tests 22 | - |travis| |requires| |coveralls| 23 | * - package 24 | - |version| |conda| |github| 25 | * - implementations 26 | - |supported-versions| |supported-implementations| 27 | 28 | .. |docs| image:: http://readthedocs.org/projects/sphinx-nbexamples/badge/?version=latest 29 | :alt: Documentation Status 30 | :target: http://sphinx-nbexamples.readthedocs.io/en/latest/?badge=latest 31 | 32 | .. |travis| image:: https://travis-ci.org/Chilipp/sphinx-nbexamples.svg?branch=master 33 | :alt: Travis 34 | :target: https://travis-ci.org/Chilipp/sphinx-nbexamples 35 | 36 | .. |coveralls| image:: https://coveralls.io/repos/github/Chilipp/sphinx-nbexamples/badge.svg?branch=master 37 | :alt: Coverage 38 | :target: https://coveralls.io/github/Chilipp/sphinx-nbexamples?branch=master 39 | 40 | .. |requires| image:: https://requires.io/github/Chilipp/sphinx-nbexamples/requirements.svg?branch=master 41 | :alt: Requirements Status 42 | :target: https://requires.io/github/Chilipp/sphinx-nbexamples/requirements/?branch=master 43 | 44 | .. |version| image:: https://img.shields.io/pypi/v/sphinx-nbexamples.svg?style=flat 45 | :alt: PyPI Package latest release 46 | :target: https://pypi.org/project/sphinx-nbexamples/ 47 | 48 | .. |conda| image:: https://anaconda.org/conda-forge/sphinx-nbexamples/badges/version.svg 49 | :alt: conda 50 | :target: https://anaconda.org/conda-forge/sphinx-nbexamples 51 | 52 | .. |github| image:: https://img.shields.io/github/release/Chilipp/sphinx-nbexamples.svg 53 | :target: https://github.com/Chilipp/sphinx-nbexamples/releases/latest 54 | :alt: Latest github release 55 | 56 | .. |supported-versions| image:: https://img.shields.io/pypi/pyversions/sphinx-nbexamples.svg?style=flat 57 | :alt: Supported versions 58 | :target: https://pypi.org/project/sphinx-nbexamples/ 59 | 60 | .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/sphinx-nbexamples.svg?style=flat 61 | :alt: Supported implementations 62 | :target: https://pypi.org/project/sphinx-nbexamples/ 63 | 64 | 65 | .. end-badges 66 | 67 | Welcome! Similarly to Oscar Najeras sphinx-gallery_ module, this module intends 68 | to create an example gallery for your documentation. However, we don't use 69 | python scripts, instead we create the example gallery out of a bunch of jupyter 70 | notebooks using nbconvert. 71 | 72 | This package can be used to 73 | 74 | 1. Put all the examples you prepared in different notebooks in an pictured 75 | gallery 76 | 2. use the same html (sphinx) scheme for your examples that you are using for 77 | your documentation 78 | 3. Include the example notebooks in an offline (pdf) documentation 79 | 4. Include not only the code, but also the link to required supplementary files 80 | 5. Include a link to the `Jupyter nbviewer`_ 81 | 82 | .. _Jupyter nbviewer: https://nbviewer.jupyter.org 83 | .. _sphinx-gallery: http://sphinx-gallery.readthedocs.org/en/latest/ 84 | 85 | 86 | 87 | Installation 88 | ============ 89 | Simply install it via ``pip``:: 90 | 91 | $ pip install sphinx-nbexamples 92 | 93 | Or you install it via:: 94 | 95 | $ python setup.py install 96 | 97 | from the `source on GitHub`_. 98 | 99 | 100 | .. _source on GitHub: https://github.com/Chilipp/sphinx-nbexamples 101 | 102 | 103 | Requirements 104 | ============ 105 | The package requires 106 | 107 | - Sphinx_>=1.3: The python library for generating automated documentation 108 | - jupyter_: The jupyter framework for jupyter notebooks. sphinx-nbexamples 109 | explicitly depends on 110 | 111 | - nbconvert_: For converting jupyter notebooks to RST 112 | - jupyter_client_: For managing the kernels 113 | - ipykernel_: For installing an ipython kernel and run the notebooks 114 | 115 | 116 | .. _Sphinx: http://www.sphinx-doc.org/en/stable 117 | .. _jupyter: http://jupyter.org/ 118 | .. _nbconvert: https://nbconvert.readthedocs.io 119 | .. _jupyter_client: https://jupyter-client.readthedocs.io 120 | .. _ipykernel: https://ipykernel.readthedocs.io 121 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/syplot.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/syplot.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/syplot" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/syplot" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /docs/api/sphinx_nbexamples.rst: -------------------------------------------------------------------------------- 1 | API Reference 2 | ============= 3 | 4 | .. automodule:: sphinx_nbexamples 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | 9 | -------------------------------------------------------------------------------- /docs/apigen.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # script to automatically generate the sphinx_nbexamples api documentation using 3 | # sphinx-apidoc and sed 4 | sphinx-apidoc -f -M -e -T -o api ../sphinx_nbexamples/ 5 | # replace chapter title in sphinx_nbexamples.rst 6 | sed -i '' -e 1,1s/.*/'API Reference'/ api/sphinx_nbexamples.rst 7 | sed -i '' -e 2,2s/.*/'============='/ api/sphinx_nbexamples.rst 8 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | .. _changelog: 2 | 3 | Changelog 4 | ********* 5 | 6 | .. include:: ../CHANGELOG.rst 7 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # sphinx-nbexamples documentation build configuration file, created by 4 | # sphinx-quickstart on Mon Jul 20 18:01:33 2015. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import sys 16 | import os 17 | import os.path as osp 18 | import re 19 | import six 20 | import sphinx_nbexamples 21 | 22 | # If extensions (or modules to document with autodoc) are in another directory, 23 | # add these directories to sys.path here. If the directory is relative to the 24 | # documentation root, use os.path.abspath to make it absolute, like shown here. 25 | sys.path.insert(0, os.path.abspath(osp.dirname(__file__))) 26 | 27 | # -- General configuration ------------------------------------------------ 28 | 29 | # If your documentation needs a minimal Sphinx version, state it here. 30 | #needs_sphinx = '1.0' 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = [ 36 | 'autodocsumm', 37 | 'sphinx.ext.doctest', 38 | 'sphinx.ext.intersphinx', 39 | 'sphinx.ext.extlinks', 40 | 'sphinx.ext.todo', 41 | 'sphinx.ext.viewcode', 42 | 'sphinx.ext.napoleon', 43 | 'sphinx_nbexamples', 44 | ] 45 | 46 | # Add any paths that contain templates here, relative to this directory. 47 | templates_path = ['_templates'] 48 | 49 | # on_rtd is whether we are on readthedocs.org, this line of code grabbed from 50 | # docs.readthedocs.org 51 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 52 | 53 | napoleon_use_admonition_for_examples = True 54 | 55 | # The suffix(es) of source filenames. 56 | # You can specify multiple suffix as a list of string: 57 | source_suffix = '.rst' 58 | 59 | not_document_data = 'sphinx_nbexamples.gallery_config' 60 | 61 | example_gallery_config = dict( 62 | dont_preprocess=['../examples/Subgallery/example_bokeh.ipynb'], 63 | insert_bokeh='0.12.1', 64 | urls='https://github.com/Chilipp/sphinx-nbexamples/blob/master/examples', 65 | binder_url='https://mybinder.org/v2/gh/Chilipp/sphinx-nbexamples/master?filepath=examples', 66 | ) 67 | process_examples = not osp.exists(osp.join(osp.dirname(__file__), 'examples')) 68 | 69 | 70 | if on_rtd: 71 | import subprocess as spr 72 | spr.call([sys.executable] + 73 | ('-m ipykernel install --user --name python3 ' 74 | '--display-name python3').split()) 75 | spr.call([sys.executable, '-m', 'bash_kernel.install']) 76 | 77 | 78 | # The encoding of source files. 79 | #source_encoding = 'utf-8-sig' 80 | 81 | # The master toctree document. 82 | master_doc = 'index' 83 | 84 | autodoc_default_flags = ['show_inheritance', 'autosummary'] 85 | autoclass_content = 'both' 86 | autodata_content = 'call' 87 | 88 | add_module_names = False 89 | 90 | # General information about the project. 91 | project = u'sphinx-nbexamples' 92 | copyright = u'2016, Philipp Sommer' 93 | author = u'Philipp Sommer' 94 | 95 | # The version info for the project you're documenting, acts as replacement for 96 | # |version| and |release|, also used in various other places throughout the 97 | # built documents. 98 | # 99 | # The short X.Y version. 100 | version = re.match('\d+\.\d+\.\d+', sphinx_nbexamples.__version__).group() 101 | # The full version, including alpha/beta/rc tags. 102 | release = sphinx_nbexamples.__version__ 103 | 104 | # The language for content autogenerated by Sphinx. Refer to documentation 105 | # for a list of supported languages. 106 | # 107 | # This is also used if you do content translation via gettext catalogs. 108 | # Usually you set "language" from the command line for these cases. 109 | language = None 110 | 111 | # There are two options for replacing |today|: either, you set today to some 112 | # non-false value, then it is used: 113 | #today = '' 114 | # Else, today_fmt is used as the format for a strftime call. 115 | #today_fmt = '%B %d, %Y' 116 | 117 | # List of patterns, relative to source directory, that match files and 118 | # directories to ignore when looking for source files. 119 | exclude_patterns = ['_build'] 120 | 121 | # The reST default role (used for this markup: `text`) to use for all 122 | # documents. 123 | #default_role = None 124 | 125 | # If true, '()' will be appended to :func: etc. cross-reference text. 126 | #add_function_parentheses = True 127 | 128 | # If true, the current module name will be prepended to all description 129 | # unit titles (such as .. function::). 130 | #add_module_names = True 131 | 132 | # If true, sectionauthor and moduleauthor directives will be shown in the 133 | # output. They are ignored by default. 134 | #show_authors = False 135 | 136 | # The name of the Pygments (syntax highlighting) style to use. 137 | pygments_style = 'sphinx' 138 | 139 | # A list of ignored prefixes for module index sorting. 140 | #modindex_common_prefix = [] 141 | 142 | # If true, keep warnings as "system message" paragraphs in the built documents. 143 | #keep_warnings = False 144 | 145 | # If true, `todo` and `todoList` produce output, else they produce nothing. 146 | todo_include_todos = True 147 | 148 | 149 | # -- Options for HTML output ---------------------------------------------- 150 | 151 | # The theme to use for HTML and HTML Help pages. See the documentation for 152 | # a list of builtin themes. 153 | 154 | if not on_rtd: # only import and set the theme if we're building docs locally 155 | import sphinx_rtd_theme 156 | html_theme = 'sphinx_rtd_theme' 157 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 158 | 159 | # Add any paths that contain custom static files (such as style sheets) here, 160 | # relative to this directory. They are copied after the builtin static files, 161 | # so a file named "default.css" will overwrite the builtin "default.css". 162 | html_static_path = ['_static'] 163 | 164 | # otherwise, readthedocs.org uses their theme by default, so no need to specify 165 | 166 | # Theme options are theme-specific and customize the look and feel of a theme 167 | # further. For a list of options available for each theme, see the 168 | # documentation. 169 | #html_theme_options = {} 170 | 171 | # Add any paths that contain custom themes here, relative to this directory. 172 | #html_theme_path = [] 173 | 174 | # The name for this set of Sphinx documents. If None, it defaults to 175 | # " v documentation". 176 | #html_title = None 177 | 178 | # A shorter title for the navigation bar. Default is the same as html_title. 179 | #html_short_title = None 180 | 181 | # The name of an image file (relative to this directory) to place at the top 182 | # of the sidebar. 183 | #html_logo = None 184 | 185 | # The name of an image file (within the static path) to use as favicon of the 186 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 187 | # pixels large. 188 | #html_favicon = None 189 | 190 | # Add any extra paths that contain custom files (such as robots.txt or 191 | # .htaccess) here, relative to this directory. These files are copied 192 | # directly to the root of the documentation. 193 | #html_extra_path = [] 194 | 195 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 196 | # using the given strftime format. 197 | #html_last_updated_fmt = '%b %d, %Y' 198 | 199 | # If true, SmartyPants will be used to convert quotes and dashes to 200 | # typographically correct entities. 201 | #html_use_smartypants = True 202 | 203 | # Custom sidebar templates, maps document names to template names. 204 | #html_sidebars = {} 205 | 206 | # Additional templates that should be rendered to pages, maps page names to 207 | # template names. 208 | #html_additional_pages = {} 209 | 210 | # If false, no module index is generated. 211 | #html_domain_indices = True 212 | 213 | # If false, no index is generated. 214 | #html_use_index = True 215 | 216 | # If true, the index is split into individual pages for each letter. 217 | #html_split_index = False 218 | 219 | # If true, links to the reST sources are added to the pages. 220 | #html_show_sourcelink = True 221 | 222 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 223 | #html_show_sphinx = True 224 | 225 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 226 | #html_show_copyright = True 227 | 228 | # If true, an OpenSearch description file will be output, and all pages will 229 | # contain a tag referring to it. The value of this option must be the 230 | # base URL from which the finished HTML is served. 231 | #html_use_opensearch = '' 232 | 233 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 234 | #html_file_suffix = None 235 | 236 | # Language to be used for generating the HTML full-text search index. 237 | # Sphinx supports the following languages: 238 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' 239 | # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' 240 | #html_search_language = 'en' 241 | 242 | # A dictionary with options for the search language support, empty by default. 243 | # Now only 'ja' uses this config value 244 | #html_search_options = {'type': 'default'} 245 | 246 | # The name of a javascript file (relative to the configuration directory) that 247 | # implements a search results scorer. If empty, the default will be used. 248 | #html_search_scorer = 'scorer.js' 249 | 250 | # Output file base name for HTML help builder. 251 | htmlhelp_basename = 'sphinx-nbexamplesdoc' 252 | 253 | # -- Options for LaTeX output --------------------------------------------- 254 | 255 | latex_elements = { 256 | # The paper size ('letterpaper' or 'a4paper'). 257 | #'papersize': 'letterpaper', 258 | 259 | # The font size ('10pt', '11pt' or '12pt'). 260 | #'pointsize': '10pt', 261 | 262 | # Additional stuff for the LaTeX preamble. 263 | #'preamble': '', 264 | 'preamble': '\setcounter{tocdepth}{10}' 265 | 266 | # Latex figure (float) alignment 267 | #'figure_align': 'htbp', 268 | } 269 | 270 | # Grouping the document tree into LaTeX files. List of tuples 271 | # (source start file, target name, title, 272 | # author, documentclass [howto, manual, or own class]). 273 | latex_documents = [ 274 | (master_doc, 'sphinx-nbexamples.tex', u'sphinx-nbexamples Documentation', 275 | u'Philipp Sommer', 'manual'), 276 | ] 277 | 278 | # The name of an image file (relative to this directory) to place at the top of 279 | # the title page. 280 | #latex_logo = None 281 | 282 | # For "manual" documents, if this is true, then toplevel headings are parts, 283 | # not chapters. 284 | #latex_use_parts = False 285 | 286 | # If true, show page references after internal links. 287 | #latex_show_pagerefs = False 288 | 289 | # If true, show URL addresses after external links. 290 | #latex_show_urls = False 291 | 292 | # Documents to append as an appendix to all manuals. 293 | #latex_appendices = [] 294 | 295 | # If false, no module index is generated. 296 | #latex_domain_indices = True 297 | 298 | 299 | # -- Options for manual page output --------------------------------------- 300 | 301 | # One entry per manual page. List of tuples 302 | # (source start file, name, description, authors, manual section). 303 | man_pages = [ 304 | (master_doc, 'sphinx-nbexamples', u'sphinx-nbexamples Documentation', 305 | [author], 1) 306 | ] 307 | 308 | # If true, show URL addresses after external links. 309 | #man_show_urls = False 310 | 311 | 312 | # -- Options for Texinfo output ------------------------------------------- 313 | 314 | # Grouping the document tree into Texinfo files. List of tuples 315 | # (source start file, target name, title, author, 316 | # dir menu entry, description, category) 317 | texinfo_documents = [ 318 | (master_doc, 'sphinx-nbexamples', u'sphinx-nbexamples Documentation', 319 | author, 'sphinx-nbexamples', 'Extending your autodoc API docs with a summary', 320 | 'Miscellaneous'), 321 | ] 322 | 323 | # Documents to append as an appendix to all manuals. 324 | #texinfo_appendices = [] 325 | 326 | # If false, no module index is generated. 327 | #texinfo_domain_indices = True 328 | 329 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 330 | #texinfo_show_urls = 'footnote' 331 | 332 | # If true, do not generate a @detailmenu in the "Top" node's menu. 333 | #texinfo_no_detailmenu = False 334 | 335 | 336 | # -- Options for Epub output ---------------------------------------------- 337 | 338 | # Bibliographic Dublin Core info. 339 | epub_title = project 340 | epub_author = author 341 | epub_publisher = author 342 | epub_copyright = copyright 343 | 344 | # The basename for the epub file. It defaults to the project name. 345 | #epub_basename = project 346 | 347 | # The HTML theme for the epub output. Since the default themes are not optimized 348 | # for small screen space, using the same theme for HTML and epub output is 349 | # usually not wise. This defaults to 'epub', a theme designed to save visual 350 | # space. 351 | #epub_theme = 'epub' 352 | 353 | # The language of the text. It defaults to the language option 354 | # or 'en' if the language is not set. 355 | #epub_language = '' 356 | 357 | # The scheme of the identifier. Typical schemes are ISBN or URL. 358 | #epub_scheme = '' 359 | 360 | # The unique identifier of the text. This can be a ISBN number 361 | # or the project homepage. 362 | #epub_identifier = '' 363 | 364 | # A unique identification for the text. 365 | #epub_uid = '' 366 | 367 | # A tuple containing the cover image and cover page html template filenames. 368 | #epub_cover = () 369 | 370 | # A sequence of (type, uri, title) tuples for the guide element of content.opf. 371 | #epub_guide = () 372 | 373 | # HTML files that should be inserted before the pages created by sphinx. 374 | # The format is a list of tuples containing the path and title. 375 | #epub_pre_files = [] 376 | 377 | # HTML files shat should be inserted after the pages created by sphinx. 378 | # The format is a list of tuples containing the path and title. 379 | #epub_post_files = [] 380 | 381 | # A list of files that should not be packed into the epub file. 382 | epub_exclude_files = ['search.html'] 383 | 384 | # The depth of the table of contents in toc.ncx. 385 | #epub_tocdepth = 3 386 | 387 | # Allow duplicate toc entries. 388 | #epub_tocdup = True 389 | 390 | # Choose between 'default' and 'includehidden'. 391 | #epub_tocscope = 'default' 392 | 393 | # Fix unsupported image types using the Pillow. 394 | #epub_fix_images = False 395 | 396 | # Scale large images. 397 | #epub_max_image_width = 0 398 | 399 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 400 | #epub_show_urls = 'inline' 401 | 402 | # If false, no index is generated. 403 | #epub_use_index = True 404 | 405 | # Example configuration for intersphinx: refer to the Python standard library. 406 | intersphinx_mapping = { 407 | 'sphinx': ('http://www.sphinx-doc.org/en/stable/', None), 408 | 'sphinx_nbexamples_doc': ( 409 | 'http://sphinx-nbexamples.readthedocs.io/en/latest/', None), 410 | 'psyplot': ('http://psyplot.readthedocs.io/en/latest/', None), 411 | 'nbconvert': ('https://nbconvert.readthedocs.io/en/latest/', None), 412 | } 413 | if six.PY3: 414 | intersphinx_mapping['python'] = ('https://docs.python.org/3.4/', None) 415 | else: 416 | intersphinx_mapping['python'] = ('https://docs.python.org/2.7/', None) 417 | 418 | 419 | extlinks = {'dudir': ('http://docutils.sourceforge.net/docs/ref/rst/' 420 | 'directives.html#%s', '')} 421 | 422 | 423 | # -- Extension interface ------------------------------------------------------ 424 | # taken from sphinx conf.py 425 | 426 | from sphinx import addnodes # noqa 427 | 428 | event_sig_re = re.compile(r'([a-zA-Z-]+)\s*\((.*)\)') 429 | 430 | 431 | def parse_event(env, sig, signode): 432 | m = event_sig_re.match(sig) 433 | if not m: 434 | signode += addnodes.desc_name(sig, sig) 435 | return sig 436 | name, args = m.groups() 437 | signode += addnodes.desc_name(name, name) 438 | plist = addnodes.desc_parameterlist() 439 | for arg in args.split(','): 440 | arg = arg.strip() 441 | plist += addnodes.desc_parameter(arg, arg) 442 | signode += plist 443 | return name 444 | 445 | 446 | def setup(app): 447 | from sphinx.util.docfields import GroupedField 448 | app.add_object_type('confval', 'confval', 449 | objname='configuration value', 450 | indextemplate='pair: %s; configuration value') 451 | fdesc = GroupedField('parameter', label='Parameters', 452 | names=['param'], can_collapse=True) 453 | app.add_object_type('event', 'event', 'pair: %s; event', parse_event, 454 | doc_field_types=[fdesc]) 455 | -------------------------------------------------------------------------------- /docs/getting_started.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: sphinx_nbexamples 2 | 3 | .. getting_started: 4 | 5 | Getting started 6 | =============== 7 | 8 | The module provides 2 additional configuration values. 9 | 10 | .. confval:: process_examples 11 | 12 | If ``True``, (the default), then the notebook files are converted to rst. 13 | 14 | 15 | .. confval:: example_gallery_config 16 | 17 | A dictionary with the parameters of the :class:`~sphinx_nbexamples.Gallery` 18 | class 19 | 20 | 21 | By default, the sphinx-nbexamples package converts your jupyter notebook in a 22 | specific directory into rst files to include it into your documentation. The 23 | :confval:`process_examples` configuration value controls this conversion. If 24 | switched off, no new files will be created. 25 | 26 | The second configuration value, :confval:`example_gallery_config`, can be used 27 | to control which examples are converted and how. They are simply the keyword 28 | arguments for the :class:`~sphinx_nbexamples.Gallery` class, but we will go in 29 | more detail in the next sections. But look into the :ref:`gallery_examples` 30 | section to see the outcome of the gallery. 31 | 32 | 33 | .. _nbstructure: 34 | 35 | Structure of the notebooks 36 | -------------------------- 37 | You are free to format your notebooks however you want. There are only 2 38 | important features since we convert the notebook to a single html page: 39 | 40 | 1. The first cell must be a Markdown cell containing a title 41 | 2. The first cell should include a short summary which will then be shown as 42 | the tooltip in the summary 43 | 44 | 45 | .. _basic_settings: 46 | 47 | Choosing the examples 48 | --------------------- 49 | The three keywords ``'examples_dirs'``, ``'gallery_dirs'``, and ``'pattern'`` can 50 | be used to select which notebooks shall be converted. The value for 51 | ``'examples_dirs'`` is the path to the directory where your raw jupyter 52 | notebooks are located. The ``'gallery_dirs'`` key on the other hand will point 53 | to the directories where the converted notebooks will be. You can also provide 54 | a list of example directories to create multiple galleries. 55 | 56 | Finally the ``'pattern'`` corresponds to the filename pattern for the example 57 | notebooks. Using the default pattern (``'example_.+.ipynb'``) implies, that 58 | all your notebooks in the ``'examples_dirs'`` starts with ``'example_'`` 59 | 60 | 61 | .. _preprocessing: 62 | 63 | Preprocessing the examples or not 64 | --------------------------------- 65 | When converting the examples, the default behaviour is to process the examples 66 | as well. This is a good possibility if you have an automatic building of the 67 | docs (e.g. using readthedocs.org_) to check that all your examples really work. 68 | However, you might not want this for all your notebooks, because it eventually 69 | takes a lot of time to process all the notebooks or it requires additional 70 | libraries. Therefore you can use the ``'preprocess'`` and ``'dont_preprocess'`` 71 | keys so select which examples are processed. 72 | 73 | 74 | .. _thumbnails: 75 | 76 | Choosing the thumbnail 77 | ---------------------- 78 | As you see in our :ref:`example gallery `, little thumbnails 79 | are created for each notebook. They can be chosen via 80 | 81 | 1. the ``'code_examples'`` key in the :confval:`example_gallery_config` 82 | 2. the ``'code_example'`` key in the meta data of the notebook 83 | 3. the ``'thumbnail_figures'`` key in the :confval:`example_gallery_config` 84 | 4. the key ``'thumbnail_figure'`` in the meta data of the notebook 85 | 5. automatically from the last matplotlib figure in the example notebook 86 | 87 | Hence, if you do not specify either ``'code_examples'`` nor 88 | ``'thumbnail_figure'`` (which is the default), it looks for a matplotlib 89 | plot in the notebook and uses this one. 90 | 91 | Otherwise, you have the possibility to give a small code sample via the 92 | ``'code_examples'`` or use the ``'thumbnail_figure'``. The latter can 93 | be the path to a picture (relative to the notebook) or a number to specify 94 | which figure of the matplotlib figures to use. 95 | 96 | 97 | .. _supp: 98 | 99 | Providing supplementary files 100 | ----------------------------- 101 | Sphinx-nbexamples automatically inserts links to download the jupyter notebook 102 | and the converted python file. However, often your example requires additional 103 | data files, etc. Here, you have two possibilities: 104 | 105 | 1. Specify the external data in the metadata of your notebook (see the 106 | :ref:`gallery_examples_example_basic.ipynb`) 107 | 2. Specify the external data in the ``'supplementary_files'`` key of your 108 | :confval:`example_gallery_config` specific for each notebook 109 | 110 | 111 | .. _nbviewer: 112 | 113 | Including a link to the nbviewer 114 | -------------------------------- 115 | If your notebooks are also published online, you can embed a link to the 116 | wonderful `jupyter nbviewer`_ in the documentation. You have multiple options 117 | here. You can either 118 | 119 | 1. specify the url for each notebook separately providing a mapping from 120 | notebook file to url in the ``'urls'`` option of the 121 | :confval:`example_gallery_config` 122 | 2. include a url item in the metadata of your notebook that points to 123 | the url of the notebook 124 | 3. specify one single url in the ``'urls'`` option of the 125 | :confval:`example_gallery_config` that will then be extended to the 126 | corresponding notebook path. For sphinx-nbexamples, this looks like:: 127 | 128 | example_gallery_config = { 129 | urls='https://github.com/Chilipp/sphinx-nbexamples/blob/master/examples', 130 | } 131 | 132 | .. _jupyter nbviewer: https://nbviewer.jupyter.org 133 | 134 | 135 | .. _binder: 136 | 137 | Including a link to the binder 138 | ------------------------------ 139 | `Jupyters binderhub`_ allows to run the example notebooks of your repository 140 | (see for example mybinder.org_). If your notebooks are also published online, 141 | sphinx-nbexamples can add a badge like |binder| in the documentation. 142 | 143 | You have multiple options here. You can either 144 | 145 | 1. specify the url for each notebook separately providing a mapping from 146 | notebook file to url in the ``'binder_urls'`` option of the 147 | :confval:`example_gallery_config` 148 | 2. include a binder_url item in the metadata of your notebook that points to 149 | the url of the notebook where it can be run interactively 150 | 3. specify one single url in the ``'binder_urls'`` option of the 151 | :confval:`example_gallery_config` that will then be extended to the 152 | corresponding notebook path. For sphinx-nbexamples at mybinder.org_, this 153 | looks like:: 154 | 155 | example_gallery_config = { 156 | 'binder_url': 'https://mybinder.org/v2/gh/Chilipp/sphinx-nbexamples/master?filepath=examples', 157 | } 158 | 159 | or for the `pangeo binder`_:: 160 | 161 | example_gallery_config = { 162 | 'binder_url': 'https://binder.pangeo.io/v2/gh/Chilipp/sphinx-nbexamples/master?filepath=examples', 163 | } 164 | 165 | See the binderhub service you use (e.g. mybinder.org_) for how to get this 166 | url for your repository. This will, e.g. for the 167 | :ref:`example_basic.ipynb ` notebook, 168 | translate into:: 169 | 170 | .. image:: https://mybinder.org/badge_logo.svg 171 | :target: https://mybinder.org/v2/gh/Chilipp/sphinx-nbexamples/master?filepath=examples/example_basic.ipynb 172 | 173 | .. |binder| image:: https://mybinder.org/badge_logo.svg 174 | :target: https://mybinder.org/v2/gh/Chilipp/sphinx-nbexamples/master 175 | 176 | .. _jupyters binderhub: https://binderhub.readthedocs.io/en/latest/ 177 | .. _mybinder.org: https://mybinder.org/ 178 | .. _pangeo binder: https://binder.pangeo.io/ 179 | 180 | 181 | .. _bokeh: 182 | 183 | Including bokeh 184 | --------------- 185 | 186 | .. warning:: 187 | 188 | Bokeh is not working for the latest version (see `#10 `_). PR's welcomed! 189 | 190 | Note that bokeh needs a special treatment, especially when using the scheme 191 | from readthedocs.org_, because it requires additional style sheets and javascript 192 | files. So, if you have bokeh plots in your documentation, we recommend to 193 | 194 | 1. use the :func:`bokeh.io.output_notebook` function in your examples 195 | 2. disable the preprocessing for this notebook using the ``'dont_preprocess'`` 196 | keyword 197 | 3. Give the bokeh version via the ``'insert_bokeh'`` keyword 198 | 199 | If you furthermore use widgets from bokeh, use the ``'insert_bokeh_widgets'`` 200 | keyword, too. 201 | 202 | .. note:: 203 | 204 | We cannot extract a thumbnail figure for bokeh notebooks. Hence, you should 205 | provide it by yourself (see :ref:`thumbnails`). 206 | 207 | .. _readthedocs.org: http://readthedocs.org 208 | 209 | .. _tag-removal: 210 | 211 | Removing cells 212 | -------------- 213 | Using notebook 5.0 and nbconvert 5.3 and higher, you can also tag cells 214 | and specify them for removal in the converted rst file. 215 | 216 | In the jupyter notebook click on 217 | :menuselection:`View --> Cell Toolbar --> Tags` and assign a tag to the cell 218 | you want to remove. You can then use one or more of the keywords 219 | 220 | remove_all_outputs_tags 221 | removes all outputs 222 | remove_cell_tags 223 | removes the entire cell 224 | remove_input_tags 225 | removes the input and only keeps the output 226 | remove_single_output_tags 227 | Removes an individual output 228 | 229 | in the :confval:`example_gallery_config`. See the :class:`Gallery` 230 | and :class:`nbconvert.preprocessors.Preprocessor` documentation for more 231 | information. 232 | 233 | To remove the entire cell, for example, set 234 | 235 | .. code-block:: python 236 | 237 | example_gallery_config = { 238 | 'remove_cell_tags': ['the-tag-of-the-cell-you-want-to-remove'], 239 | } 240 | 241 | in the ``'conf.py'`` of your docs. 242 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ============================================================= 2 | Create an examples gallery with sphinx from Jupyter Notebooks 3 | ============================================================= 4 | 5 | .. image:: http://unmaintained.tech/badge.svg 6 | :target: http://unmaintained.tech/ 7 | :alt: No Maintenance Intended 8 | 9 | **This module is not maintained. Please use** nbsphinx_ **instead!** 10 | 11 | .. _nbsphinx: https://nbsphinx.readthedocs.io 12 | 13 | .. start-badges 14 | .. only:: html and not epub 15 | 16 | .. list-table:: 17 | :stub-columns: 1 18 | :widths: 10 90 19 | 20 | * - docs 21 | - |docs| 22 | * - tests 23 | - |travis| |requires| |coveralls| 24 | * - package 25 | - |version| |conda| |github| 26 | * - implementations 27 | - |supported-versions| |supported-implementations| 28 | 29 | .. |docs| image:: https://readthedocs.org/projects/sphinx-nbexamples/badge/?version=latest 30 | :alt: Documentation Status 31 | :target: http://sphinx-nbexamples.readthedocs.io/en/latest/?badge=latest 32 | 33 | .. |travis| image:: https://travis-ci.org/Chilipp/sphinx-nbexamples.svg?branch=master 34 | :alt: Travis 35 | :target: https://travis-ci.org/Chilipp/sphinx-nbexamples 36 | 37 | .. |coveralls| image:: https://coveralls.io/repos/github/Chilipp/sphinx-nbexamples/badge.svg?branch=master 38 | :alt: Coverage 39 | :target: https://coveralls.io/github/Chilipp/sphinx-nbexamples?branch=master 40 | 41 | .. |requires| image:: https://requires.io/github/Chilipp/sphinx-nbexamples/requirements.svg?branch=master 42 | :alt: Requirements Status 43 | :target: https://requires.io/github/Chilipp/sphinx-nbexamples/requirements/?branch=master 44 | 45 | .. |version| image:: https://img.shields.io/pypi/v/sphinx-nbexamples.svg?style=flat 46 | :alt: PyPI Package latest release 47 | :target: https://pypi.org/project/sphinx-nbexamples/ 48 | 49 | .. |conda| image:: https://anaconda.org/conda-forge/sphinx-nbexamples/badges/version.svg 50 | :alt: conda 51 | :target: https://anaconda.org/conda-forge/sphinx-nbexamples 52 | 53 | .. |github| image:: https://img.shields.io/github/release/Chilipp/sphinx-nbexamples.svg 54 | :target: https://github.com/Chilipp/sphinx-nbexamples/releases/latest 55 | :alt: Latest github release 56 | 57 | .. |supported-versions| image:: https://img.shields.io/pypi/pyversions/sphinx-nbexamples.svg?style=flat 58 | :alt: Supported versions 59 | :target: https://pypi.org/project/sphinx-nbexamples/ 60 | 61 | .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/sphinx-nbexamples.svg?style=flat 62 | :alt: Supported implementations 63 | :target: https://pypi.org/project/sphinx-nbexamples/ 64 | 65 | 66 | .. end-badges 67 | 68 | Welcome! Similarly to Oscar Najeras sphinx-gallery_ module, this module intends 69 | to create an example gallery for your documentation. However, we don't use 70 | python scripts, instead we create the example gallery out of a bunch of jupyter 71 | notebooks using nbconvert. 72 | 73 | This package can be used to 74 | 75 | 1. Put all the examples you prepared in different notebooks in an pictured 76 | gallery 77 | 2. use the same html (sphinx) scheme for your examples that you are using for 78 | your documentation 79 | 3. Include the example notebooks in an offline (pdf) documentation 80 | 4. Include not only the code, but also the link to required supplementary files 81 | 5. Include a link to the `Jupyter nbviewer`_ 82 | 83 | .. _Jupyter nbviewer: https://nbviewer.jupyter.org 84 | .. _sphinx-gallery: http://sphinx-gallery.readthedocs.org/en/latest/ 85 | 86 | 87 | Content 88 | ------- 89 | 90 | .. toctree:: 91 | :maxdepth: 1 92 | 93 | installing 94 | getting_started 95 | linkgalleries 96 | examples/index 97 | api/sphinx_nbexamples 98 | changelog 99 | 100 | 101 | Installation 102 | ============ 103 | Simply install it via ``pip``:: 104 | 105 | $ pip install sphinx-nbexamples 106 | 107 | Or you install it via:: 108 | 109 | $ python setup.py install 110 | 111 | from the `source on GitHub`_. 112 | 113 | 114 | .. _source on GitHub: https://github.com/Chilipp/sphinx-nbexamples 115 | 116 | 117 | Requirements 118 | ============ 119 | The package requires 120 | 121 | - Sphinx_>=1.3: The python library for generating automated documentation 122 | - jupyter_: The jupyter framework for jupyter notebooks. sphinx-nbexamples 123 | explicitly depends on 124 | 125 | - nbconvert_: For converting jupyter notebooks to RST 126 | - jupyter_client_: For managing the kernels 127 | - ipykernel_: For installing an ipython kernel and run the notebooks 128 | 129 | 130 | .. _Sphinx: http://www.sphinx-doc.org/en/stable 131 | .. _jupyter: http://jupyter.org/ 132 | .. _nbconvert: https://nbconvert.readthedocs.io 133 | .. _jupyter_client: https://jupyter-client.readthedocs.io 134 | .. _ipykernel: https://ipykernel.readthedocs.io 135 | 136 | 137 | 138 | Indices and tables 139 | ================== 140 | 141 | * :ref:`genindex` 142 | * :ref:`modindex` 143 | * :ref:`search` 144 | -------------------------------------------------------------------------------- /docs/installing.rst: -------------------------------------------------------------------------------- 1 | .. _install: 2 | 3 | Installation 4 | ============ 5 | 6 | How to install 7 | -------------- 8 | 9 | Installation using pip 10 | ^^^^^^^^^^^^^^^^^^^^^^ 11 | If you do not want to use conda for managing your python packages, you can also 12 | use the python package manager ``pip`` and install via:: 13 | 14 | $ pip install sphinx-nbexamples 15 | 16 | If you want to preprocess your notebooks before including them in the 17 | documentation, you might also have to install the ipykernel module via:: 18 | 19 | $ pip install ipykernel 20 | 21 | and register the kernel depending on the kernel name in your notebooks via:: 22 | 23 | $ python -m ipykernel install --user --name --display-name 24 | 25 | where the ```` should be replaced by the kernel name as it is used 26 | in the examples. 27 | 28 | .. note:: 29 | 30 | If your examples require additional packages, you of course have to install 31 | them by yourself 32 | 33 | Installation from source 34 | ^^^^^^^^^^^^^^^^^^^^^^^^ 35 | You can as well install the package from the github_ via:: 36 | 37 | $ python setup.py install 38 | 39 | 40 | Usage on readthedocs.org_ 41 | ------------------------- 42 | When building your documentation on readthedocs.org_, you can either disable 43 | the preprocessing of the notebooks via the :confval:`process_examples` 44 | configuration value, e.g. via:: 45 | 46 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 47 | process_examples = not on_rtd 48 | 49 | or:: 50 | 51 | example_gallery_config['dont_preprocess'] = on_rtd 52 | 53 | or you make sure that the virtual environment installs ipykernel and all the 54 | other necessary packages for your examples and include:: 55 | 56 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 57 | if on_rtd: 58 | import subprocess as spr 59 | spr.call([sys.executable] + 60 | ('-m ipykernel install --user --name python3 ' 61 | '--display-name python3').split()) 62 | 63 | in your ``'conf.py'`` of your sphinx documentation. Change ``'python3'`` to 64 | the kernel name you are using in your examples. 65 | 66 | .. _readthedocs.org: http://readthedocs.org 67 | 68 | 69 | Running the tests 70 | ----------------- 71 | We use pytest_ for our testing, so simply install it and run:: 72 | 73 | $ py.test 74 | 75 | or in the downloaded directory from github_ run 76 | 77 | $ python setup.py pytest 78 | 79 | Building the docs 80 | ----------------- 81 | To build the docs, check out the github_ repository and install the 82 | requirements in ``'docs/environment.yml'``. The easiest way to do this is via 83 | anaconda by typing:: 84 | 85 | $ conda env create -f docs/environment.yml 86 | $ source activate sphinx_nbexamples_docs 87 | $ conda install ipykernel sphinx_rtd_theme 88 | 89 | Then build the docs via:: 90 | 91 | $ cd docs 92 | $ make html 93 | 94 | .. _github: https://github.com/Chilipp/sphinx-nbexamples 95 | .. _pytest: https://pytest.org/latest/contents.html 96 | -------------------------------------------------------------------------------- /docs/linkgalleries.rst: -------------------------------------------------------------------------------- 1 | .. _linking-galleries: 2 | 3 | Linking to other galleries 4 | ========================== 5 | You can insert the links to the example galleries in other projects using the 6 | :rst:dir:`linkgalleries` directive. This will insert all the thumbnails and the 7 | titles of the examples in a list. You can find an example 8 | :ref:`below `. 9 | 10 | 11 | .. rst:directive:: linkgalleries 12 | 13 | Insert links to other example galleries generated with the 14 | sphinx-nbexamples extension. 15 | 16 | The directive takes no arguments and the options are the same as for the 17 | :dudir:`figure` directive. By default, we use a width of 160px and the 18 | ``align`` parameter is set to ``'left'``. 19 | 20 | Each line of the content for this package must be the name of a package as 21 | it is registered in the :confval:`intersphinx_mapping` configuration value 22 | by the :mod:`sphinx.ext.intersphinx` extension. Optionally you can also 23 | provide the folder for the examples. 24 | 25 | .. warning:: 26 | 27 | This directive only works well for examples that have a thumbnail 28 | associated with them, i.e. not with code examples 29 | (see :ref:`thumbnails`). 30 | 31 | .. rubric:: Examples 32 | 33 | To insert links to the examples of the 34 | :ref:`sphinx-nbexamples gallery ` you can either 35 | use 36 | 37 | .. code-block:: rst 38 | 39 | .. linkgalleries:: 40 | 41 | sphinx_nbexamples 42 | 43 | or more explicit 44 | 45 | .. code-block:: rst 46 | 47 | .. linkgalleries:: 48 | 49 | sphinx_nbexamples examples 50 | 51 | 52 | .. _linked-gallery-example: 53 | 54 | Linked gallery example 55 | ---------------------- 56 | 57 | The outputs of 58 | 59 | .. code-block:: rst 60 | 61 | .. linkgalleries:: 62 | 63 | psyplot 64 | 65 | are links to the examples in 66 | :ref:`psyplots example gallery `. 67 | 68 | This then transforms to 69 | 70 | .. only:: html 71 | 72 | .. linkgalleries:: 73 | 74 | psyplot 75 | 76 | .. only:: latex 77 | 78 | .. linkgalleries:: 79 | :width: 160 80 | 81 | psyplot 82 | 83 | In the ``conf.py`` script, the :confval:`intersphinx_mapping` configuration 84 | value then looks like 85 | 86 | .. code-block:: python 87 | 88 | intersphinx_mapping = { 89 | 'psyplot': ('http://psyplot.readthedocs.io/en/latest/', None), 90 | } 91 | 92 | We can also insert links into the library of the current project by just 93 | inserting the name of the project. 94 | 95 | In our case (``sphinx-nbexamples``) this then looks like 96 | 97 | .. only:: html 98 | 99 | .. linkgalleries:: 100 | 101 | sphinx-nbexamples 102 | 103 | .. only:: latex 104 | 105 | .. linkgalleries:: 106 | :width: 160 107 | 108 | sphinx-nbexamples 109 | 110 | The :rst:dir:`linkgalleries` directive also accepts multiple packages, e.g. 111 | 112 | .. code-block:: rst 113 | 114 | .. linkgalleries:: 115 | 116 | psyplot 117 | sphinx-nbexamples 118 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib 2 | bokeh 3 | seaborn 4 | ipython 5 | nbconvert 6 | sphinx 7 | jupyter_client 8 | ipykernel 9 | autodocsumm 10 | bash_kernel 11 | -------------------------------------------------------------------------------- /examples/README.rst: -------------------------------------------------------------------------------- 1 | Examples for the sphinx-nbexamples package 2 | ========================================== 3 | 4 | Those examples shall just show you how you might use the sphinx-nbexamples 5 | package. All those examples are generated automatically from the `examples 6 | directory`_ of the package. But you can also download them from the given 7 | notebook. 8 | 9 | .. _examples directory: https://github.com/Chilipp/sphinx-nbexamples 10 | -------------------------------------------------------------------------------- /examples/Subgallery/README.rst: -------------------------------------------------------------------------------- 1 | Examples in a subfolder 2 | ======================= 3 | 4 | Just some examples in a subfolder. Important is, that you have a ``README.rst`` file in this folder. You can also have more subfolders with examples in it. 5 | -------------------------------------------------------------------------------- /examples/Subgallery/bokeh_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/examples/Subgallery/bokeh_example.png -------------------------------------------------------------------------------- /examples/example_bash.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "# Bash example\n", 9 | "\n", 10 | "\n", 11 | "This example notebook uses a Bash kernel.\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 1, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "# A basic hello, world in Bash\n", 21 | "\n", 22 | "function hello {\n", 23 | " echo hello, world\n", 24 | "}" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 2, 30 | "metadata": {}, 31 | "outputs": [ 32 | { 33 | "name": "stdout", 34 | "output_type": "stream", 35 | "text": [ 36 | "hello, world\n" 37 | ] 38 | } 39 | ], 40 | "source": [ 41 | "hello" 42 | ] 43 | } 44 | ], 45 | "metadata": { 46 | "kernelspec": { 47 | "display_name": "Bash", 48 | "language": "bash", 49 | "name": "bash" 50 | }, 51 | "language_info": { 52 | "codemirror_mode": "shell", 53 | "file_extension": ".sh", 54 | "mimetype": "text/x-sh", 55 | "name": "bash" 56 | }, 57 | "thumbnail_figure": "images/bash.png" 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /examples/images/bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/examples/images/bash.png -------------------------------------------------------------------------------- /examples/images/select_metadata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/examples/images/select_metadata.png -------------------------------------------------------------------------------- /postBuild: -------------------------------------------------------------------------------- 1 | python -m bash_kernel.install 2 | -------------------------------------------------------------------------------- /readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | # Build all formats 4 | formats: 5 | - htmlzip 6 | - epub 7 | python: 8 | version: 3.7 9 | install: 10 | - requirements: docs/requirements.txt 11 | - method: pip 12 | path: . 13 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib 2 | bokeh 3 | seaborn 4 | bash_kernel 5 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | # content of pytest.ini 2 | # (or tox.ini or setup.cfg) 3 | [tool:pytest] 4 | addopts = -v 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | import sys 3 | 4 | needs_pytest = {'pytest', 'test', 'ptr'}.intersection(sys.argv) 5 | pytest_runner = ['pytest-runner'] if needs_pytest else [] 6 | 7 | 8 | def readme(): 9 | with open('README.rst') as f: 10 | return f.read() 11 | 12 | 13 | setup(name='sphinx-nbexamples', 14 | version='0.4.1', 15 | description=( 16 | 'Create an examples gallery with sphinx from Jupyter Notebooks'), 17 | long_description=readme(), 18 | long_description_content_type="text/x-rst", 19 | classifiers=[ 20 | 'Development Status :: 7 - Inactive', 21 | 'Intended Audience :: Developers', 22 | 'Topic :: Documentation', 23 | 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', 24 | 'Programming Language :: Python :: 2', 25 | 'Programming Language :: Python :: 2.7', 26 | 'Programming Language :: Python :: 3', 27 | 'Programming Language :: Python :: 3.2', 28 | 'Programming Language :: Python :: 3.3', 29 | 'Programming Language :: Python :: 3.4', 30 | 'Programming Language :: Python :: 3.5', 31 | 'Operating System :: OS Independent', 32 | ], 33 | keywords=('sphinx sphinx-gallery examples documentation notebook ipython' 34 | ' jupyter nbconvert nbsphinx'), 35 | project_urls={ 36 | 'Documentation': 'https://sphinx-nbexamples.readthedocs.io', 37 | }, 38 | url='https://github.com/Chilipp/sphinx-nbexamples', 39 | author='Philipp S. Sommer', 40 | author_email='philipp.sommer@hereon.de', 41 | license="MIT", 42 | packages=find_packages(exclude=['docs', 'tests*', 'examples']), 43 | package_data={'sphinx_nbexamples': ['sphinx_nbexamples/_static/*']}, 44 | include_package_data=True, 45 | install_requires=[ 46 | 'sphinx', 47 | 'ipython', 48 | 'nbconvert', 49 | 'Pillow', 50 | 'jupyter_client', 51 | 'ipykernel', 52 | ], 53 | setup_requires=pytest_runner, 54 | tests_require=['pytest'], 55 | zip_safe=False) 56 | -------------------------------------------------------------------------------- /sphinx_nbexamples/__init__.py: -------------------------------------------------------------------------------- 1 | """Create an example gallery out of a bunch of ipython notebooks 2 | 3 | This sphinx extension extracts the ipython notebooks in a given folder to 4 | create an example gallery. It provides the follwing configuration values 5 | for you sphinx configuration file ``'conf.py'``: 6 | 7 | .. autosummary:: 8 | 9 | process_examples 10 | gallery_config 11 | 12 | Notes 13 | ----- 14 | This module was motivated by the 15 | `sphinx-gallery `__ module 16 | by Oscar Najera and in fact uses parts of it's html template for including the 17 | thumbnails and the download containers""" 18 | from __future__ import division 19 | import datetime as dt 20 | import os 21 | import os.path as osp 22 | import re 23 | import six 24 | from itertools import chain 25 | import nbconvert 26 | import nbformat 27 | from shutil import copyfile 28 | from copy import deepcopy 29 | import warnings 30 | try: 31 | from sphinx.util import logging 32 | logger = logging.getLogger(__name__) 33 | except (ImportError, AttributeError): 34 | import logging 35 | logger = logging.getLogger(__name__) 36 | 37 | import sphinx 38 | 39 | try: 40 | warn = logger.warn 41 | except AttributeError: # necessary for python 2.7 42 | warn = logger.warning 43 | 44 | import subprocess as spr 45 | from docutils.parsers.rst import Directive 46 | from docutils.parsers.rst import directives 47 | from docutils.statemachine import ViewList 48 | from docutils import nodes 49 | 50 | if six.PY2: 51 | from itertools import imap as map 52 | 53 | 54 | try: 55 | from cyordereddict import OrderedDict 56 | except ImportError: 57 | try: 58 | from collections import OrderedDict 59 | except ImportError: 60 | from ordereddict import OrderedDict 61 | 62 | __author__ = "Philipp S. Sommer" 63 | __copyright__ = "2016 - 2021, Philipp S. Sommer" 64 | 65 | __credits__ = ["Philipp S. Sommer"] 66 | __license__ = "MIT" 67 | 68 | __maintainer__ = "Philipp S. Sommer" 69 | __email__ = "philipp.sommer@hereon.de" 70 | 71 | __status__ = "Production" 72 | 73 | __version__ = '0.4.1' 74 | 75 | warnings.warn( 76 | "sphinx-nbexamples is no longer maintained! We recommend to use nbsphinx " 77 | "instead (https://nbsphinx.readthedocs.io/).", 78 | DeprecationWarning, 79 | ) 80 | 81 | if nbconvert.__version__ < '5.0': 82 | code_blocks = re.compile(r'\.\. code:: python\n(?s)(.+?)(?=\n\S+|$)') 83 | inner_code_blocks = re.compile( 84 | r'(?<=.. code:: python\n)(?s)(.+?)(?=\n\S+|$)') 85 | else: 86 | code_blocks = re.compile(r'\.\. code:: ipython\d\n(?s)(.+?)(?=\n\S+|$)') 87 | inner_code_blocks = re.compile( 88 | r'(?<=.. code:: ipython\d\n)(?s)(.+?)(?=\n\S+|$)') 89 | magic_patt = re.compile(r'(?m)^(\s+)(%.*\n)') 90 | 91 | 92 | def isstring(s): 93 | return isinstance(s, six.string_types) 94 | 95 | 96 | def create_dirs(*dirs): 97 | for d in dirs: 98 | if os.path.exists(d) and not os.path.isdir(d): 99 | raise IOError("Could not create directory %s because an " 100 | "ordinary file with that name exists already!") 101 | elif not os.path.exists(d): 102 | os.makedirs(d) 103 | 104 | 105 | def nbviewer_link(url): 106 | """Return the link to the Jupyter nbviewer for the given notebook url""" 107 | if six.PY2: 108 | from urlparse import urlparse as urlsplit 109 | else: 110 | from urllib.parse import urlsplit 111 | info = urlsplit(url) 112 | domain = info.netloc 113 | url_type = 'github' if domain == 'github.com' else 'url' 114 | return 'https://nbviewer.jupyter.org/%s%s' % (url_type, info.path) 115 | 116 | 117 | NOIMAGE = os.path.join(os.path.dirname(__file__), '_static', 'no_image.png') 118 | 119 | 120 | class NotebookProcessor(object): 121 | """Class to run process one ipython notebook and create the necessary files 122 | """ 123 | 124 | #: base string for downloading the python file and ipython notebook 125 | CODE_DOWNLOAD = """ 126 | 127 | .. only:: html 128 | 129 | .. container:: sphx-glr-download 130 | 131 | **Download {language} script:** :download:`{script}` 132 | 133 | **Download Jupyter notebook:** :download:`{nbfile}` 134 | """ 135 | 136 | #: base string for viewing the notebook in the jupyter nbviewer 137 | CODE_DOWNLOAD_NBVIEWER = CODE_DOWNLOAD + """ 138 | **View the notebook in the** `Jupyter nbviewer <{url}>`__ 139 | """ 140 | 141 | #: base string for viewing the notebook in the binder 142 | CODE_RUN_BINDER = """ 143 | **Run this example interactively:** |binder| 144 | 145 | .. |binder| image:: https://mybinder.org/badge_logo.svg 146 | :target: {url} 147 | """ 148 | 149 | #: base string for downloading supplementary data 150 | DATA_DOWNLOAD = """ 151 | 152 | .. only:: html 153 | 154 | .. container:: sphx-glr-download 155 | 156 | **Download supplementary data:** %s 157 | """ 158 | 159 | #: base string for creating the thumbnail 160 | THUMBNAIL_TEMPLATE = """ 161 | .. raw:: html 162 | 163 |
164 | 165 | .. only:: html 166 | 167 | .. figure:: /{thumbnail} 168 | 169 | :ref:`{ref_name}` 170 | 171 | .. raw:: html 172 | 173 |
174 | """ 175 | 176 | CODE_TEMPLATE = """ 177 | .. raw:: html 178 | 179 |
180 | 181 | .. only:: html 182 | 183 | .. code:: python 184 | 185 | {code} 186 | 187 | :ref:`{ref_name}` 188 | 189 | .. raw:: html 190 | 191 |
192 | """ 193 | 194 | BOKEH_STYLE_SHEET = ( 195 | "http://cdn.pydata.org/bokeh/release/bokeh-{version}.min.css") 196 | 197 | BOKEH_JS = ( 198 | "http://cdn.pydata.org/bokeh/release/bokeh-{version}.min.js") 199 | 200 | _BOKEH_TEMPLATE = """ 201 | .. raw:: html 202 | 205 | 206 | 207 | """ 208 | BOKEH_TEMPLATE = _BOKEH_TEMPLATE % (BOKEH_STYLE_SHEET, BOKEH_JS) 209 | 210 | BOKEH_WIDGETS_STYLE_SHEET = ( 211 | "http://cdn.pydata.org/bokeh/release/bokeh-{version}.min.css") 212 | 213 | BOKEH_WIDGETS_JS = ( 214 | "http://cdn.pydata.org/bokeh/release/bokeh-{version}.min.js") 215 | 216 | BOKEH_WIDGETS_TEMPLATE = _BOKEH_TEMPLATE % (BOKEH_WIDGETS_STYLE_SHEET, 217 | BOKEH_WIDGETS_JS) 218 | 219 | #: Path to the thumbnail image 220 | thumb_file = NOIMAGE 221 | 222 | #: Paths to the pictures of this notebook 223 | pictures = [] 224 | 225 | @property 226 | def thumbnail_div(self): 227 | """The string for creating the thumbnail of this example""" 228 | return self.THUMBNAIL_TEMPLATE.format( 229 | snippet=self.get_description()[1], thumbnail=self.thumb_file, 230 | ref_name=self.reference) 231 | 232 | @property 233 | def code_div(self): 234 | """The string for creating a code example for the gallery""" 235 | code_example = self.code_example 236 | if code_example is None: 237 | return None 238 | return self.CODE_TEMPLATE.format( 239 | snippet=self.get_description()[1], code=code_example, 240 | ref_name=self.reference) 241 | 242 | @property 243 | def code_example(self): 244 | """The code example out of the notebook metadata""" 245 | if self._code_example is not None: 246 | return self._code_example 247 | return getattr(self.nb.metadata, 'code_example', None) 248 | 249 | @property 250 | def supplementary_files(self): 251 | """The supplementary files of this notebook""" 252 | if self._supplementary_files is not None: 253 | return self._supplementary_files 254 | return getattr(self.nb.metadata, 'supplementary_files', None) 255 | 256 | @property 257 | def other_supplementary_files(self): 258 | """The supplementary files of this notebook""" 259 | if self._other_supplementary_files is not None: 260 | return self._other_supplementary_files 261 | return getattr(self.nb.metadata, 'other_supplementary_files', None) 262 | 263 | @property 264 | def reference(self): 265 | """The rst label of this example""" 266 | return 'gallery_' + self.outfile.replace(os.path.sep, '_').lower() 267 | 268 | @property 269 | def url(self): 270 | """The url on jupyter nbviewer for this notebook or None if unknown""" 271 | if self._url is not None: 272 | url = self._url 273 | else: 274 | url = getattr(self.nb.metadata, 'url', None) 275 | if url is not None: 276 | return nbviewer_link(url) 277 | 278 | @property 279 | def remove_tags(self): 280 | return any(self.tag_options.values()) 281 | 282 | def __init__(self, infile, outfile, disable_warnings=True, 283 | preprocess=True, clear=True, code_example=None, 284 | supplementary_files=None, other_supplementary_files=None, 285 | thumbnail_figure=None, url=None, insert_bokeh=False, 286 | insert_bokeh_widgets=False, tag_options={}, 287 | binder_url=None): 288 | """ 289 | Parameters 290 | ---------- 291 | infile: str 292 | path to the existing notebook 293 | outfile: str 294 | path to the new notebook 295 | disable_warnings: bool 296 | Boolean to control whether warnings shall be included in the rst 297 | file or not 298 | preprocess: bool 299 | If True, the notebook is processed when generating the rst file 300 | clear: bool 301 | If True, the output in the download notebook is cleared 302 | code_example: str 303 | A python code sample that shall be used instead of a thumbnail 304 | figure in the gallery. Note that you can also include a 305 | ``'code_example'`` key in the metadata of the notebook 306 | supplementary_files: list of str 307 | Supplementary data files that shall be copied to the output 308 | directory and inserted in the rst file for download 309 | other_supplementary_files: list of str 310 | Other supplementary data files that shall be copied but not 311 | inserted for download 312 | thumbnail_figure: int 313 | The number of the figure that shall be used for download or a path 314 | to a file 315 | url: str 316 | The url where to download the notebook 317 | insert_bokeh: False or str 318 | The version string for bokeh to use for the style sheet 319 | insert_bokeh_widgets: bool or str 320 | The version string for bokeh to use for the widgets style sheet 321 | tag_options: dict 322 | A dictionary with traitlets for the 323 | :class:`nbconvert.preprocessors.TagRemovePreprocessor` 324 | binder_url: str 325 | Link to the repository on mybinder.org or equivalent 326 | """ 327 | self.infile = infile 328 | self.outfile = outfile 329 | self.preprocess = preprocess 330 | self.clear = clear 331 | self._code_example = code_example 332 | self._supplementary_files = supplementary_files 333 | self._other_supplementary_files = other_supplementary_files 334 | self._thumbnail_figure = thumbnail_figure 335 | self._url = url 336 | self.insert_bokeh = insert_bokeh 337 | self.insert_bokeh_widgets = insert_bokeh_widgets 338 | self.tag_options = tag_options 339 | self.binder_url = binder_url 340 | self.process_notebook(disable_warnings) 341 | self.create_thumb() 342 | 343 | def get_out_file(self, ending='rst'): 344 | """get the output file with the specified `ending`""" 345 | return os.path.splitext(self.outfile)[0] + os.path.extsep + ending 346 | 347 | def process_notebook(self, disable_warnings=True): 348 | """Process the notebook and create all the pictures and files 349 | 350 | This method runs the notebook using the :mod:`nbconvert` and 351 | :mod:`nbformat` modules. It creates the :attr:`outfile` notebook, 352 | a python and a rst file""" 353 | infile = self.infile 354 | outfile = self.outfile 355 | in_dir = os.path.dirname(infile) + os.path.sep 356 | odir = os.path.dirname(outfile) + os.path.sep 357 | create_dirs(os.path.join(odir, 'images')) 358 | ep = nbconvert.preprocessors.ExecutePreprocessor( 359 | timeout=300) 360 | cp = nbconvert.preprocessors.ClearOutputPreprocessor( 361 | timeout=300) 362 | 363 | self.nb = nb = nbformat.read(infile, nbformat.current_nbformat) 364 | 365 | language_info = getattr(nb.metadata, 'language_info', {}) 366 | ext = language_info.get('file_extension', 'py') 367 | self.script = self.get_out_file(ext.lstrip('.')) 368 | 369 | disable_warnings = disable_warnings and self.script.endswith('.py') 370 | 371 | # write and process rst_file 372 | if self.preprocess: 373 | 374 | # disable warnings in the rst file 375 | if disable_warnings: 376 | for i, cell in enumerate(nb.cells): 377 | if cell['cell_type'] == 'code': 378 | cell = cell.copy() 379 | break 380 | cell = cell.copy() 381 | cell.source = """ 382 | import logging 383 | logging.captureWarnings(True) 384 | logging.getLogger('py.warnings').setLevel(logging.ERROR) 385 | """ 386 | nb.cells.insert(i, cell) 387 | 388 | t = dt.datetime.now() 389 | logger.info('Processing %s', self.infile) 390 | try: 391 | ep.preprocess(nb, {'metadata': {'path': in_dir}}) 392 | except nbconvert.preprocessors.execute.CellExecutionError: 393 | logger.critical( 394 | 'Error while processing %s!', self.infile, exc_info=True) 395 | else: 396 | logger.info('Done. Seconds needed: %i', 397 | (dt.datetime.now() - t).seconds) 398 | if disable_warnings: 399 | nb.cells.pop(i) 400 | 401 | if self.remove_tags: 402 | tp = nbconvert.preprocessors.TagRemovePreprocessor(timeout=300) 403 | for key, val in self.tag_options.items(): 404 | setattr(tp, key, set(val)) 405 | nb4rst = deepcopy(nb) 406 | tp.preprocess(nb4rst, {'metadata': {'path': in_dir}}) 407 | else: 408 | nb4rst = nb 409 | 410 | self.create_rst(nb4rst, in_dir, odir) 411 | 412 | if self.clear: 413 | cp.preprocess(nb, {'metadata': {'path': in_dir}}) 414 | # write notebook file 415 | nbformat.write(nb, outfile) 416 | self.create_py(nb) 417 | 418 | def create_rst(self, nb, in_dir, odir): 419 | """Create the rst file from the notebook node""" 420 | exporter = nbconvert.RSTExporter() 421 | raw_rst, resources = exporter.from_notebook_node(nb) 422 | # remove ipython magics 423 | rst_content = '' 424 | i0 = 0 425 | m = None 426 | # HACK: we insert the bokeh style sheets here as well, since for some 427 | # themes (e.g. the sphinx_rtd_theme) it is not sufficient to include 428 | # the style sheets only via app.add_stylesheet 429 | bokeh_str = '' 430 | if 'bokeh' in raw_rst and self.insert_bokeh: 431 | bokeh_str += self.BOKEH_TEMPLATE.format( 432 | version=self.insert_bokeh) 433 | if 'bokeh' in raw_rst and self.insert_bokeh_widgets: 434 | bokeh_str += self.BOKEH_WIDGETS_TEMPLATE.format( 435 | version=self.insert_bokeh_widgets) 436 | for m in code_blocks.finditer(raw_rst): 437 | lines = m.group().splitlines(True) 438 | header, content = lines[0], ''.join(lines[1:]) 439 | no_magics = magic_patt.sub('\g<1>', content) 440 | # if the code cell only contained magic commands, we skip it 441 | if no_magics.strip(): 442 | rst_content += ( 443 | raw_rst[i0:m.start()] + bokeh_str + header + no_magics) 444 | bokeh_str = '' 445 | i0 = m.end() 446 | else: 447 | rst_content += raw_rst[i0:m.start()] 448 | i0 = m.end() 449 | if m is not None: 450 | rst_content += bokeh_str + raw_rst[m.end():] 451 | else: 452 | rst_content = raw_rst 453 | rst_content = '.. _%s:\n\n' % self.reference + \ 454 | rst_content 455 | language_info = getattr(nb.metadata, 'language_info', {}) 456 | url = self.url 457 | if url is not None: 458 | rst_content += self.CODE_DOWNLOAD_NBVIEWER.format( 459 | language=language_info.get('name', 'Python'), 460 | script=os.path.basename(self.script), 461 | nbfile=os.path.basename(self.outfile), 462 | url=url) 463 | else: 464 | rst_content += self.CODE_DOWNLOAD.format( 465 | language=language_info.get('name', 'Python'), 466 | script=os.path.basename(self.script), 467 | nbfile=os.path.basename(self.outfile)) 468 | if self.binder_url is not None: 469 | rst_content += self.CODE_RUN_BINDER.format( 470 | url=self.binder_url) 471 | supplementary_files = self.supplementary_files 472 | other_supplementary_files = self.other_supplementary_files 473 | if supplementary_files or other_supplementary_files: 474 | for f in (supplementary_files or []) + ( 475 | other_supplementary_files or []): 476 | if not os.path.exists(os.path.join(odir, f)): 477 | copyfile(os.path.join(in_dir, f), os.path.join(odir, f)) 478 | if supplementary_files: 479 | rst_content += self.data_download(supplementary_files) 480 | 481 | rst_file = self.get_out_file() 482 | outputs = sorted(resources['outputs'], key=rst_content.find) 483 | base = os.path.join('images', os.path.splitext( 484 | os.path.basename(self.infile))[0] + '_%i.png') 485 | out_map = {os.path.basename(original): base % i 486 | for i, original in enumerate(outputs)} 487 | for original, final in six.iteritems(out_map): 488 | rst_content = rst_content.replace(original, final) 489 | with open(rst_file, 'w') \ 490 | as f: 491 | f.write(rst_content.rstrip() + '\n') 492 | pictures = [] 493 | for original in outputs: 494 | fname = os.path.join(odir, out_map[os.path.basename(original)]) 495 | pictures.append(fname) 496 | if six.PY3: 497 | f = open(fname, 'w+b') 498 | else: 499 | f = open(fname, 'w') 500 | f.write(resources['outputs'][original]) 501 | f.close() 502 | self.pictures = pictures 503 | 504 | def create_py(self, nb, force=False): 505 | """Create the python script from the notebook node""" 506 | # Although we would love to simply use ``nbconvert.export_python(nb)`` 507 | # this causes troubles in other cells processed by the ipython 508 | # directive. Instead of getting something like ``Out [5]:``, we get 509 | # some weird like '[0;31mOut[5]: ' which look like 510 | # color information if we allow the call of nbconvert.export_python 511 | if list(map(int, re.findall('\d+', nbconvert.__version__))) >= [4, 2]: 512 | script = os.path.basename(self.script) 513 | else: 514 | script = self.script 515 | try: 516 | level = logger.logger.level 517 | except AttributeError: 518 | level = logger.level 519 | spr.call(['jupyter', 'nbconvert', '--to=script', 520 | '--output=' + os.path.splitext(script)[0], '--log-level=%s' % level, 521 | self.outfile]) 522 | if not script.endswith('.py'): 523 | return 524 | with open(self.script) as f: 525 | py_content = f.read() 526 | # comment out ipython magics 527 | py_content = re.sub('^\s*get_ipython\(\).magic.*', '# \g<0>', 528 | py_content, flags=re.MULTILINE) 529 | with open(self.script, 'w') as f: 530 | f.write(py_content) 531 | 532 | def data_download(self, files): 533 | """Create the rst string to download supplementary data""" 534 | if len(files) > 1: 535 | return self.DATA_DOWNLOAD % ( 536 | ('\n\n' + ' '*8) + ('\n' + ' '*8).join( 537 | '* :download:`%s`' % f for f in files)) 538 | return self.DATA_DOWNLOAD % ':download:`%s`' % files[0] 539 | 540 | def create_thumb(self): 541 | """Create the thumbnail for html output""" 542 | thumbnail_figure = self.copy_thumbnail_figure() 543 | if thumbnail_figure is not None: 544 | if isstring(thumbnail_figure): 545 | pic = thumbnail_figure 546 | else: 547 | pic = self.pictures[thumbnail_figure] 548 | self.save_thumbnail(pic) 549 | else: 550 | for pic in self.pictures[::-1]: 551 | if pic.endswith('png'): 552 | self.save_thumbnail(pic) 553 | return 554 | 555 | def get_description(self): 556 | """Get summary and description of this notebook""" 557 | def split_header(s, get_header=True): 558 | s = s.lstrip().rstrip() 559 | parts = s.splitlines() 560 | if parts[0].startswith('#'): 561 | if get_header: 562 | header = re.sub('#+\s*', '', parts.pop(0)) 563 | if not parts: 564 | return header, '' 565 | else: 566 | header = '' 567 | rest = '\n'.join(parts).lstrip().split('\n\n') 568 | desc = rest[0].replace('\n', ' ') 569 | return header, desc 570 | else: 571 | if get_header: 572 | if parts[0].startswith(('=', '-')): 573 | parts = parts[1:] 574 | header = parts.pop(0) 575 | if parts and parts[0].startswith(('=', '-')): 576 | parts.pop(0) 577 | if not parts: 578 | return header, '' 579 | else: 580 | header = '' 581 | rest = '\n'.join(parts).lstrip().split('\n\n') 582 | desc = rest[0].replace('\n', ' ') 583 | return header, desc 584 | 585 | first_cell = self.nb['cells'][0] 586 | 587 | if not first_cell['cell_type'] == 'markdown': 588 | return '', '' 589 | header, desc = split_header(first_cell['source']) 590 | if not desc and len(self.nb['cells']) > 1: 591 | second_cell = self.nb['cells'][1] 592 | if second_cell['cell_type'] == 'markdown': 593 | _, desc = split_header(second_cell['source'], False) 594 | return header, desc 595 | 596 | def scale_image(self, in_fname, out_fname, max_width, max_height): 597 | """Scales an image with the same aspect ratio centered in an 598 | image with a given max_width and max_height 599 | if in_fname == out_fname the image can only be scaled down 600 | """ 601 | # local import to avoid testing dependency on PIL: 602 | try: 603 | from PIL import Image 604 | except ImportError: 605 | import Image 606 | img = Image.open(in_fname) 607 | width_in, height_in = img.size 608 | scale_w = max_width / float(width_in) 609 | scale_h = max_height / float(height_in) 610 | 611 | if height_in * scale_w <= max_height: 612 | scale = scale_w 613 | else: 614 | scale = scale_h 615 | 616 | if scale >= 1.0 and in_fname == out_fname: 617 | return 618 | 619 | width_sc = int(round(scale * width_in)) 620 | height_sc = int(round(scale * height_in)) 621 | 622 | # resize the image 623 | img.thumbnail((width_sc, height_sc), Image.ANTIALIAS) 624 | 625 | # insert centered 626 | thumb = Image.new('RGB', (max_width, max_height), (255, 255, 255)) 627 | pos_insert = ( 628 | (max_width - width_sc) // 2, (max_height - height_sc) // 2) 629 | thumb.paste(img, pos_insert) 630 | 631 | thumb.save(out_fname) 632 | 633 | def save_thumbnail(self, image_path): 634 | """Save the thumbnail image""" 635 | thumb_dir = os.path.join(os.path.dirname(image_path), 'thumb') 636 | create_dirs(thumb_dir) 637 | 638 | thumb_file = os.path.join(thumb_dir, 639 | '%s_thumb.png' % self.reference) 640 | if os.path.exists(image_path): 641 | logger.info('Scaling %s to thumbnail %s', image_path, thumb_file) 642 | self.scale_image(image_path, thumb_file, 400, 280) 643 | self.thumb_file = thumb_file 644 | 645 | def get_thumb_path(self, base_dir): 646 | """Get the relative path to the thumb nail of this notebook""" 647 | return os.path.relpath(self.thumb_file, base_dir) 648 | 649 | def copy_thumbnail_figure(self): 650 | """The integer of the thumbnail figure""" 651 | ret = None 652 | if self._thumbnail_figure is not None: 653 | if not isstring(self._thumbnail_figure): 654 | ret = self._thumbnail_figure 655 | else: 656 | ret = osp.join(osp.dirname(self.outfile), 657 | osp.basename(self._thumbnail_figure)) 658 | copyfile(self._thumbnail_figure, ret) 659 | return ret 660 | elif hasattr(self.nb.metadata, 'thumbnail_figure'): 661 | if not isstring(self.nb.metadata.thumbnail_figure): 662 | ret = self.nb.metadata.thumbnail_figure 663 | else: 664 | ret = osp.join(osp.dirname(self.outfile), 'images', 665 | osp.basename(self.nb.metadata.thumbnail_figure)) 666 | copyfile(osp.join(osp.dirname(self.infile), 667 | self.nb.metadata.thumbnail_figure), 668 | ret) 669 | return ret 670 | 671 | 672 | class Gallery(object): 673 | """Class to create one or more example gallerys""" 674 | 675 | #: The input directories 676 | in_dir = [] 677 | 678 | #: The output directories 679 | out_dir = [] 680 | 681 | @property 682 | def urls(self): 683 | return self._all_urls[self._in_dir_count] 684 | 685 | @property 686 | def binder_urls(self): 687 | return self._all_binder_urls[self._in_dir_count] 688 | 689 | def __init__(self, examples_dirs=['../examples'], gallery_dirs=None, 690 | pattern='example_.+.ipynb', disable_warnings=True, 691 | dont_preprocess=[], preprocess=True, clear=True, 692 | dont_clear=[], code_examples={}, supplementary_files={}, 693 | other_supplementary_files={}, thumbnail_figures={}, 694 | urls=None, insert_bokeh=False, insert_bokeh_widgets=False, 695 | remove_all_outputs_tags=set(), remove_cell_tags=set(), 696 | remove_input_tags=set(), remove_single_output_tags=set(), 697 | toctree_depth=-1, binder_url=None): 698 | """ 699 | Parameters 700 | ---------- 701 | examples_dirs: list of str 702 | list containing the directories to loop through. Default: 703 | ``['../examples']`` 704 | gallery_dirs: list of str 705 | None or list of directories where the rst files shall be created. 706 | If None, the current working directory and the name of the 707 | corresponding directory in the `examples_dirs` is used. Default: 708 | ``None`` 709 | pattern: list of str 710 | str. The pattern to use to find the ipython notebooks. 711 | Default: ``'example_.+.ipynb'`` 712 | disable_warnings: bool 713 | Boolean controlling whether warnings shall be disabled when 714 | processing the examples. Default: True 715 | preprocess: bool or list of str 716 | If True, all examples (except those specified in the 717 | `dont_preprocess` item) will be preprocessed when creating the rst 718 | files. Otherwise it might be a list of files that shall be 719 | preprocessed. 720 | dont_preprocess: bool or list of str 721 | If True, no example will be preprocessed when creating the rst 722 | files. Otherwise it might be a list of files that shall not be 723 | preprocessed 724 | clear: bool or list of str 725 | If True, the output in all notebooks to download will be cleared. 726 | Otherwise it might be a list of notebook files of whom to clear the 727 | output 728 | dont_clear: bool or list of str 729 | If True, the output in all notebooks to download will not be 730 | cleared. Otherwise it might be a list of notebook files of whom 731 | not to clear the output 732 | code_examples: dict 733 | A mapping from filename to code samples that shall be used instead 734 | of a thumbnail figure in the gallery. Note that you can also 735 | include a ``'code_example'`` key in the metadata of the notebook 736 | supplementary_files: dict 737 | A mapping from filename to a list of supplementary data files that 738 | shall copied to the documentation directory and can be downloaded. 739 | Note that you can also include a ``'supplementary_files'`` key in 740 | the metadata of the notebook 741 | other_supplementary_files: dict 742 | A mapping from filename to a list of other supplementary data files 743 | that shall copied to the documentation directory but can not be 744 | downloaded (e.g. pictures). 745 | Note that you can also include a ``'other_supplementary_files'`` 746 | key in the metadata of the notebook 747 | thumbnail_figures: dict 748 | A mapping from filename to an integer or the path of a file to use 749 | for the thumbnail 750 | urls: str or dict 751 | The urls where to download the notebook. Necessary to provide a 752 | link to the jupyter nbviewer. If string, the path to the notebook 753 | will be appended for each example notebook. Otherwise it should be 754 | a dictionary with links for the given notebook 755 | insert_bokeh: bool or str 756 | If True, the bokeh js [1]_ and the stylesheet [2]_ are inserted in 757 | the notebooks that have bokeh loaded (using the installed or 758 | specified bokeh version) 759 | insert_bokeh_widgets: bool or str 760 | If True, the bokeh widget js [3]_ is inserted in the notebooks that 761 | have bokeh loaded (using the installed or specified bokeh version) 762 | remove_all_outputs_tags: set 763 | Tags indicating cells for which the outputs are to be removed, 764 | matches tags in cell.metadata.tags. 765 | remove_cell_tags: set 766 | Tags indicating which cells are to be removed, matches tags in 767 | cell.metadata.tags. 768 | remove_input_tags: set 769 | Tags indicating cells for which input is to be removed, 770 | matches tags in cell.metadata.tags. 771 | remove_single_output_tags: set 772 | Tags indicating which individual outputs are to be removed, matches 773 | output i tags in cell.outputs[i].metadata.tags. 774 | toctree_depth: int 775 | Depth to expand table-of-contents trees to. To disable, set to 0. 776 | For automatic depth, set to -1. Default: -1 777 | binder_url: str 778 | Link to the notebook on mybinder.org or equivalent 779 | 780 | References 781 | ---------- 782 | .. [1] http://cdn.pydata.org/bokeh/release/bokeh-0.12.0.min.js 783 | .. [2] http://cdn.pydata.org/bokeh/release/bokeh-0.12.0.min.css 784 | .. [3] http://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.0.min.js 785 | """ 786 | if isstring(examples_dirs): 787 | examples_dirs = [examples_dirs] 788 | if gallery_dirs is None: 789 | gallery_dirs = list(map(os.path.basename, examples_dirs)) 790 | if isstring(gallery_dirs): 791 | gallery_dirs = [gallery_dirs] 792 | 793 | for i, s in enumerate(examples_dirs): 794 | if not s.endswith(os.path.sep): 795 | examples_dirs[i] += os.path.sep 796 | 797 | for i, s in enumerate(gallery_dirs): 798 | if not s.endswith(os.path.sep): 799 | gallery_dirs[i] += os.path.sep 800 | 801 | self.in_dir = examples_dirs 802 | self.out_dir = gallery_dirs 803 | 804 | if isstring(pattern): 805 | pattern = re.compile(pattern) 806 | self.pattern = pattern 807 | self.disable_warnings = disable_warnings 808 | self.dont_preprocess = dont_preprocess 809 | self.preprocess = preprocess 810 | self.clear = clear 811 | self.dont_clear = dont_clear 812 | self.code_examples = code_examples 813 | self.supplementary_files = supplementary_files 814 | self.osf = other_supplementary_files 815 | self.thumbnail_figures = thumbnail_figures 816 | self.toctree_depth = toctree_depth 817 | if urls is None or isstring(urls) or isinstance(urls, dict): 818 | urls = [urls] * len(self.in_dir) 819 | if binder_url is None or isstring(binder_url) or isinstance( 820 | binder_url, dict): 821 | binder_url = [binder_url] * len(self.in_dir) 822 | self._all_urls = urls 823 | self._all_binder_urls = binder_url 824 | if insert_bokeh and not isstring(insert_bokeh): 825 | import bokeh 826 | insert_bokeh = bokeh.__version__ 827 | if insert_bokeh_widgets and not isstring(insert_bokeh_widgets): 828 | import bokeh 829 | insert_bokeh_widgets = bokeh.__version__ 830 | tag_options = { 831 | 'remove_all_outputs_tags': remove_all_outputs_tags, 832 | 'remove_cell_tags': remove_cell_tags, 833 | 'remove_input_tags': remove_input_tags, 834 | 'remove_single_output_tags': remove_single_output_tags} 835 | self._nbp_kws = {'insert_bokeh': insert_bokeh, 836 | 'insert_bokeh_widgets': insert_bokeh_widgets, 837 | 'tag_options': tag_options, 838 | } 839 | 840 | def process_directories(self): 841 | """Create the rst files from the input directories in the 842 | :attr:`in_dir` attribute""" 843 | for i, (base_dir, target_dir, paths) in enumerate(zip( 844 | self.in_dir, self.out_dir, map(os.walk, self.in_dir))): 845 | self._in_dir_count = i 846 | self.recursive_processing(base_dir, target_dir, paths) 847 | 848 | def recursive_processing(self, base_dir, target_dir, it): 849 | """Method to recursivly process the notebooks in the `base_dir` 850 | 851 | Parameters 852 | ---------- 853 | base_dir: str 854 | Path to the base example directory (see the `examples_dir` 855 | parameter for the :class:`Gallery` class) 856 | target_dir: str 857 | Path to the output directory for the rst files (see the 858 | `gallery_dirs` parameter for the :class:`Gallery` class) 859 | it: iterable 860 | The iterator over the subdirectories and files in `base_dir` 861 | generated by the :func:`os.walk` function""" 862 | try: 863 | file_dir, dirs, files = next(it) 864 | except StopIteration: 865 | return '', [] 866 | readme_files = {'README.md', 'README.rst', 'README.txt'} 867 | if readme_files.intersection(files): 868 | foutdir = file_dir.replace(base_dir, target_dir) 869 | create_dirs(foutdir) 870 | this_nbps = [ 871 | NotebookProcessor( 872 | infile=f, 873 | outfile=os.path.join(foutdir, os.path.basename(f)), 874 | disable_warnings=self.disable_warnings, 875 | preprocess=( 876 | (self.preprocess is True or f in self.preprocess) and 877 | not (self.dont_preprocess is True or 878 | f in self.dont_preprocess)), 879 | clear=((self.clear is True or f in self.clear) and not 880 | (self.dont_clear is True or f in self.dont_clear)), 881 | code_example=self.code_examples.get(f), 882 | supplementary_files=self.supplementary_files.get(f), 883 | other_supplementary_files=self.osf.get(f), 884 | thumbnail_figure=self.thumbnail_figures.get(f), 885 | url=self.get_url(f.replace(base_dir, '')), 886 | binder_url=self.get_binder_url(f.replace(base_dir, '')), 887 | **self._nbp_kws) 888 | for f in map(lambda f: os.path.join(file_dir, f), 889 | filter(self.pattern.match, files))] 890 | readme_file = next(iter(readme_files.intersection(files))) 891 | else: 892 | return '', [] 893 | labels = OrderedDict() 894 | this_label = 'gallery_' + foutdir.replace(os.path.sep, '_') 895 | if this_label.endswith('_'): 896 | this_label = this_label[:-1] 897 | for d in dirs: 898 | label, nbps = self.recursive_processing( 899 | base_dir, target_dir, it) 900 | if label: 901 | labels[label] = nbps 902 | s = ".. _%s:\n\n" % this_label 903 | 904 | if readme_file.endswith('.md'): 905 | s += spr.check_output( 906 | ['pandoc', os.path.join(file_dir, readme_file), 907 | '-t', 'rst']).decode('utf-8').rstrip() + '\n\n' 908 | else: 909 | with open(os.path.join(file_dir, readme_file)) as f: 910 | s += f.read().rstrip() + '\n\n' 911 | 912 | if self.toctree_depth: 913 | s += "\n\n.. toctree::" 914 | if self.toctree_depth > 0: 915 | s += "\n :maxdepth: %d" % self.toctree_depth 916 | s += "\n\n" 917 | s += ''.join(' %s\n' % os.path.splitext(os.path.basename( 918 | nbp.get_out_file()))[0] for nbp in this_nbps) 919 | for d in dirs: 920 | findex = os.path.join(d, 'index.rst') 921 | if os.path.exists(os.path.join(foutdir, findex)): 922 | s += ' %s\n' % os.path.splitext(findex)[0] 923 | 924 | s += '\n' 925 | 926 | for nbp in this_nbps: 927 | code_div = nbp.code_div 928 | if code_div is not None: 929 | s += code_div + '\n' 930 | else: 931 | s += nbp.thumbnail_div + '\n' 932 | s += "\n.. raw:: html\n\n
\n" 933 | for label, nbps in labels.items(): 934 | s += '\n.. only:: html\n\n .. rubric:: :ref:`%s`\n\n' % ( 935 | label) 936 | for nbp in nbps: 937 | code_div = nbp.code_div 938 | if code_div is not None: 939 | s += code_div + '\n' 940 | else: 941 | s += nbp.thumbnail_div + '\n' 942 | s += "\n.. raw:: html\n\n
\n" 943 | 944 | s += '\n' 945 | 946 | with open(os.path.join(foutdir, 'index.rst'), 'w') as f: 947 | f.write(s) 948 | return this_label, list(chain(this_nbps, *labels.values())) 949 | 950 | @classmethod 951 | def from_sphinx(cls, app): 952 | """Class method to create a :class:`Gallery` instance from the 953 | configuration of a sphinx application""" 954 | app.config.html_static_path.append(os.path.join( 955 | os.path.dirname(__file__), '_static')) 956 | config = app.config.example_gallery_config 957 | 958 | insert_bokeh = config.get('insert_bokeh') 959 | if insert_bokeh: 960 | if not isstring(insert_bokeh): 961 | import bokeh 962 | insert_bokeh = bokeh.__version__ 963 | 964 | if int(sphinx.__version__.split('.')[0]) >= 3: 965 | app.add_css_file( 966 | NotebookProcessor.BOKEH_STYLE_SHEET.format( 967 | version=insert_bokeh)) 968 | else: 969 | app.add_stylesheet( 970 | NotebookProcessor.BOKEH_STYLE_SHEET.format( 971 | version=insert_bokeh)) 972 | app.add_js_file( 973 | NotebookProcessor.BOKEH_JS.format(version=insert_bokeh)) 974 | 975 | insert_bokeh_widgets = config.get('insert_bokeh_widgets') 976 | if insert_bokeh_widgets: 977 | if not isstring(insert_bokeh_widgets): 978 | import bokeh 979 | insert_bokeh_widgets = bokeh.__version__ 980 | if int(sphinx.__version__.split('.')[0]) >= 3: 981 | app.add_css_file( 982 | NotebookProcessor.BOKEH_WIDGETS_STYLE_SHEET.format( 983 | version=insert_bokeh_widgets)) 984 | else: 985 | app.add_stylesheet( 986 | NotebookProcessor.BOKEH_WIDGETS_STYLE_SHEET.format( 987 | version=insert_bokeh_widgets)) 988 | app.add_js_file( 989 | NotebookProcessor.BOKEH_WIDGETS_JS.format( 990 | version=insert_bokeh_widgets)) 991 | 992 | if not app.config.process_examples: 993 | return 994 | cls(**app.config.example_gallery_config).process_directories() 995 | 996 | def get_url(self, nbfile): 997 | """Return the url corresponding to the given notebook file 998 | 999 | Parameters 1000 | ---------- 1001 | nbfile: str 1002 | The path of the notebook relative to the corresponding 1003 | :attr:``in_dir`` 1004 | 1005 | Returns 1006 | ------- 1007 | str or None 1008 | The url or None if no url has been specified 1009 | """ 1010 | urls = self.urls 1011 | if isinstance(urls, dict): 1012 | return urls.get(nbfile) 1013 | elif isstring(urls): 1014 | if not urls.endswith('/'): 1015 | urls += '/' 1016 | return urls + nbfile 1017 | 1018 | def get_binder_url(self, nbfile): 1019 | """Return the url corresponding to the given notebook file 1020 | 1021 | Parameters 1022 | ---------- 1023 | nbfile: str 1024 | The path of the notebook relative to the corresponding 1025 | :attr:``in_dir`` 1026 | 1027 | Returns 1028 | ------- 1029 | str or None 1030 | The url or None if no url has been specified 1031 | """ 1032 | urls = self.binder_urls 1033 | if isinstance(urls, dict): 1034 | return urls.get(nbfile) 1035 | elif isstring(urls): 1036 | if not urls.endswith('/'): 1037 | urls += '/' 1038 | return urls + nbfile 1039 | 1040 | 1041 | def align(argument): 1042 | """Conversion function for the "align" option.""" 1043 | return directives.choice(argument, ('left', 'center', 'right')) 1044 | 1045 | 1046 | class LinkGalleriesDirective(Directive): 1047 | 1048 | has_content = True 1049 | 1050 | if hasattr(directives, 'images'): 1051 | option_spec = directives.images.Figure.option_spec 1052 | else: 1053 | option_spec = {'alt': directives.unchanged, 1054 | 'height': directives.nonnegative_int, 1055 | 'width': directives.nonnegative_int, 1056 | 'scale': directives.nonnegative_int, 1057 | 'align': align 1058 | } 1059 | 1060 | def create_image_nodes(self, header, thumb_url, key, link_url=None): 1061 | options = {'target': link_url} if link_url else {} 1062 | options.update(self.options) 1063 | d1 = directives.misc.Raw( 1064 | 'raw', ['html'], {}, ViewList([ 1065 | '
'] 1066 | ), 1067 | self.lineno, self.content_offset, self.block_text, self.state, 1068 | self.state_machine) 1069 | d = directives.images.Figure( 1070 | 'image', [thumb_url], options, ViewList([':ref:`%s`' % key]), 1071 | self.lineno, self.content_offset, self.block_text, self.state, 1072 | self.state_machine) 1073 | d2 = directives.misc.Raw( 1074 | 'raw', ['html'], {}, ViewList(['
']), 1075 | self.lineno, self.content_offset, self.block_text, self.state, 1076 | self.state_machine) 1077 | return list(chain(d1.run(), d.run(), d2.run())) 1078 | 1079 | def get_outdirs(self): 1080 | conf = self.env.config.example_gallery_config 1081 | gallery_dirs = conf.get('gallery_dirs') 1082 | if not gallery_dirs: 1083 | examples_dirs = conf.get('example_dirs', ['../examples']) 1084 | if isstring(examples_dirs): 1085 | examples_dirs = [examples_dirs] 1086 | gallery_dirs = list(map(osp.basename, examples_dirs)) 1087 | if isstring(gallery_dirs): 1088 | gallery_dirs = [gallery_dirs] 1089 | for i, s in enumerate(gallery_dirs): 1090 | if not s.endswith(os.path.sep): 1091 | gallery_dirs[i] += os.path.sep 1092 | return gallery_dirs 1093 | 1094 | def run(self): 1095 | self.env = self.state.document.settings.env 1096 | conf = self.env.config 1097 | ret = nodes.paragraph() 1098 | try: 1099 | inventory = self.env.intersphinx_named_inventory 1100 | except AttributeError: 1101 | warn('The %s directive requires the sphinx.ext.intersphinx ' 1102 | 'extension!', self.name) 1103 | return [ret] 1104 | for pkg_str in self.content: 1105 | try: 1106 | pkg, directory = pkg_str.split() 1107 | except ValueError: 1108 | pkg, directory = pkg_str, '' 1109 | directory_ = directory.replace('/', '_').lower() 1110 | if pkg == conf.project: 1111 | pass 1112 | if not directory: 1113 | directories = self.get_outdirs() 1114 | else: 1115 | directories = [directory] 1116 | for directory in directories: 1117 | for file_dir, dirs, files in os.walk(directory): 1118 | if not file_dir.endswith(osp.sep): 1119 | file_dir += osp.sep 1120 | file_dir_ = file_dir.replace(osp.sep, '_').lower() 1121 | if 'index.rst' in files: 1122 | for f in files: 1123 | if f.endswith('.ipynb'): 1124 | ref = 'gallery_' + file_dir_ + f 1125 | thumb = osp.join( 1126 | file_dir, 'images', 'thumb', 1127 | ref + '_thumb.png') 1128 | if osp.isabs(thumb): 1129 | thumb = osp.relpath(thumb, 1130 | self.env.srcdir) 1131 | header = ':ref:`%s`' % (ref, ) 1132 | ret.extend(self.create_image_nodes( 1133 | header, thumb, ref)) 1134 | else: 1135 | try: 1136 | refs = inventory[pkg]['std:label'] 1137 | except KeyError: 1138 | warn('Could not load the inventory of %s!', pkg) 1139 | continue 1140 | if sphinx.__version__ <= '1.9': 1141 | base_url = self.env.config.intersphinx_mapping[pkg][0] 1142 | else: 1143 | base_url = self.env.config.intersphinx_mapping[pkg][1][0] 1144 | if not base_url.endswith('/'): 1145 | base_url += '/' 1146 | for key, val in refs.items(): 1147 | if (key.startswith('gallery_' + directory_) and 1148 | key.endswith('.ipynb')): 1149 | link_url = val[2] 1150 | header = val[3] 1151 | thumb_url = base_url + '_images/%s_thumb.png' % key 1152 | ret.extend(self.create_image_nodes( 1153 | header, thumb_url, '%s:%s' % (pkg, key), 1154 | link_url)) 1155 | ret.extend(directives.misc.Raw( 1156 | 'raw', ['html'], {}, ViewList(["
"]), 1157 | self.lineno, self.content_offset, self.block_text, self.state, 1158 | self.state_machine).run()) 1159 | return [ret] 1160 | 1161 | 1162 | #: dictionary containing the configuration of the example gallery. 1163 | #: 1164 | #: Possible keys for the dictionary are the initialization keys of the 1165 | #: :class:`Gallery` class 1166 | gallery_config = { 1167 | 'examples_dirs': ['../examples'], 1168 | 'gallery_dirs': None, 1169 | 'pattern': 'example_.+.ipynb', 1170 | 'disable_warnings': True, 1171 | 'preprocess': True, 1172 | 'dont_preprocess': [], 1173 | 'clear': True, 1174 | 'dont_clear': [], 1175 | 'code_examples': {}, 1176 | 'supplementary_files': {}, 1177 | 'insert_bokeh': False, 1178 | 'insert_bokeh_widgets': False} 1179 | 1180 | 1181 | #: Boolean controlling whether the rst files shall created and examples 1182 | #: processed 1183 | process_examples = True 1184 | 1185 | 1186 | def setup(app): 1187 | app.add_config_value('process_examples', process_examples, 'html') 1188 | 1189 | app.add_config_value('example_gallery_config', gallery_config, 'html') 1190 | 1191 | if int(sphinx.__version__.split('.')[0]) >= 3: 1192 | app.add_css_file('example_gallery_styles.css') 1193 | else: 1194 | app.add_stylesheet('example_gallery_styles.css') 1195 | 1196 | app.add_directive('linkgalleries', LinkGalleriesDirective) 1197 | 1198 | app.connect('builder-inited', Gallery.from_sphinx) 1199 | -------------------------------------------------------------------------------- /sphinx_nbexamples/_static/example_gallery_styles.css: -------------------------------------------------------------------------------- 1 | div.sphx-glr-thumbContainer { 2 | box-shadow: none; 3 | background: #FFF; 4 | margin: 5px; 5 | padding-top: 5px; 6 | min-height: 230px; 7 | border: solid white 1px; 8 | -webkit-border-radius: 5px; 9 | -moz-border-radius: 5px; 10 | border-radius: 5px; 11 | float: left; 12 | position: relative; } 13 | div.sphx-glr-thumbContainer:hover { 14 | box-shadow: 0 0 15px rgba(142, 176, 202, 0.5); 15 | border: solid #B4DDFC 1px; } 16 | div.sphx-glr-thumbContainer a.internal { 17 | display: block; 18 | position: absolute; 19 | padding: 150px 10px 0px 10px; 20 | top: 0px; 21 | right: 0px; 22 | bottom: 0px; 23 | left: 0px; } 24 | div.sphx-glr-thumbContainer p { 25 | margin: 0 0 .1em 0; } 26 | div.sphx-glr-thumbContainer .figure { 27 | margin: 10px; 28 | width: 160px; } 29 | div.sphx-glr-thumbContainer img { 30 | max-width: 100%; 31 | max-height: 160px; 32 | display: inline; } 33 | div.sphx-glr-thumbContainer[tooltip=""]:hover:after { 34 | } 35 | div.sphx-glr-thumbContainer[tooltip=""]:hover:before { 36 | } 37 | div.sphx-glr-thumbContainer[tooltip]:hover:after { 38 | background: rgba(0, 0, 0, 0.8); 39 | -webkit-border-radius: 5px; 40 | -moz-border-radius: 5px; 41 | border-radius: 5px; 42 | color: white; 43 | content: attr(tooltip); 44 | left: 95%; 45 | padding: 5px 15px; 46 | position: absolute; 47 | z-index: 98; 48 | width: 220px; 49 | bottom: 52%; } 50 | div.sphx-glr-thumbContainer[tooltip]:hover:before { 51 | content: ""; 52 | position: absolute; 53 | z-index: 99; 54 | border: solid; 55 | border-color: #333 transparent; 56 | border-width: 18px 0px 0px 20px; 57 | left: 85%; 58 | bottom: 58%; } 59 | 60 | .sphx-glr-download { 61 | background-color: #ffc; 62 | border: 1px solid #c2c22d; 63 | border-radius: 4px; 64 | margin: 1em auto 1ex auto; 65 | max-width: 45ex; 66 | padding: 1ex; 67 | } 68 | .sphx-glr-download a { 69 | color: #4b4600; 70 | } -------------------------------------------------------------------------------- /sphinx_nbexamples/_static/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/sphinx_nbexamples/_static/no_image.png -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import os.path as osp 4 | 5 | dirname = osp.dirname(__file__) 6 | 7 | project = 'sphinx-test' 8 | 9 | master_doc = 'index' 10 | 11 | extensions = ['sphinx_nbexamples'] 12 | 13 | example_gallery_config = { 14 | 'examples_dirs': osp.join(dirname, 'raw_examples'), 15 | 'gallery_dirs': osp.join(dirname, 'examples'), 16 | 'code_examples': {osp.join(dirname, 'raw_examples', 17 | 'example_hello_world.ipynb'): 'someothercode'}, 18 | 'thumbnail_figures': { 19 | osp.join(dirname, 'raw_examples', 20 | 'example_mpl_test_figure_chosen.ipynb'): 0}, 21 | 'supplementary_files': { 22 | osp.join(dirname, 'raw_examples', 23 | 'example_hello_world.ipynb'): ['test2.txt']}, 24 | 'remove_cell_tags': ['remove_in_docs'], 25 | 'toctree_depth': 2, 26 | } 27 | 28 | exclude_patterns = ['raw_examples'] 29 | 30 | 31 | try: 32 | import pathlib 33 | 34 | def file2html(fname): 35 | return pathlib.Path(fname).as_uri() 36 | 37 | except ImportError: 38 | pathlib = None 39 | 40 | 41 | _link_dir = os.getenv('LINKGALLERYTO') 42 | if _link_dir: 43 | extensions.append('sphinx.ext.intersphinx') 44 | intersphinx_mapping = {'sphinx_nbexamples': ( 45 | file2html(_link_dir), osp.join(_link_dir, 'objects.inv'))} 46 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/index.rst: -------------------------------------------------------------------------------- 1 | Example documentation 2 | ===================== 3 | 4 | .. toctree:: 5 | 6 | examples/index 7 | 8 | .. linkgalleries:: 9 | 10 | sphinx-test 11 | sphinx_nbexamples 12 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/README.rst: -------------------------------------------------------------------------------- 1 | Some examples for testing 2 | ========================= -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_bash.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "# Bash example\n", 9 | "\n", 10 | "\n", 11 | "This example notebook uses a Bash kernel.\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": null, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "# A basic hello, world in Bash\n", 21 | "\n", 22 | "function hello {\n", 23 | " OUT=hello\n", 24 | " echo $OUT, world\n", 25 | "}" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "hello" 35 | ] 36 | } 37 | ], 38 | "metadata": { 39 | "kernelspec": { 40 | "display_name": "Bash", 41 | "language": "bash", 42 | "name": "bash" 43 | }, 44 | "language_info": { 45 | "codemirror_mode": "shell", 46 | "file_extension": ".sh", 47 | "mimetype": "text/x-sh", 48 | "name": "bash" 49 | } 50 | }, 51 | "nbformat": 4, 52 | "nbformat_minor": 2 53 | } 54 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_code_example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Example with a code command instead of a figure\n", 8 | "===============\n", 9 | "This test notebook has the ```code_example``` metadata attribute specified to be shown instead of a thumbnail" 10 | ] 11 | } 12 | ], 13 | "metadata": { 14 | "code_example": "somecode", 15 | "kernelspec": { 16 | "display_name": "Python 2", 17 | "language": "python", 18 | "name": "python2" 19 | }, 20 | "language_info": { 21 | "codemirror_mode": { 22 | "name": "ipython", 23 | "version": 3 24 | }, 25 | "file_extension": ".py", 26 | "mimetype": "text/x-python", 27 | "name": "python", 28 | "nbconvert_exporter": "python", 29 | "pygments_lexer": "ipython2", 30 | "version": "3.5.0rc4" 31 | } 32 | }, 33 | "nbformat": 4, 34 | "nbformat_minor": 0 35 | } 36 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_failure.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Expexted Failure\n", 8 | "=========\n", 9 | "Test whether the gallery can handle failing notebooks" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "collapsed": false 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "assert 1 == 2, \"Failed\"" 21 | ] 22 | } 23 | ], 24 | "metadata": { 25 | "kernelspec": { 26 | "display_name": "Python 2", 27 | "language": "python", 28 | "name": "python2" 29 | }, 30 | "language_info": { 31 | "codemirror_mode": { 32 | "name": "ipython", 33 | "version": 3 34 | }, 35 | "file_extension": ".py", 36 | "mimetype": "text/x-python", 37 | "name": "python", 38 | "nbconvert_exporter": "python", 39 | "pygments_lexer": "ipython2", 40 | "version": "3.5.0rc4" 41 | }, 42 | "thumbnail_figure": "test_image.png" 43 | }, 44 | "nbformat": 4, 45 | "nbformat_minor": 0 46 | } 47 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_hello_world.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hello World\n", 8 | "Just a simple example" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "metadata": { 15 | "collapsed": false 16 | }, 17 | "outputs": [], 18 | "source": [ 19 | "print(\"Hello World!\")" 20 | ] 21 | } 22 | ], 23 | "metadata": { 24 | "kernelspec": { 25 | "display_name": "Python 2", 26 | "language": "python", 27 | "name": "python2" 28 | }, 29 | "language_info": { 30 | "codemirror_mode": { 31 | "name": "ipython", 32 | "version": 3 33 | }, 34 | "file_extension": ".py", 35 | "mimetype": "text/x-python", 36 | "name": "python", 37 | "nbconvert_exporter": "python", 38 | "pygments_lexer": "ipython2", 39 | "version": "3.5.0rc4" 40 | } 41 | }, 42 | "nbformat": 4, 43 | "nbformat_minor": 0 44 | } 45 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_magics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Example with magics\n", 8 | "==========" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "The usual matplotlib inline as an example before, between and after a python commands" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 1, 21 | "metadata": { 22 | "collapsed": true, 23 | "scrolled": false 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "%matplotlib inline\n", 28 | "import matplotlib as mpl\n", 29 | "%matplotlib inline\n", 30 | "a = 10\n", 31 | "%matplotlib inline" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "A single magic" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 2, 44 | "metadata": { 45 | "collapsed": false 46 | }, 47 | "outputs": [ 48 | { 49 | "name": "stdout", 50 | "output_type": "stream", 51 | "text": [ 52 | "/Users/psommer\n" 53 | ] 54 | } 55 | ], 56 | "source": [ 57 | "%cd" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "Something with %test inside a markdown text" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 1, 70 | "metadata": { 71 | "collapsed": false 72 | }, 73 | "outputs": [ 74 | { 75 | "name": "stdout", 76 | "output_type": "stream", 77 | "text": [ 78 | "Something %magic like inside a python code\n" 79 | ] 80 | } 81 | ], 82 | "source": [ 83 | "print('Something %magic like inside a python code')" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 1, 89 | "metadata": { 90 | "collapsed": false 91 | }, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | "%magic okay\n" 98 | ] 99 | } 100 | ], 101 | "source": [ 102 | "print('%magic okay')" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": { 109 | "collapsed": true 110 | }, 111 | "outputs": [], 112 | "source": [] 113 | } 114 | ], 115 | "metadata": { 116 | "kernelspec": { 117 | "display_name": "Python 2", 118 | "language": "python", 119 | "name": "python2" 120 | }, 121 | "language_info": { 122 | "codemirror_mode": { 123 | "name": "ipython", 124 | "version": 3 125 | }, 126 | "file_extension": ".py", 127 | "mimetype": "text/x-python", 128 | "name": "python", 129 | "nbconvert_exporter": "python", 130 | "pygments_lexer": "ipython2", 131 | "version": "3.5.0rc4" 132 | } 133 | }, 134 | "nbformat": 4, 135 | "nbformat_minor": 0 136 | } 137 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_mpl_test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Matplotlib test\n", 8 | "==========\n", 9 | "Test if the matplotlib thumbnail is inserted correctly" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "collapsed": true 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "%matplotlib inline\n", 21 | "import matplotlib.pyplot as plt" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": { 28 | "collapsed": true 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "plt.plot([6, 7])" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": { 39 | "collapsed": true 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "plt.plot([4, 3])" 44 | ] 45 | } 46 | ], 47 | "metadata": { 48 | "kernelspec": { 49 | "display_name": "Python 2", 50 | "language": "python", 51 | "name": "python2" 52 | }, 53 | "language_info": { 54 | "codemirror_mode": { 55 | "name": "ipython", 56 | "version": 3 57 | }, 58 | "file_extension": ".py", 59 | "mimetype": "text/x-python", 60 | "name": "python", 61 | "nbconvert_exporter": "python", 62 | "pygments_lexer": "ipython2", 63 | "version": "3.5.0rc4" 64 | } 65 | }, 66 | "nbformat": 4, 67 | "nbformat_minor": 0 68 | } 69 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_mpl_test_figure_chosen.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Matplotlib test\n", 8 | "==========\n", 9 | "Test if the matplotlib thumbnail is inserted correctly" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "collapsed": true 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "%matplotlib inline\n", 21 | "import matplotlib.pyplot as plt" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": { 28 | "collapsed": false 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "plt.plot([6, 7])" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": { 39 | "collapsed": false 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "plt.plot([4, 3])" 44 | ] 45 | } 46 | ], 47 | "metadata": { 48 | "kernelspec": { 49 | "display_name": "Python 2", 50 | "language": "python", 51 | "name": "python2" 52 | }, 53 | "language_info": { 54 | "codemirror_mode": { 55 | "name": "ipython", 56 | "version": 3 57 | }, 58 | "file_extension": ".py", 59 | "mimetype": "text/x-python", 60 | "name": "python", 61 | "nbconvert_exporter": "python", 62 | "pygments_lexer": "ipython2", 63 | "version": "3.5.0rc4" 64 | } 65 | }, 66 | "nbformat": 4, 67 | "nbformat_minor": 0 68 | } 69 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/example_tag_removal.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Example for testing the removal of cells\n", 8 | "This example includes a cell that should be removed" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": { 15 | "tags": [ 16 | "remove_in_docs" 17 | ] 18 | }, 19 | "outputs": [ 20 | { 21 | "name": "stdout", 22 | "output_type": "stream", 23 | "text": [ 24 | "This should be removed!\n" 25 | ] 26 | } 27 | ], 28 | "source": [ 29 | "print(\"This should be removed!\")" 30 | ] 31 | } 32 | ], 33 | "metadata": { 34 | "celltoolbar": "Tags", 35 | "kernelspec": { 36 | "display_name": "Python 2", 37 | "language": "python", 38 | "name": "python2" 39 | }, 40 | "language_info": { 41 | "codemirror_mode": { 42 | "name": "ipython", 43 | "version": 3 44 | }, 45 | "file_extension": ".py", 46 | "mimetype": "text/x-python", 47 | "name": "python", 48 | "nbconvert_exporter": "python", 49 | "pygments_lexer": "ipython2", 50 | "version": "3.5.0rc4" 51 | } 52 | }, 53 | "nbformat": 4, 54 | "nbformat_minor": 2 55 | } 56 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/sub/README.md: -------------------------------------------------------------------------------- 1 | Some additional examples in a subfolder 2 | ======================================= 3 | 4 | This is [a markdown link](https://www.google.de/). 5 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/sub/example_supplementary_files.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Test with supplementary files\n", 8 | "=============================\n", 9 | "This notebook requires some supplementary files which should be included in the documentation" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "collapsed": false 17 | }, 18 | "outputs": [ 19 | { 20 | "name": "stdout", 21 | "output_type": "stream", 22 | "text": [ 23 | "Just a dummy file\n", 24 | "\n" 25 | ] 26 | } 27 | ], 28 | "source": [ 29 | "with open('test.txt')as f:\n", 30 | " print(f.read())" 31 | ] 32 | } 33 | ], 34 | "metadata": { 35 | "kernelspec": { 36 | "display_name": "Python 2", 37 | "language": "python", 38 | "name": "python2" 39 | }, 40 | "language_info": { 41 | "codemirror_mode": { 42 | "name": "ipython", 43 | "version": 3 44 | }, 45 | "file_extension": ".py", 46 | "mimetype": "text/x-python", 47 | "name": "python", 48 | "nbconvert_exporter": "python", 49 | "pygments_lexer": "ipython2", 50 | "version": "3.5.0rc4" 51 | }, 52 | "supplementary_files": [ 53 | "test.txt" 54 | ] 55 | }, 56 | "nbformat": 4, 57 | "nbformat_minor": 0 58 | } 59 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/sub/example_toctree.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hello World\n", 8 | "Just a simple example" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## With a subsection" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": null, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "print(\"Hello World!\")" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "kernelspec": { 30 | "display_name": "Python 2", 31 | "language": "python", 32 | "name": "python2" 33 | }, 34 | "language_info": { 35 | "codemirror_mode": { 36 | "name": "ipython", 37 | "version": 3 38 | }, 39 | "file_extension": ".py", 40 | "mimetype": "text/x-python", 41 | "name": "python", 42 | "nbconvert_exporter": "python", 43 | "pygments_lexer": "ipython2", 44 | "version": "3.5.0rc4" 45 | } 46 | }, 47 | "nbformat": 4, 48 | "nbformat_minor": 0 49 | } 50 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/sub/test.txt: -------------------------------------------------------------------------------- 1 | Just a dummy file 2 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/test2.txt: -------------------------------------------------------------------------------- 1 | Just a dummy file 2 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/test_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/tests/sphinx_supp_py2/raw_examples/test_image.png -------------------------------------------------------------------------------- /tests/sphinx_supp_py2/raw_examples/thumb/sphx_glr_test_image_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/tests/sphinx_supp_py2/raw_examples/thumb/sphx_glr_test_image_thumb.png -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import os.path as osp 4 | 5 | dirname = osp.dirname(__file__) 6 | 7 | project = 'sphinx-test' 8 | 9 | master_doc = 'index' 10 | 11 | extensions = ['sphinx_nbexamples'] 12 | 13 | example_gallery_config = { 14 | 'examples_dirs': osp.join(dirname, 'raw_examples'), 15 | 'gallery_dirs': osp.join(dirname, 'examples'), 16 | 'code_examples': {osp.join(dirname, 'raw_examples', 17 | 'example_hello_world.ipynb'): 'someothercode'}, 18 | 'thumbnail_figures': { 19 | osp.join(dirname, 'raw_examples', 20 | 'example_mpl_test_figure_chosen.ipynb'): 0}, 21 | 'supplementary_files': { 22 | osp.join(dirname, 'raw_examples', 23 | 'example_hello_world.ipynb'): ['test2.txt']}, 24 | 'remove_cell_tags': ['remove_in_docs'], 25 | 'toctree_depth': 2, 26 | } 27 | 28 | exclude_patterns = ['raw_examples'] 29 | 30 | 31 | try: 32 | import pathlib 33 | 34 | def file2html(fname): 35 | return pathlib.Path(fname).as_uri() 36 | 37 | except ImportError: 38 | pathlib = None 39 | 40 | 41 | _link_dir = os.getenv('LINKGALLERYTO') 42 | if _link_dir: 43 | extensions.append('sphinx.ext.intersphinx') 44 | intersphinx_mapping = {'sphinx_nbexamples': ( 45 | file2html(_link_dir), osp.join(_link_dir, 'objects.inv'))} 46 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/index.rst: -------------------------------------------------------------------------------- 1 | Example documentation 2 | ===================== 3 | 4 | .. toctree:: 5 | 6 | examples/index 7 | 8 | .. linkgalleries:: 9 | 10 | sphinx-test 11 | sphinx_nbexamples 12 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/README.rst: -------------------------------------------------------------------------------- 1 | Some examples for testing 2 | ========================= -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_bash.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "# Bash example\n", 9 | "\n", 10 | "\n", 11 | "This example notebook uses a Bash kernel.\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": null, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "# A basic hello, world in Bash\n", 21 | "\n", 22 | "function hello {\n", 23 | " OUT=hello\n", 24 | " echo $OUT, world\n", 25 | "}" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "hello" 35 | ] 36 | } 37 | ], 38 | "metadata": { 39 | "kernelspec": { 40 | "display_name": "Bash", 41 | "language": "bash", 42 | "name": "bash" 43 | }, 44 | "language_info": { 45 | "codemirror_mode": "shell", 46 | "file_extension": ".sh", 47 | "mimetype": "text/x-sh", 48 | "name": "bash" 49 | } 50 | }, 51 | "nbformat": 4, 52 | "nbformat_minor": 2 53 | } 54 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_code_example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Example with a code command instead of a figure\n", 8 | "===============\n", 9 | "This test notebook has the ```code_example``` metadata attribute specified to be shown instead of a thumbnail" 10 | ] 11 | } 12 | ], 13 | "metadata": { 14 | "code_example": "somecode", 15 | "kernelspec": { 16 | "display_name": "Python 3", 17 | "language": "python", 18 | "name": "python3" 19 | }, 20 | "language_info": { 21 | "codemirror_mode": { 22 | "name": "ipython", 23 | "version": 3 24 | }, 25 | "file_extension": ".py", 26 | "mimetype": "text/x-python", 27 | "name": "python", 28 | "nbconvert_exporter": "python", 29 | "pygments_lexer": "ipython3", 30 | "version": "3.5.0rc4" 31 | } 32 | }, 33 | "nbformat": 4, 34 | "nbformat_minor": 0 35 | } 36 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_failure.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Expexted Failure\n", 8 | "=========\n", 9 | "Test whether the gallery can handle failing notebooks" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "collapsed": false 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "assert 1 == 2, \"Failed\"" 21 | ] 22 | } 23 | ], 24 | "metadata": { 25 | "kernelspec": { 26 | "display_name": "Python 3", 27 | "language": "python", 28 | "name": "python3" 29 | }, 30 | "language_info": { 31 | "codemirror_mode": { 32 | "name": "ipython", 33 | "version": 3 34 | }, 35 | "file_extension": ".py", 36 | "mimetype": "text/x-python", 37 | "name": "python", 38 | "nbconvert_exporter": "python", 39 | "pygments_lexer": "ipython3", 40 | "version": "3.5.0rc4" 41 | }, 42 | "thumbnail_figure": "test_image.png" 43 | }, 44 | "nbformat": 4, 45 | "nbformat_minor": 0 46 | } 47 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_hello_world.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hello World\n", 8 | "Just a simple example" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "metadata": { 15 | "collapsed": false 16 | }, 17 | "outputs": [], 18 | "source": [ 19 | "print(\"Hello World!\")" 20 | ] 21 | } 22 | ], 23 | "metadata": { 24 | "kernelspec": { 25 | "display_name": "Python 3", 26 | "language": "python", 27 | "name": "python3" 28 | }, 29 | "language_info": { 30 | "codemirror_mode": { 31 | "name": "ipython", 32 | "version": 3 33 | }, 34 | "file_extension": ".py", 35 | "mimetype": "text/x-python", 36 | "name": "python", 37 | "nbconvert_exporter": "python", 38 | "pygments_lexer": "ipython3", 39 | "version": "3.5.0rc4" 40 | } 41 | }, 42 | "nbformat": 4, 43 | "nbformat_minor": 0 44 | } 45 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_magics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Example with magics\n", 8 | "==========" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "The usual matplotlib inline as an example before, between and after a python commands" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 1, 21 | "metadata": { 22 | "collapsed": true, 23 | "scrolled": false 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "%matplotlib inline\n", 28 | "import matplotlib as mpl\n", 29 | "%matplotlib inline\n", 30 | "a = 10\n", 31 | "%matplotlib inline" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "A single magic" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 2, 44 | "metadata": { 45 | "collapsed": false 46 | }, 47 | "outputs": [ 48 | { 49 | "name": "stdout", 50 | "output_type": "stream", 51 | "text": [ 52 | "/Users/psommer\n" 53 | ] 54 | } 55 | ], 56 | "source": [ 57 | "%cd" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "Something with %test inside a markdown text" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 1, 70 | "metadata": { 71 | "collapsed": false 72 | }, 73 | "outputs": [ 74 | { 75 | "name": "stdout", 76 | "output_type": "stream", 77 | "text": [ 78 | "Something %magic like inside a python code\n" 79 | ] 80 | } 81 | ], 82 | "source": [ 83 | "print('Something %magic like inside a python code')" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 1, 89 | "metadata": { 90 | "collapsed": false 91 | }, 92 | "outputs": [ 93 | { 94 | "name": "stdout", 95 | "output_type": "stream", 96 | "text": [ 97 | "%magic okay\n" 98 | ] 99 | } 100 | ], 101 | "source": [ 102 | "print('%magic okay')" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": { 109 | "collapsed": true 110 | }, 111 | "outputs": [], 112 | "source": [] 113 | } 114 | ], 115 | "metadata": { 116 | "kernelspec": { 117 | "display_name": "Python 3", 118 | "language": "python", 119 | "name": "python3" 120 | }, 121 | "language_info": { 122 | "codemirror_mode": { 123 | "name": "ipython", 124 | "version": 3 125 | }, 126 | "file_extension": ".py", 127 | "mimetype": "text/x-python", 128 | "name": "python", 129 | "nbconvert_exporter": "python", 130 | "pygments_lexer": "ipython3", 131 | "version": "3.5.0rc4" 132 | } 133 | }, 134 | "nbformat": 4, 135 | "nbformat_minor": 0 136 | } 137 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_mpl_test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Matplotlib test\n", 8 | "==========\n", 9 | "Test if the matplotlib thumbnail is inserted correctly" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "collapsed": true 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "%matplotlib inline\n", 21 | "import matplotlib.pyplot as plt" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": { 28 | "collapsed": true 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "plt.plot([6, 7])" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": { 39 | "collapsed": true 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "plt.plot([4, 3])" 44 | ] 45 | } 46 | ], 47 | "metadata": { 48 | "kernelspec": { 49 | "display_name": "Python 3", 50 | "language": "python", 51 | "name": "python3" 52 | }, 53 | "language_info": { 54 | "codemirror_mode": { 55 | "name": "ipython", 56 | "version": 3 57 | }, 58 | "file_extension": ".py", 59 | "mimetype": "text/x-python", 60 | "name": "python", 61 | "nbconvert_exporter": "python", 62 | "pygments_lexer": "ipython3", 63 | "version": "3.5.0rc4" 64 | } 65 | }, 66 | "nbformat": 4, 67 | "nbformat_minor": 0 68 | } 69 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_mpl_test_figure_chosen.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Matplotlib test\n", 8 | "==========\n", 9 | "Test if the matplotlib thumbnail is inserted correctly" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "collapsed": true 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "%matplotlib inline\n", 21 | "import matplotlib.pyplot as plt" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": { 28 | "collapsed": false 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "plt.plot([6, 7])" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": { 39 | "collapsed": false 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "plt.plot([4, 3])" 44 | ] 45 | } 46 | ], 47 | "metadata": { 48 | "kernelspec": { 49 | "display_name": "Python 3", 50 | "language": "python", 51 | "name": "python3" 52 | }, 53 | "language_info": { 54 | "codemirror_mode": { 55 | "name": "ipython", 56 | "version": 3 57 | }, 58 | "file_extension": ".py", 59 | "mimetype": "text/x-python", 60 | "name": "python", 61 | "nbconvert_exporter": "python", 62 | "pygments_lexer": "ipython3", 63 | "version": "3.5.0rc4" 64 | } 65 | }, 66 | "nbformat": 4, 67 | "nbformat_minor": 0 68 | } 69 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/example_tag_removal.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Example for testing the removal of cells\n", 8 | "This example includes a cell that should be removed" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": 1, 14 | "metadata": { 15 | "tags": [ 16 | "remove_in_docs" 17 | ] 18 | }, 19 | "outputs": [ 20 | { 21 | "name": "stdout", 22 | "output_type": "stream", 23 | "text": [ 24 | "This should be removed!\n" 25 | ] 26 | } 27 | ], 28 | "source": [ 29 | "print(\"This should be removed!\")" 30 | ] 31 | } 32 | ], 33 | "metadata": { 34 | "celltoolbar": "Tags", 35 | "kernelspec": { 36 | "display_name": "python3", 37 | "language": "python", 38 | "name": "python3" 39 | }, 40 | "language_info": { 41 | "codemirror_mode": { 42 | "name": "ipython", 43 | "version": 3 44 | }, 45 | "file_extension": ".py", 46 | "mimetype": "text/x-python", 47 | "name": "python", 48 | "nbconvert_exporter": "python", 49 | "pygments_lexer": "ipython3", 50 | "version": "3.6.2" 51 | } 52 | }, 53 | "nbformat": 4, 54 | "nbformat_minor": 2 55 | } 56 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/sub/README.md: -------------------------------------------------------------------------------- 1 | Some additional examples in a subfolder 2 | ======================================= 3 | 4 | This is [a markdown link](https://www.google.de/). 5 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/sub/example_supplementary_files.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "Test with supplementary files\n", 8 | "=============================\n", 9 | "This notebook requires some supplementary files which should be included in the documentation" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "collapsed": false 17 | }, 18 | "outputs": [ 19 | { 20 | "name": "stdout", 21 | "output_type": "stream", 22 | "text": [ 23 | "Just a dummy file\n", 24 | "\n" 25 | ] 26 | } 27 | ], 28 | "source": [ 29 | "with open('test.txt')as f:\n", 30 | " print(f.read())" 31 | ] 32 | } 33 | ], 34 | "metadata": { 35 | "kernelspec": { 36 | "display_name": "Python 3", 37 | "language": "python", 38 | "name": "python3" 39 | }, 40 | "language_info": { 41 | "codemirror_mode": { 42 | "name": "ipython", 43 | "version": 3 44 | }, 45 | "file_extension": ".py", 46 | "mimetype": "text/x-python", 47 | "name": "python", 48 | "nbconvert_exporter": "python", 49 | "pygments_lexer": "ipython3", 50 | "version": "3.5.0rc4" 51 | }, 52 | "supplementary_files": [ 53 | "test.txt" 54 | ] 55 | }, 56 | "nbformat": 4, 57 | "nbformat_minor": 0 58 | } 59 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/sub/example_toctree.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hello World\n", 8 | "Just a simple example" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## With a subsection" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": null, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "print(\"Hello World!\")" 25 | ] 26 | } 27 | ], 28 | "metadata": { 29 | "kernelspec": { 30 | "display_name": "Python 3", 31 | "language": "python", 32 | "name": "python3" 33 | }, 34 | "language_info": { 35 | "codemirror_mode": { 36 | "name": "ipython", 37 | "version": 3 38 | }, 39 | "file_extension": ".py", 40 | "mimetype": "text/x-python", 41 | "name": "python", 42 | "nbconvert_exporter": "python", 43 | "pygments_lexer": "ipython3", 44 | "version": "3.7.1" 45 | } 46 | }, 47 | "nbformat": 4, 48 | "nbformat_minor": 1 49 | } 50 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/sub/test.txt: -------------------------------------------------------------------------------- 1 | Just a dummy file 2 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/test2.txt: -------------------------------------------------------------------------------- 1 | Just a dummy file 2 | -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/test_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/tests/sphinx_supp_py3/raw_examples/test_image.png -------------------------------------------------------------------------------- /tests/sphinx_supp_py3/raw_examples/thumb/sphx_glr_test_image_thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chilipp/sphinx-nbexamples/4a06abe2fd991fd89349e598690dac44521b572e/tests/sphinx_supp_py3/raw_examples/thumb/sphx_glr_test_image_thumb.png -------------------------------------------------------------------------------- /tests/test_sphinx_nbexamples.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import os.path as osp 4 | import unittest 5 | from tempfile import mkdtemp 6 | from sphinx.application import Sphinx 7 | import sphinx 8 | import glob 9 | import shutil 10 | import six 11 | try: 12 | import pathlib 13 | except ImportError: 14 | pathlib = None 15 | 16 | 17 | if six.PY2: 18 | sphinx_supp = osp.abspath(osp.join(osp.dirname(__file__), 19 | 'sphinx_supp_py2')) 20 | else: 21 | sphinx_supp = osp.abspath(osp.join(osp.dirname(__file__), 22 | 'sphinx_supp_py3')) 23 | 24 | 25 | def find_files(src_dir, pattern, skip_private=True): 26 | """Find all files recursively contained in `src_dir` 27 | 28 | Parameters 29 | ---------- 30 | src_dir: str 31 | The toplevel directory 32 | pattern: str 33 | A file pattern suitable for glob 34 | skip_private: bool 35 | If True, directories with starting with single ``'.'`` are ignored""" 36 | for root, dirs, files in os.walk(src_dir): 37 | dirname = osp.basename(root) 38 | if skip_private and dirname != '.' and dirname.startswith('.'): 39 | continue 40 | for f in glob.fnmatch.filter(files, pattern): 41 | yield osp.join(root, f) 42 | 43 | 44 | class BaseTest(unittest.TestCase): 45 | 46 | def setUp(self): 47 | self.src_dir = mkdtemp(prefix='tmp_nbexamples_') 48 | os.rmdir(self.src_dir) 49 | self.out_dir = osp.join(self.src_dir, 'build', 'html') 50 | shutil.copytree(sphinx_supp, self.src_dir) 51 | 52 | self.app = Sphinx( 53 | srcdir=self.src_dir, confdir=self.src_dir, outdir=self.out_dir, 54 | doctreedir=osp.join(self.src_dir, 'build', 'doctrees'), 55 | buildername='html') 56 | self.app.build() 57 | 58 | def tearDown(self): 59 | shutil.rmtree(self.src_dir) 60 | 61 | 62 | class TestGallery(BaseTest): 63 | 64 | def test_files_exist(self): 65 | """Test if all notebooks are processed correctly""" 66 | raw_dir = osp.join(self.src_dir, 'raw_examples') 67 | for f in find_files(raw_dir, 68 | 'example_*.ipynb'): 69 | base = osp.splitext(f)[0].replace( 70 | raw_dir, osp.join(self.src_dir, 'examples')) 71 | self.assertTrue(osp.exists(base + '.ipynb'), 72 | msg=base + '.ipynb is missing') 73 | self.assertTrue(osp.exists(base + '.rst'), 74 | msg=base + '.rst is missing') 75 | script = base + ('.sh' if base.endswith('bash') else '.py') 76 | self.assertTrue(osp.exists(script), 77 | msg=script + ' is missing') 78 | html = osp.splitext( 79 | f.replace(raw_dir, osp.join( 80 | self.out_dir, 'examples')))[0] + '.html' 81 | self.assertTrue(osp.exists(html), msg=html + ' is missing!') 82 | 83 | def test_thumbnail(self): 84 | """Test if the thumbnail has been inserted correctly""" 85 | base = osp.join(self.src_dir, 'examples', 'example_mpl_test.ipynb') 86 | outdir = self.out_dir 87 | thumb = osp.join(self.src_dir, 'examples', 'images', 'thumb', 88 | 'gallery_' + base.replace(os.path.sep, '_').lower() + 89 | '_thumb.png') 90 | self.assertTrue(osp.exists(thumb), msg=thumb + ' is missing!') 91 | with open(osp.join(outdir, 'examples', 'index.html')) as f: 92 | index_html = f.read() 93 | self.assertIn(osp.basename(thumb), index_html) 94 | 95 | def test_failure(self): 96 | """Test if a failed notebook is anyway existent""" 97 | base = 'example_failure' 98 | html_path = osp.join(self.out_dir, 'examples', base) + '.html' 99 | self.assertTrue(osp.exists(html_path), 100 | msg=html_path + ' is missing!') 101 | with open(html_path) as f: 102 | html = f.read() 103 | self.assertIn('AssertionError', html) 104 | 105 | def test_magics(self): 106 | """Test whether ipython magics are removed correctly""" 107 | base = 'example_magics' 108 | rst_path = osp.join(self.src_dir, 'examples', base) + '.rst' 109 | with open(rst_path) as f: 110 | rst = f.read() 111 | # test if both '%magic okay' statements are still in the file 112 | self.assertIsNotNone( 113 | re.search(r'\(.%magic okay.\)', rst), 114 | msg="Print command 'print('%%magic okay')' not found in \n%s!" % ( 115 | rst)) 116 | self.assertIsNotNone( 117 | re.search(r'(?', html) 204 | 205 | def test_toctree(self): 206 | """Test whether the toctree depth is working""" 207 | html_path = osp.join(self.out_dir, 'examples', 'index.html') 208 | self.assertTrue(osp.exists(html_path), 209 | msg=html_path + ' is missing!') 210 | with open(html_path) as f: 211 | html = f.read() 212 | self.assertNotIn('With a subsection', html) 213 | 214 | def test_bash(self): 215 | """Test a non-python notebook""" 216 | base = 'example_bash' 217 | rst_path = osp.join(self.src_dir, 'examples', base) + '.rst' 218 | with open(rst_path) as f: 219 | rst = f.read() 220 | self.assertIn('hello, world', rst) 221 | 222 | 223 | class TestWarnings(BaseTest): 224 | 225 | def setUp(self): 226 | pass 227 | 228 | def _setUp(self): 229 | super().setUp() 230 | 231 | @unittest.skipIf(int(sphinx.__version__.split('.')[0]) != 3, 232 | "Test implemented for sphinx 3.0") 233 | @unittest.expectedFailure 234 | def test_stylesheet_warning(self): 235 | """Test whether the app.add_stylesheet() warning is triggered 236 | 237 | See https://github.com/Chilipp/sphinx-nbexamples/issues/14""" 238 | from sphinx.application import RemovedInSphinx40Warning 239 | self.assertWarnsRegex( 240 | RemovedInSphinx40Warning, '.*Please use app.add_css_file', 241 | self._setUp) 242 | 243 | 244 | @unittest.skipIf(pathlib is None, 'The pathlib package is required!') 245 | class TestLinkGalleries(BaseTest): 246 | 247 | def tearDown(self): 248 | shutil.rmtree(self.src_dir2) 249 | super(TestLinkGalleries, self).tearDown() 250 | 251 | def test_linkgalleries(self): 252 | """Test the directive""" 253 | self.src_dir2 = self.src_dir 254 | self.out_dir2 = self.out_dir 255 | os.environ['LINKGALLERYTO'] = self.out_dir 256 | fname = osp.join( 257 | self.out_dir, 'examples', 'example_mpl_test.html') 258 | self.assertTrue(osp.exists(fname), msg=fname + ' is missing!') 259 | thumbnail = osp.join( 260 | self.out_dir, '_images', 261 | 'gallery_' + self.src_dir.replace(os.path.sep, '_').lower() + 262 | '_examples_example_mpl_test.ipynb_thumb.png') 263 | self.assertTrue(osp.exists(thumbnail), msg=thumbnail + ' is missing!') 264 | # create a setup with the links 265 | self.setUp() 266 | self.assertTrue 267 | html_path = osp.join(self.out_dir, 'index.html') 268 | self.assertTrue(osp.exists(html_path), 269 | msg=html_path + ' is missing!') 270 | with open(html_path) as f: 271 | html = f.read() 272 | self.assertIn(osp.basename(thumbnail), html) 273 | 274 | # test with new thumbnail to test the linkgalleries with it's own 275 | # project 276 | thumbnails = glob.glob(osp.join( 277 | self.out_dir, '_images', 278 | 'gallery_' + self.src_dir.replace(os.path.sep, '_').lower() + 279 | '_examples_example_mpl_test.ipynb_thumb*.png')) 280 | self.assertTrue(thumbnails) # check that some thumbnails are found 281 | self.assertTrue(any(osp.relpath(f, self.out_dir) in html 282 | for f in thumbnails), 283 | msg='None of %s found in %s' % (thumbnails, html)) 284 | 285 | 286 | def _test_url(url, *args, **kwargs): 287 | if six.PY3: 288 | from urllib import request 289 | request.urlopen(url, *args, **kwargs) 290 | else: 291 | import urllib 292 | urllib.urlopen(url, *args, **kwargs) 293 | 294 | # check if we are online by trying to connect to google 295 | try: 296 | _test_url('https://www.google.de') 297 | online = True 298 | except: 299 | online = False 300 | 301 | 302 | if __name__ == '__main__': 303 | unittest.main() 304 | --------------------------------------------------------------------------------