├── .gitignore ├── .vscode └── launch.json ├── LICENSE ├── README.md ├── import_wrapper.py └── install.py /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | *.pyc 3 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Python", 6 | "type": "python", 7 | "pythonPath":"py", 8 | "request": "launch", 9 | "stopOnEntry": true, 10 | "externalConsole":false, 11 | "program": "${file}", 12 | "debugOptions": [ 13 | "WaitOnAbnormalExit", 14 | "WaitOnNormalExit", 15 | "RedirectOutput" 16 | ] 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 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 | # ipython-auto-import 2 | 3 | How many times have you quickly wanted to test something, only to do this? 4 | 5 | ``` 6 | In [1]: df = pandas.read_clipboard() 7 | --------------------------------------------------------------------------- 8 | NameError Traceback (most recent call last) 9 | in () 10 | ----> 1 df = pandas.read_clipboard() 11 | 12 | NameError: name 'pandas' is not defined 13 | 14 | In [2]: import pandas # *sigh* 15 | 16 | In [3]: df = pandas.read_clipboard() 17 | ``` 18 | 19 | Inspired by [this SO question](http://stackoverflow.com/questions/36112275/make-ipython-import-what-i-mean/36116171#36116171), you'll never need to import a module again in IPython! 20 | 21 | ``` 22 | In [1]: pandas.read_clipboard() 23 | --------------------------------------------------------------------------- 24 | NameError Traceback (most recent call last) 25 | in () 26 | ----> 1 pandas.read_clipboard() 27 | 28 | NameError: name 'pandas' is not defined 29 | AutoImport: Imported referenced module "pandas", will retry 30 | --------------------------------------------------------------------------- 31 | Out[1]: 32 | First,Last 33 | 0 Foo,Bar 34 | 1 John,Appleseed 35 | ``` 36 | 37 | The first time you reference a module, it imports it auto-magically! Don't have the module installed? You can `pip install` it right from IPython. 38 | 39 | ## Installation 40 | 41 | **NOTE**: It's recommended that you install `colorama` for best results: `pip install colorama` 42 | 43 | ### Easy way 44 | Clone the repo and run `install.py`. 45 | 46 | ### Hard way 47 | Add `import_wrapper.py` to `~/.ipython/extensions`, then call `%load_ext import_wrapper` either at the IPython prompt, or add 48 | ``` 49 | c.InteractiveShellApp.exec_lines.append("%load_ext import_wrapper") 50 | ``` 51 | at the end of `~/.ipython/profile_default/ipython_config.py`. -------------------------------------------------------------------------------- /import_wrapper.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | import re 3 | import sys 4 | 5 | try: 6 | import colorama 7 | colorama.init() 8 | pre = (colorama.Fore.CYAN + colorama.Style.BRIGHT + 9 | "AutoImport: " + colorama.Style.NORMAL + 10 | colorama.Fore.WHITE) 11 | except: 12 | pre = "AutoImport: " 13 | 14 | common_others = {"pd": "pandas", "np": "numpy", "sp": "scipy"} 15 | 16 | class pipUnsuccessfulException(Exception): 17 | pass 18 | 19 | 20 | 21 | def custom_exc(ipython, shell, etype, evalue, tb, tb_offset=None): 22 | shell.showtraceback((etype, evalue, tb), tb_offset) 23 | 24 | while tb.tb_next: 25 | tb = tb.tb_next 26 | if not re.match("\\A\\Z", tb.tb_frame.f_code.co_filename): 27 | # Innermost frame is not the IPython interactive environment. 28 | return 29 | 30 | try: 31 | # Get the name of the module you tried to import 32 | results = re.match("\\Aname '(.*)' is not defined\\Z", str(evalue)) 33 | if not results: 34 | return 35 | name = results.group(1) 36 | custom_exc.last_name = name 37 | 38 | try: 39 | __import__(name) 40 | except: 41 | if common_others.get(name): 42 | new_name = common_others.get(name) 43 | try: 44 | __import__(new_name) 45 | r = ipython.ask_yes_no( 46 | pre + 47 | "{0} isn't a module, but {1} is. " 48 | "Import {1} as {0}? (Y/n)".format(name, new_name)) 49 | if r: 50 | name = "{} as {}".format(new_name, name) 51 | else: 52 | return 53 | except Exception as e: 54 | print(pre + 55 | "{} isn't a module and nor is {}" 56 | .format(name, new_name)) 57 | print(e) 58 | return 59 | else: 60 | print(pre + "{} isn't a module".format(name)) 61 | try: 62 | last_name = custom_exc.last_name 63 | if ipython.ask_yes_no(pre + "Attempt to pip-install {}? (Y/n)" 64 | .format(last_name)): 65 | if __import__("pip").main(["install", last_name]) != 0: 66 | raise pipUnsuccessfulException 67 | else: 68 | return 69 | print(pre + "Installation completed successfully, importing...") 70 | try: 71 | res = ipython.run_cell("import {}".format(last_name)) 72 | print(pre + "Imported referenced module {}".format(last_name)) 73 | except: 74 | print(pre + "{} isn't a module".format(last_name)) 75 | except pipUnsuccessfulException: 76 | print(pre + "Installation with pip failed") 77 | 78 | except AttributeError: 79 | print(pre + "No module to install") 80 | 81 | except ImportError: 82 | print(pre + "pip not found") 83 | return 84 | 85 | # Import the module 86 | ipython.run_code("import {}".format(name)) 87 | print(pre + "Imported referenced module {!r}, will retry".format(name)) 88 | print("".join("-" for _ in range(75))) 89 | except Exception as e: 90 | print(pre + ("Attempted to import {!r}" 91 | "but an exception occured".format(name))) 92 | 93 | try: 94 | # Run the failed line again 95 | res = ipython.run_cell( 96 | list(ipython.history_manager.get_range())[-1][-1]) 97 | except Exception as e: 98 | print(pre + "Another exception occured while retrying") 99 | shell.showtraceback((type(e), e, None), None) 100 | 101 | 102 | 103 | def load_ipython_extension(ipython): 104 | # Bind the function we created to IPython's exception handler 105 | ipython.set_custom_exc((NameError,), partial(custom_exc, ipython)) 106 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | import os 3 | 4 | u = os.path.expanduser("~") 5 | assert u != "~" 6 | 7 | extensions_path = os.path.join(u, ".ipython", "extensions", 8 | "import_wrapper.py") 9 | config_path = os.path.join(u, ".ipython", "profile_default", 10 | "ipython_config.py") 11 | 12 | shutil.copyfile("import_wrapper.py", extensions_path) 13 | 14 | with open(config_path, "a") as f: 15 | f.write("\nc.InteractiveShellApp.exec_lines.append(\"%load_ext import_wra" 16 | "pper\")") 17 | 18 | print("Installation complete.") 19 | try: 20 | import colorama 21 | except ImportError: 22 | print("NOTE: Install 'colorama' for best results: 'pip install colorama'") --------------------------------------------------------------------------------