Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/IPython/terminal/magics.py: 27%

90 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

1"""Extra magics for terminal use.""" 

2 

3# Copyright (c) IPython Development Team. 

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

5 

6 

7from logging import error 

8import os 

9import sys 

10 

11from IPython.core.error import TryNext, UsageError 

12from IPython.core.magic import Magics, magics_class, line_magic 

13from IPython.lib.clipboard import ClipboardEmpty 

14from IPython.testing.skipdoctest import skip_doctest 

15from IPython.utils.text import SList, strip_email_quotes 

16from IPython.utils import py3compat 

17 

18def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False): 

19 """ Yield pasted lines until the user enters the given sentinel value. 

20 """ 

21 if not quiet: 

22 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ 

23 % sentinel) 

24 prompt = ":" 

25 else: 

26 prompt = "" 

27 while True: 

28 try: 

29 l = l_input(prompt) 

30 if l == sentinel: 

31 return 

32 else: 

33 yield l 

34 except EOFError: 

35 print('<EOF>') 

36 return 

37 

38 

39@magics_class 

40class TerminalMagics(Magics): 

41 def __init__(self, shell): 

42 super(TerminalMagics, self).__init__(shell) 

43 

44 def store_or_execute(self, block, name, store_history=False): 

45 """ Execute a block, or store it in a variable, per the user's request. 

46 """ 

47 if name: 

48 # If storing it for further editing 

49 self.shell.user_ns[name] = SList(block.splitlines()) 

50 print("Block assigned to '%s'" % name) 

51 else: 

52 b = self.preclean_input(block) 

53 self.shell.user_ns['pasted_block'] = b 

54 self.shell.using_paste_magics = True 

55 try: 

56 self.shell.run_cell(b, store_history) 

57 finally: 

58 self.shell.using_paste_magics = False 

59 

60 def preclean_input(self, block): 

61 lines = block.splitlines() 

62 while lines and not lines[0].strip(): 

63 lines = lines[1:] 

64 return strip_email_quotes('\n'.join(lines)) 

65 

66 def rerun_pasted(self, name='pasted_block'): 

67 """ Rerun a previously pasted command. 

68 """ 

69 b = self.shell.user_ns.get(name) 

70 

71 # Sanity checks 

72 if b is None: 

73 raise UsageError('No previous pasted block available') 

74 if not isinstance(b, str): 

75 raise UsageError( 

76 "Variable 'pasted_block' is not a string, can't execute") 

77 

78 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))) 

79 self.shell.run_cell(b) 

80 

81 @line_magic 

82 def autoindent(self, parameter_s = ''): 

83 """Toggle autoindent on/off (deprecated)""" 

84 self.shell.set_autoindent() 

85 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent]) 

86 

87 @skip_doctest 

88 @line_magic 

89 def cpaste(self, parameter_s=''): 

90 """Paste & execute a pre-formatted code block from clipboard. 

91 

92 You must terminate the block with '--' (two minus-signs) or Ctrl-D 

93 alone on the line. You can also provide your own sentinel with '%paste 

94 -s %%' ('%%' is the new sentinel for this operation). 

95 

96 The block is dedented prior to execution to enable execution of method 

97 definitions. '>' and '+' characters at the beginning of a line are 

98 ignored, to allow pasting directly from e-mails, diff files and 

99 doctests (the '...' continuation prompt is also stripped). The 

100 executed block is also assigned to variable named 'pasted_block' for 

101 later editing with '%edit pasted_block'. 

102 

103 You can also pass a variable name as an argument, e.g. '%cpaste foo'. 

104 This assigns the pasted block to variable 'foo' as string, without 

105 dedenting or executing it (preceding >>> and + is still stripped) 

106 

107 '%cpaste -r' re-executes the block previously entered by cpaste. 

108 '%cpaste -q' suppresses any additional output messages. 

109 

110 Do not be alarmed by garbled output on Windows (it's a readline bug). 

111 Just press enter and type -- (and press enter again) and the block 

112 will be what was just pasted. 

113 

114 Shell escapes are not supported (yet). 

115 

116 See Also 

117 -------- 

118 paste : automatically pull code from clipboard. 

119 

120 Examples 

121 -------- 

122 :: 

123 

124 In [8]: %cpaste 

125 Pasting code; enter '--' alone on the line to stop. 

126 :>>> a = ["world!", "Hello"] 

127 :>>> print(" ".join(sorted(a))) 

128 :-- 

129 Hello world! 

130 

131 :: 

132 In [8]: %cpaste 

133 Pasting code; enter '--' alone on the line to stop. 

134 :>>> %alias_magic t timeit 

135 :>>> %t -n1 pass 

136 :-- 

137 Created `%t` as an alias for `%timeit`. 

138 Created `%%t` as an alias for `%%timeit`. 

139 354 ns ± 224 ns per loop (mean ± std. dev. of 7 runs, 1 loop each) 

140 """ 

141 opts, name = self.parse_options(parameter_s, 'rqs:', mode='string') 

142 if 'r' in opts: 

143 self.rerun_pasted() 

144 return 

145 

146 quiet = ('q' in opts) 

147 

148 sentinel = opts.get('s', u'--') 

149 block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet)) 

150 self.store_or_execute(block, name, store_history=True) 

151 

152 @line_magic 

153 def paste(self, parameter_s=''): 

154 """Paste & execute a pre-formatted code block from clipboard. 

155 

156 The text is pulled directly from the clipboard without user 

157 intervention and printed back on the screen before execution (unless 

158 the -q flag is given to force quiet mode). 

159 

160 The block is dedented prior to execution to enable execution of method 

161 definitions. '>' and '+' characters at the beginning of a line are 

162 ignored, to allow pasting directly from e-mails, diff files and 

163 doctests (the '...' continuation prompt is also stripped). The 

164 executed block is also assigned to variable named 'pasted_block' for 

165 later editing with '%edit pasted_block'. 

166 

167 You can also pass a variable name as an argument, e.g. '%paste foo'. 

168 This assigns the pasted block to variable 'foo' as string, without 

169 executing it (preceding >>> and + is still stripped). 

170 

171 Options: 

172 

173 -r: re-executes the block previously entered by cpaste. 

174 

175 -q: quiet mode: do not echo the pasted text back to the terminal. 

176 

177 IPython statements (magics, shell escapes) are not supported (yet). 

178 

179 See Also 

180 -------- 

181 cpaste : manually paste code into terminal until you mark its end. 

182 """ 

183 opts, name = self.parse_options(parameter_s, 'rq', mode='string') 

184 if 'r' in opts: 

185 self.rerun_pasted() 

186 return 

187 try: 

188 block = self.shell.hooks.clipboard_get() 

189 except TryNext as clipboard_exc: 

190 message = getattr(clipboard_exc, 'args') 

191 if message: 

192 error(message[0]) 

193 else: 

194 error('Could not get text from the clipboard.') 

195 return 

196 except ClipboardEmpty as e: 

197 raise UsageError("The clipboard appears to be empty") from e 

198 

199 # By default, echo back to terminal unless quiet mode is requested 

200 if 'q' not in opts: 

201 sys.stdout.write(self.shell.pycolorize(block)) 

202 if not block.endswith("\n"): 

203 sys.stdout.write("\n") 

204 sys.stdout.write("## -- End pasted text --\n") 

205 

206 self.store_or_execute(block, name, store_history=True) 

207 

208 # Class-level: add a '%cls' magic only on Windows 

209 if sys.platform == 'win32': 

210 @line_magic 

211 def cls(self, s): 

212 """Clear screen. 

213 """ 

214 os.system("cls")