├── .gitignore ├── LICENSE ├── README.md ├── demo.ipynb ├── demo_inplace.gif ├── demo_newcell.gif ├── ipyfuturize.py ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | .ipynb_checkpoints 3 | 4 | # C extensions 5 | *.so 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | eggs 13 | parts 14 | bin 15 | var 16 | sdist 17 | develop-eggs 18 | .installed.cfg 19 | lib 20 | lib64 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | htmlcov 30 | 31 | # Translations 32 | *.mo 33 | 34 | # Mr Developer 35 | .mr.developer.cfg 36 | .project 37 | .pydevproject 38 | 39 | # Complexity 40 | output/*.html 41 | output/*/index.html 42 | 43 | # Sphinx 44 | docs/_build 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Douglas La Rocca 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ipyfuturize 2 | 3 | A cell magic for [futurize](http://python-future.org/futurize.html) (based on [2to3](https://docs.python.org/2/library/2to3.html)) 4 | 5 | ## usage & demo 6 | 7 | Ctrl-Enter overwrites the active cell (Ctrl-z will undo) 8 | 9 | ![ipyfuturize](demo_inplace.gif) 10 | 11 | Ctrl-Shift-Enter writes to a new cell 12 | 13 | ![ipyfuturize](demo_newcell.gif) 14 | 15 | Line arguments are passed directly to the `futurize` script. 16 | 17 | Executing `%%futurize?` will show the same help info as `!futurize --help`. 18 | 19 | If you're using a virtual environment it will attempt to find the `futurize` script at `$VIRTUAL_ENV/bin/futurize`, otherwise it assumes the one you want to use is in `$PATH`. 20 | 21 | No windows support. 22 | 23 | ## install 24 | 25 | ``` 26 | %install_ext https://raw.github.com/douglas-larocca/ipyfuturize/master/ipyfuturize.py 27 | ``` 28 | 29 | then 30 | 31 | ``` 32 | %load_ext ipyfuturize 33 | ``` 34 | 35 | and use with 36 | 37 | ``` 38 | %%futurize 39 | ``` 40 | 41 | Also see the [demo notebook](demo.ipynb) 42 | -------------------------------------------------------------------------------- /demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# ipyfuturize\n", 8 | "\n", 9 | "A cell magic for [futurize](http://python-future.org/futurize.html) (based on [2to3](https://docs.python.org/2/library/2to3.html))" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "collapsed": true 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "%install_ext https://raw.github.com/douglas-larocca/ipyfuturize/master/ipyfuturize.py" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 1, 26 | "metadata": { 27 | "collapsed": true 28 | }, 29 | "outputs": [], 30 | "source": [ 31 | "%load_ext ipyfuturize" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 6, 37 | "metadata": { 38 | "collapsed": false 39 | }, 40 | "outputs": [ 41 | { 42 | "name": "stdout", 43 | "output_type": "stream", 44 | "text": [ 45 | "Usage: futurize [options] file|dir ...\r\n", 46 | "\r\n", 47 | "Options:\r\n", 48 | " -h, --help show this help message and exit\r\n", 49 | " -V, --version Report the version number of futurize\r\n", 50 | " -a, --all-imports Add all __future__ and future imports to each module\r\n", 51 | " -1, --stage1 Modernize Python 2 code only; no compatibility with Python 3 (or dependency on\r\n", 52 | " ``future``)\r\n", 53 | " -2, --stage2 Take modernized (stage1) code and add a dependency on ``future`` to provide Py3\r\n", 54 | " compatibility.\r\n", 55 | " -0, --both-stages Apply both stages 1 and 2\r\n", 56 | " -u, --unicode-literals\r\n", 57 | " Add ``from __future__ import unicode_literals`` to implicitly convert all\r\n", 58 | " unadorned string literals '' into unicode strings\r\n", 59 | " -f FIX, --fix=FIX Each FIX specifies a transformation; default: all. Either use '-f division -f\r\n", 60 | " metaclass' etc. or use the fully-qualified module name: '-f\r\n", 61 | " lib2to3.fixes.fix_types -f libfuturize.fixes.fix_unicode_keep_u'\r\n", 62 | " -j PROCESSES, --processes=PROCESSES\r\n", 63 | " Run 2to3 concurrently\r\n", 64 | " -x NOFIX, --nofix=NOFIX\r\n", 65 | " Prevent a fixer from being run.\r\n", 66 | " -l, --list-fixes List available transformations\r\n", 67 | " -p, --print-function Modify the grammar so that print() is a function\r\n", 68 | " -v, --verbose More verbose logging\r\n", 69 | " --no-diffs Don't show diffs of the refactoring\r\n", 70 | " -w, --write Write back modified files\r\n", 71 | " -n, --nobackups Don't write backups for modified files.\r\n", 72 | " -o OUTPUT_DIR, --output-dir=OUTPUT_DIR\r\n", 73 | " Put output files in this directory instead of overwriting the input files.\r\n", 74 | " Requires -n. For Python >= 2.7 only.\r\n", 75 | " -W, --write-unchanged-files\r\n", 76 | " Also write files even if no changes were required (useful with --output-dir);\r\n", 77 | " implies -w.\r\n", 78 | " --add-suffix=ADD_SUFFIX\r\n", 79 | " Append this string to all output filenames. Requires -n if non-empty. For Python\r\n", 80 | " >= 2.7 only.ex: --add-suffix='3' will generate .py3 files.\r\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "%%futurize?" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "Example from [http://python-future.org/quickstart.html#to-convert-existing-python-2-code](http://python-future.org/quickstart.html#to-convert-existing-python-2-code)" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 2, 98 | "metadata": { 99 | "collapsed": false 100 | }, 101 | "outputs": [ 102 | { 103 | "data": { 104 | "application/javascript": [ 105 | "\n", 106 | " var cell = IPython.notebook.get_selected_cell();\n", 107 | " var content = \"from __future__ import print_function\\nfrom future import standard_library\\nstandard_library.install_aliases()\\nfrom builtins import next\\nfrom builtins import object\\nimport configparser # Py2 module name\\n\\nclass Upper(object):\\n def __init__(self, iterable):\\n self._iter = iter(iterable)\\n def __next__(self): # Py2-style iterator interface\\n return next(self._iter).upper()\\n def __iter__(self):\\n return self\\n\\nitr = Upper('hello')\\nprint(next(itr), end=' ')\\nfor letter in itr:\\n print(letter, end=' ') # Py2-style print statement\";\n", 108 | " \n", 109 | " cell.code_mirror.setValue(content);\n", 110 | " " 111 | ], 112 | "text/plain": [ 113 | "" 114 | ] 115 | }, 116 | "metadata": {}, 117 | "output_type": "display_data" 118 | } 119 | ], 120 | "source": [ 121 | "%%futurize\n", 122 | "import ConfigParser # Py2 module name\n", 123 | "\n", 124 | "class Upper(object):\n", 125 | " def __init__(self, iterable):\n", 126 | " self._iter = iter(iterable)\n", 127 | " def next(self): # Py2-style iterator interface\n", 128 | " return next(self._iter).upper()\n", 129 | " def __iter__(self):\n", 130 | " return self\n", 131 | "\n", 132 | "itr = Upper('hello')\n", 133 | "print next(itr),\n", 134 | "for letter in itr:\n", 135 | " print letter, # Py2-style print statement" 136 | ] 137 | } 138 | ], 139 | "metadata": { 140 | "kernelspec": { 141 | "display_name": "Python 3", 142 | "language": "python", 143 | "name": "python3" 144 | }, 145 | "language_info": { 146 | "codemirror_mode": { 147 | "name": "ipython", 148 | "version": 3 149 | }, 150 | "file_extension": ".py", 151 | "mimetype": "text/x-python", 152 | "name": "python", 153 | "nbconvert_exporter": "python", 154 | "pygments_lexer": "ipython3", 155 | "version": "3.6.0a0" 156 | } 157 | }, 158 | "nbformat": 4, 159 | "nbformat_minor": 0 160 | } 161 | -------------------------------------------------------------------------------- /demo_inplace.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglas-larocca/ipyfuturize/b0ee523cfa973ac7022653e659a6794be80a930e/demo_inplace.gif -------------------------------------------------------------------------------- /demo_newcell.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglas-larocca/ipyfuturize/b0ee523cfa973ac7022653e659a6794be80a930e/demo_newcell.gif -------------------------------------------------------------------------------- /ipyfuturize.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import shlex 4 | from tempfile import NamedTemporaryFile 5 | from datetime import datetime 6 | from IPython.core.display import Javascript 7 | from IPython.core.magic import Magics, magics_class, cell_magic, line_magic 8 | from IPython.core.magics import DisplayMagics 9 | from subprocess import Popen, PIPE 10 | 11 | 12 | class CellInject(object): 13 | def __init__(self, *args, **kwargs): 14 | pass 15 | def __call__(self, cell, extrajs=''): 16 | if not isinstance(cell, str): 17 | cell = json.dumps(cell) 18 | if not cell.startswith('"'): 19 | cell = json.dumps(cell) 20 | cell = ''' 21 | var cell = IPython.notebook.get_selected_cell(); 22 | var content = {0}; 23 | {extrajs} 24 | cell.code_mirror.setValue(content); 25 | '''.format(cell, extrajs=extrajs) 26 | DisplayMagics().javascript('', cell) 27 | 28 | 29 | @magics_class 30 | class IPythonFuturize(Magics): 31 | 32 | def __init__(self, *args, **kwargs): 33 | super().__init__(*args, **kwargs) 34 | 35 | @line_magic('futurize') 36 | def ipython_futurize(self, line): 37 | raise NotImplementedError() 38 | 39 | @cell_magic('futurize') 40 | def ipython_futurize(self, line, cell): 41 | """ 42 | Usage: futurize [options] file|dir ... 43 | 44 | Options: 45 | -h, --help show this help message and exit 46 | -V, --version Report the version number of futurize 47 | -a, --all-imports Add all __future__ and future imports to 48 | each module 49 | -1, --stage1 Modernize Python 2 code only; no compatibility 50 | with Python 3 (or dependency on ``future``) 51 | -2, --stage2 Take modernized (stage1) code and add a dependency 52 | on ``future`` to provide Py3 compatibility. 53 | -0, --both-stages Apply both stages 1 and 2 54 | -u, --unicode-literals 55 | Add ``from __future__ import unicode_literals`` 56 | to implicitly convert all unadorned string literals 57 | '' into unicode strings 58 | -f FIX, --fix=FIX Each FIX specifies a transformation; default: all. 59 | Either use '-f division -f metaclass' etc. or use the 60 | fully-qualified module name: '-f lib2to3.fixes.fix_types 61 | -f libfuturize.fixes.fix_unicode_keep_u' 62 | -j PROCESSES, --processes=PROCESSES 63 | Run 2to3 concurrently 64 | -x NOFIX, --nofix=NOFIX 65 | Prevent a fixer from being run. 66 | -l, --list-fixes List available transformations 67 | -p, --print-function Modify the grammar so that print() is a function 68 | -v, --verbose More verbose logging 69 | --no-diffs Don't show diffs of the refactoring 70 | -w, --write Write back modified files 71 | -n, --nobackups Don't write backups for modified files. 72 | -o OUTPUT_DIR, --output-dir=OUTPUT_DIR 73 | Put output files in this directory instead of overwriting the 74 | input files. Requires -n. For Python >= 2.7 only. 75 | -W, --write-unchanged-files 76 | Also write files even if no changes were required 77 | (useful with --output-dir); implies -w. 78 | --add-suffix=ADD_SUFFIX 79 | Append this string to all output filenames. Requires -n 80 | if non-empty. For Python >= 2.7 only.ex: --add-suffix='3' 81 | will generate .py3 files. 82 | """ 83 | 84 | try: 85 | futurize = os.path.join(os.environ['VIRTUAL_ENV'], 'bin/futurize') 86 | except KeyError: 87 | futurize = 'futurize' 88 | 89 | with NamedTemporaryFile(delete=False, suffix='.py') as f: 90 | f.write(cell.encode('utf-8')) 91 | filename = f.name 92 | 93 | args = shlex.split(' '.join((futurize, '-w', line, filename))) 94 | 95 | p = Popen(args, stdout=PIPE, stdin=PIPE, stderr=PIPE) 96 | out, err = p.communicate() 97 | 98 | with open(filename, 'r') as f: 99 | rf = f.read() 100 | 101 | inj = CellInject() 102 | inj(rf) 103 | 104 | def load_ipython_extension(ip): 105 | """Load the extension in IPython.""" 106 | ip.register_magics(IPythonFuturize) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ipython>=3.0.0-b1 2 | future>=0.14.3 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | try: 6 | from setuptools import setup 7 | except ImportError: 8 | from distutils.core import setup 9 | 10 | 11 | with open('README.md') as readme_file: 12 | readme = readme_file.read() 13 | 14 | requirements = [ 15 | 'ipython>=3.0.0-b1', 16 | 'future>=0.14.3', 17 | ] 18 | 19 | setup( 20 | name='ipyfuturize', 21 | version='0.0.1', 22 | description="%%futurize magic for ipython", 23 | long_description=readme, 24 | author="Douglas La Rocca", 25 | author_email='doug@larocca.io', 26 | url='https://github.com/douglas-larocca/ipyfuturize', 27 | install_requires=requirements, 28 | license="MIT", 29 | keywords='futurize 2to3 ipython magic', 30 | classifiers=[ 31 | 'Development Status :: 2 - Pre-Alpha', 32 | 'Intended Audience :: Developers', 33 | 'Natural Language :: English', 34 | "Programming Language :: Python :: 2", 35 | 'Programming Language :: Python :: 2.6', 36 | 'Programming Language :: Python :: 2.7', 37 | 'Programming Language :: Python :: 3', 38 | 'Programming Language :: Python :: 3.3', 39 | 'Programming Language :: Python :: 3.4', 40 | 'Framework :: IPython', 41 | ], 42 | py_modules=['ipyfuturize'], 43 | ) 44 | --------------------------------------------------------------------------------