1"""Utility and helper methods for tmuxp. 2 3tmuxp.shell 4~~~~~~~~~~~ 5 6""" 7import logging 8import os 9 10logger = logging.getLogger(__name__) 11 12 13def has_ipython(): 14 try: 15 from IPython import start_ipython # NOQA F841 16 except ImportError: 17 try: 18 from IPython.Shell import IPShell # NOQA F841 19 except ImportError: 20 return False 21 22 return True 23 24 25def has_ptpython(): 26 try: 27 from ptpython.repl import embed, run_config # NOQA F841 28 except ImportError: 29 try: 30 from prompt_toolkit.contrib.repl import embed, run_config # NOQA F841 31 except ImportError: 32 return False 33 34 return True 35 36 37def has_ptipython(): 38 try: 39 from ptpython.ipython import embed # NOQA F841 40 from ptpython.repl import run_config # NOQA F841 41 except ImportError: 42 try: 43 from prompt_toolkit.contrib.ipython import embed # NOQA F841 44 from prompt_toolkit.contrib.repl import run_config # NOQA F841 45 except ImportError: 46 return False 47 48 return True 49 50 51def has_bpython(): 52 try: 53 from bpython import embed # NOQA F841 54 except ImportError: 55 return False 56 return True 57 58 59def detect_best_shell(): 60 if has_ptipython(): 61 return 'ptipython' 62 elif has_ptpython(): 63 return 'ptpython' 64 elif has_ipython(): 65 return 'ipython' 66 elif has_bpython(): 67 return 'bpython' 68 return 'code' 69 70 71def get_bpython(options, extra_args=None): 72 if extra_args is None: 73 extra_args = {} 74 75 from bpython import embed # NOQA F841 76 77 def launch_bpython(): 78 imported_objects = get_launch_args(**options) 79 kwargs = {} 80 if extra_args: 81 kwargs['args'] = extra_args 82 embed(imported_objects, **kwargs) 83 84 return launch_bpython 85 86 87def get_ipython_arguments(): 88 ipython_args = 'IPYTHON_ARGUMENTS' 89 return os.environ.get(ipython_args, '').split() 90 91 92def get_ipython(options, **extra_args): 93 try: 94 from IPython import start_ipython 95 96 def launch_ipython(): 97 imported_objects = get_launch_args(**options) 98 ipython_arguments = extra_args or get_ipython_arguments() 99 start_ipython(argv=ipython_arguments, user_ns=imported_objects) 100 101 return launch_ipython 102 except ImportError: 103 # IPython < 0.11 104 # Explicitly pass an empty list as arguments, because otherwise 105 # IPython would use sys.argv from this script. 106 # Notebook not supported for IPython < 0.11. 107 from IPython.Shell import IPShell 108 109 def launch_ipython(): 110 imported_objects = get_launch_args(**options) 111 shell = IPShell(argv=[], user_ns=imported_objects) 112 shell.mainloop() 113 114 return launch_ipython 115 116 117def get_ptpython(options, vi_mode=False): 118 try: 119 from ptpython.repl import embed, run_config 120 except ImportError: 121 from prompt_toolkit.contrib.repl import embed, run_config 122 123 def launch_ptpython(): 124 imported_objects = get_launch_args(**options) 125 history_filename = os.path.expanduser('~/.ptpython_history') 126 embed( 127 globals=imported_objects, 128 history_filename=history_filename, 129 vi_mode=vi_mode, 130 configure=run_config, 131 ) 132 133 return launch_ptpython 134 135 136def get_ptipython(options, vi_mode=False): 137 """Based on django-extensions 138 139 Run renamed to launch, get_imported_objects renamed to get_launch_args 140 """ 141 try: 142 from ptpython.ipython import embed 143 from ptpython.repl import run_config 144 except ImportError: 145 # prompt_toolkit < v0.27 146 from prompt_toolkit.contrib.ipython import embed 147 from prompt_toolkit.contrib.repl import run_config 148 149 def launch_ptipython(): 150 imported_objects = get_launch_args(**options) 151 history_filename = os.path.expanduser('~/.ptpython_history') 152 embed( 153 user_ns=imported_objects, 154 history_filename=history_filename, 155 vi_mode=vi_mode, 156 configure=run_config, 157 ) 158 159 return launch_ptipython 160 161 162def get_launch_args(**kwargs): 163 import libtmux 164 165 return { 166 'libtmux': libtmux, 167 'Server': libtmux.Server, 168 'Session': libtmux.Session, 169 'Window': libtmux.Window, 170 'Pane': libtmux.Pane, 171 'server': kwargs.get('server'), 172 'session': kwargs.get('session'), 173 'window': kwargs.get('window'), 174 'pane': kwargs.get('pane'), 175 } 176 177 178def get_code(use_pythonrc, imported_objects): 179 import code 180 181 try: 182 # Try activating rlcompleter, because it's handy. 183 import readline 184 except ImportError: 185 pass 186 else: 187 # We don't have to wrap the following import in a 'try', because 188 # we already know 'readline' was imported successfully. 189 import rlcompleter 190 191 readline.set_completer(rlcompleter.Completer(imported_objects).complete) 192 # Enable tab completion on systems using libedit (e.g. macOS). 193 # These lines are copied from Lib/site.py on Python 3.4. 194 readline_doc = getattr(readline, '__doc__', '') 195 if readline_doc is not None and 'libedit' in readline_doc: 196 readline.parse_and_bind("bind ^I rl_complete") 197 else: 198 readline.parse_and_bind("tab:complete") 199 200 # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system 201 # conventions and get $PYTHONSTARTUP first then .pythonrc.py. 202 if use_pythonrc: 203 for pythonrc in set( 204 [os.environ.get("PYTHONSTARTUP"), os.path.expanduser('~/.pythonrc.py')] 205 ): 206 if not pythonrc: 207 continue 208 if not os.path.isfile(pythonrc): 209 continue 210 with open(pythonrc) as handle: 211 pythonrc_code = handle.read() 212 # Match the behavior of the cpython shell where an error in 213 # PYTHONSTARTUP prints an exception and continues. 214 exec(compile(pythonrc_code, pythonrc, 'exec'), imported_objects) 215 216 def launch_code(): 217 code.interact(local=imported_objects) 218 219 return launch_code 220 221 222def launch(shell='best', use_pythonrc=False, use_vi_mode=False, **kwargs): 223 # Also allowing passing shell='code' to force using code.interact 224 imported_objects = get_launch_args(**kwargs) 225 226 if shell == 'best': 227 shell = detect_best_shell() 228 229 if shell == 'ptipython': 230 launch = get_ptipython(options=kwargs, vi_mode=use_vi_mode) 231 elif shell == 'ptpython': 232 launch = get_ptpython(options=kwargs, vi_mode=use_vi_mode) 233 elif shell == 'ipython': 234 launch = get_ipython(options=kwargs) 235 elif shell == 'bpython': 236 launch = get_bpython(options=kwargs) 237 else: 238 launch = get_code(use_pythonrc=use_pythonrc, imported_objects=imported_objects) 239 240 launch() 241