##// END OF EJS Templates
Remove unused imports from IPython.core
Thomas Kluyver -
Show More
@@ -1,185 +1,184 b''
1 1 # encoding: utf-8
2 2 """A class for managing IPython extensions.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010-2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 import os
21 21 from shutil import copyfile
22 22 import sys
23 23
24 from IPython.core.error import UsageError
25 24 from IPython.config.configurable import Configurable
26 25 from IPython.utils.traitlets import Instance
27 26 from IPython.utils.py3compat import PY3
28 27 if PY3:
29 28 from imp import reload
30 29
31 30 #-----------------------------------------------------------------------------
32 31 # Main class
33 32 #-----------------------------------------------------------------------------
34 33
35 34 class ExtensionManager(Configurable):
36 35 """A class to manage IPython extensions.
37 36
38 37 An IPython extension is an importable Python module that has
39 38 a function with the signature::
40 39
41 40 def load_ipython_extension(ipython):
42 41 # Do things with ipython
43 42
44 43 This function is called after your extension is imported and the
45 44 currently active :class:`InteractiveShell` instance is passed as
46 45 the only argument. You can do anything you want with IPython at
47 46 that point, including defining new magic and aliases, adding new
48 47 components, etc.
49 48
50 49 You can also optionally define an :func:`unload_ipython_extension(ipython)`
51 50 function, which will be called if the user unloads or reloads the extension.
52 51 The extension manager will only call :func:`load_ipython_extension` again
53 52 if the extension is reloaded.
54 53
55 54 You can put your extension modules anywhere you want, as long as
56 55 they can be imported by Python's standard import mechanism. However,
57 56 to make it easy to write extensions, you can also put your extensions
58 57 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
59 58 is added to ``sys.path`` automatically.
60 59 """
61 60
62 61 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
63 62
64 63 def __init__(self, shell=None, **kwargs):
65 64 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
66 65 self.shell.on_trait_change(
67 66 self._on_ipython_dir_changed, 'ipython_dir'
68 67 )
69 68 self.loaded = set()
70 69
71 70 def __del__(self):
72 71 self.shell.on_trait_change(
73 72 self._on_ipython_dir_changed, 'ipython_dir', remove=True
74 73 )
75 74
76 75 @property
77 76 def ipython_extension_dir(self):
78 77 return os.path.join(self.shell.ipython_dir, u'extensions')
79 78
80 79 def _on_ipython_dir_changed(self):
81 80 if not os.path.isdir(self.ipython_extension_dir):
82 81 os.makedirs(self.ipython_extension_dir, mode = 0o777)
83 82
84 83 def load_extension(self, module_str):
85 84 """Load an IPython extension by its module name.
86 85
87 86 Returns the string "already loaded" if the extension is already loaded,
88 87 "no load function" if the module doesn't have a load_ipython_extension
89 88 function, or None if it succeeded.
90 89 """
91 90 if module_str in self.loaded:
92 91 return "already loaded"
93 92
94 93 from IPython.utils.syspathcontext import prepended_to_syspath
95 94
96 95 with self.shell.builtin_trap:
97 96 if module_str not in sys.modules:
98 97 with prepended_to_syspath(self.ipython_extension_dir):
99 98 __import__(module_str)
100 99 mod = sys.modules[module_str]
101 100 if self._call_load_ipython_extension(mod):
102 101 self.loaded.add(module_str)
103 102 else:
104 103 return "no load function"
105 104
106 105 def unload_extension(self, module_str):
107 106 """Unload an IPython extension by its module name.
108 107
109 108 This function looks up the extension's name in ``sys.modules`` and
110 109 simply calls ``mod.unload_ipython_extension(self)``.
111 110
112 111 Returns the string "no unload function" if the extension doesn't define
113 112 a function to unload itself, "not loaded" if the extension isn't loaded,
114 113 otherwise None.
115 114 """
116 115 if module_str not in self.loaded:
117 116 return "not loaded"
118 117
119 118 if module_str in sys.modules:
120 119 mod = sys.modules[module_str]
121 120 if self._call_unload_ipython_extension(mod):
122 121 self.loaded.discard(module_str)
123 122 else:
124 123 return "no unload function"
125 124
126 125 def reload_extension(self, module_str):
127 126 """Reload an IPython extension by calling reload.
128 127
129 128 If the module has not been loaded before,
130 129 :meth:`InteractiveShell.load_extension` is called. Otherwise
131 130 :func:`reload` is called and then the :func:`load_ipython_extension`
132 131 function of the module, if it exists is called.
133 132 """
134 133 from IPython.utils.syspathcontext import prepended_to_syspath
135 134
136 135 if (module_str in self.loaded) and (module_str in sys.modules):
137 136 self.unload_extension(module_str)
138 137 mod = sys.modules[module_str]
139 138 with prepended_to_syspath(self.ipython_extension_dir):
140 139 reload(mod)
141 140 if self._call_load_ipython_extension(mod):
142 141 self.loaded.add(module_str)
143 142 else:
144 143 self.load_extension(module_str)
145 144
146 145 def _call_load_ipython_extension(self, mod):
147 146 if hasattr(mod, 'load_ipython_extension'):
148 147 mod.load_ipython_extension(self.shell)
149 148 return True
150 149
151 150 def _call_unload_ipython_extension(self, mod):
152 151 if hasattr(mod, 'unload_ipython_extension'):
153 152 mod.unload_ipython_extension(self.shell)
154 153 return True
155 154
156 155 def install_extension(self, url, filename=None):
157 156 """Download and install an IPython extension.
158 157
159 158 If filename is given, the file will be so named (inside the extension
160 159 directory). Otherwise, the name from the URL will be used. The file must
161 160 have a .py or .zip extension; otherwise, a ValueError will be raised.
162 161
163 162 Returns the full path to the installed file.
164 163 """
165 164 # Ensure the extension directory exists
166 165 if not os.path.isdir(self.ipython_extension_dir):
167 166 os.makedirs(self.ipython_extension_dir, mode = 0o777)
168 167
169 168 if os.path.isfile(url):
170 169 src_filename = os.path.basename(url)
171 170 copy = copyfile
172 171 else:
173 172 from urllib import urlretrieve # Deferred imports
174 173 from urlparse import urlparse
175 174 src_filename = urlparse(url).path.split('/')[-1]
176 175 copy = urlretrieve
177 176
178 177 if filename is None:
179 178 filename = src_filename
180 179 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
181 180 raise ValueError("The file must have a .py or .zip extension", filename)
182 181
183 182 filename = os.path.join(self.ipython_extension_dir, filename)
184 183 copy(url, filename)
185 184 return filename
@@ -1,30 +1,24 b''
1 1 # encoding: utf-8
2 2 """Simple function to call to get the current InteractiveShell instance
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2013 The IPython Development Team
7 7 #
8 8 # Distributed under the terms of the BSD License. The full license is in
9 9 # the file COPYING, distributed as part of this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 import warnings
17
18 #-----------------------------------------------------------------------------
19 13 # Classes and functions
20 14 #-----------------------------------------------------------------------------
21 15
22 16
23 17 def get_ipython():
24 18 """Get the global InteractiveShell instance.
25 19
26 20 Returns None if no InteractiveShell instance is registered.
27 21 """
28 22 from IPython.core.interactiveshell import InteractiveShell
29 23 if InteractiveShell.initialized():
30 24 return InteractiveShell.instance()
@@ -1,658 +1,657 b''
1 1 """Analysis of text input into executable blocks.
2 2
3 3 The main class in this module, :class:`InputSplitter`, is designed to break
4 4 input from either interactive, line-by-line environments or block-based ones,
5 5 into standalone blocks that can be executed by Python as 'single' statements
6 6 (thus triggering sys.displayhook).
7 7
8 8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
9 9 with full support for the extended IPython syntax (magics, system calls, etc).
10 10
11 11 For more details, see the class docstring below.
12 12
13 13 Syntax Transformations
14 14 ----------------------
15 15
16 16 One of the main jobs of the code in this file is to apply all syntax
17 17 transformations that make up 'the IPython language', i.e. magics, shell
18 18 escapes, etc. All transformations should be implemented as *fully stateless*
19 19 entities, that simply take one line as their input and return a line.
20 20 Internally for implementation purposes they may be a normal function or a
21 21 callable object, but the only input they receive will be a single line and they
22 22 should only return a line, without holding any data-dependent state between
23 23 calls.
24 24
25 25 As an example, the EscapedTransformer is a class so we can more clearly group
26 26 together the functionality of dispatching to individual functions based on the
27 27 starting escape character, but the only method for public use is its call
28 28 method.
29 29
30 30
31 31 ToDo
32 32 ----
33 33
34 34 - Should we make push() actually raise an exception once push_accepts_more()
35 35 returns False?
36 36
37 37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
38 38 at least just attributes of a class so not really very exposed.
39 39
40 40 - Think about the best way to support dynamic things: automagic, autocall,
41 41 macros, etc.
42 42
43 43 - Think of a better heuristic for the application of the transforms in
44 44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
45 45 track indentation change events (indent, dedent, nothing) and apply them only
46 46 if the indentation went up, but not otherwise.
47 47
48 48 - Think of the cleanest way for supporting user-specified transformations (the
49 49 user prefilters we had before).
50 50
51 51 Authors
52 52 -------
53 53
54 54 * Fernando Perez
55 55 * Brian Granger
56 56 """
57 57 #-----------------------------------------------------------------------------
58 58 # Copyright (C) 2010 The IPython Development Team
59 59 #
60 60 # Distributed under the terms of the BSD License. The full license is in
61 61 # the file COPYING, distributed as part of this software.
62 62 #-----------------------------------------------------------------------------
63 63
64 64 #-----------------------------------------------------------------------------
65 65 # Imports
66 66 #-----------------------------------------------------------------------------
67 67 # stdlib
68 68 import ast
69 69 import codeop
70 70 import re
71 71 import sys
72 72
73 73 # IPython modules
74 from IPython.core.splitinput import split_user_input, LineInfo
75 74 from IPython.utils.py3compat import cast_unicode
76 75 from IPython.core.inputtransformer import (leading_indent,
77 76 classic_prompt,
78 77 ipy_prompt,
79 78 cellmagic,
80 79 assemble_logical_lines,
81 80 help_end,
82 81 escaped_commands,
83 82 assign_from_magic,
84 83 assign_from_system,
85 84 assemble_python_lines,
86 85 )
87 86
88 # Temporary!
87 # These are available in this module for backwards compatibility.
89 88 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
90 89 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
91 90 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
92 91
93 92 #-----------------------------------------------------------------------------
94 93 # Utilities
95 94 #-----------------------------------------------------------------------------
96 95
97 96 # FIXME: These are general-purpose utilities that later can be moved to the
98 97 # general ward. Kept here for now because we're being very strict about test
99 98 # coverage with this code, and this lets us ensure that we keep 100% coverage
100 99 # while developing.
101 100
102 101 # compiled regexps for autoindent management
103 102 dedent_re = re.compile('|'.join([
104 103 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
105 104 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
106 105 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
107 106 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
108 107 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
109 108 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
110 109 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
111 110 ]))
112 111 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
113 112
114 113 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
115 114 # before pure comments
116 115 comment_line_re = re.compile('^\s*\#')
117 116
118 117
119 118 def num_ini_spaces(s):
120 119 """Return the number of initial spaces in a string.
121 120
122 121 Note that tabs are counted as a single space. For now, we do *not* support
123 122 mixing of tabs and spaces in the user's input.
124 123
125 124 Parameters
126 125 ----------
127 126 s : string
128 127
129 128 Returns
130 129 -------
131 130 n : int
132 131 """
133 132
134 133 ini_spaces = ini_spaces_re.match(s)
135 134 if ini_spaces:
136 135 return ini_spaces.end()
137 136 else:
138 137 return 0
139 138
140 139 def last_blank(src):
141 140 """Determine if the input source ends in a blank.
142 141
143 142 A blank is either a newline or a line consisting of whitespace.
144 143
145 144 Parameters
146 145 ----------
147 146 src : string
148 147 A single or multiline string.
149 148 """
150 149 if not src: return False
151 150 ll = src.splitlines()[-1]
152 151 return (ll == '') or ll.isspace()
153 152
154 153
155 154 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
156 155 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
157 156
158 157 def last_two_blanks(src):
159 158 """Determine if the input source ends in two blanks.
160 159
161 160 A blank is either a newline or a line consisting of whitespace.
162 161
163 162 Parameters
164 163 ----------
165 164 src : string
166 165 A single or multiline string.
167 166 """
168 167 if not src: return False
169 168 # The logic here is tricky: I couldn't get a regexp to work and pass all
170 169 # the tests, so I took a different approach: split the source by lines,
171 170 # grab the last two and prepend '###\n' as a stand-in for whatever was in
172 171 # the body before the last two lines. Then, with that structure, it's
173 172 # possible to analyze with two regexps. Not the most elegant solution, but
174 173 # it works. If anyone tries to change this logic, make sure to validate
175 174 # the whole test suite first!
176 175 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
177 176 return (bool(last_two_blanks_re.match(new_src)) or
178 177 bool(last_two_blanks_re2.match(new_src)) )
179 178
180 179
181 180 def remove_comments(src):
182 181 """Remove all comments from input source.
183 182
184 183 Note: comments are NOT recognized inside of strings!
185 184
186 185 Parameters
187 186 ----------
188 187 src : string
189 188 A single or multiline input string.
190 189
191 190 Returns
192 191 -------
193 192 String with all Python comments removed.
194 193 """
195 194
196 195 return re.sub('#.*', '', src)
197 196
198 197
199 198 def get_input_encoding():
200 199 """Return the default standard input encoding.
201 200
202 201 If sys.stdin has no encoding, 'ascii' is returned."""
203 202 # There are strange environments for which sys.stdin.encoding is None. We
204 203 # ensure that a valid encoding is returned.
205 204 encoding = getattr(sys.stdin, 'encoding', None)
206 205 if encoding is None:
207 206 encoding = 'ascii'
208 207 return encoding
209 208
210 209 #-----------------------------------------------------------------------------
211 210 # Classes and functions for normal Python syntax handling
212 211 #-----------------------------------------------------------------------------
213 212
214 213 class InputSplitter(object):
215 214 """An object that can accumulate lines of Python source before execution.
216 215
217 216 This object is designed to be fed python source line-by-line, using
218 217 :meth:`push`. It will return on each push whether the currently pushed
219 218 code could be executed already. In addition, it provides a method called
220 219 :meth:`push_accepts_more` that can be used to query whether more input
221 220 can be pushed into a single interactive block.
222 221
223 222 This is a simple example of how an interactive terminal-based client can use
224 223 this tool::
225 224
226 225 isp = InputSplitter()
227 226 while isp.push_accepts_more():
228 227 indent = ' '*isp.indent_spaces
229 228 prompt = '>>> ' + indent
230 229 line = indent + raw_input(prompt)
231 230 isp.push(line)
232 231 print 'Input source was:\n', isp.source_reset(),
233 232 """
234 233 # Number of spaces of indentation computed from input that has been pushed
235 234 # so far. This is the attributes callers should query to get the current
236 235 # indentation level, in order to provide auto-indent facilities.
237 236 indent_spaces = 0
238 237 # String, indicating the default input encoding. It is computed by default
239 238 # at initialization time via get_input_encoding(), but it can be reset by a
240 239 # client with specific knowledge of the encoding.
241 240 encoding = ''
242 241 # String where the current full source input is stored, properly encoded.
243 242 # Reading this attribute is the normal way of querying the currently pushed
244 243 # source code, that has been properly encoded.
245 244 source = ''
246 245 # Code object corresponding to the current source. It is automatically
247 246 # synced to the source, so it can be queried at any time to obtain the code
248 247 # object; it will be None if the source doesn't compile to valid Python.
249 248 code = None
250 249
251 250 # Private attributes
252 251
253 252 # List with lines of input accumulated so far
254 253 _buffer = None
255 254 # Command compiler
256 255 _compile = None
257 256 # Mark when input has changed indentation all the way back to flush-left
258 257 _full_dedent = False
259 258 # Boolean indicating whether the current block is complete
260 259 _is_complete = None
261 260
262 261 def __init__(self):
263 262 """Create a new InputSplitter instance.
264 263 """
265 264 self._buffer = []
266 265 self._compile = codeop.CommandCompiler()
267 266 self.encoding = get_input_encoding()
268 267
269 268 def reset(self):
270 269 """Reset the input buffer and associated state."""
271 270 self.indent_spaces = 0
272 271 self._buffer[:] = []
273 272 self.source = ''
274 273 self.code = None
275 274 self._is_complete = False
276 275 self._full_dedent = False
277 276
278 277 def source_reset(self):
279 278 """Return the input source and perform a full reset.
280 279 """
281 280 out = self.source
282 281 self.reset()
283 282 return out
284 283
285 284 def push(self, lines):
286 285 """Push one or more lines of input.
287 286
288 287 This stores the given lines and returns a status code indicating
289 288 whether the code forms a complete Python block or not.
290 289
291 290 Any exceptions generated in compilation are swallowed, but if an
292 291 exception was produced, the method returns True.
293 292
294 293 Parameters
295 294 ----------
296 295 lines : string
297 296 One or more lines of Python input.
298 297
299 298 Returns
300 299 -------
301 300 is_complete : boolean
302 301 True if the current input source (the result of the current input
303 302 plus prior inputs) forms a complete Python execution block. Note that
304 303 this value is also stored as a private attribute (``_is_complete``), so it
305 304 can be queried at any time.
306 305 """
307 306 self._store(lines)
308 307 source = self.source
309 308
310 309 # Before calling _compile(), reset the code object to None so that if an
311 310 # exception is raised in compilation, we don't mislead by having
312 311 # inconsistent code/source attributes.
313 312 self.code, self._is_complete = None, None
314 313
315 314 # Honor termination lines properly
316 315 if source.endswith('\\\n'):
317 316 return False
318 317
319 318 self._update_indent(lines)
320 319 try:
321 320 self.code = self._compile(source, symbol="exec")
322 321 # Invalid syntax can produce any of a number of different errors from
323 322 # inside the compiler, so we have to catch them all. Syntax errors
324 323 # immediately produce a 'ready' block, so the invalid Python can be
325 324 # sent to the kernel for evaluation with possible ipython
326 325 # special-syntax conversion.
327 326 except (SyntaxError, OverflowError, ValueError, TypeError,
328 327 MemoryError):
329 328 self._is_complete = True
330 329 else:
331 330 # Compilation didn't produce any exceptions (though it may not have
332 331 # given a complete code object)
333 332 self._is_complete = self.code is not None
334 333
335 334 return self._is_complete
336 335
337 336 def push_accepts_more(self):
338 337 """Return whether a block of interactive input can accept more input.
339 338
340 339 This method is meant to be used by line-oriented frontends, who need to
341 340 guess whether a block is complete or not based solely on prior and
342 341 current input lines. The InputSplitter considers it has a complete
343 342 interactive block and will not accept more input when either:
344 343
345 344 * A SyntaxError is raised
346 345
347 346 * The code is complete and consists of a single line or a single
348 347 non-compound statement
349 348
350 349 * The code is complete and has a blank line at the end
351 350
352 351 If the current input produces a syntax error, this method immediately
353 352 returns False but does *not* raise the syntax error exception, as
354 353 typically clients will want to send invalid syntax to an execution
355 354 backend which might convert the invalid syntax into valid Python via
356 355 one of the dynamic IPython mechanisms.
357 356 """
358 357
359 358 # With incomplete input, unconditionally accept more
360 359 # A syntax error also sets _is_complete to True - see push()
361 360 if not self._is_complete:
362 361 #print("Not complete") # debug
363 362 return True
364 363
365 364 # The user can make any (complete) input execute by leaving a blank line
366 365 last_line = self.source.splitlines()[-1]
367 366 if (not last_line) or last_line.isspace():
368 367 #print("Blank line") # debug
369 368 return False
370 369
371 370 # If there's just a single line or AST node, and we're flush left, as is
372 371 # the case after a simple statement such as 'a=1', we want to execute it
373 372 # straight away.
374 373 if self.indent_spaces==0:
375 374 if len(self.source.splitlines()) <= 1:
376 375 return False
377 376
378 377 try:
379 378 code_ast = ast.parse(u''.join(self._buffer))
380 379 except Exception:
381 380 #print("Can't parse AST") # debug
382 381 return False
383 382 else:
384 383 if len(code_ast.body) == 1 and \
385 384 not hasattr(code_ast.body[0], 'body'):
386 385 #print("Simple statement") # debug
387 386 return False
388 387
389 388 # General fallback - accept more code
390 389 return True
391 390
392 391 #------------------------------------------------------------------------
393 392 # Private interface
394 393 #------------------------------------------------------------------------
395 394
396 395 def _find_indent(self, line):
397 396 """Compute the new indentation level for a single line.
398 397
399 398 Parameters
400 399 ----------
401 400 line : str
402 401 A single new line of non-whitespace, non-comment Python input.
403 402
404 403 Returns
405 404 -------
406 405 indent_spaces : int
407 406 New value for the indent level (it may be equal to self.indent_spaces
408 407 if indentation doesn't change.
409 408
410 409 full_dedent : boolean
411 410 Whether the new line causes a full flush-left dedent.
412 411 """
413 412 indent_spaces = self.indent_spaces
414 413 full_dedent = self._full_dedent
415 414
416 415 inisp = num_ini_spaces(line)
417 416 if inisp < indent_spaces:
418 417 indent_spaces = inisp
419 418 if indent_spaces <= 0:
420 419 #print 'Full dedent in text',self.source # dbg
421 420 full_dedent = True
422 421
423 422 if line.rstrip()[-1] == ':':
424 423 indent_spaces += 4
425 424 elif dedent_re.match(line):
426 425 indent_spaces -= 4
427 426 if indent_spaces <= 0:
428 427 full_dedent = True
429 428
430 429 # Safety
431 430 if indent_spaces < 0:
432 431 indent_spaces = 0
433 432 #print 'safety' # dbg
434 433
435 434 return indent_spaces, full_dedent
436 435
437 436 def _update_indent(self, lines):
438 437 for line in remove_comments(lines).splitlines():
439 438 if line and not line.isspace():
440 439 self.indent_spaces, self._full_dedent = self._find_indent(line)
441 440
442 441 def _store(self, lines, buffer=None, store='source'):
443 442 """Store one or more lines of input.
444 443
445 444 If input lines are not newline-terminated, a newline is automatically
446 445 appended."""
447 446
448 447 if buffer is None:
449 448 buffer = self._buffer
450 449
451 450 if lines.endswith('\n'):
452 451 buffer.append(lines)
453 452 else:
454 453 buffer.append(lines+'\n')
455 454 setattr(self, store, self._set_source(buffer))
456 455
457 456 def _set_source(self, buffer):
458 457 return u''.join(buffer)
459 458
460 459
461 460 class IPythonInputSplitter(InputSplitter):
462 461 """An input splitter that recognizes all of IPython's special syntax."""
463 462
464 463 # String with raw, untransformed input.
465 464 source_raw = ''
466 465
467 466 # Flag to track when a transformer has stored input that it hasn't given
468 467 # back yet.
469 468 transformer_accumulating = False
470 469
471 470 # Flag to track when assemble_python_lines has stored input that it hasn't
472 471 # given back yet.
473 472 within_python_line = False
474 473
475 474 # Private attributes
476 475
477 476 # List with lines of raw input accumulated so far.
478 477 _buffer_raw = None
479 478
480 479 def __init__(self, line_input_checker=True, physical_line_transforms=None,
481 480 logical_line_transforms=None, python_line_transforms=None):
482 481 super(IPythonInputSplitter, self).__init__()
483 482 self._buffer_raw = []
484 483 self._validate = True
485 484
486 485 if physical_line_transforms is not None:
487 486 self.physical_line_transforms = physical_line_transforms
488 487 else:
489 488 self.physical_line_transforms = [leading_indent(),
490 489 classic_prompt(),
491 490 ipy_prompt(),
492 491 ]
493 492
494 493 self.assemble_logical_lines = assemble_logical_lines()
495 494 if logical_line_transforms is not None:
496 495 self.logical_line_transforms = logical_line_transforms
497 496 else:
498 497 self.logical_line_transforms = [cellmagic(end_on_blank_line=line_input_checker),
499 498 help_end(),
500 499 escaped_commands(),
501 500 assign_from_magic(),
502 501 assign_from_system(),
503 502 ]
504 503
505 504 self.assemble_python_lines = assemble_python_lines()
506 505 if python_line_transforms is not None:
507 506 self.python_line_transforms = python_line_transforms
508 507 else:
509 508 # We don't use any of these at present
510 509 self.python_line_transforms = []
511 510
512 511 @property
513 512 def transforms(self):
514 513 "Quick access to all transformers."
515 514 return self.physical_line_transforms + \
516 515 [self.assemble_logical_lines] + self.logical_line_transforms + \
517 516 [self.assemble_python_lines] + self.python_line_transforms
518 517
519 518 @property
520 519 def transforms_in_use(self):
521 520 """Transformers, excluding logical line transformers if we're in a
522 521 Python line."""
523 522 t = self.physical_line_transforms[:]
524 523 if not self.within_python_line:
525 524 t += [self.assemble_logical_lines] + self.logical_line_transforms
526 525 return t + [self.assemble_python_lines] + self.python_line_transforms
527 526
528 527 def reset(self):
529 528 """Reset the input buffer and associated state."""
530 529 super(IPythonInputSplitter, self).reset()
531 530 self._buffer_raw[:] = []
532 531 self.source_raw = ''
533 532 self.transformer_accumulating = False
534 533 self.within_python_line = False
535 534 for t in self.transforms:
536 535 t.reset()
537 536
538 537 def flush_transformers(self):
539 538 def _flush(transform, out):
540 539 if out is not None:
541 540 tmp = transform.push(out)
542 541 return tmp or transform.reset() or None
543 542 else:
544 543 return transform.reset() or None
545 544
546 545 out = None
547 546 for t in self.transforms_in_use:
548 547 out = _flush(t, out)
549 548
550 549 if out is not None:
551 550 self._store(out)
552 551
553 552 def source_raw_reset(self):
554 553 """Return input and raw source and perform a full reset.
555 554 """
556 555 self.flush_transformers()
557 556 out = self.source
558 557 out_r = self.source_raw
559 558 self.reset()
560 559 return out, out_r
561 560
562 561 def source_reset(self):
563 562 self.flush_transformers()
564 563 return super(IPythonInputSplitter, self).source_reset()
565 564
566 565 def push_accepts_more(self):
567 566 if self.transformer_accumulating:
568 567 return True
569 568 else:
570 569 return super(IPythonInputSplitter, self).push_accepts_more()
571 570
572 571 def transform_cell(self, cell):
573 572 """Process and translate a cell of input.
574 573 """
575 574 self.reset()
576 575 self.push(cell)
577 576 return self.source_reset()
578 577
579 578 def push(self, lines):
580 579 """Push one or more lines of IPython input.
581 580
582 581 This stores the given lines and returns a status code indicating
583 582 whether the code forms a complete Python block or not, after processing
584 583 all input lines for special IPython syntax.
585 584
586 585 Any exceptions generated in compilation are swallowed, but if an
587 586 exception was produced, the method returns True.
588 587
589 588 Parameters
590 589 ----------
591 590 lines : string
592 591 One or more lines of Python input.
593 592
594 593 Returns
595 594 -------
596 595 is_complete : boolean
597 596 True if the current input source (the result of the current input
598 597 plus prior inputs) forms a complete Python execution block. Note that
599 598 this value is also stored as a private attribute (_is_complete), so it
600 599 can be queried at any time.
601 600 """
602 601
603 602 # We must ensure all input is pure unicode
604 603 lines = cast_unicode(lines, self.encoding)
605 604
606 605 # ''.splitlines() --> [], but we need to push the empty line to transformers
607 606 lines_list = lines.splitlines()
608 607 if not lines_list:
609 608 lines_list = ['']
610 609
611 610 # Store raw source before applying any transformations to it. Note
612 611 # that this must be done *after* the reset() call that would otherwise
613 612 # flush the buffer.
614 613 self._store(lines, self._buffer_raw, 'source_raw')
615 614
616 615 for line in lines_list:
617 616 out = self.push_line(line)
618 617
619 618 return out
620 619
621 620 def push_line(self, line):
622 621 buf = self._buffer
623 622
624 623 def _accumulating(dbg):
625 624 #print(dbg)
626 625 self.transformer_accumulating = True
627 626 return False
628 627
629 628 for transformer in self.physical_line_transforms:
630 629 line = transformer.push(line)
631 630 if line is None:
632 631 return _accumulating(transformer)
633 632
634 633 if not self.within_python_line:
635 634 line = self.assemble_logical_lines.push(line)
636 635 if line is None:
637 636 return _accumulating('acc logical line')
638 637
639 638 for transformer in self.logical_line_transforms:
640 639 line = transformer.push(line)
641 640 if line is None:
642 641 return _accumulating(transformer)
643 642
644 643 line = self.assemble_python_lines.push(line)
645 644 if line is None:
646 645 self.within_python_line = True
647 646 return _accumulating('acc python line')
648 647 else:
649 648 self.within_python_line = False
650 649
651 650 for transformer in self.python_line_transforms:
652 651 line = transformer.push(line)
653 652 if line is None:
654 653 return _accumulating(transformer)
655 654
656 655 #print("transformers clear") #debug
657 656 self.transformer_accumulating = False
658 657 return super(IPythonInputSplitter, self).push(line)
@@ -1,444 +1,444 b''
1 1 import abc
2 2 import functools
3 3 import re
4 4 from StringIO import StringIO
5 5
6 from IPython.core.splitinput import split_user_input, LineInfo
6 from IPython.core.splitinput import LineInfo
7 7 from IPython.utils import tokenize2
8 8 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Globals
12 12 #-----------------------------------------------------------------------------
13 13
14 14 # The escape sequences that define the syntax transformations IPython will
15 15 # apply to user input. These can NOT be just changed here: many regular
16 16 # expressions and other parts of the code may use their hardcoded values, and
17 17 # for all intents and purposes they constitute the 'IPython syntax', so they
18 18 # should be considered fixed.
19 19
20 20 ESC_SHELL = '!' # Send line to underlying system shell
21 21 ESC_SH_CAP = '!!' # Send line to system shell and capture output
22 22 ESC_HELP = '?' # Find information about object
23 23 ESC_HELP2 = '??' # Find extra-detailed information about object
24 24 ESC_MAGIC = '%' # Call magic function
25 25 ESC_MAGIC2 = '%%' # Call cell-magic function
26 26 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
27 27 ESC_QUOTE2 = ';' # Quote all args as a single string, call
28 28 ESC_PAREN = '/' # Call first argument with rest of line as arguments
29 29
30 30 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
31 31 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
32 32 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
33 33
34 34
35 35 class InputTransformer(object):
36 36 """Abstract base class for line-based input transformers."""
37 37 __metaclass__ = abc.ABCMeta
38 38
39 39 @abc.abstractmethod
40 40 def push(self, line):
41 41 """Send a line of input to the transformer, returning the transformed
42 42 input or None if the transformer is waiting for more input.
43 43
44 44 Must be overridden by subclasses.
45 45 """
46 46 pass
47 47
48 48 @abc.abstractmethod
49 49 def reset(self):
50 50 """Return, transformed any lines that the transformer has accumulated,
51 51 and reset its internal state.
52 52
53 53 Must be overridden by subclasses.
54 54 """
55 55 pass
56 56
57 57 @classmethod
58 58 def wrap(cls, func):
59 59 """Can be used by subclasses as a decorator, to return a factory that
60 60 will allow instantiation with the decorated object.
61 61 """
62 62 @functools.wraps(func)
63 63 def transformer_factory(**kwargs):
64 64 return cls(func, **kwargs)
65 65
66 66 return transformer_factory
67 67
68 68 class StatelessInputTransformer(InputTransformer):
69 69 """Wrapper for a stateless input transformer implemented as a function."""
70 70 def __init__(self, func):
71 71 self.func = func
72 72
73 73 def __repr__(self):
74 74 return "StatelessInputTransformer(func={!r})".format(self.func)
75 75
76 76 def push(self, line):
77 77 """Send a line of input to the transformer, returning the
78 78 transformed input."""
79 79 return self.func(line)
80 80
81 81 def reset(self):
82 82 """No-op - exists for compatibility."""
83 83 pass
84 84
85 85 class CoroutineInputTransformer(InputTransformer):
86 86 """Wrapper for an input transformer implemented as a coroutine."""
87 87 def __init__(self, coro, **kwargs):
88 88 # Prime it
89 89 self.coro = coro(**kwargs)
90 90 next(self.coro)
91 91
92 92 def __repr__(self):
93 93 return "CoroutineInputTransformer(coro={!r})".format(self.coro)
94 94
95 95 def push(self, line):
96 96 """Send a line of input to the transformer, returning the
97 97 transformed input or None if the transformer is waiting for more
98 98 input.
99 99 """
100 100 return self.coro.send(line)
101 101
102 102 def reset(self):
103 103 """Return, transformed any lines that the transformer has
104 104 accumulated, and reset its internal state.
105 105 """
106 106 return self.coro.send(None)
107 107
108 108 class TokenInputTransformer(InputTransformer):
109 109 """Wrapper for a token-based input transformer.
110 110
111 111 func should accept a list of tokens (5-tuples, see tokenize docs), and
112 112 return an iterable which can be passed to tokenize.untokenize().
113 113 """
114 114 def __init__(self, func):
115 115 self.func = func
116 116 self.current_line = ""
117 117 self.line_used = False
118 118 self.reset_tokenizer()
119 119
120 120 def reset_tokenizer(self):
121 121 self.tokenizer = generate_tokens(self.get_line)
122 122
123 123 def get_line(self):
124 124 if self.line_used:
125 125 raise TokenError
126 126 self.line_used = True
127 127 return self.current_line
128 128
129 129 def push(self, line):
130 130 self.current_line += line + "\n"
131 131 if self.current_line.isspace():
132 132 return self.reset()
133 133
134 134 self.line_used = False
135 135 tokens = []
136 136 stop_at_NL = False
137 137 try:
138 138 for intok in self.tokenizer:
139 139 tokens.append(intok)
140 140 t = intok[0]
141 141 if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
142 142 # Stop before we try to pull a line we don't have yet
143 143 break
144 144 elif t == tokenize2.ERRORTOKEN:
145 145 stop_at_NL = True
146 146 except TokenError:
147 147 # Multi-line statement - stop and try again with the next line
148 148 self.reset_tokenizer()
149 149 return None
150 150
151 151 return self.output(tokens)
152 152
153 153 def output(self, tokens):
154 154 self.current_line = ""
155 155 self.reset_tokenizer()
156 156 return untokenize(self.func(tokens)).rstrip('\n')
157 157
158 158 def reset(self):
159 159 l = self.current_line
160 160 self.current_line = ""
161 161 self.reset_tokenizer()
162 162 if l:
163 163 return l.rstrip('\n')
164 164
165 165 class assemble_python_lines(TokenInputTransformer):
166 166 def __init__(self):
167 167 super(assemble_python_lines, self).__init__(None)
168 168
169 169 def output(self, tokens):
170 170 return self.reset()
171 171
172 172 @CoroutineInputTransformer.wrap
173 173 def assemble_logical_lines():
174 174 """Join lines following explicit line continuations (\)"""
175 175 line = ''
176 176 while True:
177 177 line = (yield line)
178 178 if not line or line.isspace():
179 179 continue
180 180
181 181 parts = []
182 182 while line is not None:
183 183 if line.endswith('\\') and (not has_comment(line)):
184 184 parts.append(line[:-1])
185 185 line = (yield None) # Get another line
186 186 else:
187 187 parts.append(line)
188 188 break
189 189
190 190 # Output
191 191 line = ''.join(parts)
192 192
193 193 # Utilities
194 194 def _make_help_call(target, esc, lspace, next_input=None):
195 195 """Prepares a pinfo(2)/psearch call from a target name and the escape
196 196 (i.e. ? or ??)"""
197 197 method = 'pinfo2' if esc == '??' \
198 198 else 'psearch' if '*' in target \
199 199 else 'pinfo'
200 200 arg = " ".join([method, target])
201 201 if next_input is None:
202 202 return '%sget_ipython().magic(%r)' % (lspace, arg)
203 203 else:
204 204 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
205 205 (lspace, next_input, arg)
206 206
207 207 # These define the transformations for the different escape characters.
208 208 def _tr_system(line_info):
209 209 "Translate lines escaped with: !"
210 210 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
211 211 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
212 212
213 213 def _tr_system2(line_info):
214 214 "Translate lines escaped with: !!"
215 215 cmd = line_info.line.lstrip()[2:]
216 216 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
217 217
218 218 def _tr_help(line_info):
219 219 "Translate lines escaped with: ?/??"
220 220 # A naked help line should just fire the intro help screen
221 221 if not line_info.line[1:]:
222 222 return 'get_ipython().show_usage()'
223 223
224 224 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
225 225
226 226 def _tr_magic(line_info):
227 227 "Translate lines escaped with: %"
228 228 tpl = '%sget_ipython().magic(%r)'
229 229 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
230 230 return tpl % (line_info.pre, cmd)
231 231
232 232 def _tr_quote(line_info):
233 233 "Translate lines escaped with: ,"
234 234 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
235 235 '", "'.join(line_info.the_rest.split()) )
236 236
237 237 def _tr_quote2(line_info):
238 238 "Translate lines escaped with: ;"
239 239 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
240 240 line_info.the_rest)
241 241
242 242 def _tr_paren(line_info):
243 243 "Translate lines escaped with: /"
244 244 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
245 245 ", ".join(line_info.the_rest.split()))
246 246
247 247 tr = { ESC_SHELL : _tr_system,
248 248 ESC_SH_CAP : _tr_system2,
249 249 ESC_HELP : _tr_help,
250 250 ESC_HELP2 : _tr_help,
251 251 ESC_MAGIC : _tr_magic,
252 252 ESC_QUOTE : _tr_quote,
253 253 ESC_QUOTE2 : _tr_quote2,
254 254 ESC_PAREN : _tr_paren }
255 255
256 256 @StatelessInputTransformer.wrap
257 257 def escaped_commands(line):
258 258 """Transform escaped commands - %magic, !system, ?help + various autocalls.
259 259 """
260 260 if not line or line.isspace():
261 261 return line
262 262 lineinf = LineInfo(line)
263 263 if lineinf.esc not in tr:
264 264 return line
265 265
266 266 return tr[lineinf.esc](lineinf)
267 267
268 268 _initial_space_re = re.compile(r'\s*')
269 269
270 270 _help_end_re = re.compile(r"""(%{0,2}
271 271 [a-zA-Z_*][\w*]* # Variable name
272 272 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
273 273 )
274 274 (\?\??)$ # ? or ??""",
275 275 re.VERBOSE)
276 276
277 277 def has_comment(src):
278 278 """Indicate whether an input line has (i.e. ends in, or is) a comment.
279 279
280 280 This uses tokenize, so it can distinguish comments from # inside strings.
281 281
282 282 Parameters
283 283 ----------
284 284 src : string
285 285 A single line input string.
286 286
287 287 Returns
288 288 -------
289 289 comment : bool
290 290 True if source has a comment.
291 291 """
292 292 readline = StringIO(src).readline
293 293 toktypes = set()
294 294 try:
295 295 for t in generate_tokens(readline):
296 296 toktypes.add(t[0])
297 297 except TokenError:
298 298 pass
299 299 return(tokenize2.COMMENT in toktypes)
300 300
301 301
302 302 @StatelessInputTransformer.wrap
303 303 def help_end(line):
304 304 """Translate lines with ?/?? at the end"""
305 305 m = _help_end_re.search(line)
306 306 if m is None or has_comment(line):
307 307 return line
308 308 target = m.group(1)
309 309 esc = m.group(3)
310 310 lspace = _initial_space_re.match(line).group(0)
311 311
312 312 # If we're mid-command, put it back on the next prompt for the user.
313 313 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
314 314
315 315 return _make_help_call(target, esc, lspace, next_input)
316 316
317 317
318 318 @CoroutineInputTransformer.wrap
319 319 def cellmagic(end_on_blank_line=False):
320 320 """Captures & transforms cell magics.
321 321
322 322 After a cell magic is started, this stores up any lines it gets until it is
323 323 reset (sent None).
324 324 """
325 325 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
326 326 cellmagic_help_re = re.compile('%%\w+\?')
327 327 line = ''
328 328 while True:
329 329 line = (yield line)
330 330 if (not line) or (not line.startswith(ESC_MAGIC2)):
331 331 continue
332 332
333 333 if cellmagic_help_re.match(line):
334 334 # This case will be handled by help_end
335 335 continue
336 336
337 337 first = line
338 338 body = []
339 339 line = (yield None)
340 340 while (line is not None) and \
341 341 ((line.strip() != '') or not end_on_blank_line):
342 342 body.append(line)
343 343 line = (yield None)
344 344
345 345 # Output
346 346 magic_name, _, first = first.partition(' ')
347 347 magic_name = magic_name.lstrip(ESC_MAGIC2)
348 348 line = tpl % (magic_name, first, u'\n'.join(body))
349 349
350 350
351 351 def _strip_prompts(prompt_re):
352 352 """Remove matching input prompts from a block of input."""
353 353 line = ''
354 354 while True:
355 355 line = (yield line)
356 356
357 357 # First line of cell
358 358 if line is None:
359 359 continue
360 360 out, n1 = prompt_re.subn('', line, count=1)
361 361 line = (yield out)
362 362
363 363 # Second line of cell, because people often copy from just after the
364 364 # first prompt, so we might not see it in the first line.
365 365 if line is None:
366 366 continue
367 367 out, n2 = prompt_re.subn('', line, count=1)
368 368 line = (yield out)
369 369
370 370 if n1 or n2:
371 371 # Found the input prompt in the first two lines - check for it in
372 372 # the rest of the cell as well.
373 373 while line is not None:
374 374 line = (yield prompt_re.sub('', line, count=1))
375 375
376 376 else:
377 377 # Prompts not in input - wait for reset
378 378 while line is not None:
379 379 line = (yield line)
380 380
381 381 @CoroutineInputTransformer.wrap
382 382 def classic_prompt():
383 383 """Strip the >>>/... prompts of the Python interactive shell."""
384 384 prompt_re = re.compile(r'^(>>> ?|^\.\.\. ?)')
385 385 return _strip_prompts(prompt_re)
386 386
387 387 @CoroutineInputTransformer.wrap
388 388 def ipy_prompt():
389 389 """Strip IPython's In [1]:/...: prompts."""
390 390 prompt_re = re.compile(r'^(In \[\d+\]: |^\ \ \ \.\.\.+: )')
391 391 return _strip_prompts(prompt_re)
392 392
393 393
394 394 @CoroutineInputTransformer.wrap
395 395 def leading_indent():
396 396 """Remove leading indentation.
397 397
398 398 If the first line starts with a spaces or tabs, the same whitespace will be
399 399 removed from each following line until it is reset.
400 400 """
401 401 space_re = re.compile(r'^[ \t]+')
402 402 line = ''
403 403 while True:
404 404 line = (yield line)
405 405
406 406 if line is None:
407 407 continue
408 408
409 409 m = space_re.match(line)
410 410 if m:
411 411 space = m.group(0)
412 412 while line is not None:
413 413 if line.startswith(space):
414 414 line = line[len(space):]
415 415 line = (yield line)
416 416 else:
417 417 # No leading spaces - wait for reset
418 418 while line is not None:
419 419 line = (yield line)
420 420
421 421
422 422 assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
423 423 r'\s*=\s*!\s*(?P<cmd>.*)')
424 424 assign_system_template = '%s = get_ipython().getoutput(%r)'
425 425 @StatelessInputTransformer.wrap
426 426 def assign_from_system(line):
427 427 """Transform assignment from system commands (e.g. files = !ls)"""
428 428 m = assign_system_re.match(line)
429 429 if m is None:
430 430 return line
431 431
432 432 return assign_system_template % m.group('lhs', 'cmd')
433 433
434 434 assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
435 435 r'\s*=\s*%\s*(?P<cmd>.*)')
436 436 assign_magic_template = '%s = get_ipython().magic(%r)'
437 437 @StatelessInputTransformer.wrap
438 438 def assign_from_magic(line):
439 439 """Transform assignment from magic commands (e.g. a = %who_ls)"""
440 440 m = assign_magic_re.match(line)
441 441 if m is None:
442 442 return line
443 443
444 444 return assign_magic_template % m.group('lhs', 'cmd')
@@ -1,677 +1,676 b''
1 1 # encoding: utf-8
2 2 """Magic functions for InteractiveShell.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 8 # Copyright (C) 2008 The IPython Development Team
9 9
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 # Stdlib
18 import json
19 18 import os
20 19 import re
21 20 import sys
22 21 import types
23 22 from getopt import getopt, GetoptError
24 23
25 24 # Our own
26 25 from IPython.config.configurable import Configurable
27 26 from IPython.core import oinspect
28 27 from IPython.core.error import UsageError
29 28 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
30 29 from IPython.external.decorator import decorator
31 30 from IPython.utils.ipstruct import Struct
32 31 from IPython.utils.process import arg_split
33 32 from IPython.utils.text import dedent
34 33 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
35 34 from IPython.utils.warn import error
36 35
37 36 #-----------------------------------------------------------------------------
38 37 # Globals
39 38 #-----------------------------------------------------------------------------
40 39
41 40 # A dict we'll use for each class that has magics, used as temporary storage to
42 41 # pass information between the @line/cell_magic method decorators and the
43 42 # @magics_class class decorator, because the method decorators have no
44 43 # access to the class when they run. See for more details:
45 44 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
46 45
47 46 magics = dict(line={}, cell={})
48 47
49 48 magic_kinds = ('line', 'cell')
50 49 magic_spec = ('line', 'cell', 'line_cell')
51 50 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
52 51
53 52 #-----------------------------------------------------------------------------
54 53 # Utility classes and functions
55 54 #-----------------------------------------------------------------------------
56 55
57 56 class Bunch: pass
58 57
59 58
60 59 def on_off(tag):
61 60 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
62 61 return ['OFF','ON'][tag]
63 62
64 63
65 64 def compress_dhist(dh):
66 65 """Compress a directory history into a new one with at most 20 entries.
67 66
68 67 Return a new list made from the first and last 10 elements of dhist after
69 68 removal of duplicates.
70 69 """
71 70 head, tail = dh[:-10], dh[-10:]
72 71
73 72 newhead = []
74 73 done = set()
75 74 for h in head:
76 75 if h in done:
77 76 continue
78 77 newhead.append(h)
79 78 done.add(h)
80 79
81 80 return newhead + tail
82 81
83 82
84 83 def needs_local_scope(func):
85 84 """Decorator to mark magic functions which need to local scope to run."""
86 85 func.needs_local_scope = True
87 86 return func
88 87
89 88 #-----------------------------------------------------------------------------
90 89 # Class and method decorators for registering magics
91 90 #-----------------------------------------------------------------------------
92 91
93 92 def magics_class(cls):
94 93 """Class decorator for all subclasses of the main Magics class.
95 94
96 95 Any class that subclasses Magics *must* also apply this decorator, to
97 96 ensure that all the methods that have been decorated as line/cell magics
98 97 get correctly registered in the class instance. This is necessary because
99 98 when method decorators run, the class does not exist yet, so they
100 99 temporarily store their information into a module global. Application of
101 100 this class decorator copies that global data to the class instance and
102 101 clears the global.
103 102
104 103 Obviously, this mechanism is not thread-safe, which means that the
105 104 *creation* of subclasses of Magic should only be done in a single-thread
106 105 context. Instantiation of the classes has no restrictions. Given that
107 106 these classes are typically created at IPython startup time and before user
108 107 application code becomes active, in practice this should not pose any
109 108 problems.
110 109 """
111 110 cls.registered = True
112 111 cls.magics = dict(line = magics['line'],
113 112 cell = magics['cell'])
114 113 magics['line'] = {}
115 114 magics['cell'] = {}
116 115 return cls
117 116
118 117
119 118 def record_magic(dct, magic_kind, magic_name, func):
120 119 """Utility function to store a function as a magic of a specific kind.
121 120
122 121 Parameters
123 122 ----------
124 123 dct : dict
125 124 A dictionary with 'line' and 'cell' subdicts.
126 125
127 126 magic_kind : str
128 127 Kind of magic to be stored.
129 128
130 129 magic_name : str
131 130 Key to store the magic as.
132 131
133 132 func : function
134 133 Callable object to store.
135 134 """
136 135 if magic_kind == 'line_cell':
137 136 dct['line'][magic_name] = dct['cell'][magic_name] = func
138 137 else:
139 138 dct[magic_kind][magic_name] = func
140 139
141 140
142 141 def validate_type(magic_kind):
143 142 """Ensure that the given magic_kind is valid.
144 143
145 144 Check that the given magic_kind is one of the accepted spec types (stored
146 145 in the global `magic_spec`), raise ValueError otherwise.
147 146 """
148 147 if magic_kind not in magic_spec:
149 148 raise ValueError('magic_kind must be one of %s, %s given' %
150 149 magic_kinds, magic_kind)
151 150
152 151
153 152 # The docstrings for the decorator below will be fairly similar for the two
154 153 # types (method and function), so we generate them here once and reuse the
155 154 # templates below.
156 155 _docstring_template = \
157 156 """Decorate the given {0} as {1} magic.
158 157
159 158 The decorator can be used with or without arguments, as follows.
160 159
161 160 i) without arguments: it will create a {1} magic named as the {0} being
162 161 decorated::
163 162
164 163 @deco
165 164 def foo(...)
166 165
167 166 will create a {1} magic named `foo`.
168 167
169 168 ii) with one string argument: which will be used as the actual name of the
170 169 resulting magic::
171 170
172 171 @deco('bar')
173 172 def foo(...)
174 173
175 174 will create a {1} magic named `bar`.
176 175 """
177 176
178 177 # These two are decorator factories. While they are conceptually very similar,
179 178 # there are enough differences in the details that it's simpler to have them
180 179 # written as completely standalone functions rather than trying to share code
181 180 # and make a single one with convoluted logic.
182 181
183 182 def _method_magic_marker(magic_kind):
184 183 """Decorator factory for methods in Magics subclasses.
185 184 """
186 185
187 186 validate_type(magic_kind)
188 187
189 188 # This is a closure to capture the magic_kind. We could also use a class,
190 189 # but it's overkill for just that one bit of state.
191 190 def magic_deco(arg):
192 191 call = lambda f, *a, **k: f(*a, **k)
193 192
194 193 if callable(arg):
195 194 # "Naked" decorator call (just @foo, no args)
196 195 func = arg
197 196 name = func.func_name
198 197 retval = decorator(call, func)
199 198 record_magic(magics, magic_kind, name, name)
200 199 elif isinstance(arg, basestring):
201 200 # Decorator called with arguments (@foo('bar'))
202 201 name = arg
203 202 def mark(func, *a, **kw):
204 203 record_magic(magics, magic_kind, name, func.func_name)
205 204 return decorator(call, func)
206 205 retval = mark
207 206 else:
208 207 raise TypeError("Decorator can only be called with "
209 208 "string or function")
210 209 return retval
211 210
212 211 # Ensure the resulting decorator has a usable docstring
213 212 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
214 213 return magic_deco
215 214
216 215
217 216 def _function_magic_marker(magic_kind):
218 217 """Decorator factory for standalone functions.
219 218 """
220 219 validate_type(magic_kind)
221 220
222 221 # This is a closure to capture the magic_kind. We could also use a class,
223 222 # but it's overkill for just that one bit of state.
224 223 def magic_deco(arg):
225 224 call = lambda f, *a, **k: f(*a, **k)
226 225
227 226 # Find get_ipython() in the caller's namespace
228 227 caller = sys._getframe(1)
229 228 for ns in ['f_locals', 'f_globals', 'f_builtins']:
230 229 get_ipython = getattr(caller, ns).get('get_ipython')
231 230 if get_ipython is not None:
232 231 break
233 232 else:
234 233 raise NameError('Decorator can only run in context where '
235 234 '`get_ipython` exists')
236 235
237 236 ip = get_ipython()
238 237
239 238 if callable(arg):
240 239 # "Naked" decorator call (just @foo, no args)
241 240 func = arg
242 241 name = func.func_name
243 242 ip.register_magic_function(func, magic_kind, name)
244 243 retval = decorator(call, func)
245 244 elif isinstance(arg, basestring):
246 245 # Decorator called with arguments (@foo('bar'))
247 246 name = arg
248 247 def mark(func, *a, **kw):
249 248 ip.register_magic_function(func, magic_kind, name)
250 249 return decorator(call, func)
251 250 retval = mark
252 251 else:
253 252 raise TypeError("Decorator can only be called with "
254 253 "string or function")
255 254 return retval
256 255
257 256 # Ensure the resulting decorator has a usable docstring
258 257 ds = _docstring_template.format('function', magic_kind)
259 258
260 259 ds += dedent("""
261 260 Note: this decorator can only be used in a context where IPython is already
262 261 active, so that the `get_ipython()` call succeeds. You can therefore use
263 262 it in your startup files loaded after IPython initializes, but *not* in the
264 263 IPython configuration file itself, which is executed before IPython is
265 264 fully up and running. Any file located in the `startup` subdirectory of
266 265 your configuration profile will be OK in this sense.
267 266 """)
268 267
269 268 magic_deco.__doc__ = ds
270 269 return magic_deco
271 270
272 271
273 272 # Create the actual decorators for public use
274 273
275 274 # These three are used to decorate methods in class definitions
276 275 line_magic = _method_magic_marker('line')
277 276 cell_magic = _method_magic_marker('cell')
278 277 line_cell_magic = _method_magic_marker('line_cell')
279 278
280 279 # These three decorate standalone functions and perform the decoration
281 280 # immediately. They can only run where get_ipython() works
282 281 register_line_magic = _function_magic_marker('line')
283 282 register_cell_magic = _function_magic_marker('cell')
284 283 register_line_cell_magic = _function_magic_marker('line_cell')
285 284
286 285 #-----------------------------------------------------------------------------
287 286 # Core Magic classes
288 287 #-----------------------------------------------------------------------------
289 288
290 289 class MagicsManager(Configurable):
291 290 """Object that handles all magic-related functionality for IPython.
292 291 """
293 292 # Non-configurable class attributes
294 293
295 294 # A two-level dict, first keyed by magic type, then by magic function, and
296 295 # holding the actual callable object as value. This is the dict used for
297 296 # magic function dispatch
298 297 magics = Dict
299 298
300 299 # A registry of the original objects that we've been given holding magics.
301 300 registry = Dict
302 301
303 302 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
304 303
305 304 auto_magic = Bool(True, config=True, help=
306 305 "Automatically call line magics without requiring explicit % prefix")
307 306
308 307 def _auto_magic_changed(self, name, value):
309 308 self.shell.automagic = value
310 309
311 310 _auto_status = [
312 311 'Automagic is OFF, % prefix IS needed for line magics.',
313 312 'Automagic is ON, % prefix IS NOT needed for line magics.']
314 313
315 314 user_magics = Instance('IPython.core.magics.UserMagics')
316 315
317 316 def __init__(self, shell=None, config=None, user_magics=None, **traits):
318 317
319 318 super(MagicsManager, self).__init__(shell=shell, config=config,
320 319 user_magics=user_magics, **traits)
321 320 self.magics = dict(line={}, cell={})
322 321 # Let's add the user_magics to the registry for uniformity, so *all*
323 322 # registered magic containers can be found there.
324 323 self.registry[user_magics.__class__.__name__] = user_magics
325 324
326 325 def auto_status(self):
327 326 """Return descriptive string with automagic status."""
328 327 return self._auto_status[self.auto_magic]
329 328
330 329 def lsmagic(self):
331 330 """Return a dict of currently available magic functions.
332 331
333 332 The return dict has the keys 'line' and 'cell', corresponding to the
334 333 two types of magics we support. Each value is a list of names.
335 334 """
336 335 return self.magics
337 336
338 337 def lsmagic_docs(self, brief=False, missing=''):
339 338 """Return dict of documentation of magic functions.
340 339
341 340 The return dict has the keys 'line' and 'cell', corresponding to the
342 341 two types of magics we support. Each value is a dict keyed by magic
343 342 name whose value is the function docstring. If a docstring is
344 343 unavailable, the value of `missing` is used instead.
345 344
346 345 If brief is True, only the first line of each docstring will be returned.
347 346 """
348 347 docs = {}
349 348 for m_type in self.magics:
350 349 m_docs = {}
351 350 for m_name, m_func in self.magics[m_type].iteritems():
352 351 if m_func.__doc__:
353 352 if brief:
354 353 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
355 354 else:
356 355 m_docs[m_name] = m_func.__doc__.rstrip()
357 356 else:
358 357 m_docs[m_name] = missing
359 358 docs[m_type] = m_docs
360 359 return docs
361 360
362 361 def register(self, *magic_objects):
363 362 """Register one or more instances of Magics.
364 363
365 364 Take one or more classes or instances of classes that subclass the main
366 365 `core.Magic` class, and register them with IPython to use the magic
367 366 functions they provide. The registration process will then ensure that
368 367 any methods that have decorated to provide line and/or cell magics will
369 368 be recognized with the `%x`/`%%x` syntax as a line/cell magic
370 369 respectively.
371 370
372 371 If classes are given, they will be instantiated with the default
373 372 constructor. If your classes need a custom constructor, you should
374 373 instanitate them first and pass the instance.
375 374
376 375 The provided arguments can be an arbitrary mix of classes and instances.
377 376
378 377 Parameters
379 378 ----------
380 379 magic_objects : one or more classes or instances
381 380 """
382 381 # Start by validating them to ensure they have all had their magic
383 382 # methods registered at the instance level
384 383 for m in magic_objects:
385 384 if not m.registered:
386 385 raise ValueError("Class of magics %r was constructed without "
387 386 "the @register_magics class decorator")
388 387 if type(m) in (type, MetaHasTraits):
389 388 # If we're given an uninstantiated class
390 389 m = m(shell=self.shell)
391 390
392 391 # Now that we have an instance, we can register it and update the
393 392 # table of callables
394 393 self.registry[m.__class__.__name__] = m
395 394 for mtype in magic_kinds:
396 395 self.magics[mtype].update(m.magics[mtype])
397 396
398 397 def register_function(self, func, magic_kind='line', magic_name=None):
399 398 """Expose a standalone function as magic function for IPython.
400 399
401 400 This will create an IPython magic (line, cell or both) from a
402 401 standalone function. The functions should have the following
403 402 signatures:
404 403
405 404 * For line magics: `def f(line)`
406 405 * For cell magics: `def f(line, cell)`
407 406 * For a function that does both: `def f(line, cell=None)`
408 407
409 408 In the latter case, the function will be called with `cell==None` when
410 409 invoked as `%f`, and with cell as a string when invoked as `%%f`.
411 410
412 411 Parameters
413 412 ----------
414 413 func : callable
415 414 Function to be registered as a magic.
416 415
417 416 magic_kind : str
418 417 Kind of magic, one of 'line', 'cell' or 'line_cell'
419 418
420 419 magic_name : optional str
421 420 If given, the name the magic will have in the IPython namespace. By
422 421 default, the name of the function itself is used.
423 422 """
424 423
425 424 # Create the new method in the user_magics and register it in the
426 425 # global table
427 426 validate_type(magic_kind)
428 427 magic_name = func.func_name if magic_name is None else magic_name
429 428 setattr(self.user_magics, magic_name, func)
430 429 record_magic(self.magics, magic_kind, magic_name, func)
431 430
432 431 def define_magic(self, name, func):
433 432 """[Deprecated] Expose own function as magic function for IPython.
434 433
435 434 Example::
436 435
437 436 def foo_impl(self, parameter_s=''):
438 437 'My very own magic!. (Use docstrings, IPython reads them).'
439 438 print 'Magic function. Passed parameter is between < >:'
440 439 print '<%s>' % parameter_s
441 440 print 'The self object is:', self
442 441
443 442 ip.define_magic('foo',foo_impl)
444 443 """
445 444 meth = types.MethodType(func, self.user_magics)
446 445 setattr(self.user_magics, name, meth)
447 446 record_magic(self.magics, 'line', name, meth)
448 447
449 448 def register_alias(self, alias_name, magic_name, magic_kind='line'):
450 449 """Register an alias to a magic function.
451 450
452 451 The alias is an instance of :class:`MagicAlias`, which holds the
453 452 name and kind of the magic it should call. Binding is done at
454 453 call time, so if the underlying magic function is changed the alias
455 454 will call the new function.
456 455
457 456 Parameters
458 457 ----------
459 458 alias_name : str
460 459 The name of the magic to be registered.
461 460
462 461 magic_name : str
463 462 The name of an existing magic.
464 463
465 464 magic_kind : str
466 465 Kind of magic, one of 'line' or 'cell'
467 466 """
468 467
469 468 # `validate_type` is too permissive, as it allows 'line_cell'
470 469 # which we do not handle.
471 470 if magic_kind not in magic_kinds:
472 471 raise ValueError('magic_kind must be one of %s, %s given' %
473 472 magic_kinds, magic_kind)
474 473
475 474 alias = MagicAlias(self.shell, magic_name, magic_kind)
476 475 setattr(self.user_magics, alias_name, alias)
477 476 record_magic(self.magics, magic_kind, alias_name, alias)
478 477
479 478 # Key base class that provides the central functionality for magics.
480 479
481 480 class Magics(object):
482 481 """Base class for implementing magic functions.
483 482
484 483 Shell functions which can be reached as %function_name. All magic
485 484 functions should accept a string, which they can parse for their own
486 485 needs. This can make some functions easier to type, eg `%cd ../`
487 486 vs. `%cd("../")`
488 487
489 488 Classes providing magic functions need to subclass this class, and they
490 489 MUST:
491 490
492 491 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
493 492 individual methods as magic functions, AND
494 493
495 494 - Use the class decorator `@magics_class` to ensure that the magic
496 495 methods are properly registered at the instance level upon instance
497 496 initialization.
498 497
499 498 See :mod:`magic_functions` for examples of actual implementation classes.
500 499 """
501 500 # Dict holding all command-line options for each magic.
502 501 options_table = None
503 502 # Dict for the mapping of magic names to methods, set by class decorator
504 503 magics = None
505 504 # Flag to check that the class decorator was properly applied
506 505 registered = False
507 506 # Instance of IPython shell
508 507 shell = None
509 508
510 509 def __init__(self, shell):
511 510 if not(self.__class__.registered):
512 511 raise ValueError('Magics subclass without registration - '
513 512 'did you forget to apply @magics_class?')
514 513 self.shell = shell
515 514 self.options_table = {}
516 515 # The method decorators are run when the instance doesn't exist yet, so
517 516 # they can only record the names of the methods they are supposed to
518 517 # grab. Only now, that the instance exists, can we create the proper
519 518 # mapping to bound methods. So we read the info off the original names
520 519 # table and replace each method name by the actual bound method.
521 520 # But we mustn't clobber the *class* mapping, in case of multiple instances.
522 521 class_magics = self.magics
523 522 self.magics = {}
524 523 for mtype in magic_kinds:
525 524 tab = self.magics[mtype] = {}
526 525 cls_tab = class_magics[mtype]
527 526 for magic_name, meth_name in cls_tab.iteritems():
528 527 if isinstance(meth_name, basestring):
529 528 # it's a method name, grab it
530 529 tab[magic_name] = getattr(self, meth_name)
531 530 else:
532 531 # it's the real thing
533 532 tab[magic_name] = meth_name
534 533
535 534 def arg_err(self,func):
536 535 """Print docstring if incorrect arguments were passed"""
537 536 print 'Error in arguments:'
538 537 print oinspect.getdoc(func)
539 538
540 539 def format_latex(self, strng):
541 540 """Format a string for latex inclusion."""
542 541
543 542 # Characters that need to be escaped for latex:
544 543 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
545 544 # Magic command names as headers:
546 545 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
547 546 re.MULTILINE)
548 547 # Magic commands
549 548 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
550 549 re.MULTILINE)
551 550 # Paragraph continue
552 551 par_re = re.compile(r'\\$',re.MULTILINE)
553 552
554 553 # The "\n" symbol
555 554 newline_re = re.compile(r'\\n')
556 555
557 556 # Now build the string for output:
558 557 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
559 558 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
560 559 strng)
561 560 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
562 561 strng = par_re.sub(r'\\\\',strng)
563 562 strng = escape_re.sub(r'\\\1',strng)
564 563 strng = newline_re.sub(r'\\textbackslash{}n',strng)
565 564 return strng
566 565
567 566 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
568 567 """Parse options passed to an argument string.
569 568
570 569 The interface is similar to that of getopt(), but it returns back a
571 570 Struct with the options as keys and the stripped argument string still
572 571 as a string.
573 572
574 573 arg_str is quoted as a true sys.argv vector by using shlex.split.
575 574 This allows us to easily expand variables, glob files, quote
576 575 arguments, etc.
577 576
578 577 Options:
579 578 -mode: default 'string'. If given as 'list', the argument string is
580 579 returned as a list (split on whitespace) instead of a string.
581 580
582 581 -list_all: put all option values in lists. Normally only options
583 582 appearing more than once are put in a list.
584 583
585 584 -posix (True): whether to split the input line in POSIX mode or not,
586 585 as per the conventions outlined in the shlex module from the
587 586 standard library."""
588 587
589 588 # inject default options at the beginning of the input line
590 589 caller = sys._getframe(1).f_code.co_name
591 590 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
592 591
593 592 mode = kw.get('mode','string')
594 593 if mode not in ['string','list']:
595 594 raise ValueError('incorrect mode given: %s' % mode)
596 595 # Get options
597 596 list_all = kw.get('list_all',0)
598 597 posix = kw.get('posix', os.name == 'posix')
599 598 strict = kw.get('strict', True)
600 599
601 600 # Check if we have more than one argument to warrant extra processing:
602 601 odict = {} # Dictionary with options
603 602 args = arg_str.split()
604 603 if len(args) >= 1:
605 604 # If the list of inputs only has 0 or 1 thing in it, there's no
606 605 # need to look for options
607 606 argv = arg_split(arg_str, posix, strict)
608 607 # Do regular option processing
609 608 try:
610 609 opts,args = getopt(argv, opt_str, long_opts)
611 610 except GetoptError as e:
612 611 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
613 612 " ".join(long_opts)))
614 613 for o,a in opts:
615 614 if o.startswith('--'):
616 615 o = o[2:]
617 616 else:
618 617 o = o[1:]
619 618 try:
620 619 odict[o].append(a)
621 620 except AttributeError:
622 621 odict[o] = [odict[o],a]
623 622 except KeyError:
624 623 if list_all:
625 624 odict[o] = [a]
626 625 else:
627 626 odict[o] = a
628 627
629 628 # Prepare opts,args for return
630 629 opts = Struct(odict)
631 630 if mode == 'string':
632 631 args = ' '.join(args)
633 632
634 633 return opts,args
635 634
636 635 def default_option(self, fn, optstr):
637 636 """Make an entry in the options_table for fn, with value optstr"""
638 637
639 638 if fn not in self.lsmagic():
640 639 error("%s is not a magic function" % fn)
641 640 self.options_table[fn] = optstr
642 641
643 642 class MagicAlias(object):
644 643 """An alias to another magic function.
645 644
646 645 An alias is determined by its magic name and magic kind. Lookup
647 646 is done at call time, so if the underlying magic changes the alias
648 647 will call the new function.
649 648
650 649 Use the :meth:`MagicsManager.register_alias` method or the
651 650 `%alias_magic` magic function to create and register a new alias.
652 651 """
653 652 def __init__(self, shell, magic_name, magic_kind):
654 653 self.shell = shell
655 654 self.magic_name = magic_name
656 655 self.magic_kind = magic_kind
657 656
658 657 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
659 658 self.__doc__ = "Alias for `%s`." % self.pretty_target
660 659
661 660 self._in_call = False
662 661
663 662 def __call__(self, *args, **kwargs):
664 663 """Call the magic alias."""
665 664 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
666 665 if fn is None:
667 666 raise UsageError("Magic `%s` not found." % self.pretty_target)
668 667
669 668 # Protect against infinite recursion.
670 669 if self._in_call:
671 670 raise UsageError("Infinite recursion detected; "
672 671 "magic aliases cannot call themselves.")
673 672 self._in_call = True
674 673 try:
675 674 return fn(*args, **kwargs)
676 675 finally:
677 676 self._in_call = False
@@ -1,648 +1,647 b''
1 1 """Implementation of basic magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14 from __future__ import print_function
15 15
16 16 # Stdlib
17 17 import io
18 18 import json
19 19 import sys
20 20 from pprint import pformat
21 21
22 22 # Our own packages
23 from IPython.core import magic_arguments
23 from IPython.core import magic_arguments, page
24 24 from IPython.core.error import UsageError
25 25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
26 26 from IPython.utils.text import format_screen, dedent, indent
27 from IPython.core import magic_arguments, page
28 27 from IPython.testing.skipdoctest import skip_doctest
29 28 from IPython.utils.ipstruct import Struct
30 29 from IPython.utils.path import unquote_filename
31 30 from IPython.utils.warn import warn, error
32 31
33 32 #-----------------------------------------------------------------------------
34 33 # Magics class implementation
35 34 #-----------------------------------------------------------------------------
36 35
37 36 class MagicsDisplay(object):
38 37 def __init__(self, magics_manager):
39 38 self.magics_manager = magics_manager
40 39
41 40 def _lsmagic(self):
42 41 """The main implementation of the %lsmagic"""
43 42 mesc = magic_escapes['line']
44 43 cesc = magic_escapes['cell']
45 44 mman = self.magics_manager
46 45 magics = mman.lsmagic()
47 46 out = ['Available line magics:',
48 47 mesc + (' '+mesc).join(sorted(magics['line'])),
49 48 '',
50 49 'Available cell magics:',
51 50 cesc + (' '+cesc).join(sorted(magics['cell'])),
52 51 '',
53 52 mman.auto_status()]
54 53 return '\n'.join(out)
55 54
56 55 def _repr_pretty_(self, p, cycle):
57 56 p.text(self._lsmagic())
58 57
59 58 def __str__(self):
60 59 return self._lsmagic()
61 60
62 61 def _jsonable(self):
63 62 """turn magics dict into jsonable dict of the same structure
64 63
65 64 replaces object instances with their class names as strings
66 65 """
67 66 magic_dict = {}
68 67 mman = self.magics_manager
69 68 magics = mman.lsmagic()
70 69 for key, subdict in magics.items():
71 70 d = {}
72 71 magic_dict[key] = d
73 72 for name, obj in subdict.items():
74 73 try:
75 74 classname = obj.im_class.__name__
76 75 except AttributeError:
77 76 classname = 'Other'
78 77
79 78 d[name] = classname
80 79 return magic_dict
81 80
82 81 def _repr_json_(self):
83 82 return json.dumps(self._jsonable())
84 83
85 84
86 85 @magics_class
87 86 class BasicMagics(Magics):
88 87 """Magics that provide central IPython functionality.
89 88
90 89 These are various magics that don't fit into specific categories but that
91 90 are all part of the base 'IPython experience'."""
92 91
93 92 @magic_arguments.magic_arguments()
94 93 @magic_arguments.argument(
95 94 '-l', '--line', action='store_true',
96 95 help="""Create a line magic alias."""
97 96 )
98 97 @magic_arguments.argument(
99 98 '-c', '--cell', action='store_true',
100 99 help="""Create a cell magic alias."""
101 100 )
102 101 @magic_arguments.argument(
103 102 'name',
104 103 help="""Name of the magic to be created."""
105 104 )
106 105 @magic_arguments.argument(
107 106 'target',
108 107 help="""Name of the existing line or cell magic."""
109 108 )
110 109 @line_magic
111 110 def alias_magic(self, line=''):
112 111 """Create an alias for an existing line or cell magic.
113 112
114 113 Examples
115 114 --------
116 115 ::
117 116 In [1]: %alias_magic t timeit
118 117 Created `%t` as an alias for `%timeit`.
119 118 Created `%%t` as an alias for `%%timeit`.
120 119
121 120 In [2]: %t -n1 pass
122 121 1 loops, best of 3: 954 ns per loop
123 122
124 123 In [3]: %%t -n1
125 124 ...: pass
126 125 ...:
127 126 1 loops, best of 3: 954 ns per loop
128 127
129 128 In [4]: %alias_magic --cell whereami pwd
130 129 UsageError: Cell magic function `%%pwd` not found.
131 130 In [5]: %alias_magic --line whereami pwd
132 131 Created `%whereami` as an alias for `%pwd`.
133 132
134 133 In [6]: %whereami
135 134 Out[6]: u'/home/testuser'
136 135 """
137 136 args = magic_arguments.parse_argstring(self.alias_magic, line)
138 137 shell = self.shell
139 138 mman = self.shell.magics_manager
140 139 escs = ''.join(magic_escapes.values())
141 140
142 141 target = args.target.lstrip(escs)
143 142 name = args.name.lstrip(escs)
144 143
145 144 # Find the requested magics.
146 145 m_line = shell.find_magic(target, 'line')
147 146 m_cell = shell.find_magic(target, 'cell')
148 147 if args.line and m_line is None:
149 148 raise UsageError('Line magic function `%s%s` not found.' %
150 149 (magic_escapes['line'], target))
151 150 if args.cell and m_cell is None:
152 151 raise UsageError('Cell magic function `%s%s` not found.' %
153 152 (magic_escapes['cell'], target))
154 153
155 154 # If --line and --cell are not specified, default to the ones
156 155 # that are available.
157 156 if not args.line and not args.cell:
158 157 if not m_line and not m_cell:
159 158 raise UsageError(
160 159 'No line or cell magic with name `%s` found.' % target
161 160 )
162 161 args.line = bool(m_line)
163 162 args.cell = bool(m_cell)
164 163
165 164 if args.line:
166 165 mman.register_alias(name, target, 'line')
167 166 print('Created `%s%s` as an alias for `%s%s`.' % (
168 167 magic_escapes['line'], name,
169 168 magic_escapes['line'], target))
170 169
171 170 if args.cell:
172 171 mman.register_alias(name, target, 'cell')
173 172 print('Created `%s%s` as an alias for `%s%s`.' % (
174 173 magic_escapes['cell'], name,
175 174 magic_escapes['cell'], target))
176 175
177 176 @line_magic
178 177 def lsmagic(self, parameter_s=''):
179 178 """List currently available magic functions."""
180 179 return MagicsDisplay(self.shell.magics_manager)
181 180
182 181 def _magic_docs(self, brief=False, rest=False):
183 182 """Return docstrings from magic functions."""
184 183 mman = self.shell.magics_manager
185 184 docs = mman.lsmagic_docs(brief, missing='No documentation')
186 185
187 186 if rest:
188 187 format_string = '**%s%s**::\n\n%s\n\n'
189 188 else:
190 189 format_string = '%s%s:\n%s\n'
191 190
192 191 return ''.join(
193 192 [format_string % (magic_escapes['line'], fname,
194 193 indent(dedent(fndoc)))
195 194 for fname, fndoc in sorted(docs['line'].items())]
196 195 +
197 196 [format_string % (magic_escapes['cell'], fname,
198 197 indent(dedent(fndoc)))
199 198 for fname, fndoc in sorted(docs['cell'].items())]
200 199 )
201 200
202 201 @line_magic
203 202 def magic(self, parameter_s=''):
204 203 """Print information about the magic function system.
205 204
206 205 Supported formats: -latex, -brief, -rest
207 206 """
208 207
209 208 mode = ''
210 209 try:
211 210 mode = parameter_s.split()[0][1:]
212 211 if mode == 'rest':
213 212 rest_docs = []
214 213 except IndexError:
215 214 pass
216 215
217 216 brief = (mode == 'brief')
218 217 rest = (mode == 'rest')
219 218 magic_docs = self._magic_docs(brief, rest)
220 219
221 220 if mode == 'latex':
222 221 print(self.format_latex(magic_docs))
223 222 return
224 223 else:
225 224 magic_docs = format_screen(magic_docs)
226 225
227 226 out = ["""
228 227 IPython's 'magic' functions
229 228 ===========================
230 229
231 230 The magic function system provides a series of functions which allow you to
232 231 control the behavior of IPython itself, plus a lot of system-type
233 232 features. There are two kinds of magics, line-oriented and cell-oriented.
234 233
235 234 Line magics are prefixed with the % character and work much like OS
236 235 command-line calls: they get as an argument the rest of the line, where
237 236 arguments are passed without parentheses or quotes. For example, this will
238 237 time the given statement::
239 238
240 239 %timeit range(1000)
241 240
242 241 Cell magics are prefixed with a double %%, and they are functions that get as
243 242 an argument not only the rest of the line, but also the lines below it in a
244 243 separate argument. These magics are called with two arguments: the rest of the
245 244 call line and the body of the cell, consisting of the lines below the first.
246 245 For example::
247 246
248 247 %%timeit x = numpy.random.randn((100, 100))
249 248 numpy.linalg.svd(x)
250 249
251 250 will time the execution of the numpy svd routine, running the assignment of x
252 251 as part of the setup phase, which is not timed.
253 252
254 253 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 254 input with %% will automatically enter cell mode, and IPython will continue
256 255 reading input until a blank line is given. In the notebook, simply type the
257 256 whole cell as one entity, but keep in mind that the %% escape can only be at
258 257 the very start of the cell.
259 258
260 259 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 260 %automagic function), you don't need to type in the % explicitly for line
262 261 magics; cell magics always require an explicit '%%' escape. By default,
263 262 IPython ships with automagic on, so you should only rarely need the % escape.
264 263
265 264 Example: typing '%cd mydir' (without the quotes) changes you working directory
266 265 to 'mydir', if it exists.
267 266
268 267 For a list of the available magic functions, use %lsmagic. For a description
269 268 of any of them, type %magic_name?, e.g. '%cd?'.
270 269
271 270 Currently the magic system has the following functions:""",
272 271 magic_docs,
273 272 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 273 str(self.lsmagic()),
275 274 ]
276 275 page.page('\n'.join(out))
277 276
278 277
279 278 @line_magic
280 279 def page(self, parameter_s=''):
281 280 """Pretty print the object and display it through a pager.
282 281
283 282 %page [options] OBJECT
284 283
285 284 If no object is given, use _ (last output).
286 285
287 286 Options:
288 287
289 288 -r: page str(object), don't pretty-print it."""
290 289
291 290 # After a function contributed by Olivier Aubert, slightly modified.
292 291
293 292 # Process options/args
294 293 opts, args = self.parse_options(parameter_s, 'r')
295 294 raw = 'r' in opts
296 295
297 296 oname = args and args or '_'
298 297 info = self.shell._ofind(oname)
299 298 if info['found']:
300 299 txt = (raw and str or pformat)( info['obj'] )
301 300 page.page(txt)
302 301 else:
303 302 print('Object `%s` not found' % oname)
304 303
305 304 @line_magic
306 305 def profile(self, parameter_s=''):
307 306 """Print your currently active IPython profile."""
308 307 from IPython.core.application import BaseIPythonApplication
309 308 if BaseIPythonApplication.initialized():
310 309 print(BaseIPythonApplication.instance().profile)
311 310 else:
312 311 error("profile is an application-level value, but you don't appear to be in an IPython application")
313 312
314 313 @line_magic
315 314 def pprint(self, parameter_s=''):
316 315 """Toggle pretty printing on/off."""
317 316 ptformatter = self.shell.display_formatter.formatters['text/plain']
318 317 ptformatter.pprint = bool(1 - ptformatter.pprint)
319 318 print('Pretty printing has been turned',
320 319 ['OFF','ON'][ptformatter.pprint])
321 320
322 321 @line_magic
323 322 def colors(self, parameter_s=''):
324 323 """Switch color scheme for prompts, info system and exception handlers.
325 324
326 325 Currently implemented schemes: NoColor, Linux, LightBG.
327 326
328 327 Color scheme names are not case-sensitive.
329 328
330 329 Examples
331 330 --------
332 331 To get a plain black and white terminal::
333 332
334 333 %colors nocolor
335 334 """
336 335 def color_switch_err(name):
337 336 warn('Error changing %s color schemes.\n%s' %
338 337 (name, sys.exc_info()[1]))
339 338
340 339
341 340 new_scheme = parameter_s.strip()
342 341 if not new_scheme:
343 342 raise UsageError(
344 343 "%colors: you must specify a color scheme. See '%colors?'")
345 344 return
346 345 # local shortcut
347 346 shell = self.shell
348 347
349 348 import IPython.utils.rlineimpl as readline
350 349
351 350 if not shell.colors_force and \
352 351 not readline.have_readline and \
353 352 (sys.platform == "win32" or sys.platform == "cli"):
354 353 msg = """\
355 354 Proper color support under MS Windows requires the pyreadline library.
356 355 You can find it at:
357 356 http://ipython.org/pyreadline.html
358 357 Gary's readline needs the ctypes module, from:
359 358 http://starship.python.net/crew/theller/ctypes
360 359 (Note that ctypes is already part of Python versions 2.5 and newer).
361 360
362 361 Defaulting color scheme to 'NoColor'"""
363 362 new_scheme = 'NoColor'
364 363 warn(msg)
365 364
366 365 # readline option is 0
367 366 if not shell.colors_force and not shell.has_readline:
368 367 new_scheme = 'NoColor'
369 368
370 369 # Set prompt colors
371 370 try:
372 371 shell.prompt_manager.color_scheme = new_scheme
373 372 except:
374 373 color_switch_err('prompt')
375 374 else:
376 375 shell.colors = \
377 376 shell.prompt_manager.color_scheme_table.active_scheme_name
378 377 # Set exception colors
379 378 try:
380 379 shell.InteractiveTB.set_colors(scheme = new_scheme)
381 380 shell.SyntaxTB.set_colors(scheme = new_scheme)
382 381 except:
383 382 color_switch_err('exception')
384 383
385 384 # Set info (for 'object?') colors
386 385 if shell.color_info:
387 386 try:
388 387 shell.inspector.set_active_scheme(new_scheme)
389 388 except:
390 389 color_switch_err('object inspector')
391 390 else:
392 391 shell.inspector.set_active_scheme('NoColor')
393 392
394 393 @line_magic
395 394 def xmode(self, parameter_s=''):
396 395 """Switch modes for the exception handlers.
397 396
398 397 Valid modes: Plain, Context and Verbose.
399 398
400 399 If called without arguments, acts as a toggle."""
401 400
402 401 def xmode_switch_err(name):
403 402 warn('Error changing %s exception modes.\n%s' %
404 403 (name,sys.exc_info()[1]))
405 404
406 405 shell = self.shell
407 406 new_mode = parameter_s.strip().capitalize()
408 407 try:
409 408 shell.InteractiveTB.set_mode(mode=new_mode)
410 409 print('Exception reporting mode:',shell.InteractiveTB.mode)
411 410 except:
412 411 xmode_switch_err('user')
413 412
414 413 @line_magic
415 414 def quickref(self,arg):
416 415 """ Show a quick reference sheet """
417 416 from IPython.core.usage import quick_reference
418 417 qr = quick_reference + self._magic_docs(brief=True)
419 418 page.page(qr)
420 419
421 420 @line_magic
422 421 def doctest_mode(self, parameter_s=''):
423 422 """Toggle doctest mode on and off.
424 423
425 424 This mode is intended to make IPython behave as much as possible like a
426 425 plain Python shell, from the perspective of how its prompts, exceptions
427 426 and output look. This makes it easy to copy and paste parts of a
428 427 session into doctests. It does so by:
429 428
430 429 - Changing the prompts to the classic ``>>>`` ones.
431 430 - Changing the exception reporting mode to 'Plain'.
432 431 - Disabling pretty-printing of output.
433 432
434 433 Note that IPython also supports the pasting of code snippets that have
435 434 leading '>>>' and '...' prompts in them. This means that you can paste
436 435 doctests from files or docstrings (even if they have leading
437 436 whitespace), and the code will execute correctly. You can then use
438 437 '%history -t' to see the translated history; this will give you the
439 438 input after removal of all the leading prompts and whitespace, which
440 439 can be pasted back into an editor.
441 440
442 441 With these features, you can switch into this mode easily whenever you
443 442 need to do testing and changes to doctests, without having to leave
444 443 your existing IPython session.
445 444 """
446 445
447 446 # Shorthands
448 447 shell = self.shell
449 448 pm = shell.prompt_manager
450 449 meta = shell.meta
451 450 disp_formatter = self.shell.display_formatter
452 451 ptformatter = disp_formatter.formatters['text/plain']
453 452 # dstore is a data store kept in the instance metadata bag to track any
454 453 # changes we make, so we can undo them later.
455 454 dstore = meta.setdefault('doctest_mode',Struct())
456 455 save_dstore = dstore.setdefault
457 456
458 457 # save a few values we'll need to recover later
459 458 mode = save_dstore('mode',False)
460 459 save_dstore('rc_pprint',ptformatter.pprint)
461 460 save_dstore('xmode',shell.InteractiveTB.mode)
462 461 save_dstore('rc_separate_out',shell.separate_out)
463 462 save_dstore('rc_separate_out2',shell.separate_out2)
464 463 save_dstore('rc_prompts_pad_left',pm.justify)
465 464 save_dstore('rc_separate_in',shell.separate_in)
466 465 save_dstore('rc_active_types',disp_formatter.active_types)
467 466 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
468 467
469 468 if mode == False:
470 469 # turn on
471 470 pm.in_template = '>>> '
472 471 pm.in2_template = '... '
473 472 pm.out_template = ''
474 473
475 474 # Prompt separators like plain python
476 475 shell.separate_in = ''
477 476 shell.separate_out = ''
478 477 shell.separate_out2 = ''
479 478
480 479 pm.justify = False
481 480
482 481 ptformatter.pprint = False
483 482 disp_formatter.active_types = ['text/plain']
484 483
485 484 shell.magic('xmode Plain')
486 485 else:
487 486 # turn off
488 487 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
489 488
490 489 shell.separate_in = dstore.rc_separate_in
491 490
492 491 shell.separate_out = dstore.rc_separate_out
493 492 shell.separate_out2 = dstore.rc_separate_out2
494 493
495 494 pm.justify = dstore.rc_prompts_pad_left
496 495
497 496 ptformatter.pprint = dstore.rc_pprint
498 497 disp_formatter.active_types = dstore.rc_active_types
499 498
500 499 shell.magic('xmode ' + dstore.xmode)
501 500
502 501 # Store new mode and inform
503 502 dstore.mode = bool(1-int(mode))
504 503 mode_label = ['OFF','ON'][dstore.mode]
505 504 print('Doctest mode is:', mode_label)
506 505
507 506 @line_magic
508 507 def gui(self, parameter_s=''):
509 508 """Enable or disable IPython GUI event loop integration.
510 509
511 510 %gui [GUINAME]
512 511
513 512 This magic replaces IPython's threaded shells that were activated
514 513 using the (pylab/wthread/etc.) command line flags. GUI toolkits
515 514 can now be enabled at runtime and keyboard
516 515 interrupts should work without any problems. The following toolkits
517 516 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
518 517
519 518 %gui wx # enable wxPython event loop integration
520 519 %gui qt4|qt # enable PyQt4 event loop integration
521 520 %gui gtk # enable PyGTK event loop integration
522 521 %gui gtk3 # enable Gtk3 event loop integration
523 522 %gui tk # enable Tk event loop integration
524 523 %gui osx # enable Cocoa event loop integration
525 524 # (requires %matplotlib 1.1)
526 525 %gui # disable all event loop integration
527 526
528 527 WARNING: after any of these has been called you can simply create
529 528 an application object, but DO NOT start the event loop yourself, as
530 529 we have already handled that.
531 530 """
532 531 opts, arg = self.parse_options(parameter_s, '')
533 532 if arg=='': arg = None
534 533 try:
535 534 return self.shell.enable_gui(arg)
536 535 except Exception as e:
537 536 # print simple error message, rather than traceback if we can't
538 537 # hook up the GUI
539 538 error(str(e))
540 539
541 540 @skip_doctest
542 541 @line_magic
543 542 def precision(self, s=''):
544 543 """Set floating point precision for pretty printing.
545 544
546 545 Can set either integer precision or a format string.
547 546
548 547 If numpy has been imported and precision is an int,
549 548 numpy display precision will also be set, via ``numpy.set_printoptions``.
550 549
551 550 If no argument is given, defaults will be restored.
552 551
553 552 Examples
554 553 --------
555 554 ::
556 555
557 556 In [1]: from math import pi
558 557
559 558 In [2]: %precision 3
560 559 Out[2]: u'%.3f'
561 560
562 561 In [3]: pi
563 562 Out[3]: 3.142
564 563
565 564 In [4]: %precision %i
566 565 Out[4]: u'%i'
567 566
568 567 In [5]: pi
569 568 Out[5]: 3
570 569
571 570 In [6]: %precision %e
572 571 Out[6]: u'%e'
573 572
574 573 In [7]: pi**10
575 574 Out[7]: 9.364805e+04
576 575
577 576 In [8]: %precision
578 577 Out[8]: u'%r'
579 578
580 579 In [9]: pi**10
581 580 Out[9]: 93648.047476082982
582 581 """
583 582 ptformatter = self.shell.display_formatter.formatters['text/plain']
584 583 ptformatter.float_precision = s
585 584 return ptformatter.float_format
586 585
587 586 @magic_arguments.magic_arguments()
588 587 @magic_arguments.argument(
589 588 '-e', '--export', action='store_true', default=False,
590 589 help='Export IPython history as a notebook. The filename argument '
591 590 'is used to specify the notebook name and format. For example '
592 591 'a filename of notebook.ipynb will result in a notebook name '
593 592 'of "notebook" and a format of "json". Likewise using a ".py" '
594 593 'file extension will write the notebook as a Python script'
595 594 )
596 595 @magic_arguments.argument(
597 596 '-f', '--format',
598 597 help='Convert an existing IPython notebook to a new format. This option '
599 598 'specifies the new format and can have the values: json, py. '
600 599 'The target filename is chosen automatically based on the new '
601 600 'format. The filename argument gives the name of the source file.'
602 601 )
603 602 @magic_arguments.argument(
604 603 'filename', type=unicode,
605 604 help='Notebook name or filename'
606 605 )
607 606 @line_magic
608 607 def notebook(self, s):
609 608 """Export and convert IPython notebooks.
610 609
611 610 This function can export the current IPython history to a notebook file
612 611 or can convert an existing notebook file into a different format. For
613 612 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
614 613 To export the history to "foo.py" do "%notebook -e foo.py". To convert
615 614 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
616 615 formats include (json/ipynb, py).
617 616 """
618 617 args = magic_arguments.parse_argstring(self.notebook, s)
619 618
620 619 from IPython.nbformat import current
621 620 args.filename = unquote_filename(args.filename)
622 621 if args.export:
623 622 fname, name, format = current.parse_filename(args.filename)
624 623 cells = []
625 624 hist = list(self.shell.history_manager.get_range())
626 625 for session, prompt_number, input in hist[:-1]:
627 626 cells.append(current.new_code_cell(prompt_number=prompt_number,
628 627 input=input))
629 628 worksheet = current.new_worksheet(cells=cells)
630 629 nb = current.new_notebook(name=name,worksheets=[worksheet])
631 630 with io.open(fname, 'w', encoding='utf-8') as f:
632 631 current.write(nb, f, format);
633 632 elif args.format is not None:
634 633 old_fname, old_name, old_format = current.parse_filename(args.filename)
635 634 new_format = args.format
636 635 if new_format == u'xml':
637 636 raise ValueError('Notebooks cannot be written as xml.')
638 637 elif new_format == u'ipynb' or new_format == u'json':
639 638 new_fname = old_name + u'.ipynb'
640 639 new_format = u'json'
641 640 elif new_format == u'py':
642 641 new_fname = old_name + u'.py'
643 642 else:
644 643 raise ValueError('Invalid notebook format: %s' % new_format)
645 644 with io.open(old_fname, 'r', encoding='utf-8') as f:
646 645 nb = current.read(f, old_format)
647 646 with io.open(new_fname, 'w', encoding='utf-8') as f:
648 647 current.write(nb, f, new_format)
@@ -1,885 +1,882 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for inspecting Python objects.
3 3
4 4 Uses syntax highlighting for presenting the various information elements.
5 5
6 6 Similar in spirit to the inspect module, but all calls take a name argument to
7 7 reference the name under which an object is being read.
8 8 """
9 9
10 10 #*****************************************************************************
11 11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #*****************************************************************************
16 16 from __future__ import print_function
17 17
18 18 __all__ = ['Inspector','InspectColors']
19 19
20 20 # stdlib modules
21 import __builtin__
22 21 import inspect
23 22 import linecache
24 23 import os
25 import sys
26 24 import types
27 25 import io as stdlib_io
28 26
29 from collections import namedtuple
30 27 try:
31 28 from itertools import izip_longest
32 29 except ImportError:
33 30 from itertools import zip_longest as izip_longest
34 31
35 32 # IPython's own
36 33 from IPython.core import page
37 34 from IPython.testing.skipdoctest import skip_doctest_py3
38 35 from IPython.utils import PyColorize
39 36 from IPython.utils import io
40 37 from IPython.utils import openpy
41 38 from IPython.utils import py3compat
42 39 from IPython.utils.text import indent
43 40 from IPython.utils.wildcard import list_namespace
44 41 from IPython.utils.coloransi import *
45 42 from IPython.utils.py3compat import cast_unicode
46 43
47 44 #****************************************************************************
48 45 # Builtin color schemes
49 46
50 47 Colors = TermColors # just a shorthand
51 48
52 49 # Build a few color schemes
53 50 NoColor = ColorScheme(
54 51 'NoColor',{
55 52 'header' : Colors.NoColor,
56 53 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
57 54 } )
58 55
59 56 LinuxColors = ColorScheme(
60 57 'Linux',{
61 58 'header' : Colors.LightRed,
62 59 'normal' : Colors.Normal # color off (usu. Colors.Normal)
63 60 } )
64 61
65 62 LightBGColors = ColorScheme(
66 63 'LightBG',{
67 64 'header' : Colors.Red,
68 65 'normal' : Colors.Normal # color off (usu. Colors.Normal)
69 66 } )
70 67
71 68 # Build table of color schemes (needed by the parser)
72 69 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
73 70 'Linux')
74 71
75 72 #****************************************************************************
76 73 # Auxiliary functions and objects
77 74
78 75 # See the messaging spec for the definition of all these fields. This list
79 76 # effectively defines the order of display
80 77 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
81 78 'length', 'file', 'definition', 'docstring', 'source',
82 79 'init_definition', 'class_docstring', 'init_docstring',
83 80 'call_def', 'call_docstring',
84 81 # These won't be printed but will be used to determine how to
85 82 # format the object
86 83 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
87 84 ]
88 85
89 86
90 87 def object_info(**kw):
91 88 """Make an object info dict with all fields present."""
92 89 infodict = dict(izip_longest(info_fields, [None]))
93 90 infodict.update(kw)
94 91 return infodict
95 92
96 93
97 94 def get_encoding(obj):
98 95 """Get encoding for python source file defining obj
99 96
100 97 Returns None if obj is not defined in a sourcefile.
101 98 """
102 99 ofile = find_file(obj)
103 100 # run contents of file through pager starting at line where the object
104 101 # is defined, as long as the file isn't binary and is actually on the
105 102 # filesystem.
106 103 if ofile is None:
107 104 return None
108 105 elif ofile.endswith(('.so', '.dll', '.pyd')):
109 106 return None
110 107 elif not os.path.isfile(ofile):
111 108 return None
112 109 else:
113 110 # Print only text files, not extension binaries. Note that
114 111 # getsourcelines returns lineno with 1-offset and page() uses
115 112 # 0-offset, so we must adjust.
116 113 buffer = stdlib_io.open(ofile, 'rb') # Tweaked to use io.open for Python 2
117 114 encoding, lines = openpy.detect_encoding(buffer.readline)
118 115 return encoding
119 116
120 117 def getdoc(obj):
121 118 """Stable wrapper around inspect.getdoc.
122 119
123 120 This can't crash because of attribute problems.
124 121
125 122 It also attempts to call a getdoc() method on the given object. This
126 123 allows objects which provide their docstrings via non-standard mechanisms
127 124 (like Pyro proxies) to still be inspected by ipython's ? system."""
128 125 # Allow objects to offer customized documentation via a getdoc method:
129 126 try:
130 127 ds = obj.getdoc()
131 128 except Exception:
132 129 pass
133 130 else:
134 131 # if we get extra info, we add it to the normal docstring.
135 132 if isinstance(ds, basestring):
136 133 return inspect.cleandoc(ds)
137 134
138 135 try:
139 136 docstr = inspect.getdoc(obj)
140 137 encoding = get_encoding(obj)
141 138 return py3compat.cast_unicode(docstr, encoding=encoding)
142 139 except Exception:
143 140 # Harden against an inspect failure, which can occur with
144 141 # SWIG-wrapped extensions.
145 142 raise
146 143 return None
147 144
148 145
149 146 def getsource(obj,is_binary=False):
150 147 """Wrapper around inspect.getsource.
151 148
152 149 This can be modified by other projects to provide customized source
153 150 extraction.
154 151
155 152 Inputs:
156 153
157 154 - obj: an object whose source code we will attempt to extract.
158 155
159 156 Optional inputs:
160 157
161 158 - is_binary: whether the object is known to come from a binary source.
162 159 This implementation will skip returning any output for binary objects, but
163 160 custom extractors may know how to meaningfully process them."""
164 161
165 162 if is_binary:
166 163 return None
167 164 else:
168 165 # get source if obj was decorated with @decorator
169 166 if hasattr(obj,"__wrapped__"):
170 167 obj = obj.__wrapped__
171 168 try:
172 169 src = inspect.getsource(obj)
173 170 except TypeError:
174 171 if hasattr(obj,'__class__'):
175 172 src = inspect.getsource(obj.__class__)
176 173 encoding = get_encoding(obj)
177 174 return cast_unicode(src, encoding=encoding)
178 175
179 176 def getargspec(obj):
180 177 """Get the names and default values of a function's arguments.
181 178
182 179 A tuple of four things is returned: (args, varargs, varkw, defaults).
183 180 'args' is a list of the argument names (it may contain nested lists).
184 181 'varargs' and 'varkw' are the names of the * and ** arguments or None.
185 182 'defaults' is an n-tuple of the default values of the last n arguments.
186 183
187 184 Modified version of inspect.getargspec from the Python Standard
188 185 Library."""
189 186
190 187 if inspect.isfunction(obj):
191 188 func_obj = obj
192 189 elif inspect.ismethod(obj):
193 190 func_obj = obj.im_func
194 191 elif hasattr(obj, '__call__'):
195 192 func_obj = obj.__call__
196 193 else:
197 194 raise TypeError('arg is not a Python function')
198 195 args, varargs, varkw = inspect.getargs(func_obj.func_code)
199 196 return args, varargs, varkw, func_obj.func_defaults
200 197
201 198
202 199 def format_argspec(argspec):
203 200 """Format argspect, convenience wrapper around inspect's.
204 201
205 202 This takes a dict instead of ordered arguments and calls
206 203 inspect.format_argspec with the arguments in the necessary order.
207 204 """
208 205 return inspect.formatargspec(argspec['args'], argspec['varargs'],
209 206 argspec['varkw'], argspec['defaults'])
210 207
211 208
212 209 def call_tip(oinfo, format_call=True):
213 210 """Extract call tip data from an oinfo dict.
214 211
215 212 Parameters
216 213 ----------
217 214 oinfo : dict
218 215
219 216 format_call : bool, optional
220 217 If True, the call line is formatted and returned as a string. If not, a
221 218 tuple of (name, argspec) is returned.
222 219
223 220 Returns
224 221 -------
225 222 call_info : None, str or (str, dict) tuple.
226 223 When format_call is True, the whole call information is formattted as a
227 224 single string. Otherwise, the object's name and its argspec dict are
228 225 returned. If no call information is available, None is returned.
229 226
230 227 docstring : str or None
231 228 The most relevant docstring for calling purposes is returned, if
232 229 available. The priority is: call docstring for callable instances, then
233 230 constructor docstring for classes, then main object's docstring otherwise
234 231 (regular functions).
235 232 """
236 233 # Get call definition
237 234 argspec = oinfo.get('argspec')
238 235 if argspec is None:
239 236 call_line = None
240 237 else:
241 238 # Callable objects will have 'self' as their first argument, prune
242 239 # it out if it's there for clarity (since users do *not* pass an
243 240 # extra first argument explicitly).
244 241 try:
245 242 has_self = argspec['args'][0] == 'self'
246 243 except (KeyError, IndexError):
247 244 pass
248 245 else:
249 246 if has_self:
250 247 argspec['args'] = argspec['args'][1:]
251 248
252 249 call_line = oinfo['name']+format_argspec(argspec)
253 250
254 251 # Now get docstring.
255 252 # The priority is: call docstring, constructor docstring, main one.
256 253 doc = oinfo.get('call_docstring')
257 254 if doc is None:
258 255 doc = oinfo.get('init_docstring')
259 256 if doc is None:
260 257 doc = oinfo.get('docstring','')
261 258
262 259 return call_line, doc
263 260
264 261 def safe_hasattr(obj, attr):
265 262 """In recent versions of Python, hasattr() only catches AttributeError.
266 263 This catches all errors.
267 264 """
268 265 try:
269 266 getattr(obj, attr)
270 267 return True
271 268 except:
272 269 return False
273 270
274 271
275 272 def find_file(obj):
276 273 """Find the absolute path to the file where an object was defined.
277 274
278 275 This is essentially a robust wrapper around `inspect.getabsfile`.
279 276
280 277 Returns None if no file can be found.
281 278
282 279 Parameters
283 280 ----------
284 281 obj : any Python object
285 282
286 283 Returns
287 284 -------
288 285 fname : str
289 286 The absolute path to the file where the object was defined.
290 287 """
291 288 # get source if obj was decorated with @decorator
292 289 if safe_hasattr(obj, '__wrapped__'):
293 290 obj = obj.__wrapped__
294 291
295 292 fname = None
296 293 try:
297 294 fname = inspect.getabsfile(obj)
298 295 except TypeError:
299 296 # For an instance, the file that matters is where its class was
300 297 # declared.
301 298 if hasattr(obj, '__class__'):
302 299 try:
303 300 fname = inspect.getabsfile(obj.__class__)
304 301 except TypeError:
305 302 # Can happen for builtins
306 303 pass
307 304 except:
308 305 pass
309 306 return cast_unicode(fname)
310 307
311 308
312 309 def find_source_lines(obj):
313 310 """Find the line number in a file where an object was defined.
314 311
315 312 This is essentially a robust wrapper around `inspect.getsourcelines`.
316 313
317 314 Returns None if no file can be found.
318 315
319 316 Parameters
320 317 ----------
321 318 obj : any Python object
322 319
323 320 Returns
324 321 -------
325 322 lineno : int
326 323 The line number where the object definition starts.
327 324 """
328 325 # get source if obj was decorated with @decorator
329 326 if safe_hasattr(obj, '__wrapped__'):
330 327 obj = obj.__wrapped__
331 328
332 329 try:
333 330 try:
334 331 lineno = inspect.getsourcelines(obj)[1]
335 332 except TypeError:
336 333 # For instances, try the class object like getsource() does
337 334 if hasattr(obj, '__class__'):
338 335 lineno = inspect.getsourcelines(obj.__class__)[1]
339 336 else:
340 337 lineno = None
341 338 except:
342 339 return None
343 340
344 341 return lineno
345 342
346 343
347 344 class Inspector:
348 345 def __init__(self, color_table=InspectColors,
349 346 code_color_table=PyColorize.ANSICodeColors,
350 347 scheme='NoColor',
351 348 str_detail_level=0):
352 349 self.color_table = color_table
353 350 self.parser = PyColorize.Parser(code_color_table,out='str')
354 351 self.format = self.parser.format
355 352 self.str_detail_level = str_detail_level
356 353 self.set_active_scheme(scheme)
357 354
358 355 def _getdef(self,obj,oname=''):
359 356 """Return the call signature for any callable object.
360 357
361 358 If any exception is generated, None is returned instead and the
362 359 exception is suppressed."""
363 360
364 361 try:
365 362 hdef = oname + inspect.formatargspec(*getargspec(obj))
366 363 return cast_unicode(hdef)
367 364 except:
368 365 return None
369 366
370 367 def __head(self,h):
371 368 """Return a header string with proper colors."""
372 369 return '%s%s%s' % (self.color_table.active_colors.header,h,
373 370 self.color_table.active_colors.normal)
374 371
375 372 def set_active_scheme(self, scheme):
376 373 self.color_table.set_active_scheme(scheme)
377 374 self.parser.color_table.set_active_scheme(scheme)
378 375
379 376 def noinfo(self, msg, oname):
380 377 """Generic message when no information is found."""
381 378 print('No %s found' % msg, end=' ')
382 379 if oname:
383 380 print('for %s' % oname)
384 381 else:
385 382 print()
386 383
387 384 def pdef(self, obj, oname=''):
388 385 """Print the call signature for any callable object.
389 386
390 387 If the object is a class, print the constructor information."""
391 388
392 389 if not callable(obj):
393 390 print('Object is not callable.')
394 391 return
395 392
396 393 header = ''
397 394
398 395 if inspect.isclass(obj):
399 396 header = self.__head('Class constructor information:\n')
400 397 obj = obj.__init__
401 398 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
402 399 obj = obj.__call__
403 400
404 401 output = self._getdef(obj,oname)
405 402 if output is None:
406 403 self.noinfo('definition header',oname)
407 404 else:
408 405 print(header,self.format(output), end=' ', file=io.stdout)
409 406
410 407 # In Python 3, all classes are new-style, so they all have __init__.
411 408 @skip_doctest_py3
412 409 def pdoc(self,obj,oname='',formatter = None):
413 410 """Print the docstring for any object.
414 411
415 412 Optional:
416 413 -formatter: a function to run the docstring through for specially
417 414 formatted docstrings.
418 415
419 416 Examples
420 417 --------
421 418
422 419 In [1]: class NoInit:
423 420 ...: pass
424 421
425 422 In [2]: class NoDoc:
426 423 ...: def __init__(self):
427 424 ...: pass
428 425
429 426 In [3]: %pdoc NoDoc
430 427 No documentation found for NoDoc
431 428
432 429 In [4]: %pdoc NoInit
433 430 No documentation found for NoInit
434 431
435 432 In [5]: obj = NoInit()
436 433
437 434 In [6]: %pdoc obj
438 435 No documentation found for obj
439 436
440 437 In [5]: obj2 = NoDoc()
441 438
442 439 In [6]: %pdoc obj2
443 440 No documentation found for obj2
444 441 """
445 442
446 443 head = self.__head # For convenience
447 444 lines = []
448 445 ds = getdoc(obj)
449 446 if formatter:
450 447 ds = formatter(ds)
451 448 if ds:
452 449 lines.append(head("Class Docstring:"))
453 450 lines.append(indent(ds))
454 451 if inspect.isclass(obj) and hasattr(obj, '__init__'):
455 452 init_ds = getdoc(obj.__init__)
456 453 if init_ds is not None:
457 454 lines.append(head("Constructor Docstring:"))
458 455 lines.append(indent(init_ds))
459 456 elif hasattr(obj,'__call__'):
460 457 call_ds = getdoc(obj.__call__)
461 458 if call_ds:
462 459 lines.append(head("Calling Docstring:"))
463 460 lines.append(indent(call_ds))
464 461
465 462 if not lines:
466 463 self.noinfo('documentation',oname)
467 464 else:
468 465 page.page('\n'.join(lines))
469 466
470 467 def psource(self,obj,oname=''):
471 468 """Print the source code for an object."""
472 469
473 470 # Flush the source cache because inspect can return out-of-date source
474 471 linecache.checkcache()
475 472 try:
476 473 src = getsource(obj)
477 474 except:
478 475 self.noinfo('source',oname)
479 476 else:
480 477 page.page(self.format(src))
481 478
482 479 def pfile(self, obj, oname=''):
483 480 """Show the whole file where an object was defined."""
484 481
485 482 lineno = find_source_lines(obj)
486 483 if lineno is None:
487 484 self.noinfo('file', oname)
488 485 return
489 486
490 487 ofile = find_file(obj)
491 488 # run contents of file through pager starting at line where the object
492 489 # is defined, as long as the file isn't binary and is actually on the
493 490 # filesystem.
494 491 if ofile.endswith(('.so', '.dll', '.pyd')):
495 492 print('File %r is binary, not printing.' % ofile)
496 493 elif not os.path.isfile(ofile):
497 494 print('File %r does not exist, not printing.' % ofile)
498 495 else:
499 496 # Print only text files, not extension binaries. Note that
500 497 # getsourcelines returns lineno with 1-offset and page() uses
501 498 # 0-offset, so we must adjust.
502 499 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
503 500
504 501 def _format_fields(self, fields, title_width=12):
505 502 """Formats a list of fields for display.
506 503
507 504 Parameters
508 505 ----------
509 506 fields : list
510 507 A list of 2-tuples: (field_title, field_content)
511 508 title_width : int
512 509 How many characters to pad titles to. Default 12.
513 510 """
514 511 out = []
515 512 header = self.__head
516 513 for title, content in fields:
517 514 if len(content.splitlines()) > 1:
518 515 title = header(title + ":") + "\n"
519 516 else:
520 517 title = header((title+":").ljust(title_width))
521 518 out.append(cast_unicode(title) + cast_unicode(content))
522 519 return "\n".join(out)
523 520
524 521 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
525 522 pinfo_fields1 = [("Type", "type_name"),
526 523 ]
527 524
528 525 pinfo_fields2 = [("String Form", "string_form"),
529 526 ]
530 527
531 528 pinfo_fields3 = [("Length", "length"),
532 529 ("File", "file"),
533 530 ("Definition", "definition"),
534 531 ]
535 532
536 533 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
537 534 ("Constructor Docstring","init_docstring"),
538 535 ("Call def", "call_def"),
539 536 ("Call docstring", "call_docstring")]
540 537
541 538 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
542 539 """Show detailed information about an object.
543 540
544 541 Optional arguments:
545 542
546 543 - oname: name of the variable pointing to the object.
547 544
548 545 - formatter: special formatter for docstrings (see pdoc)
549 546
550 547 - info: a structure with some information fields which may have been
551 548 precomputed already.
552 549
553 550 - detail_level: if set to 1, more information is given.
554 551 """
555 552 info = self.info(obj, oname=oname, formatter=formatter,
556 553 info=info, detail_level=detail_level)
557 554 displayfields = []
558 555 def add_fields(fields):
559 556 for title, key in fields:
560 557 field = info[key]
561 558 if field is not None:
562 559 displayfields.append((title, field.rstrip()))
563 560
564 561 add_fields(self.pinfo_fields1)
565 562
566 563 # Base class for old-style instances
567 564 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
568 565 displayfields.append(("Base Class", info['base_class'].rstrip()))
569 566
570 567 add_fields(self.pinfo_fields2)
571 568
572 569 # Namespace
573 570 if info['namespace'] != 'Interactive':
574 571 displayfields.append(("Namespace", info['namespace'].rstrip()))
575 572
576 573 add_fields(self.pinfo_fields3)
577 574
578 575 # Source or docstring, depending on detail level and whether
579 576 # source found.
580 577 if detail_level > 0 and info['source'] is not None:
581 578 displayfields.append(("Source",
582 579 self.format(cast_unicode(info['source']))))
583 580 elif info['docstring'] is not None:
584 581 displayfields.append(("Docstring", info["docstring"]))
585 582
586 583 # Constructor info for classes
587 584 if info['isclass']:
588 585 if info['init_definition'] or info['init_docstring']:
589 586 displayfields.append(("Constructor information", ""))
590 587 if info['init_definition'] is not None:
591 588 displayfields.append((" Definition",
592 589 info['init_definition'].rstrip()))
593 590 if info['init_docstring'] is not None:
594 591 displayfields.append((" Docstring",
595 592 indent(info['init_docstring'])))
596 593
597 594 # Info for objects:
598 595 else:
599 596 add_fields(self.pinfo_fields_obj)
600 597
601 598 # Finally send to printer/pager:
602 599 if displayfields:
603 600 page.page(self._format_fields(displayfields))
604 601
605 602 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
606 603 """Compute a dict with detailed information about an object.
607 604
608 605 Optional arguments:
609 606
610 607 - oname: name of the variable pointing to the object.
611 608
612 609 - formatter: special formatter for docstrings (see pdoc)
613 610
614 611 - info: a structure with some information fields which may have been
615 612 precomputed already.
616 613
617 614 - detail_level: if set to 1, more information is given.
618 615 """
619 616
620 617 obj_type = type(obj)
621 618
622 619 header = self.__head
623 620 if info is None:
624 621 ismagic = 0
625 622 isalias = 0
626 623 ospace = ''
627 624 else:
628 625 ismagic = info.ismagic
629 626 isalias = info.isalias
630 627 ospace = info.namespace
631 628
632 629 # Get docstring, special-casing aliases:
633 630 if isalias:
634 631 if not callable(obj):
635 632 try:
636 633 ds = "Alias to the system command:\n %s" % obj[1]
637 634 except:
638 635 ds = "Alias: " + str(obj)
639 636 else:
640 637 ds = "Alias to " + str(obj)
641 638 if obj.__doc__:
642 639 ds += "\nDocstring:\n" + obj.__doc__
643 640 else:
644 641 ds = getdoc(obj)
645 642 if ds is None:
646 643 ds = '<no docstring>'
647 644 if formatter is not None:
648 645 ds = formatter(ds)
649 646
650 647 # store output in a dict, we initialize it here and fill it as we go
651 648 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
652 649
653 650 string_max = 200 # max size of strings to show (snipped if longer)
654 651 shalf = int((string_max -5)/2)
655 652
656 653 if ismagic:
657 654 obj_type_name = 'Magic function'
658 655 elif isalias:
659 656 obj_type_name = 'System alias'
660 657 else:
661 658 obj_type_name = obj_type.__name__
662 659 out['type_name'] = obj_type_name
663 660
664 661 try:
665 662 bclass = obj.__class__
666 663 out['base_class'] = str(bclass)
667 664 except: pass
668 665
669 666 # String form, but snip if too long in ? form (full in ??)
670 667 if detail_level >= self.str_detail_level:
671 668 try:
672 669 ostr = str(obj)
673 670 str_head = 'string_form'
674 671 if not detail_level and len(ostr)>string_max:
675 672 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
676 673 ostr = ("\n" + " " * len(str_head.expandtabs())).\
677 674 join(q.strip() for q in ostr.split("\n"))
678 675 out[str_head] = ostr
679 676 except:
680 677 pass
681 678
682 679 if ospace:
683 680 out['namespace'] = ospace
684 681
685 682 # Length (for strings and lists)
686 683 try:
687 684 out['length'] = str(len(obj))
688 685 except: pass
689 686
690 687 # Filename where object was defined
691 688 binary_file = False
692 689 fname = find_file(obj)
693 690 if fname is None:
694 691 # if anything goes wrong, we don't want to show source, so it's as
695 692 # if the file was binary
696 693 binary_file = True
697 694 else:
698 695 if fname.endswith(('.so', '.dll', '.pyd')):
699 696 binary_file = True
700 697 elif fname.endswith('<string>'):
701 698 fname = 'Dynamically generated function. No source code available.'
702 699 out['file'] = fname
703 700
704 701 # reconstruct the function definition and print it:
705 702 defln = self._getdef(obj, oname)
706 703 if defln:
707 704 out['definition'] = self.format(defln)
708 705
709 706 # Docstrings only in detail 0 mode, since source contains them (we
710 707 # avoid repetitions). If source fails, we add them back, see below.
711 708 if ds and detail_level == 0:
712 709 out['docstring'] = ds
713 710
714 711 # Original source code for any callable
715 712 if detail_level:
716 713 # Flush the source cache because inspect can return out-of-date
717 714 # source
718 715 linecache.checkcache()
719 716 source = None
720 717 try:
721 718 try:
722 719 source = getsource(obj, binary_file)
723 720 except TypeError:
724 721 if hasattr(obj, '__class__'):
725 722 source = getsource(obj.__class__, binary_file)
726 723 if source is not None:
727 724 out['source'] = source.rstrip()
728 725 except Exception:
729 726 pass
730 727
731 728 if ds and source is None:
732 729 out['docstring'] = ds
733 730
734 731
735 732 # Constructor docstring for classes
736 733 if inspect.isclass(obj):
737 734 out['isclass'] = True
738 735 # reconstruct the function definition and print it:
739 736 try:
740 737 obj_init = obj.__init__
741 738 except AttributeError:
742 739 init_def = init_ds = None
743 740 else:
744 741 init_def = self._getdef(obj_init,oname)
745 742 init_ds = getdoc(obj_init)
746 743 # Skip Python's auto-generated docstrings
747 744 if init_ds and \
748 745 init_ds.startswith('x.__init__(...) initializes'):
749 746 init_ds = None
750 747
751 748 if init_def or init_ds:
752 749 if init_def:
753 750 out['init_definition'] = self.format(init_def)
754 751 if init_ds:
755 752 out['init_docstring'] = init_ds
756 753
757 754 # and class docstring for instances:
758 755 else:
759 756 # First, check whether the instance docstring is identical to the
760 757 # class one, and print it separately if they don't coincide. In
761 758 # most cases they will, but it's nice to print all the info for
762 759 # objects which use instance-customized docstrings.
763 760 if ds:
764 761 try:
765 762 cls = getattr(obj,'__class__')
766 763 except:
767 764 class_ds = None
768 765 else:
769 766 class_ds = getdoc(cls)
770 767 # Skip Python's auto-generated docstrings
771 768 if class_ds and \
772 769 (class_ds.startswith('function(code, globals[,') or \
773 770 class_ds.startswith('instancemethod(function, instance,') or \
774 771 class_ds.startswith('module(name[,') ):
775 772 class_ds = None
776 773 if class_ds and ds != class_ds:
777 774 out['class_docstring'] = class_ds
778 775
779 776 # Next, try to show constructor docstrings
780 777 try:
781 778 init_ds = getdoc(obj.__init__)
782 779 # Skip Python's auto-generated docstrings
783 780 if init_ds and \
784 781 init_ds.startswith('x.__init__(...) initializes'):
785 782 init_ds = None
786 783 except AttributeError:
787 784 init_ds = None
788 785 if init_ds:
789 786 out['init_docstring'] = init_ds
790 787
791 788 # Call form docstring for callable instances
792 789 if safe_hasattr(obj, '__call__'):
793 790 call_def = self._getdef(obj.__call__, oname)
794 791 if call_def is not None:
795 792 out['call_def'] = self.format(call_def)
796 793 call_ds = getdoc(obj.__call__)
797 794 # Skip Python's auto-generated docstrings
798 795 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
799 796 call_ds = None
800 797 if call_ds:
801 798 out['call_docstring'] = call_ds
802 799
803 800 # Compute the object's argspec as a callable. The key is to decide
804 801 # whether to pull it from the object itself, from its __init__ or
805 802 # from its __call__ method.
806 803
807 804 if inspect.isclass(obj):
808 805 # Old-style classes need not have an __init__
809 806 callable_obj = getattr(obj, "__init__", None)
810 807 elif callable(obj):
811 808 callable_obj = obj
812 809 else:
813 810 callable_obj = None
814 811
815 812 if callable_obj:
816 813 try:
817 814 args, varargs, varkw, defaults = getargspec(callable_obj)
818 815 except (TypeError, AttributeError):
819 816 # For extensions/builtins we can't retrieve the argspec
820 817 pass
821 818 else:
822 819 out['argspec'] = dict(args=args, varargs=varargs,
823 820 varkw=varkw, defaults=defaults)
824 821
825 822 return object_info(**out)
826 823
827 824
828 825 def psearch(self,pattern,ns_table,ns_search=[],
829 826 ignore_case=False,show_all=False):
830 827 """Search namespaces with wildcards for objects.
831 828
832 829 Arguments:
833 830
834 831 - pattern: string containing shell-like wildcards to use in namespace
835 832 searches and optionally a type specification to narrow the search to
836 833 objects of that type.
837 834
838 835 - ns_table: dict of name->namespaces for search.
839 836
840 837 Optional arguments:
841 838
842 839 - ns_search: list of namespace names to include in search.
843 840
844 841 - ignore_case(False): make the search case-insensitive.
845 842
846 843 - show_all(False): show all names, including those starting with
847 844 underscores.
848 845 """
849 846 #print 'ps pattern:<%r>' % pattern # dbg
850 847
851 848 # defaults
852 849 type_pattern = 'all'
853 850 filter = ''
854 851
855 852 cmds = pattern.split()
856 853 len_cmds = len(cmds)
857 854 if len_cmds == 1:
858 855 # Only filter pattern given
859 856 filter = cmds[0]
860 857 elif len_cmds == 2:
861 858 # Both filter and type specified
862 859 filter,type_pattern = cmds
863 860 else:
864 861 raise ValueError('invalid argument string for psearch: <%s>' %
865 862 pattern)
866 863
867 864 # filter search namespaces
868 865 for name in ns_search:
869 866 if name not in ns_table:
870 867 raise ValueError('invalid namespace <%s>. Valid names: %s' %
871 868 (name,ns_table.keys()))
872 869
873 870 #print 'type_pattern:',type_pattern # dbg
874 871 search_result, namespaces_seen = set(), set()
875 872 for ns_name in ns_search:
876 873 ns = ns_table[ns_name]
877 874 # Normally, locals and globals are the same, so we just check one.
878 875 if id(ns) in namespaces_seen:
879 876 continue
880 877 namespaces_seen.add(id(ns))
881 878 tmp_res = list_namespace(ns, type_pattern, filter,
882 879 ignore_case=ignore_case, show_all=show_all)
883 880 search_result.update(tmp_res)
884 881
885 882 page.page('\n'.join(sorted(search_result)))
@@ -1,749 +1,745 b''
1 1 # encoding: utf-8
2 2 """
3 3 Prefiltering components.
4 4
5 5 Prefilters transform user input before it is exec'd by Python. These
6 6 transforms are used to implement additional syntax such as !ls and %magic.
7 7
8 8 Authors:
9 9
10 10 * Brian Granger
11 11 * Fernando Perez
12 12 * Dan Milstein
13 13 * Ville Vainio
14 14 """
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Copyright (C) 2008-2011 The IPython Development Team
18 18 #
19 19 # Distributed under the terms of the BSD License. The full license is in
20 20 # the file COPYING, distributed as part of this software.
21 21 #-----------------------------------------------------------------------------
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Imports
25 25 #-----------------------------------------------------------------------------
26 26
27 27 import re
28 28
29 29 from IPython.core.autocall import IPyAutocall
30 30 from IPython.config.configurable import Configurable
31 31 from IPython.core.inputsplitter import (
32 ESC_SHELL,
33 ESC_SH_CAP,
34 ESC_HELP,
35 32 ESC_MAGIC,
36 ESC_MAGIC2,
37 33 ESC_QUOTE,
38 34 ESC_QUOTE2,
39 35 ESC_PAREN,
40 36 )
41 37 from IPython.core.macro import Macro
42 38 from IPython.core.splitinput import LineInfo
43 39
44 40 from IPython.utils.traitlets import (
45 41 List, Integer, Unicode, CBool, Bool, Instance, CRegExp
46 42 )
47 43
48 44 #-----------------------------------------------------------------------------
49 45 # Global utilities, errors and constants
50 46 #-----------------------------------------------------------------------------
51 47
52 48
53 49 class PrefilterError(Exception):
54 50 pass
55 51
56 52
57 53 # RegExp to identify potential function names
58 54 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
59 55
60 56 # RegExp to exclude strings with this start from autocalling. In
61 57 # particular, all binary operators should be excluded, so that if foo is
62 58 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
63 59 # characters '!=()' don't need to be checked for, as the checkPythonChars
64 60 # routine explicitely does so, to catch direct calls and rebindings of
65 61 # existing names.
66 62
67 63 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
68 64 # it affects the rest of the group in square brackets.
69 65 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
70 66 r'|^is |^not |^in |^and |^or ')
71 67
72 68 # try to catch also methods for stuff in lists/tuples/dicts: off
73 69 # (experimental). For this to work, the line_split regexp would need
74 70 # to be modified so it wouldn't break things at '['. That line is
75 71 # nasty enough that I shouldn't change it until I can test it _well_.
76 72 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
77 73
78 74
79 75 # Handler Check Utilities
80 76 def is_shadowed(identifier, ip):
81 77 """Is the given identifier defined in one of the namespaces which shadow
82 78 the alias and magic namespaces? Note that an identifier is different
83 79 than ifun, because it can not contain a '.' character."""
84 80 # This is much safer than calling ofind, which can change state
85 81 return (identifier in ip.user_ns \
86 82 or identifier in ip.user_global_ns \
87 83 or identifier in ip.ns_table['builtin'])
88 84
89 85
90 86 #-----------------------------------------------------------------------------
91 87 # Main Prefilter manager
92 88 #-----------------------------------------------------------------------------
93 89
94 90
95 91 class PrefilterManager(Configurable):
96 92 """Main prefilter component.
97 93
98 94 The IPython prefilter is run on all user input before it is run. The
99 95 prefilter consumes lines of input and produces transformed lines of
100 96 input.
101 97
102 98 The iplementation consists of two phases:
103 99
104 100 1. Transformers
105 101 2. Checkers and handlers
106 102
107 103 Over time, we plan on deprecating the checkers and handlers and doing
108 104 everything in the transformers.
109 105
110 106 The transformers are instances of :class:`PrefilterTransformer` and have
111 107 a single method :meth:`transform` that takes a line and returns a
112 108 transformed line. The transformation can be accomplished using any
113 109 tool, but our current ones use regular expressions for speed.
114 110
115 111 After all the transformers have been run, the line is fed to the checkers,
116 112 which are instances of :class:`PrefilterChecker`. The line is passed to
117 113 the :meth:`check` method, which either returns `None` or a
118 114 :class:`PrefilterHandler` instance. If `None` is returned, the other
119 115 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
120 116 the line is passed to the :meth:`handle` method of the returned
121 117 handler and no further checkers are tried.
122 118
123 119 Both transformers and checkers have a `priority` attribute, that determines
124 120 the order in which they are called. Smaller priorities are tried first.
125 121
126 122 Both transformers and checkers also have `enabled` attribute, which is
127 123 a boolean that determines if the instance is used.
128 124
129 125 Users or developers can change the priority or enabled attribute of
130 126 transformers or checkers, but they must call the :meth:`sort_checkers`
131 127 or :meth:`sort_transformers` method after changing the priority.
132 128 """
133 129
134 130 multi_line_specials = CBool(True, config=True)
135 131 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
136 132
137 133 def __init__(self, shell=None, **kwargs):
138 134 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
139 135 self.shell = shell
140 136 self.init_transformers()
141 137 self.init_handlers()
142 138 self.init_checkers()
143 139
144 140 #-------------------------------------------------------------------------
145 141 # API for managing transformers
146 142 #-------------------------------------------------------------------------
147 143
148 144 def init_transformers(self):
149 145 """Create the default transformers."""
150 146 self._transformers = []
151 147 for transformer_cls in _default_transformers:
152 148 transformer_cls(
153 149 shell=self.shell, prefilter_manager=self, parent=self
154 150 )
155 151
156 152 def sort_transformers(self):
157 153 """Sort the transformers by priority.
158 154
159 155 This must be called after the priority of a transformer is changed.
160 156 The :meth:`register_transformer` method calls this automatically.
161 157 """
162 158 self._transformers.sort(key=lambda x: x.priority)
163 159
164 160 @property
165 161 def transformers(self):
166 162 """Return a list of checkers, sorted by priority."""
167 163 return self._transformers
168 164
169 165 def register_transformer(self, transformer):
170 166 """Register a transformer instance."""
171 167 if transformer not in self._transformers:
172 168 self._transformers.append(transformer)
173 169 self.sort_transformers()
174 170
175 171 def unregister_transformer(self, transformer):
176 172 """Unregister a transformer instance."""
177 173 if transformer in self._transformers:
178 174 self._transformers.remove(transformer)
179 175
180 176 #-------------------------------------------------------------------------
181 177 # API for managing checkers
182 178 #-------------------------------------------------------------------------
183 179
184 180 def init_checkers(self):
185 181 """Create the default checkers."""
186 182 self._checkers = []
187 183 for checker in _default_checkers:
188 184 checker(
189 185 shell=self.shell, prefilter_manager=self, parent=self
190 186 )
191 187
192 188 def sort_checkers(self):
193 189 """Sort the checkers by priority.
194 190
195 191 This must be called after the priority of a checker is changed.
196 192 The :meth:`register_checker` method calls this automatically.
197 193 """
198 194 self._checkers.sort(key=lambda x: x.priority)
199 195
200 196 @property
201 197 def checkers(self):
202 198 """Return a list of checkers, sorted by priority."""
203 199 return self._checkers
204 200
205 201 def register_checker(self, checker):
206 202 """Register a checker instance."""
207 203 if checker not in self._checkers:
208 204 self._checkers.append(checker)
209 205 self.sort_checkers()
210 206
211 207 def unregister_checker(self, checker):
212 208 """Unregister a checker instance."""
213 209 if checker in self._checkers:
214 210 self._checkers.remove(checker)
215 211
216 212 #-------------------------------------------------------------------------
217 213 # API for managing checkers
218 214 #-------------------------------------------------------------------------
219 215
220 216 def init_handlers(self):
221 217 """Create the default handlers."""
222 218 self._handlers = {}
223 219 self._esc_handlers = {}
224 220 for handler in _default_handlers:
225 221 handler(
226 222 shell=self.shell, prefilter_manager=self, parent=self
227 223 )
228 224
229 225 @property
230 226 def handlers(self):
231 227 """Return a dict of all the handlers."""
232 228 return self._handlers
233 229
234 230 def register_handler(self, name, handler, esc_strings):
235 231 """Register a handler instance by name with esc_strings."""
236 232 self._handlers[name] = handler
237 233 for esc_str in esc_strings:
238 234 self._esc_handlers[esc_str] = handler
239 235
240 236 def unregister_handler(self, name, handler, esc_strings):
241 237 """Unregister a handler instance by name with esc_strings."""
242 238 try:
243 239 del self._handlers[name]
244 240 except KeyError:
245 241 pass
246 242 for esc_str in esc_strings:
247 243 h = self._esc_handlers.get(esc_str)
248 244 if h is handler:
249 245 del self._esc_handlers[esc_str]
250 246
251 247 def get_handler_by_name(self, name):
252 248 """Get a handler by its name."""
253 249 return self._handlers.get(name)
254 250
255 251 def get_handler_by_esc(self, esc_str):
256 252 """Get a handler by its escape string."""
257 253 return self._esc_handlers.get(esc_str)
258 254
259 255 #-------------------------------------------------------------------------
260 256 # Main prefiltering API
261 257 #-------------------------------------------------------------------------
262 258
263 259 def prefilter_line_info(self, line_info):
264 260 """Prefilter a line that has been converted to a LineInfo object.
265 261
266 262 This implements the checker/handler part of the prefilter pipe.
267 263 """
268 264 # print "prefilter_line_info: ", line_info
269 265 handler = self.find_handler(line_info)
270 266 return handler.handle(line_info)
271 267
272 268 def find_handler(self, line_info):
273 269 """Find a handler for the line_info by trying checkers."""
274 270 for checker in self.checkers:
275 271 if checker.enabled:
276 272 handler = checker.check(line_info)
277 273 if handler:
278 274 return handler
279 275 return self.get_handler_by_name('normal')
280 276
281 277 def transform_line(self, line, continue_prompt):
282 278 """Calls the enabled transformers in order of increasing priority."""
283 279 for transformer in self.transformers:
284 280 if transformer.enabled:
285 281 line = transformer.transform(line, continue_prompt)
286 282 return line
287 283
288 284 def prefilter_line(self, line, continue_prompt=False):
289 285 """Prefilter a single input line as text.
290 286
291 287 This method prefilters a single line of text by calling the
292 288 transformers and then the checkers/handlers.
293 289 """
294 290
295 291 # print "prefilter_line: ", line, continue_prompt
296 292 # All handlers *must* return a value, even if it's blank ('').
297 293
298 294 # save the line away in case we crash, so the post-mortem handler can
299 295 # record it
300 296 self.shell._last_input_line = line
301 297
302 298 if not line:
303 299 # Return immediately on purely empty lines, so that if the user
304 300 # previously typed some whitespace that started a continuation
305 301 # prompt, he can break out of that loop with just an empty line.
306 302 # This is how the default python prompt works.
307 303 return ''
308 304
309 305 # At this point, we invoke our transformers.
310 306 if not continue_prompt or (continue_prompt and self.multi_line_specials):
311 307 line = self.transform_line(line, continue_prompt)
312 308
313 309 # Now we compute line_info for the checkers and handlers
314 310 line_info = LineInfo(line, continue_prompt)
315 311
316 312 # the input history needs to track even empty lines
317 313 stripped = line.strip()
318 314
319 315 normal_handler = self.get_handler_by_name('normal')
320 316 if not stripped:
321 317 return normal_handler.handle(line_info)
322 318
323 319 # special handlers are only allowed for single line statements
324 320 if continue_prompt and not self.multi_line_specials:
325 321 return normal_handler.handle(line_info)
326 322
327 323 prefiltered = self.prefilter_line_info(line_info)
328 324 # print "prefiltered line: %r" % prefiltered
329 325 return prefiltered
330 326
331 327 def prefilter_lines(self, lines, continue_prompt=False):
332 328 """Prefilter multiple input lines of text.
333 329
334 330 This is the main entry point for prefiltering multiple lines of
335 331 input. This simply calls :meth:`prefilter_line` for each line of
336 332 input.
337 333
338 334 This covers cases where there are multiple lines in the user entry,
339 335 which is the case when the user goes back to a multiline history
340 336 entry and presses enter.
341 337 """
342 338 llines = lines.rstrip('\n').split('\n')
343 339 # We can get multiple lines in one shot, where multiline input 'blends'
344 340 # into one line, in cases like recalling from the readline history
345 341 # buffer. We need to make sure that in such cases, we correctly
346 342 # communicate downstream which line is first and which are continuation
347 343 # ones.
348 344 if len(llines) > 1:
349 345 out = '\n'.join([self.prefilter_line(line, lnum>0)
350 346 for lnum, line in enumerate(llines) ])
351 347 else:
352 348 out = self.prefilter_line(llines[0], continue_prompt)
353 349
354 350 return out
355 351
356 352 #-----------------------------------------------------------------------------
357 353 # Prefilter transformers
358 354 #-----------------------------------------------------------------------------
359 355
360 356
361 357 class PrefilterTransformer(Configurable):
362 358 """Transform a line of user input."""
363 359
364 360 priority = Integer(100, config=True)
365 361 # Transformers don't currently use shell or prefilter_manager, but as we
366 362 # move away from checkers and handlers, they will need them.
367 363 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
368 364 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
369 365 enabled = Bool(True, config=True)
370 366
371 367 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
372 368 super(PrefilterTransformer, self).__init__(
373 369 shell=shell, prefilter_manager=prefilter_manager, **kwargs
374 370 )
375 371 self.prefilter_manager.register_transformer(self)
376 372
377 373 def transform(self, line, continue_prompt):
378 374 """Transform a line, returning the new one."""
379 375 return None
380 376
381 377 def __repr__(self):
382 378 return "<%s(priority=%r, enabled=%r)>" % (
383 379 self.__class__.__name__, self.priority, self.enabled)
384 380
385 381
386 382 #-----------------------------------------------------------------------------
387 383 # Prefilter checkers
388 384 #-----------------------------------------------------------------------------
389 385
390 386
391 387 class PrefilterChecker(Configurable):
392 388 """Inspect an input line and return a handler for that line."""
393 389
394 390 priority = Integer(100, config=True)
395 391 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
396 392 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
397 393 enabled = Bool(True, config=True)
398 394
399 395 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
400 396 super(PrefilterChecker, self).__init__(
401 397 shell=shell, prefilter_manager=prefilter_manager, **kwargs
402 398 )
403 399 self.prefilter_manager.register_checker(self)
404 400
405 401 def check(self, line_info):
406 402 """Inspect line_info and return a handler instance or None."""
407 403 return None
408 404
409 405 def __repr__(self):
410 406 return "<%s(priority=%r, enabled=%r)>" % (
411 407 self.__class__.__name__, self.priority, self.enabled)
412 408
413 409
414 410 class EmacsChecker(PrefilterChecker):
415 411
416 412 priority = Integer(100, config=True)
417 413 enabled = Bool(False, config=True)
418 414
419 415 def check(self, line_info):
420 416 "Emacs ipython-mode tags certain input lines."
421 417 if line_info.line.endswith('# PYTHON-MODE'):
422 418 return self.prefilter_manager.get_handler_by_name('emacs')
423 419 else:
424 420 return None
425 421
426 422
427 423 class MacroChecker(PrefilterChecker):
428 424
429 425 priority = Integer(250, config=True)
430 426
431 427 def check(self, line_info):
432 428 obj = self.shell.user_ns.get(line_info.ifun)
433 429 if isinstance(obj, Macro):
434 430 return self.prefilter_manager.get_handler_by_name('macro')
435 431 else:
436 432 return None
437 433
438 434
439 435 class IPyAutocallChecker(PrefilterChecker):
440 436
441 437 priority = Integer(300, config=True)
442 438
443 439 def check(self, line_info):
444 440 "Instances of IPyAutocall in user_ns get autocalled immediately"
445 441 obj = self.shell.user_ns.get(line_info.ifun, None)
446 442 if isinstance(obj, IPyAutocall):
447 443 obj.set_ip(self.shell)
448 444 return self.prefilter_manager.get_handler_by_name('auto')
449 445 else:
450 446 return None
451 447
452 448
453 449 class AssignmentChecker(PrefilterChecker):
454 450
455 451 priority = Integer(600, config=True)
456 452
457 453 def check(self, line_info):
458 454 """Check to see if user is assigning to a var for the first time, in
459 455 which case we want to avoid any sort of automagic / autocall games.
460 456
461 457 This allows users to assign to either alias or magic names true python
462 458 variables (the magic/alias systems always take second seat to true
463 459 python code). E.g. ls='hi', or ls,that=1,2"""
464 460 if line_info.the_rest:
465 461 if line_info.the_rest[0] in '=,':
466 462 return self.prefilter_manager.get_handler_by_name('normal')
467 463 else:
468 464 return None
469 465
470 466
471 467 class AutoMagicChecker(PrefilterChecker):
472 468
473 469 priority = Integer(700, config=True)
474 470
475 471 def check(self, line_info):
476 472 """If the ifun is magic, and automagic is on, run it. Note: normal,
477 473 non-auto magic would already have been triggered via '%' in
478 474 check_esc_chars. This just checks for automagic. Also, before
479 475 triggering the magic handler, make sure that there is nothing in the
480 476 user namespace which could shadow it."""
481 477 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
482 478 return None
483 479
484 480 # We have a likely magic method. Make sure we should actually call it.
485 481 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
486 482 return None
487 483
488 484 head = line_info.ifun.split('.',1)[0]
489 485 if is_shadowed(head, self.shell):
490 486 return None
491 487
492 488 return self.prefilter_manager.get_handler_by_name('magic')
493 489
494 490
495 491 class AliasChecker(PrefilterChecker):
496 492
497 493 priority = Integer(800, config=True)
498 494
499 495 def check(self, line_info):
500 496 "Check if the initital identifier on the line is an alias."
501 497 # Note: aliases can not contain '.'
502 498 head = line_info.ifun.split('.',1)[0]
503 499 if line_info.ifun not in self.shell.alias_manager \
504 500 or head not in self.shell.alias_manager \
505 501 or is_shadowed(head, self.shell):
506 502 return None
507 503
508 504 return self.prefilter_manager.get_handler_by_name('alias')
509 505
510 506
511 507 class PythonOpsChecker(PrefilterChecker):
512 508
513 509 priority = Integer(900, config=True)
514 510
515 511 def check(self, line_info):
516 512 """If the 'rest' of the line begins with a function call or pretty much
517 513 any python operator, we should simply execute the line (regardless of
518 514 whether or not there's a possible autocall expansion). This avoids
519 515 spurious (and very confusing) geattr() accesses."""
520 516 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
521 517 return self.prefilter_manager.get_handler_by_name('normal')
522 518 else:
523 519 return None
524 520
525 521
526 522 class AutocallChecker(PrefilterChecker):
527 523
528 524 priority = Integer(1000, config=True)
529 525
530 526 function_name_regexp = CRegExp(re_fun_name, config=True,
531 527 help="RegExp to identify potential function names.")
532 528 exclude_regexp = CRegExp(re_exclude_auto, config=True,
533 529 help="RegExp to exclude strings with this start from autocalling.")
534 530
535 531 def check(self, line_info):
536 532 "Check if the initial word/function is callable and autocall is on."
537 533 if not self.shell.autocall:
538 534 return None
539 535
540 536 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
541 537 if not oinfo['found']:
542 538 return None
543 539
544 540 if callable(oinfo['obj']) \
545 541 and (not self.exclude_regexp.match(line_info.the_rest)) \
546 542 and self.function_name_regexp.match(line_info.ifun):
547 543 return self.prefilter_manager.get_handler_by_name('auto')
548 544 else:
549 545 return None
550 546
551 547
552 548 #-----------------------------------------------------------------------------
553 549 # Prefilter handlers
554 550 #-----------------------------------------------------------------------------
555 551
556 552
557 553 class PrefilterHandler(Configurable):
558 554
559 555 handler_name = Unicode('normal')
560 556 esc_strings = List([])
561 557 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
562 558 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
563 559
564 560 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
565 561 super(PrefilterHandler, self).__init__(
566 562 shell=shell, prefilter_manager=prefilter_manager, **kwargs
567 563 )
568 564 self.prefilter_manager.register_handler(
569 565 self.handler_name,
570 566 self,
571 567 self.esc_strings
572 568 )
573 569
574 570 def handle(self, line_info):
575 571 # print "normal: ", line_info
576 572 """Handle normal input lines. Use as a template for handlers."""
577 573
578 574 # With autoindent on, we need some way to exit the input loop, and I
579 575 # don't want to force the user to have to backspace all the way to
580 576 # clear the line. The rule will be in this case, that either two
581 577 # lines of pure whitespace in a row, or a line of pure whitespace but
582 578 # of a size different to the indent level, will exit the input loop.
583 579 line = line_info.line
584 580 continue_prompt = line_info.continue_prompt
585 581
586 582 if (continue_prompt and
587 583 self.shell.autoindent and
588 584 line.isspace() and
589 585 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
590 586 line = ''
591 587
592 588 return line
593 589
594 590 def __str__(self):
595 591 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
596 592
597 593
598 594 class AliasHandler(PrefilterHandler):
599 595
600 596 handler_name = Unicode('alias')
601 597
602 598 def handle(self, line_info):
603 599 """Handle alias input lines. """
604 600 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
605 601 # pre is needed, because it carries the leading whitespace. Otherwise
606 602 # aliases won't work in indented sections.
607 603 line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed)
608 604
609 605 return line_out
610 606
611 607
612 608 class MacroHandler(PrefilterHandler):
613 609 handler_name = Unicode("macro")
614 610
615 611 def handle(self, line_info):
616 612 obj = self.shell.user_ns.get(line_info.ifun)
617 613 pre_space = line_info.pre_whitespace
618 614 line_sep = "\n" + pre_space
619 615 return pre_space + line_sep.join(obj.value.splitlines())
620 616
621 617
622 618 class MagicHandler(PrefilterHandler):
623 619
624 620 handler_name = Unicode('magic')
625 621 esc_strings = List([ESC_MAGIC])
626 622
627 623 def handle(self, line_info):
628 624 """Execute magic functions."""
629 625 ifun = line_info.ifun
630 626 the_rest = line_info.the_rest
631 627 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
632 628 (ifun + " " + the_rest))
633 629 return cmd
634 630
635 631
636 632 class AutoHandler(PrefilterHandler):
637 633
638 634 handler_name = Unicode('auto')
639 635 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
640 636
641 637 def handle(self, line_info):
642 638 """Handle lines which can be auto-executed, quoting if requested."""
643 639 line = line_info.line
644 640 ifun = line_info.ifun
645 641 the_rest = line_info.the_rest
646 642 pre = line_info.pre
647 643 esc = line_info.esc
648 644 continue_prompt = line_info.continue_prompt
649 645 obj = line_info.ofind(self.shell)['obj']
650 646 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
651 647
652 648 # This should only be active for single-line input!
653 649 if continue_prompt:
654 650 return line
655 651
656 652 force_auto = isinstance(obj, IPyAutocall)
657 653
658 654 # User objects sometimes raise exceptions on attribute access other
659 655 # than AttributeError (we've seen it in the past), so it's safest to be
660 656 # ultra-conservative here and catch all.
661 657 try:
662 658 auto_rewrite = obj.rewrite
663 659 except Exception:
664 660 auto_rewrite = True
665 661
666 662 if esc == ESC_QUOTE:
667 663 # Auto-quote splitting on whitespace
668 664 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
669 665 elif esc == ESC_QUOTE2:
670 666 # Auto-quote whole string
671 667 newcmd = '%s("%s")' % (ifun,the_rest)
672 668 elif esc == ESC_PAREN:
673 669 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
674 670 else:
675 671 # Auto-paren.
676 672 if force_auto:
677 673 # Don't rewrite if it is already a call.
678 674 do_rewrite = not the_rest.startswith('(')
679 675 else:
680 676 if not the_rest:
681 677 # We only apply it to argument-less calls if the autocall
682 678 # parameter is set to 2.
683 679 do_rewrite = (self.shell.autocall >= 2)
684 680 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
685 681 # Don't autocall in this case: item access for an object
686 682 # which is BOTH callable and implements __getitem__.
687 683 do_rewrite = False
688 684 else:
689 685 do_rewrite = True
690 686
691 687 # Figure out the rewritten command
692 688 if do_rewrite:
693 689 if the_rest.endswith(';'):
694 690 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
695 691 else:
696 692 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
697 693 else:
698 694 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
699 695 return normal_handler.handle(line_info)
700 696
701 697 # Display the rewritten call
702 698 if auto_rewrite:
703 699 self.shell.auto_rewrite_input(newcmd)
704 700
705 701 return newcmd
706 702
707 703
708 704 class EmacsHandler(PrefilterHandler):
709 705
710 706 handler_name = Unicode('emacs')
711 707 esc_strings = List([])
712 708
713 709 def handle(self, line_info):
714 710 """Handle input lines marked by python-mode."""
715 711
716 712 # Currently, nothing is done. Later more functionality can be added
717 713 # here if needed.
718 714
719 715 # The input cache shouldn't be updated
720 716 return line_info.line
721 717
722 718
723 719 #-----------------------------------------------------------------------------
724 720 # Defaults
725 721 #-----------------------------------------------------------------------------
726 722
727 723
728 724 _default_transformers = [
729 725 ]
730 726
731 727 _default_checkers = [
732 728 EmacsChecker,
733 729 MacroChecker,
734 730 IPyAutocallChecker,
735 731 AssignmentChecker,
736 732 AutoMagicChecker,
737 733 AliasChecker,
738 734 PythonOpsChecker,
739 735 AutocallChecker
740 736 ]
741 737
742 738 _default_handlers = [
743 739 PrefilterHandler,
744 740 AliasHandler,
745 741 MacroHandler,
746 742 MagicHandler,
747 743 AutoHandler,
748 744 EmacsHandler
749 745 ]
@@ -1,83 +1,79 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for completerlib.
3 3
4 4 """
5 5 from __future__ import absolute_import
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Imports
9 9 #-----------------------------------------------------------------------------
10 10
11 11 import os
12 12 import shutil
13 13 import sys
14 14 import tempfile
15 15 import unittest
16 16 from os.path import join
17 17
18 import nose.tools as nt
19 from nose import SkipTest
20
21 18 from IPython.core.completerlib import magic_run_completer, module_completion
22 from IPython.utils import py3compat
23 19 from IPython.utils.tempdir import TemporaryDirectory
24 20
25 21
26 22 class MockEvent(object):
27 23 def __init__(self, line):
28 24 self.line = line
29 25
30 26 #-----------------------------------------------------------------------------
31 27 # Test functions begin
32 28 #-----------------------------------------------------------------------------
33 29 class Test_magic_run_completer(unittest.TestCase):
34 30 def setUp(self):
35 31 self.BASETESTDIR = tempfile.mkdtemp()
36 32 for fil in [u"aaø.py", u"a.py", u"b.py"]:
37 33 with open(join(self.BASETESTDIR, fil), "w") as sfile:
38 34 sfile.write("pass\n")
39 35 self.oldpath = os.getcwdu()
40 36 os.chdir(self.BASETESTDIR)
41 37
42 38 def tearDown(self):
43 39 os.chdir(self.oldpath)
44 40 shutil.rmtree(self.BASETESTDIR)
45 41
46 42 def test_1(self):
47 43 """Test magic_run_completer, should match two alterntives
48 44 """
49 45 event = MockEvent(u"%run a")
50 46 mockself = None
51 47 match = set(magic_run_completer(mockself, event))
52 48 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
53 49
54 50 def test_2(self):
55 51 """Test magic_run_completer, should match one alterntive
56 52 """
57 53 event = MockEvent(u"%run aa")
58 54 mockself = None
59 55 match = set(magic_run_completer(mockself, event))
60 56 self.assertEqual(match, set([u"aaø.py"]))
61 57
62 58 def test_3(self):
63 59 """Test magic_run_completer with unterminated " """
64 60 event = MockEvent(u'%run "a')
65 61 mockself = None
66 62 match = set(magic_run_completer(mockself, event))
67 63 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
68 64
69 65 def test_import_invalid_module(self):
70 66 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
71 67 invalid_module_names = set(['foo-bar', 'foo:bar', '10foo'])
72 68 valid_module_names = set(['foobar'])
73 69 with TemporaryDirectory() as tmpdir:
74 70 sys.path.insert( 0, tmpdir )
75 71 for name in invalid_module_names | valid_module_names:
76 72 filename = os.path.join(tmpdir, name + '.py')
77 73 open(filename, 'w').close()
78 74
79 75 s = set( module_completion('import foo') )
80 76 intersection = s.intersection(invalid_module_names)
81 77 self.assertFalse(intersection, intersection)
82 78
83 79 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
@@ -1,142 +1,142 b''
1 1 """Tests for debugging machinery.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012, The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 import sys
16 16
17 17 # third-party
18 18 import nose.tools as nt
19 19
20 20 # Our own
21 21 from IPython.core import debugger
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Helper classes, from CPython's Pdb test suite
25 25 #-----------------------------------------------------------------------------
26 26
27 27 class _FakeInput(object):
28 28 """
29 29 A fake input stream for pdb's interactive debugger. Whenever a
30 30 line is read, print it (to simulate the user typing it), and then
31 31 return it. The set of lines to return is specified in the
32 32 constructor; they should not have trailing newlines.
33 33 """
34 34 def __init__(self, lines):
35 35 self.lines = iter(lines)
36 36
37 37 def readline(self):
38 38 line = next(self.lines)
39 39 print line
40 40 return line+'\n'
41 41
42 42 class PdbTestInput(object):
43 43 """Context manager that makes testing Pdb in doctests easier."""
44 44
45 45 def __init__(self, input):
46 46 self.input = input
47 47
48 48 def __enter__(self):
49 49 self.real_stdin = sys.stdin
50 50 sys.stdin = _FakeInput(self.input)
51 51
52 52 def __exit__(self, *exc):
53 53 sys.stdin = self.real_stdin
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Tests
57 57 #-----------------------------------------------------------------------------
58 58
59 59 def test_longer_repr():
60 60 from repr import repr as trepr
61 61
62 62 a = '1234567890'* 7
63 63 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
64 64 a_trunc = "'123456789012...8901234567890'"
65 65 nt.assert_equal(trepr(a), a_trunc)
66 66 # The creation of our tracer modifies the repr module's repr function
67 67 # in-place, since that global is used directly by the stdlib's pdb module.
68 68 t = debugger.Tracer()
69 69 nt.assert_equal(trepr(a), ar)
70 70
71 71 def test_ipdb_magics():
72 72 '''Test calling some IPython magics from ipdb.
73 73
74 74 First, set up some test functions and classes which we can inspect.
75 75
76 76 >>> class ExampleClass(object):
77 77 ... """Docstring for ExampleClass."""
78 78 ... def __init__(self):
79 79 ... """Docstring for ExampleClass.__init__"""
80 80 ... pass
81 81 ... def __str__(self):
82 82 ... return "ExampleClass()"
83 83
84 84 >>> def example_function(x, y, z="hello"):
85 85 ... """Docstring for example_function."""
86 86 ... pass
87 87
88 88 Create a function which triggers ipdb.
89 89
90 90 >>> def trigger_ipdb():
91 91 ... a = ExampleClass()
92 92 ... debugger.Pdb().set_trace()
93 93
94 94 >>> with PdbTestInput([
95 95 ... 'pdef example_function',
96 96 ... 'pdoc ExampleClass',
97 97 ... 'pinfo a',
98 98 ... 'continue',
99 99 ... ]):
100 100 ... trigger_ipdb()
101 101 --Return--
102 102 None
103 103 > <doctest ...>(3)trigger_ipdb()
104 104 1 def trigger_ipdb():
105 105 2 a = ExampleClass()
106 106 ----> 3 debugger.Pdb().set_trace()
107 107 <BLANKLINE>
108 108 ipdb> pdef example_function
109 109 example_function(x, y, z='hello')
110 110 ipdb> pdoc ExampleClass
111 111 Class Docstring:
112 112 Docstring for ExampleClass.
113 113 Constructor Docstring:
114 114 Docstring for ExampleClass.__init__
115 115 ipdb> pinfo a
116 116 Type: ExampleClass
117 117 String Form:ExampleClass()
118 118 Namespace: Locals
119 119 File: ...
120 120 Docstring: Docstring for ExampleClass.
121 121 Constructor Docstring:Docstring for ExampleClass.__init__
122 122 ipdb> continue
123 123 '''
124 124
125 def test_ipdb_magics():
125 def test_ipdb_magics2():
126 126 '''Test ipdb with a very short function.
127 127
128 128 >>> def bar():
129 129 ... pass
130 130
131 131 Run ipdb.
132 132
133 133 >>> with PdbTestInput([
134 134 ... 'continue',
135 135 ... ]):
136 136 ... debugger.Pdb().runcall(bar)
137 137 > <doctest ...>(2)bar()
138 138 1 def bar():
139 139 ----> 2 pass
140 140 <BLANKLINE>
141 141 ipdb> continue
142 142 '''
@@ -1,17 +1,17 b''
1 1 """Tests for the FakeModule objects.
2 2 """
3 3
4 4 import nose.tools as nt
5 5
6 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
6 from IPython.core.fakemodule import FakeModule
7 7
8 8 # Make a fakemod and check a few properties
9 9 def test_mk_fakemod():
10 10 fm = FakeModule()
11 11 yield nt.assert_true,fm
12 12 yield nt.assert_true,lambda : hasattr(fm,'__file__')
13 13
14 14 def test_mk_fakemod_fromdict():
15 15 """Test making a FakeModule object with initial data"""
16 16 fm = FakeModule(dict(hello=True))
17 17 nt.assert_true(fm.hello)
@@ -1,91 +1,90 b''
1 1 """Tests for the Formatters.
2 2 """
3 3
4 4 from math import pi
5 5
6 6 try:
7 7 import numpy
8 8 except:
9 9 numpy = None
10 10 import nose.tools as nt
11 11
12 from IPython.core.formatters import FormatterABC, PlainTextFormatter
13 from IPython.lib import pretty
12 from IPython.core.formatters import PlainTextFormatter
14 13
15 14 class A(object):
16 15 def __repr__(self):
17 16 return 'A()'
18 17
19 18 class B(A):
20 19 def __repr__(self):
21 20 return 'B()'
22 21
23 22 class BadPretty(object):
24 23 _repr_pretty_ = None
25 24
26 25 class GoodPretty(object):
27 26 def _repr_pretty_(self, pp, cycle):
28 27 pp.text('foo')
29 28
30 29 def __repr__(self):
31 30 return 'GoodPretty()'
32 31
33 32 def foo_printer(obj, pp, cycle):
34 33 pp.text('foo')
35 34
36 35 def test_pretty():
37 36 f = PlainTextFormatter()
38 37 f.for_type(A, foo_printer)
39 38 nt.assert_equal(f(A()), 'foo')
40 39 nt.assert_equal(f(B()), 'foo')
41 40 nt.assert_equal(f(GoodPretty()), 'foo')
42 41 # Just don't raise an exception for the following:
43 42 f(BadPretty())
44 43
45 44 f.pprint = False
46 45 nt.assert_equal(f(A()), 'A()')
47 46 nt.assert_equal(f(B()), 'B()')
48 47 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
49 48
50 49
51 50 def test_deferred():
52 51 f = PlainTextFormatter()
53 52
54 53 def test_precision():
55 54 """test various values for float_precision."""
56 55 f = PlainTextFormatter()
57 56 nt.assert_equal(f(pi), repr(pi))
58 57 f.float_precision = 0
59 58 if numpy:
60 59 po = numpy.get_printoptions()
61 60 nt.assert_equal(po['precision'], 0)
62 61 nt.assert_equal(f(pi), '3')
63 62 f.float_precision = 2
64 63 if numpy:
65 64 po = numpy.get_printoptions()
66 65 nt.assert_equal(po['precision'], 2)
67 66 nt.assert_equal(f(pi), '3.14')
68 67 f.float_precision = '%g'
69 68 if numpy:
70 69 po = numpy.get_printoptions()
71 70 nt.assert_equal(po['precision'], 2)
72 71 nt.assert_equal(f(pi), '3.14159')
73 72 f.float_precision = '%e'
74 73 nt.assert_equal(f(pi), '3.141593e+00')
75 74 f.float_precision = ''
76 75 if numpy:
77 76 po = numpy.get_printoptions()
78 77 nt.assert_equal(po['precision'], 8)
79 78 nt.assert_equal(f(pi), repr(pi))
80 79
81 80 def test_bad_precision():
82 81 """test various invalid values for float_precision."""
83 82 f = PlainTextFormatter()
84 83 def set_fp(p):
85 84 f.float_precision=p
86 85 nt.assert_raises(ValueError, set_fp, '%')
87 86 nt.assert_raises(ValueError, set_fp, '%.3f%i')
88 87 nt.assert_raises(ValueError, set_fp, 'foo')
89 88 nt.assert_raises(ValueError, set_fp, -1)
90 89
91 90
@@ -1,185 +1,183 b''
1 1 # coding: utf-8
2 2 """Tests for the IPython tab-completion machinery.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Module imports
6 6 #-----------------------------------------------------------------------------
7 7
8 8 # stdlib
9 9 import os
10 import shutil
11 10 import sys
12 11 import tempfile
13 import unittest
14 12 from datetime import datetime
15 13
16 14 # third party
17 15 import nose.tools as nt
18 16
19 17 # our own packages
20 18 from IPython.config.loader import Config
21 19 from IPython.utils.tempdir import TemporaryDirectory
22 20 from IPython.core.history import HistoryManager, extract_hist_ranges
23 21 from IPython.utils import py3compat
24 22
25 23 def setUp():
26 24 nt.assert_equal(sys.getdefaultencoding(), "utf-8" if py3compat.PY3 else "ascii")
27 25
28 26 def test_history():
29 27 ip = get_ipython()
30 28 with TemporaryDirectory() as tmpdir:
31 29 hist_manager_ori = ip.history_manager
32 30 hist_file = os.path.join(tmpdir, 'history.sqlite')
33 31 try:
34 32 ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file)
35 33 hist = [u'a=1', u'def f():\n test = 1\n return test', u"b='€Æ¾÷ß'"]
36 34 for i, h in enumerate(hist, start=1):
37 35 ip.history_manager.store_inputs(i, h)
38 36
39 37 ip.history_manager.db_log_output = True
40 38 # Doesn't match the input, but we'll just check it's stored.
41 39 ip.history_manager.output_hist_reprs[3] = "spam"
42 40 ip.history_manager.store_output(3)
43 41
44 42 nt.assert_equal(ip.history_manager.input_hist_raw, [''] + hist)
45 43
46 44 # Detailed tests for _get_range_session
47 45 grs = ip.history_manager._get_range_session
48 46 nt.assert_equal(list(grs(start=2,stop=-1)), zip([0], [2], hist[1:-1]))
49 47 nt.assert_equal(list(grs(start=-2)), zip([0,0], [2,3], hist[-2:]))
50 48 nt.assert_equal(list(grs(output=True)), zip([0,0,0], [1,2,3], zip(hist, [None,None,'spam'])))
51 49
52 50 # Check whether specifying a range beyond the end of the current
53 51 # session results in an error (gh-804)
54 52 ip.magic('%hist 2-500')
55 53
56 54 # Check that we can write non-ascii characters to a file
57 55 ip.magic("%%hist -f %s" % os.path.join(tmpdir, "test1"))
58 56 ip.magic("%%hist -pf %s" % os.path.join(tmpdir, "test2"))
59 57 ip.magic("%%hist -nf %s" % os.path.join(tmpdir, "test3"))
60 58 ip.magic("%%save %s 1-10" % os.path.join(tmpdir, "test4"))
61 59
62 60 # New session
63 61 ip.history_manager.reset()
64 62 newcmds = [u"z=5",
65 63 u"class X(object):\n pass",
66 64 u"k='p'",
67 65 u"z=5"]
68 66 for i, cmd in enumerate(newcmds, start=1):
69 67 ip.history_manager.store_inputs(i, cmd)
70 68 gothist = ip.history_manager.get_range(start=1, stop=4)
71 69 nt.assert_equal(list(gothist), zip([0,0,0],[1,2,3], newcmds))
72 70 # Previous session:
73 71 gothist = ip.history_manager.get_range(-1, 1, 4)
74 72 nt.assert_equal(list(gothist), zip([1,1,1],[1,2,3], hist))
75 73
76 74 newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)]
77 75
78 76 # Check get_hist_tail
79 77 gothist = ip.history_manager.get_tail(5, output=True,
80 78 include_latest=True)
81 79 expected = [(1, 3, (hist[-1], "spam"))] \
82 80 + [(s, n, (c, None)) for (s, n, c) in newhist]
83 81 nt.assert_equal(list(gothist), expected)
84 82
85 83 gothist = ip.history_manager.get_tail(2)
86 84 expected = newhist[-3:-1]
87 85 nt.assert_equal(list(gothist), expected)
88 86
89 87 # Check get_hist_search
90 88 gothist = ip.history_manager.search("*test*")
91 89 nt.assert_equal(list(gothist), [(1,2,hist[1])] )
92 90
93 91 gothist = ip.history_manager.search("*=*")
94 92 nt.assert_equal(list(gothist),
95 93 [(1, 1, hist[0]),
96 94 (1, 2, hist[1]),
97 95 (1, 3, hist[2]),
98 96 newhist[0],
99 97 newhist[2],
100 98 newhist[3]])
101 99
102 100 gothist = ip.history_manager.search("*=*", n=4)
103 101 nt.assert_equal(list(gothist),
104 102 [(1, 3, hist[2]),
105 103 newhist[0],
106 104 newhist[2],
107 105 newhist[3]])
108 106
109 107 gothist = ip.history_manager.search("*=*", unique=True)
110 108 nt.assert_equal(list(gothist),
111 109 [(1, 1, hist[0]),
112 110 (1, 2, hist[1]),
113 111 (1, 3, hist[2]),
114 112 newhist[2],
115 113 newhist[3]])
116 114
117 115 gothist = ip.history_manager.search("*=*", unique=True, n=3)
118 116 nt.assert_equal(list(gothist),
119 117 [(1, 3, hist[2]),
120 118 newhist[2],
121 119 newhist[3]])
122 120
123 121 gothist = ip.history_manager.search("b*", output=True)
124 122 nt.assert_equal(list(gothist), [(1,3,(hist[2],"spam"))] )
125 123
126 124 # Cross testing: check that magic %save can get previous session.
127 125 testfilename = os.path.realpath(os.path.join(tmpdir, "test.py"))
128 126 ip.magic("save " + testfilename + " ~1/1-3")
129 127 with py3compat.open(testfilename, encoding='utf-8') as testfile:
130 128 nt.assert_equal(testfile.read(),
131 129 u"# coding: utf-8\n" + u"\n".join(hist)+u"\n")
132 130
133 131 # Duplicate line numbers - check that it doesn't crash, and
134 132 # gets a new session
135 133 ip.history_manager.store_inputs(1, "rogue")
136 134 ip.history_manager.writeout_cache()
137 135 nt.assert_equal(ip.history_manager.session_number, 3)
138 136 finally:
139 137 # Restore history manager
140 138 ip.history_manager = hist_manager_ori
141 139
142 140
143 141 def test_extract_hist_ranges():
144 142 instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/"
145 143 expected = [(0, 1, 2), # 0 == current session
146 144 (2, 3, 4),
147 145 (-4, 5, 7),
148 146 (-4, 7, 10),
149 147 (-9, 2, None), # None == to end
150 148 (-8, 1, None),
151 149 (-7, 1, 6),
152 150 (-10, 1, None)]
153 151 actual = list(extract_hist_ranges(instr))
154 152 nt.assert_equal(actual, expected)
155 153
156 154 def test_magic_rerun():
157 155 """Simple test for %rerun (no args -> rerun last line)"""
158 156 ip = get_ipython()
159 157 ip.run_cell("a = 10", store_history=True)
160 158 ip.run_cell("a += 1", store_history=True)
161 159 nt.assert_equal(ip.user_ns["a"], 11)
162 160 ip.run_cell("%rerun", store_history=True)
163 161 nt.assert_equal(ip.user_ns["a"], 12)
164 162
165 163 def test_timestamp_type():
166 164 ip = get_ipython()
167 165 info = ip.history_manager.get_session_info()
168 166 nt.assert_true(isinstance(info[1], datetime))
169 167
170 168 def test_hist_file_config():
171 169 cfg = Config()
172 170 tfile = tempfile.NamedTemporaryFile(delete=False)
173 171 cfg.HistoryManager.hist_file = tfile.name
174 172 try:
175 173 hm = HistoryManager(shell=get_ipython(), config=cfg)
176 174 nt.assert_equal(hm.hist_file, cfg.HistoryManager.hist_file)
177 175 finally:
178 176 try:
179 177 os.remove(tfile.name)
180 178 except OSError:
181 179 # same catch as in testing.tools.TempFileMixin
182 180 # On Windows, even though we close the file, we still can't
183 181 # delete it. I have no clue why
184 182 pass
185 183
@@ -1,572 +1,564 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the inputsplitter module.
3 3
4 4 Authors
5 5 -------
6 6 * Fernando Perez
7 7 * Robert Kern
8 8 """
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010-2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19 # stdlib
20 20 import unittest
21 21 import sys
22 22
23 23 # Third party
24 24 import nose.tools as nt
25 25
26 26 # Our own
27 27 from IPython.core import inputsplitter as isp
28 28 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
29 29 from IPython.testing import tools as tt
30 30 from IPython.utils import py3compat
31 31
32 32 #-----------------------------------------------------------------------------
33 33 # Semi-complete examples (also used as tests)
34 34 #-----------------------------------------------------------------------------
35 35
36 36 # Note: at the bottom, there's a slightly more complete version of this that
37 37 # can be useful during development of code here.
38 38
39 39 def mini_interactive_loop(input_func):
40 40 """Minimal example of the logic of an interactive interpreter loop.
41 41
42 42 This serves as an example, and it is used by the test system with a fake
43 43 raw_input that simulates interactive input."""
44 44
45 45 from IPython.core.inputsplitter import InputSplitter
46 46
47 47 isp = InputSplitter()
48 48 # In practice, this input loop would be wrapped in an outside loop to read
49 49 # input indefinitely, until some exit/quit command was issued. Here we
50 50 # only illustrate the basic inner loop.
51 51 while isp.push_accepts_more():
52 52 indent = ' '*isp.indent_spaces
53 53 prompt = '>>> ' + indent
54 54 line = indent + input_func(prompt)
55 55 isp.push(line)
56 56
57 57 # Here we just return input so we can use it in a test suite, but a real
58 58 # interpreter would instead send it for execution somewhere.
59 59 src = isp.source_reset()
60 60 #print 'Input source was:\n', src # dbg
61 61 return src
62 62
63 63 #-----------------------------------------------------------------------------
64 64 # Test utilities, just for local use
65 65 #-----------------------------------------------------------------------------
66 66
67 67 def assemble(block):
68 68 """Assemble a block into multi-line sub-blocks."""
69 69 return ['\n'.join(sub_block)+'\n' for sub_block in block]
70 70
71 71
72 72 def pseudo_input(lines):
73 73 """Return a function that acts like raw_input but feeds the input list."""
74 74 ilines = iter(lines)
75 75 def raw_in(prompt):
76 76 try:
77 77 return next(ilines)
78 78 except StopIteration:
79 79 return ''
80 80 return raw_in
81 81
82 82 #-----------------------------------------------------------------------------
83 83 # Tests
84 84 #-----------------------------------------------------------------------------
85 85 def test_spaces():
86 86 tests = [('', 0),
87 87 (' ', 1),
88 88 ('\n', 0),
89 89 (' \n', 1),
90 90 ('x', 0),
91 91 (' x', 1),
92 92 (' x',2),
93 93 (' x',4),
94 94 # Note: tabs are counted as a single whitespace!
95 95 ('\tx', 1),
96 96 ('\t x', 2),
97 97 ]
98 98 tt.check_pairs(isp.num_ini_spaces, tests)
99 99
100 100
101 101 def test_remove_comments():
102 102 tests = [('text', 'text'),
103 103 ('text # comment', 'text '),
104 104 ('text # comment\n', 'text \n'),
105 105 ('text # comment \n', 'text \n'),
106 106 ('line # c \nline\n','line \nline\n'),
107 107 ('line # c \nline#c2 \nline\nline #c\n\n',
108 108 'line \nline\nline\nline \n\n'),
109 109 ]
110 110 tt.check_pairs(isp.remove_comments, tests)
111 111
112 112
113 113 def test_get_input_encoding():
114 114 encoding = isp.get_input_encoding()
115 115 nt.assert_true(isinstance(encoding, basestring))
116 116 # simple-minded check that at least encoding a simple string works with the
117 117 # encoding we got.
118 118 nt.assert_equal(u'test'.encode(encoding), b'test')
119 119
120 120
121 121 class NoInputEncodingTestCase(unittest.TestCase):
122 122 def setUp(self):
123 123 self.old_stdin = sys.stdin
124 124 class X: pass
125 125 fake_stdin = X()
126 126 sys.stdin = fake_stdin
127 127
128 128 def test(self):
129 129 # Verify that if sys.stdin has no 'encoding' attribute we do the right
130 130 # thing
131 131 enc = isp.get_input_encoding()
132 132 self.assertEqual(enc, 'ascii')
133 133
134 134 def tearDown(self):
135 135 sys.stdin = self.old_stdin
136 136
137 137
138 138 class InputSplitterTestCase(unittest.TestCase):
139 139 def setUp(self):
140 140 self.isp = isp.InputSplitter()
141 141
142 142 def test_reset(self):
143 143 isp = self.isp
144 144 isp.push('x=1')
145 145 isp.reset()
146 146 self.assertEqual(isp._buffer, [])
147 147 self.assertEqual(isp.indent_spaces, 0)
148 148 self.assertEqual(isp.source, '')
149 149 self.assertEqual(isp.code, None)
150 150 self.assertEqual(isp._is_complete, False)
151 151
152 152 def test_source(self):
153 153 self.isp._store('1')
154 154 self.isp._store('2')
155 155 self.assertEqual(self.isp.source, '1\n2\n')
156 156 self.assertTrue(len(self.isp._buffer)>0)
157 157 self.assertEqual(self.isp.source_reset(), '1\n2\n')
158 158 self.assertEqual(self.isp._buffer, [])
159 159 self.assertEqual(self.isp.source, '')
160 160
161 161 def test_indent(self):
162 162 isp = self.isp # shorthand
163 163 isp.push('x=1')
164 164 self.assertEqual(isp.indent_spaces, 0)
165 165 isp.push('if 1:\n x=1')
166 166 self.assertEqual(isp.indent_spaces, 4)
167 167 isp.push('y=2\n')
168 168 self.assertEqual(isp.indent_spaces, 0)
169 169
170 170 def test_indent2(self):
171 171 isp = self.isp
172 172 isp.push('if 1:')
173 173 self.assertEqual(isp.indent_spaces, 4)
174 174 isp.push(' x=1')
175 175 self.assertEqual(isp.indent_spaces, 4)
176 176 # Blank lines shouldn't change the indent level
177 177 isp.push(' '*2)
178 178 self.assertEqual(isp.indent_spaces, 4)
179 179
180 180 def test_indent3(self):
181 181 isp = self.isp
182 182 # When a multiline statement contains parens or multiline strings, we
183 183 # shouldn't get confused.
184 184 isp.push("if 1:")
185 185 isp.push(" x = (1+\n 2)")
186 186 self.assertEqual(isp.indent_spaces, 4)
187 187
188 188 def test_indent4(self):
189 189 isp = self.isp
190 190 # whitespace after ':' should not screw up indent level
191 191 isp.push('if 1: \n x=1')
192 192 self.assertEqual(isp.indent_spaces, 4)
193 193 isp.push('y=2\n')
194 194 self.assertEqual(isp.indent_spaces, 0)
195 195 isp.push('if 1:\t\n x=1')
196 196 self.assertEqual(isp.indent_spaces, 4)
197 197 isp.push('y=2\n')
198 198 self.assertEqual(isp.indent_spaces, 0)
199 199
200 200 def test_dedent_pass(self):
201 201 isp = self.isp # shorthand
202 202 # should NOT cause dedent
203 203 isp.push('if 1:\n passes = 5')
204 204 self.assertEqual(isp.indent_spaces, 4)
205 205 isp.push('if 1:\n pass')
206 206 self.assertEqual(isp.indent_spaces, 0)
207 207 isp.push('if 1:\n pass ')
208 208 self.assertEqual(isp.indent_spaces, 0)
209 209
210 210 def test_dedent_break(self):
211 211 isp = self.isp # shorthand
212 212 # should NOT cause dedent
213 213 isp.push('while 1:\n breaks = 5')
214 214 self.assertEqual(isp.indent_spaces, 4)
215 215 isp.push('while 1:\n break')
216 216 self.assertEqual(isp.indent_spaces, 0)
217 217 isp.push('while 1:\n break ')
218 218 self.assertEqual(isp.indent_spaces, 0)
219 219
220 220 def test_dedent_continue(self):
221 221 isp = self.isp # shorthand
222 222 # should NOT cause dedent
223 223 isp.push('while 1:\n continues = 5')
224 224 self.assertEqual(isp.indent_spaces, 4)
225 225 isp.push('while 1:\n continue')
226 226 self.assertEqual(isp.indent_spaces, 0)
227 227 isp.push('while 1:\n continue ')
228 228 self.assertEqual(isp.indent_spaces, 0)
229 229
230 230 def test_dedent_raise(self):
231 231 isp = self.isp # shorthand
232 232 # should NOT cause dedent
233 233 isp.push('if 1:\n raised = 4')
234 234 self.assertEqual(isp.indent_spaces, 4)
235 235 isp.push('if 1:\n raise TypeError()')
236 236 self.assertEqual(isp.indent_spaces, 0)
237 237 isp.push('if 1:\n raise')
238 238 self.assertEqual(isp.indent_spaces, 0)
239 239 isp.push('if 1:\n raise ')
240 240 self.assertEqual(isp.indent_spaces, 0)
241 241
242 242 def test_dedent_return(self):
243 243 isp = self.isp # shorthand
244 244 # should NOT cause dedent
245 245 isp.push('if 1:\n returning = 4')
246 246 self.assertEqual(isp.indent_spaces, 4)
247 247 isp.push('if 1:\n return 5 + 493')
248 248 self.assertEqual(isp.indent_spaces, 0)
249 249 isp.push('if 1:\n return')
250 250 self.assertEqual(isp.indent_spaces, 0)
251 251 isp.push('if 1:\n return ')
252 252 self.assertEqual(isp.indent_spaces, 0)
253 253 isp.push('if 1:\n return(0)')
254 254 self.assertEqual(isp.indent_spaces, 0)
255 255
256 256 def test_push(self):
257 257 isp = self.isp
258 258 self.assertTrue(isp.push('x=1'))
259 259
260 260 def test_push2(self):
261 261 isp = self.isp
262 262 self.assertFalse(isp.push('if 1:'))
263 263 for line in [' x=1', '# a comment', ' y=2']:
264 264 print(line)
265 265 self.assertTrue(isp.push(line))
266 266
267 267 def test_push3(self):
268 268 isp = self.isp
269 269 isp.push('if True:')
270 270 isp.push(' a = 1')
271 271 self.assertFalse(isp.push('b = [1,'))
272 272
273 273 def test_push_accepts_more(self):
274 274 isp = self.isp
275 275 isp.push('x=1')
276 276 self.assertFalse(isp.push_accepts_more())
277 277
278 278 def test_push_accepts_more2(self):
279 279 isp = self.isp
280 280 isp.push('if 1:')
281 281 self.assertTrue(isp.push_accepts_more())
282 282 isp.push(' x=1')
283 283 self.assertTrue(isp.push_accepts_more())
284 284 isp.push('')
285 285 self.assertFalse(isp.push_accepts_more())
286 286
287 287 def test_push_accepts_more3(self):
288 288 isp = self.isp
289 289 isp.push("x = (2+\n3)")
290 290 self.assertFalse(isp.push_accepts_more())
291 291
292 292 def test_push_accepts_more4(self):
293 293 isp = self.isp
294 294 # When a multiline statement contains parens or multiline strings, we
295 295 # shouldn't get confused.
296 296 # FIXME: we should be able to better handle de-dents in statements like
297 297 # multiline strings and multiline expressions (continued with \ or
298 298 # parens). Right now we aren't handling the indentation tracking quite
299 299 # correctly with this, though in practice it may not be too much of a
300 300 # problem. We'll need to see.
301 301 isp.push("if 1:")
302 302 isp.push(" x = (2+")
303 303 isp.push(" 3)")
304 304 self.assertTrue(isp.push_accepts_more())
305 305 isp.push(" y = 3")
306 306 self.assertTrue(isp.push_accepts_more())
307 307 isp.push('')
308 308 self.assertFalse(isp.push_accepts_more())
309 309
310 310 def test_push_accepts_more5(self):
311 311 isp = self.isp
312 312 isp.push('try:')
313 313 isp.push(' a = 5')
314 314 isp.push('except:')
315 315 isp.push(' raise')
316 316 # We want to be able to add an else: block at this point, so it should
317 317 # wait for a blank line.
318 318 self.assertTrue(isp.push_accepts_more())
319 319
320 320 def test_continuation(self):
321 321 isp = self.isp
322 322 isp.push("import os, \\")
323 323 self.assertTrue(isp.push_accepts_more())
324 324 isp.push("sys")
325 325 self.assertFalse(isp.push_accepts_more())
326 326
327 327 def test_syntax_error(self):
328 328 isp = self.isp
329 329 # Syntax errors immediately produce a 'ready' block, so the invalid
330 330 # Python can be sent to the kernel for evaluation with possible ipython
331 331 # special-syntax conversion.
332 332 isp.push('run foo')
333 333 self.assertFalse(isp.push_accepts_more())
334 334
335 335 def test_unicode(self):
336 336 self.isp.push(u"Pérez")
337 337 self.isp.push(u'\xc3\xa9')
338 338 self.isp.push(u"u'\xc3\xa9'")
339 339
340 340 def test_line_continuation(self):
341 341 """ Test issue #2108."""
342 342 isp = self.isp
343 343 # A blank line after a line continuation should not accept more
344 344 isp.push("1 \\\n\n")
345 345 self.assertFalse(isp.push_accepts_more())
346 346 # Whitespace after a \ is a SyntaxError. The only way to test that
347 347 # here is to test that push doesn't accept more (as with
348 348 # test_syntax_error() above).
349 349 isp.push(r"1 \ ")
350 350 self.assertFalse(isp.push_accepts_more())
351 351 # Even if the line is continuable (c.f. the regular Python
352 352 # interpreter)
353 353 isp.push(r"(1 \ ")
354 354 self.assertFalse(isp.push_accepts_more())
355 355
356 356 class InteractiveLoopTestCase(unittest.TestCase):
357 357 """Tests for an interactive loop like a python shell.
358 358 """
359 359 def check_ns(self, lines, ns):
360 360 """Validate that the given input lines produce the resulting namespace.
361 361
362 362 Note: the input lines are given exactly as they would be typed in an
363 363 auto-indenting environment, as mini_interactive_loop above already does
364 364 auto-indenting and prepends spaces to the input.
365 365 """
366 366 src = mini_interactive_loop(pseudo_input(lines))
367 367 test_ns = {}
368 368 exec src in test_ns
369 369 # We can't check that the provided ns is identical to the test_ns,
370 370 # because Python fills test_ns with extra keys (copyright, etc). But
371 371 # we can check that the given dict is *contained* in test_ns
372 372 for k,v in ns.iteritems():
373 373 self.assertEqual(test_ns[k], v)
374 374
375 375 def test_simple(self):
376 376 self.check_ns(['x=1'], dict(x=1))
377 377
378 378 def test_simple2(self):
379 379 self.check_ns(['if 1:', 'x=2'], dict(x=2))
380 380
381 381 def test_xy(self):
382 382 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
383 383
384 384 def test_abc(self):
385 385 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
386 386
387 387 def test_multi(self):
388 388 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
389 389
390 390
391 def test_LineInfo():
392 """Simple test for LineInfo construction and str()"""
393 linfo = isp.LineInfo(' %cd /home')
394 nt.assert_equal(str(linfo), 'LineInfo [ |%|cd|/home]')
395
396
397
398
399 391 class IPythonInputTestCase(InputSplitterTestCase):
400 392 """By just creating a new class whose .isp is a different instance, we
401 393 re-run the same test battery on the new input splitter.
402 394
403 395 In addition, this runs the tests over the syntax and syntax_ml dicts that
404 396 were tested by individual functions, as part of the OO interface.
405 397
406 398 It also makes some checks on the raw buffer storage.
407 399 """
408 400
409 401 def setUp(self):
410 402 self.isp = isp.IPythonInputSplitter()
411 403
412 404 def test_syntax(self):
413 405 """Call all single-line syntax tests from the main object"""
414 406 isp = self.isp
415 407 for example in syntax.itervalues():
416 408 for raw, out_t in example:
417 409 if raw.startswith(' '):
418 410 continue
419 411
420 412 isp.push(raw+'\n')
421 413 out, out_raw = isp.source_raw_reset()
422 414 self.assertEqual(out.rstrip(), out_t,
423 415 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
424 416 self.assertEqual(out_raw.rstrip(), raw.rstrip())
425 417
426 418 def test_syntax_multiline(self):
427 419 isp = self.isp
428 420 for example in syntax_ml.itervalues():
429 421 for line_pairs in example:
430 422 out_t_parts = []
431 423 raw_parts = []
432 424 for lraw, out_t_part in line_pairs:
433 425 if out_t_part is not None:
434 426 out_t_parts.append(out_t_part)
435 427
436 428 if lraw is not None:
437 429 isp.push(lraw)
438 430 raw_parts.append(lraw)
439 431
440 432 out, out_raw = isp.source_raw_reset()
441 433 out_t = '\n'.join(out_t_parts).rstrip()
442 434 raw = '\n'.join(raw_parts).rstrip()
443 435 self.assertEqual(out.rstrip(), out_t)
444 436 self.assertEqual(out_raw.rstrip(), raw)
445 437
446 438 def test_syntax_multiline_cell(self):
447 439 isp = self.isp
448 440 for example in syntax_ml.itervalues():
449 441
450 442 out_t_parts = []
451 443 for line_pairs in example:
452 444 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
453 445 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
454 446 out = isp.transform_cell(raw)
455 447 # Match ignoring trailing whitespace
456 448 self.assertEqual(out.rstrip(), out_t.rstrip())
457 449
458 450 #-----------------------------------------------------------------------------
459 451 # Main - use as a script, mostly for developer experiments
460 452 #-----------------------------------------------------------------------------
461 453
462 454 if __name__ == '__main__':
463 455 # A simple demo for interactive experimentation. This code will not get
464 456 # picked up by any test suite.
465 457 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
466 458
467 459 # configure here the syntax to use, prompt and whether to autoindent
468 460 #isp, start_prompt = InputSplitter(), '>>> '
469 461 isp, start_prompt = IPythonInputSplitter(), 'In> '
470 462
471 463 autoindent = True
472 464 #autoindent = False
473 465
474 466 try:
475 467 while True:
476 468 prompt = start_prompt
477 469 while isp.push_accepts_more():
478 470 indent = ' '*isp.indent_spaces
479 471 if autoindent:
480 472 line = indent + raw_input(prompt+indent)
481 473 else:
482 474 line = raw_input(prompt)
483 475 isp.push(line)
484 476 prompt = '... '
485 477
486 478 # Here we just return input so we can use it in a test suite, but a
487 479 # real interpreter would instead send it for execution somewhere.
488 480 #src = isp.source; raise EOFError # dbg
489 481 src, raw = isp.source_raw_reset()
490 482 print 'Input source was:\n', src
491 483 print 'Raw source was:\n', raw
492 484 except EOFError:
493 485 print 'Bye'
494 486
495 487 # Tests for cell magics support
496 488
497 489 def test_last_blank():
498 490 nt.assert_false(isp.last_blank(''))
499 491 nt.assert_false(isp.last_blank('abc'))
500 492 nt.assert_false(isp.last_blank('abc\n'))
501 493 nt.assert_false(isp.last_blank('abc\na'))
502 494
503 495 nt.assert_true(isp.last_blank('\n'))
504 496 nt.assert_true(isp.last_blank('\n '))
505 497 nt.assert_true(isp.last_blank('abc\n '))
506 498 nt.assert_true(isp.last_blank('abc\n\n'))
507 499 nt.assert_true(isp.last_blank('abc\nd\n\n'))
508 500 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
509 501 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
510 502
511 503
512 504 def test_last_two_blanks():
513 505 nt.assert_false(isp.last_two_blanks(''))
514 506 nt.assert_false(isp.last_two_blanks('abc'))
515 507 nt.assert_false(isp.last_two_blanks('abc\n'))
516 508 nt.assert_false(isp.last_two_blanks('abc\n\na'))
517 509 nt.assert_false(isp.last_two_blanks('abc\n \n'))
518 510 nt.assert_false(isp.last_two_blanks('abc\n\n'))
519 511
520 512 nt.assert_true(isp.last_two_blanks('\n\n'))
521 513 nt.assert_true(isp.last_two_blanks('\n\n '))
522 514 nt.assert_true(isp.last_two_blanks('\n \n'))
523 515 nt.assert_true(isp.last_two_blanks('abc\n\n '))
524 516 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
525 517 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
526 518 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
527 519 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
528 520 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
529 521 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
530 522
531 523
532 524 class CellMagicsCommon(object):
533 525
534 526 def test_whole_cell(self):
535 527 src = "%%cellm line\nbody\n"
536 528 sp = self.sp
537 529 sp.push(src)
538 530 out = sp.source_reset()
539 531 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
540 532 nt.assert_equal(out, py3compat.u_format(ref))
541 533
542 534 def test_cellmagic_help(self):
543 535 self.sp.push('%%cellm?')
544 536 nt.assert_false(self.sp.push_accepts_more())
545 537
546 538 def tearDown(self):
547 539 self.sp.reset()
548 540
549 541
550 542 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
551 543 sp = isp.IPythonInputSplitter(line_input_checker=False)
552 544
553 545 def test_incremental(self):
554 546 sp = self.sp
555 547 sp.push('%%cellm firstline\n')
556 548 nt.assert_true(sp.push_accepts_more()) #1
557 549 sp.push('line2\n')
558 550 nt.assert_true(sp.push_accepts_more()) #2
559 551 sp.push('\n')
560 552 # This should accept a blank line and carry on until the cell is reset
561 553 nt.assert_true(sp.push_accepts_more()) #3
562 554
563 555 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
564 556 sp = isp.IPythonInputSplitter(line_input_checker=True)
565 557
566 558 def test_incremental(self):
567 559 sp = self.sp
568 560 sp.push('%%cellm line2\n')
569 561 nt.assert_true(sp.push_accepts_more()) #1
570 562 sp.push('\n')
571 563 # In this case, a blank line should end the cell magic
572 564 nt.assert_false(sp.push_accepts_more()) #2
@@ -1,423 +1,422 b''
1 1 import tokenize
2 import unittest
3 2 import nose.tools as nt
4 3
5 4 from IPython.testing import tools as tt
6 5 from IPython.utils import py3compat
7 6 u_fmt = py3compat.u_format
8 7
9 8 from IPython.core import inputtransformer as ipt
10 9
11 10 def transform_and_reset(transformer):
12 11 transformer = transformer()
13 12 def transform(inp):
14 13 try:
15 14 return transformer.push(inp)
16 15 finally:
17 16 transformer.reset()
18 17
19 18 return transform
20 19
21 20 # Transformer tests
22 21 def transform_checker(tests, transformer, **kwargs):
23 22 """Utility to loop over test inputs"""
24 23 transformer = transformer(**kwargs)
25 24 try:
26 25 for inp, tr in tests:
27 26 if inp is None:
28 27 out = transformer.reset()
29 28 else:
30 29 out = transformer.push(inp)
31 30 nt.assert_equal(out, tr)
32 31 finally:
33 32 transformer.reset()
34 33
35 34 # Data for all the syntax tests in the form of lists of pairs of
36 35 # raw/transformed input. We store it here as a global dict so that we can use
37 36 # it both within single-function tests and also to validate the behavior of the
38 37 # larger objects
39 38
40 39 syntax = \
41 40 dict(assign_system =
42 41 [(i,py3compat.u_format(o)) for i,o in \
43 42 [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"),
44 43 (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"),
45 44 ('x=1', 'x=1'), # normal input is unmodified
46 45 (' ',' '), # blank lines are kept intact
47 46 ]],
48 47
49 48 assign_magic =
50 49 [(i,py3compat.u_format(o)) for i,o in \
51 50 [(u'a =% who', "a = get_ipython().magic({u}'who')"),
52 51 (u'b = %who', "b = get_ipython().magic({u}'who')"),
53 52 ('x=1', 'x=1'), # normal input is unmodified
54 53 (' ',' '), # blank lines are kept intact
55 54 ]],
56 55
57 56 classic_prompt =
58 57 [('>>> x=1', 'x=1'),
59 58 ('x=1', 'x=1'), # normal input is unmodified
60 59 (' ', ' '), # blank lines are kept intact
61 60 ],
62 61
63 62 ipy_prompt =
64 63 [('In [1]: x=1', 'x=1'),
65 64 ('x=1', 'x=1'), # normal input is unmodified
66 65 (' ',' '), # blank lines are kept intact
67 66 ],
68 67
69 68 # Tests for the escape transformer to leave normal code alone
70 69 escaped_noesc =
71 70 [ (' ', ' '),
72 71 ('x=1', 'x=1'),
73 72 ],
74 73
75 74 # System calls
76 75 escaped_shell =
77 76 [(i,py3compat.u_format(o)) for i,o in \
78 77 [ (u'!ls', "get_ipython().system({u}'ls')"),
79 78 # Double-escape shell, this means to capture the output of the
80 79 # subprocess and return it
81 80 (u'!!ls', "get_ipython().getoutput({u}'ls')"),
82 81 ]],
83 82
84 83 # Help/object info
85 84 escaped_help =
86 85 [(i,py3compat.u_format(o)) for i,o in \
87 86 [ (u'?', 'get_ipython().show_usage()'),
88 87 (u'?x1', "get_ipython().magic({u}'pinfo x1')"),
89 88 (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"),
90 89 (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"),
91 90 (u'?%hist1', "get_ipython().magic({u}'pinfo %hist1')"),
92 91 (u'?%%hist2', "get_ipython().magic({u}'pinfo %%hist2')"),
93 92 (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"),
94 93 ]],
95 94
96 95 end_help =
97 96 [(i,py3compat.u_format(o)) for i,o in \
98 97 [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"),
99 98 (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"),
100 99 (u'%hist1?', "get_ipython().magic({u}'pinfo %hist1')"),
101 100 (u'%hist2??', "get_ipython().magic({u}'pinfo2 %hist2')"),
102 101 (u'%%hist3?', "get_ipython().magic({u}'pinfo %%hist3')"),
103 102 (u'%%hist4??', "get_ipython().magic({u}'pinfo2 %%hist4')"),
104 103 (u'f*?', "get_ipython().magic({u}'psearch f*')"),
105 104 (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"),
106 105 (u'a = abc?', "get_ipython().set_next_input({u}'a = abc');"
107 106 "get_ipython().magic({u}'pinfo abc')"),
108 107 (u'a = abc.qe??', "get_ipython().set_next_input({u}'a = abc.qe');"
109 108 "get_ipython().magic({u}'pinfo2 abc.qe')"),
110 109 (u'a = *.items?', "get_ipython().set_next_input({u}'a = *.items');"
111 110 "get_ipython().magic({u}'psearch *.items')"),
112 111 (u'plot(a?', "get_ipython().set_next_input({u}'plot(a');"
113 112 "get_ipython().magic({u}'pinfo a')"),
114 113 (u'a*2 #comment?', 'a*2 #comment?'),
115 114 ]],
116 115
117 116 # Explicit magic calls
118 117 escaped_magic =
119 118 [(i,py3compat.u_format(o)) for i,o in \
120 119 [ (u'%cd', "get_ipython().magic({u}'cd')"),
121 120 (u'%cd /home', "get_ipython().magic({u}'cd /home')"),
122 121 # Backslashes need to be escaped.
123 122 (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"),
124 123 (u' %magic', " get_ipython().magic({u}'magic')"),
125 124 ]],
126 125
127 126 # Quoting with separate arguments
128 127 escaped_quote =
129 128 [ (',f', 'f("")'),
130 129 (',f x', 'f("x")'),
131 130 (' ,f y', ' f("y")'),
132 131 (',f a b', 'f("a", "b")'),
133 132 ],
134 133
135 134 # Quoting with single argument
136 135 escaped_quote2 =
137 136 [ (';f', 'f("")'),
138 137 (';f x', 'f("x")'),
139 138 (' ;f y', ' f("y")'),
140 139 (';f a b', 'f("a b")'),
141 140 ],
142 141
143 142 # Simply apply parens
144 143 escaped_paren =
145 144 [ ('/f', 'f()'),
146 145 ('/f x', 'f(x)'),
147 146 (' /f y', ' f(y)'),
148 147 ('/f a b', 'f(a, b)'),
149 148 ],
150 149
151 150 # Check that we transform prompts before other transforms
152 151 mixed =
153 152 [(i,py3compat.u_format(o)) for i,o in \
154 153 [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"),
155 154 (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"),
156 155 (u'In [2]: !ls', "get_ipython().system({u}'ls')"),
157 156 (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"),
158 157 (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"),
159 158 ]],
160 159 )
161 160
162 161 # multiline syntax examples. Each of these should be a list of lists, with
163 162 # each entry itself having pairs of raw/transformed input. The union (with
164 163 # '\n'.join() of the transformed inputs is what the splitter should produce
165 164 # when fed the raw lines one at a time via push.
166 165 syntax_ml = \
167 166 dict(classic_prompt =
168 167 [ [('>>> for i in range(10):','for i in range(10):'),
169 168 ('... print i',' print i'),
170 169 ('... ', ''),
171 170 ],
172 171 [('>>> a="""','a="""'),
173 172 ('... 123"""','123"""'),
174 173 ],
175 174 [('a="""','a="""'),
176 175 ('... 123','123'),
177 176 ('... 456"""','456"""'),
178 177 ],
179 178 [('a="""','a="""'),
180 179 ('123','123'),
181 180 ('... 456"""','... 456"""'),
182 181 ],
183 182 [('>>> def f(x):', 'def f(x):'),
184 183 ('...', ''),
185 184 ('... return x', ' return x'),
186 185 ],
187 186 ],
188 187
189 188 ipy_prompt =
190 189 [ [('In [24]: for i in range(10):','for i in range(10):'),
191 190 (' ....: print i',' print i'),
192 191 (' ....: ', ''),
193 192 ],
194 193 [('In [2]: a="""','a="""'),
195 194 (' ...: 123"""','123"""'),
196 195 ],
197 196 [('a="""','a="""'),
198 197 (' ...: 123','123'),
199 198 (' ...: 456"""','456"""'),
200 199 ],
201 200 [('a="""','a="""'),
202 201 ('123','123'),
203 202 (' ...: 456"""',' ...: 456"""'),
204 203 ],
205 204 ],
206 205
207 206 multiline_datastructure_prompt =
208 207 [ [('>>> a = [1,','a = [1,'),
209 208 ('... 2]','2]'),
210 209 ],
211 210 ],
212 211
213 212 multiline_datastructure =
214 213 [ [('b = ("%s"', None),
215 214 ('# comment', None),
216 215 ('%foo )', 'b = ("%s"\n# comment\n%foo )'),
217 216 ],
218 217 ],
219 218
220 219 leading_indent =
221 220 [ [(' print "hi"','print "hi"'),
222 221 ],
223 222 [(' for a in range(5):','for a in range(5):'),
224 223 (' a*2',' a*2'),
225 224 ],
226 225 [(' a="""','a="""'),
227 226 (' 123"""','123"""'),
228 227 ],
229 228 [('a="""','a="""'),
230 229 (' 123"""',' 123"""'),
231 230 ],
232 231 ],
233 232
234 233 cellmagic =
235 234 [ [(u'%%foo a', None),
236 235 (None, u_fmt("get_ipython().run_cell_magic({u}'foo', {u}'a', {u}'')")),
237 236 ],
238 237 [(u'%%bar 123', None),
239 238 (u'hello', None),
240 239 (None , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
241 240 ],
242 241 ],
243 242
244 243 escaped =
245 244 [ [('%abc def \\', None),
246 245 ('ghi', u_fmt("get_ipython().magic({u}'abc def ghi')")),
247 246 ],
248 247 [('%abc def \\', None),
249 248 ('ghi\\', None),
250 249 (None, u_fmt("get_ipython().magic({u}'abc def ghi')")),
251 250 ],
252 251 ],
253 252
254 253 assign_magic =
255 254 [ [(u'a = %bc de \\', None),
256 255 (u'fg', u_fmt("a = get_ipython().magic({u}'bc de fg')")),
257 256 ],
258 257 [(u'a = %bc de \\', None),
259 258 (u'fg\\', None),
260 259 (None, u_fmt("a = get_ipython().magic({u}'bc de fg')")),
261 260 ],
262 261 ],
263 262
264 263 assign_system =
265 264 [ [(u'a = !bc de \\', None),
266 265 (u'fg', u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
267 266 ],
268 267 [(u'a = !bc de \\', None),
269 268 (u'fg\\', None),
270 269 (None, u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
271 270 ],
272 271 ],
273 272 )
274 273
275 274
276 275 def test_assign_system():
277 276 tt.check_pairs(transform_and_reset(ipt.assign_from_system), syntax['assign_system'])
278 277
279 278 def test_assign_magic():
280 279 tt.check_pairs(transform_and_reset(ipt.assign_from_magic), syntax['assign_magic'])
281 280
282 281 def test_classic_prompt():
283 282 tt.check_pairs(transform_and_reset(ipt.classic_prompt), syntax['classic_prompt'])
284 283 for example in syntax_ml['classic_prompt']:
285 284 transform_checker(example, ipt.classic_prompt)
286 285 for example in syntax_ml['multiline_datastructure_prompt']:
287 286 transform_checker(example, ipt.classic_prompt)
288 287
289 288
290 289 def test_ipy_prompt():
291 290 tt.check_pairs(transform_and_reset(ipt.ipy_prompt), syntax['ipy_prompt'])
292 291 for example in syntax_ml['ipy_prompt']:
293 292 transform_checker(example, ipt.ipy_prompt)
294 293
295 294 def test_assemble_logical_lines():
296 295 tests = \
297 296 [ [(u"a = \\", None),
298 297 (u"123", u"a = 123"),
299 298 ],
300 299 [(u"a = \\", None), # Test resetting when within a multi-line string
301 300 (u"12 *\\", None),
302 301 (None, u"a = 12 *"),
303 302 ],
304 303 [(u"# foo\\", u"# foo\\"), # Comments can't be continued like this
305 304 ],
306 305 ]
307 306 for example in tests:
308 307 transform_checker(example, ipt.assemble_logical_lines)
309 308
310 309 def test_assemble_python_lines():
311 310 tests = \
312 311 [ [(u"a = '''", None),
313 312 (u"abc'''", u"a = '''\nabc'''"),
314 313 ],
315 314 [(u"a = '''", None), # Test resetting when within a multi-line string
316 315 (u"def", None),
317 316 (None, u"a = '''\ndef"),
318 317 ],
319 318 [(u"a = [1,", None),
320 319 (u"2]", u"a = [1,\n2]"),
321 320 ],
322 321 [(u"a = [1,", None), # Test resetting when within a multi-line string
323 322 (u"2,", None),
324 323 (None, u"a = [1,\n2,"),
325 324 ],
326 325 ] + syntax_ml['multiline_datastructure']
327 326 for example in tests:
328 327 transform_checker(example, ipt.assemble_python_lines)
329 328
330 329
331 330 def test_help_end():
332 331 tt.check_pairs(transform_and_reset(ipt.help_end), syntax['end_help'])
333 332
334 333 def test_escaped_noesc():
335 334 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_noesc'])
336 335
337 336
338 337 def test_escaped_shell():
339 338 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_shell'])
340 339
341 340
342 341 def test_escaped_help():
343 342 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_help'])
344 343
345 344
346 345 def test_escaped_magic():
347 346 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_magic'])
348 347
349 348
350 349 def test_escaped_quote():
351 350 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote'])
352 351
353 352
354 353 def test_escaped_quote2():
355 354 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote2'])
356 355
357 356
358 357 def test_escaped_paren():
359 358 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_paren'])
360 359
361 360
362 361 def test_cellmagic():
363 362 for example in syntax_ml['cellmagic']:
364 363 transform_checker(example, ipt.cellmagic)
365 364
366 365 line_example = [(u'%%bar 123', None),
367 366 (u'hello', None),
368 367 (u'' , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
369 368 ]
370 369 transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True)
371 370
372 371 def test_has_comment():
373 372 tests = [('text', False),
374 373 ('text #comment', True),
375 374 ('text #comment\n', True),
376 375 ('#comment', True),
377 376 ('#comment\n', True),
378 377 ('a = "#string"', False),
379 378 ('a = "#string" # comment', True),
380 379 ('a #comment not "string"', True),
381 380 ]
382 381 tt.check_pairs(ipt.has_comment, tests)
383 382
384 383 @ipt.TokenInputTransformer.wrap
385 384 def decistmt(tokens):
386 385 """Substitute Decimals for floats in a string of statements.
387 386
388 387 Based on an example from the tokenize module docs.
389 388 """
390 389 result = []
391 390 for toknum, tokval, _, _, _ in tokens:
392 391 if toknum == tokenize.NUMBER and '.' in tokval: # replace NUMBER tokens
393 392 for newtok in [
394 393 (tokenize.NAME, 'Decimal'),
395 394 (tokenize.OP, '('),
396 395 (tokenize.STRING, repr(tokval)),
397 396 (tokenize.OP, ')')
398 397 ]:
399 398 yield newtok
400 399 else:
401 400 yield (toknum, tokval)
402 401
403 402
404 403
405 404 def test_token_input_transformer():
406 405 tests = [(u'1.2', u_fmt(u"Decimal ({u}'1.2')")),
407 406 (u'"1.2"', u'"1.2"'),
408 407 ]
409 408 tt.check_pairs(transform_and_reset(decistmt), tests)
410 409 ml_tests = \
411 410 [ [(u"a = 1.2; b = '''x", None),
412 411 (u"y'''", u_fmt(u"a =Decimal ({u}'1.2');b ='''x\ny'''")),
413 412 ],
414 413 [(u"a = [1.2,", None),
415 414 (u"3]", u_fmt(u"a =[Decimal ({u}'1.2'),\n3 ]")),
416 415 ],
417 416 [(u"a = '''foo", None), # Test resetting when within a multi-line string
418 417 (u"bar", None),
419 418 (None, u"a = '''foo\nbar"),
420 419 ],
421 420 ]
422 421 for example in ml_tests:
423 422 transform_checker(example, decistmt)
@@ -1,260 +1,254 b''
1 1 """Tests for the key interactiveshell module, where the main ipython class is defined.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Module imports
5 5 #-----------------------------------------------------------------------------
6 6
7 # stdlib
8 import os
9 import shutil
10 import tempfile
11
12 7 # third party
13 8 import nose.tools as nt
14 9
15 10 # our own packages
16 11 from IPython.testing.globalipapp import get_ipython
17 from IPython.utils import py3compat
18 12
19 13 #-----------------------------------------------------------------------------
20 14 # Globals
21 15 #-----------------------------------------------------------------------------
22 16
23 17 # Get the public instance of IPython
24 18 ip = get_ipython()
25 19
26 20 #-----------------------------------------------------------------------------
27 21 # Test functions
28 22 #-----------------------------------------------------------------------------
29 23
30 24 def test_reset():
31 25 """reset must clear most namespaces."""
32 26
33 27 # Check that reset runs without error
34 28 ip.reset()
35 29
36 30 # Once we've reset it (to clear of any junk that might have been there from
37 31 # other tests, we can count how many variables are in the user's namespace
38 32 nvars_user_ns = len(ip.user_ns)
39 33 nvars_hidden = len(ip.user_ns_hidden)
40 34
41 35 # Now add a few variables to user_ns, and check that reset clears them
42 36 ip.user_ns['x'] = 1
43 37 ip.user_ns['y'] = 1
44 38 ip.reset()
45 39
46 40 # Finally, check that all namespaces have only as many variables as we
47 41 # expect to find in them:
48 42 nt.assert_equal(len(ip.user_ns), nvars_user_ns)
49 43 nt.assert_equal(len(ip.user_ns_hidden), nvars_hidden)
50 44
51 45
52 46 # Tests for reporting of exceptions in various modes, handling of SystemExit,
53 47 # and %tb functionality. This is really a mix of testing ultraTB and interactiveshell.
54 48
55 49 def doctest_tb_plain():
56 50 """
57 51 In [18]: xmode plain
58 52 Exception reporting mode: Plain
59 53
60 54 In [19]: run simpleerr.py
61 55 Traceback (most recent call last):
62 56 ...line 32, in <module>
63 57 bar(mode)
64 58 ...line 16, in bar
65 59 div0()
66 60 ...line 8, in div0
67 61 x/y
68 62 ZeroDivisionError: ...
69 63 """
70 64
71 65
72 66 def doctest_tb_context():
73 67 """
74 68 In [3]: xmode context
75 69 Exception reporting mode: Context
76 70
77 71 In [4]: run simpleerr.py
78 72 ---------------------------------------------------------------------------
79 73 ZeroDivisionError Traceback (most recent call last)
80 74 <BLANKLINE>
81 75 ... in <module>()
82 76 30 mode = 'div'
83 77 31
84 78 ---> 32 bar(mode)
85 79 <BLANKLINE>
86 80 ... in bar(mode)
87 81 14 "bar"
88 82 15 if mode=='div':
89 83 ---> 16 div0()
90 84 17 elif mode=='exit':
91 85 18 try:
92 86 <BLANKLINE>
93 87 ... in div0()
94 88 6 x = 1
95 89 7 y = 0
96 90 ----> 8 x/y
97 91 9
98 92 10 def sysexit(stat, mode):
99 93 <BLANKLINE>
100 94 ZeroDivisionError: ...
101 95 """
102 96
103 97
104 98 def doctest_tb_verbose():
105 99 """
106 100 In [5]: xmode verbose
107 101 Exception reporting mode: Verbose
108 102
109 103 In [6]: run simpleerr.py
110 104 ---------------------------------------------------------------------------
111 105 ZeroDivisionError Traceback (most recent call last)
112 106 <BLANKLINE>
113 107 ... in <module>()
114 108 30 mode = 'div'
115 109 31
116 110 ---> 32 bar(mode)
117 111 global bar = <function bar at ...>
118 112 global mode = 'div'
119 113 <BLANKLINE>
120 114 ... in bar(mode='div')
121 115 14 "bar"
122 116 15 if mode=='div':
123 117 ---> 16 div0()
124 118 global div0 = <function div0 at ...>
125 119 17 elif mode=='exit':
126 120 18 try:
127 121 <BLANKLINE>
128 122 ... in div0()
129 123 6 x = 1
130 124 7 y = 0
131 125 ----> 8 x/y
132 126 x = 1
133 127 y = 0
134 128 9
135 129 10 def sysexit(stat, mode):
136 130 <BLANKLINE>
137 131 ZeroDivisionError: ...
138 132 """
139 133
140 134 def doctest_tb_sysexit():
141 135 """
142 136 In [17]: %xmode plain
143 137 Exception reporting mode: Plain
144 138
145 139 In [18]: %run simpleerr.py exit
146 140 An exception has occurred, use %tb to see the full traceback.
147 141 SystemExit: (1, 'Mode = exit')
148 142
149 143 In [19]: %run simpleerr.py exit 2
150 144 An exception has occurred, use %tb to see the full traceback.
151 145 SystemExit: (2, 'Mode = exit')
152 146
153 147 In [20]: %tb
154 148 Traceback (most recent call last):
155 149 File ... in <module>
156 150 bar(mode)
157 151 File ... line 22, in bar
158 152 sysexit(stat, mode)
159 153 File ... line 11, in sysexit
160 154 raise SystemExit(stat, 'Mode = %s' % mode)
161 155 SystemExit: (2, 'Mode = exit')
162 156
163 157 In [21]: %xmode context
164 158 Exception reporting mode: Context
165 159
166 160 In [22]: %tb
167 161 ---------------------------------------------------------------------------
168 162 SystemExit Traceback (most recent call last)
169 163 <BLANKLINE>
170 164 ...<module>()
171 165 30 mode = 'div'
172 166 31
173 167 ---> 32 bar(mode)
174 168 <BLANKLINE>
175 169 ...bar(mode)
176 170 20 except:
177 171 21 stat = 1
178 172 ---> 22 sysexit(stat, mode)
179 173 23 else:
180 174 24 raise ValueError('Unknown mode')
181 175 <BLANKLINE>
182 176 ...sysexit(stat, mode)
183 177 9
184 178 10 def sysexit(stat, mode):
185 179 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
186 180 12
187 181 13 def bar(mode):
188 182 <BLANKLINE>
189 183 SystemExit: (2, 'Mode = exit')
190 184
191 185 In [23]: %xmode verbose
192 186 Exception reporting mode: Verbose
193 187
194 188 In [24]: %tb
195 189 ---------------------------------------------------------------------------
196 190 SystemExit Traceback (most recent call last)
197 191 <BLANKLINE>
198 192 ... in <module>()
199 193 30 mode = 'div'
200 194 31
201 195 ---> 32 bar(mode)
202 196 global bar = <function bar at ...>
203 197 global mode = 'exit'
204 198 <BLANKLINE>
205 199 ... in bar(mode='exit')
206 200 20 except:
207 201 21 stat = 1
208 202 ---> 22 sysexit(stat, mode)
209 203 global sysexit = <function sysexit at ...>
210 204 stat = 2
211 205 mode = 'exit'
212 206 23 else:
213 207 24 raise ValueError('Unknown mode')
214 208 <BLANKLINE>
215 209 ... in sysexit(stat=2, mode='exit')
216 210 9
217 211 10 def sysexit(stat, mode):
218 212 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
219 213 global SystemExit = undefined
220 214 stat = 2
221 215 mode = 'exit'
222 216 12
223 217 13 def bar(mode):
224 218 <BLANKLINE>
225 219 SystemExit: (2, 'Mode = exit')
226 220 """
227 221
228 222
229 223 def test_run_cell():
230 224 import textwrap
231 225 ip.run_cell('a = 10\na+=1')
232 226 ip.run_cell('assert a == 11\nassert 1')
233 227
234 228 nt.assert_equal(ip.user_ns['a'], 11)
235 229 complex = textwrap.dedent("""
236 230 if 1:
237 231 print "hello"
238 232 if 1:
239 233 print "world"
240 234
241 235 if 2:
242 236 print "foo"
243 237
244 238 if 3:
245 239 print "bar"
246 240
247 241 if 4:
248 242 print "bar"
249 243
250 244 """)
251 245 # Simply verifies that this kind of input is run
252 246 ip.run_cell(complex)
253 247
254 248
255 249 def test_db():
256 250 """Test the internal database used for variable persistence."""
257 251 ip.db['__unittest_'] = 12
258 252 nt.assert_equal(ip.db['__unittest_'], 12)
259 253 del ip.db['__unittest_']
260 254 assert '__unittest_' not in ip.db
@@ -1,868 +1,866 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions.
3 3
4 4 Needs to be run by nose (to make ipython session available).
5 5 """
6 6 from __future__ import absolute_import
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Imports
10 10 #-----------------------------------------------------------------------------
11 11
12 12 import io
13 13 import os
14 14 import sys
15 15 from StringIO import StringIO
16 16 from unittest import TestCase
17 17
18 18 try:
19 19 from importlib import invalidate_caches # Required from Python 3.3
20 20 except ImportError:
21 21 def invalidate_caches():
22 22 pass
23 23
24 24 import nose.tools as nt
25 25
26 26 from IPython.core import magic
27 27 from IPython.core.magic import (Magics, magics_class, line_magic,
28 28 cell_magic, line_cell_magic,
29 29 register_line_magic, register_cell_magic,
30 30 register_line_cell_magic)
31 31 from IPython.core.magics import execution, script, code
32 32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 33 from IPython.nbformat import current
34 34 from IPython.testing import decorators as dec
35 35 from IPython.testing import tools as tt
36 36 from IPython.utils import py3compat
37 37 from IPython.utils.io import capture_output
38 38 from IPython.utils.tempdir import TemporaryDirectory
39 39 from IPython.utils.process import find_cmd
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Test functions begin
43 43 #-----------------------------------------------------------------------------
44 44
45 45 @magic.magics_class
46 46 class DummyMagics(magic.Magics): pass
47 47
48 48 def test_rehashx():
49 49 # clear up everything
50 50 _ip = get_ipython()
51 51 _ip.alias_manager.alias_table.clear()
52 52 del _ip.db['syscmdlist']
53 53
54 54 _ip.magic('rehashx')
55 55 # Practically ALL ipython development systems will have more than 10 aliases
56 56
57 57 nt.assert_true(len(_ip.alias_manager.alias_table) > 10)
58 58 for key, val in _ip.alias_manager.alias_table.iteritems():
59 59 # we must strip dots from alias names
60 60 nt.assert_not_in('.', key)
61 61
62 62 # rehashx must fill up syscmdlist
63 63 scoms = _ip.db['syscmdlist']
64 64 nt.assert_true(len(scoms) > 10)
65 65
66 66
67 67 def test_magic_parse_options():
68 68 """Test that we don't mangle paths when parsing magic options."""
69 69 ip = get_ipython()
70 70 path = 'c:\\x'
71 71 m = DummyMagics(ip)
72 72 opts = m.parse_options('-f %s' % path,'f:')[0]
73 73 # argv splitting is os-dependent
74 74 if os.name == 'posix':
75 75 expected = 'c:x'
76 76 else:
77 77 expected = path
78 78 nt.assert_equal(opts['f'], expected)
79 79
80 80 def test_magic_parse_long_options():
81 81 """Magic.parse_options can handle --foo=bar long options"""
82 82 ip = get_ipython()
83 83 m = DummyMagics(ip)
84 84 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
85 85 nt.assert_in('foo', opts)
86 86 nt.assert_in('bar', opts)
87 87 nt.assert_equal(opts['bar'], "bubble")
88 88
89 89
90 90 @dec.skip_without('sqlite3')
91 91 def doctest_hist_f():
92 92 """Test %hist -f with temporary filename.
93 93
94 94 In [9]: import tempfile
95 95
96 96 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
97 97
98 98 In [11]: %hist -nl -f $tfile 3
99 99
100 100 In [13]: import os; os.unlink(tfile)
101 101 """
102 102
103 103
104 104 @dec.skip_without('sqlite3')
105 105 def doctest_hist_r():
106 106 """Test %hist -r
107 107
108 108 XXX - This test is not recording the output correctly. For some reason, in
109 109 testing mode the raw history isn't getting populated. No idea why.
110 110 Disabling the output checking for now, though at least we do run it.
111 111
112 112 In [1]: 'hist' in _ip.lsmagic()
113 113 Out[1]: True
114 114
115 115 In [2]: x=1
116 116
117 117 In [3]: %hist -rl 2
118 118 x=1 # random
119 119 %hist -r 2
120 120 """
121 121
122 122
123 123 @dec.skip_without('sqlite3')
124 124 def doctest_hist_op():
125 125 """Test %hist -op
126 126
127 127 In [1]: class b(float):
128 128 ...: pass
129 129 ...:
130 130
131 131 In [2]: class s(object):
132 132 ...: def __str__(self):
133 133 ...: return 's'
134 134 ...:
135 135
136 136 In [3]:
137 137
138 138 In [4]: class r(b):
139 139 ...: def __repr__(self):
140 140 ...: return 'r'
141 141 ...:
142 142
143 143 In [5]: class sr(s,r): pass
144 144 ...:
145 145
146 146 In [6]:
147 147
148 148 In [7]: bb=b()
149 149
150 150 In [8]: ss=s()
151 151
152 152 In [9]: rr=r()
153 153
154 154 In [10]: ssrr=sr()
155 155
156 156 In [11]: 4.5
157 157 Out[11]: 4.5
158 158
159 159 In [12]: str(ss)
160 160 Out[12]: 's'
161 161
162 162 In [13]:
163 163
164 164 In [14]: %hist -op
165 165 >>> class b:
166 166 ... pass
167 167 ...
168 168 >>> class s(b):
169 169 ... def __str__(self):
170 170 ... return 's'
171 171 ...
172 172 >>>
173 173 >>> class r(b):
174 174 ... def __repr__(self):
175 175 ... return 'r'
176 176 ...
177 177 >>> class sr(s,r): pass
178 178 >>>
179 179 >>> bb=b()
180 180 >>> ss=s()
181 181 >>> rr=r()
182 182 >>> ssrr=sr()
183 183 >>> 4.5
184 184 4.5
185 185 >>> str(ss)
186 186 's'
187 187 >>>
188 188 """
189 189
190 190
191 191 @dec.skip_without('sqlite3')
192 192 def test_macro():
193 193 ip = get_ipython()
194 194 ip.history_manager.reset() # Clear any existing history.
195 195 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
196 196 for i, cmd in enumerate(cmds, start=1):
197 197 ip.history_manager.store_inputs(i, cmd)
198 198 ip.magic("macro test 1-3")
199 199 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
200 200
201 201 # List macros
202 202 nt.assert_in("test", ip.magic("macro"))
203 203
204 204
205 205 @dec.skip_without('sqlite3')
206 206 def test_macro_run():
207 207 """Test that we can run a multi-line macro successfully."""
208 208 ip = get_ipython()
209 209 ip.history_manager.reset()
210 210 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
211 211 "%macro test 2-3"]
212 212 for cmd in cmds:
213 213 ip.run_cell(cmd, store_history=True)
214 214 nt.assert_equal(ip.user_ns["test"].value,
215 215 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
216 216 with tt.AssertPrints("12"):
217 217 ip.run_cell("test")
218 218 with tt.AssertPrints("13"):
219 219 ip.run_cell("test")
220 220
221 221
222 222 def test_magic_magic():
223 223 """Test %magic"""
224 224 ip = get_ipython()
225 225 with capture_output() as captured:
226 226 ip.magic("magic")
227 227
228 228 stdout = captured.stdout
229 229 nt.assert_in('%magic', stdout)
230 230 nt.assert_in('IPython', stdout)
231 231 nt.assert_in('Available', stdout)
232 232
233 233
234 234 @dec.skipif_not_numpy
235 235 def test_numpy_reset_array_undec():
236 236 "Test '%reset array' functionality"
237 237 _ip.ex('import numpy as np')
238 238 _ip.ex('a = np.empty(2)')
239 239 nt.assert_in('a', _ip.user_ns)
240 240 _ip.magic('reset -f array')
241 241 nt.assert_not_in('a', _ip.user_ns)
242 242
243 243 def test_reset_out():
244 244 "Test '%reset out' magic"
245 245 _ip.run_cell("parrot = 'dead'", store_history=True)
246 246 # test '%reset -f out', make an Out prompt
247 247 _ip.run_cell("parrot", store_history=True)
248 248 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
249 249 _ip.magic('reset -f out')
250 250 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
251 251 nt.assert_equal(len(_ip.user_ns['Out']), 0)
252 252
253 253 def test_reset_in():
254 254 "Test '%reset in' magic"
255 255 # test '%reset -f in'
256 256 _ip.run_cell("parrot", store_history=True)
257 257 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
258 258 _ip.magic('%reset -f in')
259 259 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
260 260 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
261 261
262 262 def test_reset_dhist():
263 263 "Test '%reset dhist' magic"
264 264 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
265 265 _ip.magic('cd ' + os.path.dirname(nt.__file__))
266 266 _ip.magic('cd -')
267 267 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
268 268 _ip.magic('reset -f dhist')
269 269 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
270 270 _ip.run_cell("_dh = [d for d in tmp]") #restore
271 271
272 272 def test_reset_in_length():
273 273 "Test that '%reset in' preserves In[] length"
274 274 _ip.run_cell("print 'foo'")
275 275 _ip.run_cell("reset -f in")
276 276 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
277 277
278 278 def test_tb_syntaxerror():
279 279 """test %tb after a SyntaxError"""
280 280 ip = get_ipython()
281 281 ip.run_cell("for")
282 282
283 283 # trap and validate stdout
284 284 save_stdout = sys.stdout
285 285 try:
286 286 sys.stdout = StringIO()
287 287 ip.run_cell("%tb")
288 288 out = sys.stdout.getvalue()
289 289 finally:
290 290 sys.stdout = save_stdout
291 291 # trim output, and only check the last line
292 292 last_line = out.rstrip().splitlines()[-1].strip()
293 293 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
294 294
295 295
296 296 def test_time():
297 297 ip = get_ipython()
298 298
299 299 with tt.AssertPrints("Wall time: "):
300 300 ip.run_cell("%time None")
301 301
302 302 ip.run_cell("def f(kmjy):\n"
303 303 " %time print (2*kmjy)")
304 304
305 305 with tt.AssertPrints("Wall time: "):
306 306 with tt.AssertPrints("hihi", suppress=False):
307 307 ip.run_cell("f('hi')")
308 308
309 309
310 310 @dec.skip_win32
311 311 def test_time2():
312 312 ip = get_ipython()
313 313
314 314 with tt.AssertPrints("CPU times: user "):
315 315 ip.run_cell("%time None")
316 316
317 317 def test_time3():
318 318 """Erroneous magic function calls, issue gh-3334"""
319 319 ip = get_ipython()
320 320 ip.user_ns.pop('run', None)
321 321
322 322 with tt.AssertNotPrints("not found", channel='stderr'):
323 323 ip.run_cell("%%time\n"
324 324 "run = 0\n"
325 325 "run += 1")
326 326
327 327 def test_doctest_mode():
328 328 "Toggle doctest_mode twice, it should be a no-op and run without error"
329 329 _ip.magic('doctest_mode')
330 330 _ip.magic('doctest_mode')
331 331
332 332
333 333 def test_parse_options():
334 334 """Tests for basic options parsing in magics."""
335 335 # These are only the most minimal of tests, more should be added later. At
336 336 # the very least we check that basic text/unicode calls work OK.
337 337 m = DummyMagics(_ip)
338 338 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
339 339 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
340 340
341 341
342 342 def test_dirops():
343 343 """Test various directory handling operations."""
344 344 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
345 345 curpath = os.getcwdu
346 346 startdir = os.getcwdu()
347 347 ipdir = os.path.realpath(_ip.ipython_dir)
348 348 try:
349 349 _ip.magic('cd "%s"' % ipdir)
350 350 nt.assert_equal(curpath(), ipdir)
351 351 _ip.magic('cd -')
352 352 nt.assert_equal(curpath(), startdir)
353 353 _ip.magic('pushd "%s"' % ipdir)
354 354 nt.assert_equal(curpath(), ipdir)
355 355 _ip.magic('popd')
356 356 nt.assert_equal(curpath(), startdir)
357 357 finally:
358 358 os.chdir(startdir)
359 359
360 360
361 361 def test_xmode():
362 362 # Calling xmode three times should be a no-op
363 363 xmode = _ip.InteractiveTB.mode
364 364 for i in range(3):
365 365 _ip.magic("xmode")
366 366 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
367 367
368 368 def test_reset_hard():
369 369 monitor = []
370 370 class A(object):
371 371 def __del__(self):
372 372 monitor.append(1)
373 373 def __repr__(self):
374 374 return "<A instance>"
375 375
376 376 _ip.user_ns["a"] = A()
377 377 _ip.run_cell("a")
378 378
379 379 nt.assert_equal(monitor, [])
380 380 _ip.magic("reset -f")
381 381 nt.assert_equal(monitor, [1])
382 382
383 383 class TestXdel(tt.TempFileMixin):
384 384 def test_xdel(self):
385 385 """Test that references from %run are cleared by xdel."""
386 386 src = ("class A(object):\n"
387 387 " monitor = []\n"
388 388 " def __del__(self):\n"
389 389 " self.monitor.append(1)\n"
390 390 "a = A()\n")
391 391 self.mktmp(src)
392 392 # %run creates some hidden references...
393 393 _ip.magic("run %s" % self.fname)
394 394 # ... as does the displayhook.
395 395 _ip.run_cell("a")
396 396
397 397 monitor = _ip.user_ns["A"].monitor
398 398 nt.assert_equal(monitor, [])
399 399
400 400 _ip.magic("xdel a")
401 401
402 402 # Check that a's __del__ method has been called.
403 403 nt.assert_equal(monitor, [1])
404 404
405 405 def doctest_who():
406 406 """doctest for %who
407 407
408 408 In [1]: %reset -f
409 409
410 410 In [2]: alpha = 123
411 411
412 412 In [3]: beta = 'beta'
413 413
414 414 In [4]: %who int
415 415 alpha
416 416
417 417 In [5]: %who str
418 418 beta
419 419
420 420 In [6]: %whos
421 421 Variable Type Data/Info
422 422 ----------------------------
423 423 alpha int 123
424 424 beta str beta
425 425
426 426 In [7]: %who_ls
427 427 Out[7]: ['alpha', 'beta']
428 428 """
429 429
430 430 def test_whos():
431 431 """Check that whos is protected against objects where repr() fails."""
432 432 class A(object):
433 433 def __repr__(self):
434 434 raise Exception()
435 435 _ip.user_ns['a'] = A()
436 436 _ip.magic("whos")
437 437
438 438 @py3compat.u_format
439 439 def doctest_precision():
440 440 """doctest for %precision
441 441
442 442 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
443 443
444 444 In [2]: %precision 5
445 445 Out[2]: {u}'%.5f'
446 446
447 447 In [3]: f.float_format
448 448 Out[3]: {u}'%.5f'
449 449
450 450 In [4]: %precision %e
451 451 Out[4]: {u}'%e'
452 452
453 453 In [5]: f(3.1415927)
454 454 Out[5]: {u}'3.141593e+00'
455 455 """
456 456
457 457 def test_psearch():
458 458 with tt.AssertPrints("dict.fromkeys"):
459 459 _ip.run_cell("dict.fr*?")
460 460
461 461 def test_timeit_shlex():
462 462 """test shlex issues with timeit (#1109)"""
463 463 _ip.ex("def f(*a,**kw): pass")
464 464 _ip.magic('timeit -n1 "this is a bug".count(" ")')
465 465 _ip.magic('timeit -r1 -n1 f(" ", 1)')
466 466 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
467 467 _ip.magic('timeit -r1 -n1 ("a " + "b")')
468 468 _ip.magic('timeit -r1 -n1 f("a " + "b")')
469 469 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
470 470
471 471
472 472 def test_timeit_arguments():
473 473 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
474 474 _ip.magic("timeit ('#')")
475 475
476 476
477 477 def test_timeit_special_syntax():
478 478 "Test %%timeit with IPython special syntax"
479 from IPython.core.magic import register_line_magic
480
481 479 @register_line_magic
482 480 def lmagic(line):
483 481 ip = get_ipython()
484 482 ip.user_ns['lmagic_out'] = line
485 483
486 484 # line mode test
487 485 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
488 486 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
489 487 # cell mode test
490 488 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
491 489 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
492 490
493 491
494 492 @dec.skipif(execution.profile is None)
495 493 def test_prun_quotes():
496 494 "Test that prun does not clobber string escapes (GH #1302)"
497 495 _ip.magic(r"prun -q x = '\t'")
498 496 nt.assert_equal(_ip.user_ns['x'], '\t')
499 497
500 498 def test_extension():
501 499 tmpdir = TemporaryDirectory()
502 500 orig_ipython_dir = _ip.ipython_dir
503 501 try:
504 502 _ip.ipython_dir = tmpdir.name
505 503 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
506 504 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
507 505 _ip.magic("install_ext %s" % url)
508 506 _ip.user_ns.pop('arq', None)
509 507 invalidate_caches() # Clear import caches
510 508 _ip.magic("load_ext daft_extension")
511 509 nt.assert_equal(_ip.user_ns['arq'], 185)
512 510 _ip.magic("unload_ext daft_extension")
513 511 assert 'arq' not in _ip.user_ns
514 512 finally:
515 513 _ip.ipython_dir = orig_ipython_dir
516 514 tmpdir.cleanup()
517 515
518 516 def test_notebook_export_json():
519 517 with TemporaryDirectory() as td:
520 518 outfile = os.path.join(td, "nb.ipynb")
521 519 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
522 520 _ip.magic("notebook -e %s" % outfile)
523 521
524 522 def test_notebook_export_py():
525 523 with TemporaryDirectory() as td:
526 524 outfile = os.path.join(td, "nb.py")
527 525 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
528 526 _ip.magic("notebook -e %s" % outfile)
529 527
530 528 def test_notebook_reformat_py():
531 529 with TemporaryDirectory() as td:
532 530 infile = os.path.join(td, "nb.ipynb")
533 531 with io.open(infile, 'w', encoding='utf-8') as f:
534 532 current.write(nb0, f, 'json')
535 533
536 534 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
537 535 _ip.magic("notebook -f py %s" % infile)
538 536
539 537 def test_notebook_reformat_json():
540 538 with TemporaryDirectory() as td:
541 539 infile = os.path.join(td, "nb.py")
542 540 with io.open(infile, 'w', encoding='utf-8') as f:
543 541 current.write(nb0, f, 'py')
544 542
545 543 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
546 544 _ip.magic("notebook -f ipynb %s" % infile)
547 545 _ip.magic("notebook -f json %s" % infile)
548 546
549 547 def test_env():
550 548 env = _ip.magic("env")
551 549 assert isinstance(env, dict), type(env)
552 550
553 551
554 552 class CellMagicTestCase(TestCase):
555 553
556 554 def check_ident(self, magic):
557 555 # Manually called, we get the result
558 556 out = _ip.run_cell_magic(magic, 'a', 'b')
559 557 nt.assert_equal(out, ('a','b'))
560 558 # Via run_cell, it goes into the user's namespace via displayhook
561 559 _ip.run_cell('%%' + magic +' c\nd')
562 560 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
563 561
564 562 def test_cell_magic_func_deco(self):
565 563 "Cell magic using simple decorator"
566 564 @register_cell_magic
567 565 def cellm(line, cell):
568 566 return line, cell
569 567
570 568 self.check_ident('cellm')
571 569
572 570 def test_cell_magic_reg(self):
573 571 "Cell magic manually registered"
574 572 def cellm(line, cell):
575 573 return line, cell
576 574
577 575 _ip.register_magic_function(cellm, 'cell', 'cellm2')
578 576 self.check_ident('cellm2')
579 577
580 578 def test_cell_magic_class(self):
581 579 "Cell magics declared via a class"
582 580 @magics_class
583 581 class MyMagics(Magics):
584 582
585 583 @cell_magic
586 584 def cellm3(self, line, cell):
587 585 return line, cell
588 586
589 587 _ip.register_magics(MyMagics)
590 588 self.check_ident('cellm3')
591 589
592 590 def test_cell_magic_class2(self):
593 591 "Cell magics declared via a class, #2"
594 592 @magics_class
595 593 class MyMagics2(Magics):
596 594
597 595 @cell_magic('cellm4')
598 596 def cellm33(self, line, cell):
599 597 return line, cell
600 598
601 599 _ip.register_magics(MyMagics2)
602 600 self.check_ident('cellm4')
603 601 # Check that nothing is registered as 'cellm33'
604 602 c33 = _ip.find_cell_magic('cellm33')
605 603 nt.assert_equal(c33, None)
606 604
607 605 def test_file():
608 606 """Basic %%file"""
609 607 ip = get_ipython()
610 608 with TemporaryDirectory() as td:
611 609 fname = os.path.join(td, 'file1')
612 610 ip.run_cell_magic("file", fname, u'\n'.join([
613 611 'line1',
614 612 'line2',
615 613 ]))
616 614 with open(fname) as f:
617 615 s = f.read()
618 616 nt.assert_in('line1\n', s)
619 617 nt.assert_in('line2', s)
620 618
621 619 def test_file_var_expand():
622 620 """%%file $filename"""
623 621 ip = get_ipython()
624 622 with TemporaryDirectory() as td:
625 623 fname = os.path.join(td, 'file1')
626 624 ip.user_ns['filename'] = fname
627 625 ip.run_cell_magic("file", '$filename', u'\n'.join([
628 626 'line1',
629 627 'line2',
630 628 ]))
631 629 with open(fname) as f:
632 630 s = f.read()
633 631 nt.assert_in('line1\n', s)
634 632 nt.assert_in('line2', s)
635 633
636 634 def test_file_unicode():
637 635 """%%file with unicode cell"""
638 636 ip = get_ipython()
639 637 with TemporaryDirectory() as td:
640 638 fname = os.path.join(td, 'file1')
641 639 ip.run_cell_magic("file", fname, u'\n'.join([
642 640 u'liné1',
643 641 u'liné2',
644 642 ]))
645 643 with io.open(fname, encoding='utf-8') as f:
646 644 s = f.read()
647 645 nt.assert_in(u'liné1\n', s)
648 646 nt.assert_in(u'liné2', s)
649 647
650 648 def test_file_amend():
651 649 """%%file -a amends files"""
652 650 ip = get_ipython()
653 651 with TemporaryDirectory() as td:
654 652 fname = os.path.join(td, 'file2')
655 653 ip.run_cell_magic("file", fname, u'\n'.join([
656 654 'line1',
657 655 'line2',
658 656 ]))
659 657 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
660 658 'line3',
661 659 'line4',
662 660 ]))
663 661 with open(fname) as f:
664 662 s = f.read()
665 663 nt.assert_in('line1\n', s)
666 664 nt.assert_in('line3\n', s)
667 665
668 666
669 667 def test_script_config():
670 668 ip = get_ipython()
671 669 ip.config.ScriptMagics.script_magics = ['whoda']
672 670 sm = script.ScriptMagics(shell=ip)
673 671 nt.assert_in('whoda', sm.magics['cell'])
674 672
675 673 @dec.skip_win32
676 674 def test_script_out():
677 675 ip = get_ipython()
678 676 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
679 677 nt.assert_equal(ip.user_ns['output'], 'hi\n')
680 678
681 679 @dec.skip_win32
682 680 def test_script_err():
683 681 ip = get_ipython()
684 682 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
685 683 nt.assert_equal(ip.user_ns['error'], 'hello\n')
686 684
687 685 @dec.skip_win32
688 686 def test_script_out_err():
689 687 ip = get_ipython()
690 688 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
691 689 nt.assert_equal(ip.user_ns['output'], 'hi\n')
692 690 nt.assert_equal(ip.user_ns['error'], 'hello\n')
693 691
694 692 @dec.skip_win32
695 693 def test_script_bg_out():
696 694 ip = get_ipython()
697 695 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
698 696 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
699 697
700 698 @dec.skip_win32
701 699 def test_script_bg_err():
702 700 ip = get_ipython()
703 701 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
704 702 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
705 703
706 704 @dec.skip_win32
707 705 def test_script_bg_out_err():
708 706 ip = get_ipython()
709 707 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
710 708 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
711 709 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
712 710
713 711 def test_script_defaults():
714 712 ip = get_ipython()
715 713 for cmd in ['sh', 'bash', 'perl', 'ruby']:
716 714 try:
717 715 find_cmd(cmd)
718 716 except Exception:
719 717 pass
720 718 else:
721 719 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
722 720
723 721
724 722 @magics_class
725 723 class FooFoo(Magics):
726 724 """class with both %foo and %%foo magics"""
727 725 @line_magic('foo')
728 726 def line_foo(self, line):
729 727 "I am line foo"
730 728 pass
731 729
732 730 @cell_magic("foo")
733 731 def cell_foo(self, line, cell):
734 732 "I am cell foo, not line foo"
735 733 pass
736 734
737 735 def test_line_cell_info():
738 736 """%%foo and %foo magics are distinguishable to inspect"""
739 737 ip = get_ipython()
740 738 ip.magics_manager.register(FooFoo)
741 739 oinfo = ip.object_inspect('foo')
742 740 nt.assert_true(oinfo['found'])
743 741 nt.assert_true(oinfo['ismagic'])
744 742
745 743 oinfo = ip.object_inspect('%%foo')
746 744 nt.assert_true(oinfo['found'])
747 745 nt.assert_true(oinfo['ismagic'])
748 746 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
749 747
750 748 oinfo = ip.object_inspect('%foo')
751 749 nt.assert_true(oinfo['found'])
752 750 nt.assert_true(oinfo['ismagic'])
753 751 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
754 752
755 753 def test_multiple_magics():
756 754 ip = get_ipython()
757 755 foo1 = FooFoo(ip)
758 756 foo2 = FooFoo(ip)
759 757 mm = ip.magics_manager
760 758 mm.register(foo1)
761 759 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
762 760 mm.register(foo2)
763 761 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
764 762
765 763 def test_alias_magic():
766 764 """Test %alias_magic."""
767 765 ip = get_ipython()
768 766 mm = ip.magics_manager
769 767
770 768 # Basic operation: both cell and line magics are created, if possible.
771 769 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
772 770 nt.assert_in('timeit_alias', mm.magics['line'])
773 771 nt.assert_in('timeit_alias', mm.magics['cell'])
774 772
775 773 # --cell is specified, line magic not created.
776 774 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
777 775 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
778 776 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
779 777
780 778 # Test that line alias is created successfully.
781 779 ip.run_line_magic('alias_magic', '--line env_alias env')
782 780 nt.assert_equal(ip.run_line_magic('env', ''),
783 781 ip.run_line_magic('env_alias', ''))
784 782
785 783 def test_save():
786 784 """Test %save."""
787 785 ip = get_ipython()
788 786 ip.history_manager.reset() # Clear any existing history.
789 787 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
790 788 for i, cmd in enumerate(cmds, start=1):
791 789 ip.history_manager.store_inputs(i, cmd)
792 790 with TemporaryDirectory() as tmpdir:
793 791 file = os.path.join(tmpdir, "testsave.py")
794 792 ip.run_line_magic("save", "%s 1-10" % file)
795 793 with open(file) as f:
796 794 content = f.read()
797 795 nt.assert_equal(content.count(cmds[0]), 1)
798 796 nt.assert_in('coding: utf-8', content)
799 797 ip.run_line_magic("save", "-a %s 1-10" % file)
800 798 with open(file) as f:
801 799 content = f.read()
802 800 nt.assert_equal(content.count(cmds[0]), 2)
803 801 nt.assert_in('coding: utf-8', content)
804 802
805 803
806 804 def test_store():
807 805 """Test %store."""
808 806 ip = get_ipython()
809 807 ip.run_line_magic('load_ext', 'storemagic')
810 808
811 809 # make sure the storage is empty
812 810 ip.run_line_magic('store', '-z')
813 811 ip.user_ns['var'] = 42
814 812 ip.run_line_magic('store', 'var')
815 813 ip.user_ns['var'] = 39
816 814 ip.run_line_magic('store', '-r')
817 815 nt.assert_equal(ip.user_ns['var'], 42)
818 816
819 817 ip.run_line_magic('store', '-d var')
820 818 ip.user_ns['var'] = 39
821 819 ip.run_line_magic('store' , '-r')
822 820 nt.assert_equal(ip.user_ns['var'], 39)
823 821
824 822
825 823 def _run_edit_test(arg_s, exp_filename=None,
826 824 exp_lineno=-1,
827 825 exp_contents=None,
828 826 exp_is_temp=None):
829 827 ip = get_ipython()
830 828 M = code.CodeMagics(ip)
831 829 last_call = ['','']
832 830 opts,args = M.parse_options(arg_s,'prxn:')
833 831 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
834 832
835 833 if exp_filename is not None:
836 834 nt.assert_equal(exp_filename, filename)
837 835 if exp_contents is not None:
838 836 with io.open(filename, 'r') as f:
839 837 contents = f.read()
840 838 nt.assert_equal(exp_contents, contents)
841 839 if exp_lineno != -1:
842 840 nt.assert_equal(exp_lineno, lineno)
843 841 if exp_is_temp is not None:
844 842 nt.assert_equal(exp_is_temp, is_temp)
845 843
846 844
847 845 def test_edit_interactive():
848 846 """%edit on interactively defined objects"""
849 847 ip = get_ipython()
850 848 n = ip.execution_count
851 849 ip.run_cell(u"def foo(): return 1", store_history=True)
852 850
853 851 try:
854 852 _run_edit_test("foo")
855 853 except code.InteractivelyDefined as e:
856 854 nt.assert_equal(e.index, n)
857 855 else:
858 856 raise AssertionError("Should have raised InteractivelyDefined")
859 857
860 858
861 859 def test_edit_cell():
862 860 """%edit [cell id]"""
863 861 ip = get_ipython()
864 862
865 863 ip.run_cell(u"def foo(): return 1", store_history=True)
866 864
867 865 # test
868 866 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
@@ -1,305 +1,305 b''
1 1 """Tests for the object inspection functionality.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2010-2011 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14 from __future__ import print_function
15 15
16 16 # Stdlib imports
17 17 import os
18 18 import re
19 19
20 20 # Third-party imports
21 21 import nose.tools as nt
22 22
23 23 # Our own imports
24 24 from .. import oinspect
25 25 from IPython.core.magic import (Magics, magics_class, line_magic,
26 26 cell_magic, line_cell_magic,
27 27 register_line_magic, register_cell_magic,
28 28 register_line_cell_magic)
29 29 from IPython.external.decorator import decorator
30 30 from IPython.utils import py3compat
31 31
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Globals and constants
35 35 #-----------------------------------------------------------------------------
36 36
37 37 inspector = oinspect.Inspector()
38 38 ip = get_ipython()
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Local utilities
42 42 #-----------------------------------------------------------------------------
43 43
44 44 # WARNING: since this test checks the line number where a function is
45 45 # defined, if any code is inserted above, the following line will need to be
46 46 # updated. Do NOT insert any whitespace between the next line and the function
47 47 # definition below.
48 48 THIS_LINE_NUMBER = 48 # Put here the actual number of this line
49 49 def test_find_source_lines():
50 50 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
51 51 THIS_LINE_NUMBER+1)
52 52
53 53
54 54 # A couple of utilities to ensure these tests work the same from a source or a
55 55 # binary install
56 56 def pyfile(fname):
57 57 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
58 58
59 59
60 60 def match_pyfiles(f1, f2):
61 61 nt.assert_equal(pyfile(f1), pyfile(f2))
62 62
63 63
64 64 def test_find_file():
65 65 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
66 66
67 67
68 68 def test_find_file_decorated1():
69 69
70 70 @decorator
71 71 def noop1(f):
72 72 def wrapper():
73 73 return f(*a, **kw)
74 74 return wrapper
75 75
76 76 @noop1
77 77 def f(x):
78 78 "My docstring"
79 79
80 80 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
81 81 nt.assert_equal(f.__doc__, "My docstring")
82 82
83 83
84 84 def test_find_file_decorated2():
85 85
86 86 @decorator
87 87 def noop2(f, *a, **kw):
88 88 return f(*a, **kw)
89 89
90 90 @noop2
91 91 def f(x):
92 92 "My docstring 2"
93 93
94 94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
95 95 nt.assert_equal(f.__doc__, "My docstring 2")
96 96
97 97
98 98 def test_find_file_magic():
99 99 run = ip.find_line_magic('run')
100 100 nt.assert_not_equal(oinspect.find_file(run), None)
101 101
102 102
103 103 # A few generic objects we can then inspect in the tests below
104 104
105 105 class Call(object):
106 106 """This is the class docstring."""
107 107
108 108 def __init__(self, x, y=1):
109 109 """This is the constructor docstring."""
110 110
111 111 def __call__(self, *a, **kw):
112 112 """This is the call docstring."""
113 113
114 114 def method(self, x, z=2):
115 115 """Some method's docstring"""
116 116
117 117
118 118 class OldStyle:
119 119 """An old-style class for testing."""
120 120 pass
121 121
122 122
123 123 def f(x, y=2, *a, **kw):
124 124 """A simple function."""
125 125
126 126
127 127 def g(y, z=3, *a, **kw):
128 128 pass # no docstring
129 129
130 130
131 131 @register_line_magic
132 132 def lmagic(line):
133 133 "A line magic"
134 134
135 135
136 136 @register_cell_magic
137 137 def cmagic(line, cell):
138 138 "A cell magic"
139 139
140 140
141 141 @register_line_cell_magic
142 142 def lcmagic(line, cell=None):
143 143 "A line/cell magic"
144 144
145 145
146 146 @magics_class
147 147 class SimpleMagics(Magics):
148 148 @line_magic
149 149 def Clmagic(self, cline):
150 150 "A class-based line magic"
151 151
152 152 @cell_magic
153 153 def Ccmagic(self, cline, ccell):
154 154 "A class-based cell magic"
155 155
156 156 @line_cell_magic
157 157 def Clcmagic(self, cline, ccell=None):
158 158 "A class-based line/cell magic"
159 159
160 160
161 161 class Awkward(object):
162 162 def __getattr__(self, name):
163 163 raise Exception(name)
164 164
165 165
166 166 def check_calltip(obj, name, call, docstring):
167 167 """Generic check pattern all calltip tests will use"""
168 168 info = inspector.info(obj, name)
169 169 call_line, ds = oinspect.call_tip(info)
170 170 nt.assert_equal(call_line, call)
171 171 nt.assert_equal(ds, docstring)
172 172
173 173 #-----------------------------------------------------------------------------
174 174 # Tests
175 175 #-----------------------------------------------------------------------------
176 176
177 177 def test_calltip_class():
178 178 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
179 179
180 180
181 181 def test_calltip_instance():
182 182 c = Call(1)
183 183 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
184 184
185 185
186 186 def test_calltip_method():
187 187 c = Call(1)
188 188 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
189 189
190 190
191 191 def test_calltip_function():
192 192 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
193 193
194 194
195 195 def test_calltip_function2():
196 196 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
197 197
198 198
199 199 def test_calltip_builtin():
200 200 check_calltip(sum, 'sum', None, sum.__doc__)
201 201
202 202
203 203 def test_calltip_line_magic():
204 204 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
205 205
206 206
207 207 def test_calltip_cell_magic():
208 208 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
209 209
210 210
211 def test_calltip_line_magic():
211 def test_calltip_line_cell_magic():
212 212 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
213 213 "A line/cell magic")
214 214
215 215
216 216 def test_class_magics():
217 217 cm = SimpleMagics(ip)
218 218 ip.register_magics(cm)
219 219 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
220 220 "A class-based line magic")
221 221 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
222 222 "A class-based cell magic")
223 223 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
224 224 "A class-based line/cell magic")
225 225
226 226
227 227 def test_info():
228 228 "Check that Inspector.info fills out various fields as expected."
229 229 i = inspector.info(Call, oname='Call')
230 230 nt.assert_equal(i['type_name'], 'type')
231 231 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
232 232 nt.assert_equal(i['base_class'], expted_class)
233 233 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
234 234 fname = __file__
235 235 if fname.endswith(".pyc"):
236 236 fname = fname[:-1]
237 237 # case-insensitive comparison needed on some filesystems
238 238 # e.g. Windows:
239 239 nt.assert_equal(i['file'].lower(), fname.lower())
240 240 nt.assert_equal(i['definition'], 'Call(self, *a, **kw)\n')
241 241 nt.assert_equal(i['docstring'], Call.__doc__)
242 242 nt.assert_equal(i['source'], None)
243 243 nt.assert_true(i['isclass'])
244 244 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
245 245 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
246 246
247 247 i = inspector.info(Call, detail_level=1)
248 248 nt.assert_not_equal(i['source'], None)
249 249 nt.assert_equal(i['docstring'], None)
250 250
251 251 c = Call(1)
252 252 c.__doc__ = "Modified instance docstring"
253 253 i = inspector.info(c)
254 254 nt.assert_equal(i['type_name'], 'Call')
255 255 nt.assert_equal(i['docstring'], "Modified instance docstring")
256 256 nt.assert_equal(i['class_docstring'], Call.__doc__)
257 257 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
258 258 nt.assert_equal(i['call_docstring'], c.__call__.__doc__)
259 259
260 260 # Test old-style classes, which for example may not have an __init__ method.
261 261 if not py3compat.PY3:
262 262 i = inspector.info(OldStyle)
263 263 nt.assert_equal(i['type_name'], 'classobj')
264 264
265 265 i = inspector.info(OldStyle())
266 266 nt.assert_equal(i['type_name'], 'instance')
267 267 nt.assert_equal(i['docstring'], OldStyle.__doc__)
268 268
269 269 def test_info_awkward():
270 270 # Just test that this doesn't throw an error.
271 271 i = inspector.info(Awkward())
272 272
273 273 def test_getdoc():
274 274 class A(object):
275 275 """standard docstring"""
276 276 pass
277 277
278 278 class B(object):
279 279 """standard docstring"""
280 280 def getdoc(self):
281 281 return "custom docstring"
282 282
283 283 class C(object):
284 284 """standard docstring"""
285 285 def getdoc(self):
286 286 return None
287 287
288 288 a = A()
289 289 b = B()
290 290 c = C()
291 291
292 292 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
293 293 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
294 294 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
295 295
296 296 def test_pdef():
297 297 # See gh-1914
298 298 def foo(): pass
299 299 inspector.pdef(foo, 'foo')
300 300
301 301 def test_pinfo_nonascii():
302 302 # See gh-1177
303 303 from . import nonascii2
304 304 ip.user_ns['nonascii2'] = nonascii2
305 305 ip._inspect('pinfo', 'nonascii2', detail_level=1)
@@ -1,99 +1,99 b''
1 1 """Tests for input manipulation machinery."""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Imports
5 5 #-----------------------------------------------------------------------------
6 6 import nose.tools as nt
7 7
8 8 from IPython.core.prefilter import AutocallChecker
9 from IPython.testing import tools as tt, decorators as dec
9 from IPython.testing import decorators as dec
10 10 from IPython.testing.globalipapp import get_ipython
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Tests
14 14 #-----------------------------------------------------------------------------
15 15 ip = get_ipython()
16 16
17 17 @dec.parametric
18 18 def test_prefilter():
19 19 """Test user input conversions"""
20 20
21 21 # pairs of (raw, expected correct) input
22 22 pairs = [ ('2+2','2+2'),
23 23 ]
24 24
25 25 for raw, correct in pairs:
26 26 yield nt.assert_equal(ip.prefilter(raw), correct)
27 27
28 28
29 29 @dec.parametric
30 30 def test_autocall_binops():
31 31 """See https://github.com/ipython/ipython/issues/81"""
32 32 ip.magic('autocall 2')
33 33 f = lambda x: x
34 34 ip.user_ns['f'] = f
35 35 try:
36 36 yield nt.assert_equal(ip.prefilter('f 1'),'f(1)')
37 37 for t in ['f +1', 'f -1']:
38 38 yield nt.assert_equal(ip.prefilter(t), t)
39 39
40 40 # Run tests again with a more permissive exclude_regexp, which will
41 41 # allow transformation of binary operations ('f -1' -> 'f(-1)').
42 42 pm = ip.prefilter_manager
43 43 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
44 44 config=pm.config)
45 45 try:
46 46 ac.priority = 1
47 47 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
48 48 pm.sort_checkers()
49 49
50 50 yield nt.assert_equal(ip.prefilter('f -1'), 'f(-1)')
51 51 yield nt.assert_equal(ip.prefilter('f +1'), 'f(+1)')
52 52 finally:
53 53 pm.unregister_checker(ac)
54 54 finally:
55 55 ip.magic('autocall 0')
56 56 del ip.user_ns['f']
57 57
58 58
59 59 @dec.parametric
60 60 def test_issue_114():
61 61 """Check that multiline string literals don't expand as magic
62 62 see http://github.com/ipython/ipython/issues/114"""
63 63
64 64 template = '"""\n%s\n"""'
65 65 # Store the current value of multi_line_specials and turn it off before
66 66 # running test, since it could be true (case in which the test doesn't make
67 67 # sense, as multiline string literals *will* expand as magic in that case).
68 68 msp = ip.prefilter_manager.multi_line_specials
69 69 ip.prefilter_manager.multi_line_specials = False
70 70 try:
71 71 for mgk in ip.magics_manager.lsmagic()['line']:
72 72 raw = template % mgk
73 73 yield nt.assert_equal(ip.prefilter(raw), raw)
74 74 finally:
75 75 ip.prefilter_manager.multi_line_specials = msp
76 76
77 77
78 78 def test_prefilter_attribute_errors():
79 79 """Capture exceptions thrown by user objects on attribute access.
80 80
81 81 See http://github.com/ipython/ipython/issues/988."""
82 82
83 83 class X(object):
84 84 def __getattr__(self, k):
85 85 raise ValueError('broken object')
86 86 def __call__(self, x):
87 87 return x
88 88
89 89 # Create a callable broken object
90 90 ip.user_ns['x'] = X()
91 91 ip.magic('autocall 2')
92 92 try:
93 93 # Even if x throws an attribute error when looking at its rewrite
94 94 # attribute, we should not crash. So the test here is simply making
95 95 # the prefilter call and not having an exception.
96 96 ip.prefilter('x 1')
97 97 finally:
98 98 del ip.user_ns['x']
99 99 ip.magic('autocall 0')
@@ -1,151 +1,150 b''
1 1 # coding: utf-8
2 2 """Tests for profile-related functions.
3 3
4 4 Currently only the startup-dir functionality is tested, but more tests should
5 5 be added for:
6 6
7 7 * ipython profile create
8 8 * ipython profile list
9 9 * ipython profile create --parallel
10 10 * security dir permissions
11 11
12 12 Authors
13 13 -------
14 14
15 15 * MinRK
16 16
17 17 """
18 18 from __future__ import absolute_import
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Imports
22 22 #-----------------------------------------------------------------------------
23 23
24 24 import os
25 25 import shutil
26 26 import sys
27 27 import tempfile
28 28
29 29 from unittest import TestCase
30 30
31 31 import nose.tools as nt
32 from nose import SkipTest
33 32
34 33 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
35 34 from IPython.core.profiledir import ProfileDir
36 35
37 36 from IPython.testing import decorators as dec
38 37 from IPython.testing import tools as tt
39 38 from IPython.utils import py3compat
40 39
41 40
42 41 #-----------------------------------------------------------------------------
43 42 # Globals
44 43 #-----------------------------------------------------------------------------
45 44 TMP_TEST_DIR = tempfile.mkdtemp()
46 45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
47 46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
48 47
49 48 #
50 49 # Setup/teardown functions/decorators
51 50 #
52 51
53 52 def setup():
54 53 """Setup test environment for the module:
55 54
56 55 - Adds dummy home dir tree
57 56 """
58 57 # Do not mask exceptions here. In particular, catching WindowsError is a
59 58 # problem because that exception is only defined on Windows...
60 59 os.makedirs(IP_TEST_DIR)
61 60
62 61
63 62 def teardown():
64 63 """Teardown test environment for the module:
65 64
66 65 - Remove dummy home dir tree
67 66 """
68 67 # Note: we remove the parent test dir, which is the root of all test
69 68 # subdirs we may have created. Use shutil instead of os.removedirs, so
70 69 # that non-empty directories are all recursively removed.
71 70 shutil.rmtree(TMP_TEST_DIR)
72 71
73 72
74 73 #-----------------------------------------------------------------------------
75 74 # Test functions
76 75 #-----------------------------------------------------------------------------
77 76 def win32_without_pywin32():
78 77 if sys.platform == 'win32':
79 78 try:
80 79 import pywin32
81 80 except ImportError:
82 81 return True
83 82 return False
84 83
85 84
86 85 class ProfileStartupTest(TestCase):
87 86 def setUp(self):
88 87 # create profile dir
89 88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
90 89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
91 90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
92 91
93 92 def tearDown(self):
94 93 # We must remove this profile right away so its presence doesn't
95 94 # confuse other tests.
96 95 shutil.rmtree(self.pd.location)
97 96
98 97 def init(self, startup_file, startup, test):
99 98 # write startup python file
100 99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
101 100 f.write(startup)
102 101 # write simple test file, to check that the startup file was run
103 102 with open(self.fname, 'w') as f:
104 103 f.write(py3compat.doctest_refactor_print(test))
105 104
106 105 def validate(self, output):
107 106 tt.ipexec_validate(self.fname, output, '', options=self.options)
108 107
109 108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
110 109 def test_startup_py(self):
111 110 self.init('00-start.py', 'zzz=123\n',
112 111 py3compat.doctest_refactor_print('print zzz\n'))
113 112 self.validate('123')
114 113
115 114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
116 115 def test_startup_ipy(self):
117 116 self.init('00-start.ipy', '%profile\n', '')
118 117 self.validate('test')
119 118
120 119
121 120 def test_list_profiles_in():
122 121 # No need to remove these directories and files, as they will get nuked in
123 122 # the module-level teardown.
124 123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
125 124 td = py3compat.str_to_unicode(td)
126 125 for name in ('profile_foo', u'profile_ünicode', 'profile_hello',
127 126 'not_a_profile'):
128 127 os.mkdir(os.path.join(td, name))
129 128 with open(os.path.join(td, 'profile_file'), 'w') as f:
130 129 f.write("I am not a profile directory")
131 130 profiles = list_profiles_in(td)
132 131
133 132 # unicode normalization can turn u'ünicode' into u'u\0308nicode',
134 133 # so only check for *nicode, and that creating a ProfileDir from the
135 134 # name remains valid
136 135 found_unicode = False
137 136 for p in list(profiles):
138 137 if p.endswith('nicode'):
139 138 pd = ProfileDir.find_profile_dir_by_name(td, p)
140 139 profiles.remove(p)
141 140 found_unicode = True
142 141 break
143 142 nt.assert_true(found_unicode)
144 143 nt.assert_equal(set(profiles), set(['foo', 'hello']))
145 144
146 145
147 146 def test_list_bundled_profiles():
148 147 # This variable will need to be updated when a new profile gets bundled
149 148 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
150 149 bundled = sorted(list_bundled_profiles())
151 150 nt.assert_equal(bundled, bundled_true)
@@ -1,111 +1,109 b''
1 1 # -*- coding: utf-8
2 2 """Tests for prompt generation."""
3 3
4 4 import unittest
5 5
6 6 import os
7 import nose.tools as nt
8 7
9 8 from IPython.testing import tools as tt, decorators as dec
10 9 from IPython.core.prompts import PromptManager, LazyEvaluate
11 10 from IPython.testing.globalipapp import get_ipython
12 from IPython.utils import py3compat
13 11 from IPython.utils.tempdir import TemporaryDirectory
14 12
15 13 ip = get_ipython()
16 14
17 15
18 16 class PromptTests(unittest.TestCase):
19 17 def setUp(self):
20 18 self.pm = PromptManager(shell=ip, config=ip.config)
21 19
22 20 def test_multiline_prompt(self):
23 21 self.pm.in_template = "[In]\n>>>"
24 22 self.pm.render('in')
25 23 self.assertEqual(self.pm.width, 3)
26 24 self.assertEqual(self.pm.txtwidth, 3)
27 25
28 26 self.pm.in_template = '[In]\n'
29 27 self.pm.render('in')
30 28 self.assertEqual(self.pm.width, 0)
31 29 self.assertEqual(self.pm.txtwidth, 0)
32 30
33 31 def test_translate_abbreviations(self):
34 32 def do_translate(template):
35 33 self.pm.in_template = template
36 34 return self.pm.templates['in']
37 35
38 36 pairs = [(r'%n>', '{color.number}{count}{color.prompt}>'),
39 37 (r'\T', '{time}'),
40 38 (r'\n', '\n')
41 39 ]
42 40
43 41 tt.check_pairs(do_translate, pairs)
44 42
45 43 def test_user_ns(self):
46 44 self.pm.color_scheme = 'NoColor'
47 45 ip.ex("foo='bar'")
48 46 self.pm.in_template = "In [{foo}]"
49 47 prompt = self.pm.render('in')
50 48 self.assertEqual(prompt, u'In [bar]')
51 49
52 50 def test_builtins(self):
53 51 self.pm.color_scheme = 'NoColor'
54 52 self.pm.in_template = "In [{int}]"
55 53 prompt = self.pm.render('in')
56 54 self.assertEqual(prompt, u"In [%r]" % int)
57 55
58 56 def test_undefined(self):
59 57 self.pm.color_scheme = 'NoColor'
60 58 self.pm.in_template = "In [{foo_dne}]"
61 59 prompt = self.pm.render('in')
62 60 self.assertEqual(prompt, u"In [<ERROR: 'foo_dne' not found>]")
63 61
64 62 def test_render(self):
65 63 self.pm.in_template = r'\#>'
66 64 self.assertEqual(self.pm.render('in',color=False), '%d>' % ip.execution_count)
67 65
68 66 def test_render_unicode_cwd(self):
69 67 save = os.getcwdu()
70 68 with TemporaryDirectory(u'ünicødé') as td:
71 69 os.chdir(td)
72 70 self.pm.in_template = r'\w [\#]'
73 71 p = self.pm.render('in', color=False)
74 72 self.assertEqual(p, u"%s [%i]" % (os.getcwdu(), ip.execution_count))
75 73 os.chdir(save)
76 74
77 75 def test_lazy_eval_unicode(self):
78 76 u = u'ünicødé'
79 77 lz = LazyEvaluate(lambda : u)
80 78 # str(lz) would fail
81 79 self.assertEqual(unicode(lz), u)
82 80 self.assertEqual(format(lz), u)
83 81
84 82 def test_lazy_eval_nonascii_bytes(self):
85 83 u = u'ünicødé'
86 84 b = u.encode('utf8')
87 85 lz = LazyEvaluate(lambda : b)
88 86 # unicode(lz) would fail
89 87 self.assertEqual(str(lz), str(b))
90 88 self.assertEqual(format(lz), str(b))
91 89
92 90 def test_lazy_eval_float(self):
93 91 f = 0.503
94 92 lz = LazyEvaluate(lambda : f)
95 93
96 94 self.assertEqual(str(lz), str(f))
97 95 self.assertEqual(unicode(lz), unicode(f))
98 96 self.assertEqual(format(lz), str(f))
99 97 self.assertEqual(format(lz, '.1'), '0.5')
100 98
101 99 @dec.skip_win32
102 100 def test_cwd_x(self):
103 101 self.pm.in_template = r"\X0"
104 102 save = os.getcwdu()
105 103 os.chdir(os.path.expanduser('~'))
106 104 p = self.pm.render('in', color=False)
107 105 try:
108 106 self.assertEqual(p, '~')
109 107 finally:
110 108 os.chdir(save)
111 109
@@ -1,51 +1,49 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for shellapp module.
3 3
4 4 Authors
5 5 -------
6 6 * Bradley Froehle
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2012 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 import unittest
19 19
20 import nose.tools as nt
21
22 20 from IPython.testing import decorators as dec
23 21 from IPython.testing import tools as tt
24 22
25 23 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
26 24 """Test the behavior of the file_to_run parameter."""
27 25
28 26 def test_py_script_file_attribute(self):
29 27 """Test that `__file__` is set when running `ipython file.py`"""
30 28 src = "print(__file__)\n"
31 29 self.mktmp(src)
32 30
33 31 if dec.module_not_available('sqlite3'):
34 32 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
35 33 else:
36 34 err = None
37 35 tt.ipexec_validate(self.fname, self.fname, err)
38 36
39 37 def test_ipy_script_file_attribute(self):
40 38 """Test that `__file__` is set when running `ipython file.ipy`"""
41 39 src = "print(__file__)\n"
42 40 self.mktmp(src, ext='.ipy')
43 41
44 42 if dec.module_not_available('sqlite3'):
45 43 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
46 44 else:
47 45 err = None
48 46 tt.ipexec_validate(self.fname, self.fname, err)
49 47
50 48 # Ideally we would also test that `__file__` is not set in the
51 49 # interactive namespace after running `ipython -i <file>`.
@@ -1,35 +1,42 b''
1 1 # coding: utf-8
2 from IPython.core.splitinput import split_user_input
2 import nose.tools as nt
3
4 from IPython.core.splitinput import split_user_input, LineInfo
3 5 from IPython.testing import tools as tt
4 6 from IPython.utils import py3compat
5 7
6 8 tests = [
7 9 ('x=1', ('', '', 'x', '=1')),
8 10 ('?', ('', '?', '', '')),
9 11 ('??', ('', '??', '', '')),
10 12 (' ?', (' ', '?', '', '')),
11 13 (' ??', (' ', '??', '', '')),
12 14 ('??x', ('', '??', 'x', '')),
13 15 ('?x=1', ('', '?', 'x', '=1')),
14 16 ('!ls', ('', '!', 'ls', '')),
15 17 (' !ls', (' ', '!', 'ls', '')),
16 18 ('!!ls', ('', '!!', 'ls', '')),
17 19 (' !!ls', (' ', '!!', 'ls', '')),
18 20 (',ls', ('', ',', 'ls', '')),
19 21 (';ls', ('', ';', 'ls', '')),
20 22 (' ;ls', (' ', ';', 'ls', '')),
21 23 ('f.g(x)', ('', '', 'f.g', '(x)')),
22 24 ('f.g (x)', ('', '', 'f.g', '(x)')),
23 25 ('?%hist1', ('', '?', '%hist1', '')),
24 26 ('?%%hist2', ('', '?', '%%hist2', '')),
25 27 ('??%hist3', ('', '??', '%hist3', '')),
26 28 ('??%%hist4', ('', '??', '%%hist4', '')),
27 29 ('?x*', ('', '?', 'x*', '')),
28 30 ]
29 31 if py3compat.PY3:
30 32 tests.append((u"Pérez Fernando", (u'', u'', u'Pérez', u'Fernando')))
31 33 else:
32 34 tests.append((u"Pérez Fernando", (u'', u'', u'P', u'érez Fernando')))
33 35
34 36 def test_split_user_input():
35 37 return tt.check_pairs(split_user_input, tests)
38
39 def test_LineInfo():
40 """Simple test for LineInfo construction and str()"""
41 linfo = LineInfo(' %cd /home')
42 nt.assert_equal(str(linfo), 'LineInfo [ |%|cd|/home]')
General Comments 0
You need to be logged in to leave comments. Login now