##// END OF EJS Templates
Remove code from prefilter that duplicates functionality in inputsplitter.
Thomas Kluyver -
Show More
@@ -1,956 +1,757 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 __builtin__
28 28 import codeop
29 29 import re
30 30
31 31 from IPython.core.alias import AliasManager
32 32 from IPython.core.autocall import IPyAutocall
33 33 from IPython.config.configurable import Configurable
34 34 from IPython.core.inputsplitter import (
35 35 ESC_SHELL,
36 36 ESC_SH_CAP,
37 37 ESC_HELP,
38 38 ESC_MAGIC,
39 39 ESC_MAGIC2,
40 40 ESC_QUOTE,
41 41 ESC_QUOTE2,
42 42 ESC_PAREN,
43 43 )
44 44 from IPython.core.macro import Macro
45 45 from IPython.core.splitinput import split_user_input, LineInfo
46 46 from IPython.core import page
47 47
48 48 from IPython.utils.traitlets import (
49 49 List, Integer, Any, Unicode, CBool, Bool, Instance, CRegExp
50 50 )
51 51 from IPython.utils.autoattr import auto_attr
52 52
53 53 #-----------------------------------------------------------------------------
54 54 # Global utilities, errors and constants
55 55 #-----------------------------------------------------------------------------
56 56
57 57
58 58 class PrefilterError(Exception):
59 59 pass
60 60
61 61
62 62 # RegExp to identify potential function names
63 63 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
64 64
65 65 # RegExp to exclude strings with this start from autocalling. In
66 66 # particular, all binary operators should be excluded, so that if foo is
67 67 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
68 68 # characters '!=()' don't need to be checked for, as the checkPythonChars
69 69 # routine explicitely does so, to catch direct calls and rebindings of
70 70 # existing names.
71 71
72 72 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
73 73 # it affects the rest of the group in square brackets.
74 74 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
75 75 r'|^is |^not |^in |^and |^or ')
76 76
77 77 # try to catch also methods for stuff in lists/tuples/dicts: off
78 78 # (experimental). For this to work, the line_split regexp would need
79 79 # to be modified so it wouldn't break things at '['. That line is
80 80 # nasty enough that I shouldn't change it until I can test it _well_.
81 81 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
82 82
83 83
84 84 # Handler Check Utilities
85 85 def is_shadowed(identifier, ip):
86 86 """Is the given identifier defined in one of the namespaces which shadow
87 87 the alias and magic namespaces? Note that an identifier is different
88 88 than ifun, because it can not contain a '.' character."""
89 89 # This is much safer than calling ofind, which can change state
90 90 return (identifier in ip.user_ns \
91 91 or identifier in ip.user_global_ns \
92 92 or identifier in ip.ns_table['builtin'])
93 93
94 94
95 95 #-----------------------------------------------------------------------------
96 96 # Main Prefilter manager
97 97 #-----------------------------------------------------------------------------
98 98
99 99
100 100 class PrefilterManager(Configurable):
101 101 """Main prefilter component.
102 102
103 103 The IPython prefilter is run on all user input before it is run. The
104 104 prefilter consumes lines of input and produces transformed lines of
105 105 input.
106 106
107 107 The iplementation consists of two phases:
108 108
109 109 1. Transformers
110 110 2. Checkers and handlers
111 111
112 112 Over time, we plan on deprecating the checkers and handlers and doing
113 113 everything in the transformers.
114 114
115 115 The transformers are instances of :class:`PrefilterTransformer` and have
116 116 a single method :meth:`transform` that takes a line and returns a
117 117 transformed line. The transformation can be accomplished using any
118 118 tool, but our current ones use regular expressions for speed.
119 119
120 120 After all the transformers have been run, the line is fed to the checkers,
121 121 which are instances of :class:`PrefilterChecker`. The line is passed to
122 122 the :meth:`check` method, which either returns `None` or a
123 123 :class:`PrefilterHandler` instance. If `None` is returned, the other
124 124 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
125 125 the line is passed to the :meth:`handle` method of the returned
126 126 handler and no further checkers are tried.
127 127
128 128 Both transformers and checkers have a `priority` attribute, that determines
129 129 the order in which they are called. Smaller priorities are tried first.
130 130
131 131 Both transformers and checkers also have `enabled` attribute, which is
132 132 a boolean that determines if the instance is used.
133 133
134 134 Users or developers can change the priority or enabled attribute of
135 135 transformers or checkers, but they must call the :meth:`sort_checkers`
136 136 or :meth:`sort_transformers` method after changing the priority.
137 137 """
138 138
139 139 multi_line_specials = CBool(True, config=True)
140 140 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
141 141
142 142 def __init__(self, shell=None, config=None):
143 143 super(PrefilterManager, self).__init__(shell=shell, config=config)
144 144 self.shell = shell
145 145 self.init_transformers()
146 146 self.init_handlers()
147 147 self.init_checkers()
148 148
149 149 #-------------------------------------------------------------------------
150 150 # API for managing transformers
151 151 #-------------------------------------------------------------------------
152 152
153 153 def init_transformers(self):
154 154 """Create the default transformers."""
155 155 self._transformers = []
156 156 for transformer_cls in _default_transformers:
157 157 transformer_cls(
158 158 shell=self.shell, prefilter_manager=self, config=self.config
159 159 )
160 160
161 161 def sort_transformers(self):
162 162 """Sort the transformers by priority.
163 163
164 164 This must be called after the priority of a transformer is changed.
165 165 The :meth:`register_transformer` method calls this automatically.
166 166 """
167 167 self._transformers.sort(key=lambda x: x.priority)
168 168
169 169 @property
170 170 def transformers(self):
171 171 """Return a list of checkers, sorted by priority."""
172 172 return self._transformers
173 173
174 174 def register_transformer(self, transformer):
175 175 """Register a transformer instance."""
176 176 if transformer not in self._transformers:
177 177 self._transformers.append(transformer)
178 178 self.sort_transformers()
179 179
180 180 def unregister_transformer(self, transformer):
181 181 """Unregister a transformer instance."""
182 182 if transformer in self._transformers:
183 183 self._transformers.remove(transformer)
184 184
185 185 #-------------------------------------------------------------------------
186 186 # API for managing checkers
187 187 #-------------------------------------------------------------------------
188 188
189 189 def init_checkers(self):
190 190 """Create the default checkers."""
191 191 self._checkers = []
192 192 for checker in _default_checkers:
193 193 checker(
194 194 shell=self.shell, prefilter_manager=self, config=self.config
195 195 )
196 196
197 197 def sort_checkers(self):
198 198 """Sort the checkers by priority.
199 199
200 200 This must be called after the priority of a checker is changed.
201 201 The :meth:`register_checker` method calls this automatically.
202 202 """
203 203 self._checkers.sort(key=lambda x: x.priority)
204 204
205 205 @property
206 206 def checkers(self):
207 207 """Return a list of checkers, sorted by priority."""
208 208 return self._checkers
209 209
210 210 def register_checker(self, checker):
211 211 """Register a checker instance."""
212 212 if checker not in self._checkers:
213 213 self._checkers.append(checker)
214 214 self.sort_checkers()
215 215
216 216 def unregister_checker(self, checker):
217 217 """Unregister a checker instance."""
218 218 if checker in self._checkers:
219 219 self._checkers.remove(checker)
220 220
221 221 #-------------------------------------------------------------------------
222 222 # API for managing checkers
223 223 #-------------------------------------------------------------------------
224 224
225 225 def init_handlers(self):
226 226 """Create the default handlers."""
227 227 self._handlers = {}
228 228 self._esc_handlers = {}
229 229 for handler in _default_handlers:
230 230 handler(
231 231 shell=self.shell, prefilter_manager=self, config=self.config
232 232 )
233 233
234 234 @property
235 235 def handlers(self):
236 236 """Return a dict of all the handlers."""
237 237 return self._handlers
238 238
239 239 def register_handler(self, name, handler, esc_strings):
240 240 """Register a handler instance by name with esc_strings."""
241 241 self._handlers[name] = handler
242 242 for esc_str in esc_strings:
243 243 self._esc_handlers[esc_str] = handler
244 244
245 245 def unregister_handler(self, name, handler, esc_strings):
246 246 """Unregister a handler instance by name with esc_strings."""
247 247 try:
248 248 del self._handlers[name]
249 249 except KeyError:
250 250 pass
251 251 for esc_str in esc_strings:
252 252 h = self._esc_handlers.get(esc_str)
253 253 if h is handler:
254 254 del self._esc_handlers[esc_str]
255 255
256 256 def get_handler_by_name(self, name):
257 257 """Get a handler by its name."""
258 258 return self._handlers.get(name)
259 259
260 260 def get_handler_by_esc(self, esc_str):
261 261 """Get a handler by its escape string."""
262 262 return self._esc_handlers.get(esc_str)
263 263
264 264 #-------------------------------------------------------------------------
265 265 # Main prefiltering API
266 266 #-------------------------------------------------------------------------
267 267
268 268 def prefilter_line_info(self, line_info):
269 269 """Prefilter a line that has been converted to a LineInfo object.
270 270
271 271 This implements the checker/handler part of the prefilter pipe.
272 272 """
273 273 # print "prefilter_line_info: ", line_info
274 274 handler = self.find_handler(line_info)
275 275 return handler.handle(line_info)
276 276
277 277 def find_handler(self, line_info):
278 278 """Find a handler for the line_info by trying checkers."""
279 279 for checker in self.checkers:
280 280 if checker.enabled:
281 281 handler = checker.check(line_info)
282 282 if handler:
283 283 return handler
284 284 return self.get_handler_by_name('normal')
285 285
286 286 def transform_line(self, line, continue_prompt):
287 287 """Calls the enabled transformers in order of increasing priority."""
288 288 for transformer in self.transformers:
289 289 if transformer.enabled:
290 290 line = transformer.transform(line, continue_prompt)
291 291 return line
292 292
293 293 def prefilter_line(self, line, continue_prompt=False):
294 294 """Prefilter a single input line as text.
295 295
296 296 This method prefilters a single line of text by calling the
297 297 transformers and then the checkers/handlers.
298 298 """
299 299
300 300 # print "prefilter_line: ", line, continue_prompt
301 301 # All handlers *must* return a value, even if it's blank ('').
302 302
303 303 # save the line away in case we crash, so the post-mortem handler can
304 304 # record it
305 305 self.shell._last_input_line = line
306 306
307 307 if not line:
308 308 # Return immediately on purely empty lines, so that if the user
309 309 # previously typed some whitespace that started a continuation
310 310 # prompt, he can break out of that loop with just an empty line.
311 311 # This is how the default python prompt works.
312 312 return ''
313 313
314 314 # At this point, we invoke our transformers.
315 315 if not continue_prompt or (continue_prompt and self.multi_line_specials):
316 316 line = self.transform_line(line, continue_prompt)
317 317
318 318 # Now we compute line_info for the checkers and handlers
319 319 line_info = LineInfo(line, continue_prompt)
320 320
321 321 # the input history needs to track even empty lines
322 322 stripped = line.strip()
323 323
324 324 normal_handler = self.get_handler_by_name('normal')
325 325 if not stripped:
326 326 if not continue_prompt:
327 327 self.shell.displayhook.prompt_count -= 1
328 328
329 329 return normal_handler.handle(line_info)
330 330
331 331 # special handlers are only allowed for single line statements
332 332 if continue_prompt and not self.multi_line_specials:
333 333 return normal_handler.handle(line_info)
334 334
335 335 prefiltered = self.prefilter_line_info(line_info)
336 336 # print "prefiltered line: %r" % prefiltered
337 337 return prefiltered
338 338
339 339 def prefilter_lines(self, lines, continue_prompt=False):
340 340 """Prefilter multiple input lines of text.
341 341
342 342 This is the main entry point for prefiltering multiple lines of
343 343 input. This simply calls :meth:`prefilter_line` for each line of
344 344 input.
345 345
346 346 This covers cases where there are multiple lines in the user entry,
347 347 which is the case when the user goes back to a multiline history
348 348 entry and presses enter.
349 349 """
350 350 llines = lines.rstrip('\n').split('\n')
351 351 # We can get multiple lines in one shot, where multiline input 'blends'
352 352 # into one line, in cases like recalling from the readline history
353 353 # buffer. We need to make sure that in such cases, we correctly
354 354 # communicate downstream which line is first and which are continuation
355 355 # ones.
356 356 if len(llines) > 1:
357 357 out = '\n'.join([self.prefilter_line(line, lnum>0)
358 358 for lnum, line in enumerate(llines) ])
359 359 else:
360 360 out = self.prefilter_line(llines[0], continue_prompt)
361 361
362 362 return out
363 363
364 364 #-----------------------------------------------------------------------------
365 365 # Prefilter transformers
366 366 #-----------------------------------------------------------------------------
367 367
368 368
369 369 class PrefilterTransformer(Configurable):
370 370 """Transform a line of user input."""
371 371
372 372 priority = Integer(100, config=True)
373 373 # Transformers don't currently use shell or prefilter_manager, but as we
374 374 # move away from checkers and handlers, they will need them.
375 375 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
376 376 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
377 377 enabled = Bool(True, config=True)
378 378
379 379 def __init__(self, shell=None, prefilter_manager=None, config=None):
380 380 super(PrefilterTransformer, self).__init__(
381 381 shell=shell, prefilter_manager=prefilter_manager, config=config
382 382 )
383 383 self.prefilter_manager.register_transformer(self)
384 384
385 385 def transform(self, line, continue_prompt):
386 386 """Transform a line, returning the new one."""
387 387 return None
388 388
389 389 def __repr__(self):
390 390 return "<%s(priority=%r, enabled=%r)>" % (
391 391 self.__class__.__name__, self.priority, self.enabled)
392 392
393 393
394 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
395 r'\s*=\s*!(?P<cmd>.*)')
396
397
398 class AssignSystemTransformer(PrefilterTransformer):
399 """Handle the `files = !ls` syntax."""
400
401 priority = Integer(100, config=True)
402
403 def transform(self, line, continue_prompt):
404 m = _assign_system_re.match(line)
405 if m is not None:
406 cmd = m.group('cmd')
407 lhs = m.group('lhs')
408 expr = "sc =%s" % cmd
409 new_line = '%s = get_ipython().magic(%r)' % (lhs, expr)
410 return new_line
411 return line
412
413
414 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
415 r'\s*=\s*%(?P<cmd>.*)')
416
417 class AssignMagicTransformer(PrefilterTransformer):
418 """Handle the `a = %who` syntax."""
419
420 priority = Integer(200, config=True)
421
422 def transform(self, line, continue_prompt):
423 m = _assign_magic_re.match(line)
424 if m is not None:
425 cmd = m.group('cmd')
426 lhs = m.group('lhs')
427 new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd)
428 return new_line
429 return line
430
431
432 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
433
434 class PyPromptTransformer(PrefilterTransformer):
435 """Handle inputs that start with '>>> ' syntax."""
436
437 priority = Integer(50, config=True)
438
439 def transform(self, line, continue_prompt):
440
441 if not line or line.isspace() or line.strip() == '...':
442 # This allows us to recognize multiple input prompts separated by
443 # blank lines and pasted in a single chunk, very common when
444 # pasting doctests or long tutorial passages.
445 return ''
446 m = _classic_prompt_re.match(line)
447 if m:
448 return line[len(m.group(0)):]
449 else:
450 return line
451
452
453 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
454
455 class IPyPromptTransformer(PrefilterTransformer):
456 """Handle inputs that start classic IPython prompt syntax."""
457
458 priority = Integer(50, config=True)
459
460 def transform(self, line, continue_prompt):
461
462 if not line or line.isspace() or line.strip() == '...':
463 # This allows us to recognize multiple input prompts separated by
464 # blank lines and pasted in a single chunk, very common when
465 # pasting doctests or long tutorial passages.
466 return ''
467 m = _ipy_prompt_re.match(line)
468 if m:
469 return line[len(m.group(0)):]
470 else:
471 return line
472
473 394 #-----------------------------------------------------------------------------
474 395 # Prefilter checkers
475 396 #-----------------------------------------------------------------------------
476 397
477 398
478 399 class PrefilterChecker(Configurable):
479 400 """Inspect an input line and return a handler for that line."""
480 401
481 402 priority = Integer(100, config=True)
482 403 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
483 404 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
484 405 enabled = Bool(True, config=True)
485 406
486 407 def __init__(self, shell=None, prefilter_manager=None, config=None):
487 408 super(PrefilterChecker, self).__init__(
488 409 shell=shell, prefilter_manager=prefilter_manager, config=config
489 410 )
490 411 self.prefilter_manager.register_checker(self)
491 412
492 413 def check(self, line_info):
493 414 """Inspect line_info and return a handler instance or None."""
494 415 return None
495 416
496 417 def __repr__(self):
497 418 return "<%s(priority=%r, enabled=%r)>" % (
498 419 self.__class__.__name__, self.priority, self.enabled)
499 420
500 421
501 422 class EmacsChecker(PrefilterChecker):
502 423
503 424 priority = Integer(100, config=True)
504 425 enabled = Bool(False, config=True)
505 426
506 427 def check(self, line_info):
507 428 "Emacs ipython-mode tags certain input lines."
508 429 if line_info.line.endswith('# PYTHON-MODE'):
509 430 return self.prefilter_manager.get_handler_by_name('emacs')
510 431 else:
511 432 return None
512 433
513 434
514 class ShellEscapeChecker(PrefilterChecker):
515
516 priority = Integer(200, config=True)
517
518 def check(self, line_info):
519 if line_info.line.lstrip().startswith(ESC_SHELL):
520 return self.prefilter_manager.get_handler_by_name('shell')
521
522
523 435 class MacroChecker(PrefilterChecker):
524 436
525 437 priority = Integer(250, config=True)
526 438
527 439 def check(self, line_info):
528 440 obj = self.shell.user_ns.get(line_info.ifun)
529 441 if isinstance(obj, Macro):
530 442 return self.prefilter_manager.get_handler_by_name('macro')
531 443 else:
532 444 return None
533 445
534 446
535 447 class IPyAutocallChecker(PrefilterChecker):
536 448
537 449 priority = Integer(300, config=True)
538 450
539 451 def check(self, line_info):
540 452 "Instances of IPyAutocall in user_ns get autocalled immediately"
541 453 obj = self.shell.user_ns.get(line_info.ifun, None)
542 454 if isinstance(obj, IPyAutocall):
543 455 obj.set_ip(self.shell)
544 456 return self.prefilter_manager.get_handler_by_name('auto')
545 457 else:
546 458 return None
547 459
548 460
549 class MultiLineMagicChecker(PrefilterChecker):
550
551 priority = Integer(400, config=True)
552
553 def check(self, line_info):
554 "Allow ! and !! in multi-line statements if multi_line_specials is on"
555 # Note that this one of the only places we check the first character of
556 # ifun and *not* the pre_char. Also note that the below test matches
557 # both ! and !!.
558 if line_info.continue_prompt \
559 and self.prefilter_manager.multi_line_specials:
560 if line_info.esc == ESC_MAGIC:
561 return self.prefilter_manager.get_handler_by_name('magic')
562 else:
563 return None
564
565
566 class EscCharsChecker(PrefilterChecker):
567
568 priority = Integer(500, config=True)
569
570 def check(self, line_info):
571 """Check for escape character and return either a handler to handle it,
572 or None if there is no escape char."""
573 if line_info.line[-1] == ESC_HELP \
574 and line_info.esc != ESC_SHELL \
575 and line_info.esc != ESC_SH_CAP:
576 # the ? can be at the end, but *not* for either kind of shell escape,
577 # because a ? can be a vaild final char in a shell cmd
578 return self.prefilter_manager.get_handler_by_name('help')
579 else:
580 if line_info.pre:
581 return None
582 # This returns None like it should if no handler exists
583 return self.prefilter_manager.get_handler_by_esc(line_info.esc)
584
585
586 461 class AssignmentChecker(PrefilterChecker):
587 462
588 463 priority = Integer(600, config=True)
589 464
590 465 def check(self, line_info):
591 466 """Check to see if user is assigning to a var for the first time, in
592 467 which case we want to avoid any sort of automagic / autocall games.
593 468
594 469 This allows users to assign to either alias or magic names true python
595 470 variables (the magic/alias systems always take second seat to true
596 471 python code). E.g. ls='hi', or ls,that=1,2"""
597 472 if line_info.the_rest:
598 473 if line_info.the_rest[0] in '=,':
599 474 return self.prefilter_manager.get_handler_by_name('normal')
600 475 else:
601 476 return None
602 477
603 478
604 479 class AutoMagicChecker(PrefilterChecker):
605 480
606 481 priority = Integer(700, config=True)
607 482
608 483 def check(self, line_info):
609 484 """If the ifun is magic, and automagic is on, run it. Note: normal,
610 485 non-auto magic would already have been triggered via '%' in
611 486 check_esc_chars. This just checks for automagic. Also, before
612 487 triggering the magic handler, make sure that there is nothing in the
613 488 user namespace which could shadow it."""
614 489 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
615 490 return None
616 491
617 492 # We have a likely magic method. Make sure we should actually call it.
618 493 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
619 494 return None
620 495
621 496 head = line_info.ifun.split('.',1)[0]
622 497 if is_shadowed(head, self.shell):
623 498 return None
624 499
625 500 return self.prefilter_manager.get_handler_by_name('magic')
626 501
627 502
628 503 class AliasChecker(PrefilterChecker):
629 504
630 505 priority = Integer(800, config=True)
631 506
632 507 def check(self, line_info):
633 508 "Check if the initital identifier on the line is an alias."
634 509 # Note: aliases can not contain '.'
635 510 head = line_info.ifun.split('.',1)[0]
636 511 if line_info.ifun not in self.shell.alias_manager \
637 512 or head not in self.shell.alias_manager \
638 513 or is_shadowed(head, self.shell):
639 514 return None
640 515
641 516 return self.prefilter_manager.get_handler_by_name('alias')
642 517
643 518
644 519 class PythonOpsChecker(PrefilterChecker):
645 520
646 521 priority = Integer(900, config=True)
647 522
648 523 def check(self, line_info):
649 524 """If the 'rest' of the line begins with a function call or pretty much
650 525 any python operator, we should simply execute the line (regardless of
651 526 whether or not there's a possible autocall expansion). This avoids
652 527 spurious (and very confusing) geattr() accesses."""
653 528 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
654 529 return self.prefilter_manager.get_handler_by_name('normal')
655 530 else:
656 531 return None
657 532
658 533
659 534 class AutocallChecker(PrefilterChecker):
660 535
661 536 priority = Integer(1000, config=True)
662 537
663 538 function_name_regexp = CRegExp(re_fun_name, config=True,
664 539 help="RegExp to identify potential function names.")
665 540 exclude_regexp = CRegExp(re_exclude_auto, config=True,
666 541 help="RegExp to exclude strings with this start from autocalling.")
667 542
668 543 def check(self, line_info):
669 544 "Check if the initial word/function is callable and autocall is on."
670 545 if not self.shell.autocall:
671 546 return None
672 547
673 548 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
674 549 if not oinfo['found']:
675 550 return None
676 551
677 552 if callable(oinfo['obj']) \
678 553 and (not self.exclude_regexp.match(line_info.the_rest)) \
679 554 and self.function_name_regexp.match(line_info.ifun):
680 555 return self.prefilter_manager.get_handler_by_name('auto')
681 556 else:
682 557 return None
683 558
684 559
685 560 #-----------------------------------------------------------------------------
686 561 # Prefilter handlers
687 562 #-----------------------------------------------------------------------------
688 563
689 564
690 565 class PrefilterHandler(Configurable):
691 566
692 567 handler_name = Unicode('normal')
693 568 esc_strings = List([])
694 569 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
695 570 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
696 571
697 572 def __init__(self, shell=None, prefilter_manager=None, config=None):
698 573 super(PrefilterHandler, self).__init__(
699 574 shell=shell, prefilter_manager=prefilter_manager, config=config
700 575 )
701 576 self.prefilter_manager.register_handler(
702 577 self.handler_name,
703 578 self,
704 579 self.esc_strings
705 580 )
706 581
707 582 def handle(self, line_info):
708 583 # print "normal: ", line_info
709 584 """Handle normal input lines. Use as a template for handlers."""
710 585
711 586 # With autoindent on, we need some way to exit the input loop, and I
712 587 # don't want to force the user to have to backspace all the way to
713 588 # clear the line. The rule will be in this case, that either two
714 589 # lines of pure whitespace in a row, or a line of pure whitespace but
715 590 # of a size different to the indent level, will exit the input loop.
716 591 line = line_info.line
717 592 continue_prompt = line_info.continue_prompt
718 593
719 594 if (continue_prompt and
720 595 self.shell.autoindent and
721 596 line.isspace() and
722 597 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
723 598 line = ''
724 599
725 600 return line
726 601
727 602 def __str__(self):
728 603 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
729 604
730 605
731 606 class AliasHandler(PrefilterHandler):
732 607
733 608 handler_name = Unicode('alias')
734 609
735 610 def handle(self, line_info):
736 611 """Handle alias input lines. """
737 612 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
738 613 # pre is needed, because it carries the leading whitespace. Otherwise
739 614 # aliases won't work in indented sections.
740 615 line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed)
741 616
742 617 return line_out
743 618
744 619
745 class ShellEscapeHandler(PrefilterHandler):
746
747 handler_name = Unicode('shell')
748 esc_strings = List([ESC_SHELL, ESC_SH_CAP])
749
750 def handle(self, line_info):
751 """Execute the line in a shell, empty return value"""
752 magic_handler = self.prefilter_manager.get_handler_by_name('magic')
753
754 line = line_info.line
755 if line.lstrip().startswith(ESC_SH_CAP):
756 # rewrite LineInfo's line, ifun and the_rest to properly hold the
757 # call to %sx and the actual command to be executed, so
758 # handle_magic can work correctly. Note that this works even if
759 # the line is indented, so it handles multi_line_specials
760 # properly.
761 new_rest = line.lstrip()[2:]
762 line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest)
763 line_info.ifun = 'sx'
764 line_info.the_rest = new_rest
765 return magic_handler.handle(line_info)
766 else:
767 cmd = line.lstrip().lstrip(ESC_SHELL)
768 line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, cmd)
769 return line_out
770
771
772 620 class MacroHandler(PrefilterHandler):
773 621 handler_name = Unicode("macro")
774 622
775 623 def handle(self, line_info):
776 624 obj = self.shell.user_ns.get(line_info.ifun)
777 625 pre_space = line_info.pre_whitespace
778 626 line_sep = "\n" + pre_space
779 627 return pre_space + line_sep.join(obj.value.splitlines())
780 628
781 629
782 630 class MagicHandler(PrefilterHandler):
783 631
784 632 handler_name = Unicode('magic')
785 633 esc_strings = List([ESC_MAGIC])
786 634
787 635 def handle(self, line_info):
788 636 """Execute magic functions."""
789 637 ifun = line_info.ifun
790 638 the_rest = line_info.the_rest
791 639 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
792 640 (ifun + " " + the_rest))
793 641 return cmd
794 642
795 643
796 644 class AutoHandler(PrefilterHandler):
797 645
798 646 handler_name = Unicode('auto')
799 647 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
800 648
801 649 def handle(self, line_info):
802 650 """Handle lines which can be auto-executed, quoting if requested."""
803 651 line = line_info.line
804 652 ifun = line_info.ifun
805 653 the_rest = line_info.the_rest
806 654 pre = line_info.pre
807 655 esc = line_info.esc
808 656 continue_prompt = line_info.continue_prompt
809 657 obj = line_info.ofind(self.shell)['obj']
810 658 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
811 659
812 660 # This should only be active for single-line input!
813 661 if continue_prompt:
814 662 return line
815 663
816 664 force_auto = isinstance(obj, IPyAutocall)
817 665
818 666 # User objects sometimes raise exceptions on attribute access other
819 667 # than AttributeError (we've seen it in the past), so it's safest to be
820 668 # ultra-conservative here and catch all.
821 669 try:
822 670 auto_rewrite = obj.rewrite
823 671 except Exception:
824 672 auto_rewrite = True
825 673
826 674 if esc == ESC_QUOTE:
827 675 # Auto-quote splitting on whitespace
828 676 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
829 677 elif esc == ESC_QUOTE2:
830 678 # Auto-quote whole string
831 679 newcmd = '%s("%s")' % (ifun,the_rest)
832 680 elif esc == ESC_PAREN:
833 681 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
834 682 else:
835 683 # Auto-paren.
836 684 if force_auto:
837 685 # Don't rewrite if it is already a call.
838 686 do_rewrite = not the_rest.startswith('(')
839 687 else:
840 688 if not the_rest:
841 689 # We only apply it to argument-less calls if the autocall
842 690 # parameter is set to 2.
843 691 do_rewrite = (self.shell.autocall >= 2)
844 692 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
845 693 # Don't autocall in this case: item access for an object
846 694 # which is BOTH callable and implements __getitem__.
847 695 do_rewrite = False
848 696 else:
849 697 do_rewrite = True
850 698
851 699 # Figure out the rewritten command
852 700 if do_rewrite:
853 701 if the_rest.endswith(';'):
854 702 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
855 703 else:
856 704 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
857 705 else:
858 706 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
859 707 return normal_handler.handle(line_info)
860 708
861 709 # Display the rewritten call
862 710 if auto_rewrite:
863 711 self.shell.auto_rewrite_input(newcmd)
864 712
865 713 return newcmd
866 714
867 715
868 class HelpHandler(PrefilterHandler):
869
870 handler_name = Unicode('help')
871 esc_strings = List([ESC_HELP])
872
873 def handle(self, line_info):
874 """Try to get some help for the object.
875
876 obj? or ?obj -> basic information.
877 obj?? or ??obj -> more details.
878 """
879 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
880 line = line_info.line
881 # We need to make sure that we don't process lines which would be
882 # otherwise valid python, such as "x=1 # what?"
883 try:
884 codeop.compile_command(line)
885 except SyntaxError:
886 # We should only handle as help stuff which is NOT valid syntax
887 if line[0]==ESC_HELP:
888 line = line[1:]
889 elif line[-1]==ESC_HELP:
890 line = line[:-1]
891 if line:
892 #print 'line:<%r>' % line # dbg
893 self.shell.magic('pinfo %s' % line_info.ifun)
894 else:
895 self.shell.show_usage()
896 return '' # Empty string is needed here!
897 except:
898 raise
899 # Pass any other exceptions through to the normal handler
900 return normal_handler.handle(line_info)
901 else:
902 # If the code compiles ok, we should handle it normally
903 return normal_handler.handle(line_info)
904
905
906 716 class EmacsHandler(PrefilterHandler):
907 717
908 718 handler_name = Unicode('emacs')
909 719 esc_strings = List([])
910 720
911 721 def handle(self, line_info):
912 722 """Handle input lines marked by python-mode."""
913 723
914 724 # Currently, nothing is done. Later more functionality can be added
915 725 # here if needed.
916 726
917 727 # The input cache shouldn't be updated
918 728 return line_info.line
919 729
920 730
921 731 #-----------------------------------------------------------------------------
922 732 # Defaults
923 733 #-----------------------------------------------------------------------------
924 734
925 735
926 736 _default_transformers = [
927 AssignSystemTransformer,
928 AssignMagicTransformer,
929 PyPromptTransformer,
930 IPyPromptTransformer,
931 737 ]
932 738
933 739 _default_checkers = [
934 740 EmacsChecker,
935 ShellEscapeChecker,
936 741 MacroChecker,
937 742 IPyAutocallChecker,
938 MultiLineMagicChecker,
939 EscCharsChecker,
940 743 AssignmentChecker,
941 744 AutoMagicChecker,
942 745 AliasChecker,
943 746 PythonOpsChecker,
944 747 AutocallChecker
945 748 ]
946 749
947 750 _default_handlers = [
948 751 PrefilterHandler,
949 752 AliasHandler,
950 ShellEscapeHandler,
951 753 MacroHandler,
952 754 MagicHandler,
953 755 AutoHandler,
954 HelpHandler,
955 756 EmacsHandler
956 757 ]
@@ -1,169 +1,119 b''
1 1 """Tests for input handlers.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Module imports
5 5 #-----------------------------------------------------------------------------
6 6
7 7 # third party
8 8 import nose.tools as nt
9 9
10 10 # our own packages
11 11 from IPython.core import autocall
12 12 from IPython.testing import tools as tt
13 13 from IPython.testing.globalipapp import get_ipython
14 14 from IPython.utils import py3compat
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Globals
18 18 #-----------------------------------------------------------------------------
19 19
20 20 # Get the public instance of IPython
21 21 ip = get_ipython()
22 22
23 23 failures = []
24 24 num_tests = 0
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Test functions
28 28 #-----------------------------------------------------------------------------
29 29
30 30 class CallableIndexable(object):
31 31 def __getitem__(self, idx): return True
32 32 def __call__(self, *args, **kws): return True
33 33
34 34
35 35 class Autocallable(autocall.IPyAutocall):
36 36 def __call__(self):
37 37 return "called"
38 38
39 39
40 40 def run(tests):
41 41 """Loop through a list of (pre, post) inputs, where pre is the string
42 42 handed to ipython, and post is how that string looks after it's been
43 43 transformed (i.e. ipython's notion of _i)"""
44 44 tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests)
45 45
46 46
47 47 def test_handlers():
48 48 # alias expansion
49 49
50 50 # We're using 'true' as our syscall of choice because it doesn't
51 51 # write anything to stdout.
52 52
53 53 # Turn off actual execution of aliases, because it's noisy
54 54 old_system_cmd = ip.system
55 55 ip.system = lambda cmd: None
56 56
57 57
58 58 ip.alias_manager.alias_table['an_alias'] = (0, 'true')
59 59 # These are useful for checking a particular recursive alias issue
60 60 ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
61 61 ip.alias_manager.alias_table['d'] = (0, 'true')
62 62 run([(i,py3compat.u_format(o)) for i,o in \
63 63 [("an_alias", "get_ipython().system({u}'true ')"), # alias
64 64 # Below: recursive aliases should expand whitespace-surrounded
65 65 # chars, *not* initial chars which happen to be aliases:
66 66 ("top", "get_ipython().system({u}'d:/cygwin/top ')"),
67 67 ]])
68 68 ip.system = old_system_cmd
69 69
70 70 call_idx = CallableIndexable()
71 71 ip.user_ns['call_idx'] = call_idx
72 72
73 73 # For many of the below, we're also checking that leading whitespace
74 74 # turns off the esc char, which it should unless there is a continuation
75 75 # line.
76 76 run([(i,py3compat.u_format(o)) for i,o in \
77 77 [('"no change"', '"no change"'), # normal
78 (u"!true", "get_ipython().system({u}'true')"), # shell_escapes
79 (u"!! true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
80 (u"!!true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic
81 (u"%lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
82 78 (u"lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic
83 79 #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
84
85 # post-esc-char whitespace goes inside
86 (u"! true", "get_ipython().system({u}' true')"),
87
88 # handle_help
89
90 # These are weak tests -- just looking at what the help handlers
91 # logs, which is not how it really does its work. But it still
92 # lets us check the key paths through the handler.
93
94 ("x=1 # what?", "x=1 # what?"), # no help if valid python
95 ]])
96
97 # multi_line_specials
98 ip.prefilter_manager.multi_line_specials = False
99 # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
100 run([
101 (u'if 1:\n !true', u'if 1:\n !true'),
102 (u'if 1:\n lsmagic', u'if 1:\n lsmagic'),
103 (u'if 1:\n an_alias', u'if 1:\n an_alias'),
104 ])
105
106 ip.prefilter_manager.multi_line_specials = True
107 # initial indents must be preserved.
108 run([(i,py3compat.u_format(o)) for i,o in \
109 [(u'if 1:\n !true', "if 1:\n get_ipython().system({u}'true')"),
110 (u'if 2:\n lsmagic', "if 2:\n get_ipython().magic({u}'lsmagic ')"),
111 (u'if 1:\n an_alias', "if 1:\n get_ipython().system({u}'true ')"),
112 # Weird one
113 (u'if 1:\n !!true', "if 1:\n get_ipython().magic({u}'sx true')"),
114
115 # Even with m_l_s on, autocall is off even with special chars
116 ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
117 ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'),
118 ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'),
119 ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'),
120 # What about !!
121 80 ]])
122 81
123 82 # Objects which are instances of IPyAutocall are *always* autocalled
124 83 autocallable = Autocallable()
125 84 ip.user_ns['autocallable'] = autocallable
126 85
127 86 # auto
128 87 ip.magic('autocall 0')
129 88 # Only explicit escapes or instances of IPyAutocallable should get
130 89 # expanded
131 90 run([
132 91 ('len "abc"', 'len "abc"'),
133 92 ('autocallable', 'autocallable()'),
134 93 # Don't add extra brackets (gh-1117)
135 94 ('autocallable()', 'autocallable()'),
136 (",list 1 2 3", 'list("1", "2", "3")'),
137 (";list 1 2 3", 'list("1 2 3")'),
138 ("/len range(1,4)", 'len(range(1,4))'),
139 95 ])
140 96 ip.magic('autocall 1')
141 97 run([
142 (",list 1 2 3", 'list("1", "2", "3")'),
143 (";list 1 2 3", 'list("1 2 3")'),
144 ("/len range(1,4)", 'len(range(1,4))'),
145 98 ('len "abc"', 'len("abc")'),
146 99 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
147 100 # Autocall is turned off if first arg is [] and the object
148 101 # is both callable and indexable. Like so:
149 102 ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__...
150 103 ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
151 104 ('call_idx 1', 'call_idx(1)'),
152 105 ('len', 'len'), # only at 2 does it auto-call on single args
153 106 ])
154 107 ip.magic('autocall 2')
155 108 run([
156 (",list 1 2 3", 'list("1", "2", "3")'),
157 (";list 1 2 3", 'list("1 2 3")'),
158 ("/len range(1,4)", 'len(range(1,4))'),
159 109 ('len "abc"', 'len("abc")'),
160 110 ('len "abc";', 'len("abc");'),
161 111 ('len [1,2]', 'len([1,2])'),
162 112 ('call_idx [1]', 'call_idx [1]'),
163 113 ('call_idx 1', 'call_idx(1)'),
164 114 # This is what's different:
165 115 ('len', 'len()'), # only at 2 does it auto-call on single args
166 116 ])
167 117 ip.magic('autocall 1')
168 118
169 119 nt.assert_equal(failures, [])
@@ -1,798 +1,794 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
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.tempdir import TemporaryDirectory
38 38 from IPython.utils.process import find_cmd
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Test functions begin
42 42 #-----------------------------------------------------------------------------
43 43
44 44 @magic.magics_class
45 45 class DummyMagics(magic.Magics): pass
46 46
47 47 def test_rehashx():
48 48 # clear up everything
49 49 _ip = get_ipython()
50 50 _ip.alias_manager.alias_table.clear()
51 51 del _ip.db['syscmdlist']
52 52
53 53 _ip.magic('rehashx')
54 54 # Practically ALL ipython development systems will have more than 10 aliases
55 55
56 56 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
57 57 for key, val in _ip.alias_manager.alias_table.iteritems():
58 58 # we must strip dots from alias names
59 59 nt.assert_true('.' not in key)
60 60
61 61 # rehashx must fill up syscmdlist
62 62 scoms = _ip.db['syscmdlist']
63 63 yield (nt.assert_true, len(scoms) > 10)
64 64
65 65
66 66 def test_magic_parse_options():
67 67 """Test that we don't mangle paths when parsing magic options."""
68 68 ip = get_ipython()
69 69 path = 'c:\\x'
70 70 m = DummyMagics(ip)
71 71 opts = m.parse_options('-f %s' % path,'f:')[0]
72 72 # argv splitting is os-dependent
73 73 if os.name == 'posix':
74 74 expected = 'c:x'
75 75 else:
76 76 expected = path
77 77 nt.assert_equal(opts['f'], expected)
78 78
79 79 def test_magic_parse_long_options():
80 80 """Magic.parse_options can handle --foo=bar long options"""
81 81 ip = get_ipython()
82 82 m = DummyMagics(ip)
83 83 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
84 84 nt.assert_true('foo' in opts)
85 85 nt.assert_true('bar' in opts)
86 86 nt.assert_true(opts['bar'], "bubble")
87 87
88 88
89 89 @dec.skip_without('sqlite3')
90 90 def doctest_hist_f():
91 91 """Test %hist -f with temporary filename.
92 92
93 93 In [9]: import tempfile
94 94
95 95 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
96 96
97 97 In [11]: %hist -nl -f $tfile 3
98 98
99 99 In [13]: import os; os.unlink(tfile)
100 100 """
101 101
102 102
103 103 @dec.skip_without('sqlite3')
104 104 def doctest_hist_r():
105 105 """Test %hist -r
106 106
107 107 XXX - This test is not recording the output correctly. For some reason, in
108 108 testing mode the raw history isn't getting populated. No idea why.
109 109 Disabling the output checking for now, though at least we do run it.
110 110
111 111 In [1]: 'hist' in _ip.lsmagic()
112 112 Out[1]: True
113 113
114 114 In [2]: x=1
115 115
116 116 In [3]: %hist -rl 2
117 117 x=1 # random
118 118 %hist -r 2
119 119 """
120 120
121 121
122 122 @dec.skip_without('sqlite3')
123 123 def doctest_hist_op():
124 124 """Test %hist -op
125 125
126 126 In [1]: class b(float):
127 127 ...: pass
128 128 ...:
129 129
130 130 In [2]: class s(object):
131 131 ...: def __str__(self):
132 132 ...: return 's'
133 133 ...:
134 134
135 135 In [3]:
136 136
137 137 In [4]: class r(b):
138 138 ...: def __repr__(self):
139 139 ...: return 'r'
140 140 ...:
141 141
142 142 In [5]: class sr(s,r): pass
143 143 ...:
144 144
145 145 In [6]:
146 146
147 147 In [7]: bb=b()
148 148
149 149 In [8]: ss=s()
150 150
151 151 In [9]: rr=r()
152 152
153 153 In [10]: ssrr=sr()
154 154
155 155 In [11]: 4.5
156 156 Out[11]: 4.5
157 157
158 158 In [12]: str(ss)
159 159 Out[12]: 's'
160 160
161 161 In [13]:
162 162
163 163 In [14]: %hist -op
164 164 >>> class b:
165 165 ... pass
166 166 ...
167 167 >>> class s(b):
168 168 ... def __str__(self):
169 169 ... return 's'
170 170 ...
171 171 >>>
172 172 >>> class r(b):
173 173 ... def __repr__(self):
174 174 ... return 'r'
175 175 ...
176 176 >>> class sr(s,r): pass
177 177 >>>
178 178 >>> bb=b()
179 179 >>> ss=s()
180 180 >>> rr=r()
181 181 >>> ssrr=sr()
182 182 >>> 4.5
183 183 4.5
184 184 >>> str(ss)
185 185 's'
186 186 >>>
187 187 """
188 188
189 189
190 190 @dec.skip_without('sqlite3')
191 191 def test_macro():
192 192 ip = get_ipython()
193 193 ip.history_manager.reset() # Clear any existing history.
194 194 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
195 195 for i, cmd in enumerate(cmds, start=1):
196 196 ip.history_manager.store_inputs(i, cmd)
197 197 ip.magic("macro test 1-3")
198 198 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
199 199
200 200 # List macros.
201 201 assert "test" in ip.magic("macro")
202 202
203 203
204 204 @dec.skip_without('sqlite3')
205 205 def test_macro_run():
206 206 """Test that we can run a multi-line macro successfully."""
207 207 ip = get_ipython()
208 208 ip.history_manager.reset()
209 209 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
210 210 "%macro test 2-3"]
211 211 for cmd in cmds:
212 212 ip.run_cell(cmd, store_history=True)
213 213 nt.assert_equal(ip.user_ns["test"].value,
214 214 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
215 215 with tt.AssertPrints("12"):
216 216 ip.run_cell("test")
217 217 with tt.AssertPrints("13"):
218 218 ip.run_cell("test")
219 219
220 220
221 221 @dec.skipif_not_numpy
222 222 def test_numpy_reset_array_undec():
223 223 "Test '%reset array' functionality"
224 224 _ip.ex('import numpy as np')
225 225 _ip.ex('a = np.empty(2)')
226 226 yield (nt.assert_true, 'a' in _ip.user_ns)
227 227 _ip.magic('reset -f array')
228 228 yield (nt.assert_false, 'a' in _ip.user_ns)
229 229
230 230 def test_reset_out():
231 231 "Test '%reset out' magic"
232 232 _ip.run_cell("parrot = 'dead'", store_history=True)
233 233 # test '%reset -f out', make an Out prompt
234 234 _ip.run_cell("parrot", store_history=True)
235 235 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
236 236 _ip.magic('reset -f out')
237 237 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
238 238 nt.assert_true(len(_ip.user_ns['Out']) == 0)
239 239
240 240 def test_reset_in():
241 241 "Test '%reset in' magic"
242 242 # test '%reset -f in'
243 243 _ip.run_cell("parrot", store_history=True)
244 244 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
245 245 _ip.magic('%reset -f in')
246 246 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
247 247 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
248 248
249 249 def test_reset_dhist():
250 250 "Test '%reset dhist' magic"
251 251 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
252 252 _ip.magic('cd ' + os.path.dirname(nt.__file__))
253 253 _ip.magic('cd -')
254 254 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
255 255 _ip.magic('reset -f dhist')
256 256 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
257 257 _ip.run_cell("_dh = [d for d in tmp]") #restore
258 258
259 259 def test_reset_in_length():
260 260 "Test that '%reset in' preserves In[] length"
261 261 _ip.run_cell("print 'foo'")
262 262 _ip.run_cell("reset -f in")
263 263 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
264 264
265 265 def test_time():
266 266 _ip.magic('time None')
267 267
268 268 def test_tb_syntaxerror():
269 269 """test %tb after a SyntaxError"""
270 270 ip = get_ipython()
271 271 ip.run_cell("for")
272 272
273 273 # trap and validate stdout
274 274 save_stdout = sys.stdout
275 275 try:
276 276 sys.stdout = StringIO()
277 277 ip.run_cell("%tb")
278 278 out = sys.stdout.getvalue()
279 279 finally:
280 280 sys.stdout = save_stdout
281 281 # trim output, and only check the last line
282 282 last_line = out.rstrip().splitlines()[-1].strip()
283 283 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
284 284
285 285
286 @py3compat.doctest_refactor_print
287 def doctest_time():
288 """
289 In [10]: %time None
290 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
291 Wall time: 0.00 s
286 def test_time():
287 ip = get_ipython()
292 288
293 In [11]: def f(kmjy):
294 ....: %time print 2*kmjy
295
296 In [12]: f(3)
297 6
298 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
299 Wall time: 0.00 s
300 """
301
289 with tt.AssertPrints("CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s"):
290 ip.run_cell("%time None")
291
292 ip.run_cell("def f(kmjy):\n"
293 " %time print (2*kmjy)")
294
295 with tt.AssertPrints("CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s"):
296 with tt.AssertPrints("hihi", suppress=False):
297 ip.run_cell("f('hi')")
302 298
303 299 def test_doctest_mode():
304 300 "Toggle doctest_mode twice, it should be a no-op and run without error"
305 301 _ip.magic('doctest_mode')
306 302 _ip.magic('doctest_mode')
307 303
308 304
309 305 def test_parse_options():
310 306 """Tests for basic options parsing in magics."""
311 307 # These are only the most minimal of tests, more should be added later. At
312 308 # the very least we check that basic text/unicode calls work OK.
313 309 m = DummyMagics(_ip)
314 310 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
315 311 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
316 312
317 313
318 314 def test_dirops():
319 315 """Test various directory handling operations."""
320 316 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
321 317 curpath = os.getcwdu
322 318 startdir = os.getcwdu()
323 319 ipdir = os.path.realpath(_ip.ipython_dir)
324 320 try:
325 321 _ip.magic('cd "%s"' % ipdir)
326 322 nt.assert_equal(curpath(), ipdir)
327 323 _ip.magic('cd -')
328 324 nt.assert_equal(curpath(), startdir)
329 325 _ip.magic('pushd "%s"' % ipdir)
330 326 nt.assert_equal(curpath(), ipdir)
331 327 _ip.magic('popd')
332 328 nt.assert_equal(curpath(), startdir)
333 329 finally:
334 330 os.chdir(startdir)
335 331
336 332
337 333 def test_xmode():
338 334 # Calling xmode three times should be a no-op
339 335 xmode = _ip.InteractiveTB.mode
340 336 for i in range(3):
341 337 _ip.magic("xmode")
342 338 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
343 339
344 340 def test_reset_hard():
345 341 monitor = []
346 342 class A(object):
347 343 def __del__(self):
348 344 monitor.append(1)
349 345 def __repr__(self):
350 346 return "<A instance>"
351 347
352 348 _ip.user_ns["a"] = A()
353 349 _ip.run_cell("a")
354 350
355 351 nt.assert_equal(monitor, [])
356 352 _ip.magic("reset -f")
357 353 nt.assert_equal(monitor, [1])
358 354
359 355 class TestXdel(tt.TempFileMixin):
360 356 def test_xdel(self):
361 357 """Test that references from %run are cleared by xdel."""
362 358 src = ("class A(object):\n"
363 359 " monitor = []\n"
364 360 " def __del__(self):\n"
365 361 " self.monitor.append(1)\n"
366 362 "a = A()\n")
367 363 self.mktmp(src)
368 364 # %run creates some hidden references...
369 365 _ip.magic("run %s" % self.fname)
370 366 # ... as does the displayhook.
371 367 _ip.run_cell("a")
372 368
373 369 monitor = _ip.user_ns["A"].monitor
374 370 nt.assert_equal(monitor, [])
375 371
376 372 _ip.magic("xdel a")
377 373
378 374 # Check that a's __del__ method has been called.
379 375 nt.assert_equal(monitor, [1])
380 376
381 377 def doctest_who():
382 378 """doctest for %who
383 379
384 380 In [1]: %reset -f
385 381
386 382 In [2]: alpha = 123
387 383
388 384 In [3]: beta = 'beta'
389 385
390 386 In [4]: %who int
391 387 alpha
392 388
393 389 In [5]: %who str
394 390 beta
395 391
396 392 In [6]: %whos
397 393 Variable Type Data/Info
398 394 ----------------------------
399 395 alpha int 123
400 396 beta str beta
401 397
402 398 In [7]: %who_ls
403 399 Out[7]: ['alpha', 'beta']
404 400 """
405 401
406 402 def test_whos():
407 403 """Check that whos is protected against objects where repr() fails."""
408 404 class A(object):
409 405 def __repr__(self):
410 406 raise Exception()
411 407 _ip.user_ns['a'] = A()
412 408 _ip.magic("whos")
413 409
414 410 @py3compat.u_format
415 411 def doctest_precision():
416 412 """doctest for %precision
417 413
418 414 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
419 415
420 416 In [2]: %precision 5
421 417 Out[2]: {u}'%.5f'
422 418
423 419 In [3]: f.float_format
424 420 Out[3]: {u}'%.5f'
425 421
426 422 In [4]: %precision %e
427 423 Out[4]: {u}'%e'
428 424
429 425 In [5]: f(3.1415927)
430 426 Out[5]: {u}'3.141593e+00'
431 427 """
432 428
433 429 def test_psearch():
434 430 with tt.AssertPrints("dict.fromkeys"):
435 431 _ip.run_cell("dict.fr*?")
436 432
437 433 def test_timeit_shlex():
438 434 """test shlex issues with timeit (#1109)"""
439 435 _ip.ex("def f(*a,**kw): pass")
440 436 _ip.magic('timeit -n1 "this is a bug".count(" ")')
441 437 _ip.magic('timeit -r1 -n1 f(" ", 1)')
442 438 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
443 439 _ip.magic('timeit -r1 -n1 ("a " + "b")')
444 440 _ip.magic('timeit -r1 -n1 f("a " + "b")')
445 441 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
446 442
447 443
448 444 def test_timeit_arguments():
449 445 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
450 446 _ip.magic("timeit ('#')")
451 447
452 448
453 449 def test_timeit_special_syntax():
454 450 "Test %%timeit with IPython special syntax"
455 451 from IPython.core.magic import register_line_magic
456 452
457 453 @register_line_magic
458 454 def lmagic(line):
459 455 ip = get_ipython()
460 456 ip.user_ns['lmagic_out'] = line
461 457
462 458 # line mode test
463 459 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
464 460 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
465 461 # cell mode test
466 462 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
467 463 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
468 464
469 465
470 466 @dec.skipif(execution.profile is None)
471 467 def test_prun_quotes():
472 468 "Test that prun does not clobber string escapes (GH #1302)"
473 469 _ip.magic(r"prun -q x = '\t'")
474 470 nt.assert_equal(_ip.user_ns['x'], '\t')
475 471
476 472 def test_extension():
477 473 tmpdir = TemporaryDirectory()
478 474 orig_ipython_dir = _ip.ipython_dir
479 475 try:
480 476 _ip.ipython_dir = tmpdir.name
481 477 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
482 478 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
483 479 _ip.magic("install_ext %s" % url)
484 480 _ip.user_ns.pop('arq', None)
485 481 invalidate_caches() # Clear import caches
486 482 _ip.magic("load_ext daft_extension")
487 483 nt.assert_equal(_ip.user_ns['arq'], 185)
488 484 _ip.magic("unload_ext daft_extension")
489 485 assert 'arq' not in _ip.user_ns
490 486 finally:
491 487 _ip.ipython_dir = orig_ipython_dir
492 488 tmpdir.cleanup()
493 489
494 490 def test_notebook_export_json():
495 491 with TemporaryDirectory() as td:
496 492 outfile = os.path.join(td, "nb.ipynb")
497 493 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
498 494 _ip.magic("notebook -e %s" % outfile)
499 495
500 496 def test_notebook_export_py():
501 497 with TemporaryDirectory() as td:
502 498 outfile = os.path.join(td, "nb.py")
503 499 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
504 500 _ip.magic("notebook -e %s" % outfile)
505 501
506 502 def test_notebook_reformat_py():
507 503 with TemporaryDirectory() as td:
508 504 infile = os.path.join(td, "nb.ipynb")
509 505 with io.open(infile, 'w', encoding='utf-8') as f:
510 506 current.write(nb0, f, 'json')
511 507
512 508 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
513 509 _ip.magic("notebook -f py %s" % infile)
514 510
515 511 def test_notebook_reformat_json():
516 512 with TemporaryDirectory() as td:
517 513 infile = os.path.join(td, "nb.py")
518 514 with io.open(infile, 'w', encoding='utf-8') as f:
519 515 current.write(nb0, f, 'py')
520 516
521 517 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
522 518 _ip.magic("notebook -f ipynb %s" % infile)
523 519 _ip.magic("notebook -f json %s" % infile)
524 520
525 521 def test_env():
526 522 env = _ip.magic("env")
527 523 assert isinstance(env, dict), type(env)
528 524
529 525
530 526 class CellMagicTestCase(TestCase):
531 527
532 528 def check_ident(self, magic):
533 529 # Manually called, we get the result
534 530 out = _ip.run_cell_magic(magic, 'a', 'b')
535 531 nt.assert_equal(out, ('a','b'))
536 532 # Via run_cell, it goes into the user's namespace via displayhook
537 533 _ip.run_cell('%%' + magic +' c\nd')
538 534 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
539 535
540 536 def test_cell_magic_func_deco(self):
541 537 "Cell magic using simple decorator"
542 538 @register_cell_magic
543 539 def cellm(line, cell):
544 540 return line, cell
545 541
546 542 self.check_ident('cellm')
547 543
548 544 def test_cell_magic_reg(self):
549 545 "Cell magic manually registered"
550 546 def cellm(line, cell):
551 547 return line, cell
552 548
553 549 _ip.register_magic_function(cellm, 'cell', 'cellm2')
554 550 self.check_ident('cellm2')
555 551
556 552 def test_cell_magic_class(self):
557 553 "Cell magics declared via a class"
558 554 @magics_class
559 555 class MyMagics(Magics):
560 556
561 557 @cell_magic
562 558 def cellm3(self, line, cell):
563 559 return line, cell
564 560
565 561 _ip.register_magics(MyMagics)
566 562 self.check_ident('cellm3')
567 563
568 564 def test_cell_magic_class2(self):
569 565 "Cell magics declared via a class, #2"
570 566 @magics_class
571 567 class MyMagics2(Magics):
572 568
573 569 @cell_magic('cellm4')
574 570 def cellm33(self, line, cell):
575 571 return line, cell
576 572
577 573 _ip.register_magics(MyMagics2)
578 574 self.check_ident('cellm4')
579 575 # Check that nothing is registered as 'cellm33'
580 576 c33 = _ip.find_cell_magic('cellm33')
581 577 nt.assert_equal(c33, None)
582 578
583 579 def test_file():
584 580 """Basic %%file"""
585 581 ip = get_ipython()
586 582 with TemporaryDirectory() as td:
587 583 fname = os.path.join(td, 'file1')
588 584 ip.run_cell_magic("file", fname, u'\n'.join([
589 585 'line1',
590 586 'line2',
591 587 ]))
592 588 with open(fname) as f:
593 589 s = f.read()
594 590 nt.assert_in('line1\n', s)
595 591 nt.assert_in('line2', s)
596 592
597 593 def test_file_var_expand():
598 594 """%%file $filename"""
599 595 ip = get_ipython()
600 596 with TemporaryDirectory() as td:
601 597 fname = os.path.join(td, 'file1')
602 598 ip.user_ns['filename'] = fname
603 599 ip.run_cell_magic("file", '$filename', u'\n'.join([
604 600 'line1',
605 601 'line2',
606 602 ]))
607 603 with open(fname) as f:
608 604 s = f.read()
609 605 nt.assert_in('line1\n', s)
610 606 nt.assert_in('line2', s)
611 607
612 608 def test_file_unicode():
613 609 """%%file with unicode cell"""
614 610 ip = get_ipython()
615 611 with TemporaryDirectory() as td:
616 612 fname = os.path.join(td, 'file1')
617 613 ip.run_cell_magic("file", fname, u'\n'.join([
618 614 u'linΓ©1',
619 615 u'linΓ©2',
620 616 ]))
621 617 with io.open(fname, encoding='utf-8') as f:
622 618 s = f.read()
623 619 nt.assert_in(u'linΓ©1\n', s)
624 620 nt.assert_in(u'linΓ©2', s)
625 621
626 622 def test_file_amend():
627 623 """%%file -a amends files"""
628 624 ip = get_ipython()
629 625 with TemporaryDirectory() as td:
630 626 fname = os.path.join(td, 'file2')
631 627 ip.run_cell_magic("file", fname, u'\n'.join([
632 628 'line1',
633 629 'line2',
634 630 ]))
635 631 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
636 632 'line3',
637 633 'line4',
638 634 ]))
639 635 with open(fname) as f:
640 636 s = f.read()
641 637 nt.assert_in('line1\n', s)
642 638 nt.assert_in('line3\n', s)
643 639
644 640
645 641 def test_script_config():
646 642 ip = get_ipython()
647 643 ip.config.ScriptMagics.script_magics = ['whoda']
648 644 sm = script.ScriptMagics(shell=ip)
649 645 nt.assert_in('whoda', sm.magics['cell'])
650 646
651 647 @dec.skip_win32
652 648 def test_script_out():
653 649 ip = get_ipython()
654 650 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
655 651 nt.assert_equal(ip.user_ns['output'], 'hi\n')
656 652
657 653 @dec.skip_win32
658 654 def test_script_err():
659 655 ip = get_ipython()
660 656 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
661 657 nt.assert_equal(ip.user_ns['error'], 'hello\n')
662 658
663 659 @dec.skip_win32
664 660 def test_script_out_err():
665 661 ip = get_ipython()
666 662 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
667 663 nt.assert_equal(ip.user_ns['output'], 'hi\n')
668 664 nt.assert_equal(ip.user_ns['error'], 'hello\n')
669 665
670 666 @dec.skip_win32
671 667 def test_script_bg_out():
672 668 ip = get_ipython()
673 669 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
674 670 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
675 671
676 672 @dec.skip_win32
677 673 def test_script_bg_err():
678 674 ip = get_ipython()
679 675 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
680 676 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
681 677
682 678 @dec.skip_win32
683 679 def test_script_bg_out_err():
684 680 ip = get_ipython()
685 681 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
686 682 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
687 683 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
688 684
689 685 def test_script_defaults():
690 686 ip = get_ipython()
691 687 for cmd in ['sh', 'bash', 'perl', 'ruby']:
692 688 try:
693 689 find_cmd(cmd)
694 690 except Exception:
695 691 pass
696 692 else:
697 693 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
698 694
699 695
700 696 @magics_class
701 697 class FooFoo(Magics):
702 698 """class with both %foo and %%foo magics"""
703 699 @line_magic('foo')
704 700 def line_foo(self, line):
705 701 "I am line foo"
706 702 pass
707 703
708 704 @cell_magic("foo")
709 705 def cell_foo(self, line, cell):
710 706 "I am cell foo, not line foo"
711 707 pass
712 708
713 709 def test_line_cell_info():
714 710 """%%foo and %foo magics are distinguishable to inspect"""
715 711 ip = get_ipython()
716 712 ip.magics_manager.register(FooFoo)
717 713 oinfo = ip.object_inspect('foo')
718 714 nt.assert_true(oinfo['found'])
719 715 nt.assert_true(oinfo['ismagic'])
720 716
721 717 oinfo = ip.object_inspect('%%foo')
722 718 nt.assert_true(oinfo['found'])
723 719 nt.assert_true(oinfo['ismagic'])
724 720 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
725 721
726 722 oinfo = ip.object_inspect('%foo')
727 723 nt.assert_true(oinfo['found'])
728 724 nt.assert_true(oinfo['ismagic'])
729 725 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
730 726
731 727 def test_multiple_magics():
732 728 ip = get_ipython()
733 729 foo1 = FooFoo(ip)
734 730 foo2 = FooFoo(ip)
735 731 mm = ip.magics_manager
736 732 mm.register(foo1)
737 733 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
738 734 mm.register(foo2)
739 735 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
740 736
741 737 def test_alias_magic():
742 738 """Test %alias_magic."""
743 739 ip = get_ipython()
744 740 mm = ip.magics_manager
745 741
746 742 # Basic operation: both cell and line magics are created, if possible.
747 743 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
748 744 nt.assert_true('timeit_alias' in mm.magics['line'])
749 745 nt.assert_true('timeit_alias' in mm.magics['cell'])
750 746
751 747 # --cell is specified, line magic not created.
752 748 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
753 749 nt.assert_false('timeit_cell_alias' in mm.magics['line'])
754 750 nt.assert_true('timeit_cell_alias' in mm.magics['cell'])
755 751
756 752 # Test that line alias is created successfully.
757 753 ip.run_line_magic('alias_magic', '--line env_alias env')
758 754 nt.assert_equal(ip.run_line_magic('env', ''),
759 755 ip.run_line_magic('env_alias', ''))
760 756
761 757 def test_save():
762 758 """Test %save."""
763 759 ip = get_ipython()
764 760 ip.history_manager.reset() # Clear any existing history.
765 761 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
766 762 for i, cmd in enumerate(cmds, start=1):
767 763 ip.history_manager.store_inputs(i, cmd)
768 764 with TemporaryDirectory() as tmpdir:
769 765 file = os.path.join(tmpdir, "testsave.py")
770 766 ip.run_line_magic("save", "%s 1-10" % file)
771 767 with open(file) as f:
772 768 content = f.read()
773 769 nt.assert_equal(content.count(cmds[0]), 1)
774 770 nt.assert_true('coding: utf-8' in content)
775 771 ip.run_line_magic("save", "-a %s 1-10" % file)
776 772 with open(file) as f:
777 773 content = f.read()
778 774 nt.assert_equal(content.count(cmds[0]), 2)
779 775 nt.assert_true('coding: utf-8' in content)
780 776
781 777
782 778 def test_store():
783 779 """Test %store."""
784 780 ip = get_ipython()
785 781 ip.run_line_magic('load_ext', 'storemagic')
786 782
787 783 # make sure the storage is empty
788 784 ip.run_line_magic('store', '-z')
789 785 ip.user_ns['var'] = 42
790 786 ip.run_line_magic('store', 'var')
791 787 ip.user_ns['var'] = 39
792 788 ip.run_line_magic('store', '-r')
793 789 nt.assert_equal(ip.user_ns['var'], 42)
794 790
795 791 ip.run_line_magic('store', '-d var')
796 792 ip.user_ns['var'] = 39
797 793 ip.run_line_magic('store' , '-r')
798 794 nt.assert_equal(ip.user_ns['var'], 39)
@@ -1,110 +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 9 from IPython.testing import tools as tt, 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 ('>>> 2+2','2+2'),
24 ('>>> # This is a comment\n'
25 '... 2+2',
26 '# This is a comment\n'
27 '2+2'),
28 # Some IPython input
29 ('In [1]: 1', '1'),
30 ('In [2]: for i in range(5):\n'
31 ' ...: print i,',
32 'for i in range(5):\n'
33 ' print i,'),
34 23 ]
35 24
36 25 for raw, correct in pairs:
37 26 yield nt.assert_equal(ip.prefilter(raw), correct)
38 27
39 28
40 29 @dec.parametric
41 30 def test_autocall_binops():
42 31 """See https://github.com/ipython/ipython/issues/81"""
43 32 ip.magic('autocall 2')
44 33 f = lambda x: x
45 34 ip.user_ns['f'] = f
46 35 try:
47 36 yield nt.assert_equal(ip.prefilter('f 1'),'f(1)')
48 37 for t in ['f +1', 'f -1']:
49 38 yield nt.assert_equal(ip.prefilter(t), t)
50 39
51 40 # Run tests again with a more permissive exclude_regexp, which will
52 41 # allow transformation of binary operations ('f -1' -> 'f(-1)').
53 42 pm = ip.prefilter_manager
54 43 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
55 44 config=pm.config)
56 45 try:
57 46 ac.priority = 1
58 47 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
59 48 pm.sort_checkers()
60 49
61 50 yield nt.assert_equal(ip.prefilter('f -1'), 'f(-1)')
62 51 yield nt.assert_equal(ip.prefilter('f +1'), 'f(+1)')
63 52 finally:
64 53 pm.unregister_checker(ac)
65 54 finally:
66 55 ip.magic('autocall 0')
67 56 del ip.user_ns['f']
68 57
69 58
70 59 @dec.parametric
71 60 def test_issue_114():
72 61 """Check that multiline string literals don't expand as magic
73 62 see http://github.com/ipython/ipython/issues/114"""
74 63
75 64 template = '"""\n%s\n"""'
76 65 # Store the current value of multi_line_specials and turn it off before
77 66 # running test, since it could be true (case in which the test doesn't make
78 67 # sense, as multiline string literals *will* expand as magic in that case).
79 68 msp = ip.prefilter_manager.multi_line_specials
80 69 ip.prefilter_manager.multi_line_specials = False
81 70 try:
82 71 for mgk in ip.magics_manager.lsmagic()['line']:
83 72 raw = template % mgk
84 73 yield nt.assert_equal(ip.prefilter(raw), raw)
85 74 finally:
86 75 ip.prefilter_manager.multi_line_specials = msp
87 76
88 77
89 78 def test_prefilter_attribute_errors():
90 79 """Capture exceptions thrown by user objects on attribute access.
91 80
92 81 See http://github.com/ipython/ipython/issues/988."""
93 82
94 83 class X(object):
95 84 def __getattr__(self, k):
96 85 raise ValueError('broken object')
97 86 def __call__(self, x):
98 87 return x
99 88
100 89 # Create a callable broken object
101 90 ip.user_ns['x'] = X()
102 91 ip.magic('autocall 2')
103 92 try:
104 93 # Even if x throws an attribute error when looking at its rewrite
105 94 # attribute, we should not crash. So the test here is simply making
106 95 # the prefilter call and not having an exception.
107 96 ip.prefilter('x 1')
108 97 finally:
109 98 del ip.user_ns['x']
110 99 ip.magic('autocall 0')
@@ -1,811 +1,807 b''
1 1 """Nose Plugin that supports IPython doctests.
2 2
3 3 Limitations:
4 4
5 5 - When generating examples for use as doctests, make sure that you have
6 6 pretty-printing OFF. This can be done either by setting the
7 7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
8 8 by interactively disabling it with %Pprint. This is required so that IPython
9 9 output matches that of normal Python, which is used by doctest for internal
10 10 execution.
11 11
12 12 - Do not rely on specific prompt numbers for results (such as using
13 13 '_34==True', for example). For IPython tests run via an external process the
14 14 prompt numbers may be different, and IPython tests run as normal python code
15 15 won't even have these special _NN variables set at all.
16 16 """
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Module imports
20 20
21 21 # From the standard library
22 22 import __builtin__ as builtin_mod
23 23 import commands
24 24 import doctest
25 25 import inspect
26 26 import logging
27 27 import os
28 28 import re
29 29 import sys
30 30 import traceback
31 31 import unittest
32 32
33 33 from inspect import getmodule
34 34 from StringIO import StringIO
35 35
36 36 # We are overriding the default doctest runner, so we need to import a few
37 37 # things from doctest directly
38 38 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
39 39 _unittest_reportflags, DocTestRunner,
40 40 _extract_future_flags, pdb, _OutputRedirectingPdb,
41 41 _exception_traceback,
42 42 linecache)
43 43
44 44 # Third-party modules
45 45 import nose.core
46 46
47 47 from nose.plugins import doctests, Plugin
48 48 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
49 49
50 # Our own imports
51
52 # We're temporarily using TerminalMagics.cleanup_input() until the functionality
53 # is moved into core.
54 from IPython.frontend.terminal.interactiveshell import TerminalMagics
55
50 56 #-----------------------------------------------------------------------------
51 57 # Module globals and other constants
52 58 #-----------------------------------------------------------------------------
53 59
54 60 log = logging.getLogger(__name__)
55 61
56 62
57 63 #-----------------------------------------------------------------------------
58 64 # Classes and functions
59 65 #-----------------------------------------------------------------------------
60 66
61 67 def is_extension_module(filename):
62 68 """Return whether the given filename is an extension module.
63 69
64 70 This simply checks that the extension is either .so or .pyd.
65 71 """
66 72 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
67 73
68 74
69 75 class DocTestSkip(object):
70 76 """Object wrapper for doctests to be skipped."""
71 77
72 78 ds_skip = """Doctest to skip.
73 79 >>> 1 #doctest: +SKIP
74 80 """
75 81
76 82 def __init__(self,obj):
77 83 self.obj = obj
78 84
79 85 def __getattribute__(self,key):
80 86 if key == '__doc__':
81 87 return DocTestSkip.ds_skip
82 88 else:
83 89 return getattr(object.__getattribute__(self,'obj'),key)
84 90
85 91 # Modified version of the one in the stdlib, that fixes a python bug (doctests
86 92 # not found in extension modules, http://bugs.python.org/issue3158)
87 93 class DocTestFinder(doctest.DocTestFinder):
88 94
89 95 def _from_module(self, module, object):
90 96 """
91 97 Return true if the given object is defined in the given
92 98 module.
93 99 """
94 100 if module is None:
95 101 return True
96 102 elif inspect.isfunction(object):
97 103 return module.__dict__ is object.func_globals
98 104 elif inspect.isbuiltin(object):
99 105 return module.__name__ == object.__module__
100 106 elif inspect.isclass(object):
101 107 return module.__name__ == object.__module__
102 108 elif inspect.ismethod(object):
103 109 # This one may be a bug in cython that fails to correctly set the
104 110 # __module__ attribute of methods, but since the same error is easy
105 111 # to make by extension code writers, having this safety in place
106 112 # isn't such a bad idea
107 113 return module.__name__ == object.im_class.__module__
108 114 elif inspect.getmodule(object) is not None:
109 115 return module is inspect.getmodule(object)
110 116 elif hasattr(object, '__module__'):
111 117 return module.__name__ == object.__module__
112 118 elif isinstance(object, property):
113 119 return True # [XX] no way not be sure.
114 120 else:
115 121 raise ValueError("object must be a class or function")
116 122
117 123 def _find(self, tests, obj, name, module, source_lines, globs, seen):
118 124 """
119 125 Find tests for the given object and any contained objects, and
120 126 add them to `tests`.
121 127 """
122 128 #print '_find for:', obj, name, module # dbg
123 129 if hasattr(obj,"skip_doctest"):
124 130 #print 'SKIPPING DOCTEST FOR:',obj # dbg
125 131 obj = DocTestSkip(obj)
126 132
127 133 doctest.DocTestFinder._find(self,tests, obj, name, module,
128 134 source_lines, globs, seen)
129 135
130 136 # Below we re-run pieces of the above method with manual modifications,
131 137 # because the original code is buggy and fails to correctly identify
132 138 # doctests in extension modules.
133 139
134 140 # Local shorthands
135 141 from inspect import isroutine, isclass, ismodule
136 142
137 143 # Look for tests in a module's contained objects.
138 144 if inspect.ismodule(obj) and self._recurse:
139 145 for valname, val in obj.__dict__.items():
140 146 valname1 = '%s.%s' % (name, valname)
141 147 if ( (isroutine(val) or isclass(val))
142 148 and self._from_module(module, val) ):
143 149
144 150 self._find(tests, val, valname1, module, source_lines,
145 151 globs, seen)
146 152
147 153 # Look for tests in a class's contained objects.
148 154 if inspect.isclass(obj) and self._recurse:
149 155 #print 'RECURSE into class:',obj # dbg
150 156 for valname, val in obj.__dict__.items():
151 157 # Special handling for staticmethod/classmethod.
152 158 if isinstance(val, staticmethod):
153 159 val = getattr(obj, valname)
154 160 if isinstance(val, classmethod):
155 161 val = getattr(obj, valname).im_func
156 162
157 163 # Recurse to methods, properties, and nested classes.
158 164 if ((inspect.isfunction(val) or inspect.isclass(val) or
159 165 inspect.ismethod(val) or
160 166 isinstance(val, property)) and
161 167 self._from_module(module, val)):
162 168 valname = '%s.%s' % (name, valname)
163 169 self._find(tests, val, valname, module, source_lines,
164 170 globs, seen)
165 171
166 172
167 173 class IPDoctestOutputChecker(doctest.OutputChecker):
168 174 """Second-chance checker with support for random tests.
169 175
170 176 If the default comparison doesn't pass, this checker looks in the expected
171 177 output string for flags that tell us to ignore the output.
172 178 """
173 179
174 180 random_re = re.compile(r'#\s*random\s+')
175 181
176 182 def check_output(self, want, got, optionflags):
177 183 """Check output, accepting special markers embedded in the output.
178 184
179 185 If the output didn't pass the default validation but the special string
180 186 '#random' is included, we accept it."""
181 187
182 188 # Let the original tester verify first, in case people have valid tests
183 189 # that happen to have a comment saying '#random' embedded in.
184 190 ret = doctest.OutputChecker.check_output(self, want, got,
185 191 optionflags)
186 192 if not ret and self.random_re.search(want):
187 193 #print >> sys.stderr, 'RANDOM OK:',want # dbg
188 194 return True
189 195
190 196 return ret
191 197
192 198
193 199 class DocTestCase(doctests.DocTestCase):
194 200 """Proxy for DocTestCase: provides an address() method that
195 201 returns the correct address for the doctest case. Otherwise
196 202 acts as a proxy to the test case. To provide hints for address(),
197 203 an obj may also be passed -- this will be used as the test object
198 204 for purposes of determining the test address, if it is provided.
199 205 """
200 206
201 207 # Note: this method was taken from numpy's nosetester module.
202 208
203 209 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
204 210 # its constructor that blocks non-default arguments from being passed
205 211 # down into doctest.DocTestCase
206 212
207 213 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
208 214 checker=None, obj=None, result_var='_'):
209 215 self._result_var = result_var
210 216 doctests.DocTestCase.__init__(self, test,
211 217 optionflags=optionflags,
212 218 setUp=setUp, tearDown=tearDown,
213 219 checker=checker)
214 220 # Now we must actually copy the original constructor from the stdlib
215 221 # doctest class, because we can't call it directly and a bug in nose
216 222 # means it never gets passed the right arguments.
217 223
218 224 self._dt_optionflags = optionflags
219 225 self._dt_checker = checker
220 226 self._dt_test = test
221 227 self._dt_test_globs_ori = test.globs
222 228 self._dt_setUp = setUp
223 229 self._dt_tearDown = tearDown
224 230
225 231 # XXX - store this runner once in the object!
226 232 runner = IPDocTestRunner(optionflags=optionflags,
227 233 checker=checker, verbose=False)
228 234 self._dt_runner = runner
229 235
230 236
231 237 # Each doctest should remember the directory it was loaded from, so
232 238 # things like %run work without too many contortions
233 239 self._ori_dir = os.path.dirname(test.filename)
234 240
235 241 # Modified runTest from the default stdlib
236 242 def runTest(self):
237 243 test = self._dt_test
238 244 runner = self._dt_runner
239 245
240 246 old = sys.stdout
241 247 new = StringIO()
242 248 optionflags = self._dt_optionflags
243 249
244 250 if not (optionflags & REPORTING_FLAGS):
245 251 # The option flags don't include any reporting flags,
246 252 # so add the default reporting flags
247 253 optionflags |= _unittest_reportflags
248 254
249 255 try:
250 256 # Save our current directory and switch out to the one where the
251 257 # test was originally created, in case another doctest did a
252 258 # directory change. We'll restore this in the finally clause.
253 259 curdir = os.getcwdu()
254 260 #print 'runTest in dir:', self._ori_dir # dbg
255 261 os.chdir(self._ori_dir)
256 262
257 263 runner.DIVIDER = "-"*70
258 264 failures, tries = runner.run(test,out=new.write,
259 265 clear_globs=False)
260 266 finally:
261 267 sys.stdout = old
262 268 os.chdir(curdir)
263 269
264 270 if failures:
265 271 raise self.failureException(self.format_failure(new.getvalue()))
266 272
267 273 def setUp(self):
268 274 """Modified test setup that syncs with ipython namespace"""
269 275 #print "setUp test", self._dt_test.examples # dbg
270 276 if isinstance(self._dt_test.examples[0], IPExample):
271 277 # for IPython examples *only*, we swap the globals with the ipython
272 278 # namespace, after updating it with the globals (which doctest
273 279 # fills with the necessary info from the module being tested).
274 280 self.user_ns_orig = {}
275 281 self.user_ns_orig.update(_ip.user_ns)
276 282 _ip.user_ns.update(self._dt_test.globs)
277 283 # We must remove the _ key in the namespace, so that Python's
278 284 # doctest code sets it naturally
279 285 _ip.user_ns.pop('_', None)
280 286 _ip.user_ns['__builtins__'] = builtin_mod
281 287 self._dt_test.globs = _ip.user_ns
282 288
283 289 super(DocTestCase, self).setUp()
284 290
285 291 def tearDown(self):
286 292
287 293 # Undo the test.globs reassignment we made, so that the parent class
288 294 # teardown doesn't destroy the ipython namespace
289 295 if isinstance(self._dt_test.examples[0], IPExample):
290 296 self._dt_test.globs = self._dt_test_globs_ori
291 297 _ip.user_ns.clear()
292 298 _ip.user_ns.update(self.user_ns_orig)
293 299
294 300 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
295 301 # it does look like one to me: its tearDown method tries to run
296 302 #
297 303 # delattr(__builtin__, self._result_var)
298 304 #
299 305 # without checking that the attribute really is there; it implicitly
300 306 # assumes it should have been set via displayhook. But if the
301 307 # displayhook was never called, this doesn't necessarily happen. I
302 308 # haven't been able to find a little self-contained example outside of
303 309 # ipython that would show the problem so I can report it to the nose
304 310 # team, but it does happen a lot in our code.
305 311 #
306 312 # So here, we just protect as narrowly as possible by trapping an
307 313 # attribute error whose message would be the name of self._result_var,
308 314 # and letting any other error propagate.
309 315 try:
310 316 super(DocTestCase, self).tearDown()
311 317 except AttributeError as exc:
312 318 if exc.args[0] != self._result_var:
313 319 raise
314 320
315 321
316 322 # A simple subclassing of the original with a different class name, so we can
317 323 # distinguish and treat differently IPython examples from pure python ones.
318 324 class IPExample(doctest.Example): pass
319 325
320 326
321 327 class IPExternalExample(doctest.Example):
322 328 """Doctest examples to be run in an external process."""
323 329
324 330 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
325 331 options=None):
326 332 # Parent constructor
327 333 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
328 334
329 335 # An EXTRA newline is needed to prevent pexpect hangs
330 336 self.source += '\n'
331 337
332 338
333 339 class IPDocTestParser(doctest.DocTestParser):
334 340 """
335 341 A class used to parse strings containing doctest examples.
336 342
337 343 Note: This is a version modified to properly recognize IPython input and
338 344 convert any IPython examples into valid Python ones.
339 345 """
340 346 # This regular expression is used to find doctest examples in a
341 347 # string. It defines three groups: `source` is the source code
342 348 # (including leading indentation and prompts); `indent` is the
343 349 # indentation of the first (PS1) line of the source code; and
344 350 # `want` is the expected output (including leading indentation).
345 351
346 352 # Classic Python prompts or default IPython ones
347 353 _PS1_PY = r'>>>'
348 354 _PS2_PY = r'\.\.\.'
349 355
350 356 _PS1_IP = r'In\ \[\d+\]:'
351 357 _PS2_IP = r'\ \ \ \.\.\.+:'
352 358
353 359 _RE_TPL = r'''
354 360 # Source consists of a PS1 line followed by zero or more PS2 lines.
355 361 (?P<source>
356 362 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
357 363 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
358 364 \n? # a newline
359 365 # Want consists of any non-blank lines that do not start with PS1.
360 366 (?P<want> (?:(?![ ]*$) # Not a blank line
361 367 (?![ ]*%s) # Not a line starting with PS1
362 368 (?![ ]*%s) # Not a line starting with PS2
363 369 .*$\n? # But any other line
364 370 )*)
365 371 '''
366 372
367 373 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
368 374 re.MULTILINE | re.VERBOSE)
369 375
370 376 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
371 377 re.MULTILINE | re.VERBOSE)
372 378
373 379 # Mark a test as being fully random. In this case, we simply append the
374 380 # random marker ('#random') to each individual example's output. This way
375 381 # we don't need to modify any other code.
376 382 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
377 383
378 384 # Mark tests to be executed in an external process - currently unsupported.
379 385 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
380 386
381 387 def ip2py(self,source):
382 388 """Convert input IPython source into valid Python."""
383 out = []
384 newline = out.append
385 #print 'IPSRC:\n',source,'\n###' # dbg
386 # The input source must be first stripped of all bracketing whitespace
387 # and turned into lines, so it looks to the parser like regular user
388 # input
389 for lnum,line in enumerate(source.strip().splitlines()):
390 newline(_ip.prefilter(line,lnum>0))
391 newline('') # ensure a closing newline, needed by doctest
392 #print "PYSRC:", '\n'.join(out) # dbg
393 return '\n'.join(out)
389 return TerminalMagics(_ip).cleanup_input(source)
394 390
395 391 def parse(self, string, name='<string>'):
396 392 """
397 393 Divide the given string into examples and intervening text,
398 394 and return them as a list of alternating Examples and strings.
399 395 Line numbers for the Examples are 0-based. The optional
400 396 argument `name` is a name identifying this string, and is only
401 397 used for error messages.
402 398 """
403 399
404 400 #print 'Parse string:\n',string # dbg
405 401
406 402 string = string.expandtabs()
407 403 # If all lines begin with the same indentation, then strip it.
408 404 min_indent = self._min_indent(string)
409 405 if min_indent > 0:
410 406 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
411 407
412 408 output = []
413 409 charno, lineno = 0, 0
414 410
415 411 # We make 'all random' tests by adding the '# random' mark to every
416 412 # block of output in the test.
417 413 if self._RANDOM_TEST.search(string):
418 414 random_marker = '\n# random'
419 415 else:
420 416 random_marker = ''
421 417
422 418 # Whether to convert the input from ipython to python syntax
423 419 ip2py = False
424 420 # Find all doctest examples in the string. First, try them as Python
425 421 # examples, then as IPython ones
426 422 terms = list(self._EXAMPLE_RE_PY.finditer(string))
427 423 if terms:
428 424 # Normal Python example
429 425 #print '-'*70 # dbg
430 426 #print 'PyExample, Source:\n',string # dbg
431 427 #print '-'*70 # dbg
432 428 Example = doctest.Example
433 429 else:
434 430 # It's an ipython example. Note that IPExamples are run
435 431 # in-process, so their syntax must be turned into valid python.
436 432 # IPExternalExamples are run out-of-process (via pexpect) so they
437 433 # don't need any filtering (a real ipython will be executing them).
438 434 terms = list(self._EXAMPLE_RE_IP.finditer(string))
439 435 if self._EXTERNAL_IP.search(string):
440 436 #print '-'*70 # dbg
441 437 #print 'IPExternalExample, Source:\n',string # dbg
442 438 #print '-'*70 # dbg
443 439 Example = IPExternalExample
444 440 else:
445 441 #print '-'*70 # dbg
446 442 #print 'IPExample, Source:\n',string # dbg
447 443 #print '-'*70 # dbg
448 444 Example = IPExample
449 445 ip2py = True
450 446
451 447 for m in terms:
452 448 # Add the pre-example text to `output`.
453 449 output.append(string[charno:m.start()])
454 450 # Update lineno (lines before this example)
455 451 lineno += string.count('\n', charno, m.start())
456 452 # Extract info from the regexp match.
457 453 (source, options, want, exc_msg) = \
458 454 self._parse_example(m, name, lineno,ip2py)
459 455
460 456 # Append the random-output marker (it defaults to empty in most
461 457 # cases, it's only non-empty for 'all-random' tests):
462 458 want += random_marker
463 459
464 460 if Example is IPExternalExample:
465 461 options[doctest.NORMALIZE_WHITESPACE] = True
466 462 want += '\n'
467 463
468 464 # Create an Example, and add it to the list.
469 465 if not self._IS_BLANK_OR_COMMENT(source):
470 466 output.append(Example(source, want, exc_msg,
471 467 lineno=lineno,
472 468 indent=min_indent+len(m.group('indent')),
473 469 options=options))
474 470 # Update lineno (lines inside this example)
475 471 lineno += string.count('\n', m.start(), m.end())
476 472 # Update charno.
477 473 charno = m.end()
478 474 # Add any remaining post-example text to `output`.
479 475 output.append(string[charno:])
480 476 return output
481 477
482 478 def _parse_example(self, m, name, lineno,ip2py=False):
483 479 """
484 480 Given a regular expression match from `_EXAMPLE_RE` (`m`),
485 481 return a pair `(source, want)`, where `source` is the matched
486 482 example's source code (with prompts and indentation stripped);
487 483 and `want` is the example's expected output (with indentation
488 484 stripped).
489 485
490 486 `name` is the string's name, and `lineno` is the line number
491 487 where the example starts; both are used for error messages.
492 488
493 489 Optional:
494 490 `ip2py`: if true, filter the input via IPython to convert the syntax
495 491 into valid python.
496 492 """
497 493
498 494 # Get the example's indentation level.
499 495 indent = len(m.group('indent'))
500 496
501 497 # Divide source into lines; check that they're properly
502 498 # indented; and then strip their indentation & prompts.
503 499 source_lines = m.group('source').split('\n')
504 500
505 501 # We're using variable-length input prompts
506 502 ps1 = m.group('ps1')
507 503 ps2 = m.group('ps2')
508 504 ps1_len = len(ps1)
509 505
510 506 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
511 507 if ps2:
512 508 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
513 509
514 510 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
515 511
516 512 if ip2py:
517 513 # Convert source input from IPython into valid Python syntax
518 514 source = self.ip2py(source)
519 515
520 516 # Divide want into lines; check that it's properly indented; and
521 517 # then strip the indentation. Spaces before the last newline should
522 518 # be preserved, so plain rstrip() isn't good enough.
523 519 want = m.group('want')
524 520 want_lines = want.split('\n')
525 521 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
526 522 del want_lines[-1] # forget final newline & spaces after it
527 523 self._check_prefix(want_lines, ' '*indent, name,
528 524 lineno + len(source_lines))
529 525
530 526 # Remove ipython output prompt that might be present in the first line
531 527 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
532 528
533 529 want = '\n'.join([wl[indent:] for wl in want_lines])
534 530
535 531 # If `want` contains a traceback message, then extract it.
536 532 m = self._EXCEPTION_RE.match(want)
537 533 if m:
538 534 exc_msg = m.group('msg')
539 535 else:
540 536 exc_msg = None
541 537
542 538 # Extract options from the source.
543 539 options = self._find_options(source, name, lineno)
544 540
545 541 return source, options, want, exc_msg
546 542
547 543 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
548 544 """
549 545 Given the lines of a source string (including prompts and
550 546 leading indentation), check to make sure that every prompt is
551 547 followed by a space character. If any line is not followed by
552 548 a space character, then raise ValueError.
553 549
554 550 Note: IPython-modified version which takes the input prompt length as a
555 551 parameter, so that prompts of variable length can be dealt with.
556 552 """
557 553 space_idx = indent+ps1_len
558 554 min_len = space_idx+1
559 555 for i, line in enumerate(lines):
560 556 if len(line) >= min_len and line[space_idx] != ' ':
561 557 raise ValueError('line %r of the docstring for %s '
562 558 'lacks blank after %s: %r' %
563 559 (lineno+i+1, name,
564 560 line[indent:space_idx], line))
565 561
566 562
567 563 SKIP = doctest.register_optionflag('SKIP')
568 564
569 565
570 566 class IPDocTestRunner(doctest.DocTestRunner,object):
571 567 """Test runner that synchronizes the IPython namespace with test globals.
572 568 """
573 569
574 570 def run(self, test, compileflags=None, out=None, clear_globs=True):
575 571
576 572 # Hack: ipython needs access to the execution context of the example,
577 573 # so that it can propagate user variables loaded by %run into
578 574 # test.globs. We put them here into our modified %run as a function
579 575 # attribute. Our new %run will then only make the namespace update
580 576 # when called (rather than unconconditionally updating test.globs here
581 577 # for all examples, most of which won't be calling %run anyway).
582 578 #_ip._ipdoctest_test_globs = test.globs
583 579 #_ip._ipdoctest_test_filename = test.filename
584 580
585 581 test.globs.update(_ip.user_ns)
586 582
587 583 return super(IPDocTestRunner,self).run(test,
588 584 compileflags,out,clear_globs)
589 585
590 586
591 587 class DocFileCase(doctest.DocFileCase):
592 588 """Overrides to provide filename
593 589 """
594 590 def address(self):
595 591 return (self._dt_test.filename, None, None)
596 592
597 593
598 594 class ExtensionDoctest(doctests.Doctest):
599 595 """Nose Plugin that supports doctests in extension modules.
600 596 """
601 597 name = 'extdoctest' # call nosetests with --with-extdoctest
602 598 enabled = True
603 599
604 600 def __init__(self,exclude_patterns=None):
605 601 """Create a new ExtensionDoctest plugin.
606 602
607 603 Parameters
608 604 ----------
609 605
610 606 exclude_patterns : sequence of strings, optional
611 607 These patterns are compiled as regular expressions, subsequently used
612 608 to exclude any filename which matches them from inclusion in the test
613 609 suite (using pattern.search(), NOT pattern.match() ).
614 610 """
615 611
616 612 if exclude_patterns is None:
617 613 exclude_patterns = []
618 614 self.exclude_patterns = map(re.compile,exclude_patterns)
619 615 doctests.Doctest.__init__(self)
620 616
621 617 def options(self, parser, env=os.environ):
622 618 Plugin.options(self, parser, env)
623 619 parser.add_option('--doctest-tests', action='store_true',
624 620 dest='doctest_tests',
625 621 default=env.get('NOSE_DOCTEST_TESTS',True),
626 622 help="Also look for doctests in test modules. "
627 623 "Note that classes, methods and functions should "
628 624 "have either doctests or non-doctest tests, "
629 625 "not both. [NOSE_DOCTEST_TESTS]")
630 626 parser.add_option('--doctest-extension', action="append",
631 627 dest="doctestExtension",
632 628 help="Also look for doctests in files with "
633 629 "this extension [NOSE_DOCTEST_EXTENSION]")
634 630 # Set the default as a list, if given in env; otherwise
635 631 # an additional value set on the command line will cause
636 632 # an error.
637 633 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
638 634 if env_setting is not None:
639 635 parser.set_defaults(doctestExtension=tolist(env_setting))
640 636
641 637
642 638 def configure(self, options, config):
643 639 Plugin.configure(self, options, config)
644 640 # Pull standard doctest plugin out of config; we will do doctesting
645 641 config.plugins.plugins = [p for p in config.plugins.plugins
646 642 if p.name != 'doctest']
647 643 self.doctest_tests = options.doctest_tests
648 644 self.extension = tolist(options.doctestExtension)
649 645
650 646 self.parser = doctest.DocTestParser()
651 647 self.finder = DocTestFinder()
652 648 self.checker = IPDoctestOutputChecker()
653 649 self.globs = None
654 650 self.extraglobs = None
655 651
656 652
657 653 def loadTestsFromExtensionModule(self,filename):
658 654 bpath,mod = os.path.split(filename)
659 655 modname = os.path.splitext(mod)[0]
660 656 try:
661 657 sys.path.append(bpath)
662 658 module = __import__(modname)
663 659 tests = list(self.loadTestsFromModule(module))
664 660 finally:
665 661 sys.path.pop()
666 662 return tests
667 663
668 664 # NOTE: the method below is almost a copy of the original one in nose, with
669 665 # a few modifications to control output checking.
670 666
671 667 def loadTestsFromModule(self, module):
672 668 #print '*** ipdoctest - lTM',module # dbg
673 669
674 670 if not self.matches(module.__name__):
675 671 log.debug("Doctest doesn't want module %s", module)
676 672 return
677 673
678 674 tests = self.finder.find(module,globs=self.globs,
679 675 extraglobs=self.extraglobs)
680 676 if not tests:
681 677 return
682 678
683 679 # always use whitespace and ellipsis options
684 680 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
685 681
686 682 tests.sort()
687 683 module_file = module.__file__
688 684 if module_file[-4:] in ('.pyc', '.pyo'):
689 685 module_file = module_file[:-1]
690 686 for test in tests:
691 687 if not test.examples:
692 688 continue
693 689 if not test.filename:
694 690 test.filename = module_file
695 691
696 692 yield DocTestCase(test,
697 693 optionflags=optionflags,
698 694 checker=self.checker)
699 695
700 696
701 697 def loadTestsFromFile(self, filename):
702 698 #print "ipdoctest - from file", filename # dbg
703 699 if is_extension_module(filename):
704 700 for t in self.loadTestsFromExtensionModule(filename):
705 701 yield t
706 702 else:
707 703 if self.extension and anyp(filename.endswith, self.extension):
708 704 name = os.path.basename(filename)
709 705 dh = open(filename)
710 706 try:
711 707 doc = dh.read()
712 708 finally:
713 709 dh.close()
714 710 test = self.parser.get_doctest(
715 711 doc, globs={'__file__': filename}, name=name,
716 712 filename=filename, lineno=0)
717 713 if test.examples:
718 714 #print 'FileCase:',test.examples # dbg
719 715 yield DocFileCase(test)
720 716 else:
721 717 yield False # no tests to load
722 718
723 719 def wantFile(self,filename):
724 720 """Return whether the given filename should be scanned for tests.
725 721
726 722 Modified version that accepts extension modules as valid containers for
727 723 doctests.
728 724 """
729 725 #print '*** ipdoctest- wantFile:',filename # dbg
730 726
731 727 for pat in self.exclude_patterns:
732 728 if pat.search(filename):
733 729 # print '###>>> SKIP:',filename # dbg
734 730 return False
735 731
736 732 if is_extension_module(filename):
737 733 return True
738 734 else:
739 735 return doctests.Doctest.wantFile(self,filename)
740 736
741 737 def wantDirectory(self, directory):
742 738 """Return whether the given directory should be scanned for tests.
743 739
744 740 Modified version that supports exclusions.
745 741 """
746 742
747 743 for pat in self.exclude_patterns:
748 744 if pat.search(directory):
749 745 return False
750 746 return True
751 747
752 748
753 749 class IPythonDoctest(ExtensionDoctest):
754 750 """Nose Plugin that supports doctests in extension modules.
755 751 """
756 752 name = 'ipdoctest' # call nosetests with --with-ipdoctest
757 753 enabled = True
758 754
759 755 def makeTest(self, obj, parent):
760 756 """Look for doctests in the given object, which will be a
761 757 function, method or class.
762 758 """
763 759 #print 'Plugin analyzing:', obj, parent # dbg
764 760 # always use whitespace and ellipsis options
765 761 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
766 762
767 763 doctests = self.finder.find(obj, module=getmodule(parent))
768 764 if doctests:
769 765 for test in doctests:
770 766 if len(test.examples) == 0:
771 767 continue
772 768
773 769 yield DocTestCase(test, obj=obj,
774 770 optionflags=optionflags,
775 771 checker=self.checker)
776 772
777 773 def options(self, parser, env=os.environ):
778 774 #print "Options for nose plugin:", self.name # dbg
779 775 Plugin.options(self, parser, env)
780 776 parser.add_option('--ipdoctest-tests', action='store_true',
781 777 dest='ipdoctest_tests',
782 778 default=env.get('NOSE_IPDOCTEST_TESTS',True),
783 779 help="Also look for doctests in test modules. "
784 780 "Note that classes, methods and functions should "
785 781 "have either doctests or non-doctest tests, "
786 782 "not both. [NOSE_IPDOCTEST_TESTS]")
787 783 parser.add_option('--ipdoctest-extension', action="append",
788 784 dest="ipdoctest_extension",
789 785 help="Also look for doctests in files with "
790 786 "this extension [NOSE_IPDOCTEST_EXTENSION]")
791 787 # Set the default as a list, if given in env; otherwise
792 788 # an additional value set on the command line will cause
793 789 # an error.
794 790 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
795 791 if env_setting is not None:
796 792 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
797 793
798 794 def configure(self, options, config):
799 795 #print "Configuring nose plugin:", self.name # dbg
800 796 Plugin.configure(self, options, config)
801 797 # Pull standard doctest plugin out of config; we will do doctesting
802 798 config.plugins.plugins = [p for p in config.plugins.plugins
803 799 if p.name != 'doctest']
804 800 self.doctest_tests = options.ipdoctest_tests
805 801 self.extension = tolist(options.ipdoctest_extension)
806 802
807 803 self.parser = IPDocTestParser()
808 804 self.finder = DocTestFinder(parser=self.parser)
809 805 self.checker = IPDoctestOutputChecker()
810 806 self.globs = None
811 807 self.extraglobs = None
General Comments 0
You need to be logged in to leave comments. Login now