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
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1"""Extra magics for terminal use."""
3# Copyright (c) IPython Development Team.
4# Distributed under the terms of the Modified BSD License.
7from logging import error
8import os
9import sys
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
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
39@magics_class
40class TerminalMagics(Magics):
41 def __init__(self, shell):
42 super(TerminalMagics, self).__init__(shell)
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
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))
66 def rerun_pasted(self, name='pasted_block'):
67 """ Rerun a previously pasted command.
68 """
69 b = self.shell.user_ns.get(name)
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")
78 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
79 self.shell.run_cell(b)
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])
87 @skip_doctest
88 @line_magic
89 def cpaste(self, parameter_s=''):
90 """Paste & execute a pre-formatted code block from clipboard.
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).
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'.
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)
107 '%cpaste -r' re-executes the block previously entered by cpaste.
108 '%cpaste -q' suppresses any additional output messages.
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.
114 Shell escapes are not supported (yet).
116 See Also
117 --------
118 paste : automatically pull code from clipboard.
120 Examples
121 --------
122 ::
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!
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
146 quiet = ('q' in opts)
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)
152 @line_magic
153 def paste(self, parameter_s=''):
154 """Paste & execute a pre-formatted code block from clipboard.
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).
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'.
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).
171 Options:
173 -r: re-executes the block previously entered by cpaste.
175 -q: quiet mode: do not echo the pasted text back to the terminal.
177 IPython statements (magics, shell escapes) are not supported (yet).
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
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")
206 self.store_or_execute(block, name, store_history=True)
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")