├── .gitignore ├── .noserc ├── .travis.yml ├── Automation.ipynb ├── LICENSE ├── MANIFEST.in ├── README.ipynb ├── README.rst ├── nosebook.py ├── requirements-dev.txt ├── requirements.txt ├── setup.cfg ├── setup.py └── tests ├── __init__.py ├── py2 ├── __init__.py ├── ipy2 │ ├── Scrubbing.ipynb │ ├── Test Simple.ipynb │ └── __init__.py └── ipy3 │ ├── Scrubbing.ipynb │ ├── Test Simple.ipynb │ └── __init__.py ├── py3 ├── __init__.py ├── ipy2 │ ├── Scrubbing.ipynb │ ├── Test Simple.ipynb │ └── __init__.py └── ipy3 │ ├── Scrubbing.ipynb │ ├── Test Simple.ipynb │ └── __init__.py ├── test_plugin.py └── test_scrub.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | .ipynb_checkpoints 3 | __pycache__ 4 | *.pyc 5 | build/ 6 | dist/ 7 | -------------------------------------------------------------------------------- /.noserc: -------------------------------------------------------------------------------- 1 | [nosetests] 2 | verbosity=1 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: false 3 | python: 4 | - 2.7 5 | - 3.4 6 | env: 7 | - IP_VERSION=">=2.0,<3.0" 8 | - IP_VERSION=">=3.0,<4.0" 9 | install: 10 | - pip install IPython${IP_VERSION} 11 | - ipython --version 12 | - pip install -r requirements-dev.txt 13 | - python setup.py develop 14 | script: 15 | - python -m flake8 *.py tests/*.py 16 | - python setup.py test 17 | -------------------------------------------------------------------------------- /Automation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Automation\n", 8 | "Nothing too fancy here." 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "### Run tests" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": null, 21 | "metadata": { 22 | "collapsed": false 23 | }, 24 | "outputs": [], 25 | "source": [ 26 | "!python setup.py test" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "### Check code style" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": null, 39 | "metadata": { 40 | "collapsed": false 41 | }, 42 | "outputs": [], 43 | "source": [ 44 | "!flake8 *.py tests/*.py" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "### Generate `README.md` from `README.ipynb`" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": { 58 | "collapsed": false 59 | }, 60 | "outputs": [], 61 | "source": [ 62 | "!ipython nbconvert README.ipynb --to=rst" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "## Test Release for PyPi" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": { 76 | "collapsed": false 77 | }, 78 | "outputs": [], 79 | "source": [ 80 | "!python setup.py register -r pypitest\n", 81 | "!python setup.py sdist\n", 82 | "!python setup.py bdist_wheel\n", 83 | "!python setup.py sdist upload -r pypitest\n", 84 | "!python setup.py bdist_wheel upload -r pypitest" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "# Cut a real release for PyPi" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "collapsed": true 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "!python setup.py register -r pypi\n", 103 | "!python setup.py sdist\n", 104 | "!python setup.py bdist_wheel\n", 105 | "!python setup.py sdist upload -r pypi\n", 106 | "!python setup.py bdist_wheel upload -r pypi" 107 | ] 108 | } 109 | ], 110 | "metadata": { 111 | "kernelspec": { 112 | "display_name": "Python 3", 113 | "language": "python", 114 | "name": "python3" 115 | }, 116 | "language_info": { 117 | "codemirror_mode": { 118 | "name": "ipython", 119 | "version": 3 120 | }, 121 | "file_extension": ".py", 122 | "mimetype": "text/x-python", 123 | "name": "python", 124 | "nbconvert_exporter": "python", 125 | "pygments_lexer": "ipython3", 126 | "version": "3.4.2" 127 | } 128 | }, 129 | "nbformat": 4, 130 | "nbformat_minor": 0 131 | } 132 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Nicholas Bollweg 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include *.rst 3 | include *.ipynb 4 | -------------------------------------------------------------------------------- /README.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# nosebook\n", 8 | "[![Build Status][build_svg]][build_status] [![PyPI][pypi_svg]][pypi] [![BSD][license_svg]][license]\n", 9 | "\n", 10 | "\n", 11 | "a [nose](http://nose.readthedocs.org/) plugin for finding and running IPython 2/3 notebooks as nose tests.\n", 12 | "\n", 13 | "What it can't do in terms of `setup` and `tearDown`, `nosebook` makes up for in simplicity: there is no `%%nose` magic, no metadata required: the notebook on disk is the \"gold master\".\n", 14 | "\n", 15 | "This makes it ideal for decreasing the burden of keeping documentation up to date with tests by making a single set of notebooks into both rich, multi-format documentation and a simple part of your test suite.\n", 16 | "\n", 17 | "\n", 18 | "[build_svg]: https://travis-ci.org/bollwyvl/nosebook.svg?branch=master\n", 19 | "[build_status]: https://travis-ci.org/bollwyvl/nosebook\n", 20 | "[pypi_svg]: https://pypip.in/version/nosebook/badge.svg?style=flat\n", 21 | "[pypi]: https://pypi.python.org/pypi/nosebook\n", 22 | "[license_svg]: https://pypip.in/license/nose-watcher/badge.svg\n", 23 | "[license]: ./LICENSE" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## How does it work?\n", 31 | "Each notebook found according to [`nosebook-match`](#nosebook-match) is started with a fresh kernel, based on the kernel specified in the notebook. If the kernel is not installed, no tests will be run and the error will be logged.\n", 32 | "\n", 33 | "Each `code` cell that matches [`nosebook-match-cell`](#nosebook-match-cell) will be executed against the kernel in the order in which it appears in the notebook: other cells e.g. `markdown`, `raw`, are ignored.\n", 34 | "\n", 35 | "The number and content of outputs has to __match exactly__, with the following parts of each output stripped:\n", 36 | "\n", 37 | "- execution/prompt numbers, i.e. `[1]:`\n", 38 | "- tracebacks\n", 39 | "\n", 40 | "Non-deterministic output, such as with `_repr_` methods that include the memory location of the instance, will obviously not match every time. You can use [`nosebook-scrub`](#nosebook-scrub) to rewrite or remove offending content." 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "## Related work\n", 48 | "- [`ipython_nose`](http://github.com/taavi/ipython_nose) allows you to use a notebook as a nose runner, with traditional `test_whatever` methods. You can sort of emulate this behavior with [`nosebook-match-cell`](#nosebook-match-cel)... as long as you check in passing tests!" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "## Configuring `nosetests` to use `nosebook`\n", 56 | "These options can be specified in your [nose config file](./.noserc), or as long-form command line arguments, i.e. `--with-nosebook`." 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "#### `with-nosebook`\n", 64 | "`nosetests` will look for notebooks that seem like tests, as configured with [`nosebook-match`](#nosebook-match). \n", 65 | "\n", 66 | "_Default: False_" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": { 73 | "collapsed": false 74 | }, 75 | "outputs": [], 76 | "source": [ 77 | "# Basic usage\n", 78 | "!nosetests --with-nosebook" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "#### `nosebook-match`\n", 86 | "A regular expression that tells nosebook what should be a testable notebook.\n", 87 | "\n", 88 | "_Default: `.*[Tt]est.*.ipynb$`_" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": null, 94 | "metadata": { 95 | "collapsed": false 96 | }, 97 | "outputs": [], 98 | "source": [ 99 | "# Run against all notebooks... probably not a good idea, but maybe a great idea\n", 100 | "!nosetests --with-nosebook --nosebook-match .*.ipynb" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "#### `nosebook-match-cell`\n", 108 | "A regular expression that will be replaced throughout the expected outputs and generated outputs.\n", 109 | "\n", 110 | "_Default: None_" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": { 117 | "collapsed": false 118 | }, 119 | "outputs": [], 120 | "source": [ 121 | "# will run cells where tests are defined... but you should probably run them, too\n", 122 | "!nosetests --with-nosebook --nosebook-match .*Simple.* --nosebook-match-cell '(def|class).*[Tt]est'" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "#### `nosebook-scrub`\n", 130 | "A regular expression that will be replaced throughout the expected outputs and generated outputs.\n", 131 | "\n", 132 | "_Default: None_" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": { 139 | "collapsed": false 140 | }, 141 | "outputs": [], 142 | "source": [ 143 | "# you can't fail if you don't try\n", 144 | "!nosetests --with-nosebook --nosebook-scrub .+" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "For multiple scrub values, you can pass a JSON-formatted list of regular expressions or object of pattern-replacement pairs that will be replaced. When passed in via the command line, you'll have to escape special characters: using a `.noserc` config file makes this easier." 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "metadata": { 158 | "collapsed": false 159 | }, 160 | "outputs": [], 161 | "source": [ 162 | "# there are only 10 kinds of tests...\n", 163 | "!nosetests --with-nosebook --nosebook-scrub='[\"0\", \"1\"]'" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": { 170 | "collapsed": false 171 | }, 172 | "outputs": [], 173 | "source": [ 174 | "# 0 is equally good\n", 175 | "!nosetests --with-nosebook --nosebook-scrub='{\"\\\\d+\": \"0\"}'" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "## Contributing\n", 183 | "[Issues](https://github.com/bollwyvl/nosebook/issues) and [pull requests](https://github.com/bollwyvl/nosebook/pulls) welcome!" 184 | ] 185 | }, 186 | { 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "## License\n", 191 | "`nosebook` is released as free software under the [BSD 3-Clause license](./LICENSE)." 192 | ] 193 | } 194 | ], 195 | "metadata": { 196 | "kernelspec": { 197 | "display_name": "Python 3", 198 | "language": "python", 199 | "name": "python3" 200 | }, 201 | "language_info": { 202 | "codemirror_mode": { 203 | "name": "ipython", 204 | "version": 3 205 | }, 206 | "file_extension": ".py", 207 | "mimetype": "text/x-python", 208 | "name": "python", 209 | "nbconvert_exporter": "python", 210 | "pygments_lexer": "ipython3", 211 | "version": "3.4.2" 212 | } 213 | }, 214 | "nbformat": 4, 215 | "nbformat_minor": 0 216 | } 217 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | 2 | nosebook 3 | ======== 4 | 5 | |Build Status| |PyPI| |BSD| 6 | 7 | a `nose `__ plugin for finding and running 8 | IPython 2/3 notebooks as nose tests. 9 | 10 | What it can't do in terms of ``setup`` and ``tearDown``, ``nosebook`` 11 | makes up for in simplicity: there is no ``%%nose`` magic, no metadata 12 | required: the notebook on disk is the "gold master". 13 | 14 | This makes it ideal for decreasing the burden of keeping documentation 15 | up to date with tests by making a single set of notebooks into both 16 | rich, multi-format documentation and a simple part of your test suite. 17 | 18 | .. |Build Status| image:: https://travis-ci.org/bollwyvl/nosebook.svg?branch=master 19 | :target: https://travis-ci.org/bollwyvl/nosebook 20 | .. |PyPI| image:: https://pypip.in/version/nosebook/badge.svg?style=flat 21 | :target: https://pypi.python.org/pypi/nosebook 22 | .. |BSD| image:: https://pypip.in/license/nose-watcher/badge.svg 23 | :target: ./LICENSE 24 | 25 | How does it work? 26 | ----------------- 27 | 28 | Each notebook found according to 29 | ```nosebook-match`` <#nosebook-match>`__ is started with a fresh kernel, 30 | based on the kernel specified in the notebook. If the kernel is not 31 | installed, no tests will be run and the error will be logged. 32 | 33 | Each ``code`` cell that matches 34 | ```nosebook-match-cell`` <#nosebook-match-cell>`__ will be executed 35 | against the kernel in the order in which it appears in the notebook: 36 | other cells e.g. ``markdown``, ``raw``, are ignored. 37 | 38 | The number and content of outputs has to **match exactly**, with the 39 | following parts of each output stripped: 40 | 41 | - execution/prompt numbers, i.e. ``[1]:`` 42 | - tracebacks 43 | 44 | Non-deterministic output, such as with ``_repr_`` methods that include 45 | the memory location of the instance, will obviously not match every 46 | time. You can use ```nosebook-scrub`` <#nosebook-scrub>`__ to rewrite or 47 | remove offending content. 48 | 49 | Related work 50 | ------------ 51 | 52 | - ```ipython_nose`` `__ allows 53 | you to use a notebook as a nose runner, with traditional 54 | ``test_whatever`` methods. You can sort of emulate this behavior with 55 | ```nosebook-match-cell`` <#nosebook-match-cel>`__... as long as you 56 | check in passing tests! 57 | 58 | Configuring ``nosetests`` to use ``nosebook`` 59 | --------------------------------------------- 60 | 61 | These options can be specified in your `nose config file <./.noserc>`__, 62 | or as long-form command line arguments, i.e. ``--with-nosebook``. 63 | 64 | ``with-nosebook`` 65 | ^^^^^^^^^^^^^^^^^ 66 | 67 | ``nosetests`` will look for notebooks that seem like tests, as 68 | configured with ```nosebook-match`` <#nosebook-match>`__. 69 | 70 | *Default: False* 71 | 72 | .. code:: python 73 | 74 | # Basic usage 75 | !nosetests --with-nosebook 76 | 77 | ``nosebook-match`` 78 | ^^^^^^^^^^^^^^^^^^ 79 | 80 | A regular expression that tells nosebook what should be a testable 81 | notebook. 82 | 83 | *Default: ``.*[Tt]est.*.ipynb$``* 84 | 85 | .. code:: python 86 | 87 | # Run against all notebooks... probably not a good idea, but maybe a great idea 88 | !nosetests --with-nosebook --nosebook-match .*.ipynb 89 | 90 | ``nosebook-match-cell`` 91 | ^^^^^^^^^^^^^^^^^^^^^^^ 92 | 93 | A regular expression that will be replaced throughout the expected 94 | outputs and generated outputs. 95 | 96 | *Default: None* 97 | 98 | .. code:: python 99 | 100 | # will run cells where tests are defined... but you should probably run them, too 101 | !nosetests --with-nosebook --nosebook-match .*Simple.* --nosebook-match-cell '(def|class).*[Tt]est' 102 | 103 | ``nosebook-scrub`` 104 | ^^^^^^^^^^^^^^^^^^ 105 | 106 | A regular expression that will be replaced throughout the expected 107 | outputs and generated outputs. 108 | 109 | *Default: None* 110 | 111 | .. code:: python 112 | 113 | # you can't fail if you don't try 114 | !nosetests --with-nosebook --nosebook-scrub .+ 115 | 116 | For multiple scrub values, you can pass a JSON-formatted list of regular 117 | expressions or object of pattern-replacement pairs that will be 118 | replaced. When passed in via the command line, you'll have to escape 119 | special characters: using a ``.noserc`` config file makes this easier. 120 | 121 | .. code:: python 122 | 123 | # there are only 10 kinds of tests... 124 | !nosetests --with-nosebook --nosebook-scrub='["0", "1"]' 125 | 126 | .. code:: python 127 | 128 | # 0 is equally good 129 | !nosetests --with-nosebook --nosebook-scrub='{"\\d+": "0"}' 130 | 131 | Contributing 132 | ------------ 133 | 134 | `Issues `__ and `pull 135 | requests `__ welcome! 136 | 137 | License 138 | ------- 139 | 140 | ``nosebook`` is released as free software under the `BSD 3-Clause 141 | license <./LICENSE>`__. 142 | -------------------------------------------------------------------------------- /nosebook.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import re 4 | import json 5 | from copy import copy 6 | 7 | try: 8 | # py3 9 | from queue import Empty 10 | 11 | def isstr(s): 12 | return isinstance(s, str) 13 | except ImportError: 14 | # py2 15 | from Queue import Empty 16 | 17 | def isstr(s): 18 | return isinstance(s, basestring) # noqa 19 | 20 | from unittest import TestCase 21 | 22 | from nose.plugins import Plugin 23 | 24 | 25 | try: 26 | from ipykernel.tests import utils 27 | from nbformat.converter import convert 28 | from nbformat.reader import reads 29 | IPYTHON_VERSION = 4 30 | except ImportError: 31 | from IPython.kernel.tests import utils 32 | try: 33 | from IPython.nbformat.converter import convert 34 | from IPython.nbformat.reader import reads 35 | IPYTHON_VERSION = 3 36 | except ImportError: 37 | from IPython.nbformat.convert import convert 38 | from IPython.nbformat.reader import reads 39 | IPYTHON_VERSION = 2 40 | 41 | NBFORMAT_VERSION = 4 42 | 43 | __version__ = "0.4.0" 44 | 45 | log = logging.getLogger("nose.plugins.nosebook") 46 | 47 | 48 | class NosebookTwo(object): 49 | """ 50 | Implement necessary functions against the IPython 2.x API 51 | """ 52 | 53 | def newKernel(self, nb): 54 | """ 55 | generate a new kernel 56 | """ 57 | manager, kernel = utils.start_new_kernel() 58 | return kernel 59 | 60 | 61 | class NosebookThree(object): 62 | """ 63 | Implement necessary functions against the IPython 3.x API 64 | """ 65 | def newKernel(self, nb): 66 | """ 67 | generate a new kernel 68 | """ 69 | manager, kernel = utils.start_new_kernel( 70 | kernel_name=nb.metadata.kernelspec.name 71 | ) 72 | return kernel 73 | 74 | 75 | if IPYTHON_VERSION == 2: 76 | NosebookVersion = NosebookTwo 77 | else: 78 | NosebookVersion = NosebookThree 79 | 80 | 81 | def dump_canonical(obj): 82 | return json.dumps(obj, indent=2, sort_keys=True) 83 | 84 | 85 | class Nosebook(NosebookVersion, Plugin): 86 | """ 87 | A nose plugin for discovering and executing IPython notebook cells 88 | as tests 89 | """ 90 | name = "nosebook" 91 | 92 | def options(self, parser, env=os.environ): 93 | """ 94 | advertise options 95 | """ 96 | 97 | self.testMatchPat = env.get('NOSEBOOK_TESTMATCH', 98 | r'.*[Tt]est.*\.ipynb$') 99 | 100 | self.testMatchCellPat = env.get('NOSEBOOK_CELLMATCH', 101 | r'.*') 102 | 103 | parser.add_option( 104 | "--nosebook-match", 105 | action="store", 106 | dest="nosebookTestMatch", 107 | metavar="REGEX", 108 | help="Notebook files that match this regular expression are " 109 | "considered tests. " 110 | "Default: %s [NOSEBOOK_TESTMATCH]" % self.testMatchPat, 111 | default=self.testMatchPat 112 | ) 113 | 114 | parser.add_option( 115 | "--nosebook-match-cell", 116 | action="store", 117 | dest="nosebookTestMatchCell", 118 | metavar="REGEX", 119 | help="Notebook cells that match this regular expression are " 120 | "considered tests. " 121 | "Default: %s [NOSEBOOK_CELLMATCH]" % self.testMatchCellPat, 122 | default=self.testMatchCellPat 123 | ) 124 | 125 | parser.add_option( 126 | "--nosebook-scrub", 127 | action="store", 128 | default=env.get('NOSEBOOK_SCRUB'), 129 | dest="nosebookScrub", 130 | help="a quoted regex, or JSON obj/list of regexen to " 131 | "scrub from cell outputs " 132 | "[NOSEBOOK_SCRUB]") 133 | 134 | super(Nosebook, self).options(parser, env=env) 135 | 136 | def configure(self, options, conf): 137 | """ 138 | apply configured options 139 | """ 140 | super(Nosebook, self).configure(options, conf) 141 | 142 | self.testMatch = re.compile(options.nosebookTestMatch).match 143 | self.testMatchCell = re.compile(options.nosebookTestMatchCell).match 144 | 145 | scrubs = [] 146 | if options.nosebookScrub: 147 | try: 148 | scrubs = json.loads(options.nosebookScrub) 149 | except Exception: 150 | scrubs = [options.nosebookScrub] 151 | 152 | if isstr(scrubs): 153 | scrubs = { 154 | scrubs: "<...>" 155 | } 156 | elif not isinstance(scrubs, dict): 157 | scrubs = dict([ 158 | (scrub, "<...%s>" % i) 159 | for i, scrub in enumerate(scrubs) 160 | ]) 161 | 162 | self.scrubMatch = { 163 | re.compile(scrub): sub 164 | for scrub, sub in scrubs.items() 165 | } 166 | 167 | def wantModule(self, *args, **kwargs): 168 | """ 169 | we don't handle actual code modules! 170 | """ 171 | return False 172 | 173 | def _readnb(self, filename): 174 | with open(filename) as f: 175 | return reads(f.read()) 176 | 177 | def readnb(self, filename): 178 | try: 179 | nb = self._readnb(filename) 180 | except Exception as err: 181 | log.info("could not be parse as a notebook %s\n%s", 182 | filename, 183 | err) 184 | return False 185 | 186 | return convert(nb, NBFORMAT_VERSION) 187 | 188 | def codeCells(self, nb): 189 | for cell in nb.cells: 190 | if cell.cell_type == "code": 191 | yield cell 192 | 193 | def wantFile(self, filename): 194 | """ 195 | filter files to those that match nosebook-match 196 | """ 197 | 198 | log.info("considering %s", filename) 199 | 200 | if self.testMatch(filename) is None: 201 | return False 202 | 203 | nb = self.readnb(filename) 204 | 205 | for cell in self.codeCells(nb): 206 | return True 207 | 208 | log.info("no `code` cells in %s", filename) 209 | 210 | return False 211 | 212 | def loadTestsFromFile(self, filename): 213 | """ 214 | find all tests in a notebook. 215 | """ 216 | nb = self.readnb(filename) 217 | 218 | kernel = self.newKernel(nb) 219 | 220 | for cell_idx, cell in enumerate(self.codeCells(nb)): 221 | if self.testMatchCell(cell.source) is not None: 222 | yield NoseCellTestCase( 223 | cell, 224 | cell_idx, 225 | kernel, 226 | filename=filename, 227 | scrubs=self.scrubMatch 228 | ) 229 | 230 | 231 | class NoseCellTestCase(TestCase): 232 | """ 233 | A test case for a single cell. 234 | """ 235 | IGNORE_TYPES = ["execute_request", "execute_input", "status", "pyin"] 236 | STRIP_KEYS = ["execution_count", "traceback", "prompt_number", "source"] 237 | 238 | def __init__(self, cell, cell_idx, kernel, *args, **kwargs): 239 | """ 240 | initialize this cell as a test 241 | """ 242 | 243 | self.cell = self.sanitizeCell(cell) 244 | self.cell_idx = cell_idx 245 | self.scrubs = kwargs.pop("scrubs", []) 246 | self.filename = kwargs.pop("filename", "") 247 | 248 | self.kernel = kernel 249 | self.iopub = self.kernel.iopub_channel 250 | 251 | self.runTest.__func__.__doc__ = self.id() 252 | 253 | super(NoseCellTestCase, self).__init__(*args, **kwargs) 254 | 255 | def id(self): 256 | return "%s#%s" % (self.filename, self.cell_idx) 257 | 258 | def cellCode(self): 259 | if hasattr(self.cell, "source"): 260 | return self.cell.source 261 | return self.cell.input 262 | 263 | def runTest(self): 264 | self.kernel.execute(self.cellCode()) 265 | 266 | outputs = [] 267 | msg = None 268 | 269 | while self.shouldContinue(msg): 270 | try: 271 | msg = self.iopub.get_msg(block=True, timeout=1) 272 | except Empty: 273 | continue 274 | 275 | if msg["msg_type"] not in self.IGNORE_TYPES: 276 | output = self.transformMessage( 277 | msg, 278 | self.cell.outputs[len(outputs)] 279 | ) 280 | outputs.append(output) 281 | 282 | scrub = lambda x: dump_canonical(list(self.scrubOutputs(x))) 283 | 284 | scrubbed = scrub(outputs) 285 | expected = scrub(self.cell.outputs) 286 | 287 | self.assertEqual(scrubbed, expected, "\n{}\n\n{}".format( 288 | scrubbed, 289 | expected 290 | )) 291 | 292 | def scrubOutputs(self, outputs): 293 | """ 294 | remove all scrubs from output data and text 295 | """ 296 | for output in outputs: 297 | out = copy(output) 298 | 299 | for scrub, sub in self.scrubs.items(): 300 | def _scrubLines(lines): 301 | if isstr(lines): 302 | return re.sub(scrub, sub, lines) 303 | else: 304 | return [re.sub(scrub, sub, line) for line in lines] 305 | 306 | if "text" in out: 307 | out["text"] = _scrubLines(out["text"]) 308 | 309 | if "data" in out: 310 | if isinstance(out["data"], dict): 311 | for mime, data in out["data"].items(): 312 | out["data"][mime] = _scrubLines(data) 313 | else: 314 | out["data"] = _scrubLines(out["data"]) 315 | yield out 316 | 317 | def stripKeys(self, d): 318 | """ 319 | remove keys from STRIP_KEYS to ensure comparability 320 | """ 321 | for key in self.STRIP_KEYS: 322 | d.pop(key, None) 323 | return d 324 | 325 | def sanitizeCell(self, cell): 326 | """ 327 | remove non-reproducible things 328 | """ 329 | for output in cell.outputs: 330 | self.stripKeys(output) 331 | return cell 332 | 333 | def transformMessage(self, msg, expected): 334 | """ 335 | transform a message into something like the notebook 336 | """ 337 | SWAP_KEYS = { 338 | "output_type": { 339 | "pyout": "execute_result", 340 | "pyerr": "error" 341 | } 342 | } 343 | 344 | output = { 345 | u"output_type": msg["msg_type"] 346 | } 347 | output.update(msg["content"]) 348 | 349 | output = self.stripKeys(output) 350 | for key, swaps in SWAP_KEYS.items(): 351 | if key in output and output[key] in swaps: 352 | output[key] = swaps[output[key]] 353 | 354 | if "data" in output and "data" not in expected: 355 | output["text"] = output["data"] 356 | del output["data"] 357 | 358 | return output 359 | 360 | def shouldContinue(self, msg): 361 | """ 362 | determine whether the current message is the last for this cell 363 | """ 364 | if msg is None: 365 | return True 366 | 367 | return not (msg["msg_type"] == "status" and 368 | msg["content"]["execution_state"] == "idle") 369 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | flake8 3 | wheel 4 | munch 5 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | nose>=1.3.4 2 | IPython 3 | jsonschema 4 | pyzmq 5 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup 3 | 4 | # you'd add this, too, for `python setup.py test` integration 5 | from setuptools.command.test import test as TestCommand 6 | 7 | 8 | class NosebookTestCommand(TestCommand): 9 | def run_tests(self): 10 | # Run nose ensuring that argv simulates running nosetests directly 11 | import nose 12 | nose.run_exit(argv=['nosetests', '-c', './.noserc']) 13 | 14 | 15 | def read(fname): 16 | """ 17 | Utility function to read the README file. 18 | Used for the long_description. It's nice, because now 1) we have a top 19 | level README file and 2) it's easier to type in the README file than to put 20 | a raw string in below ... 21 | """ 22 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 23 | 24 | 25 | setup( 26 | name="nosebook", 27 | version="0.4.0", 28 | author="Nicholas Bollweg", 29 | author_email="nick.bollweg@gmail.com", 30 | description="a nose plugin for IPython notebooks", 31 | license="BSD", 32 | keywords="IPython nose", 33 | url="http://github.com/bollwyvl/nosebook", 34 | py_modules=["nosebook"], 35 | long_description=read("README.rst"), 36 | test_suite="nose.collector", 37 | classifiers=[ 38 | "Topic :: Utilities", 39 | "Framework :: IPython", 40 | "Natural Language :: English", 41 | "Programming Language :: Python", 42 | "Intended Audience :: Developers", 43 | "Development Status :: 3 - Alpha", 44 | "Operating System :: OS Independent", 45 | "Programming Language :: Python :: 3", 46 | "Programming Language :: Python :: 2", 47 | "License :: OSI Approved :: BSD License", 48 | "Topic :: Software Development :: Testing", 49 | ], 50 | setup_requires=[ 51 | "nose", 52 | "IPython", 53 | "jsonschema", 54 | "pyzmq" 55 | ], 56 | entry_points={ 57 | "nose.plugins.0.10": [ 58 | "nosebook = nosebook:Nosebook", 59 | "subprocstreams = " 60 | "IPython.testing.iptest:SubprocessStreamCapturePlugin" 61 | ] 62 | }, 63 | cmdclass={'test': NosebookTestCommand} 64 | ) 65 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bollwyvl/nosebook/6a79104b9be4b5acf1ff06cbf745f220a54a4613/tests/__init__.py -------------------------------------------------------------------------------- /tests/py2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bollwyvl/nosebook/6a79104b9be4b5acf1ff06cbf745f220a54a4613/tests/py2/__init__.py -------------------------------------------------------------------------------- /tests/py2/ipy2/Scrubbing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "kernelspec": { 4 | "display_name": "Python 3", 5 | "language": "python", 6 | "name": "python3" 7 | }, 8 | "language_info": { 9 | "codemirror_mode": { 10 | "name": "ipython", 11 | "version": 3 12 | }, 13 | "file_extension": ".py", 14 | "mimetype": "text/x-python", 15 | "name": "python", 16 | "nbconvert_exporter": "python", 17 | "pygments_lexer": "ipython3", 18 | "version": "3.4.2" 19 | }, 20 | "name": "", 21 | "signature": "sha256:5c51069ba15af88cc9bdb1f9dcfdc93473a1e1043c58621b423e98028eabc4c6" 22 | }, 23 | "nbformat": 3, 24 | "nbformat_minor": 0, 25 | "worksheets": [ 26 | { 27 | "cells": [ 28 | { 29 | "cell_type": "code", 30 | "collapsed": true, 31 | "input": [ 32 | "import random\n", 33 | "from IPython import display" 34 | ], 35 | "language": "python", 36 | "metadata": {}, 37 | "outputs": [], 38 | "prompt_number": 1 39 | }, 40 | { 41 | "cell_type": "code", 42 | "collapsed": false, 43 | "input": [ 44 | "rnd = \"a random number <0x%s>\" % random.random()" 45 | ], 46 | "language": "python", 47 | "metadata": {}, 48 | "outputs": [], 49 | "prompt_number": 2 50 | }, 51 | { 52 | "cell_type": "code", 53 | "collapsed": false, 54 | "input": [ 55 | "rnd" 56 | ], 57 | "language": "python", 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "metadata": {}, 62 | "output_type": "pyout", 63 | "prompt_number": 3, 64 | "text": [ 65 | "'a random number <0x0.676340644778>'" 66 | ] 67 | } 68 | ], 69 | "prompt_number": 3 70 | }, 71 | { 72 | "cell_type": "code", 73 | "collapsed": false, 74 | "input": [ 75 | "print(rnd)\n", 76 | "print(1234)\n", 77 | "rnd" 78 | ], 79 | "language": "python", 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "output_type": "stream", 84 | "stream": "stdout", 85 | "text": [ 86 | "a random number <0x0.676340644778>\n", 87 | "1234\n" 88 | ] 89 | }, 90 | { 91 | "metadata": {}, 92 | "output_type": "pyout", 93 | "prompt_number": 4, 94 | "text": [ 95 | "'a random number <0x0.676340644778>'" 96 | ] 97 | } 98 | ], 99 | "prompt_number": 4 100 | }, 101 | { 102 | "cell_type": "code", 103 | "collapsed": true, 104 | "input": [ 105 | "rnd2 = \"some other random number <0x%s>\" % random.random()" 106 | ], 107 | "language": "python", 108 | "metadata": {}, 109 | "outputs": [], 110 | "prompt_number": 5 111 | }, 112 | { 113 | "cell_type": "code", 114 | "collapsed": false, 115 | "input": [ 116 | "rnd2" 117 | ], 118 | "language": "python", 119 | "metadata": {}, 120 | "outputs": [ 121 | { 122 | "metadata": {}, 123 | "output_type": "pyout", 124 | "prompt_number": 6, 125 | "text": [ 126 | "'some other random number <0x0.0804665272065>'" 127 | ] 128 | } 129 | ], 130 | "prompt_number": 6 131 | }, 132 | { 133 | "cell_type": "code", 134 | "collapsed": false, 135 | "input": [ 136 | "print(rnd2)\n", 137 | "print(4567)\n", 138 | "rnd" 139 | ], 140 | "language": "python", 141 | "metadata": {}, 142 | "outputs": [ 143 | { 144 | "output_type": "stream", 145 | "stream": "stdout", 146 | "text": [ 147 | "some other random number <0x0.0804665272065>\n", 148 | "4567\n" 149 | ] 150 | }, 151 | { 152 | "metadata": {}, 153 | "output_type": "pyout", 154 | "prompt_number": 7, 155 | "text": [ 156 | "'a random number <0x0.676340644778>'" 157 | ] 158 | } 159 | ], 160 | "prompt_number": 7 161 | }, 162 | { 163 | "cell_type": "code", 164 | "collapsed": false, 165 | "input": [ 166 | "display.display(display.HTML(\"

%s

\" % rnd2))" 167 | ], 168 | "language": "python", 169 | "metadata": {}, 170 | "outputs": [ 171 | { 172 | "html": [ 173 | "

some other random number <0x0.0804665272065>

" 174 | ], 175 | "metadata": {}, 176 | "output_type": "display_data", 177 | "text": [ 178 | "" 179 | ] 180 | } 181 | ], 182 | "prompt_number": 8 183 | }, 184 | { 185 | "cell_type": "code", 186 | "collapsed": false, 187 | "input": [ 188 | "class A(object):\n", 189 | " pass\n", 190 | "A()" 191 | ], 192 | "language": "python", 193 | "metadata": {}, 194 | "outputs": [ 195 | { 196 | "metadata": {}, 197 | "output_type": "pyout", 198 | "prompt_number": 9, 199 | "text": [ 200 | "<__main__.A at 0x7fc8d4d31750>" 201 | ] 202 | } 203 | ], 204 | "prompt_number": 9 205 | } 206 | ], 207 | "metadata": {} 208 | } 209 | ] 210 | } -------------------------------------------------------------------------------- /tests/py2/ipy2/Test Simple.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "kernelspec": { 4 | "display_name": "Python 3", 5 | "language": "python", 6 | "name": "python3" 7 | }, 8 | "language_info": { 9 | "codemirror_mode": { 10 | "name": "ipython", 11 | "version": 3 12 | }, 13 | "file_extension": ".py", 14 | "mimetype": "text/x-python", 15 | "name": "python", 16 | "nbconvert_exporter": "python", 17 | "pygments_lexer": "ipython3", 18 | "version": "3.4.2" 19 | }, 20 | "name": "", 21 | "signature": "sha256:2f65490364ed1651f192f20ed05d45a0982af27ce70a4fd414ee5a1607c7ea0b" 22 | }, 23 | "nbformat": 3, 24 | "nbformat_minor": 0, 25 | "worksheets": [ 26 | { 27 | "cells": [ 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "This is nothing." 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "collapsed": true, 38 | "input": [], 39 | "language": "python", 40 | "metadata": {}, 41 | "outputs": [], 42 | "prompt_number": 0 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "This does nothing." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "collapsed": true, 54 | "input": [ 55 | "from IPython import display" 56 | ], 57 | "language": "python", 58 | "metadata": {}, 59 | "outputs": [], 60 | "prompt_number": 1 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "This is an `execute_result`." 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "collapsed": false, 72 | "input": [ 73 | "1 + 1" 74 | ], 75 | "language": "python", 76 | "metadata": {}, 77 | "outputs": [ 78 | { 79 | "metadata": {}, 80 | "output_type": "pyout", 81 | "prompt_number": 2, 82 | "text": [ 83 | "2" 84 | ] 85 | } 86 | ], 87 | "prompt_number": 2 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "This is a `stdout` stream." 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "collapsed": false, 99 | "input": [ 100 | "print(1 + 1)" 101 | ], 102 | "language": "python", 103 | "metadata": {}, 104 | "outputs": [ 105 | { 106 | "output_type": "stream", 107 | "stream": "stdout", 108 | "text": [ 109 | "2\n" 110 | ] 111 | } 112 | ], 113 | "prompt_number": 3 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "This is an `execute_result` and a `stdout`." 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "collapsed": false, 125 | "input": [ 126 | "print(1 + 1)\n", 127 | "1 + 1" 128 | ], 129 | "language": "python", 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "output_type": "stream", 134 | "stream": "stdout", 135 | "text": [ 136 | "2\n" 137 | ] 138 | }, 139 | { 140 | "metadata": {}, 141 | "output_type": "pyout", 142 | "prompt_number": 4, 143 | "text": [ 144 | "2" 145 | ] 146 | } 147 | ], 148 | "prompt_number": 4 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "This is a `stderr`." 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "collapsed": false, 160 | "input": [ 161 | "0 / 0" 162 | ], 163 | "language": "python", 164 | "metadata": {}, 165 | "outputs": [ 166 | { 167 | "ename": "ZeroDivisionError", 168 | "evalue": "integer division or modulo by zero", 169 | "output_type": "pyerr", 170 | "traceback": [ 171 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 172 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;36m0\u001b[0m \u001b[1;33m/\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 173 | "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero" 174 | ] 175 | } 176 | ], 177 | "prompt_number": 5 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "This is `stderr` and `stdout`." 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "collapsed": false, 189 | "input": [ 190 | "print(1 + 1)\n", 191 | "0/0" 192 | ], 193 | "language": "python", 194 | "metadata": {}, 195 | "outputs": [ 196 | { 197 | "output_type": "stream", 198 | "stream": "stdout", 199 | "text": [ 200 | "2\n" 201 | ] 202 | }, 203 | { 204 | "ename": "ZeroDivisionError", 205 | "evalue": "integer division or modulo by zero", 206 | "output_type": "pyerr", 207 | "traceback": [ 208 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 209 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;36m0\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 210 | "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero" 211 | ] 212 | } 213 | ], 214 | "prompt_number": 6 215 | }, 216 | { 217 | "cell_type": "heading", 218 | "level": 1, 219 | "metadata": {}, 220 | "source": [ 221 | "IPython.display" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": {}, 227 | "source": [ 228 | "This is some HTML." 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "collapsed": false, 234 | "input": [ 235 | "display.HTML(\"

Some HTML

\")" 236 | ], 237 | "language": "python", 238 | "metadata": {}, 239 | "outputs": [ 240 | { 241 | "html": [ 242 | "

Some HTML

" 243 | ], 244 | "metadata": {}, 245 | "output_type": "pyout", 246 | "prompt_number": 7, 247 | "text": [ 248 | "" 249 | ] 250 | } 251 | ], 252 | "prompt_number": 7 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "This uses multiple `displays`." 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "collapsed": false, 264 | "input": [ 265 | "display.display(display.HTML(\"

Some Other HTML

\"))\n", 266 | "display.display(display.HTML(\"

Yet Other HTML

\"))" 267 | ], 268 | "language": "python", 269 | "metadata": {}, 270 | "outputs": [ 271 | { 272 | "html": [ 273 | "

Some Other HTML

" 274 | ], 275 | "metadata": {}, 276 | "output_type": "display_data", 277 | "text": [ 278 | "" 279 | ] 280 | }, 281 | { 282 | "html": [ 283 | "

Yet Other HTML

" 284 | ], 285 | "metadata": {}, 286 | "output_type": "display_data", 287 | "text": [ 288 | "" 289 | ] 290 | } 291 | ], 292 | "prompt_number": 8 293 | }, 294 | { 295 | "cell_type": "code", 296 | "collapsed": false, 297 | "input": [ 298 | "def test_a_thing():\n", 299 | " assert 1 == 0\n", 300 | "test_a_thing()" 301 | ], 302 | "language": "python", 303 | "metadata": {}, 304 | "outputs": [ 305 | { 306 | "ename": "AssertionError", 307 | "evalue": "", 308 | "output_type": "pyerr", 309 | "traceback": [ 310 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", 311 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 312 | "\u001b[1;32m\u001b[0m in \u001b[0;36mtest_a_thing\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 313 | "\u001b[1;31mAssertionError\u001b[0m: " 314 | ] 315 | } 316 | ], 317 | "prompt_number": 9 318 | } 319 | ], 320 | "metadata": {} 321 | } 322 | ] 323 | } -------------------------------------------------------------------------------- /tests/py2/ipy2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bollwyvl/nosebook/6a79104b9be4b5acf1ff06cbf745f220a54a4613/tests/py2/ipy2/__init__.py -------------------------------------------------------------------------------- /tests/py2/ipy3/Scrubbing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import random\n", 12 | "from IPython import display" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 2, 18 | "metadata": { 19 | "collapsed": false 20 | }, 21 | "outputs": [], 22 | "source": [ 23 | "rnd = \"a random number <0x%s>\" % random.random()" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 3, 29 | "metadata": { 30 | "collapsed": false 31 | }, 32 | "outputs": [ 33 | { 34 | "data": { 35 | "text/plain": [ 36 | "'a random number <0x0.88879177514>'" 37 | ] 38 | }, 39 | "execution_count": 3, 40 | "metadata": {}, 41 | "output_type": "execute_result" 42 | } 43 | ], 44 | "source": [ 45 | "rnd" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 4, 51 | "metadata": { 52 | "collapsed": false 53 | }, 54 | "outputs": [ 55 | { 56 | "name": "stdout", 57 | "output_type": "stream", 58 | "text": [ 59 | "a random number <0x0.88879177514>\n", 60 | "1234\n" 61 | ] 62 | }, 63 | { 64 | "data": { 65 | "text/plain": [ 66 | "'a random number <0x0.88879177514>'" 67 | ] 68 | }, 69 | "execution_count": 4, 70 | "metadata": {}, 71 | "output_type": "execute_result" 72 | } 73 | ], 74 | "source": [ 75 | "print(rnd)\n", 76 | "print(1234)\n", 77 | "rnd" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 5, 83 | "metadata": { 84 | "collapsed": true 85 | }, 86 | "outputs": [], 87 | "source": [ 88 | "rnd2 = \"some other random number <0x%s>\" % random.random()" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 6, 94 | "metadata": { 95 | "collapsed": false 96 | }, 97 | "outputs": [ 98 | { 99 | "data": { 100 | "text/plain": [ 101 | "'some other random number <0x0.408338140507>'" 102 | ] 103 | }, 104 | "execution_count": 6, 105 | "metadata": {}, 106 | "output_type": "execute_result" 107 | } 108 | ], 109 | "source": [ 110 | "rnd2" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 7, 116 | "metadata": { 117 | "collapsed": false 118 | }, 119 | "outputs": [ 120 | { 121 | "name": "stdout", 122 | "output_type": "stream", 123 | "text": [ 124 | "some other random number <0x0.408338140507>\n", 125 | "4567\n" 126 | ] 127 | }, 128 | { 129 | "data": { 130 | "text/plain": [ 131 | "'a random number <0x0.88879177514>'" 132 | ] 133 | }, 134 | "execution_count": 7, 135 | "metadata": {}, 136 | "output_type": "execute_result" 137 | } 138 | ], 139 | "source": [ 140 | "print(rnd2)\n", 141 | "print(4567)\n", 142 | "rnd" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 8, 148 | "metadata": { 149 | "collapsed": false 150 | }, 151 | "outputs": [ 152 | { 153 | "data": { 154 | "text/markdown": [ 155 | "#some other random number <0x0.408338140507>" 156 | ], 157 | "text/plain": [ 158 | "" 159 | ] 160 | }, 161 | "metadata": {}, 162 | "output_type": "display_data" 163 | } 164 | ], 165 | "source": [ 166 | "display.display(display.Markdown(\"#%s\" % rnd2))" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": 9, 172 | "metadata": { 173 | "collapsed": false 174 | }, 175 | "outputs": [ 176 | { 177 | "data": { 178 | "text/plain": [ 179 | "<__main__.A at 0x7f5b90738fd0>" 180 | ] 181 | }, 182 | "execution_count": 9, 183 | "metadata": {}, 184 | "output_type": "execute_result" 185 | } 186 | ], 187 | "source": [ 188 | "class A(object):\n", 189 | " pass\n", 190 | "A()" 191 | ] 192 | } 193 | ], 194 | "metadata": { 195 | "kernelspec": { 196 | "display_name": "Python 2", 197 | "language": "python", 198 | "name": "python2" 199 | }, 200 | "language_info": { 201 | "codemirror_mode": { 202 | "name": "ipython", 203 | "version": 2 204 | }, 205 | "file_extension": ".py", 206 | "mimetype": "text/x-python", 207 | "name": "python", 208 | "nbconvert_exporter": "python", 209 | "pygments_lexer": "ipython2", 210 | "version": "2.7.8" 211 | } 212 | }, 213 | "nbformat": 4, 214 | "nbformat_minor": 0 215 | } 216 | -------------------------------------------------------------------------------- /tests/py2/ipy3/Test Simple.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "This is nothing." 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "This does nothing." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 1, 29 | "metadata": { 30 | "collapsed": true 31 | }, 32 | "outputs": [], 33 | "source": [ 34 | "from IPython import display" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "This is an `execute_result`." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 2, 47 | "metadata": { 48 | "collapsed": false 49 | }, 50 | "outputs": [ 51 | { 52 | "data": { 53 | "text/plain": [ 54 | "2" 55 | ] 56 | }, 57 | "execution_count": 2, 58 | "metadata": {}, 59 | "output_type": "execute_result" 60 | } 61 | ], 62 | "source": [ 63 | "1 + 1" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "This is a `stdout` stream." 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 3, 76 | "metadata": { 77 | "collapsed": false 78 | }, 79 | "outputs": [ 80 | { 81 | "name": "stdout", 82 | "output_type": "stream", 83 | "text": [ 84 | "2\n" 85 | ] 86 | } 87 | ], 88 | "source": [ 89 | "print(1 + 1)" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "This is an `execute_result` and a `stdout`." 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 4, 102 | "metadata": { 103 | "collapsed": false 104 | }, 105 | "outputs": [ 106 | { 107 | "name": "stdout", 108 | "output_type": "stream", 109 | "text": [ 110 | "2\n" 111 | ] 112 | }, 113 | { 114 | "data": { 115 | "text/plain": [ 116 | "2" 117 | ] 118 | }, 119 | "execution_count": 4, 120 | "metadata": {}, 121 | "output_type": "execute_result" 122 | } 123 | ], 124 | "source": [ 125 | "print(1 + 1)\n", 126 | "1 + 1" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "This is a `stderr`." 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 5, 139 | "metadata": { 140 | "collapsed": false 141 | }, 142 | "outputs": [ 143 | { 144 | "ename": "ZeroDivisionError", 145 | "evalue": "integer division or modulo by zero", 146 | "output_type": "error", 147 | "traceback": [ 148 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 149 | "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 150 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;36m0\u001b[0m \u001b[1;33m/\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 151 | "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero" 152 | ] 153 | } 154 | ], 155 | "source": [ 156 | "0 / 0" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "This is `stderr` and `stdout`." 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": 6, 169 | "metadata": { 170 | "collapsed": false 171 | }, 172 | "outputs": [ 173 | { 174 | "name": "stdout", 175 | "output_type": "stream", 176 | "text": [ 177 | "2\n" 178 | ] 179 | }, 180 | { 181 | "ename": "ZeroDivisionError", 182 | "evalue": "integer division or modulo by zero", 183 | "output_type": "error", 184 | "traceback": [ 185 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 186 | "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 187 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;36m0\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 188 | "\u001b[1;31mZeroDivisionError\u001b[0m: integer division or modulo by zero" 189 | ] 190 | } 191 | ], 192 | "source": [ 193 | "print(1 + 1)\n", 194 | "0/0" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "# IPython.display" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "This is some HTML." 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 7, 214 | "metadata": { 215 | "collapsed": false 216 | }, 217 | "outputs": [ 218 | { 219 | "data": { 220 | "text/html": [ 221 | "

Some HTML

" 222 | ], 223 | "text/plain": [ 224 | "" 225 | ] 226 | }, 227 | "execution_count": 7, 228 | "metadata": {}, 229 | "output_type": "execute_result" 230 | } 231 | ], 232 | "source": [ 233 | "display.HTML(\"

Some HTML

\")" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "This uses multiple `displays`." 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": 8, 246 | "metadata": { 247 | "collapsed": false 248 | }, 249 | "outputs": [ 250 | { 251 | "data": { 252 | "text/html": [ 253 | "

Some Other HTML

" 254 | ], 255 | "text/plain": [ 256 | "" 257 | ] 258 | }, 259 | "metadata": {}, 260 | "output_type": "display_data" 261 | }, 262 | { 263 | "data": { 264 | "text/html": [ 265 | "

Yet Other HTML

" 266 | ], 267 | "text/plain": [ 268 | "" 269 | ] 270 | }, 271 | "metadata": {}, 272 | "output_type": "display_data" 273 | } 274 | ], 275 | "source": [ 276 | "display.display(display.HTML(\"

Some Other HTML

\"))\n", 277 | "display.display(display.HTML(\"

Yet Other HTML

\"))" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 9, 283 | "metadata": { 284 | "collapsed": false 285 | }, 286 | "outputs": [ 287 | { 288 | "ename": "AssertionError", 289 | "evalue": "", 290 | "output_type": "error", 291 | "traceback": [ 292 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 293 | "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", 294 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 295 | "\u001b[1;32m\u001b[0m in \u001b[0;36mtest_a_thing\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 296 | "\u001b[1;31mAssertionError\u001b[0m: " 297 | ] 298 | } 299 | ], 300 | "source": [ 301 | "def test_a_thing():\n", 302 | " assert 1 == 0\n", 303 | "test_a_thing()" 304 | ] 305 | } 306 | ], 307 | "metadata": { 308 | "kernelspec": { 309 | "display_name": "Python 2", 310 | "language": "python", 311 | "name": "python2" 312 | }, 313 | "language_info": { 314 | "codemirror_mode": { 315 | "name": "ipython", 316 | "version": 2 317 | }, 318 | "file_extension": ".py", 319 | "mimetype": "text/x-python", 320 | "name": "python", 321 | "nbconvert_exporter": "python", 322 | "pygments_lexer": "ipython2", 323 | "version": "2.7.8" 324 | } 325 | }, 326 | "nbformat": 4, 327 | "nbformat_minor": 0 328 | } 329 | -------------------------------------------------------------------------------- /tests/py2/ipy3/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bollwyvl/nosebook/6a79104b9be4b5acf1ff06cbf745f220a54a4613/tests/py2/ipy3/__init__.py -------------------------------------------------------------------------------- /tests/py3/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bollwyvl/nosebook/6a79104b9be4b5acf1ff06cbf745f220a54a4613/tests/py3/__init__.py -------------------------------------------------------------------------------- /tests/py3/ipy2/Scrubbing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "kernelspec": { 4 | "display_name": "Python 3", 5 | "language": "python", 6 | "name": "python3" 7 | }, 8 | "language_info": { 9 | "codemirror_mode": { 10 | "name": "ipython", 11 | "version": 3 12 | }, 13 | "file_extension": ".py", 14 | "mimetype": "text/x-python", 15 | "name": "python", 16 | "nbconvert_exporter": "python", 17 | "pygments_lexer": "ipython3", 18 | "version": "3.4.2" 19 | }, 20 | "name": "", 21 | "signature": "sha256:4788eb6a95d2631328917c12af7a3f83a932e78b82f22a5c80d0d8d8cb5c87c4" 22 | }, 23 | "nbformat": 3, 24 | "nbformat_minor": 0, 25 | "worksheets": [ 26 | { 27 | "cells": [ 28 | { 29 | "cell_type": "code", 30 | "collapsed": true, 31 | "input": [ 32 | "import random\n", 33 | "from IPython import display" 34 | ], 35 | "language": "python", 36 | "metadata": {}, 37 | "outputs": [], 38 | "prompt_number": 1 39 | }, 40 | { 41 | "cell_type": "code", 42 | "collapsed": false, 43 | "input": [ 44 | "rnd = \"a random number <0x%s>\" % random.random()" 45 | ], 46 | "language": "python", 47 | "metadata": {}, 48 | "outputs": [], 49 | "prompt_number": 2 50 | }, 51 | { 52 | "cell_type": "code", 53 | "collapsed": false, 54 | "input": [ 55 | "rnd" 56 | ], 57 | "language": "python", 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "metadata": {}, 62 | "output_type": "pyout", 63 | "prompt_number": 3, 64 | "text": [ 65 | "'a random number <0x0.05252146385286727>'" 66 | ] 67 | } 68 | ], 69 | "prompt_number": 3 70 | }, 71 | { 72 | "cell_type": "code", 73 | "collapsed": false, 74 | "input": [ 75 | "print(rnd)\n", 76 | "print(1234)\n", 77 | "rnd" 78 | ], 79 | "language": "python", 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "output_type": "stream", 84 | "stream": "stdout", 85 | "text": [ 86 | "a random number <0x0.05252146385286727>\n", 87 | "1234\n" 88 | ] 89 | }, 90 | { 91 | "metadata": {}, 92 | "output_type": "pyout", 93 | "prompt_number": 4, 94 | "text": [ 95 | "'a random number <0x0.05252146385286727>'" 96 | ] 97 | } 98 | ], 99 | "prompt_number": 4 100 | }, 101 | { 102 | "cell_type": "code", 103 | "collapsed": true, 104 | "input": [ 105 | "rnd2 = \"some other random number <0x%s>\" % random.random()" 106 | ], 107 | "language": "python", 108 | "metadata": {}, 109 | "outputs": [], 110 | "prompt_number": 5 111 | }, 112 | { 113 | "cell_type": "code", 114 | "collapsed": false, 115 | "input": [ 116 | "rnd2" 117 | ], 118 | "language": "python", 119 | "metadata": {}, 120 | "outputs": [ 121 | { 122 | "metadata": {}, 123 | "output_type": "pyout", 124 | "prompt_number": 6, 125 | "text": [ 126 | "'some other random number <0x0.7032183399822858>'" 127 | ] 128 | } 129 | ], 130 | "prompt_number": 6 131 | }, 132 | { 133 | "cell_type": "code", 134 | "collapsed": false, 135 | "input": [ 136 | "print(rnd2)\n", 137 | "print(4567)\n", 138 | "rnd" 139 | ], 140 | "language": "python", 141 | "metadata": {}, 142 | "outputs": [ 143 | { 144 | "output_type": "stream", 145 | "stream": "stdout", 146 | "text": [ 147 | "some other random number <0x0.7032183399822858>\n", 148 | "4567\n" 149 | ] 150 | }, 151 | { 152 | "metadata": {}, 153 | "output_type": "pyout", 154 | "prompt_number": 7, 155 | "text": [ 156 | "'a random number <0x0.05252146385286727>'" 157 | ] 158 | } 159 | ], 160 | "prompt_number": 7 161 | }, 162 | { 163 | "cell_type": "code", 164 | "collapsed": false, 165 | "input": [ 166 | "display.display(display.HTML(\"

%s

\" % rnd2))" 167 | ], 168 | "language": "python", 169 | "metadata": {}, 170 | "outputs": [ 171 | { 172 | "html": [ 173 | "

some other random number <0x0.7032183399822858>

" 174 | ], 175 | "metadata": {}, 176 | "output_type": "display_data", 177 | "text": [ 178 | "" 179 | ] 180 | } 181 | ], 182 | "prompt_number": 8 183 | }, 184 | { 185 | "cell_type": "code", 186 | "collapsed": false, 187 | "input": [ 188 | "class A(object):\n", 189 | " pass\n", 190 | "A()" 191 | ], 192 | "language": "python", 193 | "metadata": {}, 194 | "outputs": [ 195 | { 196 | "metadata": {}, 197 | "output_type": "pyout", 198 | "prompt_number": 9, 199 | "text": [ 200 | "<__main__.A at 0x7f4c6002a438>" 201 | ] 202 | } 203 | ], 204 | "prompt_number": 9 205 | } 206 | ], 207 | "metadata": {} 208 | } 209 | ] 210 | } -------------------------------------------------------------------------------- /tests/py3/ipy2/Test Simple.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "kernelspec": { 4 | "display_name": "Python 3", 5 | "language": "python", 6 | "name": "python3" 7 | }, 8 | "language_info": { 9 | "codemirror_mode": { 10 | "name": "ipython", 11 | "version": 3 12 | }, 13 | "file_extension": ".py", 14 | "mimetype": "text/x-python", 15 | "name": "python", 16 | "nbconvert_exporter": "python", 17 | "pygments_lexer": "ipython3", 18 | "version": "3.4.2" 19 | }, 20 | "name": "", 21 | "signature": "sha256:3a0505e34e085a142683d6c392b8ba1c282b5815014464da5459545182931f60" 22 | }, 23 | "nbformat": 3, 24 | "nbformat_minor": 0, 25 | "worksheets": [ 26 | { 27 | "cells": [ 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "This is nothing." 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "collapsed": true, 38 | "input": [], 39 | "language": "python", 40 | "metadata": {}, 41 | "outputs": [], 42 | "prompt_number": 0 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "This does nothing." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "collapsed": true, 54 | "input": [ 55 | "from IPython import display" 56 | ], 57 | "language": "python", 58 | "metadata": {}, 59 | "outputs": [], 60 | "prompt_number": 1 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "This is an `execute_result`." 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "collapsed": false, 72 | "input": [ 73 | "1 + 1" 74 | ], 75 | "language": "python", 76 | "metadata": {}, 77 | "outputs": [ 78 | { 79 | "metadata": {}, 80 | "output_type": "pyout", 81 | "prompt_number": 2, 82 | "text": [ 83 | "2" 84 | ] 85 | } 86 | ], 87 | "prompt_number": 2 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "This is a `stdout` stream." 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "collapsed": false, 99 | "input": [ 100 | "print(1 + 1)" 101 | ], 102 | "language": "python", 103 | "metadata": {}, 104 | "outputs": [ 105 | { 106 | "output_type": "stream", 107 | "stream": "stdout", 108 | "text": [ 109 | "2\n" 110 | ] 111 | } 112 | ], 113 | "prompt_number": 3 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "This is an `execute_result` and a `stdout`." 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "collapsed": false, 125 | "input": [ 126 | "print(1 + 1)\n", 127 | "1 + 1" 128 | ], 129 | "language": "python", 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "output_type": "stream", 134 | "stream": "stdout", 135 | "text": [ 136 | "2\n" 137 | ] 138 | }, 139 | { 140 | "metadata": {}, 141 | "output_type": "pyout", 142 | "prompt_number": 4, 143 | "text": [ 144 | "2" 145 | ] 146 | } 147 | ], 148 | "prompt_number": 4 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "This is a `stderr`." 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "collapsed": false, 160 | "input": [ 161 | "0 / 0" 162 | ], 163 | "language": "python", 164 | "metadata": {}, 165 | "outputs": [ 166 | { 167 | "ename": "ZeroDivisionError", 168 | "evalue": "division by zero", 169 | "output_type": "pyerr", 170 | "traceback": [ 171 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 172 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;36m0\u001b[0m \u001b[1;33m/\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 173 | "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" 174 | ] 175 | } 176 | ], 177 | "prompt_number": 5 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "This is `stderr` and `stdout`." 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "collapsed": false, 189 | "input": [ 190 | "print(1 + 1)\n", 191 | "0/0" 192 | ], 193 | "language": "python", 194 | "metadata": {}, 195 | "outputs": [ 196 | { 197 | "output_type": "stream", 198 | "stream": "stdout", 199 | "text": [ 200 | "2\n" 201 | ] 202 | }, 203 | { 204 | "ename": "ZeroDivisionError", 205 | "evalue": "division by zero", 206 | "output_type": "pyerr", 207 | "traceback": [ 208 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 209 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;36m0\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 210 | "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" 211 | ] 212 | } 213 | ], 214 | "prompt_number": 6 215 | }, 216 | { 217 | "cell_type": "heading", 218 | "level": 1, 219 | "metadata": {}, 220 | "source": [ 221 | "IPython.display" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": {}, 227 | "source": [ 228 | "This is some HTML." 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "collapsed": false, 234 | "input": [ 235 | "display.HTML(\"

Some HTML

\")" 236 | ], 237 | "language": "python", 238 | "metadata": {}, 239 | "outputs": [ 240 | { 241 | "html": [ 242 | "

Some HTML

" 243 | ], 244 | "metadata": {}, 245 | "output_type": "pyout", 246 | "prompt_number": 7, 247 | "text": [ 248 | "" 249 | ] 250 | } 251 | ], 252 | "prompt_number": 7 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "This uses multiple `displays`." 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "collapsed": false, 264 | "input": [ 265 | "display.display(display.HTML(\"

Some Other HTML

\"))\n", 266 | "display.display(display.HTML(\"

Yet Other HTML

\"))" 267 | ], 268 | "language": "python", 269 | "metadata": {}, 270 | "outputs": [ 271 | { 272 | "html": [ 273 | "

Some Other HTML

" 274 | ], 275 | "metadata": {}, 276 | "output_type": "display_data", 277 | "text": [ 278 | "" 279 | ] 280 | }, 281 | { 282 | "html": [ 283 | "

Yet Other HTML

" 284 | ], 285 | "metadata": {}, 286 | "output_type": "display_data", 287 | "text": [ 288 | "" 289 | ] 290 | } 291 | ], 292 | "prompt_number": 8 293 | }, 294 | { 295 | "cell_type": "code", 296 | "collapsed": false, 297 | "input": [ 298 | "def test_a_thing():\n", 299 | " assert 1 == 0\n", 300 | "test_a_thing()" 301 | ], 302 | "language": "python", 303 | "metadata": {}, 304 | "outputs": [ 305 | { 306 | "ename": "AssertionError", 307 | "evalue": "", 308 | "output_type": "pyerr", 309 | "traceback": [ 310 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", 311 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 312 | "\u001b[1;32m\u001b[0m in \u001b[0;36mtest_a_thing\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 313 | "\u001b[1;31mAssertionError\u001b[0m: " 314 | ] 315 | } 316 | ], 317 | "prompt_number": 9 318 | } 319 | ], 320 | "metadata": {} 321 | } 322 | ] 323 | } -------------------------------------------------------------------------------- /tests/py3/ipy2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bollwyvl/nosebook/6a79104b9be4b5acf1ff06cbf745f220a54a4613/tests/py3/ipy2/__init__.py -------------------------------------------------------------------------------- /tests/py3/ipy3/Scrubbing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 3, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import random\n", 12 | "from IPython import display" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 4, 18 | "metadata": { 19 | "collapsed": false 20 | }, 21 | "outputs": [], 22 | "source": [ 23 | "rnd = \"a random number <0x%s>\" % random.random()" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 5, 29 | "metadata": { 30 | "collapsed": false 31 | }, 32 | "outputs": [ 33 | { 34 | "data": { 35 | "text/plain": [ 36 | "'a random number <0x0.8961822563910737>'" 37 | ] 38 | }, 39 | "execution_count": 5, 40 | "metadata": {}, 41 | "output_type": "execute_result" 42 | } 43 | ], 44 | "source": [ 45 | "rnd" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 6, 51 | "metadata": { 52 | "collapsed": false 53 | }, 54 | "outputs": [ 55 | { 56 | "name": "stdout", 57 | "output_type": "stream", 58 | "text": [ 59 | "a random number <0x0.8961822563910737>\n", 60 | "1234\n" 61 | ] 62 | }, 63 | { 64 | "data": { 65 | "text/plain": [ 66 | "'a random number <0x0.8961822563910737>'" 67 | ] 68 | }, 69 | "execution_count": 6, 70 | "metadata": {}, 71 | "output_type": "execute_result" 72 | } 73 | ], 74 | "source": [ 75 | "print(rnd)\n", 76 | "print(1234)\n", 77 | "rnd" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 7, 83 | "metadata": { 84 | "collapsed": true 85 | }, 86 | "outputs": [], 87 | "source": [ 88 | "rnd2 = \"some other random number <0x%s>\" % random.random()" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 8, 94 | "metadata": { 95 | "collapsed": false 96 | }, 97 | "outputs": [ 98 | { 99 | "data": { 100 | "text/plain": [ 101 | "'some other random number <0x0.17670111352577222>'" 102 | ] 103 | }, 104 | "execution_count": 8, 105 | "metadata": {}, 106 | "output_type": "execute_result" 107 | } 108 | ], 109 | "source": [ 110 | "rnd2" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 9, 116 | "metadata": { 117 | "collapsed": false 118 | }, 119 | "outputs": [ 120 | { 121 | "name": "stdout", 122 | "output_type": "stream", 123 | "text": [ 124 | "some other random number <0x0.17670111352577222>\n", 125 | "4567\n" 126 | ] 127 | }, 128 | { 129 | "data": { 130 | "text/plain": [ 131 | "'a random number <0x0.8961822563910737>'" 132 | ] 133 | }, 134 | "execution_count": 9, 135 | "metadata": {}, 136 | "output_type": "execute_result" 137 | } 138 | ], 139 | "source": [ 140 | "print(rnd2)\n", 141 | "print(4567)\n", 142 | "rnd" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 10, 148 | "metadata": { 149 | "collapsed": false 150 | }, 151 | "outputs": [ 152 | { 153 | "data": { 154 | "text/markdown": [ 155 | "#some other random number <0x0.17670111352577222>" 156 | ], 157 | "text/plain": [ 158 | "" 159 | ] 160 | }, 161 | "metadata": {}, 162 | "output_type": "display_data" 163 | } 164 | ], 165 | "source": [ 166 | "display.display(display.Markdown(\"#%s\" % rnd2))" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": 11, 172 | "metadata": { 173 | "collapsed": false 174 | }, 175 | "outputs": [ 176 | { 177 | "data": { 178 | "text/plain": [ 179 | "<__main__.A at 0x7f8d745a1390>" 180 | ] 181 | }, 182 | "execution_count": 11, 183 | "metadata": {}, 184 | "output_type": "execute_result" 185 | } 186 | ], 187 | "source": [ 188 | "class A(object):\n", 189 | " pass\n", 190 | "A()" 191 | ] 192 | } 193 | ], 194 | "metadata": { 195 | "kernelspec": { 196 | "display_name": "Python 3", 197 | "language": "python", 198 | "name": "python3" 199 | }, 200 | "language_info": { 201 | "codemirror_mode": { 202 | "name": "ipython", 203 | "version": 3 204 | }, 205 | "file_extension": ".py", 206 | "mimetype": "text/x-python", 207 | "name": "python", 208 | "nbconvert_exporter": "python", 209 | "pygments_lexer": "ipython3", 210 | "version": "3.4.2" 211 | } 212 | }, 213 | "nbformat": 4, 214 | "nbformat_minor": 0 215 | } 216 | -------------------------------------------------------------------------------- /tests/py3/ipy3/Test Simple.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "This is nothing." 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "This does nothing." 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 1, 29 | "metadata": { 30 | "collapsed": true 31 | }, 32 | "outputs": [], 33 | "source": [ 34 | "from IPython import display" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "This is an `execute_result`." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 2, 47 | "metadata": { 48 | "collapsed": false 49 | }, 50 | "outputs": [ 51 | { 52 | "data": { 53 | "text/plain": [ 54 | "2" 55 | ] 56 | }, 57 | "execution_count": 2, 58 | "metadata": {}, 59 | "output_type": "execute_result" 60 | } 61 | ], 62 | "source": [ 63 | "1 + 1" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "This is a `stdout` stream." 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 3, 76 | "metadata": { 77 | "collapsed": false 78 | }, 79 | "outputs": [ 80 | { 81 | "name": "stdout", 82 | "output_type": "stream", 83 | "text": [ 84 | "2\n" 85 | ] 86 | } 87 | ], 88 | "source": [ 89 | "print(1 + 1)" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "This is an `execute_result` and a `stdout`." 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 4, 102 | "metadata": { 103 | "collapsed": false 104 | }, 105 | "outputs": [ 106 | { 107 | "name": "stdout", 108 | "output_type": "stream", 109 | "text": [ 110 | "2\n" 111 | ] 112 | }, 113 | { 114 | "data": { 115 | "text/plain": [ 116 | "2" 117 | ] 118 | }, 119 | "execution_count": 4, 120 | "metadata": {}, 121 | "output_type": "execute_result" 122 | } 123 | ], 124 | "source": [ 125 | "print(1 + 1)\n", 126 | "1 + 1" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "This is a `stderr`." 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 5, 139 | "metadata": { 140 | "collapsed": false 141 | }, 142 | "outputs": [ 143 | { 144 | "ename": "ZeroDivisionError", 145 | "evalue": "division by zero", 146 | "output_type": "error", 147 | "traceback": [ 148 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 149 | "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 150 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;36m0\u001b[0m \u001b[1;33m/\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 151 | "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" 152 | ] 153 | } 154 | ], 155 | "source": [ 156 | "0 / 0" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "This is `stderr` and `stdout`." 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": 6, 169 | "metadata": { 170 | "collapsed": false 171 | }, 172 | "outputs": [ 173 | { 174 | "name": "stdout", 175 | "output_type": "stream", 176 | "text": [ 177 | "2\n" 178 | ] 179 | }, 180 | { 181 | "ename": "ZeroDivisionError", 182 | "evalue": "division by zero", 183 | "output_type": "error", 184 | "traceback": [ 185 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 186 | "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", 187 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;36m0\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 188 | "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" 189 | ] 190 | } 191 | ], 192 | "source": [ 193 | "print(1 + 1)\n", 194 | "0/0" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "# IPython.display" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "This is some HTML." 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 7, 214 | "metadata": { 215 | "collapsed": false 216 | }, 217 | "outputs": [ 218 | { 219 | "data": { 220 | "text/html": [ 221 | "

Some HTML

" 222 | ], 223 | "text/plain": [ 224 | "" 225 | ] 226 | }, 227 | "execution_count": 7, 228 | "metadata": {}, 229 | "output_type": "execute_result" 230 | } 231 | ], 232 | "source": [ 233 | "display.HTML(\"

Some HTML

\")" 234 | ] 235 | }, 236 | { 237 | "cell_type": "markdown", 238 | "metadata": {}, 239 | "source": [ 240 | "This uses multiple `displays`." 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": 8, 246 | "metadata": { 247 | "collapsed": false 248 | }, 249 | "outputs": [ 250 | { 251 | "data": { 252 | "text/html": [ 253 | "

Some Other HTML

" 254 | ], 255 | "text/plain": [ 256 | "" 257 | ] 258 | }, 259 | "metadata": {}, 260 | "output_type": "display_data" 261 | }, 262 | { 263 | "data": { 264 | "text/html": [ 265 | "

Yet Other HTML

" 266 | ], 267 | "text/plain": [ 268 | "" 269 | ] 270 | }, 271 | "metadata": {}, 272 | "output_type": "display_data" 273 | } 274 | ], 275 | "source": [ 276 | "display.display(display.HTML(\"

Some Other HTML

\"))\n", 277 | "display.display(display.HTML(\"

Yet Other HTML

\"))" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 9, 283 | "metadata": { 284 | "collapsed": false 285 | }, 286 | "outputs": [ 287 | { 288 | "ename": "AssertionError", 289 | "evalue": "", 290 | "output_type": "error", 291 | "traceback": [ 292 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 293 | "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", 294 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", 295 | "\u001b[1;32m\u001b[0m in \u001b[0;36mtest_a_thing\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m1\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mtest_a_thing\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 296 | "\u001b[1;31mAssertionError\u001b[0m: " 297 | ] 298 | } 299 | ], 300 | "source": [ 301 | "def test_a_thing():\n", 302 | " assert 1 == 0\n", 303 | "test_a_thing()" 304 | ] 305 | } 306 | ], 307 | "metadata": { 308 | "kernelspec": { 309 | "display_name": "Python 3", 310 | "language": "python", 311 | "name": "python3" 312 | }, 313 | "language_info": { 314 | "codemirror_mode": { 315 | "name": "ipython", 316 | "version": 3 317 | }, 318 | "file_extension": ".py", 319 | "mimetype": "text/x-python", 320 | "name": "python", 321 | "nbconvert_exporter": "python", 322 | "pygments_lexer": "ipython3", 323 | "version": "3.4.2" 324 | } 325 | }, 326 | "nbformat": 4, 327 | "nbformat_minor": 0 328 | } 329 | -------------------------------------------------------------------------------- /tests/py3/ipy3/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bollwyvl/nosebook/6a79104b9be4b5acf1ff06cbf745f220a54a4613/tests/py3/ipy3/__init__.py -------------------------------------------------------------------------------- /tests/test_plugin.py: -------------------------------------------------------------------------------- 1 | import json 2 | import unittest 3 | import sys 4 | 5 | from IPython import version_info 6 | 7 | from nose.plugins import PluginTester 8 | 9 | from nosebook import Nosebook 10 | 11 | OTHER_ARGS = [] 12 | 13 | PY_VERSION = "py%s" % sys.version_info[0] 14 | IPY_VERSION = "ipy%s" % version_info[0] 15 | 16 | 17 | def match(pattern): 18 | return "--nosebook-match=.*/{}/{}/.*{}.*".format( 19 | PY_VERSION, 20 | IPY_VERSION, 21 | pattern 22 | ) 23 | 24 | 25 | def match_cell(pattern): 26 | return "--nosebook-match-cell=%s" % pattern 27 | 28 | 29 | def scrub(patterns): 30 | return "--nosebook-scrub=%s" % json.dumps(patterns) 31 | 32 | 33 | class TestNosebook(PluginTester, unittest.TestCase): 34 | activate = "--with-nosebook" 35 | plugins = [Nosebook()] 36 | args = [match("Test Simple"), scrub(r"<.* at 0x[0-9a-f]+>")] + OTHER_ARGS 37 | env = {} 38 | 39 | def test_found(self): 40 | """ 41 | Tests are found 42 | """ 43 | assert "Ran 0 tests" not in self.output, ("got: %s" % self.output) 44 | 45 | def test_pass(self): 46 | """ 47 | Tests pass 48 | """ 49 | assert "FAIL" not in self.output, ("got: %s" % self.output) 50 | 51 | def makeSuite(self): 52 | """ 53 | will find the notebooks 54 | """ 55 | pass 56 | 57 | 58 | class TestScrubDict(TestNosebook): 59 | """ 60 | Support dictionary of scrubs 61 | """ 62 | args = [ 63 | match("Scrubbing"), 64 | scrub({ 65 | r"a random number <0x0\.\d*>": "scrub1", 66 | r"some other random number <0x0\.\d*>": "scrub2", 67 | r"<(.*) at 0x[0-9a-f]+>": "<\1>" 68 | }) 69 | ] + OTHER_ARGS 70 | 71 | 72 | class TestScrubList(TestNosebook): 73 | """ 74 | Support list of scrubs 75 | """ 76 | args = [ 77 | match("Scrubbing"), 78 | scrub([ 79 | r"a random number <0x0\.\d*>", 80 | r"some other random number <0x0\.\d*>", 81 | r"<(.*) at 0x[0-9a-f]+>" 82 | ]) 83 | ] + OTHER_ARGS 84 | 85 | 86 | class TestScrubStr(TestNosebook): 87 | """ 88 | Support a single scrub 89 | """ 90 | args = [ 91 | match("Scrubbing"), 92 | scrub( 93 | r"((a|some other) random number <0x0\.\d*>)|(<.* at 0x[0-9a-f]+>)" 94 | ) 95 | ] + OTHER_ARGS 96 | 97 | 98 | class TestMatchCell(TestNosebook): 99 | """ 100 | Support a normalish cell match 101 | """ 102 | args = [ 103 | match("Test"), 104 | match_cell(r"^\s*(class|def) .*[tT]est.*") 105 | ] + OTHER_ARGS 106 | 107 | 108 | if __name__ == '__main__': 109 | unittest.main() 110 | -------------------------------------------------------------------------------- /tests/test_scrub.py: -------------------------------------------------------------------------------- 1 | import nosebook 2 | import munch 3 | 4 | import unittest 5 | 6 | 7 | class TestNosebook(unittest.TestCase): 8 | def setUp(self): 9 | self.cell = munch.Munch({ 10 | "cell_type": "code", 11 | "execution_count": 21, 12 | "metadata": { 13 | "collapsed": False 14 | }, 15 | "outputs": [ 16 | { 17 | "name": "stdout", 18 | "output_type": "stream", 19 | "text": [ 20 | "a random number <0x0.17537838216771606>\n", 21 | "1234\n" 22 | ] 23 | }, 24 | { 25 | "data": { 26 | "text/plain": [ 27 | "'a random number <0x0.17537838216771606>'" 28 | ] 29 | }, 30 | "execution_count": 21, 31 | "metadata": {}, 32 | "output_type": "execute_result" 33 | } 34 | ], 35 | "source": [ 36 | "print(rnd)\n", 37 | "print(1234)\n", 38 | "rnd" 39 | ] 40 | }) 41 | 42 | self.kernel = munch.Munch({ 43 | "iopub_channel": {} 44 | }) 45 | 46 | def make_case(self, scrubs, expected): 47 | case = nosebook.NoseCellTestCase( 48 | self.cell, 49 | 0, 50 | self.kernel, 51 | scrubs=scrubs 52 | ) 53 | 54 | self.assertEquals( 55 | list(case.scrubOutputs(self.cell.outputs)), 56 | expected, 57 | list(case.scrubOutputs(self.cell.outputs)), 58 | ) 59 | 60 | def test_scrub_dict(self): 61 | self.make_case( 62 | { 63 | r"a random number <0x0\.\d*>": "scrub1", 64 | r"some other random number <0x0\.\d*>": "scrub2", 65 | r"<(.*) at 0x[0-9a-f]+>": "<\1>" 66 | }, 67 | [ 68 | { 69 | 'output_type': 'stream', 70 | 'name': 'stdout', 71 | 'text': ['scrub1\n', '1234\n'] 72 | }, 73 | { 74 | 'metadata': {}, 75 | 'output_type': 'execute_result', 76 | 'data': { 77 | 'text/plain': ["'scrub1'"] 78 | } 79 | } 80 | ] 81 | ) 82 | 83 | def test_scrub_list(self): 84 | self.make_case( 85 | { 86 | r"a random number <0x0\.\d*>": "scrub1", 87 | r"some other random number <0x0\.\d*>": "scrub2", 88 | r"<(.*) at 0x[0-9a-f]+>": "scrub3" 89 | }, 90 | [ 91 | { 92 | 'output_type': 'stream', 93 | 'name': 'stdout', 94 | 'text': ['scrub1\n', '1234\n'] 95 | }, 96 | { 97 | 'output_type': 'execute_result', 98 | 'data': { 99 | 'text/plain': ["'scrub1'"] 100 | }, 101 | 'metadata': {} 102 | } 103 | ] 104 | ) 105 | 106 | def test_scrub_str(self): 107 | self.make_case( 108 | { 109 | r"((a|some other) random number <0x0\.\d*>)|" 110 | r"<(.*) at 0x[0-9a-f]+>": "" 111 | }, 112 | [ 113 | { 114 | 'output_type': 'stream', 115 | 'name': 'stdout', 116 | 'text': ['\n', '1234\n'] 117 | }, { 118 | 'output_type': 'execute_result', 119 | 'data': { 120 | 'text/plain': ["''"] 121 | }, 'metadata': {} 122 | } 123 | ] 124 | ) 125 | --------------------------------------------------------------------------------