builtin_trap.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. """
  2. A context manager for managing things injected into :mod:`__builtin__`.
  3. Authors:
  4. * Brian Granger
  5. * Fernando Perez
  6. """
  7. #-----------------------------------------------------------------------------
  8. # Copyright (C) 2010-2011 The IPython Development Team.
  9. #
  10. # Distributed under the terms of the BSD License.
  11. #
  12. # Complete license in the file COPYING.txt, distributed with this software.
  13. #-----------------------------------------------------------------------------
  14. #-----------------------------------------------------------------------------
  15. # Imports
  16. #-----------------------------------------------------------------------------
  17. from traitlets.config.configurable import Configurable
  18. from IPython.utils.py3compat import builtin_mod, iteritems
  19. from traitlets import Instance
  20. #-----------------------------------------------------------------------------
  21. # Classes and functions
  22. #-----------------------------------------------------------------------------
  23. class __BuiltinUndefined(object): pass
  24. BuiltinUndefined = __BuiltinUndefined()
  25. class __HideBuiltin(object): pass
  26. HideBuiltin = __HideBuiltin()
  27. class BuiltinTrap(Configurable):
  28. shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
  29. allow_none=True)
  30. def __init__(self, shell=None):
  31. super(BuiltinTrap, self).__init__(shell=shell, config=None)
  32. self._orig_builtins = {}
  33. # We define this to track if a single BuiltinTrap is nested.
  34. # Only turn off the trap when the outermost call to __exit__ is made.
  35. self._nested_level = 0
  36. self.shell = shell
  37. # builtins we always add - if set to HideBuiltin, they will just
  38. # be removed instead of being replaced by something else
  39. self.auto_builtins = {'exit': HideBuiltin,
  40. 'quit': HideBuiltin,
  41. 'get_ipython': self.shell.get_ipython,
  42. }
  43. # Recursive reload function
  44. try:
  45. from IPython.lib import deepreload
  46. if self.shell.deep_reload:
  47. from warnings import warn
  48. warn("Automatically replacing builtin `reload` by `deepreload.reload` is deprecated since IPython 4.0, please import `reload` explicitly from `IPython.lib.deepreload", DeprecationWarning)
  49. self.auto_builtins['reload'] = deepreload._dreload
  50. else:
  51. self.auto_builtins['dreload']= deepreload._dreload
  52. except ImportError:
  53. pass
  54. def __enter__(self):
  55. if self._nested_level == 0:
  56. self.activate()
  57. self._nested_level += 1
  58. # I return self, so callers can use add_builtin in a with clause.
  59. return self
  60. def __exit__(self, type, value, traceback):
  61. if self._nested_level == 1:
  62. self.deactivate()
  63. self._nested_level -= 1
  64. # Returning False will cause exceptions to propagate
  65. return False
  66. def add_builtin(self, key, value):
  67. """Add a builtin and save the original."""
  68. bdict = builtin_mod.__dict__
  69. orig = bdict.get(key, BuiltinUndefined)
  70. if value is HideBuiltin:
  71. if orig is not BuiltinUndefined: #same as 'key in bdict'
  72. self._orig_builtins[key] = orig
  73. del bdict[key]
  74. else:
  75. self._orig_builtins[key] = orig
  76. bdict[key] = value
  77. def remove_builtin(self, key, orig):
  78. """Remove an added builtin and re-set the original."""
  79. if orig is BuiltinUndefined:
  80. del builtin_mod.__dict__[key]
  81. else:
  82. builtin_mod.__dict__[key] = orig
  83. def activate(self):
  84. """Store ipython references in the __builtin__ namespace."""
  85. add_builtin = self.add_builtin
  86. for name, func in iteritems(self.auto_builtins):
  87. add_builtin(name, func)
  88. def deactivate(self):
  89. """Remove any builtins which might have been added by add_builtins, or
  90. restore overwritten ones to their previous values."""
  91. remove_builtin = self.remove_builtin
  92. for key, val in iteritems(self._orig_builtins):
  93. remove_builtin(key, val)
  94. self._orig_builtins.clear()
  95. self._builtins_added = False