├── .github └── workflows │ └── master.yml ├── LICENSE.txt ├── README.md ├── examples ├── capture_output.ipynb ├── example.ipynb └── example_outputs.ipynb ├── ipycache.py ├── ipynb_runner.py ├── requirements.txt ├── setup.py ├── test_ipycache.py ├── test_requirements.txt └── test_requirements_python27.txt /.github/workflows/master.yml: -------------------------------------------------------------------------------- 1 | name: "Run tests" 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | run-tests: 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [ 'ubuntu-18.04', 'ubuntu-20.04', 'macos-10.15', 'macos-11' ] 16 | python: [ '2.7', '3.7', '3.8', '3.9', '3.10' ] 17 | name: Python ${{ matrix.python }} (${{ matrix.os }}) 18 | steps: 19 | - name: Checkout repo 20 | uses: actions/checkout@v2 21 | 22 | - name: Set up Python 23 | uses: actions/setup-python@v2 24 | with: 25 | python-version: ${{ matrix.python }} 26 | architecture: x64 27 | 28 | - name: Set up caching for pip (Linux) 29 | uses: actions/cache@v3 30 | if: startsWith(runner.os, 'Linux') 31 | with: 32 | path: ~/.cache/pip 33 | key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements*.txt') }} 34 | restore-keys: | 35 | ${{ runner.os }}-pip- 36 | 37 | - name: Set up caching for pip (macOS) 38 | uses: actions/cache@v3 39 | if: startsWith(runner.os, 'macOS') 40 | with: 41 | path: ~/Library/Caches/pip 42 | key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements*.txt') }} 43 | restore-keys: | 44 | ${{ runner.os }}-pip- 45 | 46 | - name: Install core requirements 47 | run: pip install -r requirements.txt 48 | 49 | - name: Install Python 2.7 test requirements 50 | if: ${{ matrix.python == '2.7' }} 51 | run: pip install -r test_requirements_python27.txt 52 | 53 | - name: Install Python 3 test requirements 54 | if: ${{ matrix.python != '2.7' }} 55 | run: pip install -r test_requirements.txt 56 | 57 | - name: Run unit tests 58 | run: python -m unittest discover 59 | 60 | - name: Check setup.py metadata 61 | run: python setup.py check --metadata --strict 62 | 63 | - name: Run notebook tests 64 | run: | 65 | python ipynb_runner.py -v -s examples/example.ipynb 66 | python ipynb_runner.py -v -s examples/example_outputs.ipynb 67 | # Removed in https://github.com/rossant/ipycache/commit/632b7732622239cf363e3606f694735818ec6cc6 68 | # when this was using Travis CI; need to look into whether this needs to be re-enabled or removed. 69 | # python ipynb_runner.py -v -s examples/capture_output.ipynb 70 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-present, ipycache development team 2 | Copyright (c) 2013, Cyrille Rossant 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or 6 | without modification, are permitted provided that the following 7 | conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following 14 | disclaimer in the documentation and/or other materials provided 15 | with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived 19 | from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 22 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 29 | USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 | POSSIBILITY OF SUCH DAMAGE. 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ipycache 2 | 3 | [![Build Status][github-ci-badge]][github-ci-url] 4 | [![Latest PyPI version][pypi-badge]][pypi-url] 5 | 6 | [github-ci-badge]: https://github.com/rossant/ipycache/actions/workflows/master.yml/badge.svg 7 | [github-ci-url]: https://github.com/rossant/ipycache/actions/workflows/master.yml 8 | [pypi-badge]: https://img.shields.io/pypi/v/ipycache.svg 9 | [pypi-url]: https://pypi.org/project/ipycache/ 10 | 11 | Defines a `%%cache` cell magic in the IPython notebook to cache results and 12 | outputs of long-lasting computations in a persistent pickle file. Useful when 13 | some computations in a notebook are long and you want to easily save the results 14 | in a file. 15 | 16 | ## Examples 17 | 18 | * [Sample usage](examples/example.ipynb) 19 | * [Example with output](examples/example_outputs.ipynb) 20 | * [Simultaneously printing and capturing output](examples/capture_output.ipynb) 21 | 22 | ## Installation 23 | 24 | Latest PyPI release: 25 | 26 | pip install ipycache 27 | 28 | Latest development version: 29 | 30 | pip install git+https://github.com/rossant/ipycache.git 31 | 32 | ## Usage 33 | 34 | In IPython, execute the following: 35 | 36 | %load_ext ipycache 37 | 38 | Then, create a cell with: 39 | 40 | %%cache mycache.pkl var1 var2 41 | var1 = 1 42 | var2 = 2 43 | 44 | When you execute this cell the first time, the code is executed, and the 45 | variables `var1` and `var2` are saved in `mycache.pkl` in the current directory 46 | along with the outputs. Rich display outputs are only saved if you use the 47 | development version of IPython. When you execute this cell again, the code is 48 | skipped, the variables are loaded from the file and injected into the namespace, 49 | and the outputs are restored in the notebook. 50 | 51 | Alternatively use `$file_name` instead of `mycache.pkl`, where `file_name` is a 52 | variable holding the path to the file used for caching. 53 | 54 | Use the `--force` or `-f` option to force the cell's execution and overwrite the 55 | file. 56 | 57 | Use the `--read` or `-r` option to prevent the cell's execution and always load 58 | the variables from the cache. An exception is raised if the file does not exist. 59 | 60 | Use the `--cachedir` or `-d` option to specify the cache directory. You can 61 | specify a default directory in the IPython configuration file in your profile 62 | (typically in `~\.ipython\profile_default\ipython_config.py`) by adding the 63 | following line: 64 | 65 | c.CacheMagics.cachedir = "/path/to/mycache" 66 | 67 | If both a default cache directory and the `--cachedir` option are given, the 68 | latter is used. 69 | -------------------------------------------------------------------------------- /examples/capture_output.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:8abfcc4f24abe7e7592c8c402c6784ee753805d0c9211245e4923be0209921fb" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "# Demonstrate simultaneous printing and capturing capabilities\n", 16 | "\n", 17 | "see [this branch](https://github.com/ihrke/ipycache/tree/capture_and_print)" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "collapsed": false, 23 | "input": [ 24 | "%reload_ext ipycache\n", 25 | "import pylab as pl\n", 26 | "%matplotlib inline" 27 | ], 28 | "language": "python", 29 | "metadata": {}, 30 | "outputs": [], 31 | "prompt_number": 125 32 | }, 33 | { 34 | "cell_type": "code", 35 | "collapsed": false, 36 | "input": [ 37 | "%%cache test.pkl var\n", 38 | "import time\n", 39 | "var=[i for i in range(100000)]\n", 40 | "\n", 41 | "print \"hallo\"\n", 42 | "for i in range(3):\n", 43 | " time.sleep(1.0)\n", 44 | " print i\n", 45 | "pl.plot(var)" 46 | ], 47 | "language": "python", 48 | "metadata": {}, 49 | "outputs": [ 50 | { 51 | "output_type": "stream", 52 | "stream": "stdout", 53 | "text": [ 54 | "[Skipped the cell's code and loaded variables var from file '/home/mittner/work/prog/stuff/ipycache/test.pkl'.]\n", 55 | "hallo\n", 56 | "0\n", 57 | "1\n", 58 | "2\n" 59 | ] 60 | }, 61 | { 62 | "metadata": {}, 63 | "output_type": "display_data", 64 | "png": "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\nQmCC\n", 65 | "text": [ 66 | "" 67 | ] 68 | } 69 | ], 70 | "prompt_number": 127 71 | }, 72 | { 73 | "cell_type": "code", 74 | "collapsed": false, 75 | "input": [ 76 | "import shelve\n", 77 | "import ipycache " 78 | ], 79 | "language": "python", 80 | "metadata": {}, 81 | "outputs": [], 82 | "prompt_number": 60 83 | }, 84 | { 85 | "cell_type": "code", 86 | "collapsed": false, 87 | "input": [ 88 | "a=ipycache.load_vars('./test.pkl', ['var'])\n", 89 | "print a.keys()\n", 90 | "print \"stdout>\", a['_captured_io']['stdout'].getvalue()\n", 91 | "print \"stderr>\", a['_captured_io']['stderr'].getvalue()\n", 92 | "print \"output>\",a['_captured_io']['outputs']" 93 | ], 94 | "language": "python", 95 | "metadata": {}, 96 | "outputs": [ 97 | { 98 | "output_type": "stream", 99 | "stream": "stdout", 100 | "text": [ 101 | "['var', '_captured_io']\n", 102 | "stdout> hallo\n", 103 | "0\n", 104 | "1\n", 105 | "2\n", 106 | "\n", 107 | "stderr> \n", 108 | "output> [('display', {u'image/png': '\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00\\x01\\x97\\x00\\x00\\x01\\x00\\x08\\x06\\x00\\x00\\x00\\x7f\\x05;\\xf6\\x00\\x00\\x00\\x04sBIT\\x08\\x08\\x08\\x08|\\x08d\\x88\\x00\\x00\\x00\\tpHYs\\x00\\x00\\x0b\\x12\\x00\\x00\\x0b\\x12\\x01\\xd2\\xdd~\\xfc\\x00\\x00\\x16\\xcdIDATx\\x9c\\xed\\xdc\\x7f\\xac_w}\\xdf\\xf1\\xe7k6\\xc9\\xa0\\xd0\\x18g\\xc8\\xf9I\\x92\\xb5N\\x89\\'\\xd6A\\xa6$\\xeb\\xb6r1\\x90zU\\t\\xf9\\x03\\x11G\"\\x8d\\x8a;ix\\x15x\\xcbZ|\\xf9c\\xb9\\xd3\\xa4*\\xa9Z\\x85P\\xe4Tk\\xd2\\x10\\xa29MJ\\xaa\\x90\\xac`b\\x02WC\\x9d\\x82\\xe9\\x9av.\\xc6\\xb3\\x83\\x17\\x1a;\\xd8Af\\x84n\\x7f\\x8c\\xb8~\\xef\\x8f\\xefq|\\xe2\\\\__\\x7f\\xef\\xf7~\\x7f\\xdc\\xf3|HW>\\xdf\\xcf\\xf7|\\xcf=\\xe7\\x80\\xfd\\xb9\\xcfsNn\\xaa\\nI\\x92\\x06\\xe9\\xef\\x8cz\\x07$I\\xcb\\x8f\\x93\\x8b$i\\xe0\\x9c\\\\$I\\x03\\xe7\\xe4\"I\\x1a8\\'\\x17I\\xd2\\xc09\\xb9H\\x92\\x06n\\xde\\xc9%\\xc9\\x1f$9\\x92dwklu\\x92\\x9dI\\xf6%y2\\xc9\\xaa\\xd6{\\xd3I\\xf6\\'\\xd9\\x9b\\xe4\\xfa\\xd6\\xf8\\xd5Iv7\\xef\\xdd\\xdd\\x1a?7\\xc9\\xc3\\xcd\\xf8\\xd3I.k\\xbdwk\\xf3=\\xf6%\\xf9\\xe5\\xc1\\x1d\\xb2$i\\xa9\\x9d\\xa9\\\\\\xee\\x076\\x9c2\\xb6\\x15\\xd8YUW\\x02O5\\xafI\\xb2\\x0e\\xb8\\tX\\xd7|f[\\x924\\x9f\\xb9\\x07\\xd8TUk\\x81\\xb5INls\\x13p\\xb4\\x19\\xbf\\x0b\\xb8\\xb3\\xd9\\xd6j\\xe0\\xdf\\x03\\xd74_\\xb7\\xb7\\'1I\\xd2x\\x9bwr\\xa9\\xaa\\xaf\\x03\\xff\\xfb\\x94\\xe1\\x1b\\x80\\x07\\x9a\\xe5\\x07\\x80\\x1b\\x9b\\xe5\\x0f\\x00\\x0fU\\xd5\\xcbU\\xf5\\x1c\\xf0,pm\\x92\\x0b\\x817U\\xd5\\xaef\\xbd\\xcf\\xb5>\\xd3\\xde\\xd6\\xa3\\xc0{\\x9a\\xe5_\\x00\\x9e\\xac\\xaa\\x1fV\\xd5\\x0f\\x81\\x9d\\xbcv\\x92\\x93$\\x8d\\xa9~\\xee\\xb9\\xac\\xa9\\xaa#\\xcd\\xf2\\x11`M\\xb3|\\x11p\\xb0\\xb5\\xdeA\\xe0\\xe29\\xc6\\x0f5\\xe34\\x7f>\\x0fPU\\xc7\\x80\\x97\\x92\\x9c?\\xcf\\xb6$I\\x13`Q7\\xf4\\xab\\xf7\\xbbc\\xfc\\xfd1\\x92\\xa4WY\\xd9\\xc7g\\x8e$\\xb9\\xa0\\xaa\\x0e7\\x97\\xbc^l\\xc6\\x0f\\x01\\x97\\xb6\\xd6\\xbb\\x84^q\\x1cj\\x96O\\x1d?\\xf1\\x99\\xb7\\x02/$Y\\t\\x9cWUG\\x93\\x1c\\x02\\xa6Z\\x9f\\xb9\\x14\\xf8\\xea\\\\;\\x93\\xc4\\xc9M\\x92\\xceRU\\xe5\\xcck\\xf5\\xaf\\x9fry\\x1c\\xb8\\xb5Y\\xbe\\x15x\\xac5\\xbe1\\xc99I\\xae\\x00\\xd6\\x02\\xbb\\xaa\\xea0\\xf0\\xa3$\\xd767\\xf8o\\x01\\xbe0\\xc7\\xb6>H\\xef\\x01\\x01\\x80\\'\\x81\\xeb\\x93\\xacJ\\xf2f\\xe0}\\xc0\\x97O\\xb7CU\\xe5W\\x15\\xb7\\xdf~\\xfb\\xc8\\xf7a\\x1c\\xbe<\\x0f\\x9e\\x0b\\xcf\\xc5\\xc9\\xaf\\xbf\\xfd\\xdb\\xe2w\\x7f\\xb78\\xff\\xfc\\xe2\\xb7\\x7f\\xbb8vl8?\\x8f\\xcf[.I\\x1e\\x02\\xde\\x05\\xfc\\xbd$\\xcf\\xd3{\\x82\\xeb\\x0e\\xe0\\x91$\\x9b\\x80\\xe7\\x80\\x0f\\x01T\\xd5\\x9e$\\x8f\\x00{\\x80c\\xc0\\xe6\\xaa:q\\x14\\x9b\\x81\\xcf\\x02\\xaf\\x07\\xbeXU;\\x9a\\xf1\\xfb\\x80\\x07\\x93\\xec\\x07\\x8e\\x02\\x1b\\x9bm\\xfd \\xc9\\x7f\\x04\\xbe\\xd9\\xac\\xf7\\x1f\\xaawc_\\x92\\xb4@\\x07\\x0e\\xc0G>\\x02?\\xfe1\\xfc\\xe9\\x9f\\xc2\\xcf\\xfc\\xcc\\xf0\\xbe\\xf7\\xbc\\x93KU\\xdd|\\x9a\\xb7\\xde{\\x9a\\xf5\\x7f\\x13\\xf8\\xcd9\\xc6\\xff;\\xf0\\xf69\\xc6\\xff\\x1f\\xcd\\xe44\\xc7{\\xf7\\xd3{\\x14Z\\x92t\\x16\\x8e\\x1f\\x87m\\xdb`f\\x06\\xa6\\xa7a\\xcb\\x16X\\xb1b\\xb8\\xfb\\xd0\\xcf=\\x17\\x8d\\xa9\\xa9\\xa9\\xa9Q\\xef\\xc2X\\xf0<\\x9c\\xe4\\xb98\\xa9+\\xe7b\\x94\\xb5\\xd2\\x96\\x93W\\xae&S\\x92\\x9a\\xf4c\\x90\\xa4\\xc5:\\x9bZIB-\\xf1\\r}\\xcbE\\x92&\\xdc\\xb8\\xd4J\\x9b\\xbf\\xb8R\\x92&\\xd4\\xf1\\xe3\\xf0\\x99\\xcf\\xc05\\xd7\\xc0\\xfb\\xdf\\x0f_\\xff\\xfaxL,`\\xb9H\\xd2D\\x1a\\xc7Zi\\xb3\\\\$i\\x82\\x8cs\\xad\\xb4Y.\\x924!\\xc6\\xbdV\\xda,\\x17I\\x1as\\x93R+m\\x96\\x8b$\\x8d\\xb1I\\xaa\\x956\\xcbE\\x92\\xc6\\xd0$\\xd6J\\x9b\\xe5\"IcfRk\\xa5\\xcdr\\x91\\xa411\\xe9\\xb5\\xd2f\\xb9H\\xd2\\x18X\\x0e\\xb5\\xd2f\\xb9H\\xd2\\x08-\\xa7Zi\\xb3\\\\$iD\\x96[\\xad\\xb4Y.\\x924d\\xcb\\xb5V\\xda,\\x17I\\x1a\\xa2\\xe5\\\\+m\\x96\\x8b$\\rA\\x17j\\xa5\\xcdr\\x91\\xa4%\\xd6\\x95Zi\\xb3\\\\$i\\x89t\\xadV\\xda,\\x17IZ\\x02]\\xac\\x956\\xcbE\\x92\\x06\\xa8\\xcb\\xb5\\xd2f\\xb9H\\xd2\\x80t\\xbdV\\xda,\\x17IZ$k\\xe5\\xb5,\\x17IZ\\x04ken\\x96\\x8b$\\xf5\\xc1Z\\x99\\x9f\\xe5\"Ig\\xc9Z93\\xcbE\\x92\\x16\\xc8ZY8\\xcbE\\x92\\x16\\xc0Z9;\\x96\\x8b$\\xcd\\xc3Z\\xe9\\x8f\\xe5\"I\\xa7a\\xad\\xf4\\xcfr\\x91\\xa4SX+\\x8bg\\xb9HR\\x8b\\xb52\\x18\\x96\\x8b$a\\xad\\x0c\\x9a\\xe5\"\\xa9\\xf3\\xac\\x95\\xc1\\xb3\\\\$u\\x96\\xb5\\xb2t\\xfa\\x9e\\\\\\x92L\\'\\xf9V\\x92\\xddI\\xb6\\'97\\xc9\\xea$;\\x93\\xecK\\xf2d\\x92U\\xa7\\xac\\xbf?\\xc9\\xde$\\xd7\\xb7\\xc6\\xafn\\xb6\\xb1?\\xc9\\xdd\\xad\\xf1s\\x93<\\xdc\\x8c?\\x9d\\xe4\\xb2\\xfe\\x0fS\\x92^\\xed\\xc0\\x01X\\xbf\\x1e\\xb6o\\xef\\xd5\\xcam\\xb7\\xc1\\x8a\\x15\\xa3\\xde\\xab\\xe5\\xa3\\xaf\\xc9%\\xc9\\xe5\\xc0\\xbf\\x04\\xdeYUo\\x07V\\x00\\x1b\\x81\\xad\\xc0\\xce\\xaa\\xba\\x12x\\xaayM\\x92u\\xc0M\\xc0:`\\x03\\xb0-I\\x9a\\xcd\\xdd\\x03l\\xaa\\xaa\\xb5\\xc0\\xda$\\x1b\\x9a\\xf1M\\xc0\\xd1f\\xfc.\\xe0\\xce~\\xf6U\\x92\\xda\\xac\\x95\\xe1\\xe8\\xb7\\\\~\\x04\\xbc\\x0c\\xbc!\\xc9J\\xe0\\r\\xc0\\x0b\\xc0\\r\\xc0\\x03\\xcd:\\x0f\\x0076\\xcb\\x1f\\x00\\x1e\\xaa\\xaa\\x97\\xab\\xea9\\xe0Y\\xe0\\xda$\\x17\\x02o\\xaa\\xaa]\\xcdz\\x9fk}\\xa6\\xbd\\xadG\\x81\\xf7\\xf4\\xb9\\xaf\\x92\\x04X+\\xc3\\xd4\\xd7\\xe4RU?\\x00~\\x07\\xf8kz\\x93\\xca\\x0f\\xabj\\'\\xb0\\xa6\\xaa\\x8e4\\xab\\x1d\\x01\\xd64\\xcb\\x17\\x01\\x07[\\x9b8\\x08\\\\<\\xc7\\xf8\\xa1f\\x9c\\xe6\\xcf\\xe7\\x9b\\xefw\\x0cx)\\xc9\\xea~\\xf6WR\\xb7Y+\\xc3\\xd7\\xd7\\xd3bI~\\n\\xd8\\x02\\\\\\x0e\\xbc\\x04\\xfcQ\\x92\\x0f\\xb7\\xd7\\xa9\\xaaJR\\x8b\\xde\\xc3\\x05\\x98\\x99\\x99yeyjj\\x8a\\xa9\\xa9\\xa9a|[I\\x13\\xc0\\'\\xc1`vv\\x96\\xd9\\xd9\\xd9\\xa1~\\xcfT\\x9d\\xfd\\xbf\\xffIn\\x02\\xdeWU\\xbf\\xda\\xbc\\xbe\\x05\\xb8\\x0eX\\x0f\\xbc\\xbb\\xaa\\x0e7\\x97\\xbc\\xbeVUoK\\xb2\\x15\\xa0\\xaa\\xeeh\\xd6\\xdf\\x01\\xdc\\x0e|\\xb7Y\\xe7\\xaaf\\xfcf\\xe0\\xe7\\xab\\xea\\xa3\\xcd:3U\\xf5ts\\xe9\\xed{U\\xf5\\x969\\xf6\\xa5\\xfa9\\x06I\\xcb\\xdb\\xf1\\xe3\\xb0m\\x1b\\xcc\\xcc\\xc0\\xf44l\\xd9\\xe2%\\xb0\\x13\\x92PU9\\xf3\\x9a\\xfd\\xeb\\xf7\\x9e\\xcb^\\xe0\\xba$\\xafon\\xcc\\xbf\\x17\\xd8\\x03<\\x01\\xdc\\xda\\xacs+\\xf0X\\xb3\\xfc8\\xb01\\xc99I\\xae\\x00\\xd6\\x02\\xbb\\xaa\\xea0\\xf0\\xa3$\\xd76\\xdb\\xb9\\x05\\xf8B\\xeb3\\'\\xb6\\xf5Az\\x0f\\x08H\\xd2\\x19yoe\\xf4\\xfa\\xbd\\xe7\\xf2\\x97\\xf4n\\xbe\\xff\\x19\\xf0?\\x9a\\xe1\\xff\\x04\\xdc\\x01\\xbc/\\xc9>z\\x15sG\\xb3\\xfe\\x1e\\xe0\\x11z\\x13\\xd0\\x97\\x80\\xcd\\xad\\xdc\\xd8\\x0c\\xdc\\x0b\\xec\\x07\\x9e\\xad\\xaa\\x1d\\xcd\\xf8}\\xc0\\xf9I\\xf6\\xd3\\xbb\\x04\\xb7\\xb5\\x9f}\\x95\\xd4\\x1d\\xde[\\x19\\x1f}]\\x16\\x1b\\'^\\x16\\x93\\x04\\xaf\\xbe\\xb7r\\xff\\xfdN*\\xf3\\x19\\xe7\\xcbb\\x924\\x16\\xac\\x95\\xf1\\xe4\\xef\\x16\\x934\\xb1|\\x12l|Y.\\x92&\\x8e\\xb52\\xfe,\\x17I\\x13\\xc5Z\\x99\\x0c\\x96\\x8b\\xa4\\x89`\\xadL\\x16\\xcbE\\xd2\\xd8\\xb3V&\\x8f\\xe5\"ilY+\\x93\\xcbr\\x914\\x96\\xac\\x95\\xc9f\\xb9H\\x1a+\\xd6\\xca\\xf2`\\xb9H\\x1a\\x1b\\xd6\\xca\\xf2a\\xb9H\\x1a9ke\\xf9\\xb1\\\\$\\x8d\\x94\\xb5\\xb2u\\xfc\\xc4g\\xde\\n\\xbc\\xd0\\\\\\x16;\\xaf\\xaa~0\\xd7\\xce\\xcc\\xcc\\xcc\\xbc\\xb2<55\\xc5\\xd4\\xd4T\\x9f\\x87%M\\xbe\\xe3\\xc7a\\xdb6\\x98\\x99\\x81\\xe9i\\xd8\\xb2\\xc5\\x1b\\xf6]7;;\\xcb\\xec\\xec\\xecP\\xbfg_\\xf7\\\\\\x00\\x92\\xfcW\\xe0W\\xabj_\\x92\\x19\\xe0\\r\\xcd[G\\xab\\xea\\xce$[\\x81UU\\xb5\\xb5\\xb9\\xa1\\xbf\\x1d\\xb8\\x86\\xde\\xe5\\xae\\xaf\\x00?\\xdd\\xd4\\xcd7\\x80\\x8f\\x01\\xbb\\x80?\\x01>]U;\\x92l\\x06\\xde^U\\x1fm\\xee\\xc5\\xdcXU\\x1b\\xe7\\xd8\\x0f\\xef\\xb9H\\r\\xef\\xadh!\\x86q\\xcfe1\\x93\\xcb\\xcf\\x02\\xf7\\x02\\xe7\\x00\\xdf\\x01~\\x05X\\x01TU?l\\xd6\\xff$\\xf0\\x11\\xe0\\x18\\xf0\\xf1\\xaa\\xfar3~5\\xf0Y\\xe0\\xf5\\xf4\\x9e>\\xfbX3~.\\xf0 \\xf0\\x0e\\xe0(\\xb0\\xb1\\xaa\\x9e\\x9bc?\\x9c\\\\\\xd4y\\xd6\\x8a\\xce\\xc6XO.\\xe3\\xc2\\xc9E]g\\xad\\xe8l\\x8d\\xf3\\xd3b\\x92F\\xcc\\'\\xc14\\xce\\xfc\\xddb\\xd2\\x04\\xf2I0\\x8d;\\xcbE\\x9a \\xd6\\x8a&\\x85\\xe5\"M\\x08kE\\x93\\xc4r\\x91\\xc6\\x9c\\xb5\\xa2Id\\xb9Hc\\xccZ\\xd1\\xa4\\xb2\\\\\\xa41d\\xadh\\xd2Y.\\xd2\\x98\\xb1V\\xb4\\x1cX.\\xd2\\x98\\xb0V\\xb4\\x9cX.\\xd2\\x18\\xb0V\\xb4\\xdcX.\\xd2\\x08Y+Z\\xae,\\x17iD\\xac\\x15-g\\x96\\x8b4d\\xd6\\x8a\\xba\\xc0r\\x91\\x86\\xc8ZQWX.\\xd2\\x10X+\\xea\\x1a\\xcbEZb\\xd6\\x8a\\xba\\xc8r\\x91\\x96\\x88\\xb5\\xa2.\\xb3\\\\\\xa4%`\\xad\\xa8\\xeb,\\x17i\\x80\\xac\\x15\\xa9\\xc7r\\x91\\x06\\xc4Z\\x91N\\xb2\\\\\\xa4E\\xb2V\\xa4\\xd7\\xb2\\\\\\xa4E\\xb0V\\xa4\\xb9Y.R\\x1f\\xac\\x15i~\\x96\\x8bt\\x96\\xac\\x15\\xe9\\xcc,\\x17i\\x81\\xac\\x15i\\xe1,\\x17i\\x01\\xac\\x15\\xe9\\xecX.\\xd2<\\xac\\x15\\xa9?\\x96\\x8bt\\x1a\\xd6\\x8a\\xd4?\\xcbE:\\x85\\xb5\"-\\x9e\\xe5\"\\xb5X+\\xd2`X.\\x12\\xd6\\x8a4h\\x96\\x8b:\\xcfZ\\x91\\x06\\xcfrQgY+\\xd2\\xd2\\xb1\\\\\\xd4I\\xd6\\x8a\\xb4\\xb4,\\x17u\\x8a\\xb5\"\\r\\x87\\xe5\\xa2\\xce\\xb0V\\xa4\\xe1YT\\xb9$Y\\x91\\xe4\\x99$O4\\xafW\\'\\xd9\\x99d_\\x92\\'\\x93\\xacj\\xad;\\x9dd\\x7f\\x92\\xbdI\\xaeo\\x8d_\\x9ddw\\xf3\\xde\\xdd\\xad\\xf1s\\x93<\\xdc\\x8c?\\x9d\\xe4\\xb2\\xc5\\xec\\xab\\xba\\xcbZ\\x91\\x86o\\xb1\\x97\\xc5>\\x0e\\xec\\x01\\xaay\\xbd\\x15\\xd8YUW\\x02O5\\xafI\\xb2\\x0e\\xb8\\tX\\x07l\\x00\\xb6%I\\xf3\\x99{\\x80MU\\xb5\\x16X\\x9bdC3\\xbe\\t8\\xda\\x8c\\xdf\\x05\\xdc\\xb9\\xc8}U\\x07\\x1d8\\x00\\xeb\\xd7\\xc3\\xf6\\xed\\xbdZ\\xb9\\xed6X\\xb1b\\xd4{%-\\x7f}O.I.\\x01~\\x11\\xb8\\x1781Q\\xdc\\x00<\\xd0,?\\x00\\xdc\\xd8,\\x7f\\x00x\\xa8\\xaa^\\xae\\xaa\\xe7\\x80g\\x81k\\x93\\\\\\x08\\xbc\\xa9\\xaav5\\xeb}\\xae\\xf5\\x99\\xf6\\xb6\\x1e\\x05\\xde\\xd3\\xef\\xbe\\xaa{\\xac\\x15i\\xb4\\x16s\\xcf\\xe5.\\xe0\\xd7\\x81\\x9fl\\x8d\\xad\\xa9\\xaa#\\xcd\\xf2\\x11`M\\xb3|\\x11\\xf0tk\\xbd\\x83\\xc0\\xc5\\xc0\\xcb\\xcd\\xf2\\t\\x87\\x9aq\\x9a?\\x9f\\x07\\xa8\\xaacI^J\\xb2\\xba\\xaa~\\xb0\\x88}V\\x07xoE\\x1a\\xbd\\xbe\\xca%\\xc9/\\x01/V\\xd53\\x9c\\xac\\x96W\\xa9\\xaa\\xe2\\xe4\\xe52i\\xc9Y+\\xd2\\xf8\\xe8\\xb7\\\\~\\x0e\\xb8!\\xc9/\\x02\\x7f\\x17\\xf8\\xc9$\\x0f\\x02G\\x92\\\\PU\\x87\\x9bK^/6\\xeb\\x1f\\x02.m}\\xfe\\x12z\\xc5r\\xa8Y>u\\xfc\\xc4g\\xde\\n\\xbc\\x90d%p\\xde\\xe9\\xaaeff\\xe6\\x95\\xe5\\xa9\\xa9)\\xa6\\xa6\\xa6\\xfa<,M*kE:\\xbd\\xd9\\xd9Yfgg\\x87\\xfa=\\xd3\\x0b\\x8cEl y\\x17\\xf0\\xef\\xaa\\xea\\xfdI~\\x8b\\xdeM\\xf8;\\x93l\\x05VU\\xd5\\xd6\\xe6\\x86\\xfev\\xe0\\x1az\\x97\\xbb\\xbe\\x02\\xfctUU\\x92o\\x00\\x1f\\x03v\\x01\\x7f\\x02|\\xba\\xaav$\\xd9\\x0c\\xbc\\xbd\\xaa>\\x9ad#pcUm\\x9c\\xe3\\xfb\\xd7b\\x8fA\\x93\\xeb\\xf8q\\xd8\\xb6\\rff`z\\x1a\\xb6l\\xf1\\x86\\xbdt&I\\xa8\\xaa9\\xaf:\\r\\xca\\xa0\\xfe;\\x97\\x13\\xff\\xba\\xdf\\x01<\\x92d\\x13\\xf0\\x1c\\xf0!\\x80\\xaa\\xda\\x93\\xe4\\x11zO\\x96\\x1d\\x036\\xb7f\\x84\\xcd\\xc0g\\x81\\xd7\\x03_\\xac\\xaa\\x1d\\xcd\\xf8}\\xc0\\x83I\\xf6\\x03G\\x81\\xd7L,\\xea6kE\\x1a_\\x8b.\\x97Q\\xb3\\\\\\xba\\xc7Z\\x91\\x16g\\x92\\xcaE\\x1a\\nkE\\x9a\\x0c\\xfen1M\\x04\\x9f\\x04\\x93&\\x8b\\xe5\\xa2\\xb1g\\xadH\\x93\\xc7r\\xd1\\xd8\\xb2V\\xa4\\xc9e\\xb9h,Y+\\xd2d\\xb3\\\\4V\\xac\\x15iy\\xb0\\\\46\\xac\\x15i\\xf9\\xb0\\\\4r\\xd6\\x8a\\xb4\\xfcX.\\x1a)kEZ\\x9e,\\x17\\x8d\\x84\\xb5\"-o\\x96\\x8b\\x86\\xceZ\\x91\\x96?\\xcbECc\\xadH\\xdda\\xb9h(\\xac\\x15\\xa9[,\\x17-)kE\\xea&\\xcbEK\\xc6Z\\x91\\xba\\xcbr\\xd1\\xc0Y+\\x92,\\x17\\r\\x94\\xb5\"\\t,\\x17\\r\\x88\\xb5\"\\xa9\\xcdr\\xd1\\xa2Y+\\x92Ne\\xb9\\xa8o\\xd6\\x8a\\xa4\\xd3\\xb1\\\\\\xd4\\x17kE\\xd2|,\\x17\\x9d\\x15kE\\xd2BX.Z0kE\\xd2BY.:#kE\\xd2\\xd9\\xb2\\\\4/kER?,\\x17\\xcd\\xc9Z\\x91\\xb4\\x18\\x96\\x8b^\\xc3Z\\x91\\xb4X\\x96\\x8b^a\\xadH\\x1a\\x14\\xcbE\\x80\\xb5\"i\\xb0,\\x97\\x8e\\xb3V$-\\x05\\xcb\\xa5\\xc3\\xac\\x15IK\\xc5r\\xe9 kE\\xd2R\\xb3\\\\:\\xc6Z\\x914\\x0c\\x96KGX+\\x92\\x86\\xc9r\\xe9\\x00kE\\xd2\\xb0Y.\\xcb\\x98\\xb5\"iT\\xfa\\x9a\\\\\\x92\\\\\\x9a\\xe4kI\\xbe\\x95\\xe4\\xaf\\x92|\\xac\\x19_\\x9ddg\\x92}I\\x9eL\\xb2\\xaa\\xf5\\x99\\xe9$\\xfb\\x93\\xecMr}k\\xfc\\xea$\\xbb\\x9b\\xf7\\xeen\\x8d\\x9f\\x9b\\xe4\\xe1f\\xfc\\xe9$\\x97-\\xe6@\\xbb\\xe6\\xc0\\x01X\\xbf\\x1e\\xb6o\\xef\\xd5\\xcam\\xb7\\xc1\\x8a\\x15\\xa3\\xde+I]\\xd1o\\xb9\\xbc\\x0c\\xfc\\x9b\\xaa\\xfa\\x07\\xc0u\\xc0\\xbfNr\\x15\\xb0\\x15\\xd8YUW\\x02O5\\xafI\\xb2\\x0e\\xb8\\tX\\x07l\\x00\\xb6%I\\xb3\\xad{\\x80MU\\xb5\\x16X\\x9bdC3\\xbe\\t8\\xda\\x8c\\xdf\\x05\\xdc\\xd9\\xe7\\xbev\\x8a\\xb5\"i\\x1c\\xf4u\\xcf\\xa5\\xaa\\x0e\\x03\\x87\\x9b\\xe5\\xff\\x93\\xe4\\xdb\\xc0\\xc5\\xc0\\r\\xc0\\xbb\\x9a\\xd5\\x1e\\x00f\\xe9M0\\x1f\\x00\\x1e\\xaa\\xaa\\x97\\x81\\xe7\\x92<\\x0b\\\\\\x9b\\xe4\\xbb\\xc0\\x9b\\xaajW\\xf3\\x99\\xcf\\x017\\x02;\\x9am\\xdd\\xde\\x8c?\\n|\\xa6\\x9f}\\xed\\x12\\xef\\xadH\\x1a\\x17\\x8b\\xbe\\xe7\\x92\\xe4r\\xe0\\x1d\\xc07\\x805Uu\\xa4y\\xeb\\x08\\xb0\\xa6Y\\xbe\\x088\\xd8\\xfa\\xd8Az\\x93\\xd1\\xa9\\xe3\\x87\\x9aq\\x9a?\\x9f\\x07\\xa8\\xaac\\xc0KIV/v\\x7f\\x97#kE\\xd2\\xb8Y\\xd4\\xd3bI\\xdeH\\xaf*>^U\\x7fs\\xf2J\\x17TU%\\xa9E\\xee\\xdf\\x82\\xcc\\xcc\\xcc\\xbc\\xb2<55\\xc5\\xd4\\xd4\\xd40\\xbe\\xedX\\xb0V$\\x9d\\xc9\\xec\\xec,\\xb3\\xb3\\xb3C\\xfd\\x9e\\xa9\\xea\\xef\\xdf\\xff$\\xaf\\x03\\xfe\\x0b\\xf0\\xa5\\xaa\\xfaT3\\xb6\\x17\\x98\\xaa\\xaa\\xc3I.\\x04\\xbeVUoK\\xb2\\x15\\xa0\\xaa\\xeeh\\xd6\\xdbA\\xef\\x92\\xd7w\\x9bu\\xaej\\xc6o\\x06~\\xbe\\xaa>\\xda\\xac3SUO\\'Y\\t|\\xaf\\xaa\\xde2\\xc7~T\\xbf\\xc70\\xc9\\x8e\\x1f\\x87m\\xdb`f\\x06\\xa6\\xa7a\\xcb\\x16o\\xd8KZ\\x98$TU\\xce\\xbcf\\xff\\xfa}Z,\\xc0}\\xc0\\x9e\\x13\\x13K\\xe3q\\xe0\\xd6f\\xf9V\\xe0\\xb1\\xd6\\xf8\\xc6$\\xe7$\\xb9\\x02X\\x0b\\xecj\\xee\\xdd\\xfc(\\xc9\\xb5\\xcd6o\\x01\\xbe0\\xc7\\xb6>H\\xef\\x01\\x01\\xe1\\x93`\\x92\\xc6_\\xbf\\xf7\\\\\\xfe)\\xf0a\\xe0\\xddI\\x9ei\\xbe6\\x00w\\x00\\xefK\\xb2\\x0fX\\xdf\\xbc\\xa6\\xaa\\xf6\\x00\\x8f\\x00{\\x80/\\x01\\x9b[\\xb9\\xb1\\x19\\xb8\\x17\\xd8\\x0f<[U;\\x9a\\xf1\\xfb\\x80\\xf3\\x93\\xec\\x07\\xb6\\xd0\\xb9\\\\\\x0c<\\xdfz}\\xb0\\x19{\\x95.\\xd7\\x8a$\\x8d\\xa3q\\xbf\\xe7R\\x0bY\\xc9{+\\x924^R\\xb5\\xa0\\x7f\\xbfG\"\\xc9u\\xc0LUmh^O\\x03\\xc7\\xdb7\\xf5\\x93\\x8c\\xef\\x01H\\xd2\\x98\\xaa\\xaa,\\xe5\\xf6\\xc7}rY\\t\\xfcO\\xe0=\\xc0\\x0b\\xc0.\\xe0\\xe6\\xaa\\xfa\\xf6HwL\\x924\\xaf\\xb1\\xbe,VU\\xc7\\x92\\xfc\\x1a\\xf0ez\\x8f\"\\xdf\\xe7\\xc4\"I\\xe3o\\xac\\xcbE\\x924\\x99\\xc6\\xfdi\\xb1\\xd3J\\xb2!\\xc9\\xde$\\xfb\\x93|b\\xd4\\xfb3\\x08I.M\\xf2\\xb5$\\xdfJ\\xf2WI>\\xd6\\x8c\\xafN\\xb23\\xc9\\xbe$O&Y\\xd5\\xfa\\xccts\\x0e\\xf6&\\xb9\\xbe5~u\\x92\\xdd\\xcd{w\\xb7\\xc6\\xcfM\\xf2p3\\xfet\\x92\\xcb\\x86{\\x94g\\'\\xc9\\x8a$\\xcf$y\\xa2y\\xdd\\xc9s\\x91dU\\x92\\xcf\\'\\xf9v\\x92=I\\xae\\xed\\xf0\\xb9\\x98n\\xfe\\x8e\\xecN\\xb2\\xbd\\xd9\\xf7N\\x9c\\x8b$\\x7f\\x90\\xe4H\\x92\\xdd\\xad\\xb1\\xa1\\x1c{\\x92[\\x9b\\xef\\xb1/\\xc9/\\x9fqg\\xabj\\xe2\\xbe\\xe8]\"{\\x16\\xb8\\x1cx\\x1d\\xf0\\x17\\xc0U\\xa3\\xde\\xaf\\x01\\x1c\\xd7\\x05\\xc0?j\\x96\\xdfH\\xef~\\xd3U\\xc0o\\x01\\xbf\\xd1\\x8c\\x7f\\x02\\xb8\\xa3Y^\\xd7\\x1c\\xfb\\xeb\\x9as\\xf1,\\'kt\\x17pM\\xb3\\xfcE`C\\xb3\\xbc\\x19\\xd8\\xd6,\\xdf\\x04\\xfc\\xe1\\xa8\\x8f\\xfb\\x0c\\xe7\\xe4\\xdf\\x02\\xff\\x19x\\xbcy\\xdd\\xc9s\\x01<\\x00|\\xa4Y^\\t\\x9c\\xd7\\xc5s\\xd1\\x1c\\xcf\\x01\\xe0\\xdc\\xe6\\xf5\\xc3\\xc0\\xad]9\\x17\\xc0?\\x07\\xde\\x01\\xecn\\x8d-\\xf9\\xb1\\x03\\xab\\x81\\xef\\x00\\xab\\x9a\\xaf\\xef\\x00\\xab\\xe6\\xdd\\xd7Q\\x9f\\xac>O\\xf0?\\x01v\\xb4^o\\x05\\xb6\\x8ez\\xbf\\x96\\xe08\\x1f\\x03\\xde\\x0b\\xec\\x05\\xd64c\\x17\\x00{\\x9b\\xe5i\\xe0\\x13\\xad\\xf5w\\x00\\xd7\\x01\\x17\\x02\\xdfn\\x8do\\x04~\\xaf\\xb5\\xce\\xb5\\xcd\\xf2J\\xe0\\xfb\\xa3>\\xcey\\x8e\\xff\\x12\\xe0+\\xc0\\xbb\\x81\\'\\x9a\\xb1\\xce\\x9d\\x0bz\\x13\\xc9\\x819\\xc6\\xbbx.V\\xd3\\xfb\\xa1\\xeb\\xcd\\xcd~>\\x01\\xbc\\xafK\\xe7\\x82\\xdeD\\xd1\\x9e\\\\\\x96\\xfc\\xd8\\x81\\x9b\\x81{Z\\x9f\\xf9=`\\xe3|\\xfb9\\xa9\\x97\\xc5\\x16\\xf4\\x1fWN\\xb2$\\x97\\xd3\\xfb\\t\\xe5\\x1b\\xf4\\xfe\\x8fs\\xa4y\\xeb\\x08\\xb0\\xa6Y\\xbe\\x88\\xde\\xb1\\x9fp\\xe2<\\x9c:~\\x88\\x93\\xe7\\xe7\\x95sWU\\xc7\\x80\\x97\\x92\\xac\\x1e\\xfc\\x11\\x0c\\xc4]\\xc0\\xaf\\x03\\xc7[c]<\\x17W\\x00\\xdfOr\\x7f\\x92?O\\xf2\\xfbI~\\x82\\x0e\\x9e\\x8b\\xaa\\xfa\\x01\\xf0;\\xc0_\\xd3{\\x82\\xf4\\x87U\\xb5\\x93\\x0e\\x9e\\x8b\\x96\\xa5>\\xf6\\xf3\\xe7\\xd9\\xd6iM\\xea\\xe4\\xb2\\xac\\x9fBH\\xf2F\\xe0Q\\xe0\\xe3U\\xf57\\xed\\xf7\\xaa\\xf7c\\xc3\\xb2>~\\x80$\\xbf\\x04\\xbcXU\\xcf\\x00s>\\x8f\\xdf\\x95sA\\xef\\'\\xc8w\\xd2\\xbb\\\\\\xf1N\\xe0\\xff\\xd2\\xab\\xf5Wt\\xe5\\\\$\\xf9)`\\x0b\\xbd\\x9f\\xde/\\x02\\xde\\x98\\xe4\\xc3\\xedu\\xbar.\\xe62N\\xc7>\\xa9\\x93\\xcb!\\xe0\\xd2\\xd6\\xebKy\\xf5\\xac:\\xb1\\x92\\xbc\\x8e\\xde\\xc4\\xf2`U=\\xd6\\x0c\\x1fIrA\\xf3\\xfe\\x85\\xc0\\x8b\\xcd\\xf8\\xa9\\xe7\\xe1\\x12z\\xe7\\xe1P\\xb3|\\xea\\xf8\\x89\\xcf\\xbc\\xb5\\xd9\\xd6J\\xe0\\xbc\\xe6\\xa7\\xc1q\\xf3s\\xc0\\rI\\xfe\\x17\\xf0\\x10\\xb0>\\xc9\\x83t\\xf3\\\\\\x1c\\x04\\x0eV\\xd57\\x9b\\xd7\\x9f\\xa77\\xd9\\x1c\\xee\\xe0\\xb9\\xf8\\xc7\\xc0\\x7f\\xab\\xaa\\xa3\\xcdO\\xd6\\x7fL\\xef2y\\x17\\xcf\\xc5\\tK\\xfdw\\xe2\\xe8\\x1c\\xdb:\\xe3\\xbf\\xb9\\x93:\\xb9\\xfc\\x19\\xb06\\xc9\\xe5I\\xce\\xa1w\\xe3\\xe9\\xf1\\x11\\xef\\xd3\\xa2%\\tp\\x1f\\xb0\\xa7\\xaa>\\xd5z\\xebqz7-i\\xfe|\\xac5\\xbe1\\xc99I\\xae\\x00\\xd6\\x02\\xbb\\xaa\\xea0\\xf0\\xa3\\xe6\\x89\\xa2\\x00\\xb7\\x00_\\x98c[\\x1f\\x04\\x9eZ\\xb2\\x03Z\\x84\\xaa\\xfadU]ZUW\\xd0\\xbb&\\xfc\\xd5\\xaa\\xba\\x85n\\x9e\\x8b\\xc3\\xc0\\xf3I\\xael\\x86\\xde\\x0b|\\x8b\\xde\\xfd\\x86N\\x9d\\x0bz\\xf7\\x17\\xaeK\\xf2\\xfa\\xe6\\x18\\xde\\x0b\\xec\\xa1\\x9b\\xe7\\xe2\\x84a\\xfc\\x9dx\\x12\\xb8>\\xbd\\xa7\\x16\\xdfL\\xef>\\xd7\\x97\\xe7\\xdd\\xabQ\\xdf\\x9cZ\\xc4M\\xad\\x7fA\\xef\\xc6\\xde\\xb3\\xc0\\xf4\\xa8\\xf7g@\\xc7\\xf4\\xcf\\xe8\\xdd_\\xf8\\x0b\\xe0\\x99\\xe6k\\x03\\xbd\\x9b\\x98_\\x01\\xf65\\xff#\\xafj}\\xe6\\x93\\xcd9\\xd8\\x0b\\xfcBk\\xfcj`w\\xf3\\xde\\xa7[\\xe3\\xe7\\x02\\x8f\\x00\\xfb\\x81\\xa7\\x81\\xcbG}\\xdc\\x0b8/\\xef\\xe2\\xe4\\xd3b\\x9d<\\x17\\xc0\\xcf\\x02\\xdf\\x04\\xfe\\x92\\xdeO\\xeb\\xe7u\\xf8\\\\\\xfc\\x06\\xbd\\xc9u7\\xbd\\xa7\\xe8^\\xd7\\x95sA\\xaf\\xe2_\\x00~L\\xef\\xde\\xc8\\xaf\\x0c\\xeb\\xd8\\x9b\\xef\\xb5\\xbf\\xf9\\xba\\xf5L\\xfb\\xea\\x7fD)I\\x1a\\xb8I\\xbd,&I\\x1acN.\\x92\\xa4\\x81sr\\x91$\\r\\x9c\\x93\\x8b$i\\xe0\\x9c\\\\$I\\x03\\xe7\\xe4\"I\\x1a8\\'\\x17I\\xd2\\xc09\\xb9H\\x92\\x06\\xee\\xff\\x03k\\x14\\xb4\\xfd3*\\xec\\xc9\\x00\\x00\\x00\\x00IEND\\xaeB`\\x82', u'text/plain': ''}, {})]\n" 109 | ] 110 | } 111 | ], 112 | "prompt_number": 100 113 | } 114 | ], 115 | "metadata": {} 116 | } 117 | ] 118 | } -------------------------------------------------------------------------------- /examples/example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "" 4 | }, 5 | "nbformat": 3, 6 | "nbformat_minor": 0, 7 | "worksheets": [ 8 | { 9 | "cells": [ 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# Caching variables in a file" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "The [ipycache](https://github.com/rossant/ipycache) package defines a `%%cache` cell magic allowing you to cache results of long-lasting computations in a pickle file." 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "collapsed": false, 27 | "input": [ 28 | "import numpy as np" 29 | ], 30 | "language": "python", 31 | "metadata": {}, 32 | "outputs": [], 33 | "prompt_number": 1 34 | }, 35 | { 36 | "cell_type": "code", 37 | "collapsed": false, 38 | "input": [ 39 | "%load_ext ipycache" 40 | ], 41 | "language": "python", 42 | "metadata": {}, 43 | "outputs": [], 44 | "prompt_number": 2 45 | }, 46 | { 47 | "cell_type": "code", 48 | "collapsed": false, 49 | "input": [ 50 | "def long_function(a, b):\n", 51 | " import time\n", 52 | " time.sleep(1)\n", 53 | " return a + b" 54 | ], 55 | "language": "python", 56 | "metadata": {}, 57 | "outputs": [], 58 | "prompt_number": 3 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": {}, 63 | "source": [ 64 | "The following cell will only be executed if the pickle file does not exist (also, there is a `--force` option to always execute the cell and overwrite the results in the pickle file)." 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "collapsed": false, 70 | "input": [ 71 | "%%cache myvars.pkl a b c\n", 72 | "a = 3\n", 73 | "b = np.random.randn(3)\n", 74 | "c = long_function(a, b)" 75 | ], 76 | "language": "python", 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "output_type": "stream", 81 | "stream": "stdout", 82 | "text": [ 83 | "Saved variables a, b, c to file 'myvars.pkl'.\n" 84 | ] 85 | } 86 | ], 87 | "prompt_number": 4 88 | }, 89 | { 90 | "cell_type": "code", 91 | "collapsed": false, 92 | "input": [ 93 | "print(a, b, c)" 94 | ], 95 | "language": "python", 96 | "metadata": {}, 97 | "outputs": [ 98 | { 99 | "output_type": "stream", 100 | "stream": "stdout", 101 | "text": [ 102 | "(3, array([-0.95123539, -0.17912806, -0.50877324]), array([ 2.04876461, 2.82087194, 2.49122676]))\n" 103 | ] 104 | } 105 | ], 106 | "prompt_number": 5 107 | }, 108 | { 109 | "cell_type": "code", 110 | "collapsed": false, 111 | "input": [ 112 | "del a, b, c" 113 | ], 114 | "language": "python", 115 | "metadata": {}, 116 | "outputs": [], 117 | "prompt_number": 6 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "Now, we execute the same cell again (in practice, the cell only appears once in the notebook, so this simulates multiple executions of the same cell)." 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "collapsed": false, 129 | "input": [ 130 | "%%cache myvars.pkl a b c\n", 131 | "a = 3\n", 132 | "b = np.random.randn(3)\n", 133 | "c = long_function(a, b)" 134 | ], 135 | "language": "python", 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "output_type": "stream", 140 | "stream": "stdout", 141 | "text": [ 142 | "Skipped the cell's code and loaded variables a, b, c from file 'myvars.pkl'.\n" 143 | ] 144 | } 145 | ], 146 | "prompt_number": 7 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "The cell has been skipped, but the variables have been recovered from the pickle file." 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "collapsed": false, 158 | "input": [ 159 | "print(a, b, c)" 160 | ], 161 | "language": "python", 162 | "metadata": {}, 163 | "outputs": [ 164 | { 165 | "output_type": "stream", 166 | "stream": "stdout", 167 | "text": [ 168 | "(3, array([-0.95123539, -0.17912806, -0.50877324]), array([ 2.04876461, 2.82087194, 2.49122676]))\n" 169 | ] 170 | } 171 | ], 172 | "prompt_number": 8 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "Now, let's delete the file." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "collapsed": false, 184 | "input": [ 185 | "import os\n", 186 | "os.remove('myvars.pkl')" 187 | ], 188 | "language": "python", 189 | "metadata": {}, 190 | "outputs": [], 191 | "prompt_number": 9 192 | }, 193 | { 194 | "cell_type": "markdown", 195 | "metadata": {}, 196 | "source": [ 197 | "Let's execute the cell once more." 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "collapsed": false, 203 | "input": [ 204 | "%%cache myvars.pkl a b c\n", 205 | "a = 3\n", 206 | "b = np.random.randn(3)\n", 207 | "c = long_function(a, b)" 208 | ], 209 | "language": "python", 210 | "metadata": {}, 211 | "outputs": [ 212 | { 213 | "output_type": "stream", 214 | "stream": "stdout", 215 | "text": [ 216 | "Saved variables a, b, c to file 'myvars.pkl'.\n" 217 | ] 218 | } 219 | ], 220 | "prompt_number": 10 221 | }, 222 | { 223 | "cell_type": "code", 224 | "collapsed": false, 225 | "input": [ 226 | "print(a, b, c)" 227 | ], 228 | "language": "python", 229 | "metadata": {}, 230 | "outputs": [ 231 | { 232 | "output_type": "stream", 233 | "stream": "stdout", 234 | "text": [ 235 | "(3, array([ 0.19778047, 1.81953213, -0.1259566 ]), array([ 3.19778047, 4.81953213, 2.8740434 ]))\n" 236 | ] 237 | } 238 | ], 239 | "prompt_number": 11 240 | }, 241 | { 242 | "cell_type": "code", 243 | "collapsed": false, 244 | "input": [ 245 | "os.remove('myvars.pkl')" 246 | ], 247 | "language": "python", 248 | "metadata": {}, 249 | "outputs": [], 250 | "prompt_number": 12 251 | } 252 | ], 253 | "metadata": {} 254 | } 255 | ] 256 | } -------------------------------------------------------------------------------- /examples/example_outputs.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "" 4 | }, 5 | "nbformat": 3, 6 | "nbformat_minor": 0, 7 | "worksheets": [ 8 | { 9 | "cells": [ 10 | { 11 | "cell_type": "code", 12 | "collapsed": false, 13 | "input": [ 14 | "%pylab inline" 15 | ], 16 | "language": "python", 17 | "metadata": {}, 18 | "outputs": [ 19 | { 20 | "output_type": "stream", 21 | "stream": "stdout", 22 | "text": [ 23 | "Populating the interactive namespace from numpy and matplotlib\n" 24 | ] 25 | } 26 | ], 27 | "prompt_number": 1 28 | }, 29 | { 30 | "cell_type": "code", 31 | "collapsed": false, 32 | "input": [ 33 | "%load_ext ipycache" 34 | ], 35 | "language": "python", 36 | "metadata": {}, 37 | "outputs": [], 38 | "prompt_number": 2 39 | }, 40 | { 41 | "cell_type": "code", 42 | "collapsed": false, 43 | "input": [ 44 | "%%cache plot.pkl\n", 45 | "print(\"Hello world!\")\n", 46 | "plt.plot(np.random.randn(1000));\n", 47 | "plt.show()" 48 | ], 49 | "language": "python", 50 | "metadata": {}, 51 | "outputs": [ 52 | { 53 | "output_type": "stream", 54 | "stream": "stdout", 55 | "text": [ 56 | "[Skipped the cell's code and loaded variables from file 'D:\\git\\ipycache\\examples\\plot.pkl'.]\n", 57 | "Hello world!\n" 58 | ] 59 | }, 60 | { 61 | "metadata": {}, 62 | "output_type": "display_data", 63 | "png": "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\nrkJggg==\n", 64 | "text": [ 65 | "" 66 | ] 67 | } 68 | ], 69 | "prompt_number": 4 70 | }, 71 | { 72 | "cell_type": "code", 73 | "collapsed": false, 74 | "input": [ 75 | "import os\n", 76 | "os.remove('plot.pkl')" 77 | ], 78 | "language": "python", 79 | "metadata": {}, 80 | "outputs": [], 81 | "prompt_number": 5 82 | } 83 | ], 84 | "metadata": {} 85 | } 86 | ] 87 | } -------------------------------------------------------------------------------- /ipycache.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Defines a %%cache cell magic in the notebook to persistent-cache results of 3 | long-lasting computations. 4 | """ 5 | 6 | import hashlib 7 | import os 8 | import re 9 | import sys 10 | 11 | from traitlets.config.configurable import Configurable 12 | from IPython.core import magic_arguments 13 | from IPython.core.magic import Magics, magics_class, line_magic, cell_magic 14 | from IPython.display import clear_output 15 | import IPython.utils.io 16 | from IPython.utils.io import CapturedIO, capture_output 17 | from traitlets import Unicode 18 | 19 | 20 | # ------------------------------------------------------------------------------ 21 | # Six utility functions for Python 2/3 compatibility 22 | # ------------------------------------------------------------------------------ 23 | # Author: "Benjamin Peterson " 24 | 25 | PY2 = sys.version_info[0] == 2 26 | PY3 = sys.version_info[0] == 3 27 | 28 | if PY3: 29 | import builtins 30 | import pickle 31 | from io import StringIO 32 | _iteritems = "items" 33 | 34 | exec_ = getattr(builtins, "exec") 35 | else: 36 | import cPickle as pickle 37 | from StringIO import StringIO 38 | _iteritems = "iteritems" 39 | 40 | def exec_(_code_, _globs_=None, _locs_=None): 41 | """Execute code in a namespace.""" 42 | if _globs_ is None: 43 | frame = sys._getframe(1) 44 | _globs_ = frame.f_globals 45 | if _locs_ is None: 46 | _locs_ = frame.f_locals 47 | del frame 48 | elif _locs_ is None: 49 | _locs_ = _globs_ 50 | exec("""exec _code_ in _globs_, _locs_""") 51 | 52 | 53 | def iteritems(d, **kw): 54 | """Return an iterator over the (key, value) pairs of a dictionary.""" 55 | return iter(getattr(d, _iteritems)(**kw)) 56 | 57 | # ------------------------------------------------------------------------------ 58 | # cloudpickle 59 | # ------------------------------------------------------------------------------ 60 | 61 | 62 | try: 63 | import cloudpickle 64 | dump = cloudpickle.dump 65 | except ImportError: 66 | dump = pickle.dump 67 | 68 | # ------------------------------------------------------------------------------ 69 | # Functions 70 | # ------------------------------------------------------------------------------ 71 | 72 | 73 | def conditional_eval(var, variables): 74 | """Evaluates the variable string if it starts with $. 75 | 76 | If the variable string contains one or several {code} statements, the code 77 | is executed and the result stringified (wrapped in str()) into the rest of 78 | the string. 79 | """ 80 | if var[0] == '$': 81 | return variables.get(var[1:], var) 82 | 83 | def evalfun(x): 84 | code = x.group(0)[1:-1] 85 | return str(eval(code, variables)) 86 | return re.sub(r'{.*?}', evalfun, var, flags=re.DOTALL) 87 | 88 | 89 | def clean_var(var): 90 | """Clean variable name, removing accidental commas, etc.""" 91 | return var.strip().replace(',', '') 92 | 93 | 94 | def clean_vars(vars): 95 | """Clean variable names, removing accidental commas, etc.""" 96 | return sorted(map(clean_var, vars)) 97 | 98 | 99 | def do_save(path, force=False, read=False): 100 | """Return True or False whether the variables need to be saved or not.""" 101 | if force and read: 102 | raise ValueError(("The 'force' and 'read' options are " 103 | "mutually exclusive.")) 104 | 105 | # Execute the cell and save the variables. 106 | return force or (not read and not os.path.exists(path)) 107 | 108 | 109 | def load_vars(path, vars): 110 | """Load variables from a pickle file. 111 | 112 | Arguments: 113 | 114 | * path: the path to the pickle file. 115 | * vars: a list of variable names. 116 | 117 | Returns: 118 | 119 | * cache: a dictionary {var_name: var_value}. 120 | """ 121 | with open(path, 'rb') as f: 122 | # Load the variables from the cache. 123 | try: 124 | cache = pickle.load(f) 125 | except EOFError as e: 126 | cache = {} 127 | #raise IOError(str(e)) 128 | 129 | # Check that all requested variables could be loaded successfully 130 | # from the cache. 131 | missing_vars = sorted(set(vars) - set(cache.keys())) 132 | if missing_vars: 133 | raise ValueError(("The following variables could not be loaded " 134 | "from the cache: {0:s}").format( 135 | ', '.join(["'{0:s}'".format(var) for var in missing_vars]))) 136 | additional_vars = sorted(set(cache.keys()) - set(vars)) 137 | for hidden_variable in '_captured_io', '_cell_md5': 138 | try: 139 | additional_vars.remove(hidden_variable) 140 | except ValueError: 141 | pass 142 | if additional_vars: 143 | raise ValueError("The following variables were present in the cache, " 144 | "but removed from the storage request: {0:s}".format( 145 | ', '.join(["'{0:s}'".format(var) for var in additional_vars]))) 146 | 147 | return cache 148 | 149 | 150 | def save_vars(path, vars_d): 151 | """Save variables into a pickle file. 152 | 153 | Arguments: 154 | 155 | * path: the path to the pickle file. 156 | * vars_d: a dictionary {var_name: var_value}. 157 | """ 158 | with open(path, 'wb') as f: 159 | dump(vars_d, f) 160 | 161 | 162 | # ------------------------------------------------------------------------------ 163 | # CapturedIO 164 | # ------------------------------------------------------------------------------ 165 | def save_captured_io(io): 166 | return dict( 167 | stdout=StringIO(io._stdout.getvalue()), 168 | stderr=StringIO(io._stderr.getvalue()), 169 | outputs=getattr(io, '_outputs', []), # Only IPython master has this 170 | ) 171 | 172 | 173 | def load_captured_io(captured_io): 174 | try: 175 | return CapturedIO(captured_io.get('stdout', None), 176 | captured_io.get('stderr', None), 177 | outputs=captured_io.get('outputs', []), 178 | ) 179 | except TypeError: 180 | return CapturedIO(captured_io.get('stdout', None), 181 | captured_io.get('stderr', None), 182 | ) 183 | 184 | 185 | class myStringIO(StringIO): 186 | """class to simultaneously capture and output""" 187 | 188 | def __init__(self, out=None, buf=""): 189 | self._out = out 190 | StringIO.__init__(self, buf) 191 | 192 | def write(self, s): 193 | self._out.write(s) 194 | StringIO.write(self, s) 195 | 196 | 197 | class capture_output_and_print(object): 198 | """ 199 | Taken from IPython.utils.io and modified to use myStringIO. 200 | context manager for capturing stdout/err 201 | """ 202 | stdout = True 203 | stderr = True 204 | display = True 205 | 206 | def __init__(self, stdout=True, stderr=True, display=True): 207 | self.stdout = stdout 208 | self.stderr = stderr 209 | self.display = display 210 | self.shell = None 211 | 212 | def __enter__(self): 213 | from IPython.core.getipython import get_ipython 214 | from IPython.core.displaypub import CapturingDisplayPublisher 215 | 216 | self.sys_stdout = sys.stdout 217 | self.sys_stderr = sys.stderr 218 | 219 | if self.display: 220 | self.shell = get_ipython() 221 | if self.shell is None: 222 | self.save_display_pub = None 223 | self.display = False 224 | 225 | stdout = stderr = outputs = None 226 | if self.stdout: 227 | #stdout = sys.stdout = StringIO() 228 | stdout = sys.stdout = myStringIO(out=self.sys_stdout) 229 | if self.stderr: 230 | #stderr = sys.stderr = StringIO() 231 | stderr = sys.stderr = myStringIO(out=self.sys_stderr) 232 | if self.display: 233 | self.save_display_pub = self.shell.display_pub 234 | self.shell.display_pub = CapturingDisplayPublisher() 235 | outputs = self.shell.display_pub.outputs 236 | 237 | return CapturedIO(stdout, stderr, outputs) 238 | 239 | def __exit__(self, exc_type, exc_value, traceback): 240 | sys.stdout = self.sys_stdout 241 | sys.stderr = self.sys_stderr 242 | if self.display and self.shell: 243 | self.shell.display_pub = self.save_display_pub 244 | 245 | # ----------------------------------------------------------------------------- 246 | # %%cache Magics 247 | # ------------------------------------------------------------------------------ 248 | 249 | 250 | def cache(cell, path, vars=[], 251 | # HACK: this function implementing the magic's logic is testable 252 | # without IPython, by giving mock functions here instead of IPython 253 | # methods. 254 | ip_user_ns={}, ip_run_cell=None, ip_push=None, ip_clear_output=lambda: None, 255 | force=False, read=False, verbose=True): 256 | 257 | if not path: 258 | raise ValueError("The path needs to be specified as a first argument.") 259 | 260 | path = os.path.abspath(path) 261 | cell_md5 = hashlib.md5(cell.encode()).hexdigest() 262 | 263 | if do_save(path, force=force, read=read): 264 | # Capture the outputs of the cell. 265 | with capture_output_and_print() as io: 266 | try: 267 | ip_run_cell(cell) 268 | except: 269 | # Display input/output. 270 | io() 271 | return 272 | # Create the cache from the namespace. 273 | try: 274 | cached = {var: ip_user_ns[var] for var in vars} 275 | except KeyError: 276 | vars_missing = set(vars) - set(ip_user_ns.keys()) 277 | vars_missing_str = ', '.join(["'{0:s}'".format(_) 278 | for _ in vars_missing]) 279 | raise ValueError(("Variable(s) {0:s} could not be found in the " 280 | "interactive namespace").format(vars_missing_str)) 281 | # Save the outputs in the cache. 282 | cached['_captured_io'] = save_captured_io(io) 283 | cached['_cell_md5'] = cell_md5 284 | # Save the cache in the pickle file. 285 | save_vars(path, cached) 286 | # clear away the temporary output and replace with the saved output (ideal?) 287 | ip_clear_output() 288 | if verbose: 289 | print("[Saved variables '{0:s}' to file '{1:s}'.]".format( 290 | ', '.join(vars), path)) 291 | 292 | # If the cache file exists, and no --force mode, load the requested 293 | # variables from the specified file into the interactive namespace. 294 | else: 295 | # Load the variables from cache in inject them in the namespace. 296 | force_recalc = False 297 | try: 298 | cached = load_vars(path, vars) 299 | except ValueError as e: 300 | if 'The following variables' in str(e): 301 | if read: 302 | raise 303 | force_recalc = True 304 | else: 305 | raise 306 | cached = {} 307 | if not '_cell_md5' in cached or cell_md5 != cached['_cell_md5']: 308 | force_recalc = True 309 | if force_recalc and not read: 310 | return cache(cell, path, vars, ip_user_ns, ip_run_cell, ip_push, ip_clear_output, True, read, verbose) 311 | # Handle the outputs separately. 312 | io = load_captured_io(cached.get('_captured_io', {})) 313 | # Push the remaining variables in the namespace. 314 | ip_push(cached) 315 | if verbose: 316 | print(("[Skipped the cell's code and loaded variables {0:s} " 317 | "from file '{1:s}'.]").format(', '.join(vars), path)) 318 | 319 | # Display the outputs, whether they come from the cell's execution 320 | # or the pickle file. 321 | io() # output is only printed when loading file 322 | 323 | 324 | @magics_class 325 | class CacheMagics(Magics, Configurable): 326 | """Variable caching. 327 | 328 | Provides the %cache magic.""" 329 | 330 | cachedir = Unicode('', config=True) 331 | 332 | def __init__(self, shell=None): 333 | Magics.__init__(self, shell) 334 | Configurable.__init__(self, config=shell.config) 335 | 336 | @magic_arguments.magic_arguments() 337 | @magic_arguments.argument( 338 | 'to', nargs=1, type=str, 339 | help="Path to the file containing the cached variables." 340 | ) 341 | @magic_arguments.argument( 342 | 'vars', nargs='*', type=str, 343 | help="Variables to save." 344 | ) 345 | @magic_arguments.argument( 346 | '-s', '--silent', action='store_true', default=False, 347 | help="Do not display information when loading/saving variables." 348 | ) 349 | @magic_arguments.argument( 350 | '-d', '--cachedir', 351 | help="Cache directory as an absolute or relative path." 352 | ) 353 | @magic_arguments.argument( 354 | '-f', '--force', action='store_true', default=False, 355 | help="Force the cell's execution and save the variables." 356 | ) 357 | @magic_arguments.argument( 358 | '-r', '--read', action='store_true', default=False, 359 | help=("Always read from the file and prevent the cell's execution, " 360 | "raising an error if the file does not exist.") 361 | ) 362 | @cell_magic 363 | def cache(self, line, cell): 364 | """Cache user variables in a file, and skip the cell if the cached 365 | variables exist. 366 | 367 | Usage: 368 | 369 | %%cache myfile.pkl var1 var2 370 | # If myfile.pkl doesn't exist, this cell is executed and 371 | # var1 and var2 are saved in this file. 372 | # Otherwise, the cell is skipped and these variables are 373 | # injected from the file to the interactive namespace. 374 | var1 = ... 375 | var2 = ... 376 | """ 377 | ip = self.shell 378 | args = magic_arguments.parse_argstring(self.cache, line) 379 | code = cell if cell.endswith('\n') else cell+'\n' 380 | vars = clean_vars(args.vars) 381 | path = conditional_eval(args.to[0], ip.user_ns) 382 | cachedir_from_path = os.path.split(path)[0] 383 | # The cachedir can be specified with --cachedir or inferred from the 384 | # path or in ipython_config.py 385 | cachedir = args.cachedir or cachedir_from_path or self.cachedir 386 | # If path is relative, use the user-specified cache cachedir. 387 | if not os.path.isabs(path) and cachedir: 388 | # Try to create the cachedir if it does not already exist. 389 | if not os.path.exists(cachedir): 390 | try: 391 | os.mkdir(cachedir) 392 | print("[Created cachedir '{0:s}'.]".format(cachedir)) 393 | except: 394 | pass 395 | path = os.path.join(cachedir, path) 396 | cache(cell, path, vars=vars, 397 | force=args.force, verbose=not args.silent, read=args.read, 398 | # IPython methods 399 | ip_user_ns=ip.user_ns, 400 | ip_run_cell=ip.run_cell, 401 | ip_push=ip.push, 402 | ip_clear_output=clear_output 403 | ) 404 | 405 | 406 | def load_ipython_extension(ip): 407 | """Load the extension in IPython.""" 408 | ip.register_magics(CacheMagics) 409 | -------------------------------------------------------------------------------- /ipynb_runner.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script for running IPython notebooks. 3 | """ 4 | 5 | from __future__ import print_function 6 | 7 | import argparse 8 | import sys 9 | 10 | from jupyter_client.manager import KernelManager 11 | import nbformat 12 | 13 | 14 | def get_ncells(nb): 15 | """Return number of code cells in a notebook.""" 16 | ncells = 0 17 | for ws in nb.worksheets: 18 | for cell in ws.cells: 19 | if cell.cell_type == "code": 20 | ncells += 1 21 | return ncells 22 | 23 | 24 | # input arguments parsing 25 | parser = argparse.ArgumentParser(description="Run an IPython Notebook") 26 | parser.add_argument("notebook", 27 | type=str, 28 | help='notebook to run') 29 | parser.add_argument("-v", "--verbose", help="increase output verbosity", 30 | action="store_true") 31 | parser.add_argument("-b", "--break-at-error", help="stop at error", 32 | action="store_true") 33 | parser.add_argument("-s", "--summary", help="print summary", 34 | action="store_true") 35 | 36 | args = parser.parse_args() 37 | 38 | # add .ipynb extension if not given 39 | notebook = '{name}{ext}'.format(name=args.notebook, ext='' 40 | if '.' in args.notebook else '.ipynb') 41 | 42 | if args.verbose: 43 | print('Checking: {}'.format(notebook)) 44 | 45 | nb = nbformat.read(open(notebook), as_version=3) 46 | 47 | # starting up kernel 48 | km = KernelManager() 49 | km.start_kernel() 50 | kc = km.client() 51 | kc.start_channels() 52 | kc.wait_for_ready() 53 | shell = kc.shell_channel 54 | 55 | ncells = get_ncells(nb) 56 | 57 | nerrors = 0 # accumulate number of errors 58 | nsucc = 0 59 | 60 | # loop over cells 61 | icell = 1 62 | for ws in nb.worksheets: 63 | for cell in ws.cells: 64 | if cell.cell_type == 'code': 65 | if args.verbose: 66 | print("Cell:%i/%i> " % (icell, ncells), end=" ") 67 | icell += 1 68 | kc.execute(cell.input) 69 | msg = kc.get_shell_msg() 70 | status = msg['content']['status'] 71 | if args.verbose: 72 | print(status) 73 | if status == 'ok': 74 | nsucc += 1 75 | continue 76 | nerrors += 1 77 | if args.verbose: 78 | print("=" * 80) 79 | print(msg['content']['ename'], ":", msg['content']['evalue']) 80 | print("{0:-^80}".format("")) 81 | print(cell.input) 82 | print("{0:-^80}".format("")) 83 | for m in msg['content']['traceback']: 84 | print(m) 85 | print("=" * 80) 86 | if args.break_at_error: 87 | break 88 | 89 | if args.summary: 90 | print("{0:#^80}".format(" Summary: %s " % args.notebook)) 91 | print("Num Errors : ", nerrors) 92 | print("Num Successes: ", nsucc) 93 | print("Num Cells : ", ncells) 94 | 95 | 96 | # kernel cleanup 97 | kc.stop_channels() 98 | km.shutdown_kernel(now=True) 99 | sys.exit(-1 if nerrors > 0 else 0) 100 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ipython < 8.0.0 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from setuptools import setup 3 | 4 | 5 | def read(fname): 6 | """Utility function to read the README file. 7 | 8 | Used for long_description. It's nice, because now (1) we have a top level 9 | README file and (2) it's easier to type in the README file than to put a raw 10 | string in below.""" 11 | return open(os.path.join(os.path.dirname(__file__), fname)).read() 12 | 13 | 14 | setup( 15 | name="ipycache", 16 | version="0.1.5dev", 17 | author="Cyrille Rossant", 18 | author_email="rossant@github", 19 | description=("Defines a %%cache cell magic in the IPython notebook to " 20 | "cache results of long-lasting computations in a persistent " 21 | "pickle file."), 22 | license="BSD-3-Clause", 23 | keywords="ipython notebook cache", 24 | url="https://github.com/rossant/ipycache", 25 | py_modules=['ipycache'], 26 | long_description=read('README.md'), 27 | long_description_content_type='text/markdown', 28 | classifiers=[ 29 | "Development Status :: 3 - Alpha", 30 | "Topic :: Utilities", 31 | "Framework :: IPython", 32 | "License :: OSI Approved :: BSD License", 33 | ], 34 | ) 35 | -------------------------------------------------------------------------------- /test_ipycache.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Tests for ipycache. 3 | """ 4 | 5 | import hashlib 6 | import os 7 | import pickle 8 | import sys 9 | import unittest 10 | 11 | from ipycache import (save_vars, load_vars, clean_var, clean_vars, do_save, 12 | cache, exec_, conditional_eval) 13 | 14 | PY2 = sys.version_info[0] == 2 15 | PY3 = sys.version_info[0] == 3 16 | 17 | if PY2: 18 | from cStringIO import StringIO 19 | else: 20 | from io import StringIO 21 | 22 | 23 | def removeFile(path): 24 | """Remove a file which may or may not exist, without throwing exceptions.""" 25 | # In Python 3, we can write: 26 | # 27 | # with contextlib.suppress(FileNotFoundError): 28 | # os.remove(path) 29 | # 30 | # but to be compatible with Python 2, we explicitly check + remove. 31 | if os.path.exists(path): 32 | os.remove(path) 33 | 34 | 35 | class FunctionTests(unittest.TestCase): 36 | 37 | def test_conditional_eval(self): 38 | test_var = 'abc' 39 | self.assertEqual(conditional_eval('$test_var', locals()), 'abc') 40 | x, fun = 10, lambda x: x 41 | test_eval = 'abc_{"10" if x==10 else "not_10"}_{fun(10)}' 42 | expect = 'abc_10_10' 43 | self.assertEqual(conditional_eval(test_eval, locals()), expect) 44 | 45 | def test_clean_var(self): 46 | self.assertEqual(clean_var('abc'), 'abc') 47 | self.assertEqual(clean_var('abc '), 'abc') 48 | self.assertEqual(clean_var('abc,'), 'abc') 49 | self.assertEqual(clean_var(',abc'), 'abc') 50 | 51 | def test_clean_vars(self): 52 | self.assertEqual(clean_vars(['abc', 'abc,']), ['abc'] * 2) 53 | 54 | def test_do_save(self): 55 | path = 'myvars.pkl' 56 | 57 | # File exists. 58 | open(path, 'wb').close() 59 | self.assertRaises(ValueError, do_save, path, force=True, read=True) 60 | self.assertTrue(do_save(path, force=True, read=False)) 61 | self.assertFalse(do_save(path, force=False, read=False)) 62 | self.assertFalse(do_save(path, force=False, read=True)) 63 | removeFile(path) 64 | 65 | # File does not exist. 66 | self.assertRaises(ValueError, do_save, path, force=True, read=True) 67 | self.assertTrue(do_save(path, force=True, read=False)) 68 | self.assertTrue(do_save(path, force=False, read=False)) 69 | self.assertFalse(do_save(path, force=False, read=True)) 70 | 71 | def test_load_fail(self): 72 | path = 'myvars.pkl' 73 | self.assertRaises(IOError, load_vars, path, ['a', 'b']) 74 | 75 | def test_save_load(self): 76 | path = 'myvars.pkl' 77 | vars = {'a': 1, 'b': '2'} 78 | save_vars(path, vars) 79 | vars2 = load_vars(path, list(vars.keys())) 80 | self.assertEqual(vars, vars2) 81 | removeFile(path) 82 | 83 | 84 | class CacheMagicTests(unittest.TestCase): 85 | def test_cache_1(self): 86 | path = 'myvars.pkl' 87 | cell = """a = 1""" 88 | 89 | user_ns = {} 90 | 91 | def ip_run_cell(cell): 92 | exec_(cell, {}, user_ns) 93 | 94 | def ip_push(vars): 95 | user_ns.update(vars) 96 | 97 | cache(cell, path, vars=['a'], force=False, read=False, 98 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 99 | self.assertEqual(user_ns['a'], 1) 100 | 101 | # We modify the variable in the namespace, 102 | user_ns['a'] = 2 103 | # and execute the cell again. The value should be loaded from the pickle 104 | # file. Note how we did not change cell contents 105 | cache("""a = 1""", path, vars=['a'], force=False, read=False, 106 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 107 | self.assertEqual(user_ns['a'], 1) 108 | 109 | # changing the cell will trigger reload 110 | # file. Note how we did not change cell contents 111 | cache("""a = 2""", path, vars=['a'], force=False, read=False, 112 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 113 | self.assertEqual(user_ns['a'], 2) 114 | 115 | # store 1 again 116 | user_ns['a'] = 1 117 | cache("""a = 1""", path, vars=['a'], force=False, read=False, 118 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 119 | # hack the md5 so code change does not retrigger 120 | with open(path, 'rb') as op: 121 | data = pickle.load(op) 122 | data['_cell_md5'] = hashlib.md5("""a = 2""".encode()).hexdigest() 123 | with open(path, 'wb') as op: 124 | pickle.dump(data, op) 125 | # ensure we don't rerun 126 | user_ns['a'] = 2 127 | # and execute the cell again. The value should be loaded from the pickle 128 | # file. Note how we did not change cell contents 129 | cache("""a = 1""", path, vars=['a'], force=False, read=False, 130 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 131 | self.assertEqual(user_ns['a'], 1) 132 | 133 | # Now, we force the cell's execution. 134 | cache("""a = 2""", path, vars=['a'], force=True, read=False, 135 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 136 | self.assertEqual(user_ns['a'], 2) 137 | 138 | # Now, we prevent the cell's execution. 139 | user_ns['a'] = 0 140 | cache("""a = 3""", path, vars=['a'], force=False, read=True, 141 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 142 | self.assertEqual(user_ns['a'], 2) 143 | 144 | removeFile(path) 145 | 146 | def test_cache_exception(self): 147 | """Check that, if an exception is raised during the cell's execution, 148 | the pickle file is not written.""" 149 | path = 'myvars.pkl' 150 | cell = """a = 1;b = 1/0""" 151 | 152 | user_ns = {} 153 | 154 | def ip_run_cell(cell): 155 | exec_(cell, {}, user_ns) 156 | 157 | def ip_push(vars): 158 | user_ns.update(vars) 159 | 160 | cache(cell, path, vars=['a'], force=False, read=False, 161 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 162 | self.assertEqual(user_ns['a'], 1) 163 | 164 | self.assertFalse(os.path.exists(path)) 165 | removeFile(path) 166 | 167 | def test_cache_outputs(self): 168 | """Test the capture of stdout.""" 169 | path = 'myvars.pkl' 170 | cell = """a = 1;print(a+1)""" 171 | 172 | user_ns = {} 173 | 174 | def ip_run_cell(cell): 175 | exec_(cell, {}, user_ns) 176 | 177 | def ip_push(vars): 178 | user_ns.update(vars) 179 | 180 | cache(cell, path, vars=['a'], verbose=False, 181 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 182 | self.assertEqual(user_ns['a'], 1) 183 | 184 | # Capture stdout. 185 | old_stdout = sys.stdout 186 | sys.stdout = mystdout = StringIO() 187 | 188 | user_ns = {} 189 | cache(cell, path, vars=['a'], verbose=False, 190 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 191 | self.assertEqual(user_ns['a'], 1) 192 | 193 | sys.stdout = old_stdout 194 | 195 | # Check that stdout contains the print statement of the cached cell. 196 | self.assertEqual(mystdout.getvalue(), '2\n') 197 | 198 | removeFile(path) 199 | 200 | def test_cache_fail_1(self): 201 | """Fails when saving nonexistent variables.""" 202 | path = 'myvars.pkl' 203 | cell = """a = 1""" 204 | 205 | user_ns = {} 206 | 207 | def ip_run_cell(cell): 208 | exec_(cell, {}, user_ns) 209 | 210 | def ip_push(vars): 211 | user_ns.update(vars) 212 | 213 | self.assertRaises(ValueError, cache, cell, path, vars=['a', 'b'], 214 | ip_user_ns=user_ns, ip_run_cell=ip_run_cell, ip_push=ip_push) 215 | 216 | removeFile(path) 217 | -------------------------------------------------------------------------------- /test_requirements.txt: -------------------------------------------------------------------------------- 1 | # Note: this file can only be used in a Python 3 environment; for Python 2.7, 2 | # use test_requirements_python27.txt instead. 3 | 4 | numpy 5 | matplotlib 6 | nbformat ~= 5.1.3 7 | jupyter-client ~= 7.1.1 8 | ipykernel ~= 6.7.0 9 | -------------------------------------------------------------------------------- /test_requirements_python27.txt: -------------------------------------------------------------------------------- 1 | # Note: this file can only be used in a Python 2.7 environment; for Python 3, 2 | # use test_requirements.txt instead. 3 | 4 | numpy 5 | matplotlib 6 | nbformat ~= 4.4.0 7 | jupyter-client ~= 5.3.5 8 | ipykernel ~= 4.10.1 9 | --------------------------------------------------------------------------------