Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/extensions.py: 30%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

61 statements  

1"""A class for managing IPython extensions.""" 

2 

3# Copyright (c) IPython Development Team. 

4# Distributed under the terms of the Modified BSD License. 

5 

6import os 

7import os.path 

8import sys 

9from importlib import import_module, reload 

10 

11from traitlets.config.configurable import Configurable 

12from IPython.utils.path import ensure_dir_exists 

13from traitlets import Instance 

14 

15 

16#----------------------------------------------------------------------------- 

17# Main class 

18#----------------------------------------------------------------------------- 

19 

20BUILTINS_EXTS = {"storemagic": False, "autoreload": False} 

21 

22 

23class ExtensionManager(Configurable): 

24 """A class to manage IPython extensions. 

25 

26 An IPython extension is an importable Python module that has 

27 a function with the signature:: 

28 

29 def load_ipython_extension(ipython): 

30 # Do things with ipython 

31 

32 This function is called after your extension is imported and the 

33 currently active :class:`InteractiveShell` instance is passed as 

34 the only argument. You can do anything you want with IPython at 

35 that point, including defining new magic and aliases, adding new 

36 components, etc. 

37 

38 You can also optionally define an :func:`unload_ipython_extension(ipython)` 

39 function, which will be called if the user unloads or reloads the extension. 

40 The extension manager will only call :func:`load_ipython_extension` again 

41 if the extension is reloaded. 

42 

43 You can put your extension modules anywhere you want, as long as 

44 they can be imported by Python's standard import mechanism. 

45 """ 

46 

47 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) 

48 

49 def __init__(self, shell=None, **kwargs): 

50 super().__init__(shell=shell, **kwargs) 

51 self.loaded = set() 

52 

53 def load_extension(self, module_str: str): 

54 """Load an IPython extension by its module name. 

55 

56 Returns the string "already loaded" if the extension is already loaded, 

57 "no load function" if the module doesn't have a load_ipython_extension 

58 function, or None if it succeeded. 

59 """ 

60 try: 

61 return self._load_extension(module_str) 

62 except ModuleNotFoundError: 

63 if module_str in BUILTINS_EXTS: 

64 BUILTINS_EXTS[module_str] = True 

65 return self._load_extension("IPython.extensions." + module_str) 

66 raise 

67 

68 def _load_extension(self, module_str: str): 

69 if module_str in self.loaded: 

70 return "already loaded" 

71 

72 assert self.shell is not None 

73 

74 with self.shell.builtin_trap: 

75 if module_str not in sys.modules: 

76 mod = import_module(module_str) 

77 mod = sys.modules[module_str] 

78 if self._call_load_ipython_extension(mod): 

79 self.loaded.add(module_str) 

80 else: 

81 return "no load function" 

82 

83 def unload_extension(self, module_str: str): 

84 """Unload an IPython extension by its module name. 

85 

86 This function looks up the extension's name in ``sys.modules`` and 

87 simply calls ``mod.unload_ipython_extension(self)``. 

88 

89 Returns the string "no unload function" if the extension doesn't define 

90 a function to unload itself, "not loaded" if the extension isn't loaded, 

91 otherwise None. 

92 """ 

93 if BUILTINS_EXTS.get(module_str, False) is True: 

94 module_str = "IPython.extensions." + module_str 

95 if module_str not in self.loaded: 

96 return "not loaded" 

97 

98 if module_str in sys.modules: 

99 mod = sys.modules[module_str] 

100 if self._call_unload_ipython_extension(mod): 

101 self.loaded.discard(module_str) 

102 else: 

103 return "no unload function" 

104 

105 def reload_extension(self, module_str: str): 

106 """Reload an IPython extension by calling reload. 

107 

108 If the module has not been loaded before, 

109 :meth:`InteractiveShell.load_extension` is called. Otherwise 

110 :func:`reload` is called and then the :func:`load_ipython_extension` 

111 function of the module, if it exists is called. 

112 """ 

113 

114 if BUILTINS_EXTS.get(module_str, False) is True: 

115 module_str = "IPython.extensions." + module_str 

116 

117 if (module_str in self.loaded) and (module_str in sys.modules): 

118 self.unload_extension(module_str) 

119 mod = sys.modules[module_str] 

120 reload(mod) 

121 if self._call_load_ipython_extension(mod): 

122 self.loaded.add(module_str) 

123 else: 

124 self.load_extension(module_str) 

125 

126 def _call_load_ipython_extension(self, mod): 

127 if hasattr(mod, 'load_ipython_extension'): 

128 mod.load_ipython_extension(self.shell) 

129 return True 

130 

131 def _call_unload_ipython_extension(self, mod): 

132 if hasattr(mod, 'unload_ipython_extension'): 

133 mod.unload_ipython_extension(self.shell) 

134 return True