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

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

91 statements  

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 

16 

17def get_pasted_lines(sentinel, l_input=input, quiet=False): 

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

19 """ 

20 if not quiet: 

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

22 % sentinel) 

23 prompt = ":" 

24 else: 

25 prompt = "" 

26 while True: 

27 try: 

28 l = l_input(prompt) 

29 if l == sentinel: 

30 return 

31 else: 

32 yield l 

33 except EOFError: 

34 print('<EOF>') 

35 return 

36 

37 

38@magics_class 

39class TerminalMagics(Magics): 

40 def __init__(self, shell): 

41 super().__init__(shell) 

42 

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

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

45 """ 

46 if name: 

47 # If storing it for further editing 

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

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

50 else: 

51 b = self.preclean_input(block) 

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

53 self.shell.using_paste_magics = True 

54 try: 

55 self.shell.run_cell(b, store_history) 

56 finally: 

57 self.shell.using_paste_magics = False 

58 

59 def preclean_input(self, block): 

60 lines = block.splitlines() 

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

62 lines = lines[1:] 

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

64 

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

66 """ Rerun a previously pasted command. 

67 """ 

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

69 

70 # Sanity checks 

71 if b is None: 

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

73 if not isinstance(b, str): 

74 raise UsageError( 

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

76 

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

78 self.shell.run_cell(b) 

79 

80 @line_magic 

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

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

83 self.shell.set_autoindent() 

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

85 

86 @skip_doctest 

87 @line_magic 

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

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

90 

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

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

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

94 

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

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

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

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

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

100 later editing with '%edit pasted_block'. 

101 

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

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

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

105 

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

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

108 

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

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

111 will be what was just pasted. 

112 

113 Shell escapes are not supported (yet). 

114 

115 See Also 

116 -------- 

117 paste : automatically pull code from clipboard. 

118 

119 Examples 

120 -------- 

121 :: 

122 

123 In [8]: %cpaste 

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

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

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

127 :-- 

128 Hello world! 

129 

130 :: 

131 In [8]: %cpaste 

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

133 :>>> %alias_magic t timeit 

134 :>>> %t -n1 pass 

135 :-- 

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

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

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

139 """ 

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

141 if 'r' in opts: 

142 self.rerun_pasted() 

143 return 

144 

145 quiet = ('q' in opts) 

146 

147 sentinel = opts.get('s', '--') 

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

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

150 

151 @line_magic 

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

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

154 

155 The text is pulled directly from the clipboard without user 

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

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

158 

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

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

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

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

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

164 later editing with '%edit pasted_block'. 

165 

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

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

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

169 

170 Options: 

171 

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

173 

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

175 

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

177 

178 See Also 

179 -------- 

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

181 """ 

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

183 if 'r' in opts: 

184 self.rerun_pasted() 

185 return 

186 try: 

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

188 except TryNext as clipboard_exc: 

189 message = getattr(clipboard_exc, 'args') 

190 if message: 

191 error(message[0]) 

192 else: 

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

194 return 

195 except ClipboardEmpty as e: 

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

197 

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

199 if 'q' not in opts: 

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

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

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

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

204 

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

206 

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

208 if sys.platform == 'win32': 

209 @line_magic 

210 def cls(self, s): 

211 """Clear screen. 

212 """ 

213 os.system("cls")