pyflyby 1.9.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyflyby might be problematic. Click here for more details.

Files changed (54) hide show
  1. pyflyby/__init__.py +56 -0
  2. pyflyby/__main__.py +9 -0
  3. pyflyby/_autoimp.py +2114 -0
  4. pyflyby/_cmdline.py +531 -0
  5. pyflyby/_comms.py +221 -0
  6. pyflyby/_dbg.py +1339 -0
  7. pyflyby/_docxref.py +379 -0
  8. pyflyby/_file.py +738 -0
  9. pyflyby/_flags.py +230 -0
  10. pyflyby/_format.py +182 -0
  11. pyflyby/_idents.py +233 -0
  12. pyflyby/_import_sorting.py +165 -0
  13. pyflyby/_importclns.py +642 -0
  14. pyflyby/_importdb.py +588 -0
  15. pyflyby/_imports2s.py +639 -0
  16. pyflyby/_importstmt.py +662 -0
  17. pyflyby/_interactive.py +2605 -0
  18. pyflyby/_livepatch.py +793 -0
  19. pyflyby/_log.py +199 -0
  20. pyflyby/_modules.py +515 -0
  21. pyflyby/_parse.py +1441 -0
  22. pyflyby/_py.py +2078 -0
  23. pyflyby/_util.py +459 -0
  24. pyflyby/_version.py +7 -0
  25. pyflyby/autoimport.py +20 -0
  26. pyflyby/importdb.py +19 -0
  27. pyflyby-1.9.4.data/data/etc/pyflyby/canonical.py +10 -0
  28. pyflyby-1.9.4.data/data/etc/pyflyby/common.py +27 -0
  29. pyflyby-1.9.4.data/data/etc/pyflyby/forget.py +10 -0
  30. pyflyby-1.9.4.data/data/etc/pyflyby/mandatory.py +10 -0
  31. pyflyby-1.9.4.data/data/etc/pyflyby/numpy.py +156 -0
  32. pyflyby-1.9.4.data/data/etc/pyflyby/std.py +335 -0
  33. pyflyby-1.9.4.data/data/libexec/pyflyby/colordiff +34 -0
  34. pyflyby-1.9.4.data/data/libexec/pyflyby/diff-colorize +148 -0
  35. pyflyby-1.9.4.data/data/share/doc/pyflyby/LICENSE.txt +23 -0
  36. pyflyby-1.9.4.data/data/share/doc/pyflyby/TODO.txt +115 -0
  37. pyflyby-1.9.4.data/data/share/doc/pyflyby/testing.txt +13 -0
  38. pyflyby-1.9.4.data/data/share/emacs/site-lisp/pyflyby.el +108 -0
  39. pyflyby-1.9.4.data/scripts/collect-exports +76 -0
  40. pyflyby-1.9.4.data/scripts/collect-imports +58 -0
  41. pyflyby-1.9.4.data/scripts/find-import +38 -0
  42. pyflyby-1.9.4.data/scripts/list-bad-xrefs +34 -0
  43. pyflyby-1.9.4.data/scripts/prune-broken-imports +34 -0
  44. pyflyby-1.9.4.data/scripts/pyflyby-diff +34 -0
  45. pyflyby-1.9.4.data/scripts/reformat-imports +27 -0
  46. pyflyby-1.9.4.data/scripts/replace-star-imports +37 -0
  47. pyflyby-1.9.4.data/scripts/tidy-imports +191 -0
  48. pyflyby-1.9.4.data/scripts/transform-imports +47 -0
  49. pyflyby-1.9.4.dist-info/LICENSE.txt +23 -0
  50. pyflyby-1.9.4.dist-info/METADATA +507 -0
  51. pyflyby-1.9.4.dist-info/RECORD +54 -0
  52. pyflyby-1.9.4.dist-info/WHEEL +5 -0
  53. pyflyby-1.9.4.dist-info/entry_points.txt +3 -0
  54. pyflyby-1.9.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2605 @@
1
+ # pyflyby/_interactive.py.
2
+ # Copyright (C) 2011, 2012, 2013, 2014, 2015, 2018 Karl Chen.
3
+ # License: MIT http://opensource.org/licenses/MIT
4
+
5
+
6
+
7
+ import ast
8
+ import builtins
9
+ from contextlib import contextmanager
10
+ import errno
11
+ import inspect
12
+ import os
13
+ import operator
14
+ import re
15
+ import subprocess
16
+ import sys
17
+
18
+
19
+ from pyflyby._autoimp import (LoadSymbolError, ScopeStack, auto_eval,
20
+ auto_import,
21
+ clear_failed_imports_cache,
22
+ load_symbol)
23
+ from pyflyby._comms import (initialize_comms, remove_comms,
24
+ send_comm_message, MISSING_IMPORTS)
25
+ from pyflyby._file import Filename, atomic_write_file, read_file
26
+ from pyflyby._idents import is_identifier
27
+ from pyflyby._importdb import ImportDB
28
+ from pyflyby._log import logger
29
+ from pyflyby._modules import ModuleHandle
30
+ from pyflyby._parse import PythonBlock
31
+ from pyflyby._util import (AdviceCtx, Aspect, CwdCtx,
32
+ FunctionWithGlobals, NullCtx, advise,
33
+ indent)
34
+
35
+
36
+ if False:
37
+ __original__ = None # for pyflakes
38
+
39
+
40
+ get_method_self = operator.attrgetter('__self__')
41
+
42
+ # TODO: also support arbitrary code (in the form of a lambda and/or
43
+ # assignment) as new way to do "lazy" creations, e.g. foo = a.b.c(d.e+f.g())
44
+
45
+
46
+ class NoIPythonPackageError(Exception):
47
+ """
48
+ Exception raised when the IPython package is not installed in the system.
49
+ """
50
+
51
+
52
+ class NoActiveIPythonAppError(Exception):
53
+ """
54
+ Exception raised when there is no current IPython application instance.
55
+ """
56
+
57
+
58
+ def _get_or_create_ipython_terminal_app():
59
+ """
60
+ Create/get the singleton IPython terminal application.
61
+
62
+ :rtype:
63
+ ``TerminalIPythonApp``
64
+ :raise NoIPythonPackageError:
65
+ IPython is not installed in the system.
66
+ """
67
+ try:
68
+ import IPython
69
+ except ImportError as e:
70
+ raise NoIPythonPackageError(e)
71
+ # The following has been tested on IPython 1.0, 1.2, 2.0, 2.1, 2.2, 2.3.
72
+ try:
73
+ TerminalIPythonApp = IPython.terminal.ipapp.TerminalIPythonApp
74
+ except AttributeError:
75
+ pass
76
+ else:
77
+ return TerminalIPythonApp.instance()
78
+ # The following has been tested on IPython 0.11, 0.12, 0.13.
79
+ try:
80
+ TerminalIPythonApp = IPython.frontend.terminal.ipapp.TerminalIPythonApp
81
+ except AttributeError:
82
+ pass
83
+ else:
84
+ return TerminalIPythonApp.instance()
85
+ # The following has been tested on IPython 0.10.
86
+ if hasattr(IPython, "ipapi"):
87
+ return _IPython010TerminalApplication.instance()
88
+ raise RuntimeError(
89
+ "Couldn't get TerminalIPythonApp class. "
90
+ "Is your IPython version too old (or too new)? "
91
+ "IPython.__version__=%r" % (IPython.__version__))
92
+
93
+
94
+ def _app_is_initialized(app):
95
+ """
96
+ Return whether ``app.initialize()`` has been called.
97
+
98
+ :type app:
99
+ `IPython.Application`
100
+ :rtype:
101
+ ``bool``
102
+ """
103
+ # There's no official way to tell whether app.initialize() has been called
104
+ # before. We guess whether the app has been initialized by checking
105
+ # whether all traits have values.
106
+ #
107
+ # There's a method app.initialized(), but it doesn't do what we want. It
108
+ # does not return whether app.initialize() has been called - rather,
109
+ # type(app).initialized() returns whether an instance of the class has
110
+ # ever been constructed, i.e. app.initialized() always returns True.
111
+ cache_name = "__is_initialized_54283907"
112
+ if cache_name in app.__dict__:
113
+ return True
114
+ if all(n in app._trait_values for n in app.trait_names()):
115
+ app.__dict__[cache_name] = True
116
+ return True
117
+ else:
118
+ return False
119
+
120
+
121
+
122
+ class _IPython010TerminalApplication(object):
123
+ """
124
+ Shim class that mimics IPython 0.11+ application classes, for use in
125
+ IPython 0.10.
126
+ """
127
+
128
+ # IPython.ipapi.launch_instance() => IPython.Shell.start() creates an
129
+ # instance of "IPShell". IPShell has an attribute named "IP" which is an
130
+ # "InteractiveShell".
131
+
132
+ _instance = None
133
+
134
+ @classmethod
135
+ def instance(cls):
136
+ if cls._instance is not None:
137
+ self = cls._instance
138
+ self.init_shell()
139
+ return self
140
+ import IPython
141
+ if not hasattr(IPython, "ipapi"):
142
+ raise RuntimeError("Inappropriate version of IPython %r"
143
+ % (IPython.__version__,))
144
+ self = cls._instance = cls()
145
+ self.init_shell()
146
+ return self
147
+
148
+ def init_shell(self):
149
+ import IPython
150
+ ipapi = IPython.ipapi.get() # IPApi instance
151
+ if ipapi is not None:
152
+ self.shell = ipapi.IP # InteractiveShell instance
153
+ else:
154
+ self.shell = None
155
+
156
+ def initialize(self, argv=None):
157
+ import IPython
158
+ logger.debug("Creating IPython 0.10 session")
159
+ self._session = IPython.ipapi.make_session() # IPShell instance
160
+ self.init_shell()
161
+ assert self._session is not None
162
+
163
+ def start(self):
164
+ self._session.mainloop()
165
+
166
+
167
+
168
+ class _DummyIPythonEmbeddedApp(object):
169
+ """
170
+ Small wrapper around an `InteractiveShellEmbed`.
171
+ """
172
+
173
+ def __init__(self, shell):
174
+ self.shell = shell
175
+
176
+
177
+
178
+ def _get_or_create_ipython_kernel_app():
179
+ """
180
+ Create/get the singleton IPython kernel application.
181
+
182
+ :rtype:
183
+ ``callable``
184
+ :return:
185
+ The function that can be called to start the kernel application.
186
+ """
187
+ import IPython
188
+ # The following has been tested on IPython 4.0
189
+ try:
190
+ from ipykernel.kernelapp import IPKernelApp
191
+ except ImportError:
192
+ pass
193
+ else:
194
+ return IPKernelApp.instance()
195
+ # The following has been tested on IPython 1.0, 1.2, 2.0, 2.1, 2.2, 2.3,
196
+ # 2.4, 3.0, 3.1, 3.2
197
+ try:
198
+ from IPython.kernel.zmq.kernelapp import IPKernelApp
199
+ except ImportError:
200
+ pass
201
+ else:
202
+ return IPKernelApp.instance()
203
+ # The following has been tested on IPython 0.12, 0.13
204
+ try:
205
+ from IPython.zmq.ipkernel import IPKernelApp
206
+ except ImportError:
207
+ pass
208
+ else:
209
+ return IPKernelApp.instance()
210
+ raise RuntimeError(
211
+ "Couldn't get IPKernelApp class. "
212
+ "Is your IPython version too old (or too new)? "
213
+ "IPython.__version__=%r" % (IPython.__version__))
214
+
215
+
216
+ def get_ipython_terminal_app_with_autoimporter():
217
+ """
218
+ Return an initialized ``TerminalIPythonApp``.
219
+
220
+ If a ``TerminalIPythonApp`` has already been created, then use it (whether
221
+ we are inside that app or not). If there isn't already one, then create
222
+ one. Enable the auto importer, if it hasn't already been enabled. If the
223
+ app hasn't been initialized yet, then initialize() it (but don't start()
224
+ it).
225
+
226
+ :rtype:
227
+ ``TerminalIPythonApp``
228
+ :raise NoIPythonPackageError:
229
+ IPython is not installed in the system.
230
+ """
231
+ app = _get_or_create_ipython_terminal_app()
232
+ AutoImporter(app).enable()
233
+ if not _app_is_initialized(app):
234
+ old_display_banner = app.display_banner
235
+ try:
236
+ app.display_banner = False
237
+ app.initialize([])
238
+ finally:
239
+ app.display_banner = old_display_banner
240
+ return app
241
+
242
+
243
+ def start_ipython_with_autoimporter(argv=None, app=None, _user_ns=None):
244
+ """
245
+ Start IPython (terminal) with autoimporter enabled.
246
+ """
247
+ if app is None:
248
+ subcmd = argv and argv[0]
249
+ if subcmd == 'console':
250
+ # The following has been tested on IPython 5.8 / Jupyter console 5.2.
251
+ # Note: jupyter_console.app.JupyterApp also appears to work in some
252
+ # contexts, but that actually execs the script jupyter-console which
253
+ # uses ZMQTerminalIPythonApp. The exec makes the target use whatever
254
+ # shebang line is in that script, which may be a different python
255
+ # major version than what we're currently running. We want to avoid
256
+ # the exec in general (as a library function) and avoid changing
257
+ # python versions.
258
+ try:
259
+ from ipkernel.app import IPKernelApp
260
+ except (ImportError, AttributeError):
261
+ pass
262
+ else:
263
+ app = IPKernelApp.instance()
264
+ argv = argv[1:]
265
+ elif subcmd == 'notebook':
266
+ try:
267
+ from notebook.notebookapp import NotebookApp
268
+ except (ImportError, AttributeError):
269
+ pass
270
+ else:
271
+ app = NotebookApp.instance()
272
+ argv = argv[1:]
273
+ if app is None:
274
+ app = _get_or_create_ipython_terminal_app()
275
+ if _user_ns is not None:
276
+ # Tested with IPython 1.2, 2.0, 2.1, 2.2, 2.3. 2.4, 3.0, 3.1, 3.2
277
+ # TODO: support older versions of IPython.
278
+ # FIXME TODO: fix attaching debugger to IPython started this way. It
279
+ # has to do with assigning user_ns. Apparently if user_ns["__name__"]
280
+ # is "__main__" (which IPython defaults to, and we want to use
281
+ # anyway), then user_module must be a true ModuleType in order for
282
+ # attaching to work correctly. If you specify user_ns but not
283
+ # user_module, then user_module is a DummyModule rather than a true
284
+ # ModuleType (since ModuleType.__dict__ is read-only). Thus, if we
285
+ # specify user_ns, we should specify user_module also. However, while
286
+ # user_module is a constructor parameter to InteractiveShell,
287
+ # IPythonTerminalApp doesn't pass that parameter to it. We can't
288
+ # assign after initialize() because user_module and user_ns are
289
+ # already used during initialization. One workaround idea is to let
290
+ # IPython initialize without specifying either user_ns or user_module,
291
+ # and then patch in members. However, that has the downside of
292
+ # breaking func_globals of lambdas, e.g. if a script does 'def f():
293
+ # global x; x=4', then we run it with 'py -i', our globals dict won't
294
+ # be the same dict. We should create a true ModuleType anyway even if
295
+ # not using IPython. We might need to resort to advising
296
+ # init_create_namespaces etc. depending on IPython version.
297
+ if getattr(app, 'shell', None) is not None:
298
+ app.shell.user_ns.update(_user_ns)
299
+ else:
300
+ app.user_ns = _user_ns
301
+ return _initialize_and_start_app_with_autoimporter(app, argv)
302
+
303
+
304
+ def start_ipython_kernel_with_autoimporter(argv=None):
305
+ """
306
+ Start IPython kernel with autoimporter enabled.
307
+ """
308
+ app = _get_or_create_ipython_kernel_app()
309
+ return _initialize_and_start_app_with_autoimporter(app, argv)
310
+
311
+
312
+ def _initialize_and_start_app_with_autoimporter(app, argv):
313
+ """
314
+ Initialize and start an IPython app, with autoimporting enabled.
315
+
316
+ :type app:
317
+ `BaseIPythonApplication`
318
+ """
319
+ # Enable the auto importer.
320
+ AutoImporter(app).enable()
321
+ # Save the value of the "_" name in the user namespace, to avoid
322
+ # initialize() clobbering it.
323
+ user_ns = getattr(app, "user_ns", None)
324
+ saved_user_ns = {}
325
+ if user_ns is not None:
326
+ for k in ["_"]:
327
+ try:
328
+ saved_user_ns[k] = user_ns[k]
329
+ except KeyError:
330
+ pass
331
+ # Initialize the app.
332
+ if not _app_is_initialized(app):
333
+ app.initialize(argv)
334
+ if user_ns is not None:
335
+ user_ns.update(saved_user_ns)
336
+ # Start the app mainloop.
337
+ return app.start()
338
+
339
+
340
+ def run_ipython_line_magic(arg):
341
+ """
342
+ Run IPython magic command.
343
+ If necessary, start an IPython terminal app to do so.
344
+ """
345
+ import IPython
346
+ if not arg.startswith("%"):
347
+ arg = "%" + arg
348
+ app = _get_or_create_ipython_terminal_app()
349
+ AutoImporter(app).enable()
350
+ # TODO: only initialize if not already initialized.
351
+ if not _app_is_initialized(app):
352
+ app.initialize([])
353
+ ip = app.shell
354
+ if hasattr(ip, "magic"):
355
+ # IPython 0.11+.
356
+ # The following has been tested on IPython 0.11, 0.12, 0.13, 1.0, 1.2,
357
+ # 2.0, 2.1, 2.2, 2.3.
358
+ # TODO: may want to wrap in one or two layers of dummy functions to make
359
+ # sure run_line_magic() doesn't inspect our locals.
360
+ return ip.magic(arg)
361
+ elif hasattr(ip, "runlines"):
362
+ # IPython 0.10
363
+ return ip.runlines(arg)
364
+ else:
365
+ raise RuntimeError(
366
+ "Couldn't run IPython magic. "
367
+ "Is your IPython version too old (or too new)? "
368
+ "IPython.__version__=%r" % (IPython.__version__))
369
+
370
+
371
+ def _python_can_import_pyflyby(expected_path, sys_path_entry=None):
372
+ """
373
+ Try to figure out whether python (when started from scratch) can get the
374
+ same pyflyby package as the current process.
375
+ """
376
+ with CwdCtx("/"):
377
+ cmd = 'import pyflyby; print(pyflyby.__path__[0])'
378
+ if sys_path_entry is not None:
379
+ impcmd = "import sys; sys.path.insert(0, %r)\n" % (sys_path_entry,)
380
+ cmd = impcmd + cmd
381
+ proc = subprocess.Popen(
382
+ [sys.executable, '-c', cmd],
383
+ stdin=open("/dev/null"),
384
+ stdout=subprocess.PIPE,
385
+ stderr=open("/dev/null",'w'))
386
+ result = proc.communicate()[0].strip()
387
+ if not result:
388
+ return False
389
+ try:
390
+ return os.path.samefile(result, expected_path)
391
+ except OSError:
392
+ return False
393
+
394
+
395
+ def install_in_ipython_config_file():
396
+ """
397
+ Install the call to 'pyflyby.enable_auto_importer()' to the default
398
+ IPython startup file.
399
+
400
+ This makes all "ipython" sessions behave like "autoipython", i.e. start
401
+ with the autoimporter already enabled.
402
+ """
403
+ import IPython
404
+ # The following has been tested on IPython 4.0, 5.0
405
+ try:
406
+ IPython.paths
407
+ except AttributeError:
408
+ pass
409
+ else:
410
+ _install_in_ipython_config_file_40()
411
+ return
412
+ # The following has been tested on IPython 0.12, 0.13, 1.0, 1.2, 2.0, 2.1,
413
+ # 2.2, 2.3, 2.4, 3.0, 3.1, 3.2, 4.0.
414
+ try:
415
+ IPython.core.profiledir.ProfileDir.startup_dir
416
+ except AttributeError:
417
+ pass
418
+ else:
419
+ _install_in_ipython_config_file_012()
420
+ return
421
+ # The following has been tested on IPython 0.11.
422
+ try:
423
+ IPython.core.profiledir.ProfileDir
424
+ except AttributeError:
425
+ pass
426
+ else:
427
+ _install_in_ipython_config_file_011()
428
+ return
429
+ try:
430
+ IPython.genutils.get_ipython_dir
431
+ except AttributeError:
432
+ pass
433
+ else:
434
+ _install_in_ipython_config_file_010()
435
+ return
436
+ raise RuntimeError(
437
+ "Couldn't install pyflyby autoimporter in IPython. "
438
+ "Is your IPython version too old (or too new)? "
439
+ "IPython.__version__=%r" % (IPython.__version__))
440
+
441
+
442
+ def _generate_enabler_code():
443
+ """
444
+ Generate code for enabling the auto importer.
445
+
446
+ :rtype:
447
+ ``str``
448
+ """
449
+ funcdef = (
450
+ "import pyflyby\n"
451
+ "pyflyby.enable_auto_importer()\n"
452
+ )
453
+ # Check whether we need to include the path in sys.path, and if so, add
454
+ # that to the contents.
455
+ import pyflyby
456
+ pyflyby_path = pyflyby.__path__[0]
457
+ if not _python_can_import_pyflyby(pyflyby_path):
458
+ path_entry = os.path.dirname(os.path.realpath(pyflyby_path))
459
+ assert _python_can_import_pyflyby(pyflyby_path, path_entry)
460
+ funcdef = (
461
+ "import sys\n"
462
+ "saved_sys_path = sys.path[:]\n"
463
+ "try:\n"
464
+ " sys.path.insert(0, %r)\n" % (path_entry,) +
465
+ indent(funcdef, " ") +
466
+ "finally:\n"
467
+ " sys.path = saved_sys_path\n"
468
+ )
469
+ # Wrap the code in a temporary function, call it, then delete the
470
+ # function. This avoids polluting the user's global namespace. Although
471
+ # the global name "pyflyby" will almost always end up meaning the module
472
+ # "pyflyby" anyway, if the user types it, there's still value in not
473
+ # polluting the namespace in case something enumerates over globals().
474
+ # For the function name we use a name that's unlikely to be used by the
475
+ # user.
476
+ contents = (
477
+ "def __pyflyby_enable_auto_importer_60321389():\n" +
478
+ indent(funcdef, " ") +
479
+ "__pyflyby_enable_auto_importer_60321389()\n"
480
+ "del __pyflyby_enable_auto_importer_60321389\n"
481
+ )
482
+ return contents
483
+
484
+
485
+ def _install_in_ipython_config_file_40():
486
+ """
487
+ Implementation of `install_in_ipython_config_file` for IPython 4.0+.
488
+ """
489
+ import IPython
490
+ ipython_dir = Filename(IPython.paths.get_ipython_dir())
491
+ if not ipython_dir.isdir:
492
+ raise RuntimeError(
493
+ "Couldn't find IPython config dir. Tried %s" % (ipython_dir,))
494
+
495
+ # Add to extensions list in ~/.ipython/profile_default/ipython_config.py
496
+ config_fn = ipython_dir / "profile_default" / "ipython_config.py"
497
+ if not config_fn.exists:
498
+ subprocess.call(['ipython', 'profile', 'create'])
499
+ if not config_fn.exists:
500
+ raise RuntimeError(
501
+ "Couldn't find IPython config file. Tried %s" % (config_fn,))
502
+ old_config_blob = read_file(config_fn)
503
+ # This is the line we'll add.
504
+ line_to_add = 'c.InteractiveShellApp.extensions.append("pyflyby")'
505
+ non_comment_lines = [re.sub("#.*", "", line) for line in old_config_blob.lines]
506
+ if any(line_to_add in line for line in non_comment_lines):
507
+ logger.info("[NOTHING TO DO] File %s already loads pyflyby", config_fn)
508
+ elif any("pyflyby" in line for line in non_comment_lines):
509
+ logger.info("[NOTHING TO DO] File %s already references pyflyby in some nonstandard way, assuming you configured it manually", config_fn)
510
+ else:
511
+ # Add pyflyby to config file.
512
+ lines_to_add = [line_to_add]
513
+ # Check whether we need to include the path in sys.path, and if so, add
514
+ # that to the contents. This is only needed if pyflyby is running out
515
+ # of a home directory rather than site-packages/virtualenv/etc.
516
+ # TODO: we should use tidy-imports to insert the 'import sys', if
517
+ # needed, at the top, rather than always appending it at the bottom.
518
+ import pyflyby
519
+ pyflyby_path = pyflyby.__path__[0]
520
+ if not _python_can_import_pyflyby(pyflyby_path):
521
+ path_entry = os.path.dirname(os.path.realpath(pyflyby_path))
522
+ assert _python_can_import_pyflyby(pyflyby_path, path_entry)
523
+ lines_to_add = [
524
+ "import sys",
525
+ "sys.path.append(%r)" % (path_entry,)
526
+ ] + lines_to_add
527
+ lines_to_add.insert(0, "# Pyflyby")
528
+ blob_to_add = "\n\n" + "\n".join(lines_to_add) + "\n"
529
+ new_config_blob = old_config_blob.joined.rstrip() + blob_to_add
530
+ atomic_write_file(config_fn, new_config_blob)
531
+ logger.info("[DONE] Appended to %s: %s", config_fn, line_to_add)
532
+
533
+ # Delete file installed with older approach.
534
+ startup_dir = ipython_dir / "profile_default" / "startup"
535
+ old_fn = startup_dir / "50-pyflyby.py"
536
+ if old_fn.exists:
537
+ trash_dir = old_fn.dir / ".TRASH"
538
+ trash_fn = trash_dir / old_fn.base
539
+ try:
540
+ os.mkdir(str(trash_dir))
541
+ except EnvironmentError as e:
542
+ if e.errno == errno.EEXIST:
543
+ pass
544
+ else:
545
+ raise RuntimeError("Couldn't mkdir %s: %s: %s"
546
+ % (trash_dir, type(e).__name__, e))
547
+ try:
548
+ os.rename(str(old_fn), str(trash_fn))
549
+ except EnvironmentError as e:
550
+ raise RuntimeError("Couldn't rename %s to %s: %s: %s"
551
+ % (old_fn, trash_fn, type(e).__name__, e))
552
+ logger.info("[DONE] Removed old file %s (moved to %s)", old_fn, trash_fn)
553
+
554
+
555
+ def _install_in_ipython_config_file_012():
556
+ """
557
+ Implementation of `install_in_ipython_config_file` for IPython 0.12+.
558
+ Tested with IPython 0.12, 0.13, 1.0, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0,
559
+ 3.1, 3.2, 4.0.
560
+ """
561
+ import IPython
562
+ ipython_dir = Filename(IPython.utils.path.get_ipython_dir())
563
+ if not ipython_dir.isdir:
564
+ raise RuntimeError(
565
+ "Couldn't find IPython config dir. Tried %s" % (ipython_dir,))
566
+ startup_dir = ipython_dir / "profile_default" / "startup"
567
+ if not startup_dir.isdir:
568
+ raise RuntimeError(
569
+ "Couldn't find IPython startup dir. Tried %s" % (startup_dir,))
570
+ fn = startup_dir / "50-pyflyby.py"
571
+ if fn.exists:
572
+ logger.info("Doing nothing, because %s already exists", fn)
573
+ return
574
+ argv = sys.argv[:]
575
+ argv[0] = os.path.realpath(argv[0])
576
+ argv = ' '.join(argv)
577
+ header = (
578
+ "# File: {fn}\n"
579
+ "#\n"
580
+ "# Generated by {argv}\n"
581
+ "#\n"
582
+ "# This file causes IPython to enable the Pyflyby Auto Importer.\n"
583
+ "#\n"
584
+ "# To uninstall, just delete this file.\n"
585
+ "#\n"
586
+ ).format(**locals())
587
+ contents = header + _generate_enabler_code()
588
+ logger.info("Installing pyflyby auto importer in your IPython startup")
589
+ logger.info("Writing to %s:\n%s", fn, contents)
590
+ atomic_write_file(fn, contents)
591
+
592
+
593
+ def _install_in_ipython_config_file_011():
594
+ """
595
+ Implementation of `install_in_ipython_config_file` for IPython 0.11.
596
+ """
597
+ import IPython
598
+ ipython_dir = Filename(IPython.utils.path.get_ipython_dir())
599
+ fn = ipython_dir / "profile_default" / "ipython_config.py"
600
+ if not fn.exists:
601
+ raise RuntimeError(
602
+ "Couldn't find IPython startup file. Tried %s" % (fn,))
603
+ old_contents = read_file(fn).joined
604
+ if re.search(r"^ *(pyflyby[.])?enable_auto_importer[(][)]", old_contents, re.M):
605
+ logger.info("Doing nothing, because already installed in %s", fn)
606
+ return
607
+ header = (
608
+ "\n"
609
+ "\n"
610
+ "#\n"
611
+ "# Enable the Pyflyby Auto Importer.\n"
612
+ )
613
+ new_contents = header + _generate_enabler_code()
614
+ contents = old_contents.rstrip() + new_contents
615
+ logger.info("Installing pyflyby auto importer in your IPython startup")
616
+ logger.info("Appending to %s:\n%s", fn, new_contents)
617
+ atomic_write_file(fn, contents)
618
+
619
+
620
+ def _install_in_ipython_config_file_010():
621
+ """
622
+ Implementation of `install_in_ipython_config_file` for IPython 0.10.
623
+ """
624
+ import IPython
625
+ ipython_dir = Filename(IPython.genutils.get_ipython_dir())
626
+ fn = ipython_dir / "ipy_user_conf.py"
627
+ if not fn.exists:
628
+ raise RuntimeError(
629
+ "Couldn't find IPython config file. Tried %s" % (fn,))
630
+ old_contents = read_file(fn).joined
631
+ if re.search(r"^ *(pyflyby[.])?enable_auto_importer[(][)]", old_contents, re.M):
632
+ logger.info("Doing nothing, because already installed in %s", fn)
633
+ return
634
+ header = (
635
+ "\n"
636
+ "\n"
637
+ "#\n"
638
+ "# Enable the Pyflyby Auto Importer.\n"
639
+ )
640
+ new_contents = header + _generate_enabler_code()
641
+ contents = old_contents.rstrip() + new_contents
642
+ logger.info("Installing pyflyby auto importer in your IPython startup")
643
+ logger.info("Appending to %s:\n%s", fn, new_contents)
644
+ atomic_write_file(fn, contents)
645
+
646
+
647
+ def _ipython_in_multiline(ip):
648
+ """
649
+ Return ``False`` if the user has entered only one line of input so far,
650
+ including the current line, or ``True`` if it is the second or later line.
651
+
652
+ :type ip:
653
+ ``InteractiveShell``
654
+ :rtype:
655
+ ``bool``
656
+ """
657
+ if hasattr(ip, "input_splitter"):
658
+ # IPython 0.11+. Tested with IPython 0.11, 0.12, 0.13, 1.0, 1.2, 2.0,
659
+ # 2.1, 2.2, 2.3, 2.4, 3.0, 3.1, 3.2, 4.0.
660
+ return bool(ip.input_splitter.source)
661
+ elif hasattr(ip, "buffer"):
662
+ # IPython 0.10
663
+ return bool(ip.buffer)
664
+ else:
665
+ # IPython version too old or too new?
666
+ return False
667
+
668
+
669
+ def InterceptPrintsDuringPromptCtx(ip):
670
+ """
671
+ Decorator that hooks our logger so that::
672
+
673
+ 1. Before the first print, if any, print an extra newline.
674
+ 2. Upon context exit, if any lines were printed, redisplay the prompt.
675
+
676
+ :type ip:
677
+ ``InteractiveShell``
678
+ """
679
+ if not ip:
680
+ return NullCtx()
681
+
682
+ if not hasattr(ip, 'readline'):
683
+ if type(sys.stdout).__module__.startswith("prompt_toolkit."):
684
+ # prompt_toolkit replaces stdout with a proxy that takes
685
+ # care of redrawing the prompt correctly.
686
+ return NullCtx()
687
+
688
+ if not hasattr(ip, "prompts_class"):
689
+ # This could be a Jupyter console/notebook.
690
+ return NullCtx()
691
+
692
+ def pre():
693
+ sys.stdout.write("\n")
694
+ sys.stdout.flush()
695
+ def post():
696
+ # Re-display the current line.
697
+ sys.stdout.write("\n")
698
+ t = ip.prompts_class(ip).in_prompt_tokens()
699
+ ip.pt_cli.print_tokens(t)
700
+ sys.stdout.write(ip.pt_cli.current_buffer.document.current_line)
701
+ sys.stdout.flush()
702
+ return logger.HookCtx(pre=pre, post=post)
703
+
704
+ readline = ip.readline
705
+ if not hasattr(readline, "redisplay"):
706
+ # May be IPython Notebook.
707
+ return NullCtx()
708
+ redisplay = readline.redisplay
709
+ get_prompt = None
710
+ if type(ip).__module__ == "rlipython.shell":
711
+ # IPython 5.4 with
712
+ # interactive_shell_class=rlipython.TerminalInteractiveShell
713
+ def get_prompt_rlipython():
714
+ pdb_instance = _get_pdb_if_is_in_pdb()
715
+ if pdb_instance is not None:
716
+ return pdb_instance.prompt
717
+ elif _ipython_in_multiline(ip):
718
+ return ip.prompt_in2
719
+ else:
720
+ return ip.separate_in + ip.prompt_in1.format(ip.execution_count)
721
+ get_prompt = get_prompt_rlipython
722
+ elif hasattr(ip, "prompt_manager"):
723
+ # IPython >= 0.12 (known to work including up to 1.2, 2.1)
724
+ prompt_manager = ip.prompt_manager
725
+ def get_prompt_ipython_012():
726
+ pdb_instance = _get_pdb_if_is_in_pdb()
727
+ if pdb_instance is not None:
728
+ return pdb_instance.prompt
729
+ elif _ipython_in_multiline(ip):
730
+ return prompt_manager.render("in2")
731
+ else:
732
+ return ip.separate_in + prompt_manager.render("in")
733
+ get_prompt = get_prompt_ipython_012
734
+ elif hasattr(ip.hooks, "generate_prompt"):
735
+ # IPython 0.10, 0.11
736
+ generate_prompt = ip.hooks.generate_prompt
737
+ def get_prompt_ipython_010():
738
+ pdb_instance = _get_pdb_if_is_in_pdb()
739
+ if pdb_instance is not None:
740
+ return pdb_instance.prompt
741
+ elif _ipython_in_multiline(ip):
742
+ return generate_prompt(True)
743
+ else:
744
+ if hasattr(ip, "outputcache"):
745
+ # IPython 0.10 (but not 0.11+):
746
+ # Decrement the prompt_count since it otherwise
747
+ # auto-increments. (It's hard to avoid the
748
+ # auto-increment as it happens as a side effect of
749
+ # __str__!)
750
+ ip.outputcache.prompt_count -= 1
751
+ return generate_prompt(False)
752
+ get_prompt = get_prompt_ipython_010
753
+ else:
754
+ # Too old or too new IPython version?
755
+ return NullCtx()
756
+ def pre():
757
+ sys.stdout.write("\n")
758
+ sys.stdout.flush()
759
+ def post():
760
+ # Re-display the current line.
761
+ prompt = get_prompt()
762
+ prompt = prompt.replace("\x01", "").replace("\x02", "")
763
+ line = readline.get_line_buffer()[:readline.get_endidx()]
764
+ sys.stdout.write(prompt + line)
765
+ redisplay()
766
+ sys.stdout.flush()
767
+ return logger.HookCtx(pre=pre, post=post)
768
+
769
+
770
+ def _get_ipython_app():
771
+ """
772
+ Get an IPython application instance, if we are inside an IPython session.
773
+
774
+ If there isn't already an IPython application, raise an exception; don't
775
+ create one.
776
+
777
+ If there is a subapp, return it.
778
+
779
+ :rtype:
780
+ `BaseIPythonApplication` or an object that mimics some of its behavior
781
+ """
782
+ try:
783
+ IPython = sys.modules['IPython']
784
+ except KeyError:
785
+ # The 'IPython' module isn't already loaded, so we're not in an
786
+ # IPython session. Don't import it.
787
+ raise NoActiveIPythonAppError(
788
+ "No active IPython application (IPython not even imported yet)")
789
+ # The following has been tested on IPython 0.11, 0.12, 0.13, 1.0, 1.2,
790
+ # 2.0, 2.1, 2.2, 2.3.
791
+ try:
792
+ App = IPython.core.application.BaseIPythonApplication
793
+ except AttributeError:
794
+ pass
795
+ else:
796
+ app = App._instance
797
+ if app is not None:
798
+ if app.subapp is not None:
799
+ return app.subapp
800
+ else:
801
+ return app
802
+ # If we're inside an embedded shell, then there will be an active
803
+ # InteractiveShellEmbed but no application. In that case, create a
804
+ # fake application.
805
+ # (An alternative implementation would be to use
806
+ # IPython.core.interactiveshell.InteractiveShell._instance. However,
807
+ # that doesn't work with older versions of IPython, where the embedded
808
+ # shell is not a singleton.)
809
+ if hasattr(builtins, "get_ipython"):
810
+ shell = builtins.get_ipython()
811
+ else:
812
+ shell = None
813
+ if shell is not None:
814
+ return _DummyIPythonEmbeddedApp(shell)
815
+ # No active IPython app/shell.
816
+ raise NoActiveIPythonAppError("No active IPython application")
817
+ # The following has been tested on IPython 0.10.
818
+ if hasattr(IPython, "ipapi"):
819
+ return _IPython010TerminalApplication.instance()
820
+ raise NoActiveIPythonAppError(
821
+ "Could not figure out how to get active IPython application for IPython version %s"
822
+ % (IPython.__version__,))
823
+
824
+
825
+ def _ipython_namespaces(ip):
826
+ """
827
+ Return the (global) namespaces used for IPython.
828
+
829
+ The ordering follows IPython convention of most-local to most-global.
830
+
831
+ :type ip:
832
+ ``InteractiveShell``
833
+ :rtype:
834
+ ``list``
835
+ :return:
836
+ List of (name, namespace_dict) tuples.
837
+ """
838
+ # This list is copied from IPython 2.2's InteractiveShell._ofind().
839
+ # Earlier versions of IPython (back to 1.x) also include
840
+ # ip.alias_manager.alias_table at the end. This doesn't work in IPython
841
+ # 2.2 and isn't necessary anyway in earlier versions of IPython.
842
+ return [ ('Interactive' , ip.user_ns),
843
+ ('Interactive (global)', ip.user_global_ns),
844
+ ('Python builtin' , builtins.__dict__),
845
+ ]
846
+
847
+
848
+ # TODO class NamespaceList(tuple):
849
+
850
+
851
+ _IS_PDB_IGNORE_PKGS = frozenset([
852
+ 'IPython',
853
+ 'cmd',
854
+ 'contextlib',
855
+ 'prompt_toolkit',
856
+ 'pyflyby',
857
+ 'rlipython',
858
+ 'asyncio',
859
+ ])
860
+
861
+ _IS_PDB_IGNORE_PKGS_OTHER_THREADS = frozenset([
862
+ 'IPython',
863
+ 'cmd',
864
+ 'contextlib',
865
+ 'prompt_toolkit',
866
+ 'pyflyby',
867
+ 'threading',
868
+ ])
869
+
870
+ def _get_pdb_if_is_in_pdb():
871
+ """
872
+ Return the current Pdb instance, if we're currently called from Pdb.
873
+
874
+ :rtype:
875
+ ``pdb.Pdb`` or ``NoneType``
876
+ """
877
+ # This is kludgy. Todo: Is there a better way to do this?
878
+ pframe, pkgname = _skip_frames(sys._getframe(1), _IS_PDB_IGNORE_PKGS)
879
+ if pkgname == "threading":
880
+ # _skip_frames skipped all the way back to threading.__bootstrap.
881
+ # prompt_toolkit calls completion in a separate thread.
882
+ # Search all other threads for pdb.
883
+ # TODO: make this less kludgy.
884
+ import threading
885
+ current_tid = threading.current_thread().ident
886
+ pframes = [_skip_frames(frame, _IS_PDB_IGNORE_PKGS_OTHER_THREADS)
887
+ for tid, frame in sys._current_frames().items()
888
+ if tid != current_tid]
889
+ else:
890
+ pframes = [(pframe, pkgname)]
891
+ logger.debug("_get_pdb_if_is_in_pdb(): pframes = %r", pframes)
892
+ del pframe, pkgname
893
+ pdb_frames = [pframe for pframe,pkgname in pframes
894
+ if pkgname == "pdb"]
895
+ if not pdb_frames:
896
+ return None
897
+ # Found a pdb frame.
898
+ pdb_frame = pdb_frames[0]
899
+ import pdb
900
+
901
+ pdb_instance = pdb_frame.f_locals.get("self", None)
902
+ if (type(pdb_instance).__name__ == "Pdb" or
903
+ isinstance(pdb_instance, pdb.Pdb)):
904
+ return pdb_instance
905
+ else:
906
+ return None
907
+
908
+
909
+ def _skip_frames(frame, ignore_pkgs):
910
+ # import traceback;print("".join(traceback.format_stack(frame)))
911
+ while True:
912
+ if frame is None:
913
+ return None, None
914
+ modname = frame.f_globals.get("__name__", None) or ""
915
+ pkgname = modname.split(".",1)[0]
916
+ # logger.debug("_skip_frames: frame: %r %r", frame, modname)
917
+ if pkgname in ignore_pkgs:
918
+ frame = frame.f_back
919
+ continue
920
+ break
921
+ # logger.debug("_skip_frames: => %r %r", frame, pkgname)
922
+ return frame, pkgname
923
+
924
+
925
+ def get_global_namespaces(ip):
926
+ """
927
+ Get the global interactive namespaces.
928
+
929
+ :type ip:
930
+ ``InteractiveShell``
931
+ :param ip:
932
+ IPython shell or ``None`` to assume not in IPython.
933
+ :rtype:
934
+ ``list`` of ``dict``
935
+ """
936
+ # logger.debug("get_global_namespaces()")
937
+ pdb_instance = _get_pdb_if_is_in_pdb()
938
+ # logger.debug("get_global_namespaces(): pdb_instance=%r", pdb_instance)
939
+ if pdb_instance:
940
+ frame = pdb_instance.curframe
941
+ return [frame.f_globals, pdb_instance.curframe_locals]
942
+ elif ip:
943
+ return [ns for nsname, ns in _ipython_namespaces(ip)][::-1]
944
+ else:
945
+ import __main__
946
+ return [builtins.__dict__, __main__.__dict__]
947
+
948
+
949
+ def complete_symbol(fullname, namespaces, db=None, autoimported=None, ip=None,
950
+ allow_eval=False):
951
+ """
952
+ Enumerate possible completions for ``fullname``.
953
+
954
+ Includes globals and auto-importable symbols.
955
+
956
+ >>> complete_symbol("threadi", [{}]) # doctest:+ELLIPSIS
957
+ [...'threading'...]
958
+
959
+ Completion works on attributes, even on modules not yet imported - modules
960
+ are auto-imported first if not yet imported::
961
+
962
+ >>> ns = {}
963
+ >>> complete_symbol("threading.Threa", namespaces=[ns])
964
+ [PYFLYBY] import threading
965
+ ['threading.Thread', 'threading.ThreadError']
966
+
967
+ >>> 'threading' in ns
968
+ True
969
+
970
+ >>> complete_symbol("threading.Threa", namespaces=[ns])
971
+ ['threading.Thread', 'threading.ThreadError']
972
+
973
+ We only need to import *parent* modules (packages) of the symbol being
974
+ completed. If the user asks to complete "foo.bar.quu<TAB>", we need to
975
+ import foo.bar, but we don't need to import foo.bar.quux.
976
+
977
+ :type fullname:
978
+ ``str``
979
+ :param fullname:
980
+ String to complete. ("Full" refers to the fact that it should contain
981
+ dots starting from global level.)
982
+ :type namespaces:
983
+ ``dict`` or ``list`` of ``dict``
984
+ :param namespaces:
985
+ Namespaces of (already-imported) globals.
986
+ :type db:
987
+ `importDB`
988
+ :param db:
989
+ Import database to use.
990
+ :type ip:
991
+ ``InteractiveShell``
992
+ :param ip:
993
+ IPython shell instance if in IPython; ``None`` to assume not in IPython.
994
+ :param allow_eval:
995
+ Whether to allow evaluating code, which is necessary to allow completing
996
+ e.g. 'foo[0].bar<TAB>' or 'foo().bar<TAB>'. Note that IPython will only
997
+ pass such strings if IPCompleter.greedy is configured to True by the
998
+ user.
999
+ :rtype:
1000
+ ``list`` of ``str``
1001
+ :return:
1002
+ Completion candidates.
1003
+ """
1004
+ namespaces = ScopeStack(namespaces)
1005
+ logger.debug("complete_symbol(%r)", fullname)
1006
+ splt = fullname.rsplit(".", 1)
1007
+ attrname = splt[-1]
1008
+ # The right-hand-side of the split (the part to complete, possibly the
1009
+ # fullname) must be a prefix of a valid symbol. Otherwise don't bother
1010
+ # generating completions.
1011
+ # As for the left-hand-side of the split, load_symbol() will validate it
1012
+ # or evaluate it depending on ``allow_eval``.
1013
+ if not is_identifier(attrname, prefix=True):
1014
+ return []
1015
+ # Get the database of known imports.
1016
+ db = ImportDB.interpret_arg(db, target_filename=".")
1017
+ known = db.known_imports
1018
+ if len(splt) == 1:
1019
+ # Check global names, including global-level known modules and
1020
+ # importable modules.
1021
+ results = set()
1022
+ for ns in namespaces:
1023
+ for name in ns:
1024
+ if '.' not in name:
1025
+ results.add(name)
1026
+ results.update(known.member_names.get("", []))
1027
+ results.update([str(m) for m in ModuleHandle.list()])
1028
+ assert all('.' not in r for r in results)
1029
+ results = sorted([r for r in results if r.startswith(attrname)])
1030
+ elif len(splt) == 2:
1031
+ # Check members, including known sub-modules and importable sub-modules.
1032
+ pname = splt[0]
1033
+ if allow_eval:
1034
+ # Evaluate the parent, with autoimporting.
1035
+ ns_g, ns_l = namespaces.merged_to_two()
1036
+ # TODO: only catch exceptions around the eval, not the other stuff
1037
+ # (loading import db, etc).
1038
+ try:
1039
+ parent = auto_eval(pname, globals=ns_g, locals=ns_l, db=db)
1040
+ except Exception as e:
1041
+ logger.debug("complete_symbol(%r): couldn't evaluate %r: %s: %s",
1042
+ fullname, pname, type(e).__name__, e)
1043
+ return []
1044
+ else:
1045
+ try:
1046
+ parent = load_symbol(pname, namespaces, autoimport=True, db=db,
1047
+ autoimported=autoimported)
1048
+ except LoadSymbolError as e2:
1049
+ # Even after attempting auto-import, the symbol is still
1050
+ # unavailable, or some other error occurred. Nothing to complete.
1051
+ e3 = getattr(e2, "__cause__", e2)
1052
+ logger.debug("complete_symbol(%r): couldn't load symbol %r: %s: %s",
1053
+ fullname, pname, type(e3).__name__, e3)
1054
+ return []
1055
+ logger.debug("complete_symbol(%r): %s == %r", fullname, pname, parent)
1056
+ results = set()
1057
+ # Add current attribute members.
1058
+ results.update(_list_members_for_completion(parent, ip))
1059
+ # Is the parent a package/module?
1060
+ if sys.modules.get(pname, Ellipsis) is parent and parent.__name__ == pname:
1061
+ # Add known_imports entries from the database.
1062
+ results.update(known.member_names.get(pname, []))
1063
+ # Get the module handle. Note that we use ModuleHandle() on the
1064
+ # *name* of the module (``pname``) instead of the module instance
1065
+ # (``parent``). Using the module instance normally works, but
1066
+ # breaks if the module hackily replaced itself with a pseudo
1067
+ # module (e.g. https://github.com/josiahcarlson/mprop).
1068
+ pmodule = ModuleHandle(pname)
1069
+ # Add importable submodules.
1070
+ results.update([m.name.parts[-1] for m in pmodule.submodules])
1071
+ results = sorted([r for r in results if r.startswith(attrname)])
1072
+ results = ["%s.%s" % (pname, r) for r in results]
1073
+ else:
1074
+ raise AssertionError
1075
+ logger.debug("complete_symbol(%r) => %r", fullname, results)
1076
+ return results
1077
+
1078
+
1079
+ def _list_members_for_completion(obj, ip):
1080
+ """
1081
+ Enumerate the existing member attributes of an object.
1082
+ This emulates the regular Python/IPython completion items.
1083
+
1084
+ It does not include not-yet-imported submodules.
1085
+
1086
+ :param obj:
1087
+ Object whose member attributes to enumerate.
1088
+ :rtype:
1089
+ ``list`` of ``str``
1090
+ """
1091
+ if ip is None:
1092
+ words = dir(obj)
1093
+ else:
1094
+ try:
1095
+ limit_to__all__ = ip.Completer.limit_to__all__
1096
+ except AttributeError:
1097
+ limit_to__all__ = False
1098
+ if limit_to__all__ and hasattr(obj, '__all__'):
1099
+ words = getattr(obj, '__all__')
1100
+ elif "IPython.core.error" in sys.modules:
1101
+ from IPython.utils import generics
1102
+ from IPython.utils.dir2 import dir2
1103
+ from IPython.core.error import TryNext
1104
+ words = dir2(obj)
1105
+ try:
1106
+ words = generics.complete_object(obj, words)
1107
+ except TryNext:
1108
+ pass
1109
+ else:
1110
+ words = dir(obj)
1111
+ return [w for w in words if isinstance(w, str)]
1112
+
1113
+
1114
+ def _auto_import_in_pdb_frame(pdb_instance, arg):
1115
+ frame = pdb_instance.curframe
1116
+ namespaces = [ frame.f_globals, pdb_instance.curframe_locals ]
1117
+ filename = frame.f_code.co_filename
1118
+ if not filename or filename.startswith("<"):
1119
+ filename = "."
1120
+ db = ImportDB.get_default(filename)
1121
+ auto_import(arg, namespaces=namespaces, db=db)
1122
+
1123
+
1124
+ def _enable_pdb_hooks(pdb_instance):
1125
+ # Enable hooks in pdb.Pdb.
1126
+ # Should be called after pdb.Pdb.__init__().
1127
+ logger.debug("_enable_pdb_hooks(%r)", pdb_instance)
1128
+ # Patch Pdb._getval() to use auto_eval.
1129
+ # This supports 'ipdb> p foo'.
1130
+ @advise(pdb_instance._getval)
1131
+ def _getval_with_autoimport(arg):
1132
+ logger.debug("Pdb._getval(%r)", arg)
1133
+ _auto_import_in_pdb_frame(pdb_instance, arg)
1134
+ return __original__(arg)
1135
+ # Patch Pdb.default() to use auto_import.
1136
+ # This supports 'ipdb> foo()'.
1137
+ @advise(pdb_instance.default)
1138
+ def default_with_autoimport(arg):
1139
+ logger.debug("Pdb.default(%r)", arg)
1140
+ if arg.startswith("!"):
1141
+ arg = arg[1:]
1142
+ _auto_import_in_pdb_frame(pdb_instance, arg)
1143
+ return __original__(arg)
1144
+
1145
+
1146
+ def _enable_terminal_pdb_hooks(pdb_instance, auto_importer=None):
1147
+ # Should be called after TerminalPdb.__init__().
1148
+ # Tested with IPython 5.8 with prompt_toolkit.
1149
+ logger.debug("_enable_terminal_pdb_hooks(%r)", pdb_instance)
1150
+ ptcomp = getattr(pdb_instance, "_ptcomp", None)
1151
+ completer = getattr(ptcomp, "ipy_completer", None)
1152
+ logger.debug("_enable_terminal_pdb_hooks(): completer=%r", completer)
1153
+ if completer is not None and auto_importer is not None:
1154
+ auto_importer._enable_completer_hooks(completer)
1155
+
1156
+
1157
+ def _get_IPdb_class():
1158
+ """
1159
+ Get the IPython (core) Pdb class.
1160
+ """
1161
+ try:
1162
+ import IPython
1163
+ except ImportError:
1164
+ raise NoIPythonPackageError()
1165
+ try:
1166
+ # IPython 0.11+. Tested with IPython 0.11, 0.12, 0.13, 1.0, 1.1, 1.2,
1167
+ # 2.0, 2.1, 2.2, 2.3, 2.4, 3.0, 3.1, 3.2, 4.0
1168
+ from IPython.core import debugger
1169
+ return debugger.Pdb
1170
+ except ImportError:
1171
+ pass
1172
+ try:
1173
+ # IPython 0.10
1174
+ from IPython import Debugger
1175
+ return Debugger.Pdb
1176
+ except ImportError:
1177
+ pass
1178
+ # IPython exists but couldn't figure out how to get Pdb.
1179
+ raise RuntimeError(
1180
+ "Couldn't get IPython Pdb. "
1181
+ "Is your IPython version too old (or too new)? "
1182
+ "IPython.__version__=%r" % (IPython.__version__))
1183
+
1184
+
1185
+ def _get_TerminalPdb_class():
1186
+ """
1187
+ Get the IPython TerminalPdb class.
1188
+ """
1189
+ # The TerminalPdb subclasses the (core) Pdb class. If the TerminalPdb
1190
+ # class is being used, then in that case we only need to advise
1191
+ # TerminalPdb stuff, not (core) Pdb stuff. However, in some cases the
1192
+ # TerminalPdb class is not used even if it exists, so we advise the (core)
1193
+ # Pdb class separately.
1194
+ try:
1195
+ import IPython
1196
+ del IPython
1197
+ except ImportError:
1198
+ raise NoIPythonPackageError()
1199
+ try:
1200
+ from IPython.terminal.debugger import TerminalPdb
1201
+ return TerminalPdb
1202
+ except ImportError:
1203
+ pass
1204
+ raise RuntimeError("Couldn't get TerminalPdb")
1205
+
1206
+
1207
+ def new_IPdb_instance():
1208
+ """
1209
+ Create a new Pdb instance.
1210
+
1211
+ If IPython is available, then use IPython's Pdb. Initialize a new IPython
1212
+ terminal application if necessary.
1213
+
1214
+ If the IPython package is not installed in the system, then use regular Pdb.
1215
+
1216
+ Enable the auto importer.
1217
+
1218
+ :rtype:
1219
+ `Pdb`
1220
+ """
1221
+ logger.debug("new_IPdb_instance()")
1222
+ try:
1223
+ app = get_ipython_terminal_app_with_autoimporter()
1224
+ except Exception as e:
1225
+ if isinstance(e, NoIPythonPackageError) or e.__class__.__name__ == "MultipleInstanceError":
1226
+ logger.debug("%s: %s", type(e).__name__, e)
1227
+ from pdb import Pdb
1228
+ pdb_instance = Pdb()
1229
+ _enable_pdb_hooks(pdb_instance)
1230
+ _enable_terminal_pdb_hooks(pdb_instance)
1231
+ return pdb_instance
1232
+ else:
1233
+ raise
1234
+ pdb_class = _get_IPdb_class()
1235
+ logger.debug("new_IPdb_instance(): pdb_class=%s", pdb_class)
1236
+ color_scheme = _get_ipython_color_scheme(app)
1237
+ try:
1238
+ pdb_instance = pdb_class(completekey='tab', color_scheme=color_scheme)
1239
+ except TypeError:
1240
+ pdb_instance = pdb_class(completekey='tab')
1241
+ _enable_pdb_hooks(pdb_instance)
1242
+ _enable_terminal_pdb_hooks(pdb_instance)
1243
+ return pdb_instance
1244
+
1245
+
1246
+ def _get_ipython_color_scheme(app):
1247
+ """
1248
+ Get the configured IPython color scheme.
1249
+
1250
+ :type app:
1251
+ `TerminalIPythonApp`
1252
+ :param app:
1253
+ An initialized IPython terminal application.
1254
+ :rtype:
1255
+ ``str``
1256
+ """
1257
+ try:
1258
+ # Tested with IPython 0.11, 0.12, 0.13, 1.0, 1.1, 1.2, 2.0, 2.1, 2.2,
1259
+ # 2.3, 2.4, 3.0, 3.1, 3.2, 4.0.
1260
+ return app.shell.colors
1261
+ except AttributeError:
1262
+ pass
1263
+ try:
1264
+ # Tested with IPython 0.10.
1265
+ import IPython
1266
+ ipapi = IPython.ipapi.get()
1267
+ return ipapi.options.colors
1268
+ except AttributeError:
1269
+ pass
1270
+ import IPython
1271
+ raise RuntimeError(
1272
+ "Couldn't get IPython colors. "
1273
+ "Is your IPython version too old (or too new)? "
1274
+ "IPython.__version__=%r" % (IPython.__version__))
1275
+
1276
+
1277
+ def print_verbose_tb(*exc_info):
1278
+ """
1279
+ Print a traceback, using IPython's ultraTB if possible.
1280
+
1281
+ :param exc_info:
1282
+ 3 arguments as returned by sys.exc_info().
1283
+ """
1284
+ if not exc_info:
1285
+ exc_info = sys.exc_info()
1286
+ elif len(exc_info) == 1 and isinstance(exc_info[0], tuple):
1287
+ exc_info, = exc_info
1288
+ if len(exc_info) != 3:
1289
+ raise TypeError(
1290
+ "Expected 3 items for exc_info; got %d" % len(exc_info))
1291
+ try:
1292
+ # Tested with IPython 0.11, 0.12, 0.13, 1.0, 1.1, 1.2, 2.0, 2.1, 2.2,
1293
+ # 2.3, 2.4, 3.0, 3.1, 3.2, 4.0.
1294
+ from IPython.core.ultratb import VerboseTB
1295
+ except ImportError:
1296
+ try:
1297
+ # Tested with IPython 0.10.
1298
+ from IPython.ultraTB import VerboseTB
1299
+ except ImportError:
1300
+ VerboseTB = None
1301
+ exc_type, exc_value, exc_tb = exc_info
1302
+ # TODO: maybe use ip.showtraceback() instead?
1303
+ if VerboseTB is not None:
1304
+ VerboseTB(include_vars=False)(exc_type, exc_value, exc_tb)
1305
+ else:
1306
+ import traceback
1307
+ def red(x):
1308
+ return "\033[0m\033[31;1m%s\033[0m" % (x,)
1309
+ exc_name = exc_type
1310
+ try:
1311
+ exc_name = exc_name.__name__
1312
+ except AttributeError:
1313
+ pass
1314
+ exc_name = str(exc_name)
1315
+ print(red("---------------------------------------------------------------------------"))
1316
+ print(red(exc_name.ljust(42)) + "Traceback (most recent call last)")
1317
+ traceback.print_tb(exc_tb)
1318
+ print()
1319
+ print("%s: %s" % (red(exc_name), exc_value),
1320
+ file=sys.stderr)
1321
+ print()
1322
+
1323
+
1324
+ @contextmanager
1325
+ def UpdateIPythonStdioCtx():
1326
+ """
1327
+ Context manager that updates IPython's cached stdin/stdout/stderr handles
1328
+ to match the current values of sys.stdin/sys.stdout/sys.stderr.
1329
+ """
1330
+ if "IPython" not in sys.modules:
1331
+ yield
1332
+ return
1333
+
1334
+ import IPython
1335
+
1336
+ if IPython.version_info[:1] >= (8,):
1337
+ yield
1338
+ return
1339
+
1340
+ if "IPython.utils.io" in sys.modules:
1341
+ # Tested with IPython 0.11, 0.12, 0.13, 1.0, 1.1, 1.2, 2.0, 2.1, 2.2,
1342
+ # 2.3, 2.4, 3.0, 3.1, 3.2, 4.0.
1343
+ module = sys.modules["IPython.utils.io"]
1344
+ container = module
1345
+ IOStream = module.IOStream
1346
+ elif "IPython.genutils" in sys.modules:
1347
+ # Tested with IPython 0.10.
1348
+ module = sys.modules["IPython.genutils"]
1349
+ container = module.Term
1350
+ IOStream = module.IOStream
1351
+ else:
1352
+ # IPython version too old or too new?
1353
+ # For now just silently do nothing.
1354
+ yield
1355
+ return
1356
+ old_stdin = container.stdin
1357
+ old_stdout = container.stdout
1358
+ old_stderr = container.stderr
1359
+ try:
1360
+ container.stdin = IOStream(sys.stdin)
1361
+ container.stdout = IOStream(sys.stdout)
1362
+ container.stderr = IOStream(sys.stderr)
1363
+ yield
1364
+ finally:
1365
+ container.stdin = old_stdin
1366
+ container.stdout = old_stdout
1367
+ container.stderr = old_stderr
1368
+
1369
+
1370
+
1371
+ class _EnableState(object):
1372
+ DISABLING = "DISABLING"
1373
+ DISABLED = "DISABLED"
1374
+ ENABLING = "ENABLING"
1375
+ ENABLED = "ENABLED"
1376
+
1377
+
1378
+ class AutoImporter(object):
1379
+ """
1380
+ Auto importer enable state.
1381
+
1382
+ The state is attached to an IPython "application".
1383
+ """
1384
+
1385
+ def __new__(cls, arg=Ellipsis):
1386
+ """
1387
+ Get the AutoImporter for the given app, or create and assign one.
1388
+
1389
+ :type arg:
1390
+ `AutoImporter`, `BaseIPythonApplication`, `InteractiveShell`
1391
+ """
1392
+ if isinstance(arg, AutoImporter):
1393
+ return arg
1394
+ # Check the type of the arg. Avoid isinstance because it's so hard
1395
+ # to know where to import something from.
1396
+ # Todo: make this more robust.
1397
+ if arg is Ellipsis:
1398
+ app = _get_ipython_app()
1399
+ return cls._from_app(app)
1400
+ clsname = type(arg).__name__
1401
+ if "App" in clsname:
1402
+ return cls._from_app(arg)
1403
+ elif "Shell" in clsname:
1404
+ # If given an ``InteractiveShell`` argument, then get its parent app.
1405
+ # Tested with IPython 1.0, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0, 3.1,
1406
+ # 3.2, 4.0.
1407
+ if hasattr(arg, 'parent') and getattr(arg.parent, 'shell', None) is arg:
1408
+ app = arg.parent
1409
+ return cls._from_app(app)
1410
+ # Tested with IPython 0.10, 0.11, 0.12, 0.13.
1411
+ app = _get_ipython_app()
1412
+ if app.shell is arg:
1413
+ return cls._from_app(app)
1414
+ raise ValueError(
1415
+ "Got a shell instance %r but couldn't match it to an app"
1416
+ % (arg,))
1417
+ else:
1418
+ raise TypeError("AutoImporter(): unexpected %s" % (clsname,))
1419
+
1420
+ @classmethod
1421
+ def _from_app(cls, app):
1422
+ subapp = getattr(app, "subapp", None)
1423
+ if subapp is not None:
1424
+ app = subapp
1425
+ try:
1426
+ self = app.auto_importer
1427
+ except AttributeError:
1428
+ pass
1429
+ else:
1430
+ assert isinstance(self, cls)
1431
+ return self
1432
+ # Create a new instance and assign to the app.
1433
+ self = cls._construct(app)
1434
+ app.auto_importer = self
1435
+ return self
1436
+
1437
+ @classmethod
1438
+ def _construct(cls, app):
1439
+ """
1440
+ Create a new AutoImporter for ``app``.
1441
+
1442
+ :type app:
1443
+ `IPython.core.application.BaseIPythonApplication`
1444
+ """
1445
+ self = object.__new__(cls)
1446
+ self.app = app
1447
+ logger.debug("Constructing %r for app=%r, subapp=%r", self, app,
1448
+ getattr(app, "subapp", None))
1449
+ # Functions to call to disable the auto importer.
1450
+ self._disablers = []
1451
+ # Current enabling state.
1452
+ self._state = _EnableState.DISABLED
1453
+ # Whether there has been an error implying a bug in pyflyby code or a
1454
+ # problem with the import database.
1455
+ self._errored = False
1456
+ # A reference to the IPython shell object.
1457
+ self._ip = None
1458
+ # The AST transformer, if any (IPython 1.0+).
1459
+ self._ast_transformer = None
1460
+ # Dictionary of things we've attempted to autoimport for this cell.
1461
+ self._autoimported_this_cell = {}
1462
+ return self
1463
+
1464
+ def enable(self, even_if_previously_errored=False):
1465
+ """
1466
+ Turn on the auto-importer in the current IPython session.
1467
+ """
1468
+ # Check that we are not enabled/enabling yet.
1469
+ if self._state is _EnableState.DISABLED:
1470
+ pass
1471
+ elif self._state is _EnableState.ENABLED:
1472
+ logger.debug("Already enabled")
1473
+ return
1474
+ elif self._state is _EnableState.ENABLING:
1475
+ logger.debug("Already enabling")
1476
+ return
1477
+ elif self._state is _EnableState.DISABLING:
1478
+ logger.debug("Still disabling (run disable() to completion first)")
1479
+ return
1480
+ else:
1481
+ raise AssertionError
1482
+ self.reset_state_new_cell()
1483
+ # Check if previously errored.
1484
+ if self._errored:
1485
+ if even_if_previously_errored:
1486
+ self._errored = False
1487
+ else:
1488
+ # Be conservative: Once we've had problems, don't try again
1489
+ # this session. Exceptions in the interactive loop can be
1490
+ # annoying to deal with.
1491
+ logger.warning(
1492
+ "Not reattempting to enable auto importer after earlier "
1493
+ "error")
1494
+ return
1495
+ import IPython
1496
+ logger.debug("Enabling auto importer for IPython version %s, pid=%r",
1497
+ IPython.__version__, os.getpid())
1498
+ logger.debug("enable(): state %s=>ENABLING", self._state)
1499
+ self._errored = False
1500
+ self._state = _EnableState.ENABLING
1501
+ self._safe_call(self._enable_internal)
1502
+
1503
+ def _continue_enable(self):
1504
+ if self._state != _EnableState.ENABLING:
1505
+ logger.debug("_enable_internal(): state = %s", self._state)
1506
+ return
1507
+ logger.debug("Continuing enabling auto importer")
1508
+ self._safe_call(self._enable_internal)
1509
+
1510
+ def _enable_internal(self):
1511
+ # Main enabling entry point. This function can get called multiple
1512
+ # times, depending on what's been initialized so far.
1513
+ app = self.app
1514
+ assert app is not None
1515
+ if getattr(app, "subapp", None) is not None:
1516
+ app = app.subapp
1517
+ self.app = app
1518
+ logger.debug("app = %r", app)
1519
+ ok = True
1520
+ ok &= self._enable_ipython_bugfixes()
1521
+ ok &= self._enable_initializer_hooks(app)
1522
+ ok &= self._enable_kernel_manager_hook(app)
1523
+ ok &= self._enable_shell_hooks(app)
1524
+ if ok:
1525
+ logger.debug("_enable_internal(): success! state: %s=>ENABLED",
1526
+ self._state)
1527
+ self._state = _EnableState.ENABLED
1528
+ elif self._pending_initializers:
1529
+ logger.debug("_enable_internal(): did what we can for now; "
1530
+ "will enable more after further IPython initialization. "
1531
+ "state=%s", self._state)
1532
+ else:
1533
+ logger.debug("_enable_internal(): did what we can, but not "
1534
+ "fully successful. state: %s=>ENABLED",
1535
+ self._state)
1536
+ self._state = _EnableState.ENABLED
1537
+
1538
+ def _enable_initializer_hooks(self, app):
1539
+ # Hook initializers. There are various things we want to hook, and
1540
+ # the hooking needs to be done at different times, depending on the
1541
+ # IPython version and the "app". For example, for most versions of
1542
+ # IPython, terminal app, many things need to be done after
1543
+ # initialize()/init_shell(); on the other hand, in some cases
1544
+ # (e.g. IPython console), we need to do stuff *inside* the
1545
+ # initialization function.
1546
+ # Thus, we take a brute force approach: add hooks to a bunch of
1547
+ # places, if they seem to not have run yet, and each time add any
1548
+ # hooks that are ready to be added.
1549
+ ok = True
1550
+ pending = False
1551
+ ip = getattr(app, "shell", None)
1552
+ if ip is None:
1553
+ if hasattr(app, "init_shell"):
1554
+ @self._advise(app.init_shell)
1555
+ def init_shell_enable_auto_importer():
1556
+ __original__()
1557
+ logger.debug("init_shell() completed")
1558
+ ip = app.shell
1559
+ if ip is None:
1560
+ logger.debug("Aborting enabling AutoImporter: "
1561
+ "even after init_shell(), "
1562
+ "still no shell in app=%r", app)
1563
+ return
1564
+ self._continue_enable()
1565
+ elif not hasattr(app, "shell") and hasattr(app, "kernel_manager"):
1566
+ logger.debug("No shell applicable; ok because using kernel manager")
1567
+ pass
1568
+ else:
1569
+ logger.debug("App shell missing and no init_shell() to advise")
1570
+ ok = False
1571
+ if hasattr(app, "initialize_subcommand"):
1572
+ # Hook the subapp, if any. This requires some cleverness:
1573
+ # 'ipython console' requires us to do some stuff *before*
1574
+ # initialize() is called on the new app, while 'ipython
1575
+ # notebook' requires us to do stuff *after* initialize() is
1576
+ # called.
1577
+ @self._advise(app.initialize_subcommand)
1578
+ def init_subcmd_enable_auto_importer(*args, **kwargs):
1579
+ logger.debug("initialize_subcommand()")
1580
+ from IPython.core.application import Application
1581
+ @advise((Application, "instance"))
1582
+ def app_instance_enable_auto_importer(cls, *args, **kwargs):
1583
+ logger.debug("%s.instance()", cls.__name__)
1584
+ app = __original__(cls, *args, **kwargs)
1585
+ if app != self.app:
1586
+ self.app = app
1587
+ self._continue_enable()
1588
+ return app
1589
+ try:
1590
+ __original__(*args, **kwargs)
1591
+ finally:
1592
+ app_instance_enable_auto_importer.unadvise()
1593
+ self._continue_enable()
1594
+ pending = True
1595
+ if (hasattr(ip, "post_config_initialization") and
1596
+ not hasattr(ip, "rl_next_input")):
1597
+ # IPython 0.10 might not be ready to hook yet because we're called
1598
+ # from the config phase, and certain stuff (like Completer) is set
1599
+ # up in post-config. Re-run after post_config_initialization.
1600
+ # Kludge: post_config_initialization() sets ip.rl_next_input=None,
1601
+ # so detect whether it's been run by checking for that attribute.
1602
+ @self._advise(ip.post_config_initialization)
1603
+ def post_config_enable_auto_importer():
1604
+ __original__()
1605
+ logger.debug("post_config_initialization() completed")
1606
+ if not hasattr(ip, "rl_next_input"):
1607
+ # Post-config initialization failed?
1608
+ return
1609
+ self._continue_enable()
1610
+ pending = True
1611
+ self._pending_initializers = pending
1612
+ return ok
1613
+
1614
+ def _enable_kernel_manager_hook(self, app):
1615
+ # For IPython notebook, by the time we get here, there's generally a
1616
+ # kernel_manager already assigned, but kernel_manager.start_kernel()
1617
+ # hasn't been called yet. Hook app.kernel_manager.start_kernel().
1618
+ kernel_manager = getattr(app, "kernel_manager", None)
1619
+ ok = True
1620
+ if kernel_manager is not None:
1621
+ ok &= self._enable_start_kernel_hook(kernel_manager)
1622
+ # For IPython console, a single function constructs the kernel_manager
1623
+ # and then immediately calls kernel_manager.start_kernel(). The
1624
+ # easiest way to intercept start_kernel() is by installing a hook
1625
+ # after the kernel_manager is constructed.
1626
+ if getattr(app, "kernel_manager_class", None) is not None:
1627
+ @self._advise((app, "kernel_manager_class"))
1628
+ def kernel_manager_class_with_autoimport(*args, **kwargs):
1629
+ logger.debug("kernel_manager_class_with_autoimport()")
1630
+ kernel_manager = __original__(*args, **kwargs)
1631
+ self._enable_start_kernel_hook(kernel_manager)
1632
+ return kernel_manager
1633
+ # It's OK if no kernel_manager nor kernel_manager_class; this is the
1634
+ # typical case, when using regular IPython terminal console (not
1635
+ # IPython notebook/console).
1636
+ return True
1637
+
1638
+ def _enable_start_kernel_hook(self, kernel_manager):
1639
+ # Various IPython versions have different 'main' commands called from
1640
+ # here, e.g.
1641
+ # IPython 2: IPython.kernel.zmq.kernelapp.main
1642
+ # IPython 3: IPython.kernel.__main__
1643
+ # IPython 4: ipykernel.__main__
1644
+ # These essentially all do 'kernelapp.launch_new_instance()' (imported
1645
+ # from different places). We hook the guts of that to enable the
1646
+ # autoimporter.
1647
+ new_cmd = [
1648
+ '-c',
1649
+ 'from pyflyby._interactive import start_ipython_kernel_with_autoimporter; '
1650
+ 'start_ipython_kernel_with_autoimporter()'
1651
+ ]
1652
+ try:
1653
+ # Tested with Jupyter/IPython 4.0
1654
+ from jupyter_client.manager import KernelManager as JupyterKernelManager
1655
+ except ImportError:
1656
+ pass
1657
+ else:
1658
+ @self._advise(kernel_manager.start_kernel)
1659
+ def start_kernel_with_autoimport_jupyter(*args, **kwargs):
1660
+ logger.debug("start_kernel()")
1661
+ # Advise format_kernel_cmd(), which is the function that
1662
+ # computes the command line for a subprocess to run a new
1663
+ # kernel. Note that we advise the method on the class, rather
1664
+ # than this instance of kernel_manager, because start_kernel()
1665
+ # actually creates a *new* KernelInstance for this.
1666
+ @advise(JupyterKernelManager.format_kernel_cmd)
1667
+ def format_kernel_cmd_with_autoimport(*args, **kwargs):
1668
+ result = __original__(*args, **kwargs)
1669
+ logger.debug("intercepting format_kernel_cmd(): orig = %r", result)
1670
+ if (len(result) >= 3 and
1671
+ result[1] == '-m' and
1672
+ result[2] in ['ipykernel', 'ipykernel_launcher']):
1673
+ result[1:3] = new_cmd
1674
+ logger.debug("intercepting format_kernel_cmd(): new = %r", result)
1675
+ return result
1676
+ else:
1677
+ logger.debug("intercepting format_kernel_cmd(): unexpected output; not modifying it")
1678
+ return result
1679
+ try:
1680
+ return __original__(*args, **kwargs)
1681
+ finally:
1682
+ format_kernel_cmd_with_autoimport.unadvise()
1683
+ return True
1684
+ try:
1685
+ # Tested with IPython 1.0, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0, 3.1,
1686
+ # 3.2.
1687
+ from IPython.kernel.manager import KernelManager as IPythonKernelManager
1688
+ except ImportError:
1689
+ pass
1690
+ else:
1691
+ @self._advise(kernel_manager.start_kernel)
1692
+ def start_kernel_with_autoimport_ipython(*args, **kwargs):
1693
+ logger.debug("start_kernel()")
1694
+ # Advise format_kernel_cmd(), which is the function that
1695
+ # computes the command line for a subprocess to run a new
1696
+ # kernel. Note that we advise the method on the class, rather
1697
+ # than this instance of kernel_manager, because start_kernel()
1698
+ # actually creates a *new* KernelInstance for this.
1699
+ @advise(IPythonKernelManager.format_kernel_cmd)
1700
+ def format_kernel_cmd_with_autoimport(*args, **kwargs):
1701
+ result = __original__(*args, **kwargs)
1702
+ logger.debug("intercepting format_kernel_cmd(): orig = %r", result)
1703
+ if result[1:3] in [
1704
+ # IPython 3.x
1705
+ ['-m', 'IPython.kernel'],
1706
+ # IPython 1.x, 2.x
1707
+ ['-c', 'from IPython.kernel.zmq.kernelapp import main; main()'],
1708
+ ]:
1709
+ result[1:3] = new_cmd
1710
+ logger.debug("intercepting format_kernel_cmd(): new = %r", result)
1711
+ return result
1712
+ else:
1713
+ logger.debug("intercepting format_kernel_cmd(): unexpected output; not modifying it")
1714
+ return result
1715
+ try:
1716
+ return __original__(*args, **kwargs)
1717
+ finally:
1718
+ format_kernel_cmd_with_autoimport.unadvise()
1719
+ return True
1720
+ # Tested with IPython 0.12, 0.13
1721
+ try:
1722
+ import IPython.zmq.ipkernel
1723
+ except ImportError:
1724
+ pass
1725
+ else:
1726
+ @self._advise(kernel_manager.start_kernel)
1727
+ def start_kernel_with_autoimport013(*args, **kwargs):
1728
+ logger.debug("start_kernel()")
1729
+ @advise((IPython.zmq.ipkernel, 'base_launch_kernel'))
1730
+ def base_launch_kernel_with_autoimport(cmd, *args, **kwargs):
1731
+ logger.debug("base_launch_kernel()")
1732
+ expected_cmd = 'from IPython.zmq.ipkernel import main; main()'
1733
+ if cmd != expected_cmd:
1734
+ logger.debug("unexpected command, not modifying it: %r", cmd)
1735
+ else:
1736
+ cmd = (
1737
+ 'from pyflyby._interactive import start_ipython_kernel_with_autoimporter; '
1738
+ 'start_ipython_kernel_with_autoimporter()')
1739
+ return __original__(cmd, *args, **kwargs)
1740
+ try:
1741
+ return __original__(*args, **kwargs)
1742
+ finally:
1743
+ base_launch_kernel_with_autoimport.unadvise()
1744
+ return True
1745
+ logger.debug("Couldn't enable start_kernel hook")
1746
+ return False
1747
+
1748
+ def _enable_shell_hooks(self, app):
1749
+ """
1750
+ Enable hooks to run auto_import before code execution.
1751
+ """
1752
+ # Check again in case this was registered delayed
1753
+ if self._state != _EnableState.ENABLING:
1754
+ return False
1755
+ try:
1756
+ ip = app.shell
1757
+ except AttributeError:
1758
+ logger.debug("_enable_shell_hooks(): no shell at all")
1759
+ return True
1760
+ if ip is None:
1761
+ logger.debug("_enable_shell_hooks(): no shell yet")
1762
+ return False
1763
+ logger.debug("Enabling IPython shell hooks, shell=%r", ip)
1764
+ self._ip = ip
1765
+ # Notes on why we hook what we hook:
1766
+ #
1767
+ # There are many different places within IPython we can consider
1768
+ # hooking/advising, depending on the version:
1769
+ # * ip.input_transformer_manager.logical_line_transforms
1770
+ # * ip.compile.ast_parse (IPython 0.12+)
1771
+ # * ip.run_ast_nodes (IPython 0.11+)
1772
+ # * ip.runsource (IPython 0.10)
1773
+ # * ip.prefilter_manager.checks
1774
+ # * ip.prefilter_manager.handlers["auto"]
1775
+ # * ip.ast_transformers
1776
+ # * ip.hooks['pre_run_code_hook']
1777
+ # * ip._ofind
1778
+ #
1779
+ # We choose to hook in two places: (1) _ofind and (2)
1780
+ # ast_transformers. The motivation follows. We want to handle
1781
+ # auto-imports for all of these input cases:
1782
+ # (1) "foo.bar"
1783
+ # (2) "arbitrarily_complicated_stuff((lambda: foo.bar)())"
1784
+ # (3) "foo.bar?", "foo.bar??" (pinfo/pinfo2)
1785
+ # (4) "foo.bar 1, 2" => "foo.bar(1, 2)" (autocall)
1786
+ #
1787
+ # Case 1 is the easiest and can be handled by nearly any method. Case
1788
+ # 2 must be done either as a prefilter or as an AST transformer.
1789
+ # Cases 3 and 4 must be done either as an input line transformer or by
1790
+ # monkey-patching _ofind, because by the time the
1791
+ # prefilter/ast_transformer is called, it's too late.
1792
+ #
1793
+ # To handle case 2, we use an AST transformer (for IPython > 1.0), or
1794
+ # monkey-patch one of the compilation steps (ip.compile for IPython
1795
+ # 0.10 and ip.run_ast_nodes for IPython 0.11-0.13).
1796
+ # prefilter_manager.checks() is the "supported" way to add a
1797
+ # pre-execution hook, but it only works for single lines, not for
1798
+ # multi-line cells. (There is no explanation in the IPython source
1799
+ # for why prefilter hooks are seemingly intentionally skipped for
1800
+ # multi-line cells).
1801
+ #
1802
+ # To handle cases 3/4 (pinfo/autocall), we choose to advise _ofind.
1803
+ # This is a private function that is called by both pinfo and autocall
1804
+ # code paths. (Alternatively, we could have added something to the
1805
+ # logical_line_transforms. The downside of that is that we would need
1806
+ # to re-implement all the parsing perfectly matching IPython.
1807
+ # Although monkey-patching is in general bad, it seems the lesser of
1808
+ # the two evils in this case.)
1809
+ #
1810
+ # Since we have two invocations of auto_import(), case 1 is
1811
+ # handled twice. That's fine, because it runs quickly.
1812
+ ok = True
1813
+ ok &= self._enable_reset_hook(ip)
1814
+ ok &= self._enable_ofind_hook(ip)
1815
+ ok &= self._enable_ast_hook(ip)
1816
+ ok &= self._enable_time_hook(ip)
1817
+ ok &= self._enable_timeit_hook(ip)
1818
+ ok &= self._enable_prun_hook(ip)
1819
+ ok &= self._enable_completion_hook(ip)
1820
+ ok &= self._enable_run_hook(ip)
1821
+ ok &= self._enable_debugger_hook(ip)
1822
+ ok &= self._enable_ipython_shell_bugfixes(ip)
1823
+ return ok
1824
+
1825
+ def _enable_reset_hook(self, ip):
1826
+ # Register a hook that resets autoimporter state per input cell.
1827
+ # The only per-input-cell state we currently have is the recording of
1828
+ # which autoimports we've attempted but failed. We keep track of this
1829
+ # to avoid multiple error messages for a single import, in case of
1830
+ # overlapping hooks.
1831
+ # Note: Some of the below approaches (both registering an
1832
+ # input_transformer_manager hook or advising reset()) cause the reset
1833
+ # function to get called twice per cell. This seems like an
1834
+ # unintentional repeated call in IPython itself. This is harmless for
1835
+ # us, since doing an extra reset shouldn't hurt.
1836
+ if hasattr(ip, "input_transformers_post"):
1837
+ # In IPython 7.0+, the input transformer API changed.
1838
+ def reset_auto_importer_state(line):
1839
+ # There is a bug in IPython that causes the transformer to be
1840
+ # called multiple times
1841
+ # (https://github.com/ipython/ipython/issues/11714). Until it
1842
+ # is fixed, workaround it by skipping one of the calls.
1843
+ stack = inspect.stack()
1844
+ if any([
1845
+ stack[3].function == 'run_cell_async',
1846
+ # These are the other places it is called.
1847
+ # stack[3].function == 'should_run_async',
1848
+ # stack[1].function == 'check_complete'
1849
+ ]):
1850
+ return line
1851
+ logger.debug("reset_auto_importer_state(%r)", line)
1852
+ self.reset_state_new_cell()
1853
+ return line
1854
+ # on IPython 7.17 (July 2020) or above, the check_complete
1855
+ # path of the code will not call transformer that have this magic attribute
1856
+ # when trying to check whether the code is complete.
1857
+ reset_auto_importer_state.has_side_effect = True
1858
+ ip.input_transformers_cleanup.append(reset_auto_importer_state)
1859
+ return True
1860
+ elif hasattr(ip, "input_transformer_manager"):
1861
+ # Tested with IPython 1.0, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0, 3.1,
1862
+ # 3.2, 4.0.
1863
+ class ResetAutoImporterState(object):
1864
+ def push(self_, line):
1865
+ return line
1866
+ def reset(self_):
1867
+ logger.debug("ResetAutoImporterState.reset()")
1868
+ self.reset_state_new_cell()
1869
+ t = ResetAutoImporterState()
1870
+ transforms = ip.input_transformer_manager.python_line_transforms
1871
+ transforms.append(t)
1872
+ def unregister_input_transformer():
1873
+ try:
1874
+ transforms.remove(t)
1875
+ except ValueError:
1876
+ logger.info(
1877
+ "Couldn't remove python_line_transformer hook")
1878
+ self._disablers.append(unregister_input_transformer)
1879
+ return True
1880
+ elif hasattr(ip, "input_splitter"):
1881
+ # Tested with IPython 0.13. Also works with later versions, but
1882
+ # for those versions, we can use a real hook instead of advising.
1883
+ @self._advise(ip.input_splitter.reset)
1884
+ def reset_input_splitter_and_autoimporter_state():
1885
+ logger.debug("reset_input_splitter_and_autoimporter_state()")
1886
+ self.reset_state_new_cell()
1887
+ return __original__()
1888
+ return True
1889
+ elif hasattr(ip, "resetbuffer"):
1890
+ # Tested with IPython 0.10.
1891
+ @self._advise(ip.resetbuffer)
1892
+ def resetbuffer_and_autoimporter_state():
1893
+ logger.debug("resetbuffer_and_autoimporter_state")
1894
+ self.reset_state_new_cell()
1895
+ return __original__()
1896
+ return True
1897
+ else:
1898
+ logger.debug("Couldn't enable reset hook")
1899
+ return False
1900
+
1901
+ def _enable_ofind_hook(self, ip):
1902
+ """
1903
+ Enable a hook of _ofind(), which is used for pinfo, autocall, etc.
1904
+ """
1905
+ # Advise _ofind.
1906
+ if hasattr(ip, "_ofind"):
1907
+ # Tested with IPython 0.10, 0.11, 0.12, 0.13, 1.0, 1.2, 2.0, 2.3,
1908
+ # 2.4, 3.0, 3.1, 3.2, 4.0.
1909
+ @self._advise(ip._ofind)
1910
+ def ofind_with_autoimport(oname, namespaces=None):
1911
+ logger.debug("_ofind(oname=%r, namespaces=%r)", oname, namespaces)
1912
+ is_multiline = False
1913
+ if hasattr(ip, "buffer"):
1914
+ # In IPython 0.10, _ofind() gets called for each line of a
1915
+ # multiline input. Skip them.
1916
+ is_multiline = len(ip.buffer) > 0
1917
+ if namespaces is None:
1918
+ namespaces = _ipython_namespaces(ip)
1919
+ is_network_request = False
1920
+ frame = inspect.currentframe()
1921
+ # jupyter_lab_completer seem to send inspect request when
1922
+ # cycling through completions which trigger import.
1923
+ # We cannot differentiate those from actual inspect when
1924
+ # clicking on an object.
1925
+ # So for now when we see the inspect request comes from
1926
+ # ipykernel, we just don't autoimport
1927
+ while frame is not None:
1928
+ if "ipykernel/ipkernel.py" in inspect.getframeinfo(frame).filename:
1929
+ is_network_request = True
1930
+ break
1931
+ frame = frame.f_back
1932
+ if (
1933
+ not is_multiline
1934
+ and is_identifier(oname, dotted=True)
1935
+ and not is_network_request
1936
+ ):
1937
+ self.auto_import(
1938
+ str(oname), [ns for nsname, ns in namespaces][::-1]
1939
+ )
1940
+ result = __original__(oname, namespaces=namespaces)
1941
+ return result
1942
+ return True
1943
+ else:
1944
+ logger.debug("Couldn't enable ofind hook")
1945
+ return False
1946
+
1947
+ def _enable_ast_hook(self, ip):
1948
+ """
1949
+ Enable a hook somewhere in the source => parsed AST => compiled code
1950
+ pipeline.
1951
+ """
1952
+ # Register an AST transformer.
1953
+ if hasattr(ip, 'ast_transformers'):
1954
+ logger.debug("Registering an ast_transformer")
1955
+ # First choice: register a formal ast_transformer.
1956
+ # Tested with IPython 1.0, 1.2, 2.0, 2.3, 2.4, 3.0, 3.1, 3.2, 4.0.
1957
+ class _AutoImporter_ast_transformer(object):
1958
+ """
1959
+ A NodeVisitor-like wrapper around ``auto_import_for_ast`` for
1960
+ the API that IPython 1.x's ``ast_transformers`` needs.
1961
+ """
1962
+ def visit(self_, node):
1963
+ # We don't actually transform the node; we just use
1964
+ # the ast_transformers mechanism instead of the
1965
+ # prefilter mechanism as an optimization to avoid
1966
+ # re-parsing the text into an AST.
1967
+ #
1968
+ # We use raise_on_error=False to avoid propagating any
1969
+ # exceptions here. That would cause IPython to try to
1970
+ # remove the ast_transformer. On error, we've already
1971
+ # done that ourselves.
1972
+ logger.debug("_AutoImporter_ast_transformer.visit()")
1973
+ self.auto_import(node, raise_on_error=False)
1974
+ return node
1975
+ self._ast_transformer = t = _AutoImporter_ast_transformer()
1976
+ ip.ast_transformers.append(t)
1977
+ def unregister_ast_transformer():
1978
+ try:
1979
+ ip.ast_transformers.remove(t)
1980
+ except ValueError:
1981
+ logger.info(
1982
+ "Couldn't remove ast_transformer hook - already gone?")
1983
+ self._ast_transformer = None
1984
+ self._disablers.append(unregister_ast_transformer)
1985
+ return True
1986
+ elif hasattr(ip, "run_ast_nodes"):
1987
+ # Second choice: advise the run_ast_nodes() function. Tested with
1988
+ # IPython 0.11, 0.12, 0.13. This is the most robust way available
1989
+ # for those versions.
1990
+ # (ip.compile.ast_parse also works in IPython 0.12-0.13; no major
1991
+ # flaw, but might as well use the same mechanism that works in
1992
+ # 0.11.)
1993
+ @self._advise(ip.run_ast_nodes)
1994
+ def run_ast_nodes_with_autoimport(nodelist, *args, **kwargs):
1995
+ logger.debug("run_ast_nodes")
1996
+ ast_node = ast.Module(nodelist)
1997
+ self.auto_import(ast_node)
1998
+ return __original__(nodelist, *args, **kwargs)
1999
+ return True
2000
+ elif hasattr(ip, 'compile'):
2001
+ # Third choice: Advise ip.compile.
2002
+ # Tested with IPython 0.10.
2003
+ # We don't hook prefilter because that gets called once per line,
2004
+ # not per multiline code.
2005
+ # We don't hook runsource because that gets called incrementally
2006
+ # with partial multiline source until the source is complete.
2007
+ @self._advise((ip, "compile"))
2008
+ def compile_with_autoimport(source, filename="<input>",
2009
+ symbol="single"):
2010
+ result = __original__(source, filename, symbol)
2011
+ if result is None:
2012
+ # The original ip.compile is an instance of
2013
+ # codeop.CommandCompiler. CommandCompiler.__call__
2014
+ # returns None if the source is a possibly incomplete
2015
+ # multiline block of code. In that case we don't
2016
+ # autoimport yet.
2017
+ pass
2018
+ else:
2019
+ # Got full code that our caller, runsource, will execute.
2020
+ self.auto_import(source)
2021
+ return result
2022
+ return True
2023
+ else:
2024
+ logger.debug("Couldn't enable parse hook")
2025
+ return False
2026
+
2027
+ def _enable_time_hook(self, ip):
2028
+ """
2029
+ Enable a hook so that %time will autoimport.
2030
+ """
2031
+ # For IPython 1.0+, the ast_transformer takes care of it.
2032
+ if self._ast_transformer:
2033
+ return True
2034
+ # Otherwise, we advise %time to temporarily override the compile()
2035
+ # builtin within it.
2036
+ if hasattr(ip, 'magics_manager'):
2037
+ # Tested with IPython 0.13. (IPython 1.0+ also has
2038
+ # magics_manager, but for those versions, ast_transformer takes
2039
+ # care of %time.)
2040
+ line_magics = ip.magics_manager.magics['line']
2041
+ @self._advise((line_magics, 'time'))
2042
+ def time_with_autoimport(*args, **kwargs):
2043
+ logger.debug("time_with_autoimport()")
2044
+ wrapped = FunctionWithGlobals(
2045
+ __original__, compile=self.compile_with_autoimport)
2046
+ return wrapped(*args, **kwargs)
2047
+ return True
2048
+ elif hasattr(ip, 'magic_time'):
2049
+ # Tested with IPython 0.10, 0.11, 0.12
2050
+ @self._advise(ip.magic_time)
2051
+ def magic_time_with_autoimport(*args, **kwargs):
2052
+ logger.debug("time_with_autoimport()")
2053
+ wrapped = FunctionWithGlobals(
2054
+ __original__, compile=self.compile_with_autoimport)
2055
+ return wrapped(*args, **kwargs)
2056
+ return True
2057
+ else:
2058
+ logger.debug("Couldn't enable time hook")
2059
+ return False
2060
+
2061
+ def _enable_timeit_hook(self, ip):
2062
+ """
2063
+ Enable a hook so that %timeit will autoimport.
2064
+ """
2065
+ # For IPython 1.0+, the ast_transformer takes care of it.
2066
+ if self._ast_transformer:
2067
+ return True
2068
+ # Otherwise, we advise %timeit to temporarily override the compile()
2069
+ # builtin within it.
2070
+ if hasattr(ip, 'magics_manager'):
2071
+ # Tested with IPython 0.13. (IPython 1.0+ also has
2072
+ # magics_manager, but for those versions, ast_transformer takes
2073
+ # care of %timeit.)
2074
+ line_magics = ip.magics_manager.magics['line']
2075
+ @self._advise((line_magics, 'timeit'))
2076
+ def timeit_with_autoimport(*args, **kwargs):
2077
+ logger.debug("timeit_with_autoimport()")
2078
+ wrapped = FunctionWithGlobals(
2079
+ __original__, compile=self.compile_with_autoimport)
2080
+ return wrapped(*args, **kwargs)
2081
+ return True
2082
+ elif hasattr(ip, 'magic_timeit'):
2083
+ # Tested with IPython 0.10, 0.11, 0.12
2084
+ @self._advise(ip.magic_timeit)
2085
+ def magic_timeit_with_autoimport(*args, **kwargs):
2086
+ logger.debug("timeit_with_autoimport()")
2087
+ wrapped = FunctionWithGlobals(
2088
+ __original__, compile=self.compile_with_autoimport)
2089
+ return wrapped(*args, **kwargs)
2090
+ return True
2091
+ else:
2092
+ logger.debug("Couldn't enable timeit hook")
2093
+ return False
2094
+
2095
+ def _enable_prun_hook(self, ip):
2096
+ """
2097
+ Enable a hook so that %prun will autoimport.
2098
+ """
2099
+ if hasattr(ip, 'magics_manager'):
2100
+ # Tested with IPython 1.0, 1.1, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0,
2101
+ # 3.1, 3.2, 4.0.
2102
+ line_magics = ip.magics_manager.magics['line']
2103
+ execmgr = get_method_self(line_magics['prun'])#.im_self
2104
+ if hasattr(execmgr, "_run_with_profiler"):
2105
+ @self._advise(execmgr._run_with_profiler)
2106
+ def run_with_profiler_with_autoimport(code, opts, namespace):
2107
+ logger.debug("run_with_profiler_with_autoimport()")
2108
+ self.auto_import(code, [namespace])
2109
+ return __original__(code, opts, namespace)
2110
+ return True
2111
+ else:
2112
+ # Tested with IPython 0.13.
2113
+ class ProfileFactory_with_autoimport(object):
2114
+ def Profile(self_, *args):
2115
+ import profile
2116
+ p = profile.Profile()
2117
+ @advise(p.runctx)
2118
+ def runctx_with_autoimport(cmd, globals, locals):
2119
+ self.auto_import(cmd, [globals, locals])
2120
+ return __original__(cmd, globals, locals)
2121
+ return p
2122
+ @self._advise((line_magics, 'prun'))
2123
+ def prun_with_autoimport(*args, **kwargs):
2124
+ logger.debug("prun_with_autoimport()")
2125
+ wrapped = FunctionWithGlobals(
2126
+ __original__, profile=ProfileFactory_with_autoimport())
2127
+ return wrapped(*args, **kwargs)
2128
+ return True
2129
+ elif hasattr(ip, "magic_prun"):
2130
+ # Tested with IPython 0.10, 0.11, 0.12.
2131
+ class ProfileFactory_with_autoimport(object):
2132
+ def Profile(self_, *args):
2133
+ import profile
2134
+ p = profile.Profile()
2135
+ @advise(p.runctx)
2136
+ def runctx_with_autoimport(cmd, globals, locals):
2137
+ self.auto_import(cmd, [globals, locals])
2138
+ return __original__(cmd, globals, locals)
2139
+ return p
2140
+ @self._advise(ip.magic_prun)
2141
+ def magic_prun_with_autoimport(*args, **kwargs):
2142
+ logger.debug("magic_prun_with_autoimport()")
2143
+ wrapped = FunctionWithGlobals(
2144
+ __original__, profile=ProfileFactory_with_autoimport())
2145
+ return wrapped(*args, **kwargs)
2146
+ return True
2147
+ else:
2148
+ logger.debug("Couldn't enable prun hook")
2149
+ return False
2150
+
2151
+ def _enable_completer_hooks(self, completer):
2152
+ # Hook a completer instance.
2153
+ #
2154
+ # This is called:
2155
+ # - initially when enabling pyflyby
2156
+ # - each time we enter the debugger, since each Pdb instance has its
2157
+ # own completer
2158
+ #
2159
+ # There are a few different places within IPython we can consider
2160
+ # hooking/advising:
2161
+ # * ip.completer.custom_completers / ip.set_hook("complete_command")
2162
+ # * ip.completer.python_matches
2163
+ # * ip.completer.global_matches
2164
+ # * ip.completer.attr_matches
2165
+ # * ip.completer.python_func_kw_matches
2166
+ #
2167
+ # The "custom_completers" list, which set_hook("complete_command")
2168
+ # manages, is not useful because that only works for specific commands.
2169
+ # (A "command" refers to the first word on a line, such as "cd".)
2170
+ #
2171
+ # We choose to advise global_matches() and attr_matches(), which are
2172
+ # called to enumerate global and non-global attribute symbols
2173
+ # respectively. (python_matches() calls these two. We advise
2174
+ # global_matches() and attr_matches() instead of python_matches()
2175
+ # because a few other functions call global_matches/attr_matches
2176
+ # directly.)
2177
+ logger.debug("_enable_completer_hooks(%r)", completer)
2178
+ if hasattr(completer, "global_matches"):
2179
+ # Tested with IPython 0.10, 0.11, 0.12, 0.13, 1.0, 1.2, 2.0, 2.3,
2180
+ # 2.4, 3.0, 3.1, 3.2, 4.0, 5.8.
2181
+ try:
2182
+ completer.shell.pt_cli
2183
+ is_pt = True
2184
+ except AttributeError:
2185
+ is_pt = False
2186
+ if is_pt:
2187
+ def get_completer_namespaces():
2188
+ return [completer.namespace, completer.global_namespace]
2189
+ else:
2190
+ def get_completer_namespaces():
2191
+ # For non-prompt_toolkit, (1) completer.namespace is not
2192
+ # reliable inside pdb, and (2) _get_pdb_if_is_in_pdb() is
2193
+ # reliable inside pdb because no threading.
2194
+ # Use get_global_namespaces(), which relies on
2195
+ # _get_pdb_if_is_in_pdb().
2196
+ return None
2197
+ if getattr(completer, 'use_jedi', False):
2198
+ # IPython 6.0+ uses jedi completion by default, which bypasses
2199
+ # the global and attr matchers. For now we manually reenable
2200
+ # them. A TODO would be to hook the Jedi completer itself.
2201
+ if completer.python_matches not in completer.matchers:
2202
+ @self._advise(type(completer).matchers)
2203
+ def matchers_with_python_matches(completer):
2204
+ return __original__.fget(completer)+[completer.python_matches]
2205
+
2206
+ @self._advise(completer.global_matches)
2207
+ def global_matches_with_autoimport(fullname):
2208
+ if len(fullname) == 0:
2209
+ return []
2210
+ logger.debug("global_matches_with_autoimport(%r)", fullname)
2211
+ namespaces = get_completer_namespaces()
2212
+ return self.complete_symbol(fullname, namespaces, on_error=__original__)
2213
+ @self._advise(completer.attr_matches)
2214
+ def attr_matches_with_autoimport(fullname):
2215
+ logger.debug("attr_matches_with_autoimport(%r)", fullname)
2216
+ namespaces = get_completer_namespaces()
2217
+ return self.complete_symbol(fullname, namespaces, on_error=__original__)
2218
+
2219
+ return True
2220
+ elif hasattr(completer, "complete_request"):
2221
+ # This is a ZMQCompleter, so nothing to do.
2222
+ return True
2223
+ else:
2224
+ logger.debug("Couldn't enable completion hook")
2225
+ return False
2226
+
2227
+ def _enable_completion_hook(self, ip):
2228
+ """
2229
+ Enable a tab-completion hook.
2230
+ """
2231
+ return self._enable_completer_hooks(getattr(ip, "Completer", None))
2232
+
2233
+ def _enable_run_hook(self, ip):
2234
+ """
2235
+ Enable a hook so that %run will autoimport.
2236
+ """
2237
+ if hasattr(ip, "safe_execfile"):
2238
+ # Tested with IPython 0.10, 0.11, 0.12, 0.13, 1.0, 1.2, 2.0, 2.3,
2239
+ # 2.4, 3.0, 3.1, 3.2, 4.0.
2240
+ @self._advise(ip.safe_execfile)
2241
+ def safe_execfile_with_autoimport(filename,
2242
+ globals=None, locals=None,
2243
+ **kwargs):
2244
+ logger.debug("safe_execfile %r", filename)
2245
+ if globals is None:
2246
+ globals = {}
2247
+ if locals is None:
2248
+ locals = globals
2249
+ namespaces = [globals, locals]
2250
+ try:
2251
+ block = PythonBlock(Filename(filename))
2252
+ ast_node = block.ast_node
2253
+ self.auto_import(ast_node, namespaces)
2254
+ except Exception as e:
2255
+ logger.error("%s: %s", type(e).__name__, e)
2256
+ return __original__(filename, *namespaces, **kwargs)
2257
+ return True
2258
+ else:
2259
+ logger.debug("Couldn't enable execfile hook")
2260
+ return False
2261
+
2262
+ def _enable_debugger_hook(self, ip):
2263
+ try:
2264
+ Pdb = _get_IPdb_class()
2265
+ except Exception as e:
2266
+ logger.debug("Couldn't locate Pdb class: %s: %s",
2267
+ type(e).__name__, e)
2268
+ return False
2269
+ try:
2270
+ TerminalPdb = _get_TerminalPdb_class()
2271
+ except Exception as e:
2272
+ logger.debug("Couldn't locate TerminalPdb class: %s: %s",
2273
+ type(e).__name__, e)
2274
+ TerminalPdb = None
2275
+ @contextmanager
2276
+ def HookPdbCtx():
2277
+ def Pdb_with_autoimport(self_pdb, *args):
2278
+ __original__(self_pdb, *args)
2279
+ _enable_pdb_hooks(self_pdb)
2280
+ def TerminalPdb_with_autoimport(self_pdb, *args):
2281
+ __original__(self_pdb, *args)
2282
+ _enable_terminal_pdb_hooks(self_pdb, self)
2283
+ with AdviceCtx(Pdb.__init__, Pdb_with_autoimport):
2284
+ if TerminalPdb is None:
2285
+ yield
2286
+ else:
2287
+ with AdviceCtx(TerminalPdb.__init__, TerminalPdb_with_autoimport):
2288
+ yield
2289
+ iptb = getattr(ip, "InteractiveTB", None)
2290
+ ok = True
2291
+ if hasattr(iptb, "debugger"):
2292
+ # Hook ip.InteractiveTB.debugger(). This implements auto
2293
+ # importing for "%debug" (postmortem mode).
2294
+ # Tested with IPython 0.10, 0.11, 0.12, 0.13, 1.0, 1.1, 1.2, 2.0,
2295
+ # 2.1, 2.2, 2.3, 2.4, 3.0, 3.1, 3.2, 4.0.
2296
+ @self._advise(iptb.debugger)
2297
+ def debugger_with_autoimport(*args, **kwargs):
2298
+ with HookPdbCtx():
2299
+ return __original__(*args, **kwargs)
2300
+ else:
2301
+ ok = False
2302
+ if hasattr(ip, 'magics_manager'):
2303
+ # Hook ExecutionMagics._run_with_debugger(). This implements auto
2304
+ # importing for "%debug <statement>".
2305
+ # Tested with IPython 1.0, 1.1, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0,
2306
+ # 3.1, 3.2, 4.0, 5.8.
2307
+ line_magics = ip.magics_manager.magics['line']
2308
+ execmgr = get_method_self(line_magics['debug'])
2309
+ if hasattr(execmgr, "_run_with_debugger"):
2310
+ @self._advise(execmgr._run_with_debugger)
2311
+ def run_with_debugger_with_autoimport(code, code_ns,
2312
+ filename=None,
2313
+ *args, **kwargs):
2314
+ db = ImportDB.get_default(filename or ".")
2315
+ auto_import(code, namespaces=[code_ns], db=db)
2316
+ with HookPdbCtx():
2317
+ return __original__(code, code_ns, filename,
2318
+ *args, **kwargs
2319
+ )
2320
+ else:
2321
+ # IPython 0.13 and earlier don't have "%debug <statement>".
2322
+ pass
2323
+ else:
2324
+ ok = False
2325
+ return ok
2326
+
2327
+
2328
+ def _enable_ipython_shell_bugfixes(self, ip):
2329
+ """
2330
+ Enable some advice that's actually just fixing bugs in IPython.
2331
+ """
2332
+ # IPython 2.x on Python 2.x has a bug where 'run -n' doesn't work
2333
+ # because it uses Unicode for the module name. This is a bug in
2334
+ # IPython itself ("run -n" is plain broken for ipython-2.x on
2335
+ # python-2.x); we patch it here.
2336
+ return True
2337
+
2338
+ def _enable_ipython_bugfixes(self):
2339
+ """
2340
+ Enable some advice that's actually just fixing bugs in IPython.
2341
+ """
2342
+ ok = True
2343
+ ok &= self._enable_ipython_bugfixes_LevelFormatter()
2344
+ return ok
2345
+
2346
+ def _enable_ipython_bugfixes_LevelFormatter(self):
2347
+ # New versions of IPython complain if you import 'IPython.config'.
2348
+ # Old versions of IPython already have it imported.
2349
+ if 'IPython.config' not in sys.modules:
2350
+ return True
2351
+ try:
2352
+ from IPython.config.application import LevelFormatter
2353
+ except ImportError:
2354
+ return True
2355
+ if (not issubclass(LevelFormatter, object) and
2356
+ "super" in LevelFormatter.format.__func__.__code__.co_names and
2357
+ "logging" not in LevelFormatter.format.__func__.__code__.co_names):
2358
+ # In IPython 1.0, LevelFormatter uses super(), which assumes
2359
+ # that logging.Formatter is a subclass of object. However,
2360
+ # this is only true in Python 2.7+, not in Python 2.6. So
2361
+ # Python 2.6 + IPython 1.0 causes problems. IPython 1.2
2362
+ # already includes this fix.
2363
+ from logging import Formatter
2364
+ @self._advise(LevelFormatter.format)
2365
+ def format_patched(self, record):
2366
+ if record.levelno >= self.highlevel_limit:
2367
+ record.highlevel = self.highlevel_format % record.__dict__
2368
+ else:
2369
+ record.highlevel = ""
2370
+ return Formatter.format(self, record)
2371
+ return True
2372
+
2373
+ def disable(self):
2374
+ """
2375
+ Turn off auto-importer in the current IPython session.
2376
+ """
2377
+ if self._state is _EnableState.DISABLED:
2378
+ logger.debug("disable(): already disabled")
2379
+ return
2380
+ logger.debug("disable(): state: %s=>DISABLING", self._state)
2381
+ self._state = _EnableState.DISABLING
2382
+ while self._disablers:
2383
+ f = self._disablers.pop(-1)
2384
+ try:
2385
+ f()
2386
+ except Exception as e:
2387
+ self._errored = True
2388
+ logger.error("Error while disabling: %s: %s", type(e).__name__, e)
2389
+ if logger.debug_enabled:
2390
+ raise
2391
+ else:
2392
+ logger.info(
2393
+ "Set the env var PYFLYBY_LOG_LEVEL=DEBUG to debug.")
2394
+ logger.debug("disable(): state: %s=>DISABLED", self._state)
2395
+ self._state = _EnableState.DISABLED
2396
+
2397
+ def _safe_call(self, function, *args, **kwargs):
2398
+ on_error = kwargs.pop("on_error", None)
2399
+ raise_on_error = kwargs.pop("raise_on_error", "if_debug")
2400
+ if self._errored:
2401
+ # If we previously errored, then we should already have
2402
+ # unregistered the hook that led to here. However, in some corner
2403
+ # cases we can get called one more time. If so, go straight to
2404
+ # the on_error case.
2405
+ pass
2406
+ else:
2407
+ try:
2408
+ return function(*args, **kwargs)
2409
+ except Exception as e:
2410
+ # Something went wrong. Remember that we've had a problem.
2411
+ self._errored = True
2412
+ logger.error("%s: %s", type(e).__name__, e)
2413
+ if not logger.debug_enabled:
2414
+ logger.info(
2415
+ "Set the env var PYFLYBY_LOG_LEVEL=DEBUG to debug.")
2416
+ logger.warning("Disabling pyflyby auto importer.")
2417
+ # Disable everything. If something's broken, chances are
2418
+ # other stuff is broken too.
2419
+ try:
2420
+ self.disable()
2421
+ except Exception as e2:
2422
+ logger.error("Error trying to disable: %s: %s",
2423
+ type(e2).__name__, e2)
2424
+ # Raise or print traceback in debug mode.
2425
+ if raise_on_error == True:
2426
+ raise
2427
+ elif raise_on_error == 'if_debug':
2428
+ if logger.debug_enabled:
2429
+ if type(e) == SyntaxError:
2430
+ # The traceback for SyntaxError tends to get
2431
+ # swallowed, so print it out now.
2432
+ import traceback
2433
+ traceback.print_exc()
2434
+ raise
2435
+ elif raise_on_error == False:
2436
+ if logger.debug_enabled:
2437
+ import traceback
2438
+ traceback.print_exc()
2439
+ else:
2440
+ logger.error("internal error: invalid raise_on_error=%r",
2441
+ raise_on_error)
2442
+ # Return what user wanted to in case of error.
2443
+ if on_error:
2444
+ return on_error(*args, **kwargs)
2445
+ else:
2446
+ return None # just to be explicit
2447
+
2448
+ def reset_state_new_cell(self):
2449
+ # Reset the state for a new cell.
2450
+ if logger.debug_enabled:
2451
+ autoimported = self._autoimported_this_cell
2452
+ logger.debug("reset_state_new_cell(): previously autoimported: "
2453
+ "succeeded=%s, failed=%s",
2454
+ sorted([k for k,v in autoimported.items() if v]),
2455
+ sorted([k for k,v in autoimported.items() if not v]))
2456
+ self._autoimported_this_cell = {}
2457
+
2458
+ def auto_import(self, arg, namespaces=None,
2459
+ raise_on_error='if_debug', on_error=None):
2460
+ if namespaces is None:
2461
+ namespaces = get_global_namespaces(self._ip)
2462
+
2463
+ def post_import_hook(imp):
2464
+ send_comm_message(MISSING_IMPORTS, {"missing_imports": str(imp)})
2465
+
2466
+ return self._safe_call(
2467
+ auto_import, arg, namespaces,
2468
+ autoimported=self._autoimported_this_cell,
2469
+ raise_on_error=raise_on_error, on_error=on_error,
2470
+ post_import_hook=post_import_hook)
2471
+
2472
+ def complete_symbol(self, fullname, namespaces,
2473
+ raise_on_error='if_debug', on_error=None):
2474
+ with InterceptPrintsDuringPromptCtx(self._ip):
2475
+ if namespaces is None:
2476
+ namespaces = get_global_namespaces(self._ip)
2477
+ if on_error is not None:
2478
+ def on_error1(fullname, namespaces, autoimported, ip, allow_eval):
2479
+ return on_error(fullname)
2480
+ else:
2481
+ on_error1 = None
2482
+ return self._safe_call(
2483
+ complete_symbol, fullname, namespaces,
2484
+ autoimported=self._autoimported_this_cell,
2485
+ ip=self._ip, allow_eval=True,
2486
+ raise_on_error=raise_on_error, on_error=on_error1)
2487
+
2488
+ def compile_with_autoimport(self, src, filename, mode, flags=0):
2489
+ logger.debug("compile_with_autoimport(%r)", src)
2490
+ ast_node = compile(src, filename, mode, flags|ast.PyCF_ONLY_AST,
2491
+ dont_inherit=True)
2492
+ self.auto_import(ast_node)
2493
+ if flags & ast.PyCF_ONLY_AST:
2494
+ return ast_node
2495
+ else:
2496
+ return compile(ast_node, filename, mode, flags, dont_inherit=True)
2497
+
2498
+ def _advise(self, joinpoint):
2499
+ def advisor(f):
2500
+ aspect = Aspect(joinpoint)
2501
+ if aspect.advise(f, once=True):
2502
+ self._disablers.append(aspect.unadvise)
2503
+ return advisor
2504
+
2505
+
2506
+
2507
+ def enable_auto_importer(if_no_ipython='raise'):
2508
+ """
2509
+ Turn on the auto-importer in the current IPython application.
2510
+
2511
+ :param if_no_ipython:
2512
+ If we are not inside IPython and if_no_ipython=='ignore', then silently
2513
+ do nothing.
2514
+ If we are not inside IPython and if_no_ipython=='raise', then raise
2515
+ NoActiveIPythonAppError.
2516
+ """
2517
+ try:
2518
+ app = _get_ipython_app()
2519
+ except NoActiveIPythonAppError:
2520
+ if if_no_ipython=='ignore':
2521
+ return
2522
+ else:
2523
+ raise
2524
+ auto_importer = AutoImporter(app)
2525
+ auto_importer.enable()
2526
+
2527
+
2528
+ def disable_auto_importer():
2529
+ """
2530
+ Turn off the auto-importer in the current IPython application.
2531
+ """
2532
+ try:
2533
+ app = _get_ipython_app()
2534
+ except NoActiveIPythonAppError:
2535
+ return
2536
+ auto_importer = AutoImporter(app)
2537
+ auto_importer.disable()
2538
+
2539
+
2540
+ def load_ipython_extension(arg=Ellipsis):
2541
+ """
2542
+ Turn on pyflyby features, including the auto-importer, for the given
2543
+ IPython shell.
2544
+
2545
+ Clear the ImportDB cache of known-imports.
2546
+
2547
+ This function is used by IPython's extension mechanism.
2548
+
2549
+ To load pyflyby in an existing IPython session, run::
2550
+
2551
+ In [1]: %load_ext pyflyby
2552
+
2553
+ To refresh the imports database (if you modified ~/.pyflyby), run::
2554
+
2555
+ In [1]: %reload_ext pyflyby
2556
+
2557
+ To load pyflyby automatically on IPython startup, appendto
2558
+ ~/.ipython/profile_default/ipython_config.py::
2559
+ c.InteractiveShellApp.extensions.append("pyflyby")
2560
+
2561
+ :type arg:
2562
+ ``InteractiveShell``
2563
+ :see:
2564
+ http://ipython.org/ipython-doc/dev/config/extensions/index.html
2565
+ """
2566
+ logger.debug("load_ipython_extension() called for %s",
2567
+ os.path.dirname(__file__))
2568
+ # Turn on the auto-importer.
2569
+ auto_importer = AutoImporter(arg)
2570
+ auto_importer.enable(even_if_previously_errored=True)
2571
+ # Clear ImportDB cache.
2572
+ ImportDB.clear_default_cache()
2573
+ # Clear the set of errored imports.
2574
+ clear_failed_imports_cache()
2575
+ # Enable debugging tools. These aren't IPython-specific, and are better
2576
+ # put in usercustomize.py. But this is a convenient way for them to be
2577
+ # loaded. They're fine to run again even if they've already been run via
2578
+ # usercustomize.py.
2579
+ from ._dbg import (enable_faulthandler,
2580
+ enable_signal_handler_debugger,
2581
+ enable_sigterm_handler,
2582
+ add_debug_functions_to_builtins)
2583
+ enable_faulthandler()
2584
+ enable_signal_handler_debugger()
2585
+ enable_sigterm_handler(on_existing_handler='keep_existing')
2586
+ add_debug_functions_to_builtins()
2587
+ initialize_comms()
2588
+
2589
+
2590
+ def unload_ipython_extension(arg=Ellipsis):
2591
+ """
2592
+ Turn off pyflyby features, including the auto-importer.
2593
+
2594
+ This function is used by IPython's extension mechanism.
2595
+
2596
+ To unload interactively, run::
2597
+
2598
+ In [1]: %unload_ext pyflyby
2599
+ """
2600
+ logger.debug("unload_ipython_extension() called for %s",
2601
+ os.path.dirname(__file__))
2602
+ auto_importer = AutoImporter(arg)
2603
+ auto_importer.disable()
2604
+ remove_comms()
2605
+ # TODO: disable signal handlers etc.