##// END OF EJS Templates
conform to pep 3110...
Matthias BUSSONNIER -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,696 +1,696 b''
1 1 """A simple configuration system.
2 2
3 3 Authors
4 4 -------
5 5 * Brian Granger
6 6 * Fernando Perez
7 7 * Min RK
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2008-2011 The IPython Development Team
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 21 import __builtin__ as builtin_mod
22 22 import os
23 23 import re
24 24 import sys
25 25
26 26 from IPython.external import argparse
27 27 from IPython.utils.path import filefind, get_ipython_dir
28 28 from IPython.utils import py3compat, text, warn
29 29 from IPython.utils.encoding import DEFAULT_ENCODING
30 30
31 31 #-----------------------------------------------------------------------------
32 32 # Exceptions
33 33 #-----------------------------------------------------------------------------
34 34
35 35
36 36 class ConfigError(Exception):
37 37 pass
38 38
39 39 class ConfigLoaderError(ConfigError):
40 40 pass
41 41
42 42 class ConfigFileNotFound(ConfigError):
43 43 pass
44 44
45 45 class ArgumentError(ConfigLoaderError):
46 46 pass
47 47
48 48 #-----------------------------------------------------------------------------
49 49 # Argparse fix
50 50 #-----------------------------------------------------------------------------
51 51
52 52 # Unfortunately argparse by default prints help messages to stderr instead of
53 53 # stdout. This makes it annoying to capture long help screens at the command
54 54 # line, since one must know how to pipe stderr, which many users don't know how
55 55 # to do. So we override the print_help method with one that defaults to
56 56 # stdout and use our class instead.
57 57
58 58 class ArgumentParser(argparse.ArgumentParser):
59 59 """Simple argparse subclass that prints help to stdout by default."""
60 60
61 61 def print_help(self, file=None):
62 62 if file is None:
63 63 file = sys.stdout
64 64 return super(ArgumentParser, self).print_help(file)
65 65
66 66 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
67 67
68 68 #-----------------------------------------------------------------------------
69 69 # Config class for holding config information
70 70 #-----------------------------------------------------------------------------
71 71
72 72
73 73 class Config(dict):
74 74 """An attribute based dict that can do smart merges."""
75 75
76 76 def __init__(self, *args, **kwds):
77 77 dict.__init__(self, *args, **kwds)
78 78 # This sets self.__dict__ = self, but it has to be done this way
79 79 # because we are also overriding __setattr__.
80 80 dict.__setattr__(self, '__dict__', self)
81 81
82 82 def _merge(self, other):
83 83 to_update = {}
84 84 for k, v in other.iteritems():
85 85 if not self.has_key(k):
86 86 to_update[k] = v
87 87 else: # I have this key
88 88 if isinstance(v, Config):
89 89 # Recursively merge common sub Configs
90 90 self[k]._merge(v)
91 91 else:
92 92 # Plain updates for non-Configs
93 93 to_update[k] = v
94 94
95 95 self.update(to_update)
96 96
97 97 def _is_section_key(self, key):
98 98 if key[0].upper()==key[0] and not key.startswith('_'):
99 99 return True
100 100 else:
101 101 return False
102 102
103 103 def __contains__(self, key):
104 104 if self._is_section_key(key):
105 105 return True
106 106 else:
107 107 return super(Config, self).__contains__(key)
108 108 # .has_key is deprecated for dictionaries.
109 109 has_key = __contains__
110 110
111 111 def _has_section(self, key):
112 112 if self._is_section_key(key):
113 113 if super(Config, self).__contains__(key):
114 114 return True
115 115 return False
116 116
117 117 def copy(self):
118 118 return type(self)(dict.copy(self))
119 119
120 120 def __copy__(self):
121 121 return self.copy()
122 122
123 123 def __deepcopy__(self, memo):
124 124 import copy
125 125 return type(self)(copy.deepcopy(self.items()))
126 126
127 127 def __getitem__(self, key):
128 128 # We cannot use directly self._is_section_key, because it triggers
129 129 # infinite recursion on top of PyPy. Instead, we manually fish the
130 130 # bound method.
131 131 is_section_key = self.__class__._is_section_key.__get__(self)
132 132
133 133 # Because we use this for an exec namespace, we need to delegate
134 134 # the lookup of names in __builtin__ to itself. This means
135 135 # that you can't have section or attribute names that are
136 136 # builtins.
137 137 try:
138 138 return getattr(builtin_mod, key)
139 139 except AttributeError:
140 140 pass
141 141 if is_section_key(key):
142 142 try:
143 143 return dict.__getitem__(self, key)
144 144 except KeyError:
145 145 c = Config()
146 146 dict.__setitem__(self, key, c)
147 147 return c
148 148 else:
149 149 return dict.__getitem__(self, key)
150 150
151 151 def __setitem__(self, key, value):
152 152 # Don't allow names in __builtin__ to be modified.
153 153 if hasattr(builtin_mod, key):
154 154 raise ConfigError('Config variable names cannot have the same name '
155 155 'as a Python builtin: %s' % key)
156 156 if self._is_section_key(key):
157 157 if not isinstance(value, Config):
158 158 raise ValueError('values whose keys begin with an uppercase '
159 159 'char must be Config instances: %r, %r' % (key, value))
160 160 else:
161 161 dict.__setitem__(self, key, value)
162 162
163 163 def __getattr__(self, key):
164 164 try:
165 165 return self.__getitem__(key)
166 except KeyError, e:
166 except KeyError as e:
167 167 raise AttributeError(e)
168 168
169 169 def __setattr__(self, key, value):
170 170 try:
171 171 self.__setitem__(key, value)
172 except KeyError, e:
172 except KeyError as e:
173 173 raise AttributeError(e)
174 174
175 175 def __delattr__(self, key):
176 176 try:
177 177 dict.__delitem__(self, key)
178 except KeyError, e:
178 except KeyError as e:
179 179 raise AttributeError(e)
180 180
181 181
182 182 #-----------------------------------------------------------------------------
183 183 # Config loading classes
184 184 #-----------------------------------------------------------------------------
185 185
186 186
187 187 class ConfigLoader(object):
188 188 """A object for loading configurations from just about anywhere.
189 189
190 190 The resulting configuration is packaged as a :class:`Struct`.
191 191
192 192 Notes
193 193 -----
194 194 A :class:`ConfigLoader` does one thing: load a config from a source
195 195 (file, command line arguments) and returns the data as a :class:`Struct`.
196 196 There are lots of things that :class:`ConfigLoader` does not do. It does
197 197 not implement complex logic for finding config files. It does not handle
198 198 default values or merge multiple configs. These things need to be
199 199 handled elsewhere.
200 200 """
201 201
202 202 def __init__(self):
203 203 """A base class for config loaders.
204 204
205 205 Examples
206 206 --------
207 207
208 208 >>> cl = ConfigLoader()
209 209 >>> config = cl.load_config()
210 210 >>> config
211 211 {}
212 212 """
213 213 self.clear()
214 214
215 215 def clear(self):
216 216 self.config = Config()
217 217
218 218 def load_config(self):
219 219 """Load a config from somewhere, return a :class:`Config` instance.
220 220
221 221 Usually, this will cause self.config to be set and then returned.
222 222 However, in most cases, :meth:`ConfigLoader.clear` should be called
223 223 to erase any previous state.
224 224 """
225 225 self.clear()
226 226 return self.config
227 227
228 228
229 229 class FileConfigLoader(ConfigLoader):
230 230 """A base class for file based configurations.
231 231
232 232 As we add more file based config loaders, the common logic should go
233 233 here.
234 234 """
235 235 pass
236 236
237 237
238 238 class PyFileConfigLoader(FileConfigLoader):
239 239 """A config loader for pure python files.
240 240
241 241 This calls execfile on a plain python file and looks for attributes
242 242 that are all caps. These attribute are added to the config Struct.
243 243 """
244 244
245 245 def __init__(self, filename, path=None):
246 246 """Build a config loader for a filename and path.
247 247
248 248 Parameters
249 249 ----------
250 250 filename : str
251 251 The file name of the config file.
252 252 path : str, list, tuple
253 253 The path to search for the config file on, or a sequence of
254 254 paths to try in order.
255 255 """
256 256 super(PyFileConfigLoader, self).__init__()
257 257 self.filename = filename
258 258 self.path = path
259 259 self.full_filename = ''
260 260 self.data = None
261 261
262 262 def load_config(self):
263 263 """Load the config from a file and return it as a Struct."""
264 264 self.clear()
265 265 try:
266 266 self._find_file()
267 267 except IOError as e:
268 268 raise ConfigFileNotFound(str(e))
269 269 self._read_file_as_dict()
270 270 self._convert_to_config()
271 271 return self.config
272 272
273 273 def _find_file(self):
274 274 """Try to find the file by searching the paths."""
275 275 self.full_filename = filefind(self.filename, self.path)
276 276
277 277 def _read_file_as_dict(self):
278 278 """Load the config file into self.config, with recursive loading."""
279 279 # This closure is made available in the namespace that is used
280 280 # to exec the config file. It allows users to call
281 281 # load_subconfig('myconfig.py') to load config files recursively.
282 282 # It needs to be a closure because it has references to self.path
283 283 # and self.config. The sub-config is loaded with the same path
284 284 # as the parent, but it uses an empty config which is then merged
285 285 # with the parents.
286 286
287 287 # If a profile is specified, the config file will be loaded
288 288 # from that profile
289 289
290 290 def load_subconfig(fname, profile=None):
291 291 # import here to prevent circular imports
292 292 from IPython.core.profiledir import ProfileDir, ProfileDirError
293 293 if profile is not None:
294 294 try:
295 295 profile_dir = ProfileDir.find_profile_dir_by_name(
296 296 get_ipython_dir(),
297 297 profile,
298 298 )
299 299 except ProfileDirError:
300 300 return
301 301 path = profile_dir.location
302 302 else:
303 303 path = self.path
304 304 loader = PyFileConfigLoader(fname, path)
305 305 try:
306 306 sub_config = loader.load_config()
307 307 except ConfigFileNotFound:
308 308 # Pass silently if the sub config is not there. This happens
309 309 # when a user s using a profile, but not the default config.
310 310 pass
311 311 else:
312 312 self.config._merge(sub_config)
313 313
314 314 # Again, this needs to be a closure and should be used in config
315 315 # files to get the config being loaded.
316 316 def get_config():
317 317 return self.config
318 318
319 319 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
320 320 fs_encoding = sys.getfilesystemencoding() or 'ascii'
321 321 conf_filename = self.full_filename.encode(fs_encoding)
322 322 py3compat.execfile(conf_filename, namespace)
323 323
324 324 def _convert_to_config(self):
325 325 if self.data is None:
326 326 ConfigLoaderError('self.data does not exist')
327 327
328 328
329 329 class CommandLineConfigLoader(ConfigLoader):
330 330 """A config loader for command line arguments.
331 331
332 332 As we add more command line based loaders, the common logic should go
333 333 here.
334 334 """
335 335
336 336 def _exec_config_str(self, lhs, rhs):
337 337 """execute self.config.<lhs> = <rhs>
338 338
339 339 * expands ~ with expanduser
340 340 * tries to assign with raw eval, otherwise assigns with just the string,
341 341 allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not*
342 342 equivalent are `--C.a=4` and `--C.a='4'`.
343 343 """
344 344 rhs = os.path.expanduser(rhs)
345 345 try:
346 346 # Try to see if regular Python syntax will work. This
347 347 # won't handle strings as the quote marks are removed
348 348 # by the system shell.
349 349 value = eval(rhs)
350 350 except (NameError, SyntaxError):
351 351 # This case happens if the rhs is a string.
352 352 value = rhs
353 353
354 354 exec u'self.config.%s = value' % lhs
355 355
356 356 def _load_flag(self, cfg):
357 357 """update self.config from a flag, which can be a dict or Config"""
358 358 if isinstance(cfg, (dict, Config)):
359 359 # don't clobber whole config sections, update
360 360 # each section from config:
361 361 for sec,c in cfg.iteritems():
362 362 self.config[sec].update(c)
363 363 else:
364 364 raise TypeError("Invalid flag: %r" % cfg)
365 365
366 366 # raw --identifier=value pattern
367 367 # but *also* accept '-' as wordsep, for aliases
368 368 # accepts: --foo=a
369 369 # --Class.trait=value
370 370 # --alias-name=value
371 371 # rejects: -foo=value
372 372 # --foo
373 373 # --Class.trait
374 374 kv_pattern = re.compile(r'\-\-[A-Za-z][\w\-]*(\.[\w\-]+)*\=.*')
375 375
376 376 # just flags, no assignments, with two *or one* leading '-'
377 377 # accepts: --foo
378 378 # -foo-bar-again
379 379 # rejects: --anything=anything
380 380 # --two.word
381 381
382 382 flag_pattern = re.compile(r'\-\-?\w+[\-\w]*$')
383 383
384 384 class KeyValueConfigLoader(CommandLineConfigLoader):
385 385 """A config loader that loads key value pairs from the command line.
386 386
387 387 This allows command line options to be gives in the following form::
388 388
389 389 ipython --profile="foo" --InteractiveShell.autocall=False
390 390 """
391 391
392 392 def __init__(self, argv=None, aliases=None, flags=None):
393 393 """Create a key value pair config loader.
394 394
395 395 Parameters
396 396 ----------
397 397 argv : list
398 398 A list that has the form of sys.argv[1:] which has unicode
399 399 elements of the form u"key=value". If this is None (default),
400 400 then sys.argv[1:] will be used.
401 401 aliases : dict
402 402 A dict of aliases for configurable traits.
403 403 Keys are the short aliases, Values are the resolved trait.
404 404 Of the form: `{'alias' : 'Configurable.trait'}`
405 405 flags : dict
406 406 A dict of flags, keyed by str name. Vaues can be Config objects,
407 407 dicts, or "key=value" strings. If Config or dict, when the flag
408 408 is triggered, The flag is loaded as `self.config.update(m)`.
409 409
410 410 Returns
411 411 -------
412 412 config : Config
413 413 The resulting Config object.
414 414
415 415 Examples
416 416 --------
417 417
418 418 >>> from IPython.config.loader import KeyValueConfigLoader
419 419 >>> cl = KeyValueConfigLoader()
420 420 >>> d = cl.load_config(["--A.name='brian'","--B.number=0"])
421 421 >>> sorted(d.items())
422 422 [('A', {'name': 'brian'}), ('B', {'number': 0})]
423 423 """
424 424 self.clear()
425 425 if argv is None:
426 426 argv = sys.argv[1:]
427 427 self.argv = argv
428 428 self.aliases = aliases or {}
429 429 self.flags = flags or {}
430 430
431 431
432 432 def clear(self):
433 433 super(KeyValueConfigLoader, self).clear()
434 434 self.extra_args = []
435 435
436 436
437 437 def _decode_argv(self, argv, enc=None):
438 438 """decode argv if bytes, using stin.encoding, falling back on default enc"""
439 439 uargv = []
440 440 if enc is None:
441 441 enc = DEFAULT_ENCODING
442 442 for arg in argv:
443 443 if not isinstance(arg, unicode):
444 444 # only decode if not already decoded
445 445 arg = arg.decode(enc)
446 446 uargv.append(arg)
447 447 return uargv
448 448
449 449
450 450 def load_config(self, argv=None, aliases=None, flags=None):
451 451 """Parse the configuration and generate the Config object.
452 452
453 453 After loading, any arguments that are not key-value or
454 454 flags will be stored in self.extra_args - a list of
455 455 unparsed command-line arguments. This is used for
456 456 arguments such as input files or subcommands.
457 457
458 458 Parameters
459 459 ----------
460 460 argv : list, optional
461 461 A list that has the form of sys.argv[1:] which has unicode
462 462 elements of the form u"key=value". If this is None (default),
463 463 then self.argv will be used.
464 464 aliases : dict
465 465 A dict of aliases for configurable traits.
466 466 Keys are the short aliases, Values are the resolved trait.
467 467 Of the form: `{'alias' : 'Configurable.trait'}`
468 468 flags : dict
469 469 A dict of flags, keyed by str name. Values can be Config objects
470 470 or dicts. When the flag is triggered, The config is loaded as
471 471 `self.config.update(cfg)`.
472 472 """
473 473 from IPython.config.configurable import Configurable
474 474
475 475 self.clear()
476 476 if argv is None:
477 477 argv = self.argv
478 478 if aliases is None:
479 479 aliases = self.aliases
480 480 if flags is None:
481 481 flags = self.flags
482 482
483 483 # ensure argv is a list of unicode strings:
484 484 uargv = self._decode_argv(argv)
485 485 for idx,raw in enumerate(uargv):
486 486 # strip leading '-'
487 487 item = raw.lstrip('-')
488 488
489 489 if raw == '--':
490 490 # don't parse arguments after '--'
491 491 # this is useful for relaying arguments to scripts, e.g.
492 492 # ipython -i foo.py --pylab=qt -- args after '--' go-to-foo.py
493 493 self.extra_args.extend(uargv[idx+1:])
494 494 break
495 495
496 496 if kv_pattern.match(raw):
497 497 lhs,rhs = item.split('=',1)
498 498 # Substitute longnames for aliases.
499 499 if lhs in aliases:
500 500 lhs = aliases[lhs]
501 501 if '.' not in lhs:
502 502 # probably a mistyped alias, but not technically illegal
503 503 warn.warn("Unrecognized alias: '%s', it will probably have no effect."%lhs)
504 504 try:
505 505 self._exec_config_str(lhs, rhs)
506 506 except Exception:
507 507 raise ArgumentError("Invalid argument: '%s'" % raw)
508 508
509 509 elif flag_pattern.match(raw):
510 510 if item in flags:
511 511 cfg,help = flags[item]
512 512 self._load_flag(cfg)
513 513 else:
514 514 raise ArgumentError("Unrecognized flag: '%s'"%raw)
515 515 elif raw.startswith('-'):
516 516 kv = '--'+item
517 517 if kv_pattern.match(kv):
518 518 raise ArgumentError("Invalid argument: '%s', did you mean '%s'?"%(raw, kv))
519 519 else:
520 520 raise ArgumentError("Invalid argument: '%s'"%raw)
521 521 else:
522 522 # keep all args that aren't valid in a list,
523 523 # in case our parent knows what to do with them.
524 524 self.extra_args.append(item)
525 525 return self.config
526 526
527 527 class ArgParseConfigLoader(CommandLineConfigLoader):
528 528 """A loader that uses the argparse module to load from the command line."""
529 529
530 530 def __init__(self, argv=None, aliases=None, flags=None, *parser_args, **parser_kw):
531 531 """Create a config loader for use with argparse.
532 532
533 533 Parameters
534 534 ----------
535 535
536 536 argv : optional, list
537 537 If given, used to read command-line arguments from, otherwise
538 538 sys.argv[1:] is used.
539 539
540 540 parser_args : tuple
541 541 A tuple of positional arguments that will be passed to the
542 542 constructor of :class:`argparse.ArgumentParser`.
543 543
544 544 parser_kw : dict
545 545 A tuple of keyword arguments that will be passed to the
546 546 constructor of :class:`argparse.ArgumentParser`.
547 547
548 548 Returns
549 549 -------
550 550 config : Config
551 551 The resulting Config object.
552 552 """
553 553 super(CommandLineConfigLoader, self).__init__()
554 554 self.clear()
555 555 if argv is None:
556 556 argv = sys.argv[1:]
557 557 self.argv = argv
558 558 self.aliases = aliases or {}
559 559 self.flags = flags or {}
560 560
561 561 self.parser_args = parser_args
562 562 self.version = parser_kw.pop("version", None)
563 563 kwargs = dict(argument_default=argparse.SUPPRESS)
564 564 kwargs.update(parser_kw)
565 565 self.parser_kw = kwargs
566 566
567 567 def load_config(self, argv=None, aliases=None, flags=None):
568 568 """Parse command line arguments and return as a Config object.
569 569
570 570 Parameters
571 571 ----------
572 572
573 573 args : optional, list
574 574 If given, a list with the structure of sys.argv[1:] to parse
575 575 arguments from. If not given, the instance's self.argv attribute
576 576 (given at construction time) is used."""
577 577 self.clear()
578 578 if argv is None:
579 579 argv = self.argv
580 580 if aliases is None:
581 581 aliases = self.aliases
582 582 if flags is None:
583 583 flags = self.flags
584 584 self._create_parser(aliases, flags)
585 585 self._parse_args(argv)
586 586 self._convert_to_config()
587 587 return self.config
588 588
589 589 def get_extra_args(self):
590 590 if hasattr(self, 'extra_args'):
591 591 return self.extra_args
592 592 else:
593 593 return []
594 594
595 595 def _create_parser(self, aliases=None, flags=None):
596 596 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
597 597 self._add_arguments(aliases, flags)
598 598
599 599 def _add_arguments(self, aliases=None, flags=None):
600 600 raise NotImplementedError("subclasses must implement _add_arguments")
601 601
602 602 def _parse_args(self, args):
603 603 """self.parser->self.parsed_data"""
604 604 # decode sys.argv to support unicode command-line options
605 605 enc = DEFAULT_ENCODING
606 606 uargs = [py3compat.cast_unicode(a, enc) for a in args]
607 607 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
608 608
609 609 def _convert_to_config(self):
610 610 """self.parsed_data->self.config"""
611 611 for k, v in vars(self.parsed_data).iteritems():
612 612 exec "self.config.%s = v"%k in locals(), globals()
613 613
614 614 class KVArgParseConfigLoader(ArgParseConfigLoader):
615 615 """A config loader that loads aliases and flags with argparse,
616 616 but will use KVLoader for the rest. This allows better parsing
617 617 of common args, such as `ipython -c 'print 5'`, but still gets
618 618 arbitrary config with `ipython --InteractiveShell.use_readline=False`"""
619 619
620 620 def _add_arguments(self, aliases=None, flags=None):
621 621 self.alias_flags = {}
622 622 # print aliases, flags
623 623 if aliases is None:
624 624 aliases = self.aliases
625 625 if flags is None:
626 626 flags = self.flags
627 627 paa = self.parser.add_argument
628 628 for key,value in aliases.iteritems():
629 629 if key in flags:
630 630 # flags
631 631 nargs = '?'
632 632 else:
633 633 nargs = None
634 634 if len(key) is 1:
635 635 paa('-'+key, '--'+key, type=unicode, dest=value, nargs=nargs)
636 636 else:
637 637 paa('--'+key, type=unicode, dest=value, nargs=nargs)
638 638 for key, (value, help) in flags.iteritems():
639 639 if key in self.aliases:
640 640 #
641 641 self.alias_flags[self.aliases[key]] = value
642 642 continue
643 643 if len(key) is 1:
644 644 paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)
645 645 else:
646 646 paa('--'+key, action='append_const', dest='_flags', const=value)
647 647
648 648 def _convert_to_config(self):
649 649 """self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
650 650 # remove subconfigs list from namespace before transforming the Namespace
651 651 if '_flags' in self.parsed_data:
652 652 subcs = self.parsed_data._flags
653 653 del self.parsed_data._flags
654 654 else:
655 655 subcs = []
656 656
657 657 for k, v in vars(self.parsed_data).iteritems():
658 658 if v is None:
659 659 # it was a flag that shares the name of an alias
660 660 subcs.append(self.alias_flags[k])
661 661 else:
662 662 # eval the KV assignment
663 663 self._exec_config_str(k, v)
664 664
665 665 for subc in subcs:
666 666 self._load_flag(subc)
667 667
668 668 if self.extra_args:
669 669 sub_parser = KeyValueConfigLoader()
670 670 sub_parser.load_config(self.extra_args)
671 671 self.config._merge(sub_parser.config)
672 672 self.extra_args = sub_parser.extra_args
673 673
674 674
675 675 def load_pyconfig_files(config_files, path):
676 676 """Load multiple Python config files, merging each of them in turn.
677 677
678 678 Parameters
679 679 ==========
680 680 config_files : list of str
681 681 List of config files names to load and merge into the config.
682 682 path : unicode
683 683 The full path to the location of the config files.
684 684 """
685 685 config = Config()
686 686 for cf in config_files:
687 687 loader = PyFileConfigLoader(cf, path=path)
688 688 try:
689 689 next_config = loader.load_config()
690 690 except ConfigFileNotFound:
691 691 pass
692 692 except:
693 693 raise
694 694 else:
695 695 config._merge(next_config)
696 696 return config
@@ -1,263 +1,263 b''
1 1 # encoding: utf-8
2 2 """
3 3 System command aliases.
4 4
5 5 Authors:
6 6
7 7 * Fernando Perez
8 8 * Brian Granger
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License.
15 15 #
16 16 # The full license is in the file COPYING.txt, distributed with this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import __builtin__
24 24 import keyword
25 25 import os
26 26 import re
27 27 import sys
28 28
29 29 from IPython.config.configurable import Configurable
30 30 from IPython.core.splitinput import split_user_input
31 31
32 32 from IPython.utils.traitlets import List, Instance
33 33 from IPython.utils.autoattr import auto_attr
34 34 from IPython.utils.warn import warn, error
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Utilities
38 38 #-----------------------------------------------------------------------------
39 39
40 40 # This is used as the pattern for calls to split_user_input.
41 41 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
42 42
43 43 def default_aliases():
44 44 """Return list of shell aliases to auto-define.
45 45 """
46 46 # Note: the aliases defined here should be safe to use on a kernel
47 47 # regardless of what frontend it is attached to. Frontends that use a
48 48 # kernel in-process can define additional aliases that will only work in
49 49 # their case. For example, things like 'less' or 'clear' that manipulate
50 50 # the terminal should NOT be declared here, as they will only work if the
51 51 # kernel is running inside a true terminal, and not over the network.
52 52
53 53 if os.name == 'posix':
54 54 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
55 55 ('mv', 'mv -i'), ('rm', 'rm -i'), ('cp', 'cp -i'),
56 56 ('cat', 'cat'),
57 57 ]
58 58 # Useful set of ls aliases. The GNU and BSD options are a little
59 59 # different, so we make aliases that provide as similar as possible
60 60 # behavior in ipython, by passing the right flags for each platform
61 61 if sys.platform.startswith('linux'):
62 62 ls_aliases = [('ls', 'ls -F --color'),
63 63 # long ls
64 64 ('ll', 'ls -F -o --color'),
65 65 # ls normal files only
66 66 ('lf', 'ls -F -o --color %l | grep ^-'),
67 67 # ls symbolic links
68 68 ('lk', 'ls -F -o --color %l | grep ^l'),
69 69 # directories or links to directories,
70 70 ('ldir', 'ls -F -o --color %l | grep /$'),
71 71 # things which are executable
72 72 ('lx', 'ls -F -o --color %l | grep ^-..x'),
73 73 ]
74 74 else:
75 75 # BSD, OSX, etc.
76 76 ls_aliases = [('ls', 'ls -F'),
77 77 # long ls
78 78 ('ll', 'ls -F -l'),
79 79 # ls normal files only
80 80 ('lf', 'ls -F -l %l | grep ^-'),
81 81 # ls symbolic links
82 82 ('lk', 'ls -F -l %l | grep ^l'),
83 83 # directories or links to directories,
84 84 ('ldir', 'ls -F -l %l | grep /$'),
85 85 # things which are executable
86 86 ('lx', 'ls -F -l %l | grep ^-..x'),
87 87 ]
88 88 default_aliases = default_aliases + ls_aliases
89 89 elif os.name in ['nt', 'dos']:
90 90 default_aliases = [('ls', 'dir /on'),
91 91 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
92 92 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
93 93 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
94 94 ]
95 95 else:
96 96 default_aliases = []
97 97
98 98 return default_aliases
99 99
100 100
101 101 class AliasError(Exception):
102 102 pass
103 103
104 104
105 105 class InvalidAliasError(AliasError):
106 106 pass
107 107
108 108 #-----------------------------------------------------------------------------
109 109 # Main AliasManager class
110 110 #-----------------------------------------------------------------------------
111 111
112 112 class AliasManager(Configurable):
113 113
114 114 default_aliases = List(default_aliases(), config=True)
115 115 user_aliases = List(default_value=[], config=True)
116 116 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
117 117
118 118 def __init__(self, shell=None, config=None):
119 119 super(AliasManager, self).__init__(shell=shell, config=config)
120 120 self.alias_table = {}
121 121 self.exclude_aliases()
122 122 self.init_aliases()
123 123
124 124 def __contains__(self, name):
125 125 return name in self.alias_table
126 126
127 127 @property
128 128 def aliases(self):
129 129 return [(item[0], item[1][1]) for item in self.alias_table.iteritems()]
130 130
131 131 def exclude_aliases(self):
132 132 # set of things NOT to alias (keywords, builtins and some magics)
133 133 no_alias = set(['cd','popd','pushd','dhist','alias','unalias'])
134 134 no_alias.update(set(keyword.kwlist))
135 135 no_alias.update(set(__builtin__.__dict__.keys()))
136 136 self.no_alias = no_alias
137 137
138 138 def init_aliases(self):
139 139 # Load default aliases
140 140 for name, cmd in self.default_aliases:
141 141 self.soft_define_alias(name, cmd)
142 142
143 143 # Load user aliases
144 144 for name, cmd in self.user_aliases:
145 145 self.soft_define_alias(name, cmd)
146 146
147 147 def clear_aliases(self):
148 148 self.alias_table.clear()
149 149
150 150 def soft_define_alias(self, name, cmd):
151 151 """Define an alias, but don't raise on an AliasError."""
152 152 try:
153 153 self.define_alias(name, cmd)
154 except AliasError, e:
154 except AliasError as e:
155 155 error("Invalid alias: %s" % e)
156 156
157 157 def define_alias(self, name, cmd):
158 158 """Define a new alias after validating it.
159 159
160 160 This will raise an :exc:`AliasError` if there are validation
161 161 problems.
162 162 """
163 163 nargs = self.validate_alias(name, cmd)
164 164 self.alias_table[name] = (nargs, cmd)
165 165
166 166 def undefine_alias(self, name):
167 167 if self.alias_table.has_key(name):
168 168 del self.alias_table[name]
169 169
170 170 def validate_alias(self, name, cmd):
171 171 """Validate an alias and return the its number of arguments."""
172 172 if name in self.no_alias:
173 173 raise InvalidAliasError("The name %s can't be aliased "
174 174 "because it is a keyword or builtin." % name)
175 175 if not (isinstance(cmd, basestring)):
176 176 raise InvalidAliasError("An alias command must be a string, "
177 177 "got: %r" % cmd)
178 178 nargs = cmd.count('%s')
179 179 if nargs>0 and cmd.find('%l')>=0:
180 180 raise InvalidAliasError('The %s and %l specifiers are mutually '
181 181 'exclusive in alias definitions.')
182 182 return nargs
183 183
184 184 def call_alias(self, alias, rest=''):
185 185 """Call an alias given its name and the rest of the line."""
186 186 cmd = self.transform_alias(alias, rest)
187 187 try:
188 188 self.shell.system(cmd)
189 189 except:
190 190 self.shell.showtraceback()
191 191
192 192 def transform_alias(self, alias,rest=''):
193 193 """Transform alias to system command string."""
194 194 nargs, cmd = self.alias_table[alias]
195 195
196 196 if ' ' in cmd and os.path.isfile(cmd):
197 197 cmd = '"%s"' % cmd
198 198
199 199 # Expand the %l special to be the user's input line
200 200 if cmd.find('%l') >= 0:
201 201 cmd = cmd.replace('%l', rest)
202 202 rest = ''
203 203 if nargs==0:
204 204 # Simple, argument-less aliases
205 205 cmd = '%s %s' % (cmd, rest)
206 206 else:
207 207 # Handle aliases with positional arguments
208 208 args = rest.split(None, nargs)
209 209 if len(args) < nargs:
210 210 raise AliasError('Alias <%s> requires %s arguments, %s given.' %
211 211 (alias, nargs, len(args)))
212 212 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
213 213 return cmd
214 214
215 215 def expand_alias(self, line):
216 216 """ Expand an alias in the command line
217 217
218 218 Returns the provided command line, possibly with the first word
219 219 (command) translated according to alias expansion rules.
220 220
221 221 [ipython]|16> _ip.expand_aliases("np myfile.txt")
222 222 <16> 'q:/opt/np/notepad++.exe myfile.txt'
223 223 """
224 224
225 225 pre,_,fn,rest = split_user_input(line)
226 226 res = pre + self.expand_aliases(fn, rest)
227 227 return res
228 228
229 229 def expand_aliases(self, fn, rest):
230 230 """Expand multiple levels of aliases:
231 231
232 232 if:
233 233
234 234 alias foo bar /tmp
235 235 alias baz foo
236 236
237 237 then:
238 238
239 239 baz huhhahhei -> bar /tmp huhhahhei
240 240 """
241 241 line = fn + " " + rest
242 242
243 243 done = set()
244 244 while 1:
245 245 pre,_,fn,rest = split_user_input(line, shell_line_split)
246 246 if fn in self.alias_table:
247 247 if fn in done:
248 248 warn("Cyclic alias definition, repeated '%s'" % fn)
249 249 return ""
250 250 done.add(fn)
251 251
252 252 l2 = self.transform_alias(fn, rest)
253 253 if l2 == line:
254 254 break
255 255 # ls -> ls -F should not recurse forever
256 256 if l2.split(None,1)[0] == line.split(None,1)[0]:
257 257 line = l2
258 258 break
259 259 line=l2
260 260 else:
261 261 break
262 262
263 263 return line
@@ -1,3009 +1,3009 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Main IPython class."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from __future__ import with_statement
18 18 from __future__ import absolute_import
19 19
20 20 import __builtin__ as builtin_mod
21 21 import __future__
22 22 import abc
23 23 import ast
24 24 import atexit
25 25 import os
26 26 import re
27 27 import runpy
28 28 import sys
29 29 import tempfile
30 30 import types
31 31
32 32 # We need to use nested to support python 2.6, once we move to >=2.7, we can
33 33 # use the with keyword's new builtin support for nested managers
34 34 try:
35 35 from contextlib import nested
36 36 except:
37 37 from IPython.utils.nested_context import nested
38 38
39 39 from IPython.config.configurable import SingletonConfigurable
40 40 from IPython.core import debugger, oinspect
41 41 from IPython.core import history as ipcorehist
42 42 from IPython.core import magic
43 43 from IPython.core import page
44 44 from IPython.core import prefilter
45 45 from IPython.core import shadowns
46 46 from IPython.core import ultratb
47 47 from IPython.core.alias import AliasManager, AliasError
48 48 from IPython.core.autocall import ExitAutocall
49 49 from IPython.core.builtin_trap import BuiltinTrap
50 50 from IPython.core.compilerop import CachingCompiler
51 51 from IPython.core.display_trap import DisplayTrap
52 52 from IPython.core.displayhook import DisplayHook
53 53 from IPython.core.displaypub import DisplayPublisher
54 54 from IPython.core.error import UsageError
55 55 from IPython.core.extensions import ExtensionManager
56 56 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
57 57 from IPython.core.formatters import DisplayFormatter
58 58 from IPython.core.history import HistoryManager
59 59 from IPython.core.inputsplitter import IPythonInputSplitter, ESC_MAGIC, ESC_MAGIC2
60 60 from IPython.core.logger import Logger
61 61 from IPython.core.macro import Macro
62 62 from IPython.core.payload import PayloadManager
63 63 from IPython.core.plugin import PluginManager
64 64 from IPython.core.prefilter import PrefilterManager
65 65 from IPython.core.profiledir import ProfileDir
66 66 from IPython.core.pylabtools import pylab_activate
67 67 from IPython.core.prompts import PromptManager
68 68 from IPython.utils import PyColorize
69 69 from IPython.utils import io
70 70 from IPython.utils import py3compat
71 71 from IPython.utils import openpy
72 72 from IPython.utils.doctestreload import doctest_reload
73 73 from IPython.utils.io import ask_yes_no
74 74 from IPython.utils.ipstruct import Struct
75 75 from IPython.utils.path import get_home_dir, get_ipython_dir, get_py_filename, unquote_filename
76 76 from IPython.utils.pickleshare import PickleShareDB
77 77 from IPython.utils.process import system, getoutput
78 78 from IPython.utils.strdispatch import StrDispatch
79 79 from IPython.utils.syspathcontext import prepended_to_syspath
80 80 from IPython.utils.text import (format_screen, LSString, SList,
81 81 DollarFormatter)
82 82 from IPython.utils.traitlets import (Integer, CBool, CaselessStrEnum, Enum,
83 83 List, Unicode, Instance, Type)
84 84 from IPython.utils.warn import warn, error
85 85 import IPython.core.hooks
86 86
87 87 # FIXME: do this in a function to avoid circular dependencies
88 88 # A better solution is to remove IPython.parallel.error,
89 89 # and place those classes in IPython.core.error.
90 90
91 91 class RemoteError(Exception):
92 92 pass
93 93
94 94 def _import_remote_error():
95 95 global RemoteError
96 96 try:
97 97 from IPython.parallel.error import RemoteError
98 98 except:
99 99 pass
100 100
101 101 _import_remote_error()
102 102
103 103 #-----------------------------------------------------------------------------
104 104 # Globals
105 105 #-----------------------------------------------------------------------------
106 106
107 107 # compiled regexps for autoindent management
108 108 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
109 109
110 110 #-----------------------------------------------------------------------------
111 111 # Utilities
112 112 #-----------------------------------------------------------------------------
113 113
114 114 def softspace(file, newvalue):
115 115 """Copied from code.py, to remove the dependency"""
116 116
117 117 oldvalue = 0
118 118 try:
119 119 oldvalue = file.softspace
120 120 except AttributeError:
121 121 pass
122 122 try:
123 123 file.softspace = newvalue
124 124 except (AttributeError, TypeError):
125 125 # "attribute-less object" or "read-only attributes"
126 126 pass
127 127 return oldvalue
128 128
129 129
130 130 def no_op(*a, **kw): pass
131 131
132 132 class NoOpContext(object):
133 133 def __enter__(self): pass
134 134 def __exit__(self, type, value, traceback): pass
135 135 no_op_context = NoOpContext()
136 136
137 137 class SpaceInInput(Exception): pass
138 138
139 139 class Bunch: pass
140 140
141 141
142 142 def get_default_colors():
143 143 if sys.platform=='darwin':
144 144 return "LightBG"
145 145 elif os.name=='nt':
146 146 return 'Linux'
147 147 else:
148 148 return 'Linux'
149 149
150 150
151 151 class SeparateUnicode(Unicode):
152 152 """A Unicode subclass to validate separate_in, separate_out, etc.
153 153
154 154 This is a Unicode based trait that converts '0'->'' and '\\n'->'\n'.
155 155 """
156 156
157 157 def validate(self, obj, value):
158 158 if value == '0': value = ''
159 159 value = value.replace('\\n','\n')
160 160 return super(SeparateUnicode, self).validate(obj, value)
161 161
162 162
163 163 class ReadlineNoRecord(object):
164 164 """Context manager to execute some code, then reload readline history
165 165 so that interactive input to the code doesn't appear when pressing up."""
166 166 def __init__(self, shell):
167 167 self.shell = shell
168 168 self._nested_level = 0
169 169
170 170 def __enter__(self):
171 171 if self._nested_level == 0:
172 172 try:
173 173 self.orig_length = self.current_length()
174 174 self.readline_tail = self.get_readline_tail()
175 175 except (AttributeError, IndexError): # Can fail with pyreadline
176 176 self.orig_length, self.readline_tail = 999999, []
177 177 self._nested_level += 1
178 178
179 179 def __exit__(self, type, value, traceback):
180 180 self._nested_level -= 1
181 181 if self._nested_level == 0:
182 182 # Try clipping the end if it's got longer
183 183 try:
184 184 e = self.current_length() - self.orig_length
185 185 if e > 0:
186 186 for _ in range(e):
187 187 self.shell.readline.remove_history_item(self.orig_length)
188 188
189 189 # If it still doesn't match, just reload readline history.
190 190 if self.current_length() != self.orig_length \
191 191 or self.get_readline_tail() != self.readline_tail:
192 192 self.shell.refill_readline_hist()
193 193 except (AttributeError, IndexError):
194 194 pass
195 195 # Returning False will cause exceptions to propagate
196 196 return False
197 197
198 198 def current_length(self):
199 199 return self.shell.readline.get_current_history_length()
200 200
201 201 def get_readline_tail(self, n=10):
202 202 """Get the last n items in readline history."""
203 203 end = self.shell.readline.get_current_history_length() + 1
204 204 start = max(end-n, 1)
205 205 ghi = self.shell.readline.get_history_item
206 206 return [ghi(x) for x in range(start, end)]
207 207
208 208 #-----------------------------------------------------------------------------
209 209 # Main IPython class
210 210 #-----------------------------------------------------------------------------
211 211
212 212 class InteractiveShell(SingletonConfigurable):
213 213 """An enhanced, interactive shell for Python."""
214 214
215 215 _instance = None
216 216
217 217 autocall = Enum((0,1,2), default_value=0, config=True, help=
218 218 """
219 219 Make IPython automatically call any callable object even if you didn't
220 220 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
221 221 automatically. The value can be '0' to disable the feature, '1' for
222 222 'smart' autocall, where it is not applied if there are no more
223 223 arguments on the line, and '2' for 'full' autocall, where all callable
224 224 objects are automatically called (even if no arguments are present).
225 225 """
226 226 )
227 227 # TODO: remove all autoindent logic and put into frontends.
228 228 # We can't do this yet because even runlines uses the autoindent.
229 229 autoindent = CBool(True, config=True, help=
230 230 """
231 231 Autoindent IPython code entered interactively.
232 232 """
233 233 )
234 234 automagic = CBool(True, config=True, help=
235 235 """
236 236 Enable magic commands to be called without the leading %.
237 237 """
238 238 )
239 239 cache_size = Integer(1000, config=True, help=
240 240 """
241 241 Set the size of the output cache. The default is 1000, you can
242 242 change it permanently in your config file. Setting it to 0 completely
243 243 disables the caching system, and the minimum value accepted is 20 (if
244 244 you provide a value less than 20, it is reset to 0 and a warning is
245 245 issued). This limit is defined because otherwise you'll spend more
246 246 time re-flushing a too small cache than working
247 247 """
248 248 )
249 249 color_info = CBool(True, config=True, help=
250 250 """
251 251 Use colors for displaying information about objects. Because this
252 252 information is passed through a pager (like 'less'), and some pagers
253 253 get confused with color codes, this capability can be turned off.
254 254 """
255 255 )
256 256 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
257 257 default_value=get_default_colors(), config=True,
258 258 help="Set the color scheme (NoColor, Linux, or LightBG)."
259 259 )
260 260 colors_force = CBool(False, help=
261 261 """
262 262 Force use of ANSI color codes, regardless of OS and readline
263 263 availability.
264 264 """
265 265 # FIXME: This is essentially a hack to allow ZMQShell to show colors
266 266 # without readline on Win32. When the ZMQ formatting system is
267 267 # refactored, this should be removed.
268 268 )
269 269 debug = CBool(False, config=True)
270 270 deep_reload = CBool(False, config=True, help=
271 271 """
272 272 Enable deep (recursive) reloading by default. IPython can use the
273 273 deep_reload module which reloads changes in modules recursively (it
274 274 replaces the reload() function, so you don't need to change anything to
275 275 use it). deep_reload() forces a full reload of modules whose code may
276 276 have changed, which the default reload() function does not. When
277 277 deep_reload is off, IPython will use the normal reload(), but
278 278 deep_reload will still be available as dreload().
279 279 """
280 280 )
281 281 disable_failing_post_execute = CBool(False, config=True,
282 282 help="Don't call post-execute functions that have failed in the past."
283 283 )
284 284 display_formatter = Instance(DisplayFormatter)
285 285 displayhook_class = Type(DisplayHook)
286 286 display_pub_class = Type(DisplayPublisher)
287 287
288 288 exit_now = CBool(False)
289 289 exiter = Instance(ExitAutocall)
290 290 def _exiter_default(self):
291 291 return ExitAutocall(self)
292 292 # Monotonically increasing execution counter
293 293 execution_count = Integer(1)
294 294 filename = Unicode("<ipython console>")
295 295 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
296 296
297 297 # Input splitter, to split entire cells of input into either individual
298 298 # interactive statements or whole blocks.
299 299 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
300 300 (), {})
301 301 logstart = CBool(False, config=True, help=
302 302 """
303 303 Start logging to the default log file.
304 304 """
305 305 )
306 306 logfile = Unicode('', config=True, help=
307 307 """
308 308 The name of the logfile to use.
309 309 """
310 310 )
311 311 logappend = Unicode('', config=True, help=
312 312 """
313 313 Start logging to the given file in append mode.
314 314 """
315 315 )
316 316 object_info_string_level = Enum((0,1,2), default_value=0,
317 317 config=True)
318 318 pdb = CBool(False, config=True, help=
319 319 """
320 320 Automatically call the pdb debugger after every exception.
321 321 """
322 322 )
323 323 multiline_history = CBool(sys.platform != 'win32', config=True,
324 324 help="Save multi-line entries as one entry in readline history"
325 325 )
326 326
327 327 # deprecated prompt traits:
328 328
329 329 prompt_in1 = Unicode('In [\\#]: ', config=True,
330 330 help="Deprecated, use PromptManager.in_template")
331 331 prompt_in2 = Unicode(' .\\D.: ', config=True,
332 332 help="Deprecated, use PromptManager.in2_template")
333 333 prompt_out = Unicode('Out[\\#]: ', config=True,
334 334 help="Deprecated, use PromptManager.out_template")
335 335 prompts_pad_left = CBool(True, config=True,
336 336 help="Deprecated, use PromptManager.justify")
337 337
338 338 def _prompt_trait_changed(self, name, old, new):
339 339 table = {
340 340 'prompt_in1' : 'in_template',
341 341 'prompt_in2' : 'in2_template',
342 342 'prompt_out' : 'out_template',
343 343 'prompts_pad_left' : 'justify',
344 344 }
345 345 warn("InteractiveShell.{name} is deprecated, use PromptManager.{newname}\n".format(
346 346 name=name, newname=table[name])
347 347 )
348 348 # protect against weird cases where self.config may not exist:
349 349 if self.config is not None:
350 350 # propagate to corresponding PromptManager trait
351 351 setattr(self.config.PromptManager, table[name], new)
352 352
353 353 _prompt_in1_changed = _prompt_trait_changed
354 354 _prompt_in2_changed = _prompt_trait_changed
355 355 _prompt_out_changed = _prompt_trait_changed
356 356 _prompt_pad_left_changed = _prompt_trait_changed
357 357
358 358 show_rewritten_input = CBool(True, config=True,
359 359 help="Show rewritten input, e.g. for autocall."
360 360 )
361 361
362 362 quiet = CBool(False, config=True)
363 363
364 364 history_length = Integer(10000, config=True)
365 365
366 366 # The readline stuff will eventually be moved to the terminal subclass
367 367 # but for now, we can't do that as readline is welded in everywhere.
368 368 readline_use = CBool(True, config=True)
369 369 readline_remove_delims = Unicode('-/~', config=True)
370 370 # don't use \M- bindings by default, because they
371 371 # conflict with 8-bit encodings. See gh-58,gh-88
372 372 readline_parse_and_bind = List([
373 373 'tab: complete',
374 374 '"\C-l": clear-screen',
375 375 'set show-all-if-ambiguous on',
376 376 '"\C-o": tab-insert',
377 377 '"\C-r": reverse-search-history',
378 378 '"\C-s": forward-search-history',
379 379 '"\C-p": history-search-backward',
380 380 '"\C-n": history-search-forward',
381 381 '"\e[A": history-search-backward',
382 382 '"\e[B": history-search-forward',
383 383 '"\C-k": kill-line',
384 384 '"\C-u": unix-line-discard',
385 385 ], allow_none=False, config=True)
386 386
387 387 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
388 388 default_value='last_expr', config=True,
389 389 help="""
390 390 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
391 391 run interactively (displaying output from expressions).""")
392 392
393 393 # TODO: this part of prompt management should be moved to the frontends.
394 394 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
395 395 separate_in = SeparateUnicode('\n', config=True)
396 396 separate_out = SeparateUnicode('', config=True)
397 397 separate_out2 = SeparateUnicode('', config=True)
398 398 wildcards_case_sensitive = CBool(True, config=True)
399 399 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
400 400 default_value='Context', config=True)
401 401
402 402 # Subcomponents of InteractiveShell
403 403 alias_manager = Instance('IPython.core.alias.AliasManager')
404 404 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
405 405 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap')
406 406 display_trap = Instance('IPython.core.display_trap.DisplayTrap')
407 407 extension_manager = Instance('IPython.core.extensions.ExtensionManager')
408 408 plugin_manager = Instance('IPython.core.plugin.PluginManager')
409 409 payload_manager = Instance('IPython.core.payload.PayloadManager')
410 410 history_manager = Instance('IPython.core.history.HistoryManager')
411 411 magics_manager = Instance('IPython.core.magic.MagicsManager')
412 412
413 413 profile_dir = Instance('IPython.core.application.ProfileDir')
414 414 @property
415 415 def profile(self):
416 416 if self.profile_dir is not None:
417 417 name = os.path.basename(self.profile_dir.location)
418 418 return name.replace('profile_','')
419 419
420 420
421 421 # Private interface
422 422 _post_execute = Instance(dict)
423 423
424 424 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
425 425 user_module=None, user_ns=None,
426 426 custom_exceptions=((), None)):
427 427
428 428 # This is where traits with a config_key argument are updated
429 429 # from the values on config.
430 430 super(InteractiveShell, self).__init__(config=config)
431 431 self.configurables = [self]
432 432
433 433 # These are relatively independent and stateless
434 434 self.init_ipython_dir(ipython_dir)
435 435 self.init_profile_dir(profile_dir)
436 436 self.init_instance_attrs()
437 437 self.init_environment()
438 438
439 439 # Check if we're in a virtualenv, and set up sys.path.
440 440 self.init_virtualenv()
441 441
442 442 # Create namespaces (user_ns, user_global_ns, etc.)
443 443 self.init_create_namespaces(user_module, user_ns)
444 444 # This has to be done after init_create_namespaces because it uses
445 445 # something in self.user_ns, but before init_sys_modules, which
446 446 # is the first thing to modify sys.
447 447 # TODO: When we override sys.stdout and sys.stderr before this class
448 448 # is created, we are saving the overridden ones here. Not sure if this
449 449 # is what we want to do.
450 450 self.save_sys_module_state()
451 451 self.init_sys_modules()
452 452
453 453 # While we're trying to have each part of the code directly access what
454 454 # it needs without keeping redundant references to objects, we have too
455 455 # much legacy code that expects ip.db to exist.
456 456 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
457 457
458 458 self.init_history()
459 459 self.init_encoding()
460 460 self.init_prefilter()
461 461
462 462 self.init_syntax_highlighting()
463 463 self.init_hooks()
464 464 self.init_pushd_popd_magic()
465 465 # self.init_traceback_handlers use to be here, but we moved it below
466 466 # because it and init_io have to come after init_readline.
467 467 self.init_user_ns()
468 468 self.init_logger()
469 469 self.init_alias()
470 470 self.init_builtins()
471 471
472 472 # pre_config_initialization
473 473
474 474 # The next section should contain everything that was in ipmaker.
475 475 self.init_logstart()
476 476
477 477 # The following was in post_config_initialization
478 478 self.init_inspector()
479 479 # init_readline() must come before init_io(), because init_io uses
480 480 # readline related things.
481 481 self.init_readline()
482 482 # We save this here in case user code replaces raw_input, but it needs
483 483 # to be after init_readline(), because PyPy's readline works by replacing
484 484 # raw_input.
485 485 if py3compat.PY3:
486 486 self.raw_input_original = input
487 487 else:
488 488 self.raw_input_original = raw_input
489 489 # init_completer must come after init_readline, because it needs to
490 490 # know whether readline is present or not system-wide to configure the
491 491 # completers, since the completion machinery can now operate
492 492 # independently of readline (e.g. over the network)
493 493 self.init_completer()
494 494 # TODO: init_io() needs to happen before init_traceback handlers
495 495 # because the traceback handlers hardcode the stdout/stderr streams.
496 496 # This logic in in debugger.Pdb and should eventually be changed.
497 497 self.init_io()
498 498 self.init_traceback_handlers(custom_exceptions)
499 499 self.init_prompts()
500 500 self.init_display_formatter()
501 501 self.init_display_pub()
502 502 self.init_displayhook()
503 503 self.init_reload_doctest()
504 504 self.init_magics()
505 505 self.init_pdb()
506 506 self.init_extension_manager()
507 507 self.init_plugin_manager()
508 508 self.init_payload()
509 509 self.hooks.late_startup_hook()
510 510 atexit.register(self.atexit_operations)
511 511
512 512 def get_ipython(self):
513 513 """Return the currently running IPython instance."""
514 514 return self
515 515
516 516 #-------------------------------------------------------------------------
517 517 # Trait changed handlers
518 518 #-------------------------------------------------------------------------
519 519
520 520 def _ipython_dir_changed(self, name, new):
521 521 if not os.path.isdir(new):
522 522 os.makedirs(new, mode = 0777)
523 523
524 524 def set_autoindent(self,value=None):
525 525 """Set the autoindent flag, checking for readline support.
526 526
527 527 If called with no arguments, it acts as a toggle."""
528 528
529 529 if value != 0 and not self.has_readline:
530 530 if os.name == 'posix':
531 531 warn("The auto-indent feature requires the readline library")
532 532 self.autoindent = 0
533 533 return
534 534 if value is None:
535 535 self.autoindent = not self.autoindent
536 536 else:
537 537 self.autoindent = value
538 538
539 539 #-------------------------------------------------------------------------
540 540 # init_* methods called by __init__
541 541 #-------------------------------------------------------------------------
542 542
543 543 def init_ipython_dir(self, ipython_dir):
544 544 if ipython_dir is not None:
545 545 self.ipython_dir = ipython_dir
546 546 return
547 547
548 548 self.ipython_dir = get_ipython_dir()
549 549
550 550 def init_profile_dir(self, profile_dir):
551 551 if profile_dir is not None:
552 552 self.profile_dir = profile_dir
553 553 return
554 554 self.profile_dir =\
555 555 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
556 556
557 557 def init_instance_attrs(self):
558 558 self.more = False
559 559
560 560 # command compiler
561 561 self.compile = CachingCompiler()
562 562
563 563 # Make an empty namespace, which extension writers can rely on both
564 564 # existing and NEVER being used by ipython itself. This gives them a
565 565 # convenient location for storing additional information and state
566 566 # their extensions may require, without fear of collisions with other
567 567 # ipython names that may develop later.
568 568 self.meta = Struct()
569 569
570 570 # Temporary files used for various purposes. Deleted at exit.
571 571 self.tempfiles = []
572 572
573 573 # Keep track of readline usage (later set by init_readline)
574 574 self.has_readline = False
575 575
576 576 # keep track of where we started running (mainly for crash post-mortem)
577 577 # This is not being used anywhere currently.
578 578 self.starting_dir = os.getcwdu()
579 579
580 580 # Indentation management
581 581 self.indent_current_nsp = 0
582 582
583 583 # Dict to track post-execution functions that have been registered
584 584 self._post_execute = {}
585 585
586 586 def init_environment(self):
587 587 """Any changes we need to make to the user's environment."""
588 588 pass
589 589
590 590 def init_encoding(self):
591 591 # Get system encoding at startup time. Certain terminals (like Emacs
592 592 # under Win32 have it set to None, and we need to have a known valid
593 593 # encoding to use in the raw_input() method
594 594 try:
595 595 self.stdin_encoding = sys.stdin.encoding or 'ascii'
596 596 except AttributeError:
597 597 self.stdin_encoding = 'ascii'
598 598
599 599 def init_syntax_highlighting(self):
600 600 # Python source parser/formatter for syntax highlighting
601 601 pyformat = PyColorize.Parser().format
602 602 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
603 603
604 604 def init_pushd_popd_magic(self):
605 605 # for pushd/popd management
606 606 self.home_dir = get_home_dir()
607 607
608 608 self.dir_stack = []
609 609
610 610 def init_logger(self):
611 611 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
612 612 logmode='rotate')
613 613
614 614 def init_logstart(self):
615 615 """Initialize logging in case it was requested at the command line.
616 616 """
617 617 if self.logappend:
618 618 self.magic('logstart %s append' % self.logappend)
619 619 elif self.logfile:
620 620 self.magic('logstart %' % self.logfile)
621 621 elif self.logstart:
622 622 self.magic('logstart')
623 623
624 624 def init_builtins(self):
625 625 # A single, static flag that we set to True. Its presence indicates
626 626 # that an IPython shell has been created, and we make no attempts at
627 627 # removing on exit or representing the existence of more than one
628 628 # IPython at a time.
629 629 builtin_mod.__dict__['__IPYTHON__'] = True
630 630
631 631 # In 0.11 we introduced '__IPYTHON__active' as an integer we'd try to
632 632 # manage on enter/exit, but with all our shells it's virtually
633 633 # impossible to get all the cases right. We're leaving the name in for
634 634 # those who adapted their codes to check for this flag, but will
635 635 # eventually remove it after a few more releases.
636 636 builtin_mod.__dict__['__IPYTHON__active'] = \
637 637 'Deprecated, check for __IPYTHON__'
638 638
639 639 self.builtin_trap = BuiltinTrap(shell=self)
640 640
641 641 def init_inspector(self):
642 642 # Object inspector
643 643 self.inspector = oinspect.Inspector(oinspect.InspectColors,
644 644 PyColorize.ANSICodeColors,
645 645 'NoColor',
646 646 self.object_info_string_level)
647 647
648 648 def init_io(self):
649 649 # This will just use sys.stdout and sys.stderr. If you want to
650 650 # override sys.stdout and sys.stderr themselves, you need to do that
651 651 # *before* instantiating this class, because io holds onto
652 652 # references to the underlying streams.
653 653 if sys.platform == 'win32' and self.has_readline:
654 654 io.stdout = io.stderr = io.IOStream(self.readline._outputfile)
655 655 else:
656 656 io.stdout = io.IOStream(sys.stdout)
657 657 io.stderr = io.IOStream(sys.stderr)
658 658
659 659 def init_prompts(self):
660 660 self.prompt_manager = PromptManager(shell=self, config=self.config)
661 661 self.configurables.append(self.prompt_manager)
662 662 # Set system prompts, so that scripts can decide if they are running
663 663 # interactively.
664 664 sys.ps1 = 'In : '
665 665 sys.ps2 = '...: '
666 666 sys.ps3 = 'Out: '
667 667
668 668 def init_display_formatter(self):
669 669 self.display_formatter = DisplayFormatter(config=self.config)
670 670 self.configurables.append(self.display_formatter)
671 671
672 672 def init_display_pub(self):
673 673 self.display_pub = self.display_pub_class(config=self.config)
674 674 self.configurables.append(self.display_pub)
675 675
676 676 def init_displayhook(self):
677 677 # Initialize displayhook, set in/out prompts and printing system
678 678 self.displayhook = self.displayhook_class(
679 679 config=self.config,
680 680 shell=self,
681 681 cache_size=self.cache_size,
682 682 )
683 683 self.configurables.append(self.displayhook)
684 684 # This is a context manager that installs/revmoes the displayhook at
685 685 # the appropriate time.
686 686 self.display_trap = DisplayTrap(hook=self.displayhook)
687 687
688 688 def init_reload_doctest(self):
689 689 # Do a proper resetting of doctest, including the necessary displayhook
690 690 # monkeypatching
691 691 try:
692 692 doctest_reload()
693 693 except ImportError:
694 694 warn("doctest module does not exist.")
695 695
696 696 def init_virtualenv(self):
697 697 """Add a virtualenv to sys.path so the user can import modules from it.
698 698 This isn't perfect: it doesn't use the Python interpreter with which the
699 699 virtualenv was built, and it ignores the --no-site-packages option. A
700 700 warning will appear suggesting the user installs IPython in the
701 701 virtualenv, but for many cases, it probably works well enough.
702 702
703 703 Adapted from code snippets online.
704 704
705 705 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
706 706 """
707 707 if 'VIRTUAL_ENV' not in os.environ:
708 708 # Not in a virtualenv
709 709 return
710 710
711 711 if sys.executable.startswith(os.environ['VIRTUAL_ENV']):
712 712 # Running properly in the virtualenv, don't need to do anything
713 713 return
714 714
715 715 warn("Attempting to work in a virtualenv. If you encounter problems, please "
716 716 "install IPython inside the virtualenv.\n")
717 717 if sys.platform == "win32":
718 718 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
719 719 else:
720 720 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
721 721 'python%d.%d' % sys.version_info[:2], 'site-packages')
722 722
723 723 import site
724 724 sys.path.insert(0, virtual_env)
725 725 site.addsitedir(virtual_env)
726 726
727 727 #-------------------------------------------------------------------------
728 728 # Things related to injections into the sys module
729 729 #-------------------------------------------------------------------------
730 730
731 731 def save_sys_module_state(self):
732 732 """Save the state of hooks in the sys module.
733 733
734 734 This has to be called after self.user_module is created.
735 735 """
736 736 self._orig_sys_module_state = {}
737 737 self._orig_sys_module_state['stdin'] = sys.stdin
738 738 self._orig_sys_module_state['stdout'] = sys.stdout
739 739 self._orig_sys_module_state['stderr'] = sys.stderr
740 740 self._orig_sys_module_state['excepthook'] = sys.excepthook
741 741 self._orig_sys_modules_main_name = self.user_module.__name__
742 742 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
743 743
744 744 def restore_sys_module_state(self):
745 745 """Restore the state of the sys module."""
746 746 try:
747 747 for k, v in self._orig_sys_module_state.iteritems():
748 748 setattr(sys, k, v)
749 749 except AttributeError:
750 750 pass
751 751 # Reset what what done in self.init_sys_modules
752 752 if self._orig_sys_modules_main_mod is not None:
753 753 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
754 754
755 755 #-------------------------------------------------------------------------
756 756 # Things related to hooks
757 757 #-------------------------------------------------------------------------
758 758
759 759 def init_hooks(self):
760 760 # hooks holds pointers used for user-side customizations
761 761 self.hooks = Struct()
762 762
763 763 self.strdispatchers = {}
764 764
765 765 # Set all default hooks, defined in the IPython.hooks module.
766 766 hooks = IPython.core.hooks
767 767 for hook_name in hooks.__all__:
768 768 # default hooks have priority 100, i.e. low; user hooks should have
769 769 # 0-100 priority
770 770 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
771 771
772 772 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
773 773 """set_hook(name,hook) -> sets an internal IPython hook.
774 774
775 775 IPython exposes some of its internal API as user-modifiable hooks. By
776 776 adding your function to one of these hooks, you can modify IPython's
777 777 behavior to call at runtime your own routines."""
778 778
779 779 # At some point in the future, this should validate the hook before it
780 780 # accepts it. Probably at least check that the hook takes the number
781 781 # of args it's supposed to.
782 782
783 783 f = types.MethodType(hook,self)
784 784
785 785 # check if the hook is for strdispatcher first
786 786 if str_key is not None:
787 787 sdp = self.strdispatchers.get(name, StrDispatch())
788 788 sdp.add_s(str_key, f, priority )
789 789 self.strdispatchers[name] = sdp
790 790 return
791 791 if re_key is not None:
792 792 sdp = self.strdispatchers.get(name, StrDispatch())
793 793 sdp.add_re(re.compile(re_key), f, priority )
794 794 self.strdispatchers[name] = sdp
795 795 return
796 796
797 797 dp = getattr(self.hooks, name, None)
798 798 if name not in IPython.core.hooks.__all__:
799 799 print "Warning! Hook '%s' is not one of %s" % \
800 800 (name, IPython.core.hooks.__all__ )
801 801 if not dp:
802 802 dp = IPython.core.hooks.CommandChainDispatcher()
803 803
804 804 try:
805 805 dp.add(f,priority)
806 806 except AttributeError:
807 807 # it was not commandchain, plain old func - replace
808 808 dp = f
809 809
810 810 setattr(self.hooks,name, dp)
811 811
812 812 def register_post_execute(self, func):
813 813 """Register a function for calling after code execution.
814 814 """
815 815 if not callable(func):
816 816 raise ValueError('argument %s must be callable' % func)
817 817 self._post_execute[func] = True
818 818
819 819 #-------------------------------------------------------------------------
820 820 # Things related to the "main" module
821 821 #-------------------------------------------------------------------------
822 822
823 823 def new_main_mod(self,ns=None):
824 824 """Return a new 'main' module object for user code execution.
825 825 """
826 826 main_mod = self._user_main_module
827 827 init_fakemod_dict(main_mod,ns)
828 828 return main_mod
829 829
830 830 def cache_main_mod(self,ns,fname):
831 831 """Cache a main module's namespace.
832 832
833 833 When scripts are executed via %run, we must keep a reference to the
834 834 namespace of their __main__ module (a FakeModule instance) around so
835 835 that Python doesn't clear it, rendering objects defined therein
836 836 useless.
837 837
838 838 This method keeps said reference in a private dict, keyed by the
839 839 absolute path of the module object (which corresponds to the script
840 840 path). This way, for multiple executions of the same script we only
841 841 keep one copy of the namespace (the last one), thus preventing memory
842 842 leaks from old references while allowing the objects from the last
843 843 execution to be accessible.
844 844
845 845 Note: we can not allow the actual FakeModule instances to be deleted,
846 846 because of how Python tears down modules (it hard-sets all their
847 847 references to None without regard for reference counts). This method
848 848 must therefore make a *copy* of the given namespace, to allow the
849 849 original module's __dict__ to be cleared and reused.
850 850
851 851
852 852 Parameters
853 853 ----------
854 854 ns : a namespace (a dict, typically)
855 855
856 856 fname : str
857 857 Filename associated with the namespace.
858 858
859 859 Examples
860 860 --------
861 861
862 862 In [10]: import IPython
863 863
864 864 In [11]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
865 865
866 866 In [12]: IPython.__file__ in _ip._main_ns_cache
867 867 Out[12]: True
868 868 """
869 869 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
870 870
871 871 def clear_main_mod_cache(self):
872 872 """Clear the cache of main modules.
873 873
874 874 Mainly for use by utilities like %reset.
875 875
876 876 Examples
877 877 --------
878 878
879 879 In [15]: import IPython
880 880
881 881 In [16]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
882 882
883 883 In [17]: len(_ip._main_ns_cache) > 0
884 884 Out[17]: True
885 885
886 886 In [18]: _ip.clear_main_mod_cache()
887 887
888 888 In [19]: len(_ip._main_ns_cache) == 0
889 889 Out[19]: True
890 890 """
891 891 self._main_ns_cache.clear()
892 892
893 893 #-------------------------------------------------------------------------
894 894 # Things related to debugging
895 895 #-------------------------------------------------------------------------
896 896
897 897 def init_pdb(self):
898 898 # Set calling of pdb on exceptions
899 899 # self.call_pdb is a property
900 900 self.call_pdb = self.pdb
901 901
902 902 def _get_call_pdb(self):
903 903 return self._call_pdb
904 904
905 905 def _set_call_pdb(self,val):
906 906
907 907 if val not in (0,1,False,True):
908 908 raise ValueError,'new call_pdb value must be boolean'
909 909
910 910 # store value in instance
911 911 self._call_pdb = val
912 912
913 913 # notify the actual exception handlers
914 914 self.InteractiveTB.call_pdb = val
915 915
916 916 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
917 917 'Control auto-activation of pdb at exceptions')
918 918
919 919 def debugger(self,force=False):
920 920 """Call the pydb/pdb debugger.
921 921
922 922 Keywords:
923 923
924 924 - force(False): by default, this routine checks the instance call_pdb
925 925 flag and does not actually invoke the debugger if the flag is false.
926 926 The 'force' option forces the debugger to activate even if the flag
927 927 is false.
928 928 """
929 929
930 930 if not (force or self.call_pdb):
931 931 return
932 932
933 933 if not hasattr(sys,'last_traceback'):
934 934 error('No traceback has been produced, nothing to debug.')
935 935 return
936 936
937 937 # use pydb if available
938 938 if debugger.has_pydb:
939 939 from pydb import pm
940 940 else:
941 941 # fallback to our internal debugger
942 942 pm = lambda : self.InteractiveTB.debugger(force=True)
943 943
944 944 with self.readline_no_record:
945 945 pm()
946 946
947 947 #-------------------------------------------------------------------------
948 948 # Things related to IPython's various namespaces
949 949 #-------------------------------------------------------------------------
950 950 default_user_namespaces = True
951 951
952 952 def init_create_namespaces(self, user_module=None, user_ns=None):
953 953 # Create the namespace where the user will operate. user_ns is
954 954 # normally the only one used, and it is passed to the exec calls as
955 955 # the locals argument. But we do carry a user_global_ns namespace
956 956 # given as the exec 'globals' argument, This is useful in embedding
957 957 # situations where the ipython shell opens in a context where the
958 958 # distinction between locals and globals is meaningful. For
959 959 # non-embedded contexts, it is just the same object as the user_ns dict.
960 960
961 961 # FIXME. For some strange reason, __builtins__ is showing up at user
962 962 # level as a dict instead of a module. This is a manual fix, but I
963 963 # should really track down where the problem is coming from. Alex
964 964 # Schmolck reported this problem first.
965 965
966 966 # A useful post by Alex Martelli on this topic:
967 967 # Re: inconsistent value from __builtins__
968 968 # Von: Alex Martelli <aleaxit@yahoo.com>
969 969 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
970 970 # Gruppen: comp.lang.python
971 971
972 972 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
973 973 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
974 974 # > <type 'dict'>
975 975 # > >>> print type(__builtins__)
976 976 # > <type 'module'>
977 977 # > Is this difference in return value intentional?
978 978
979 979 # Well, it's documented that '__builtins__' can be either a dictionary
980 980 # or a module, and it's been that way for a long time. Whether it's
981 981 # intentional (or sensible), I don't know. In any case, the idea is
982 982 # that if you need to access the built-in namespace directly, you
983 983 # should start with "import __builtin__" (note, no 's') which will
984 984 # definitely give you a module. Yeah, it's somewhat confusing:-(.
985 985
986 986 # These routines return a properly built module and dict as needed by
987 987 # the rest of the code, and can also be used by extension writers to
988 988 # generate properly initialized namespaces.
989 989 if (user_ns is not None) or (user_module is not None):
990 990 self.default_user_namespaces = False
991 991 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
992 992
993 993 # A record of hidden variables we have added to the user namespace, so
994 994 # we can list later only variables defined in actual interactive use.
995 995 self.user_ns_hidden = set()
996 996
997 997 # Now that FakeModule produces a real module, we've run into a nasty
998 998 # problem: after script execution (via %run), the module where the user
999 999 # code ran is deleted. Now that this object is a true module (needed
1000 1000 # so docetst and other tools work correctly), the Python module
1001 1001 # teardown mechanism runs over it, and sets to None every variable
1002 1002 # present in that module. Top-level references to objects from the
1003 1003 # script survive, because the user_ns is updated with them. However,
1004 1004 # calling functions defined in the script that use other things from
1005 1005 # the script will fail, because the function's closure had references
1006 1006 # to the original objects, which are now all None. So we must protect
1007 1007 # these modules from deletion by keeping a cache.
1008 1008 #
1009 1009 # To avoid keeping stale modules around (we only need the one from the
1010 1010 # last run), we use a dict keyed with the full path to the script, so
1011 1011 # only the last version of the module is held in the cache. Note,
1012 1012 # however, that we must cache the module *namespace contents* (their
1013 1013 # __dict__). Because if we try to cache the actual modules, old ones
1014 1014 # (uncached) could be destroyed while still holding references (such as
1015 1015 # those held by GUI objects that tend to be long-lived)>
1016 1016 #
1017 1017 # The %reset command will flush this cache. See the cache_main_mod()
1018 1018 # and clear_main_mod_cache() methods for details on use.
1019 1019
1020 1020 # This is the cache used for 'main' namespaces
1021 1021 self._main_ns_cache = {}
1022 1022 # And this is the single instance of FakeModule whose __dict__ we keep
1023 1023 # copying and clearing for reuse on each %run
1024 1024 self._user_main_module = FakeModule()
1025 1025
1026 1026 # A table holding all the namespaces IPython deals with, so that
1027 1027 # introspection facilities can search easily.
1028 1028 self.ns_table = {'user_global':self.user_module.__dict__,
1029 1029 'user_local':self.user_ns,
1030 1030 'builtin':builtin_mod.__dict__
1031 1031 }
1032 1032
1033 1033 @property
1034 1034 def user_global_ns(self):
1035 1035 return self.user_module.__dict__
1036 1036
1037 1037 def prepare_user_module(self, user_module=None, user_ns=None):
1038 1038 """Prepare the module and namespace in which user code will be run.
1039 1039
1040 1040 When IPython is started normally, both parameters are None: a new module
1041 1041 is created automatically, and its __dict__ used as the namespace.
1042 1042
1043 1043 If only user_module is provided, its __dict__ is used as the namespace.
1044 1044 If only user_ns is provided, a dummy module is created, and user_ns
1045 1045 becomes the global namespace. If both are provided (as they may be
1046 1046 when embedding), user_ns is the local namespace, and user_module
1047 1047 provides the global namespace.
1048 1048
1049 1049 Parameters
1050 1050 ----------
1051 1051 user_module : module, optional
1052 1052 The current user module in which IPython is being run. If None,
1053 1053 a clean module will be created.
1054 1054 user_ns : dict, optional
1055 1055 A namespace in which to run interactive commands.
1056 1056
1057 1057 Returns
1058 1058 -------
1059 1059 A tuple of user_module and user_ns, each properly initialised.
1060 1060 """
1061 1061 if user_module is None and user_ns is not None:
1062 1062 user_ns.setdefault("__name__", "__main__")
1063 1063 class DummyMod(object):
1064 1064 "A dummy module used for IPython's interactive namespace."
1065 1065 pass
1066 1066 user_module = DummyMod()
1067 1067 user_module.__dict__ = user_ns
1068 1068
1069 1069 if user_module is None:
1070 1070 user_module = types.ModuleType("__main__",
1071 1071 doc="Automatically created module for IPython interactive environment")
1072 1072
1073 1073 # We must ensure that __builtin__ (without the final 's') is always
1074 1074 # available and pointing to the __builtin__ *module*. For more details:
1075 1075 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1076 1076 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1077 1077 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1078 1078
1079 1079 if user_ns is None:
1080 1080 user_ns = user_module.__dict__
1081 1081
1082 1082 return user_module, user_ns
1083 1083
1084 1084 def init_sys_modules(self):
1085 1085 # We need to insert into sys.modules something that looks like a
1086 1086 # module but which accesses the IPython namespace, for shelve and
1087 1087 # pickle to work interactively. Normally they rely on getting
1088 1088 # everything out of __main__, but for embedding purposes each IPython
1089 1089 # instance has its own private namespace, so we can't go shoving
1090 1090 # everything into __main__.
1091 1091
1092 1092 # note, however, that we should only do this for non-embedded
1093 1093 # ipythons, which really mimic the __main__.__dict__ with their own
1094 1094 # namespace. Embedded instances, on the other hand, should not do
1095 1095 # this because they need to manage the user local/global namespaces
1096 1096 # only, but they live within a 'normal' __main__ (meaning, they
1097 1097 # shouldn't overtake the execution environment of the script they're
1098 1098 # embedded in).
1099 1099
1100 1100 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1101 1101 main_name = self.user_module.__name__
1102 1102 sys.modules[main_name] = self.user_module
1103 1103
1104 1104 def init_user_ns(self):
1105 1105 """Initialize all user-visible namespaces to their minimum defaults.
1106 1106
1107 1107 Certain history lists are also initialized here, as they effectively
1108 1108 act as user namespaces.
1109 1109
1110 1110 Notes
1111 1111 -----
1112 1112 All data structures here are only filled in, they are NOT reset by this
1113 1113 method. If they were not empty before, data will simply be added to
1114 1114 therm.
1115 1115 """
1116 1116 # This function works in two parts: first we put a few things in
1117 1117 # user_ns, and we sync that contents into user_ns_hidden so that these
1118 1118 # initial variables aren't shown by %who. After the sync, we add the
1119 1119 # rest of what we *do* want the user to see with %who even on a new
1120 1120 # session (probably nothing, so theye really only see their own stuff)
1121 1121
1122 1122 # The user dict must *always* have a __builtin__ reference to the
1123 1123 # Python standard __builtin__ namespace, which must be imported.
1124 1124 # This is so that certain operations in prompt evaluation can be
1125 1125 # reliably executed with builtins. Note that we can NOT use
1126 1126 # __builtins__ (note the 's'), because that can either be a dict or a
1127 1127 # module, and can even mutate at runtime, depending on the context
1128 1128 # (Python makes no guarantees on it). In contrast, __builtin__ is
1129 1129 # always a module object, though it must be explicitly imported.
1130 1130
1131 1131 # For more details:
1132 1132 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1133 1133 ns = dict()
1134 1134
1135 1135 # Put 'help' in the user namespace
1136 1136 try:
1137 1137 from site import _Helper
1138 1138 ns['help'] = _Helper()
1139 1139 except ImportError:
1140 1140 warn('help() not available - check site.py')
1141 1141
1142 1142 # make global variables for user access to the histories
1143 1143 ns['_ih'] = self.history_manager.input_hist_parsed
1144 1144 ns['_oh'] = self.history_manager.output_hist
1145 1145 ns['_dh'] = self.history_manager.dir_hist
1146 1146
1147 1147 ns['_sh'] = shadowns
1148 1148
1149 1149 # user aliases to input and output histories. These shouldn't show up
1150 1150 # in %who, as they can have very large reprs.
1151 1151 ns['In'] = self.history_manager.input_hist_parsed
1152 1152 ns['Out'] = self.history_manager.output_hist
1153 1153
1154 1154 # Store myself as the public api!!!
1155 1155 ns['get_ipython'] = self.get_ipython
1156 1156
1157 1157 ns['exit'] = self.exiter
1158 1158 ns['quit'] = self.exiter
1159 1159
1160 1160 # Sync what we've added so far to user_ns_hidden so these aren't seen
1161 1161 # by %who
1162 1162 self.user_ns_hidden.update(ns)
1163 1163
1164 1164 # Anything put into ns now would show up in %who. Think twice before
1165 1165 # putting anything here, as we really want %who to show the user their
1166 1166 # stuff, not our variables.
1167 1167
1168 1168 # Finally, update the real user's namespace
1169 1169 self.user_ns.update(ns)
1170 1170
1171 1171 @property
1172 1172 def all_ns_refs(self):
1173 1173 """Get a list of references to all the namespace dictionaries in which
1174 1174 IPython might store a user-created object.
1175 1175
1176 1176 Note that this does not include the displayhook, which also caches
1177 1177 objects from the output."""
1178 1178 return [self.user_ns, self.user_global_ns,
1179 1179 self._user_main_module.__dict__] + self._main_ns_cache.values()
1180 1180
1181 1181 def reset(self, new_session=True):
1182 1182 """Clear all internal namespaces, and attempt to release references to
1183 1183 user objects.
1184 1184
1185 1185 If new_session is True, a new history session will be opened.
1186 1186 """
1187 1187 # Clear histories
1188 1188 self.history_manager.reset(new_session)
1189 1189 # Reset counter used to index all histories
1190 1190 if new_session:
1191 1191 self.execution_count = 1
1192 1192
1193 1193 # Flush cached output items
1194 1194 if self.displayhook.do_full_cache:
1195 1195 self.displayhook.flush()
1196 1196
1197 1197 # The main execution namespaces must be cleared very carefully,
1198 1198 # skipping the deletion of the builtin-related keys, because doing so
1199 1199 # would cause errors in many object's __del__ methods.
1200 1200 if self.user_ns is not self.user_global_ns:
1201 1201 self.user_ns.clear()
1202 1202 ns = self.user_global_ns
1203 1203 drop_keys = set(ns.keys())
1204 1204 drop_keys.discard('__builtin__')
1205 1205 drop_keys.discard('__builtins__')
1206 1206 drop_keys.discard('__name__')
1207 1207 for k in drop_keys:
1208 1208 del ns[k]
1209 1209
1210 1210 self.user_ns_hidden.clear()
1211 1211
1212 1212 # Restore the user namespaces to minimal usability
1213 1213 self.init_user_ns()
1214 1214
1215 1215 # Restore the default and user aliases
1216 1216 self.alias_manager.clear_aliases()
1217 1217 self.alias_manager.init_aliases()
1218 1218
1219 1219 # Flush the private list of module references kept for script
1220 1220 # execution protection
1221 1221 self.clear_main_mod_cache()
1222 1222
1223 1223 # Clear out the namespace from the last %run
1224 1224 self.new_main_mod()
1225 1225
1226 1226 def del_var(self, varname, by_name=False):
1227 1227 """Delete a variable from the various namespaces, so that, as
1228 1228 far as possible, we're not keeping any hidden references to it.
1229 1229
1230 1230 Parameters
1231 1231 ----------
1232 1232 varname : str
1233 1233 The name of the variable to delete.
1234 1234 by_name : bool
1235 1235 If True, delete variables with the given name in each
1236 1236 namespace. If False (default), find the variable in the user
1237 1237 namespace, and delete references to it.
1238 1238 """
1239 1239 if varname in ('__builtin__', '__builtins__'):
1240 1240 raise ValueError("Refusing to delete %s" % varname)
1241 1241
1242 1242 ns_refs = self.all_ns_refs
1243 1243
1244 1244 if by_name: # Delete by name
1245 1245 for ns in ns_refs:
1246 1246 try:
1247 1247 del ns[varname]
1248 1248 except KeyError:
1249 1249 pass
1250 1250 else: # Delete by object
1251 1251 try:
1252 1252 obj = self.user_ns[varname]
1253 1253 except KeyError:
1254 1254 raise NameError("name '%s' is not defined" % varname)
1255 1255 # Also check in output history
1256 1256 ns_refs.append(self.history_manager.output_hist)
1257 1257 for ns in ns_refs:
1258 1258 to_delete = [n for n, o in ns.iteritems() if o is obj]
1259 1259 for name in to_delete:
1260 1260 del ns[name]
1261 1261
1262 1262 # displayhook keeps extra references, but not in a dictionary
1263 1263 for name in ('_', '__', '___'):
1264 1264 if getattr(self.displayhook, name) is obj:
1265 1265 setattr(self.displayhook, name, None)
1266 1266
1267 1267 def reset_selective(self, regex=None):
1268 1268 """Clear selective variables from internal namespaces based on a
1269 1269 specified regular expression.
1270 1270
1271 1271 Parameters
1272 1272 ----------
1273 1273 regex : string or compiled pattern, optional
1274 1274 A regular expression pattern that will be used in searching
1275 1275 variable names in the users namespaces.
1276 1276 """
1277 1277 if regex is not None:
1278 1278 try:
1279 1279 m = re.compile(regex)
1280 1280 except TypeError:
1281 1281 raise TypeError('regex must be a string or compiled pattern')
1282 1282 # Search for keys in each namespace that match the given regex
1283 1283 # If a match is found, delete the key/value pair.
1284 1284 for ns in self.all_ns_refs:
1285 1285 for var in ns:
1286 1286 if m.search(var):
1287 1287 del ns[var]
1288 1288
1289 1289 def push(self, variables, interactive=True):
1290 1290 """Inject a group of variables into the IPython user namespace.
1291 1291
1292 1292 Parameters
1293 1293 ----------
1294 1294 variables : dict, str or list/tuple of str
1295 1295 The variables to inject into the user's namespace. If a dict, a
1296 1296 simple update is done. If a str, the string is assumed to have
1297 1297 variable names separated by spaces. A list/tuple of str can also
1298 1298 be used to give the variable names. If just the variable names are
1299 1299 give (list/tuple/str) then the variable values looked up in the
1300 1300 callers frame.
1301 1301 interactive : bool
1302 1302 If True (default), the variables will be listed with the ``who``
1303 1303 magic.
1304 1304 """
1305 1305 vdict = None
1306 1306
1307 1307 # We need a dict of name/value pairs to do namespace updates.
1308 1308 if isinstance(variables, dict):
1309 1309 vdict = variables
1310 1310 elif isinstance(variables, (basestring, list, tuple)):
1311 1311 if isinstance(variables, basestring):
1312 1312 vlist = variables.split()
1313 1313 else:
1314 1314 vlist = variables
1315 1315 vdict = {}
1316 1316 cf = sys._getframe(1)
1317 1317 for name in vlist:
1318 1318 try:
1319 1319 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1320 1320 except:
1321 1321 print ('Could not get variable %s from %s' %
1322 1322 (name,cf.f_code.co_name))
1323 1323 else:
1324 1324 raise ValueError('variables must be a dict/str/list/tuple')
1325 1325
1326 1326 # Propagate variables to user namespace
1327 1327 self.user_ns.update(vdict)
1328 1328
1329 1329 # And configure interactive visibility
1330 1330 user_ns_hidden = self.user_ns_hidden
1331 1331 if interactive:
1332 1332 user_ns_hidden.difference_update(vdict)
1333 1333 else:
1334 1334 user_ns_hidden.update(vdict)
1335 1335
1336 1336 def drop_by_id(self, variables):
1337 1337 """Remove a dict of variables from the user namespace, if they are the
1338 1338 same as the values in the dictionary.
1339 1339
1340 1340 This is intended for use by extensions: variables that they've added can
1341 1341 be taken back out if they are unloaded, without removing any that the
1342 1342 user has overwritten.
1343 1343
1344 1344 Parameters
1345 1345 ----------
1346 1346 variables : dict
1347 1347 A dictionary mapping object names (as strings) to the objects.
1348 1348 """
1349 1349 for name, obj in variables.iteritems():
1350 1350 if name in self.user_ns and self.user_ns[name] is obj:
1351 1351 del self.user_ns[name]
1352 1352 self.user_ns_hidden.discard(name)
1353 1353
1354 1354 #-------------------------------------------------------------------------
1355 1355 # Things related to object introspection
1356 1356 #-------------------------------------------------------------------------
1357 1357
1358 1358 def _ofind(self, oname, namespaces=None):
1359 1359 """Find an object in the available namespaces.
1360 1360
1361 1361 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1362 1362
1363 1363 Has special code to detect magic functions.
1364 1364 """
1365 1365 oname = oname.strip()
1366 1366 #print '1- oname: <%r>' % oname # dbg
1367 1367 if not oname.startswith(ESC_MAGIC) and \
1368 1368 not oname.startswith(ESC_MAGIC2) and \
1369 1369 not py3compat.isidentifier(oname, dotted=True):
1370 1370 return dict(found=False)
1371 1371
1372 1372 alias_ns = None
1373 1373 if namespaces is None:
1374 1374 # Namespaces to search in:
1375 1375 # Put them in a list. The order is important so that we
1376 1376 # find things in the same order that Python finds them.
1377 1377 namespaces = [ ('Interactive', self.user_ns),
1378 1378 ('Interactive (global)', self.user_global_ns),
1379 1379 ('Python builtin', builtin_mod.__dict__),
1380 1380 ('Alias', self.alias_manager.alias_table),
1381 1381 ]
1382 1382 alias_ns = self.alias_manager.alias_table
1383 1383
1384 1384 # initialize results to 'null'
1385 1385 found = False; obj = None; ospace = None; ds = None;
1386 1386 ismagic = False; isalias = False; parent = None
1387 1387
1388 1388 # We need to special-case 'print', which as of python2.6 registers as a
1389 1389 # function but should only be treated as one if print_function was
1390 1390 # loaded with a future import. In this case, just bail.
1391 1391 if (oname == 'print' and not py3compat.PY3 and not \
1392 1392 (self.compile.compiler_flags & __future__.CO_FUTURE_PRINT_FUNCTION)):
1393 1393 return {'found':found, 'obj':obj, 'namespace':ospace,
1394 1394 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1395 1395
1396 1396 # Look for the given name by splitting it in parts. If the head is
1397 1397 # found, then we look for all the remaining parts as members, and only
1398 1398 # declare success if we can find them all.
1399 1399 oname_parts = oname.split('.')
1400 1400 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1401 1401 for nsname,ns in namespaces:
1402 1402 try:
1403 1403 obj = ns[oname_head]
1404 1404 except KeyError:
1405 1405 continue
1406 1406 else:
1407 1407 #print 'oname_rest:', oname_rest # dbg
1408 1408 for part in oname_rest:
1409 1409 try:
1410 1410 parent = obj
1411 1411 obj = getattr(obj,part)
1412 1412 except:
1413 1413 # Blanket except b/c some badly implemented objects
1414 1414 # allow __getattr__ to raise exceptions other than
1415 1415 # AttributeError, which then crashes IPython.
1416 1416 break
1417 1417 else:
1418 1418 # If we finish the for loop (no break), we got all members
1419 1419 found = True
1420 1420 ospace = nsname
1421 1421 if ns == alias_ns:
1422 1422 isalias = True
1423 1423 break # namespace loop
1424 1424
1425 1425 # Try to see if it's magic
1426 1426 if not found:
1427 1427 obj = None
1428 1428 if oname.startswith(ESC_MAGIC2):
1429 1429 oname = oname.lstrip(ESC_MAGIC2)
1430 1430 obj = self.find_cell_magic(oname)
1431 1431 elif oname.startswith(ESC_MAGIC):
1432 1432 oname = oname.lstrip(ESC_MAGIC)
1433 1433 obj = self.find_line_magic(oname)
1434 1434 else:
1435 1435 # search without prefix, so run? will find %run?
1436 1436 obj = self.find_line_magic(oname)
1437 1437 if obj is None:
1438 1438 obj = self.find_cell_magic(oname)
1439 1439 if obj is not None:
1440 1440 found = True
1441 1441 ospace = 'IPython internal'
1442 1442 ismagic = True
1443 1443
1444 1444 # Last try: special-case some literals like '', [], {}, etc:
1445 1445 if not found and oname_head in ["''",'""','[]','{}','()']:
1446 1446 obj = eval(oname_head)
1447 1447 found = True
1448 1448 ospace = 'Interactive'
1449 1449
1450 1450 return {'found':found, 'obj':obj, 'namespace':ospace,
1451 1451 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1452 1452
1453 1453 def _ofind_property(self, oname, info):
1454 1454 """Second part of object finding, to look for property details."""
1455 1455 if info.found:
1456 1456 # Get the docstring of the class property if it exists.
1457 1457 path = oname.split('.')
1458 1458 root = '.'.join(path[:-1])
1459 1459 if info.parent is not None:
1460 1460 try:
1461 1461 target = getattr(info.parent, '__class__')
1462 1462 # The object belongs to a class instance.
1463 1463 try:
1464 1464 target = getattr(target, path[-1])
1465 1465 # The class defines the object.
1466 1466 if isinstance(target, property):
1467 1467 oname = root + '.__class__.' + path[-1]
1468 1468 info = Struct(self._ofind(oname))
1469 1469 except AttributeError: pass
1470 1470 except AttributeError: pass
1471 1471
1472 1472 # We return either the new info or the unmodified input if the object
1473 1473 # hadn't been found
1474 1474 return info
1475 1475
1476 1476 def _object_find(self, oname, namespaces=None):
1477 1477 """Find an object and return a struct with info about it."""
1478 1478 inf = Struct(self._ofind(oname, namespaces))
1479 1479 return Struct(self._ofind_property(oname, inf))
1480 1480
1481 1481 def _inspect(self, meth, oname, namespaces=None, **kw):
1482 1482 """Generic interface to the inspector system.
1483 1483
1484 1484 This function is meant to be called by pdef, pdoc & friends."""
1485 1485 info = self._object_find(oname)
1486 1486 if info.found:
1487 1487 pmethod = getattr(self.inspector, meth)
1488 1488 formatter = format_screen if info.ismagic else None
1489 1489 if meth == 'pdoc':
1490 1490 pmethod(info.obj, oname, formatter)
1491 1491 elif meth == 'pinfo':
1492 1492 pmethod(info.obj, oname, formatter, info, **kw)
1493 1493 else:
1494 1494 pmethod(info.obj, oname)
1495 1495 else:
1496 1496 print 'Object `%s` not found.' % oname
1497 1497 return 'not found' # so callers can take other action
1498 1498
1499 1499 def object_inspect(self, oname, detail_level=0):
1500 1500 with self.builtin_trap:
1501 1501 info = self._object_find(oname)
1502 1502 if info.found:
1503 1503 return self.inspector.info(info.obj, oname, info=info,
1504 1504 detail_level=detail_level
1505 1505 )
1506 1506 else:
1507 1507 return oinspect.object_info(name=oname, found=False)
1508 1508
1509 1509 #-------------------------------------------------------------------------
1510 1510 # Things related to history management
1511 1511 #-------------------------------------------------------------------------
1512 1512
1513 1513 def init_history(self):
1514 1514 """Sets up the command history, and starts regular autosaves."""
1515 1515 self.history_manager = HistoryManager(shell=self, config=self.config)
1516 1516 self.configurables.append(self.history_manager)
1517 1517
1518 1518 #-------------------------------------------------------------------------
1519 1519 # Things related to exception handling and tracebacks (not debugging)
1520 1520 #-------------------------------------------------------------------------
1521 1521
1522 1522 def init_traceback_handlers(self, custom_exceptions):
1523 1523 # Syntax error handler.
1524 1524 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor')
1525 1525
1526 1526 # The interactive one is initialized with an offset, meaning we always
1527 1527 # want to remove the topmost item in the traceback, which is our own
1528 1528 # internal code. Valid modes: ['Plain','Context','Verbose']
1529 1529 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1530 1530 color_scheme='NoColor',
1531 1531 tb_offset = 1,
1532 1532 check_cache=self.compile.check_cache)
1533 1533
1534 1534 # The instance will store a pointer to the system-wide exception hook,
1535 1535 # so that runtime code (such as magics) can access it. This is because
1536 1536 # during the read-eval loop, it may get temporarily overwritten.
1537 1537 self.sys_excepthook = sys.excepthook
1538 1538
1539 1539 # and add any custom exception handlers the user may have specified
1540 1540 self.set_custom_exc(*custom_exceptions)
1541 1541
1542 1542 # Set the exception mode
1543 1543 self.InteractiveTB.set_mode(mode=self.xmode)
1544 1544
1545 1545 def set_custom_exc(self, exc_tuple, handler):
1546 1546 """set_custom_exc(exc_tuple,handler)
1547 1547
1548 1548 Set a custom exception handler, which will be called if any of the
1549 1549 exceptions in exc_tuple occur in the mainloop (specifically, in the
1550 1550 run_code() method).
1551 1551
1552 1552 Parameters
1553 1553 ----------
1554 1554
1555 1555 exc_tuple : tuple of exception classes
1556 1556 A *tuple* of exception classes, for which to call the defined
1557 1557 handler. It is very important that you use a tuple, and NOT A
1558 1558 LIST here, because of the way Python's except statement works. If
1559 1559 you only want to trap a single exception, use a singleton tuple::
1560 1560
1561 1561 exc_tuple == (MyCustomException,)
1562 1562
1563 1563 handler : callable
1564 1564 handler must have the following signature::
1565 1565
1566 1566 def my_handler(self, etype, value, tb, tb_offset=None):
1567 1567 ...
1568 1568 return structured_traceback
1569 1569
1570 1570 Your handler must return a structured traceback (a list of strings),
1571 1571 or None.
1572 1572
1573 1573 This will be made into an instance method (via types.MethodType)
1574 1574 of IPython itself, and it will be called if any of the exceptions
1575 1575 listed in the exc_tuple are caught. If the handler is None, an
1576 1576 internal basic one is used, which just prints basic info.
1577 1577
1578 1578 To protect IPython from crashes, if your handler ever raises an
1579 1579 exception or returns an invalid result, it will be immediately
1580 1580 disabled.
1581 1581
1582 1582 WARNING: by putting in your own exception handler into IPython's main
1583 1583 execution loop, you run a very good chance of nasty crashes. This
1584 1584 facility should only be used if you really know what you are doing."""
1585 1585
1586 1586 assert type(exc_tuple)==type(()) , \
1587 1587 "The custom exceptions must be given AS A TUPLE."
1588 1588
1589 1589 def dummy_handler(self,etype,value,tb,tb_offset=None):
1590 1590 print '*** Simple custom exception handler ***'
1591 1591 print 'Exception type :',etype
1592 1592 print 'Exception value:',value
1593 1593 print 'Traceback :',tb
1594 1594 #print 'Source code :','\n'.join(self.buffer)
1595 1595
1596 1596 def validate_stb(stb):
1597 1597 """validate structured traceback return type
1598 1598
1599 1599 return type of CustomTB *should* be a list of strings, but allow
1600 1600 single strings or None, which are harmless.
1601 1601
1602 1602 This function will *always* return a list of strings,
1603 1603 and will raise a TypeError if stb is inappropriate.
1604 1604 """
1605 1605 msg = "CustomTB must return list of strings, not %r" % stb
1606 1606 if stb is None:
1607 1607 return []
1608 1608 elif isinstance(stb, basestring):
1609 1609 return [stb]
1610 1610 elif not isinstance(stb, list):
1611 1611 raise TypeError(msg)
1612 1612 # it's a list
1613 1613 for line in stb:
1614 1614 # check every element
1615 1615 if not isinstance(line, basestring):
1616 1616 raise TypeError(msg)
1617 1617 return stb
1618 1618
1619 1619 if handler is None:
1620 1620 wrapped = dummy_handler
1621 1621 else:
1622 1622 def wrapped(self,etype,value,tb,tb_offset=None):
1623 1623 """wrap CustomTB handler, to protect IPython from user code
1624 1624
1625 1625 This makes it harder (but not impossible) for custom exception
1626 1626 handlers to crash IPython.
1627 1627 """
1628 1628 try:
1629 1629 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1630 1630 return validate_stb(stb)
1631 1631 except:
1632 1632 # clear custom handler immediately
1633 1633 self.set_custom_exc((), None)
1634 1634 print >> io.stderr, "Custom TB Handler failed, unregistering"
1635 1635 # show the exception in handler first
1636 1636 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1637 1637 print >> io.stdout, self.InteractiveTB.stb2text(stb)
1638 1638 print >> io.stdout, "The original exception:"
1639 1639 stb = self.InteractiveTB.structured_traceback(
1640 1640 (etype,value,tb), tb_offset=tb_offset
1641 1641 )
1642 1642 return stb
1643 1643
1644 1644 self.CustomTB = types.MethodType(wrapped,self)
1645 1645 self.custom_exceptions = exc_tuple
1646 1646
1647 1647 def excepthook(self, etype, value, tb):
1648 1648 """One more defense for GUI apps that call sys.excepthook.
1649 1649
1650 1650 GUI frameworks like wxPython trap exceptions and call
1651 1651 sys.excepthook themselves. I guess this is a feature that
1652 1652 enables them to keep running after exceptions that would
1653 1653 otherwise kill their mainloop. This is a bother for IPython
1654 1654 which excepts to catch all of the program exceptions with a try:
1655 1655 except: statement.
1656 1656
1657 1657 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1658 1658 any app directly invokes sys.excepthook, it will look to the user like
1659 1659 IPython crashed. In order to work around this, we can disable the
1660 1660 CrashHandler and replace it with this excepthook instead, which prints a
1661 1661 regular traceback using our InteractiveTB. In this fashion, apps which
1662 1662 call sys.excepthook will generate a regular-looking exception from
1663 1663 IPython, and the CrashHandler will only be triggered by real IPython
1664 1664 crashes.
1665 1665
1666 1666 This hook should be used sparingly, only in places which are not likely
1667 1667 to be true IPython errors.
1668 1668 """
1669 1669 self.showtraceback((etype,value,tb),tb_offset=0)
1670 1670
1671 1671 def _get_exc_info(self, exc_tuple=None):
1672 1672 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1673 1673
1674 1674 Ensures sys.last_type,value,traceback hold the exc_info we found,
1675 1675 from whichever source.
1676 1676
1677 1677 raises ValueError if none of these contain any information
1678 1678 """
1679 1679 if exc_tuple is None:
1680 1680 etype, value, tb = sys.exc_info()
1681 1681 else:
1682 1682 etype, value, tb = exc_tuple
1683 1683
1684 1684 if etype is None:
1685 1685 if hasattr(sys, 'last_type'):
1686 1686 etype, value, tb = sys.last_type, sys.last_value, \
1687 1687 sys.last_traceback
1688 1688
1689 1689 if etype is None:
1690 1690 raise ValueError("No exception to find")
1691 1691
1692 1692 # Now store the exception info in sys.last_type etc.
1693 1693 # WARNING: these variables are somewhat deprecated and not
1694 1694 # necessarily safe to use in a threaded environment, but tools
1695 1695 # like pdb depend on their existence, so let's set them. If we
1696 1696 # find problems in the field, we'll need to revisit their use.
1697 1697 sys.last_type = etype
1698 1698 sys.last_value = value
1699 1699 sys.last_traceback = tb
1700 1700
1701 1701 return etype, value, tb
1702 1702
1703 1703
1704 1704 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None,
1705 1705 exception_only=False):
1706 1706 """Display the exception that just occurred.
1707 1707
1708 1708 If nothing is known about the exception, this is the method which
1709 1709 should be used throughout the code for presenting user tracebacks,
1710 1710 rather than directly invoking the InteractiveTB object.
1711 1711
1712 1712 A specific showsyntaxerror() also exists, but this method can take
1713 1713 care of calling it if needed, so unless you are explicitly catching a
1714 1714 SyntaxError exception, don't try to analyze the stack manually and
1715 1715 simply call this method."""
1716 1716
1717 1717 try:
1718 1718 try:
1719 1719 etype, value, tb = self._get_exc_info(exc_tuple)
1720 1720 except ValueError:
1721 1721 self.write_err('No traceback available to show.\n')
1722 1722 return
1723 1723
1724 1724 if etype is SyntaxError:
1725 1725 # Though this won't be called by syntax errors in the input
1726 1726 # line, there may be SyntaxError cases with imported code.
1727 1727 self.showsyntaxerror(filename)
1728 1728 elif etype is UsageError:
1729 1729 self.write_err("UsageError: %s" % value)
1730 1730 elif issubclass(etype, RemoteError):
1731 1731 # IPython.parallel remote exceptions.
1732 1732 # Draw the remote traceback, not the local one.
1733 1733 self._showtraceback(etype, value, value.render_traceback())
1734 1734 else:
1735 1735 if exception_only:
1736 1736 stb = ['An exception has occurred, use %tb to see '
1737 1737 'the full traceback.\n']
1738 1738 stb.extend(self.InteractiveTB.get_exception_only(etype,
1739 1739 value))
1740 1740 else:
1741 1741 stb = self.InteractiveTB.structured_traceback(etype,
1742 1742 value, tb, tb_offset=tb_offset)
1743 1743
1744 1744 self._showtraceback(etype, value, stb)
1745 1745 if self.call_pdb:
1746 1746 # drop into debugger
1747 1747 self.debugger(force=True)
1748 1748 return
1749 1749
1750 1750 # Actually show the traceback
1751 1751 self._showtraceback(etype, value, stb)
1752 1752
1753 1753 except KeyboardInterrupt:
1754 1754 self.write_err("\nKeyboardInterrupt\n")
1755 1755
1756 1756 def _showtraceback(self, etype, evalue, stb):
1757 1757 """Actually show a traceback.
1758 1758
1759 1759 Subclasses may override this method to put the traceback on a different
1760 1760 place, like a side channel.
1761 1761 """
1762 1762 print >> io.stdout, self.InteractiveTB.stb2text(stb)
1763 1763
1764 1764 def showsyntaxerror(self, filename=None):
1765 1765 """Display the syntax error that just occurred.
1766 1766
1767 1767 This doesn't display a stack trace because there isn't one.
1768 1768
1769 1769 If a filename is given, it is stuffed in the exception instead
1770 1770 of what was there before (because Python's parser always uses
1771 1771 "<string>" when reading from a string).
1772 1772 """
1773 1773 etype, value, last_traceback = self._get_exc_info()
1774 1774
1775 1775 if filename and etype is SyntaxError:
1776 1776 try:
1777 1777 value.filename = filename
1778 1778 except:
1779 1779 # Not the format we expect; leave it alone
1780 1780 pass
1781 1781
1782 1782 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1783 1783 self._showtraceback(etype, value, stb)
1784 1784
1785 1785 # This is overridden in TerminalInteractiveShell to show a message about
1786 1786 # the %paste magic.
1787 1787 def showindentationerror(self):
1788 1788 """Called by run_cell when there's an IndentationError in code entered
1789 1789 at the prompt.
1790 1790
1791 1791 This is overridden in TerminalInteractiveShell to show a message about
1792 1792 the %paste magic."""
1793 1793 self.showsyntaxerror()
1794 1794
1795 1795 #-------------------------------------------------------------------------
1796 1796 # Things related to readline
1797 1797 #-------------------------------------------------------------------------
1798 1798
1799 1799 def init_readline(self):
1800 1800 """Command history completion/saving/reloading."""
1801 1801
1802 1802 if self.readline_use:
1803 1803 import IPython.utils.rlineimpl as readline
1804 1804
1805 1805 self.rl_next_input = None
1806 1806 self.rl_do_indent = False
1807 1807
1808 1808 if not self.readline_use or not readline.have_readline:
1809 1809 self.has_readline = False
1810 1810 self.readline = None
1811 1811 # Set a number of methods that depend on readline to be no-op
1812 1812 self.readline_no_record = no_op_context
1813 1813 self.set_readline_completer = no_op
1814 1814 self.set_custom_completer = no_op
1815 1815 self.set_completer_frame = no_op
1816 1816 if self.readline_use:
1817 1817 warn('Readline services not available or not loaded.')
1818 1818 else:
1819 1819 self.has_readline = True
1820 1820 self.readline = readline
1821 1821 sys.modules['readline'] = readline
1822 1822
1823 1823 # Platform-specific configuration
1824 1824 if os.name == 'nt':
1825 1825 # FIXME - check with Frederick to see if we can harmonize
1826 1826 # naming conventions with pyreadline to avoid this
1827 1827 # platform-dependent check
1828 1828 self.readline_startup_hook = readline.set_pre_input_hook
1829 1829 else:
1830 1830 self.readline_startup_hook = readline.set_startup_hook
1831 1831
1832 1832 # Load user's initrc file (readline config)
1833 1833 # Or if libedit is used, load editrc.
1834 1834 inputrc_name = os.environ.get('INPUTRC')
1835 1835 if inputrc_name is None:
1836 1836 inputrc_name = '.inputrc'
1837 1837 if readline.uses_libedit:
1838 1838 inputrc_name = '.editrc'
1839 1839 inputrc_name = os.path.join(self.home_dir, inputrc_name)
1840 1840 if os.path.isfile(inputrc_name):
1841 1841 try:
1842 1842 readline.read_init_file(inputrc_name)
1843 1843 except:
1844 1844 warn('Problems reading readline initialization file <%s>'
1845 1845 % inputrc_name)
1846 1846
1847 1847 # Configure readline according to user's prefs
1848 1848 # This is only done if GNU readline is being used. If libedit
1849 1849 # is being used (as on Leopard) the readline config is
1850 1850 # not run as the syntax for libedit is different.
1851 1851 if not readline.uses_libedit:
1852 1852 for rlcommand in self.readline_parse_and_bind:
1853 1853 #print "loading rl:",rlcommand # dbg
1854 1854 readline.parse_and_bind(rlcommand)
1855 1855
1856 1856 # Remove some chars from the delimiters list. If we encounter
1857 1857 # unicode chars, discard them.
1858 1858 delims = readline.get_completer_delims()
1859 1859 if not py3compat.PY3:
1860 1860 delims = delims.encode("ascii", "ignore")
1861 1861 for d in self.readline_remove_delims:
1862 1862 delims = delims.replace(d, "")
1863 1863 delims = delims.replace(ESC_MAGIC, '')
1864 1864 readline.set_completer_delims(delims)
1865 1865 # otherwise we end up with a monster history after a while:
1866 1866 readline.set_history_length(self.history_length)
1867 1867
1868 1868 self.refill_readline_hist()
1869 1869 self.readline_no_record = ReadlineNoRecord(self)
1870 1870
1871 1871 # Configure auto-indent for all platforms
1872 1872 self.set_autoindent(self.autoindent)
1873 1873
1874 1874 def refill_readline_hist(self):
1875 1875 # Load the last 1000 lines from history
1876 1876 self.readline.clear_history()
1877 1877 stdin_encoding = sys.stdin.encoding or "utf-8"
1878 1878 last_cell = u""
1879 1879 for _, _, cell in self.history_manager.get_tail(1000,
1880 1880 include_latest=True):
1881 1881 # Ignore blank lines and consecutive duplicates
1882 1882 cell = cell.rstrip()
1883 1883 if cell and (cell != last_cell):
1884 1884 if self.multiline_history:
1885 1885 self.readline.add_history(py3compat.unicode_to_str(cell,
1886 1886 stdin_encoding))
1887 1887 else:
1888 1888 for line in cell.splitlines():
1889 1889 self.readline.add_history(py3compat.unicode_to_str(line,
1890 1890 stdin_encoding))
1891 1891 last_cell = cell
1892 1892
1893 1893 def set_next_input(self, s):
1894 1894 """ Sets the 'default' input string for the next command line.
1895 1895
1896 1896 Requires readline.
1897 1897
1898 1898 Example:
1899 1899
1900 1900 [D:\ipython]|1> _ip.set_next_input("Hello Word")
1901 1901 [D:\ipython]|2> Hello Word_ # cursor is here
1902 1902 """
1903 1903 self.rl_next_input = py3compat.cast_bytes_py2(s)
1904 1904
1905 1905 # Maybe move this to the terminal subclass?
1906 1906 def pre_readline(self):
1907 1907 """readline hook to be used at the start of each line.
1908 1908
1909 1909 Currently it handles auto-indent only."""
1910 1910
1911 1911 if self.rl_do_indent:
1912 1912 self.readline.insert_text(self._indent_current_str())
1913 1913 if self.rl_next_input is not None:
1914 1914 self.readline.insert_text(self.rl_next_input)
1915 1915 self.rl_next_input = None
1916 1916
1917 1917 def _indent_current_str(self):
1918 1918 """return the current level of indentation as a string"""
1919 1919 return self.input_splitter.indent_spaces * ' '
1920 1920
1921 1921 #-------------------------------------------------------------------------
1922 1922 # Things related to text completion
1923 1923 #-------------------------------------------------------------------------
1924 1924
1925 1925 def init_completer(self):
1926 1926 """Initialize the completion machinery.
1927 1927
1928 1928 This creates completion machinery that can be used by client code,
1929 1929 either interactively in-process (typically triggered by the readline
1930 1930 library), programatically (such as in test suites) or out-of-prcess
1931 1931 (typically over the network by remote frontends).
1932 1932 """
1933 1933 from IPython.core.completer import IPCompleter
1934 1934 from IPython.core.completerlib import (module_completer,
1935 1935 magic_run_completer, cd_completer, reset_completer)
1936 1936
1937 1937 self.Completer = IPCompleter(shell=self,
1938 1938 namespace=self.user_ns,
1939 1939 global_namespace=self.user_global_ns,
1940 1940 alias_table=self.alias_manager.alias_table,
1941 1941 use_readline=self.has_readline,
1942 1942 config=self.config,
1943 1943 )
1944 1944 self.configurables.append(self.Completer)
1945 1945
1946 1946 # Add custom completers to the basic ones built into IPCompleter
1947 1947 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1948 1948 self.strdispatchers['complete_command'] = sdisp
1949 1949 self.Completer.custom_completers = sdisp
1950 1950
1951 1951 self.set_hook('complete_command', module_completer, str_key = 'import')
1952 1952 self.set_hook('complete_command', module_completer, str_key = 'from')
1953 1953 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
1954 1954 self.set_hook('complete_command', cd_completer, str_key = '%cd')
1955 1955 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1956 1956
1957 1957 # Only configure readline if we truly are using readline. IPython can
1958 1958 # do tab-completion over the network, in GUIs, etc, where readline
1959 1959 # itself may be absent
1960 1960 if self.has_readline:
1961 1961 self.set_readline_completer()
1962 1962
1963 1963 def complete(self, text, line=None, cursor_pos=None):
1964 1964 """Return the completed text and a list of completions.
1965 1965
1966 1966 Parameters
1967 1967 ----------
1968 1968
1969 1969 text : string
1970 1970 A string of text to be completed on. It can be given as empty and
1971 1971 instead a line/position pair are given. In this case, the
1972 1972 completer itself will split the line like readline does.
1973 1973
1974 1974 line : string, optional
1975 1975 The complete line that text is part of.
1976 1976
1977 1977 cursor_pos : int, optional
1978 1978 The position of the cursor on the input line.
1979 1979
1980 1980 Returns
1981 1981 -------
1982 1982 text : string
1983 1983 The actual text that was completed.
1984 1984
1985 1985 matches : list
1986 1986 A sorted list with all possible completions.
1987 1987
1988 1988 The optional arguments allow the completion to take more context into
1989 1989 account, and are part of the low-level completion API.
1990 1990
1991 1991 This is a wrapper around the completion mechanism, similar to what
1992 1992 readline does at the command line when the TAB key is hit. By
1993 1993 exposing it as a method, it can be used by other non-readline
1994 1994 environments (such as GUIs) for text completion.
1995 1995
1996 1996 Simple usage example:
1997 1997
1998 1998 In [1]: x = 'hello'
1999 1999
2000 2000 In [2]: _ip.complete('x.l')
2001 2001 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2002 2002 """
2003 2003
2004 2004 # Inject names into __builtin__ so we can complete on the added names.
2005 2005 with self.builtin_trap:
2006 2006 return self.Completer.complete(text, line, cursor_pos)
2007 2007
2008 2008 def set_custom_completer(self, completer, pos=0):
2009 2009 """Adds a new custom completer function.
2010 2010
2011 2011 The position argument (defaults to 0) is the index in the completers
2012 2012 list where you want the completer to be inserted."""
2013 2013
2014 2014 newcomp = types.MethodType(completer,self.Completer)
2015 2015 self.Completer.matchers.insert(pos,newcomp)
2016 2016
2017 2017 def set_readline_completer(self):
2018 2018 """Reset readline's completer to be our own."""
2019 2019 self.readline.set_completer(self.Completer.rlcomplete)
2020 2020
2021 2021 def set_completer_frame(self, frame=None):
2022 2022 """Set the frame of the completer."""
2023 2023 if frame:
2024 2024 self.Completer.namespace = frame.f_locals
2025 2025 self.Completer.global_namespace = frame.f_globals
2026 2026 else:
2027 2027 self.Completer.namespace = self.user_ns
2028 2028 self.Completer.global_namespace = self.user_global_ns
2029 2029
2030 2030 #-------------------------------------------------------------------------
2031 2031 # Things related to magics
2032 2032 #-------------------------------------------------------------------------
2033 2033
2034 2034 def init_magics(self):
2035 2035 from IPython.core import magics as m
2036 2036 self.magics_manager = magic.MagicsManager(shell=self,
2037 2037 confg=self.config,
2038 2038 user_magics=m.UserMagics(self))
2039 2039 self.configurables.append(self.magics_manager)
2040 2040
2041 2041 # Expose as public API from the magics manager
2042 2042 self.register_magics = self.magics_manager.register
2043 2043 self.register_magic_function = self.magics_manager.register_function
2044 2044 self.define_magic = self.magics_manager.define_magic
2045 2045
2046 2046 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2047 2047 m.ConfigMagics, m.DeprecatedMagics, m.ExecutionMagics,
2048 2048 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2049 2049 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2050 2050 )
2051 2051
2052 2052 # FIXME: Move the color initialization to the DisplayHook, which
2053 2053 # should be split into a prompt manager and displayhook. We probably
2054 2054 # even need a centralize colors management object.
2055 2055 self.magic('colors %s' % self.colors)
2056 2056
2057 2057 def run_line_magic(self, magic_name, line):
2058 2058 """Execute the given line magic.
2059 2059
2060 2060 Parameters
2061 2061 ----------
2062 2062 magic_name : str
2063 2063 Name of the desired magic function, without '%' prefix.
2064 2064
2065 2065 line : str
2066 2066 The rest of the input line as a single string.
2067 2067 """
2068 2068 fn = self.find_line_magic(magic_name)
2069 2069 if fn is None:
2070 2070 cm = self.find_cell_magic(magic_name)
2071 2071 etpl = "Line magic function `%%%s` not found%s."
2072 2072 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2073 2073 'did you mean that instead?)' % magic_name )
2074 2074 error(etpl % (magic_name, extra))
2075 2075 else:
2076 2076 # Note: this is the distance in the stack to the user's frame.
2077 2077 # This will need to be updated if the internal calling logic gets
2078 2078 # refactored, or else we'll be expanding the wrong variables.
2079 2079 stack_depth = 2
2080 2080 magic_arg_s = self.var_expand(line, stack_depth)
2081 2081 # Put magic args in a list so we can call with f(*a) syntax
2082 2082 args = [magic_arg_s]
2083 2083 # Grab local namespace if we need it:
2084 2084 if getattr(fn, "needs_local_scope", False):
2085 2085 args.append(sys._getframe(stack_depth).f_locals)
2086 2086 with self.builtin_trap:
2087 2087 result = fn(*args)
2088 2088 return result
2089 2089
2090 2090 def run_cell_magic(self, magic_name, line, cell):
2091 2091 """Execute the given cell magic.
2092 2092
2093 2093 Parameters
2094 2094 ----------
2095 2095 magic_name : str
2096 2096 Name of the desired magic function, without '%' prefix.
2097 2097
2098 2098 line : str
2099 2099 The rest of the first input line as a single string.
2100 2100
2101 2101 cell : str
2102 2102 The body of the cell as a (possibly multiline) string.
2103 2103 """
2104 2104 fn = self.find_cell_magic(magic_name)
2105 2105 if fn is None:
2106 2106 lm = self.find_line_magic(magic_name)
2107 2107 etpl = "Cell magic function `%%%%%s` not found%s."
2108 2108 extra = '' if lm is None else (' (But line magic `%%%s` exists, '
2109 2109 'did you mean that instead?)' % magic_name )
2110 2110 error(etpl % (magic_name, extra))
2111 2111 else:
2112 2112 # Note: this is the distance in the stack to the user's frame.
2113 2113 # This will need to be updated if the internal calling logic gets
2114 2114 # refactored, or else we'll be expanding the wrong variables.
2115 2115 stack_depth = 2
2116 2116 magic_arg_s = self.var_expand(line, stack_depth)
2117 2117 with self.builtin_trap:
2118 2118 result = fn(line, cell)
2119 2119 return result
2120 2120
2121 2121 def find_line_magic(self, magic_name):
2122 2122 """Find and return a line magic by name.
2123 2123
2124 2124 Returns None if the magic isn't found."""
2125 2125 return self.magics_manager.magics['line'].get(magic_name)
2126 2126
2127 2127 def find_cell_magic(self, magic_name):
2128 2128 """Find and return a cell magic by name.
2129 2129
2130 2130 Returns None if the magic isn't found."""
2131 2131 return self.magics_manager.magics['cell'].get(magic_name)
2132 2132
2133 2133 def find_magic(self, magic_name, magic_kind='line'):
2134 2134 """Find and return a magic of the given type by name.
2135 2135
2136 2136 Returns None if the magic isn't found."""
2137 2137 return self.magics_manager.magics[magic_kind].get(magic_name)
2138 2138
2139 2139 def magic(self, arg_s):
2140 2140 """DEPRECATED. Use run_line_magic() instead.
2141 2141
2142 2142 Call a magic function by name.
2143 2143
2144 2144 Input: a string containing the name of the magic function to call and
2145 2145 any additional arguments to be passed to the magic.
2146 2146
2147 2147 magic('name -opt foo bar') is equivalent to typing at the ipython
2148 2148 prompt:
2149 2149
2150 2150 In[1]: %name -opt foo bar
2151 2151
2152 2152 To call a magic without arguments, simply use magic('name').
2153 2153
2154 2154 This provides a proper Python function to call IPython's magics in any
2155 2155 valid Python code you can type at the interpreter, including loops and
2156 2156 compound statements.
2157 2157 """
2158 2158 # TODO: should we issue a loud deprecation warning here?
2159 2159 magic_name, _, magic_arg_s = arg_s.partition(' ')
2160 2160 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2161 2161 return self.run_line_magic(magic_name, magic_arg_s)
2162 2162
2163 2163 #-------------------------------------------------------------------------
2164 2164 # Things related to macros
2165 2165 #-------------------------------------------------------------------------
2166 2166
2167 2167 def define_macro(self, name, themacro):
2168 2168 """Define a new macro
2169 2169
2170 2170 Parameters
2171 2171 ----------
2172 2172 name : str
2173 2173 The name of the macro.
2174 2174 themacro : str or Macro
2175 2175 The action to do upon invoking the macro. If a string, a new
2176 2176 Macro object is created by passing the string to it.
2177 2177 """
2178 2178
2179 2179 from IPython.core import macro
2180 2180
2181 2181 if isinstance(themacro, basestring):
2182 2182 themacro = macro.Macro(themacro)
2183 2183 if not isinstance(themacro, macro.Macro):
2184 2184 raise ValueError('A macro must be a string or a Macro instance.')
2185 2185 self.user_ns[name] = themacro
2186 2186
2187 2187 #-------------------------------------------------------------------------
2188 2188 # Things related to the running of system commands
2189 2189 #-------------------------------------------------------------------------
2190 2190
2191 2191 def system_piped(self, cmd):
2192 2192 """Call the given cmd in a subprocess, piping stdout/err
2193 2193
2194 2194 Parameters
2195 2195 ----------
2196 2196 cmd : str
2197 2197 Command to execute (can not end in '&', as background processes are
2198 2198 not supported. Should not be a command that expects input
2199 2199 other than simple text.
2200 2200 """
2201 2201 if cmd.rstrip().endswith('&'):
2202 2202 # this is *far* from a rigorous test
2203 2203 # We do not support backgrounding processes because we either use
2204 2204 # pexpect or pipes to read from. Users can always just call
2205 2205 # os.system() or use ip.system=ip.system_raw
2206 2206 # if they really want a background process.
2207 2207 raise OSError("Background processes not supported.")
2208 2208
2209 2209 # we explicitly do NOT return the subprocess status code, because
2210 2210 # a non-None value would trigger :func:`sys.displayhook` calls.
2211 2211 # Instead, we store the exit_code in user_ns.
2212 2212 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2213 2213
2214 2214 def system_raw(self, cmd):
2215 2215 """Call the given cmd in a subprocess using os.system
2216 2216
2217 2217 Parameters
2218 2218 ----------
2219 2219 cmd : str
2220 2220 Command to execute.
2221 2221 """
2222 2222 cmd = self.var_expand(cmd, depth=1)
2223 2223 # protect os.system from UNC paths on Windows, which it can't handle:
2224 2224 if sys.platform == 'win32':
2225 2225 from IPython.utils._process_win32 import AvoidUNCPath
2226 2226 with AvoidUNCPath() as path:
2227 2227 if path is not None:
2228 2228 cmd = '"pushd %s &&"%s' % (path, cmd)
2229 2229 cmd = py3compat.unicode_to_str(cmd)
2230 2230 ec = os.system(cmd)
2231 2231 else:
2232 2232 cmd = py3compat.unicode_to_str(cmd)
2233 2233 ec = os.system(cmd)
2234 2234
2235 2235 # We explicitly do NOT return the subprocess status code, because
2236 2236 # a non-None value would trigger :func:`sys.displayhook` calls.
2237 2237 # Instead, we store the exit_code in user_ns.
2238 2238 self.user_ns['_exit_code'] = ec
2239 2239
2240 2240 # use piped system by default, because it is better behaved
2241 2241 system = system_piped
2242 2242
2243 2243 def getoutput(self, cmd, split=True, depth=0):
2244 2244 """Get output (possibly including stderr) from a subprocess.
2245 2245
2246 2246 Parameters
2247 2247 ----------
2248 2248 cmd : str
2249 2249 Command to execute (can not end in '&', as background processes are
2250 2250 not supported.
2251 2251 split : bool, optional
2252 2252 If True, split the output into an IPython SList. Otherwise, an
2253 2253 IPython LSString is returned. These are objects similar to normal
2254 2254 lists and strings, with a few convenience attributes for easier
2255 2255 manipulation of line-based output. You can use '?' on them for
2256 2256 details.
2257 2257 depth : int, optional
2258 2258 How many frames above the caller are the local variables which should
2259 2259 be expanded in the command string? The default (0) assumes that the
2260 2260 expansion variables are in the stack frame calling this function.
2261 2261 """
2262 2262 if cmd.rstrip().endswith('&'):
2263 2263 # this is *far* from a rigorous test
2264 2264 raise OSError("Background processes not supported.")
2265 2265 out = getoutput(self.var_expand(cmd, depth=depth+1))
2266 2266 if split:
2267 2267 out = SList(out.splitlines())
2268 2268 else:
2269 2269 out = LSString(out)
2270 2270 return out
2271 2271
2272 2272 #-------------------------------------------------------------------------
2273 2273 # Things related to aliases
2274 2274 #-------------------------------------------------------------------------
2275 2275
2276 2276 def init_alias(self):
2277 2277 self.alias_manager = AliasManager(shell=self, config=self.config)
2278 2278 self.configurables.append(self.alias_manager)
2279 2279 self.ns_table['alias'] = self.alias_manager.alias_table,
2280 2280
2281 2281 #-------------------------------------------------------------------------
2282 2282 # Things related to extensions and plugins
2283 2283 #-------------------------------------------------------------------------
2284 2284
2285 2285 def init_extension_manager(self):
2286 2286 self.extension_manager = ExtensionManager(shell=self, config=self.config)
2287 2287 self.configurables.append(self.extension_manager)
2288 2288
2289 2289 def init_plugin_manager(self):
2290 2290 self.plugin_manager = PluginManager(config=self.config)
2291 2291 self.configurables.append(self.plugin_manager)
2292 2292
2293 2293
2294 2294 #-------------------------------------------------------------------------
2295 2295 # Things related to payloads
2296 2296 #-------------------------------------------------------------------------
2297 2297
2298 2298 def init_payload(self):
2299 2299 self.payload_manager = PayloadManager(config=self.config)
2300 2300 self.configurables.append(self.payload_manager)
2301 2301
2302 2302 #-------------------------------------------------------------------------
2303 2303 # Things related to the prefilter
2304 2304 #-------------------------------------------------------------------------
2305 2305
2306 2306 def init_prefilter(self):
2307 2307 self.prefilter_manager = PrefilterManager(shell=self, config=self.config)
2308 2308 self.configurables.append(self.prefilter_manager)
2309 2309 # Ultimately this will be refactored in the new interpreter code, but
2310 2310 # for now, we should expose the main prefilter method (there's legacy
2311 2311 # code out there that may rely on this).
2312 2312 self.prefilter = self.prefilter_manager.prefilter_lines
2313 2313
2314 2314 def auto_rewrite_input(self, cmd):
2315 2315 """Print to the screen the rewritten form of the user's command.
2316 2316
2317 2317 This shows visual feedback by rewriting input lines that cause
2318 2318 automatic calling to kick in, like::
2319 2319
2320 2320 /f x
2321 2321
2322 2322 into::
2323 2323
2324 2324 ------> f(x)
2325 2325
2326 2326 after the user's input prompt. This helps the user understand that the
2327 2327 input line was transformed automatically by IPython.
2328 2328 """
2329 2329 if not self.show_rewritten_input:
2330 2330 return
2331 2331
2332 2332 rw = self.prompt_manager.render('rewrite') + cmd
2333 2333
2334 2334 try:
2335 2335 # plain ascii works better w/ pyreadline, on some machines, so
2336 2336 # we use it and only print uncolored rewrite if we have unicode
2337 2337 rw = str(rw)
2338 2338 print >> io.stdout, rw
2339 2339 except UnicodeEncodeError:
2340 2340 print "------> " + cmd
2341 2341
2342 2342 #-------------------------------------------------------------------------
2343 2343 # Things related to extracting values/expressions from kernel and user_ns
2344 2344 #-------------------------------------------------------------------------
2345 2345
2346 2346 def _simple_error(self):
2347 2347 etype, value = sys.exc_info()[:2]
2348 2348 return u'[ERROR] {e.__name__}: {v}'.format(e=etype, v=value)
2349 2349
2350 2350 def user_variables(self, names):
2351 2351 """Get a list of variable names from the user's namespace.
2352 2352
2353 2353 Parameters
2354 2354 ----------
2355 2355 names : list of strings
2356 2356 A list of names of variables to be read from the user namespace.
2357 2357
2358 2358 Returns
2359 2359 -------
2360 2360 A dict, keyed by the input names and with the repr() of each value.
2361 2361 """
2362 2362 out = {}
2363 2363 user_ns = self.user_ns
2364 2364 for varname in names:
2365 2365 try:
2366 2366 value = repr(user_ns[varname])
2367 2367 except:
2368 2368 value = self._simple_error()
2369 2369 out[varname] = value
2370 2370 return out
2371 2371
2372 2372 def user_expressions(self, expressions):
2373 2373 """Evaluate a dict of expressions in the user's namespace.
2374 2374
2375 2375 Parameters
2376 2376 ----------
2377 2377 expressions : dict
2378 2378 A dict with string keys and string values. The expression values
2379 2379 should be valid Python expressions, each of which will be evaluated
2380 2380 in the user namespace.
2381 2381
2382 2382 Returns
2383 2383 -------
2384 2384 A dict, keyed like the input expressions dict, with the repr() of each
2385 2385 value.
2386 2386 """
2387 2387 out = {}
2388 2388 user_ns = self.user_ns
2389 2389 global_ns = self.user_global_ns
2390 2390 for key, expr in expressions.iteritems():
2391 2391 try:
2392 2392 value = repr(eval(expr, global_ns, user_ns))
2393 2393 except:
2394 2394 value = self._simple_error()
2395 2395 out[key] = value
2396 2396 return out
2397 2397
2398 2398 #-------------------------------------------------------------------------
2399 2399 # Things related to the running of code
2400 2400 #-------------------------------------------------------------------------
2401 2401
2402 2402 def ex(self, cmd):
2403 2403 """Execute a normal python statement in user namespace."""
2404 2404 with self.builtin_trap:
2405 2405 exec cmd in self.user_global_ns, self.user_ns
2406 2406
2407 2407 def ev(self, expr):
2408 2408 """Evaluate python expression expr in user namespace.
2409 2409
2410 2410 Returns the result of evaluation
2411 2411 """
2412 2412 with self.builtin_trap:
2413 2413 return eval(expr, self.user_global_ns, self.user_ns)
2414 2414
2415 2415 def safe_execfile(self, fname, *where, **kw):
2416 2416 """A safe version of the builtin execfile().
2417 2417
2418 2418 This version will never throw an exception, but instead print
2419 2419 helpful error messages to the screen. This only works on pure
2420 2420 Python files with the .py extension.
2421 2421
2422 2422 Parameters
2423 2423 ----------
2424 2424 fname : string
2425 2425 The name of the file to be executed.
2426 2426 where : tuple
2427 2427 One or two namespaces, passed to execfile() as (globals,locals).
2428 2428 If only one is given, it is passed as both.
2429 2429 exit_ignore : bool (False)
2430 2430 If True, then silence SystemExit for non-zero status (it is always
2431 2431 silenced for zero status, as it is so common).
2432 2432 raise_exceptions : bool (False)
2433 2433 If True raise exceptions everywhere. Meant for testing.
2434 2434
2435 2435 """
2436 2436 kw.setdefault('exit_ignore', False)
2437 2437 kw.setdefault('raise_exceptions', False)
2438 2438
2439 2439 fname = os.path.abspath(os.path.expanduser(fname))
2440 2440
2441 2441 # Make sure we can open the file
2442 2442 try:
2443 2443 with open(fname) as thefile:
2444 2444 pass
2445 2445 except:
2446 2446 warn('Could not open file <%s> for safe execution.' % fname)
2447 2447 return
2448 2448
2449 2449 # Find things also in current directory. This is needed to mimic the
2450 2450 # behavior of running a script from the system command line, where
2451 2451 # Python inserts the script's directory into sys.path
2452 2452 dname = os.path.dirname(fname)
2453 2453
2454 2454 with prepended_to_syspath(dname):
2455 2455 try:
2456 2456 py3compat.execfile(fname,*where)
2457 except SystemExit, status:
2457 except SystemExit as status:
2458 2458 # If the call was made with 0 or None exit status (sys.exit(0)
2459 2459 # or sys.exit() ), don't bother showing a traceback, as both of
2460 2460 # these are considered normal by the OS:
2461 2461 # > python -c'import sys;sys.exit(0)'; echo $?
2462 2462 # 0
2463 2463 # > python -c'import sys;sys.exit()'; echo $?
2464 2464 # 0
2465 2465 # For other exit status, we show the exception unless
2466 2466 # explicitly silenced, but only in short form.
2467 2467 if kw['raise_exceptions']:
2468 2468 raise
2469 2469 if status.code not in (0, None) and not kw['exit_ignore']:
2470 2470 self.showtraceback(exception_only=True)
2471 2471 except:
2472 2472 if kw['raise_exceptions']:
2473 2473 raise
2474 2474 self.showtraceback()
2475 2475
2476 2476 def safe_execfile_ipy(self, fname):
2477 2477 """Like safe_execfile, but for .ipy files with IPython syntax.
2478 2478
2479 2479 Parameters
2480 2480 ----------
2481 2481 fname : str
2482 2482 The name of the file to execute. The filename must have a
2483 2483 .ipy extension.
2484 2484 """
2485 2485 fname = os.path.abspath(os.path.expanduser(fname))
2486 2486
2487 2487 # Make sure we can open the file
2488 2488 try:
2489 2489 with open(fname) as thefile:
2490 2490 pass
2491 2491 except:
2492 2492 warn('Could not open file <%s> for safe execution.' % fname)
2493 2493 return
2494 2494
2495 2495 # Find things also in current directory. This is needed to mimic the
2496 2496 # behavior of running a script from the system command line, where
2497 2497 # Python inserts the script's directory into sys.path
2498 2498 dname = os.path.dirname(fname)
2499 2499
2500 2500 with prepended_to_syspath(dname):
2501 2501 try:
2502 2502 with open(fname) as thefile:
2503 2503 # self.run_cell currently captures all exceptions
2504 2504 # raised in user code. It would be nice if there were
2505 2505 # versions of runlines, execfile that did raise, so
2506 2506 # we could catch the errors.
2507 2507 self.run_cell(thefile.read(), store_history=False)
2508 2508 except:
2509 2509 self.showtraceback()
2510 2510 warn('Unknown failure executing file: <%s>' % fname)
2511 2511
2512 2512 def safe_run_module(self, mod_name, where):
2513 2513 """A safe version of runpy.run_module().
2514 2514
2515 2515 This version will never throw an exception, but instead print
2516 2516 helpful error messages to the screen.
2517 2517
2518 2518 Parameters
2519 2519 ----------
2520 2520 mod_name : string
2521 2521 The name of the module to be executed.
2522 2522 where : dict
2523 2523 The globals namespace.
2524 2524 """
2525 2525 try:
2526 2526 where.update(
2527 2527 runpy.run_module(str(mod_name), run_name="__main__",
2528 2528 alter_sys=True)
2529 2529 )
2530 2530 except:
2531 2531 self.showtraceback()
2532 2532 warn('Unknown failure executing module: <%s>' % mod_name)
2533 2533
2534 2534 def _run_cached_cell_magic(self, magic_name, line):
2535 2535 """Special method to call a cell magic with the data stored in self.
2536 2536 """
2537 2537 cell = self._current_cell_magic_body
2538 2538 self._current_cell_magic_body = None
2539 2539 return self.run_cell_magic(magic_name, line, cell)
2540 2540
2541 2541 def run_cell(self, raw_cell, store_history=False, silent=False):
2542 2542 """Run a complete IPython cell.
2543 2543
2544 2544 Parameters
2545 2545 ----------
2546 2546 raw_cell : str
2547 2547 The code (including IPython code such as %magic functions) to run.
2548 2548 store_history : bool
2549 2549 If True, the raw and translated cell will be stored in IPython's
2550 2550 history. For user code calling back into IPython's machinery, this
2551 2551 should be set to False.
2552 2552 silent : bool
2553 2553 If True, avoid side-effets, such as implicit displayhooks, history,
2554 2554 and logging. silent=True forces store_history=False.
2555 2555 """
2556 2556 if (not raw_cell) or raw_cell.isspace():
2557 2557 return
2558 2558
2559 2559 if silent:
2560 2560 store_history = False
2561 2561
2562 2562 self.input_splitter.push(raw_cell)
2563 2563
2564 2564 # Check for cell magics, which leave state behind. This interface is
2565 2565 # ugly, we need to do something cleaner later... Now the logic is
2566 2566 # simply that the input_splitter remembers if there was a cell magic,
2567 2567 # and in that case we grab the cell body.
2568 2568 if self.input_splitter.cell_magic_parts:
2569 2569 self._current_cell_magic_body = \
2570 2570 ''.join(self.input_splitter.cell_magic_parts)
2571 2571 cell = self.input_splitter.source_reset()
2572 2572
2573 2573 with self.builtin_trap:
2574 2574 prefilter_failed = False
2575 2575 if len(cell.splitlines()) == 1:
2576 2576 try:
2577 2577 # use prefilter_lines to handle trailing newlines
2578 2578 # restore trailing newline for ast.parse
2579 2579 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2580 2580 except AliasError as e:
2581 2581 error(e)
2582 2582 prefilter_failed = True
2583 2583 except Exception:
2584 2584 # don't allow prefilter errors to crash IPython
2585 2585 self.showtraceback()
2586 2586 prefilter_failed = True
2587 2587
2588 2588 # Store raw and processed history
2589 2589 if store_history:
2590 2590 self.history_manager.store_inputs(self.execution_count,
2591 2591 cell, raw_cell)
2592 2592 if not silent:
2593 2593 self.logger.log(cell, raw_cell)
2594 2594
2595 2595 if not prefilter_failed:
2596 2596 # don't run if prefilter failed
2597 2597 cell_name = self.compile.cache(cell, self.execution_count)
2598 2598
2599 2599 with self.display_trap:
2600 2600 try:
2601 2601 code_ast = self.compile.ast_parse(cell,
2602 2602 filename=cell_name)
2603 2603 except IndentationError:
2604 2604 self.showindentationerror()
2605 2605 if store_history:
2606 2606 self.execution_count += 1
2607 2607 return None
2608 2608 except (OverflowError, SyntaxError, ValueError, TypeError,
2609 2609 MemoryError):
2610 2610 self.showsyntaxerror()
2611 2611 if store_history:
2612 2612 self.execution_count += 1
2613 2613 return None
2614 2614
2615 2615 interactivity = "none" if silent else self.ast_node_interactivity
2616 2616 self.run_ast_nodes(code_ast.body, cell_name,
2617 2617 interactivity=interactivity)
2618 2618
2619 2619 # Execute any registered post-execution functions.
2620 2620 # unless we are silent
2621 2621 post_exec = [] if silent else self._post_execute.iteritems()
2622 2622
2623 2623 for func, status in post_exec:
2624 2624 if self.disable_failing_post_execute and not status:
2625 2625 continue
2626 2626 try:
2627 2627 func()
2628 2628 except KeyboardInterrupt:
2629 2629 print >> io.stderr, "\nKeyboardInterrupt"
2630 2630 except Exception:
2631 2631 # register as failing:
2632 2632 self._post_execute[func] = False
2633 2633 self.showtraceback()
2634 2634 print >> io.stderr, '\n'.join([
2635 2635 "post-execution function %r produced an error." % func,
2636 2636 "If this problem persists, you can disable failing post-exec functions with:",
2637 2637 "",
2638 2638 " get_ipython().disable_failing_post_execute = True"
2639 2639 ])
2640 2640
2641 2641 if store_history:
2642 2642 # Write output to the database. Does nothing unless
2643 2643 # history output logging is enabled.
2644 2644 self.history_manager.store_output(self.execution_count)
2645 2645 # Each cell is a *single* input, regardless of how many lines it has
2646 2646 self.execution_count += 1
2647 2647
2648 2648 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr'):
2649 2649 """Run a sequence of AST nodes. The execution mode depends on the
2650 2650 interactivity parameter.
2651 2651
2652 2652 Parameters
2653 2653 ----------
2654 2654 nodelist : list
2655 2655 A sequence of AST nodes to run.
2656 2656 cell_name : str
2657 2657 Will be passed to the compiler as the filename of the cell. Typically
2658 2658 the value returned by ip.compile.cache(cell).
2659 2659 interactivity : str
2660 2660 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2661 2661 run interactively (displaying output from expressions). 'last_expr'
2662 2662 will run the last node interactively only if it is an expression (i.e.
2663 2663 expressions in loops or other blocks are not displayed. Other values
2664 2664 for this parameter will raise a ValueError.
2665 2665 """
2666 2666 if not nodelist:
2667 2667 return
2668 2668
2669 2669 if interactivity == 'last_expr':
2670 2670 if isinstance(nodelist[-1], ast.Expr):
2671 2671 interactivity = "last"
2672 2672 else:
2673 2673 interactivity = "none"
2674 2674
2675 2675 if interactivity == 'none':
2676 2676 to_run_exec, to_run_interactive = nodelist, []
2677 2677 elif interactivity == 'last':
2678 2678 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2679 2679 elif interactivity == 'all':
2680 2680 to_run_exec, to_run_interactive = [], nodelist
2681 2681 else:
2682 2682 raise ValueError("Interactivity was %r" % interactivity)
2683 2683
2684 2684 exec_count = self.execution_count
2685 2685
2686 2686 try:
2687 2687 for i, node in enumerate(to_run_exec):
2688 2688 mod = ast.Module([node])
2689 2689 code = self.compile(mod, cell_name, "exec")
2690 2690 if self.run_code(code):
2691 2691 return True
2692 2692
2693 2693 for i, node in enumerate(to_run_interactive):
2694 2694 mod = ast.Interactive([node])
2695 2695 code = self.compile(mod, cell_name, "single")
2696 2696 if self.run_code(code):
2697 2697 return True
2698 2698
2699 2699 # Flush softspace
2700 2700 if softspace(sys.stdout, 0):
2701 2701 print
2702 2702
2703 2703 except:
2704 2704 # It's possible to have exceptions raised here, typically by
2705 2705 # compilation of odd code (such as a naked 'return' outside a
2706 2706 # function) that did parse but isn't valid. Typically the exception
2707 2707 # is a SyntaxError, but it's safest just to catch anything and show
2708 2708 # the user a traceback.
2709 2709
2710 2710 # We do only one try/except outside the loop to minimize the impact
2711 2711 # on runtime, and also because if any node in the node list is
2712 2712 # broken, we should stop execution completely.
2713 2713 self.showtraceback()
2714 2714
2715 2715 return False
2716 2716
2717 2717 def run_code(self, code_obj):
2718 2718 """Execute a code object.
2719 2719
2720 2720 When an exception occurs, self.showtraceback() is called to display a
2721 2721 traceback.
2722 2722
2723 2723 Parameters
2724 2724 ----------
2725 2725 code_obj : code object
2726 2726 A compiled code object, to be executed
2727 2727
2728 2728 Returns
2729 2729 -------
2730 2730 False : successful execution.
2731 2731 True : an error occurred.
2732 2732 """
2733 2733
2734 2734 # Set our own excepthook in case the user code tries to call it
2735 2735 # directly, so that the IPython crash handler doesn't get triggered
2736 2736 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2737 2737
2738 2738 # we save the original sys.excepthook in the instance, in case config
2739 2739 # code (such as magics) needs access to it.
2740 2740 self.sys_excepthook = old_excepthook
2741 2741 outflag = 1 # happens in more places, so it's easier as default
2742 2742 try:
2743 2743 try:
2744 2744 self.hooks.pre_run_code_hook()
2745 2745 #rprint('Running code', repr(code_obj)) # dbg
2746 2746 exec code_obj in self.user_global_ns, self.user_ns
2747 2747 finally:
2748 2748 # Reset our crash handler in place
2749 2749 sys.excepthook = old_excepthook
2750 2750 except SystemExit:
2751 2751 self.showtraceback(exception_only=True)
2752 2752 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2753 2753 except self.custom_exceptions:
2754 2754 etype,value,tb = sys.exc_info()
2755 2755 self.CustomTB(etype,value,tb)
2756 2756 except:
2757 2757 self.showtraceback()
2758 2758 else:
2759 2759 outflag = 0
2760 2760 return outflag
2761 2761
2762 2762 # For backwards compatibility
2763 2763 runcode = run_code
2764 2764
2765 2765 #-------------------------------------------------------------------------
2766 2766 # Things related to GUI support and pylab
2767 2767 #-------------------------------------------------------------------------
2768 2768
2769 2769 def enable_gui(self, gui=None):
2770 2770 raise NotImplementedError('Implement enable_gui in a subclass')
2771 2771
2772 2772 def enable_pylab(self, gui=None, import_all=True):
2773 2773 """Activate pylab support at runtime.
2774 2774
2775 2775 This turns on support for matplotlib, preloads into the interactive
2776 2776 namespace all of numpy and pylab, and configures IPython to correctly
2777 2777 interact with the GUI event loop. The GUI backend to be used can be
2778 2778 optionally selected with the optional :param:`gui` argument.
2779 2779
2780 2780 Parameters
2781 2781 ----------
2782 2782 gui : optional, string
2783 2783
2784 2784 If given, dictates the choice of matplotlib GUI backend to use
2785 2785 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2786 2786 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2787 2787 matplotlib (as dictated by the matplotlib build-time options plus the
2788 2788 user's matplotlibrc configuration file). Note that not all backends
2789 2789 make sense in all contexts, for example a terminal ipython can't
2790 2790 display figures inline.
2791 2791 """
2792 2792 from IPython.core.pylabtools import mpl_runner
2793 2793 # We want to prevent the loading of pylab to pollute the user's
2794 2794 # namespace as shown by the %who* magics, so we execute the activation
2795 2795 # code in an empty namespace, and we update *both* user_ns and
2796 2796 # user_ns_hidden with this information.
2797 2797 ns = {}
2798 2798 try:
2799 2799 gui = pylab_activate(ns, gui, import_all, self)
2800 2800 except KeyError:
2801 2801 error("Backend %r not supported" % gui)
2802 2802 return
2803 2803 self.user_ns.update(ns)
2804 2804 self.user_ns_hidden.update(ns)
2805 2805 # Now we must activate the gui pylab wants to use, and fix %run to take
2806 2806 # plot updates into account
2807 2807 self.enable_gui(gui)
2808 2808 self.magics_manager.registry['ExecutionMagics'].default_runner = \
2809 2809 mpl_runner(self.safe_execfile)
2810 2810
2811 2811 #-------------------------------------------------------------------------
2812 2812 # Utilities
2813 2813 #-------------------------------------------------------------------------
2814 2814
2815 2815 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
2816 2816 """Expand python variables in a string.
2817 2817
2818 2818 The depth argument indicates how many frames above the caller should
2819 2819 be walked to look for the local namespace where to expand variables.
2820 2820
2821 2821 The global namespace for expansion is always the user's interactive
2822 2822 namespace.
2823 2823 """
2824 2824 ns = self.user_ns.copy()
2825 2825 ns.update(sys._getframe(depth+1).f_locals)
2826 2826 ns.pop('self', None)
2827 2827 try:
2828 2828 cmd = formatter.format(cmd, **ns)
2829 2829 except Exception:
2830 2830 # if formatter couldn't format, just let it go untransformed
2831 2831 pass
2832 2832 return cmd
2833 2833
2834 2834 def mktempfile(self, data=None, prefix='ipython_edit_'):
2835 2835 """Make a new tempfile and return its filename.
2836 2836
2837 2837 This makes a call to tempfile.mktemp, but it registers the created
2838 2838 filename internally so ipython cleans it up at exit time.
2839 2839
2840 2840 Optional inputs:
2841 2841
2842 2842 - data(None): if data is given, it gets written out to the temp file
2843 2843 immediately, and the file is closed again."""
2844 2844
2845 2845 filename = tempfile.mktemp('.py', prefix)
2846 2846 self.tempfiles.append(filename)
2847 2847
2848 2848 if data:
2849 2849 tmp_file = open(filename,'w')
2850 2850 tmp_file.write(data)
2851 2851 tmp_file.close()
2852 2852 return filename
2853 2853
2854 2854 # TODO: This should be removed when Term is refactored.
2855 2855 def write(self,data):
2856 2856 """Write a string to the default output"""
2857 2857 io.stdout.write(data)
2858 2858
2859 2859 # TODO: This should be removed when Term is refactored.
2860 2860 def write_err(self,data):
2861 2861 """Write a string to the default error output"""
2862 2862 io.stderr.write(data)
2863 2863
2864 2864 def ask_yes_no(self, prompt, default=None):
2865 2865 if self.quiet:
2866 2866 return True
2867 2867 return ask_yes_no(prompt,default)
2868 2868
2869 2869 def show_usage(self):
2870 2870 """Show a usage message"""
2871 2871 page.page(IPython.core.usage.interactive_usage)
2872 2872
2873 2873 def extract_input_lines(self, range_str, raw=False):
2874 2874 """Return as a string a set of input history slices.
2875 2875
2876 2876 Parameters
2877 2877 ----------
2878 2878 range_str : string
2879 2879 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
2880 2880 since this function is for use by magic functions which get their
2881 2881 arguments as strings. The number before the / is the session
2882 2882 number: ~n goes n back from the current session.
2883 2883
2884 2884 Optional Parameters:
2885 2885 - raw(False): by default, the processed input is used. If this is
2886 2886 true, the raw input history is used instead.
2887 2887
2888 2888 Note that slices can be called with two notations:
2889 2889
2890 2890 N:M -> standard python form, means including items N...(M-1).
2891 2891
2892 2892 N-M -> include items N..M (closed endpoint)."""
2893 2893 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
2894 2894 return "\n".join(x for _, _, x in lines)
2895 2895
2896 2896 def find_user_code(self, target, raw=True, py_only=False):
2897 2897 """Get a code string from history, file, url, or a string or macro.
2898 2898
2899 2899 This is mainly used by magic functions.
2900 2900
2901 2901 Parameters
2902 2902 ----------
2903 2903
2904 2904 target : str
2905 2905
2906 2906 A string specifying code to retrieve. This will be tried respectively
2907 2907 as: ranges of input history (see %history for syntax), url,
2908 2908 correspnding .py file, filename, or an expression evaluating to a
2909 2909 string or Macro in the user namespace.
2910 2910
2911 2911 raw : bool
2912 2912 If true (default), retrieve raw history. Has no effect on the other
2913 2913 retrieval mechanisms.
2914 2914
2915 2915 py_only : bool (default False)
2916 2916 Only try to fetch python code, do not try alternative methods to decode file
2917 2917 if unicode fails.
2918 2918
2919 2919 Returns
2920 2920 -------
2921 2921 A string of code.
2922 2922
2923 2923 ValueError is raised if nothing is found, and TypeError if it evaluates
2924 2924 to an object of another type. In each case, .args[0] is a printable
2925 2925 message.
2926 2926 """
2927 2927 code = self.extract_input_lines(target, raw=raw) # Grab history
2928 2928 if code:
2929 2929 return code
2930 2930 utarget = unquote_filename(target)
2931 2931 try:
2932 2932 if utarget.startswith(('http://', 'https://')):
2933 2933 return openpy.read_py_url(utarget, skip_encoding_cookie=True)
2934 2934 except UnicodeDecodeError:
2935 2935 if not py_only :
2936 2936 response = urllib.urlopen(target)
2937 2937 return response.read().decode('latin1')
2938 2938 raise ValueError(("'%s' seem to be unreadable.") % utarget)
2939 2939
2940 2940 potential_target = [target]
2941 2941 try :
2942 2942 potential_target.insert(0,get_py_filename(target))
2943 2943 except IOError:
2944 2944 pass
2945 2945
2946 2946 for tgt in potential_target :
2947 2947 if os.path.isfile(tgt): # Read file
2948 2948 try :
2949 2949 return openpy.read_py_file(tgt, skip_encoding_cookie=True)
2950 2950 except UnicodeDecodeError :
2951 2951 if not py_only :
2952 2952 with io_open(tgt,'r', encoding='latin1') as f :
2953 2953 return f.read()
2954 2954 raise ValueError(("'%s' seem to be unreadable.") % target)
2955 2955
2956 2956 try: # User namespace
2957 2957 codeobj = eval(target, self.user_ns)
2958 2958 except Exception:
2959 2959 raise ValueError(("'%s' was not found in history, as a file, url, "
2960 2960 "nor in the user namespace.") % target)
2961 2961 if isinstance(codeobj, basestring):
2962 2962 return codeobj
2963 2963 elif isinstance(codeobj, Macro):
2964 2964 return codeobj.value
2965 2965
2966 2966 raise TypeError("%s is neither a string nor a macro." % target,
2967 2967 codeobj)
2968 2968
2969 2969 #-------------------------------------------------------------------------
2970 2970 # Things related to IPython exiting
2971 2971 #-------------------------------------------------------------------------
2972 2972 def atexit_operations(self):
2973 2973 """This will be executed at the time of exit.
2974 2974
2975 2975 Cleanup operations and saving of persistent data that is done
2976 2976 unconditionally by IPython should be performed here.
2977 2977
2978 2978 For things that may depend on startup flags or platform specifics (such
2979 2979 as having readline or not), register a separate atexit function in the
2980 2980 code that has the appropriate information, rather than trying to
2981 2981 clutter
2982 2982 """
2983 2983 # Close the history session (this stores the end time and line count)
2984 2984 # this must be *before* the tempfile cleanup, in case of temporary
2985 2985 # history db
2986 2986 self.history_manager.end_session()
2987 2987
2988 2988 # Cleanup all tempfiles left around
2989 2989 for tfile in self.tempfiles:
2990 2990 try:
2991 2991 os.unlink(tfile)
2992 2992 except OSError:
2993 2993 pass
2994 2994
2995 2995 # Clear all user namespaces to release all references cleanly.
2996 2996 self.reset(new_session=False)
2997 2997
2998 2998 # Run user hooks
2999 2999 self.hooks.shutdown_hook()
3000 3000
3001 3001 def cleanup(self):
3002 3002 self.restore_sys_module_state()
3003 3003
3004 3004
3005 3005 class InteractiveShellABC(object):
3006 3006 """An abstract base class for InteractiveShell."""
3007 3007 __metaclass__ = abc.ABCMeta
3008 3008
3009 3009 InteractiveShellABC.register(InteractiveShell)
@@ -1,617 +1,617 b''
1 1 # encoding: utf-8
2 2 """Magic functions for InteractiveShell.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 8 # Copyright (C) 2008 The IPython Development Team
9 9
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17 # Stdlib
18 18 import os
19 19 import re
20 20 import sys
21 21 import types
22 22 from getopt import getopt, GetoptError
23 23
24 24 # Our own
25 25 from IPython.config.configurable import Configurable
26 26 from IPython.core import oinspect
27 27 from IPython.core.error import UsageError
28 28 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
29 29 from IPython.external.decorator import decorator
30 30 from IPython.utils.ipstruct import Struct
31 31 from IPython.utils.process import arg_split
32 32 from IPython.utils.text import dedent
33 33 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
34 34 from IPython.utils.warn import error, warn
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Globals
38 38 #-----------------------------------------------------------------------------
39 39
40 40 # A dict we'll use for each class that has magics, used as temporary storage to
41 41 # pass information between the @line/cell_magic method decorators and the
42 42 # @magics_class class decorator, because the method decorators have no
43 43 # access to the class when they run. See for more details:
44 44 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
45 45
46 46 magics = dict(line={}, cell={})
47 47
48 48 magic_kinds = ('line', 'cell')
49 49 magic_spec = ('line', 'cell', 'line_cell')
50 50 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
51 51
52 52 #-----------------------------------------------------------------------------
53 53 # Utility classes and functions
54 54 #-----------------------------------------------------------------------------
55 55
56 56 class Bunch: pass
57 57
58 58
59 59 def on_off(tag):
60 60 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
61 61 return ['OFF','ON'][tag]
62 62
63 63
64 64 def compress_dhist(dh):
65 65 """Compress a directory history into a new one with at most 20 entries.
66 66
67 67 Return a new list made from the first and last 10 elements of dhist after
68 68 removal of duplicates.
69 69 """
70 70 head, tail = dh[:-10], dh[-10:]
71 71
72 72 newhead = []
73 73 done = set()
74 74 for h in head:
75 75 if h in done:
76 76 continue
77 77 newhead.append(h)
78 78 done.add(h)
79 79
80 80 return newhead + tail
81 81
82 82
83 83 def needs_local_scope(func):
84 84 """Decorator to mark magic functions which need to local scope to run."""
85 85 func.needs_local_scope = True
86 86 return func
87 87
88 88 #-----------------------------------------------------------------------------
89 89 # Class and method decorators for registering magics
90 90 #-----------------------------------------------------------------------------
91 91
92 92 def magics_class(cls):
93 93 """Class decorator for all subclasses of the main Magics class.
94 94
95 95 Any class that subclasses Magics *must* also apply this decorator, to
96 96 ensure that all the methods that have been decorated as line/cell magics
97 97 get correctly registered in the class instance. This is necessary because
98 98 when method decorators run, the class does not exist yet, so they
99 99 temporarily store their information into a module global. Application of
100 100 this class decorator copies that global data to the class instance and
101 101 clears the global.
102 102
103 103 Obviously, this mechanism is not thread-safe, which means that the
104 104 *creation* of subclasses of Magic should only be done in a single-thread
105 105 context. Instantiation of the classes has no restrictions. Given that
106 106 these classes are typically created at IPython startup time and before user
107 107 application code becomes active, in practice this should not pose any
108 108 problems.
109 109 """
110 110 cls.registered = True
111 111 cls.magics = dict(line = magics['line'],
112 112 cell = magics['cell'])
113 113 magics['line'] = {}
114 114 magics['cell'] = {}
115 115 return cls
116 116
117 117
118 118 def record_magic(dct, magic_kind, magic_name, func):
119 119 """Utility function to store a function as a magic of a specific kind.
120 120
121 121 Parameters
122 122 ----------
123 123 dct : dict
124 124 A dictionary with 'line' and 'cell' subdicts.
125 125
126 126 magic_kind : str
127 127 Kind of magic to be stored.
128 128
129 129 magic_name : str
130 130 Key to store the magic as.
131 131
132 132 func : function
133 133 Callable object to store.
134 134 """
135 135 if magic_kind == 'line_cell':
136 136 dct['line'][magic_name] = dct['cell'][magic_name] = func
137 137 else:
138 138 dct[magic_kind][magic_name] = func
139 139
140 140
141 141 def validate_type(magic_kind):
142 142 """Ensure that the given magic_kind is valid.
143 143
144 144 Check that the given magic_kind is one of the accepted spec types (stored
145 145 in the global `magic_spec`), raise ValueError otherwise.
146 146 """
147 147 if magic_kind not in magic_spec:
148 148 raise ValueError('magic_kind must be one of %s, %s given' %
149 149 magic_kinds, magic_kind)
150 150
151 151
152 152 # The docstrings for the decorator below will be fairly similar for the two
153 153 # types (method and function), so we generate them here once and reuse the
154 154 # templates below.
155 155 _docstring_template = \
156 156 """Decorate the given {0} as {1} magic.
157 157
158 158 The decorator can be used with or without arguments, as follows.
159 159
160 160 i) without arguments: it will create a {1} magic named as the {0} being
161 161 decorated::
162 162
163 163 @deco
164 164 def foo(...)
165 165
166 166 will create a {1} magic named `foo`.
167 167
168 168 ii) with one string argument: which will be used as the actual name of the
169 169 resulting magic::
170 170
171 171 @deco('bar')
172 172 def foo(...)
173 173
174 174 will create a {1} magic named `bar`.
175 175 """
176 176
177 177 # These two are decorator factories. While they are conceptually very similar,
178 178 # there are enough differences in the details that it's simpler to have them
179 179 # written as completely standalone functions rather than trying to share code
180 180 # and make a single one with convoluted logic.
181 181
182 182 def _method_magic_marker(magic_kind):
183 183 """Decorator factory for methods in Magics subclasses.
184 184 """
185 185
186 186 validate_type(magic_kind)
187 187
188 188 # This is a closure to capture the magic_kind. We could also use a class,
189 189 # but it's overkill for just that one bit of state.
190 190 def magic_deco(arg):
191 191 call = lambda f, *a, **k: f(*a, **k)
192 192
193 193 if callable(arg):
194 194 # "Naked" decorator call (just @foo, no args)
195 195 func = arg
196 196 name = func.func_name
197 197 retval = decorator(call, func)
198 198 record_magic(magics, magic_kind, name, name)
199 199 elif isinstance(arg, basestring):
200 200 # Decorator called with arguments (@foo('bar'))
201 201 name = arg
202 202 def mark(func, *a, **kw):
203 203 record_magic(magics, magic_kind, name, func.func_name)
204 204 return decorator(call, func)
205 205 retval = mark
206 206 else:
207 207 raise TypeError("Decorator can only be called with "
208 208 "string or function")
209 209 return retval
210 210
211 211 # Ensure the resulting decorator has a usable docstring
212 212 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
213 213 return magic_deco
214 214
215 215
216 216 def _function_magic_marker(magic_kind):
217 217 """Decorator factory for standalone functions.
218 218 """
219 219 validate_type(magic_kind)
220 220
221 221 # This is a closure to capture the magic_kind. We could also use a class,
222 222 # but it's overkill for just that one bit of state.
223 223 def magic_deco(arg):
224 224 call = lambda f, *a, **k: f(*a, **k)
225 225
226 226 # Find get_ipython() in the caller's namespace
227 227 caller = sys._getframe(1)
228 228 for ns in ['f_locals', 'f_globals', 'f_builtins']:
229 229 get_ipython = getattr(caller, ns).get('get_ipython')
230 230 if get_ipython is not None:
231 231 break
232 232 else:
233 233 raise NameError('Decorator can only run in context where '
234 234 '`get_ipython` exists')
235 235
236 236 ip = get_ipython()
237 237
238 238 if callable(arg):
239 239 # "Naked" decorator call (just @foo, no args)
240 240 func = arg
241 241 name = func.func_name
242 242 ip.register_magic_function(func, magic_kind, name)
243 243 retval = decorator(call, func)
244 244 elif isinstance(arg, basestring):
245 245 # Decorator called with arguments (@foo('bar'))
246 246 name = arg
247 247 def mark(func, *a, **kw):
248 248 ip.register_magic_function(func, magic_kind, name)
249 249 return decorator(call, func)
250 250 retval = mark
251 251 else:
252 252 raise TypeError("Decorator can only be called with "
253 253 "string or function")
254 254 return retval
255 255
256 256 # Ensure the resulting decorator has a usable docstring
257 257 ds = _docstring_template.format('function', magic_kind)
258 258
259 259 ds += dedent("""
260 260 Note: this decorator can only be used in a context where IPython is already
261 261 active, so that the `get_ipython()` call succeeds. You can therefore use
262 262 it in your startup files loaded after IPython initializes, but *not* in the
263 263 IPython configuration file itself, which is executed before IPython is
264 264 fully up and running. Any file located in the `startup` subdirectory of
265 265 your configuration profile will be OK in this sense.
266 266 """)
267 267
268 268 magic_deco.__doc__ = ds
269 269 return magic_deco
270 270
271 271
272 272 # Create the actual decorators for public use
273 273
274 274 # These three are used to decorate methods in class definitions
275 275 line_magic = _method_magic_marker('line')
276 276 cell_magic = _method_magic_marker('cell')
277 277 line_cell_magic = _method_magic_marker('line_cell')
278 278
279 279 # These three decorate standalone functions and perform the decoration
280 280 # immediately. They can only run where get_ipython() works
281 281 register_line_magic = _function_magic_marker('line')
282 282 register_cell_magic = _function_magic_marker('cell')
283 283 register_line_cell_magic = _function_magic_marker('line_cell')
284 284
285 285 #-----------------------------------------------------------------------------
286 286 # Core Magic classes
287 287 #-----------------------------------------------------------------------------
288 288
289 289 class MagicsManager(Configurable):
290 290 """Object that handles all magic-related functionality for IPython.
291 291 """
292 292 # Non-configurable class attributes
293 293
294 294 # A two-level dict, first keyed by magic type, then by magic function, and
295 295 # holding the actual callable object as value. This is the dict used for
296 296 # magic function dispatch
297 297 magics = Dict
298 298
299 299 # A registry of the original objects that we've been given holding magics.
300 300 registry = Dict
301 301
302 302 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
303 303
304 304 auto_magic = Bool(True, config=True, help=
305 305 "Automatically call line magics without requiring explicit % prefix")
306 306
307 307 _auto_status = [
308 308 'Automagic is OFF, % prefix IS needed for line magics.',
309 309 'Automagic is ON, % prefix IS NOT needed for line magics.']
310 310
311 311 user_magics = Instance('IPython.core.magics.UserMagics')
312 312
313 313 def __init__(self, shell=None, config=None, user_magics=None, **traits):
314 314
315 315 super(MagicsManager, self).__init__(shell=shell, config=config,
316 316 user_magics=user_magics, **traits)
317 317 self.magics = dict(line={}, cell={})
318 318 # Let's add the user_magics to the registry for uniformity, so *all*
319 319 # registered magic containers can be found there.
320 320 self.registry[user_magics.__class__.__name__] = user_magics
321 321
322 322 def auto_status(self):
323 323 """Return descriptive string with automagic status."""
324 324 return self._auto_status[self.auto_magic]
325 325
326 326 def lsmagic_info(self):
327 327 magic_list = []
328 328 for m_type in self.magics :
329 329 for m_name,mgc in self.magics[m_type].items():
330 330 try :
331 331 magic_list.append({'name':m_name,'type':m_type,'class':mgc.im_class.__name__})
332 332 except AttributeError :
333 333 magic_list.append({'name':m_name,'type':m_type,'class':'Other'})
334 334 return magic_list
335 335
336 336 def lsmagic(self):
337 337 """Return a dict of currently available magic functions.
338 338
339 339 The return dict has the keys 'line' and 'cell', corresponding to the
340 340 two types of magics we support. Each value is a list of names.
341 341 """
342 342 return self.magics
343 343
344 344 def lsmagic_docs(self, brief=False, missing=''):
345 345 """Return dict of documentation of magic functions.
346 346
347 347 The return dict has the keys 'line' and 'cell', corresponding to the
348 348 two types of magics we support. Each value is a dict keyed by magic
349 349 name whose value is the function docstring. If a docstring is
350 350 unavailable, the value of `missing` is used instead.
351 351
352 352 If brief is True, only the first line of each docstring will be returned.
353 353 """
354 354 docs = {}
355 355 for m_type in self.magics:
356 356 m_docs = {}
357 357 for m_name, m_func in self.magics[m_type].iteritems():
358 358 if m_func.__doc__:
359 359 if brief:
360 360 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
361 361 else:
362 362 m_docs[m_name] = m_func.__doc__.rstrip()
363 363 else:
364 364 m_docs[m_name] = missing
365 365 docs[m_type] = m_docs
366 366 return docs
367 367
368 368 def register(self, *magic_objects):
369 369 """Register one or more instances of Magics.
370 370
371 371 Take one or more classes or instances of classes that subclass the main
372 372 `core.Magic` class, and register them with IPython to use the magic
373 373 functions they provide. The registration process will then ensure that
374 374 any methods that have decorated to provide line and/or cell magics will
375 375 be recognized with the `%x`/`%%x` syntax as a line/cell magic
376 376 respectively.
377 377
378 378 If classes are given, they will be instantiated with the default
379 379 constructor. If your classes need a custom constructor, you should
380 380 instanitate them first and pass the instance.
381 381
382 382 The provided arguments can be an arbitrary mix of classes and instances.
383 383
384 384 Parameters
385 385 ----------
386 386 magic_objects : one or more classes or instances
387 387 """
388 388 # Start by validating them to ensure they have all had their magic
389 389 # methods registered at the instance level
390 390 for m in magic_objects:
391 391 if not m.registered:
392 392 raise ValueError("Class of magics %r was constructed without "
393 393 "the @register_magics class decorator")
394 394 if type(m) in (type, MetaHasTraits):
395 395 # If we're given an uninstantiated class
396 396 m = m(shell=self.shell)
397 397
398 398 # Now that we have an instance, we can register it and update the
399 399 # table of callables
400 400 self.registry[m.__class__.__name__] = m
401 401 for mtype in magic_kinds:
402 402 self.magics[mtype].update(m.magics[mtype])
403 403
404 404 def register_function(self, func, magic_kind='line', magic_name=None):
405 405 """Expose a standalone function as magic function for IPython.
406 406
407 407 This will create an IPython magic (line, cell or both) from a
408 408 standalone function. The functions should have the following
409 409 signatures:
410 410
411 411 * For line magics: `def f(line)`
412 412 * For cell magics: `def f(line, cell)`
413 413 * For a function that does both: `def f(line, cell=None)`
414 414
415 415 In the latter case, the function will be called with `cell==None` when
416 416 invoked as `%f`, and with cell as a string when invoked as `%%f`.
417 417
418 418 Parameters
419 419 ----------
420 420 func : callable
421 421 Function to be registered as a magic.
422 422
423 423 magic_kind : str
424 424 Kind of magic, one of 'line', 'cell' or 'line_cell'
425 425
426 426 magic_name : optional str
427 427 If given, the name the magic will have in the IPython namespace. By
428 428 default, the name of the function itself is used.
429 429 """
430 430
431 431 # Create the new method in the user_magics and register it in the
432 432 # global table
433 433 validate_type(magic_kind)
434 434 magic_name = func.func_name if magic_name is None else magic_name
435 435 setattr(self.user_magics, magic_name, func)
436 436 record_magic(self.magics, magic_kind, magic_name, func)
437 437
438 438 def define_magic(self, name, func):
439 439 """[Deprecated] Expose own function as magic function for IPython.
440 440
441 441 Example::
442 442
443 443 def foo_impl(self, parameter_s=''):
444 444 'My very own magic!. (Use docstrings, IPython reads them).'
445 445 print 'Magic function. Passed parameter is between < >:'
446 446 print '<%s>' % parameter_s
447 447 print 'The self object is:', self
448 448
449 449 ip.define_magic('foo',foo_impl)
450 450 """
451 451 meth = types.MethodType(func, self.user_magics)
452 452 setattr(self.user_magics, name, meth)
453 453 record_magic(self.magics, 'line', name, meth)
454 454
455 455 # Key base class that provides the central functionality for magics.
456 456
457 457 class Magics(object):
458 458 """Base class for implementing magic functions.
459 459
460 460 Shell functions which can be reached as %function_name. All magic
461 461 functions should accept a string, which they can parse for their own
462 462 needs. This can make some functions easier to type, eg `%cd ../`
463 463 vs. `%cd("../")`
464 464
465 465 Classes providing magic functions need to subclass this class, and they
466 466 MUST:
467 467
468 468 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
469 469 individual methods as magic functions, AND
470 470
471 471 - Use the class decorator `@magics_class` to ensure that the magic
472 472 methods are properly registered at the instance level upon instance
473 473 initialization.
474 474
475 475 See :mod:`magic_functions` for examples of actual implementation classes.
476 476 """
477 477 # Dict holding all command-line options for each magic.
478 478 options_table = None
479 479 # Dict for the mapping of magic names to methods, set by class decorator
480 480 magics = None
481 481 # Flag to check that the class decorator was properly applied
482 482 registered = False
483 483 # Instance of IPython shell
484 484 shell = None
485 485
486 486 def __init__(self, shell):
487 487 if not(self.__class__.registered):
488 488 raise ValueError('Magics subclass without registration - '
489 489 'did you forget to apply @magics_class?')
490 490 self.shell = shell
491 491 self.options_table = {}
492 492 # The method decorators are run when the instance doesn't exist yet, so
493 493 # they can only record the names of the methods they are supposed to
494 494 # grab. Only now, that the instance exists, can we create the proper
495 495 # mapping to bound methods. So we read the info off the original names
496 496 # table and replace each method name by the actual bound method.
497 497 # But we mustn't clobber the *class* mapping, in case of multiple instances.
498 498 class_magics = self.magics
499 499 self.magics = {}
500 500 for mtype in magic_kinds:
501 501 tab = self.magics[mtype] = {}
502 502 cls_tab = class_magics[mtype]
503 503 for magic_name, meth_name in cls_tab.iteritems():
504 504 if isinstance(meth_name, basestring):
505 505 # it's a method name, grab it
506 506 tab[magic_name] = getattr(self, meth_name)
507 507 else:
508 508 # it's the real thing
509 509 tab[magic_name] = meth_name
510 510
511 511 def arg_err(self,func):
512 512 """Print docstring if incorrect arguments were passed"""
513 513 print 'Error in arguments:'
514 514 print oinspect.getdoc(func)
515 515
516 516 def format_latex(self, strng):
517 517 """Format a string for latex inclusion."""
518 518
519 519 # Characters that need to be escaped for latex:
520 520 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
521 521 # Magic command names as headers:
522 522 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
523 523 re.MULTILINE)
524 524 # Magic commands
525 525 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
526 526 re.MULTILINE)
527 527 # Paragraph continue
528 528 par_re = re.compile(r'\\$',re.MULTILINE)
529 529
530 530 # The "\n" symbol
531 531 newline_re = re.compile(r'\\n')
532 532
533 533 # Now build the string for output:
534 534 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
535 535 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
536 536 strng)
537 537 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
538 538 strng = par_re.sub(r'\\\\',strng)
539 539 strng = escape_re.sub(r'\\\1',strng)
540 540 strng = newline_re.sub(r'\\textbackslash{}n',strng)
541 541 return strng
542 542
543 543 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
544 544 """Parse options passed to an argument string.
545 545
546 546 The interface is similar to that of getopt(), but it returns back a
547 547 Struct with the options as keys and the stripped argument string still
548 548 as a string.
549 549
550 550 arg_str is quoted as a true sys.argv vector by using shlex.split.
551 551 This allows us to easily expand variables, glob files, quote
552 552 arguments, etc.
553 553
554 554 Options:
555 555 -mode: default 'string'. If given as 'list', the argument string is
556 556 returned as a list (split on whitespace) instead of a string.
557 557
558 558 -list_all: put all option values in lists. Normally only options
559 559 appearing more than once are put in a list.
560 560
561 561 -posix (True): whether to split the input line in POSIX mode or not,
562 562 as per the conventions outlined in the shlex module from the
563 563 standard library."""
564 564
565 565 # inject default options at the beginning of the input line
566 566 caller = sys._getframe(1).f_code.co_name
567 567 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
568 568
569 569 mode = kw.get('mode','string')
570 570 if mode not in ['string','list']:
571 571 raise ValueError,'incorrect mode given: %s' % mode
572 572 # Get options
573 573 list_all = kw.get('list_all',0)
574 574 posix = kw.get('posix', os.name == 'posix')
575 575 strict = kw.get('strict', True)
576 576
577 577 # Check if we have more than one argument to warrant extra processing:
578 578 odict = {} # Dictionary with options
579 579 args = arg_str.split()
580 580 if len(args) >= 1:
581 581 # If the list of inputs only has 0 or 1 thing in it, there's no
582 582 # need to look for options
583 583 argv = arg_split(arg_str, posix, strict)
584 584 # Do regular option processing
585 585 try:
586 586 opts,args = getopt(argv, opt_str, long_opts)
587 except GetoptError,e:
587 except GetoptError as e:
588 588 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
589 589 " ".join(long_opts)))
590 590 for o,a in opts:
591 591 if o.startswith('--'):
592 592 o = o[2:]
593 593 else:
594 594 o = o[1:]
595 595 try:
596 596 odict[o].append(a)
597 597 except AttributeError:
598 598 odict[o] = [odict[o],a]
599 599 except KeyError:
600 600 if list_all:
601 601 odict[o] = [a]
602 602 else:
603 603 odict[o] = a
604 604
605 605 # Prepare opts,args for return
606 606 opts = Struct(odict)
607 607 if mode == 'string':
608 608 args = ' '.join(args)
609 609
610 610 return opts,args
611 611
612 612 def default_option(self, fn, optstr):
613 613 """Make an entry in the options_table for fn, with value optstr"""
614 614
615 615 if fn not in self.lsmagic():
616 616 error("%s is not a magic function" % fn)
617 617 self.options_table[fn] = optstr
@@ -1,521 +1,521 b''
1 1 """Implementation of code management magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 # Stdlib
16 16 import inspect
17 17 import io
18 18 import json
19 19 import os
20 20 import sys
21 21 from urllib2 import urlopen
22 22
23 23 # Our own packages
24 24 from IPython.core.error import TryNext, StdinNotImplementedError
25 25 from IPython.core.macro import Macro
26 26 from IPython.core.magic import Magics, magics_class, line_magic
27 27 from IPython.core.oinspect import find_file, find_source_lines
28 28 from IPython.testing.skipdoctest import skip_doctest
29 29 from IPython.utils import openpy
30 30 from IPython.utils import py3compat
31 31 from IPython.utils.io import file_read
32 32 from IPython.utils.path import get_py_filename, unquote_filename
33 33 from IPython.utils.warn import warn
34 34
35 35 #-----------------------------------------------------------------------------
36 36 # Magic implementation classes
37 37 #-----------------------------------------------------------------------------
38 38
39 39 # Used for exception handling in magic_edit
40 40 class MacroToEdit(ValueError): pass
41 41
42 42
43 43 @magics_class
44 44 class CodeMagics(Magics):
45 45 """Magics related to code management (loading, saving, editing, ...)."""
46 46
47 47 @line_magic
48 48 def save(self, parameter_s=''):
49 49 """Save a set of lines or a macro to a given filename.
50 50
51 51 Usage:\\
52 52 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
53 53
54 54 Options:
55 55
56 56 -r: use 'raw' input. By default, the 'processed' history is used,
57 57 so that magics are loaded in their transformed version to valid
58 58 Python. If this option is given, the raw input as typed as the
59 59 command line is used instead.
60 60
61 61 -f: force overwrite. If file exists, %save will prompt for overwrite
62 62 unless -f is given.
63 63
64 64 This function uses the same syntax as %history for input ranges,
65 65 then saves the lines to the filename you specify.
66 66
67 67 It adds a '.py' extension to the file if you don't do so yourself, and
68 68 it asks for confirmation before overwriting existing files.
69 69
70 70 If `-r` option is used, the default extension is `.ipy`.
71 71 """
72 72
73 73 opts,args = self.parse_options(parameter_s,'fr',mode='list')
74 74 raw = 'r' in opts
75 75 force = 'f' in opts
76 76 ext = u'.ipy' if raw else u'.py'
77 77 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
78 78 if not fname.endswith((u'.py',u'.ipy')):
79 79 fname += ext
80 80 if os.path.isfile(fname) and not force:
81 81 try:
82 82 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
83 83 except StdinNotImplementedError:
84 84 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
85 85 return
86 86 if not overwrite :
87 87 print 'Operation cancelled.'
88 88 return
89 89 try:
90 90 cmds = self.shell.find_user_code(codefrom,raw)
91 91 except (TypeError, ValueError) as e:
92 92 print e.args[0]
93 93 return
94 94 with io.open(fname,'w', encoding="utf-8") as f:
95 95 f.write(u"# coding: utf-8\n")
96 96 f.write(py3compat.cast_unicode(cmds))
97 97 print 'The following commands were written to file `%s`:' % fname
98 98 print cmds
99 99
100 100 @line_magic
101 101 def pastebin(self, parameter_s=''):
102 102 """Upload code to Github's Gist paste bin, returning the URL.
103 103
104 104 Usage:\\
105 105 %pastebin [-d "Custom description"] 1-7
106 106
107 107 The argument can be an input history range, a filename, or the name of a
108 108 string or macro.
109 109
110 110 Options:
111 111
112 112 -d: Pass a custom description for the gist. The default will say
113 113 "Pasted from IPython".
114 114 """
115 115 opts, args = self.parse_options(parameter_s, 'd:')
116 116
117 117 try:
118 118 code = self.shell.find_user_code(args)
119 119 except (ValueError, TypeError) as e:
120 120 print e.args[0]
121 121 return
122 122
123 123 post_data = json.dumps({
124 124 "description": opts.get('d', "Pasted from IPython"),
125 125 "public": True,
126 126 "files": {
127 127 "file1.py": {
128 128 "content": code
129 129 }
130 130 }
131 131 }).encode('utf-8')
132 132
133 133 response = urlopen("https://api.github.com/gists", post_data)
134 134 response_data = json.loads(response.read().decode('utf-8'))
135 135 return response_data['html_url']
136 136
137 137 @line_magic
138 138 def loadpy(self, arg_s):
139 139 """Alias of `%load`
140 140
141 141 `%loadpy` has gained some flexibility and droped the requirement of a `.py`
142 142 extension. So it has been renamed simply into %load. You can look at
143 143 `%load`'s docstring for more info.
144 144 """
145 145 self.load(arg_s)
146 146
147 147 @line_magic
148 148 def load(self, arg_s):
149 149 """Load code into the current frontend.
150 150
151 151 Usage:\\
152 152 %load [options] source
153 153
154 154 where source can be a filename, URL, input history range or macro
155 155
156 156 Options:
157 157 --------
158 158 -y : Don't ask confirmation for loading source above 200 000 characters.
159 159
160 160 This magic command can either take a local filename, a URL, an history
161 161 range (see %history) or a macro as argument, it will prompt for
162 162 confirmation before loading source with more than 200 000 characters, unless
163 163 -y flag is passed or if the frontend does not support raw_input::
164 164
165 165 %load myscript.py
166 166 %load 7-27
167 167 %load myMacro
168 168 %load http://www.example.com/myscript.py
169 169 """
170 170 opts,args = self.parse_options(arg_s,'y')
171 171
172 172 contents = self.shell.find_user_code(args)
173 173 l = len(contents)
174 174
175 175 # 200 000 is ~ 2500 full 80 caracter lines
176 176 # so in average, more than 5000 lines
177 177 if l > 200000 and 'y' not in opts:
178 178 try:
179 179 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
180 180 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
181 181 except StdinNotImplementedError:
182 182 #asume yes if raw input not implemented
183 183 ans = True
184 184
185 185 if ans is False :
186 186 print 'Operation cancelled.'
187 187 return
188 188
189 189 self.shell.set_next_input(contents)
190 190
191 191 @staticmethod
192 192 def _find_edit_target(shell, args, opts, last_call):
193 193 """Utility method used by magic_edit to find what to edit."""
194 194
195 195 def make_filename(arg):
196 196 "Make a filename from the given args"
197 197 arg = unquote_filename(arg)
198 198 try:
199 199 filename = get_py_filename(arg)
200 200 except IOError:
201 201 # If it ends with .py but doesn't already exist, assume we want
202 202 # a new file.
203 203 if arg.endswith('.py'):
204 204 filename = arg
205 205 else:
206 206 filename = None
207 207 return filename
208 208
209 209 # Set a few locals from the options for convenience:
210 210 opts_prev = 'p' in opts
211 211 opts_raw = 'r' in opts
212 212
213 213 # custom exceptions
214 214 class DataIsObject(Exception): pass
215 215
216 216 # Default line number value
217 217 lineno = opts.get('n',None)
218 218
219 219 if opts_prev:
220 220 args = '_%s' % last_call[0]
221 221 if not shell.user_ns.has_key(args):
222 222 args = last_call[1]
223 223
224 224 # use last_call to remember the state of the previous call, but don't
225 225 # let it be clobbered by successive '-p' calls.
226 226 try:
227 227 last_call[0] = shell.displayhook.prompt_count
228 228 if not opts_prev:
229 229 last_call[1] = args
230 230 except:
231 231 pass
232 232
233 233 # by default this is done with temp files, except when the given
234 234 # arg is a filename
235 235 use_temp = True
236 236
237 237 data = ''
238 238
239 239 # First, see if the arguments should be a filename.
240 240 filename = make_filename(args)
241 241 if filename:
242 242 use_temp = False
243 243 elif args:
244 244 # Mode where user specifies ranges of lines, like in %macro.
245 245 data = shell.extract_input_lines(args, opts_raw)
246 246 if not data:
247 247 try:
248 248 # Load the parameter given as a variable. If not a string,
249 249 # process it as an object instead (below)
250 250
251 251 #print '*** args',args,'type',type(args) # dbg
252 252 data = eval(args, shell.user_ns)
253 253 if not isinstance(data, basestring):
254 254 raise DataIsObject
255 255
256 256 except (NameError,SyntaxError):
257 257 # given argument is not a variable, try as a filename
258 258 filename = make_filename(args)
259 259 if filename is None:
260 260 warn("Argument given (%s) can't be found as a variable "
261 261 "or as a filename." % args)
262 262 return
263 263 use_temp = False
264 264
265 265 except DataIsObject:
266 266 # macros have a special edit function
267 267 if isinstance(data, Macro):
268 268 raise MacroToEdit(data)
269 269
270 270 # For objects, try to edit the file where they are defined
271 271 filename = find_file(data)
272 272 if filename:
273 273 if 'fakemodule' in filename.lower() and \
274 274 inspect.isclass(data):
275 275 # class created by %edit? Try to find source
276 276 # by looking for method definitions instead, the
277 277 # __module__ in those classes is FakeModule.
278 278 attrs = [getattr(data, aname) for aname in dir(data)]
279 279 for attr in attrs:
280 280 if not inspect.ismethod(attr):
281 281 continue
282 282 filename = find_file(attr)
283 283 if filename and \
284 284 'fakemodule' not in filename.lower():
285 285 # change the attribute to be the edit
286 286 # target instead
287 287 data = attr
288 288 break
289 289
290 290 datafile = 1
291 291 if filename is None:
292 292 filename = make_filename(args)
293 293 datafile = 1
294 294 warn('Could not find file where `%s` is defined.\n'
295 295 'Opening a file named `%s`' % (args, filename))
296 296 # Now, make sure we can actually read the source (if it was
297 297 # in a temp file it's gone by now).
298 298 if datafile:
299 299 if lineno is None:
300 300 lineno = find_source_lines(data)
301 301 if lineno is None:
302 302 filename = make_filename(args)
303 303 if filename is None:
304 304 warn('The file `%s` where `%s` was defined '
305 305 'cannot be read.' % (filename, data))
306 306 return
307 307 use_temp = False
308 308
309 309 if use_temp:
310 310 filename = shell.mktempfile(data)
311 311 print 'IPython will make a temporary file named:',filename
312 312
313 313 return filename, lineno, use_temp
314 314
315 315 def _edit_macro(self,mname,macro):
316 316 """open an editor with the macro data in a file"""
317 317 filename = self.shell.mktempfile(macro.value)
318 318 self.shell.hooks.editor(filename)
319 319
320 320 # and make a new macro object, to replace the old one
321 321 mfile = open(filename)
322 322 mvalue = mfile.read()
323 323 mfile.close()
324 324 self.shell.user_ns[mname] = Macro(mvalue)
325 325
326 326 @line_magic
327 327 def ed(self, parameter_s=''):
328 328 """Alias to %edit."""
329 329 return self.edit(parameter_s)
330 330
331 331 @skip_doctest
332 332 @line_magic
333 333 def edit(self, parameter_s='',last_call=['','']):
334 334 """Bring up an editor and execute the resulting code.
335 335
336 336 Usage:
337 337 %edit [options] [args]
338 338
339 339 %edit runs IPython's editor hook. The default version of this hook is
340 340 set to call the editor specified by your $EDITOR environment variable.
341 341 If this isn't found, it will default to vi under Linux/Unix and to
342 342 notepad under Windows. See the end of this docstring for how to change
343 343 the editor hook.
344 344
345 345 You can also set the value of this editor via the
346 346 ``TerminalInteractiveShell.editor`` option in your configuration file.
347 347 This is useful if you wish to use a different editor from your typical
348 348 default with IPython (and for Windows users who typically don't set
349 349 environment variables).
350 350
351 351 This command allows you to conveniently edit multi-line code right in
352 352 your IPython session.
353 353
354 354 If called without arguments, %edit opens up an empty editor with a
355 355 temporary file and will execute the contents of this file when you
356 356 close it (don't forget to save it!).
357 357
358 358
359 359 Options:
360 360
361 361 -n <number>: open the editor at a specified line number. By default,
362 362 the IPython editor hook uses the unix syntax 'editor +N filename', but
363 363 you can configure this by providing your own modified hook if your
364 364 favorite editor supports line-number specifications with a different
365 365 syntax.
366 366
367 367 -p: this will call the editor with the same data as the previous time
368 368 it was used, regardless of how long ago (in your current session) it
369 369 was.
370 370
371 371 -r: use 'raw' input. This option only applies to input taken from the
372 372 user's history. By default, the 'processed' history is used, so that
373 373 magics are loaded in their transformed version to valid Python. If
374 374 this option is given, the raw input as typed as the command line is
375 375 used instead. When you exit the editor, it will be executed by
376 376 IPython's own processor.
377 377
378 378 -x: do not execute the edited code immediately upon exit. This is
379 379 mainly useful if you are editing programs which need to be called with
380 380 command line arguments, which you can then do using %run.
381 381
382 382
383 383 Arguments:
384 384
385 385 If arguments are given, the following possibilities exist:
386 386
387 387 - If the argument is a filename, IPython will load that into the
388 388 editor. It will execute its contents with execfile() when you exit,
389 389 loading any code in the file into your interactive namespace.
390 390
391 391 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
392 392 The syntax is the same as in the %history magic.
393 393
394 394 - If the argument is a string variable, its contents are loaded
395 395 into the editor. You can thus edit any string which contains
396 396 python code (including the result of previous edits).
397 397
398 398 - If the argument is the name of an object (other than a string),
399 399 IPython will try to locate the file where it was defined and open the
400 400 editor at the point where it is defined. You can use `%edit function`
401 401 to load an editor exactly at the point where 'function' is defined,
402 402 edit it and have the file be executed automatically.
403 403
404 404 - If the object is a macro (see %macro for details), this opens up your
405 405 specified editor with a temporary file containing the macro's data.
406 406 Upon exit, the macro is reloaded with the contents of the file.
407 407
408 408 Note: opening at an exact line is only supported under Unix, and some
409 409 editors (like kedit and gedit up to Gnome 2.8) do not understand the
410 410 '+NUMBER' parameter necessary for this feature. Good editors like
411 411 (X)Emacs, vi, jed, pico and joe all do.
412 412
413 413 After executing your code, %edit will return as output the code you
414 414 typed in the editor (except when it was an existing file). This way
415 415 you can reload the code in further invocations of %edit as a variable,
416 416 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
417 417 the output.
418 418
419 419 Note that %edit is also available through the alias %ed.
420 420
421 421 This is an example of creating a simple function inside the editor and
422 422 then modifying it. First, start up the editor::
423 423
424 424 In [1]: ed
425 425 Editing... done. Executing edited code...
426 426 Out[1]: 'def foo():\\n print "foo() was defined in an editing
427 427 session"\\n'
428 428
429 429 We can then call the function foo()::
430 430
431 431 In [2]: foo()
432 432 foo() was defined in an editing session
433 433
434 434 Now we edit foo. IPython automatically loads the editor with the
435 435 (temporary) file where foo() was previously defined::
436 436
437 437 In [3]: ed foo
438 438 Editing... done. Executing edited code...
439 439
440 440 And if we call foo() again we get the modified version::
441 441
442 442 In [4]: foo()
443 443 foo() has now been changed!
444 444
445 445 Here is an example of how to edit a code snippet successive
446 446 times. First we call the editor::
447 447
448 448 In [5]: ed
449 449 Editing... done. Executing edited code...
450 450 hello
451 451 Out[5]: "print 'hello'\\n"
452 452
453 453 Now we call it again with the previous output (stored in _)::
454 454
455 455 In [6]: ed _
456 456 Editing... done. Executing edited code...
457 457 hello world
458 458 Out[6]: "print 'hello world'\\n"
459 459
460 460 Now we call it with the output #8 (stored in _8, also as Out[8])::
461 461
462 462 In [7]: ed _8
463 463 Editing... done. Executing edited code...
464 464 hello again
465 465 Out[7]: "print 'hello again'\\n"
466 466
467 467
468 468 Changing the default editor hook:
469 469
470 470 If you wish to write your own editor hook, you can put it in a
471 471 configuration file which you load at startup time. The default hook
472 472 is defined in the IPython.core.hooks module, and you can use that as a
473 473 starting example for further modifications. That file also has
474 474 general instructions on how to set a new hook for use once you've
475 475 defined it."""
476 476 opts,args = self.parse_options(parameter_s,'prxn:')
477 477
478 478 try:
479 479 filename, lineno, is_temp = self._find_edit_target(self.shell,
480 480 args, opts, last_call)
481 481 except MacroToEdit as e:
482 482 self._edit_macro(args, e.args[0])
483 483 return
484 484
485 485 # do actual editing here
486 486 print 'Editing...',
487 487 sys.stdout.flush()
488 488 try:
489 489 # Quote filenames that may have spaces in them
490 490 if ' ' in filename:
491 491 filename = "'%s'" % filename
492 492 self.shell.hooks.editor(filename,lineno)
493 493 except TryNext:
494 494 warn('Could not open editor')
495 495 return
496 496
497 497 # XXX TODO: should this be generalized for all string vars?
498 498 # For now, this is special-cased to blocks created by cpaste
499 499 if args.strip() == 'pasted_block':
500 500 self.shell.user_ns['pasted_block'] = file_read(filename)
501 501
502 502 if 'x' in opts: # -x prevents actual execution
503 503 print
504 504 else:
505 505 print 'done. Executing edited code...'
506 506 if 'r' in opts: # Untranslated IPython code
507 507 self.shell.run_cell(file_read(filename),
508 508 store_history=False)
509 509 else:
510 510 self.shell.safe_execfile(filename, self.shell.user_ns,
511 511 self.shell.user_ns)
512 512
513 513 if is_temp:
514 514 try:
515 515 return open(filename).read()
516 except IOError,msg:
516 except IOError as msg:
517 517 if msg.filename == filename:
518 518 warn('File not found. Did you forget to save?')
519 519 return
520 520 else:
521 521 self.shell.showtraceback()
@@ -1,700 +1,700 b''
1 1 """Implementation of namespace-related magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 # Stdlib
16 16 import gc
17 17 import re
18 18 import sys
19 19
20 20 # Our own packages
21 21 from IPython.core import page
22 22 from IPython.core.error import StdinNotImplementedError
23 23 from IPython.core.magic import Magics, magics_class, line_magic
24 24 from IPython.testing.skipdoctest import skip_doctest
25 25 from IPython.utils.encoding import DEFAULT_ENCODING
26 26 from IPython.utils.path import get_py_filename
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Magic implementation classes
30 30 #-----------------------------------------------------------------------------
31 31
32 32 @magics_class
33 33 class NamespaceMagics(Magics):
34 34 """Magics to manage various aspects of the user's namespace.
35 35
36 36 These include listing variables, introspecting into them, etc.
37 37 """
38 38
39 39 @line_magic
40 40 def pinfo(self, parameter_s='', namespaces=None):
41 41 """Provide detailed information about an object.
42 42
43 43 '%pinfo object' is just a synonym for object? or ?object."""
44 44
45 45 #print 'pinfo par: <%s>' % parameter_s # dbg
46 46 # detail_level: 0 -> obj? , 1 -> obj??
47 47 detail_level = 0
48 48 # We need to detect if we got called as 'pinfo pinfo foo', which can
49 49 # happen if the user types 'pinfo foo?' at the cmd line.
50 50 pinfo,qmark1,oname,qmark2 = \
51 51 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
52 52 if pinfo or qmark1 or qmark2:
53 53 detail_level = 1
54 54 if "*" in oname:
55 55 self.psearch(oname)
56 56 else:
57 57 self.shell._inspect('pinfo', oname, detail_level=detail_level,
58 58 namespaces=namespaces)
59 59
60 60 @line_magic
61 61 def pinfo2(self, parameter_s='', namespaces=None):
62 62 """Provide extra detailed information about an object.
63 63
64 64 '%pinfo2 object' is just a synonym for object?? or ??object."""
65 65 self.shell._inspect('pinfo', parameter_s, detail_level=1,
66 66 namespaces=namespaces)
67 67
68 68 @skip_doctest
69 69 @line_magic
70 70 def pdef(self, parameter_s='', namespaces=None):
71 71 """Print the definition header for any callable object.
72 72
73 73 If the object is a class, print the constructor information.
74 74
75 75 Examples
76 76 --------
77 77 ::
78 78
79 79 In [3]: %pdef urllib.urlopen
80 80 urllib.urlopen(url, data=None, proxies=None)
81 81 """
82 82 self.shell._inspect('pdef',parameter_s, namespaces)
83 83
84 84 @line_magic
85 85 def pdoc(self, parameter_s='', namespaces=None):
86 86 """Print the docstring for an object.
87 87
88 88 If the given object is a class, it will print both the class and the
89 89 constructor docstrings."""
90 90 self.shell._inspect('pdoc',parameter_s, namespaces)
91 91
92 92 @line_magic
93 93 def psource(self, parameter_s='', namespaces=None):
94 94 """Print (or run through pager) the source code for an object."""
95 95 self.shell._inspect('psource',parameter_s, namespaces)
96 96
97 97 @line_magic
98 98 def pfile(self, parameter_s=''):
99 99 """Print (or run through pager) the file where an object is defined.
100 100
101 101 The file opens at the line where the object definition begins. IPython
102 102 will honor the environment variable PAGER if set, and otherwise will
103 103 do its best to print the file in a convenient form.
104 104
105 105 If the given argument is not an object currently defined, IPython will
106 106 try to interpret it as a filename (automatically adding a .py extension
107 107 if needed). You can thus use %pfile as a syntax highlighting code
108 108 viewer."""
109 109
110 110 # first interpret argument as an object name
111 111 out = self.shell._inspect('pfile',parameter_s)
112 112 # if not, try the input as a filename
113 113 if out == 'not found':
114 114 try:
115 115 filename = get_py_filename(parameter_s)
116 except IOError,msg:
116 except IOError as msg:
117 117 print msg
118 118 return
119 119 page.page(self.shell.inspector.format(open(filename).read()))
120 120
121 121 @line_magic
122 122 def psearch(self, parameter_s=''):
123 123 """Search for object in namespaces by wildcard.
124 124
125 125 %psearch [options] PATTERN [OBJECT TYPE]
126 126
127 127 Note: ? can be used as a synonym for %psearch, at the beginning or at
128 128 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
129 129 rest of the command line must be unchanged (options come first), so
130 130 for example the following forms are equivalent
131 131
132 132 %psearch -i a* function
133 133 -i a* function?
134 134 ?-i a* function
135 135
136 136 Arguments:
137 137
138 138 PATTERN
139 139
140 140 where PATTERN is a string containing * as a wildcard similar to its
141 141 use in a shell. The pattern is matched in all namespaces on the
142 142 search path. By default objects starting with a single _ are not
143 143 matched, many IPython generated objects have a single
144 144 underscore. The default is case insensitive matching. Matching is
145 145 also done on the attributes of objects and not only on the objects
146 146 in a module.
147 147
148 148 [OBJECT TYPE]
149 149
150 150 Is the name of a python type from the types module. The name is
151 151 given in lowercase without the ending type, ex. StringType is
152 152 written string. By adding a type here only objects matching the
153 153 given type are matched. Using all here makes the pattern match all
154 154 types (this is the default).
155 155
156 156 Options:
157 157
158 158 -a: makes the pattern match even objects whose names start with a
159 159 single underscore. These names are normally omitted from the
160 160 search.
161 161
162 162 -i/-c: make the pattern case insensitive/sensitive. If neither of
163 163 these options are given, the default is read from your configuration
164 164 file, with the option ``InteractiveShell.wildcards_case_sensitive``.
165 165 If this option is not specified in your configuration file, IPython's
166 166 internal default is to do a case sensitive search.
167 167
168 168 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
169 169 specify can be searched in any of the following namespaces:
170 170 'builtin', 'user', 'user_global','internal', 'alias', where
171 171 'builtin' and 'user' are the search defaults. Note that you should
172 172 not use quotes when specifying namespaces.
173 173
174 174 'Builtin' contains the python module builtin, 'user' contains all
175 175 user data, 'alias' only contain the shell aliases and no python
176 176 objects, 'internal' contains objects used by IPython. The
177 177 'user_global' namespace is only used by embedded IPython instances,
178 178 and it contains module-level globals. You can add namespaces to the
179 179 search with -s or exclude them with -e (these options can be given
180 180 more than once).
181 181
182 182 Examples
183 183 --------
184 184 ::
185 185
186 186 %psearch a* -> objects beginning with an a
187 187 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
188 188 %psearch a* function -> all functions beginning with an a
189 189 %psearch re.e* -> objects beginning with an e in module re
190 190 %psearch r*.e* -> objects that start with e in modules starting in r
191 191 %psearch r*.* string -> all strings in modules beginning with r
192 192
193 193 Case sensitive search::
194 194
195 195 %psearch -c a* list all object beginning with lower case a
196 196
197 197 Show objects beginning with a single _::
198 198
199 199 %psearch -a _* list objects beginning with a single underscore
200 200 """
201 201 try:
202 202 parameter_s.encode('ascii')
203 203 except UnicodeEncodeError:
204 204 print 'Python identifiers can only contain ascii characters.'
205 205 return
206 206
207 207 # default namespaces to be searched
208 208 def_search = ['user_local', 'user_global', 'builtin']
209 209
210 210 # Process options/args
211 211 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
212 212 opt = opts.get
213 213 shell = self.shell
214 214 psearch = shell.inspector.psearch
215 215
216 216 # select case options
217 217 if opts.has_key('i'):
218 218 ignore_case = True
219 219 elif opts.has_key('c'):
220 220 ignore_case = False
221 221 else:
222 222 ignore_case = not shell.wildcards_case_sensitive
223 223
224 224 # Build list of namespaces to search from user options
225 225 def_search.extend(opt('s',[]))
226 226 ns_exclude = ns_exclude=opt('e',[])
227 227 ns_search = [nm for nm in def_search if nm not in ns_exclude]
228 228
229 229 # Call the actual search
230 230 try:
231 231 psearch(args,shell.ns_table,ns_search,
232 232 show_all=opt('a'),ignore_case=ignore_case)
233 233 except:
234 234 shell.showtraceback()
235 235
236 236 @skip_doctest
237 237 @line_magic
238 238 def who_ls(self, parameter_s=''):
239 239 """Return a sorted list of all interactive variables.
240 240
241 241 If arguments are given, only variables of types matching these
242 242 arguments are returned.
243 243
244 244 Examples
245 245 --------
246 246
247 247 Define two variables and list them with who_ls::
248 248
249 249 In [1]: alpha = 123
250 250
251 251 In [2]: beta = 'test'
252 252
253 253 In [3]: %who_ls
254 254 Out[3]: ['alpha', 'beta']
255 255
256 256 In [4]: %who_ls int
257 257 Out[4]: ['alpha']
258 258
259 259 In [5]: %who_ls str
260 260 Out[5]: ['beta']
261 261 """
262 262
263 263 user_ns = self.shell.user_ns
264 264 user_ns_hidden = self.shell.user_ns_hidden
265 265 out = [ i for i in user_ns
266 266 if not i.startswith('_') \
267 267 and not i in user_ns_hidden ]
268 268
269 269 typelist = parameter_s.split()
270 270 if typelist:
271 271 typeset = set(typelist)
272 272 out = [i for i in out if type(user_ns[i]).__name__ in typeset]
273 273
274 274 out.sort()
275 275 return out
276 276
277 277 @skip_doctest
278 278 @line_magic
279 279 def who(self, parameter_s=''):
280 280 """Print all interactive variables, with some minimal formatting.
281 281
282 282 If any arguments are given, only variables whose type matches one of
283 283 these are printed. For example::
284 284
285 285 %who function str
286 286
287 287 will only list functions and strings, excluding all other types of
288 288 variables. To find the proper type names, simply use type(var) at a
289 289 command line to see how python prints type names. For example:
290 290
291 291 ::
292 292
293 293 In [1]: type('hello')\\
294 294 Out[1]: <type 'str'>
295 295
296 296 indicates that the type name for strings is 'str'.
297 297
298 298 ``%who`` always excludes executed names loaded through your configuration
299 299 file and things which are internal to IPython.
300 300
301 301 This is deliberate, as typically you may load many modules and the
302 302 purpose of %who is to show you only what you've manually defined.
303 303
304 304 Examples
305 305 --------
306 306
307 307 Define two variables and list them with who::
308 308
309 309 In [1]: alpha = 123
310 310
311 311 In [2]: beta = 'test'
312 312
313 313 In [3]: %who
314 314 alpha beta
315 315
316 316 In [4]: %who int
317 317 alpha
318 318
319 319 In [5]: %who str
320 320 beta
321 321 """
322 322
323 323 varlist = self.who_ls(parameter_s)
324 324 if not varlist:
325 325 if parameter_s:
326 326 print 'No variables match your requested type.'
327 327 else:
328 328 print 'Interactive namespace is empty.'
329 329 return
330 330
331 331 # if we have variables, move on...
332 332 count = 0
333 333 for i in varlist:
334 334 print i+'\t',
335 335 count += 1
336 336 if count > 8:
337 337 count = 0
338 338 print
339 339 print
340 340
341 341 @skip_doctest
342 342 @line_magic
343 343 def whos(self, parameter_s=''):
344 344 """Like %who, but gives some extra information about each variable.
345 345
346 346 The same type filtering of %who can be applied here.
347 347
348 348 For all variables, the type is printed. Additionally it prints:
349 349
350 350 - For {},[],(): their length.
351 351
352 352 - For numpy arrays, a summary with shape, number of
353 353 elements, typecode and size in memory.
354 354
355 355 - Everything else: a string representation, snipping their middle if
356 356 too long.
357 357
358 358 Examples
359 359 --------
360 360
361 361 Define two variables and list them with whos::
362 362
363 363 In [1]: alpha = 123
364 364
365 365 In [2]: beta = 'test'
366 366
367 367 In [3]: %whos
368 368 Variable Type Data/Info
369 369 --------------------------------
370 370 alpha int 123
371 371 beta str test
372 372 """
373 373
374 374 varnames = self.who_ls(parameter_s)
375 375 if not varnames:
376 376 if parameter_s:
377 377 print 'No variables match your requested type.'
378 378 else:
379 379 print 'Interactive namespace is empty.'
380 380 return
381 381
382 382 # if we have variables, move on...
383 383
384 384 # for these types, show len() instead of data:
385 385 seq_types = ['dict', 'list', 'tuple']
386 386
387 387 # for numpy arrays, display summary info
388 388 ndarray_type = None
389 389 if 'numpy' in sys.modules:
390 390 try:
391 391 from numpy import ndarray
392 392 except ImportError:
393 393 pass
394 394 else:
395 395 ndarray_type = ndarray.__name__
396 396
397 397 # Find all variable names and types so we can figure out column sizes
398 398 def get_vars(i):
399 399 return self.shell.user_ns[i]
400 400
401 401 # some types are well known and can be shorter
402 402 abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
403 403 def type_name(v):
404 404 tn = type(v).__name__
405 405 return abbrevs.get(tn,tn)
406 406
407 407 varlist = map(get_vars,varnames)
408 408
409 409 typelist = []
410 410 for vv in varlist:
411 411 tt = type_name(vv)
412 412
413 413 if tt=='instance':
414 414 typelist.append( abbrevs.get(str(vv.__class__),
415 415 str(vv.__class__)))
416 416 else:
417 417 typelist.append(tt)
418 418
419 419 # column labels and # of spaces as separator
420 420 varlabel = 'Variable'
421 421 typelabel = 'Type'
422 422 datalabel = 'Data/Info'
423 423 colsep = 3
424 424 # variable format strings
425 425 vformat = "{0:<{varwidth}}{1:<{typewidth}}"
426 426 aformat = "%s: %s elems, type `%s`, %s bytes"
427 427 # find the size of the columns to format the output nicely
428 428 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
429 429 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
430 430 # table header
431 431 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
432 432 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
433 433 # and the table itself
434 434 kb = 1024
435 435 Mb = 1048576 # kb**2
436 436 for vname,var,vtype in zip(varnames,varlist,typelist):
437 437 print vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth),
438 438 if vtype in seq_types:
439 439 print "n="+str(len(var))
440 440 elif vtype == ndarray_type:
441 441 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
442 442 if vtype==ndarray_type:
443 443 # numpy
444 444 vsize = var.size
445 445 vbytes = vsize*var.itemsize
446 446 vdtype = var.dtype
447 447
448 448 if vbytes < 100000:
449 449 print aformat % (vshape, vsize, vdtype, vbytes)
450 450 else:
451 451 print aformat % (vshape, vsize, vdtype, vbytes),
452 452 if vbytes < Mb:
453 453 print '(%s kb)' % (vbytes/kb,)
454 454 else:
455 455 print '(%s Mb)' % (vbytes/Mb,)
456 456 else:
457 457 try:
458 458 vstr = str(var)
459 459 except UnicodeEncodeError:
460 460 vstr = unicode(var).encode(DEFAULT_ENCODING,
461 461 'backslashreplace')
462 462 except:
463 463 vstr = "<object with id %d (str() failed)>" % id(var)
464 464 vstr = vstr.replace('\n', '\\n')
465 465 if len(vstr) < 50:
466 466 print vstr
467 467 else:
468 468 print vstr[:25] + "<...>" + vstr[-25:]
469 469
470 470 @line_magic
471 471 def reset(self, parameter_s=''):
472 472 """Resets the namespace by removing all names defined by the user, if
473 473 called without arguments, or by removing some types of objects, such
474 474 as everything currently in IPython's In[] and Out[] containers (see
475 475 the parameters for details).
476 476
477 477 Parameters
478 478 ----------
479 479 -f : force reset without asking for confirmation.
480 480
481 481 -s : 'Soft' reset: Only clears your namespace, leaving history intact.
482 482 References to objects may be kept. By default (without this option),
483 483 we do a 'hard' reset, giving you a new session and removing all
484 484 references to objects from the current session.
485 485
486 486 in : reset input history
487 487
488 488 out : reset output history
489 489
490 490 dhist : reset directory history
491 491
492 492 array : reset only variables that are NumPy arrays
493 493
494 494 See Also
495 495 --------
496 496 magic_reset_selective : invoked as ``%reset_selective``
497 497
498 498 Examples
499 499 --------
500 500 ::
501 501
502 502 In [6]: a = 1
503 503
504 504 In [7]: a
505 505 Out[7]: 1
506 506
507 507 In [8]: 'a' in _ip.user_ns
508 508 Out[8]: True
509 509
510 510 In [9]: %reset -f
511 511
512 512 In [1]: 'a' in _ip.user_ns
513 513 Out[1]: False
514 514
515 515 In [2]: %reset -f in
516 516 Flushing input history
517 517
518 518 In [3]: %reset -f dhist in
519 519 Flushing directory history
520 520 Flushing input history
521 521
522 522 Notes
523 523 -----
524 524 Calling this magic from clients that do not implement standard input,
525 525 such as the ipython notebook interface, will reset the namespace
526 526 without confirmation.
527 527 """
528 528 opts, args = self.parse_options(parameter_s,'sf', mode='list')
529 529 if 'f' in opts:
530 530 ans = True
531 531 else:
532 532 try:
533 533 ans = self.shell.ask_yes_no(
534 534 "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
535 535 default='n')
536 536 except StdinNotImplementedError:
537 537 ans = True
538 538 if not ans:
539 539 print 'Nothing done.'
540 540 return
541 541
542 542 if 's' in opts: # Soft reset
543 543 user_ns = self.shell.user_ns
544 544 for i in self.who_ls():
545 545 del(user_ns[i])
546 546 elif len(args) == 0: # Hard reset
547 547 self.shell.reset(new_session = False)
548 548
549 549 # reset in/out/dhist/array: previously extensinions/clearcmd.py
550 550 ip = self.shell
551 551 user_ns = self.shell.user_ns # local lookup, heavily used
552 552
553 553 for target in args:
554 554 target = target.lower() # make matches case insensitive
555 555 if target == 'out':
556 556 print "Flushing output cache (%d entries)" % len(user_ns['_oh'])
557 557 self.shell.displayhook.flush()
558 558
559 559 elif target == 'in':
560 560 print "Flushing input history"
561 561 pc = self.shell.displayhook.prompt_count + 1
562 562 for n in range(1, pc):
563 563 key = '_i'+repr(n)
564 564 user_ns.pop(key,None)
565 565 user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
566 566 hm = ip.history_manager
567 567 # don't delete these, as %save and %macro depending on the
568 568 # length of these lists to be preserved
569 569 hm.input_hist_parsed[:] = [''] * pc
570 570 hm.input_hist_raw[:] = [''] * pc
571 571 # hm has internal machinery for _i,_ii,_iii, clear it out
572 572 hm._i = hm._ii = hm._iii = hm._i00 = u''
573 573
574 574 elif target == 'array':
575 575 # Support cleaning up numpy arrays
576 576 try:
577 577 from numpy import ndarray
578 578 # This must be done with items and not iteritems because
579 579 # we're going to modify the dict in-place.
580 580 for x,val in user_ns.items():
581 581 if isinstance(val,ndarray):
582 582 del user_ns[x]
583 583 except ImportError:
584 584 print "reset array only works if Numpy is available."
585 585
586 586 elif target == 'dhist':
587 587 print "Flushing directory history"
588 588 del user_ns['_dh'][:]
589 589
590 590 else:
591 591 print "Don't know how to reset ",
592 592 print target + ", please run `%reset?` for details"
593 593
594 594 gc.collect()
595 595
596 596 @line_magic
597 597 def reset_selective(self, parameter_s=''):
598 598 """Resets the namespace by removing names defined by the user.
599 599
600 600 Input/Output history are left around in case you need them.
601 601
602 602 %reset_selective [-f] regex
603 603
604 604 No action is taken if regex is not included
605 605
606 606 Options
607 607 -f : force reset without asking for confirmation.
608 608
609 609 See Also
610 610 --------
611 611 magic_reset : invoked as ``%reset``
612 612
613 613 Examples
614 614 --------
615 615
616 616 We first fully reset the namespace so your output looks identical to
617 617 this example for pedagogical reasons; in practice you do not need a
618 618 full reset::
619 619
620 620 In [1]: %reset -f
621 621
622 622 Now, with a clean namespace we can make a few variables and use
623 623 ``%reset_selective`` to only delete names that match our regexp::
624 624
625 625 In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
626 626
627 627 In [3]: who_ls
628 628 Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
629 629
630 630 In [4]: %reset_selective -f b[2-3]m
631 631
632 632 In [5]: who_ls
633 633 Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
634 634
635 635 In [6]: %reset_selective -f d
636 636
637 637 In [7]: who_ls
638 638 Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
639 639
640 640 In [8]: %reset_selective -f c
641 641
642 642 In [9]: who_ls
643 643 Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
644 644
645 645 In [10]: %reset_selective -f b
646 646
647 647 In [11]: who_ls
648 648 Out[11]: ['a']
649 649
650 650 Notes
651 651 -----
652 652 Calling this magic from clients that do not implement standard input,
653 653 such as the ipython notebook interface, will reset the namespace
654 654 without confirmation.
655 655 """
656 656
657 657 opts, regex = self.parse_options(parameter_s,'f')
658 658
659 659 if opts.has_key('f'):
660 660 ans = True
661 661 else:
662 662 try:
663 663 ans = self.shell.ask_yes_no(
664 664 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
665 665 default='n')
666 666 except StdinNotImplementedError:
667 667 ans = True
668 668 if not ans:
669 669 print 'Nothing done.'
670 670 return
671 671 user_ns = self.shell.user_ns
672 672 if not regex:
673 673 print 'No regex pattern specified. Nothing done.'
674 674 return
675 675 else:
676 676 try:
677 677 m = re.compile(regex)
678 678 except TypeError:
679 679 raise TypeError('regex must be a string or compiled pattern')
680 680 for i in self.who_ls():
681 681 if m.search(i):
682 682 del(user_ns[i])
683 683
684 684 @line_magic
685 685 def xdel(self, parameter_s=''):
686 686 """Delete a variable, trying to clear it from anywhere that
687 687 IPython's machinery has references to it. By default, this uses
688 688 the identity of the named object in the user namespace to remove
689 689 references held under other names. The object is also removed
690 690 from the output history.
691 691
692 692 Options
693 693 -n : Delete the specified name from all namespaces, without
694 694 checking their identity.
695 695 """
696 696 opts, varname = self.parse_options(parameter_s,'n')
697 697 try:
698 698 self.shell.del_var(varname, ('n' in opts))
699 699 except (NameError, ValueError) as e:
700 700 print type(e).__name__ +": "+ str(e)
@@ -1,340 +1,340 b''
1 1 # encoding: utf-8
2 2 """
3 3 Paging capabilities for IPython.core
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Fernando Perez
9 9
10 10 Notes
11 11 -----
12 12
13 13 For now this uses ipapi, so it can't be in IPython.utils. If we can get
14 14 rid of that dependency, we could move it there.
15 15 -----
16 16 """
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Copyright (C) 2008-2011 The IPython Development Team
20 20 #
21 21 # Distributed under the terms of the BSD License. The full license is in
22 22 # the file COPYING, distributed as part of this software.
23 23 #-----------------------------------------------------------------------------
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Imports
27 27 #-----------------------------------------------------------------------------
28 28
29 29 import os
30 30 import re
31 31 import sys
32 32 import tempfile
33 33
34 34 from io import UnsupportedOperation
35 35
36 36 from IPython.core import ipapi
37 37 from IPython.core.error import TryNext
38 38 from IPython.utils.cursesimport import use_curses
39 39 from IPython.utils.data import chop
40 40 from IPython.utils import io
41 41 from IPython.utils.process import system
42 42 from IPython.utils.terminal import get_terminal_size
43 43
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Classes and functions
47 47 #-----------------------------------------------------------------------------
48 48
49 49 esc_re = re.compile(r"(\x1b[^m]+m)")
50 50
51 51 def page_dumb(strng, start=0, screen_lines=25):
52 52 """Very dumb 'pager' in Python, for when nothing else works.
53 53
54 54 Only moves forward, same interface as page(), except for pager_cmd and
55 55 mode."""
56 56
57 57 out_ln = strng.splitlines()[start:]
58 58 screens = chop(out_ln,screen_lines-1)
59 59 if len(screens) == 1:
60 60 print >>io.stdout, os.linesep.join(screens[0])
61 61 else:
62 62 last_escape = ""
63 63 for scr in screens[0:-1]:
64 64 hunk = os.linesep.join(scr)
65 65 print >>io.stdout, last_escape + hunk
66 66 if not page_more():
67 67 return
68 68 esc_list = esc_re.findall(hunk)
69 69 if len(esc_list) > 0:
70 70 last_escape = esc_list[-1]
71 71 print >>io.stdout, last_escape + os.linesep.join(screens[-1])
72 72
73 73 def _detect_screen_size(use_curses, screen_lines_def):
74 74 """Attempt to work out the number of lines on the screen.
75 75
76 76 This is called by page(). It can raise an error (e.g. when run in the
77 77 test suite), so it's separated out so it can easily be called in a try block.
78 78 """
79 79 TERM = os.environ.get('TERM',None)
80 80 if (TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5':
81 81 local_use_curses = use_curses
82 82 else:
83 83 # curses causes problems on many terminals other than xterm, and
84 84 # some termios calls lock up on Sun OS5.
85 85 local_use_curses = False
86 86 if local_use_curses:
87 87 import termios
88 88 import curses
89 89 # There is a bug in curses, where *sometimes* it fails to properly
90 90 # initialize, and then after the endwin() call is made, the
91 91 # terminal is left in an unusable state. Rather than trying to
92 92 # check everytime for this (by requesting and comparing termios
93 93 # flags each time), we just save the initial terminal state and
94 94 # unconditionally reset it every time. It's cheaper than making
95 95 # the checks.
96 96 term_flags = termios.tcgetattr(sys.stdout)
97 97
98 98 # Curses modifies the stdout buffer size by default, which messes
99 99 # up Python's normal stdout buffering. This would manifest itself
100 100 # to IPython users as delayed printing on stdout after having used
101 101 # the pager.
102 102 #
103 103 # We can prevent this by manually setting the NCURSES_NO_SETBUF
104 104 # environment variable. For more details, see:
105 105 # http://bugs.python.org/issue10144
106 106 NCURSES_NO_SETBUF = os.environ.get('NCURSES_NO_SETBUF', None)
107 107 os.environ['NCURSES_NO_SETBUF'] = ''
108 108
109 109 # Proceed with curses initialization
110 110 scr = curses.initscr()
111 111 screen_lines_real,screen_cols = scr.getmaxyx()
112 112 curses.endwin()
113 113
114 114 # Restore environment
115 115 if NCURSES_NO_SETBUF is None:
116 116 del os.environ['NCURSES_NO_SETBUF']
117 117 else:
118 118 os.environ['NCURSES_NO_SETBUF'] = NCURSES_NO_SETBUF
119 119
120 120 # Restore terminal state in case endwin() didn't.
121 121 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
122 122 # Now we have what we needed: the screen size in rows/columns
123 123 return screen_lines_real
124 124 #print '***Screen size:',screen_lines_real,'lines x',\
125 125 #screen_cols,'columns.' # dbg
126 126 else:
127 127 return screen_lines_def
128 128
129 129 def page(strng, start=0, screen_lines=0, pager_cmd=None):
130 130 """Print a string, piping through a pager after a certain length.
131 131
132 132 The screen_lines parameter specifies the number of *usable* lines of your
133 133 terminal screen (total lines minus lines you need to reserve to show other
134 134 information).
135 135
136 136 If you set screen_lines to a number <=0, page() will try to auto-determine
137 137 your screen size and will only use up to (screen_size+screen_lines) for
138 138 printing, paging after that. That is, if you want auto-detection but need
139 139 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
140 140 auto-detection without any lines reserved simply use screen_lines = 0.
141 141
142 142 If a string won't fit in the allowed lines, it is sent through the
143 143 specified pager command. If none given, look for PAGER in the environment,
144 144 and ultimately default to less.
145 145
146 146 If no system pager works, the string is sent through a 'dumb pager'
147 147 written in python, very simplistic.
148 148 """
149 149
150 150 # Some routines may auto-compute start offsets incorrectly and pass a
151 151 # negative value. Offset to 0 for robustness.
152 152 start = max(0, start)
153 153
154 154 # first, try the hook
155 155 ip = ipapi.get()
156 156 if ip:
157 157 try:
158 158 ip.hooks.show_in_pager(strng)
159 159 return
160 160 except TryNext:
161 161 pass
162 162
163 163 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
164 164 TERM = os.environ.get('TERM','dumb')
165 165 if TERM in ['dumb','emacs'] and os.name != 'nt':
166 166 print strng
167 167 return
168 168 # chop off the topmost part of the string we don't want to see
169 169 str_lines = strng.splitlines()[start:]
170 170 str_toprint = os.linesep.join(str_lines)
171 171 num_newlines = len(str_lines)
172 172 len_str = len(str_toprint)
173 173
174 174 # Dumb heuristics to guesstimate number of on-screen lines the string
175 175 # takes. Very basic, but good enough for docstrings in reasonable
176 176 # terminals. If someone later feels like refining it, it's not hard.
177 177 numlines = max(num_newlines,int(len_str/80)+1)
178 178
179 179 screen_lines_def = get_terminal_size()[1]
180 180
181 181 # auto-determine screen size
182 182 if screen_lines <= 0:
183 183 try:
184 184 screen_lines += _detect_screen_size(use_curses, screen_lines_def)
185 185 except (TypeError, UnsupportedOperation):
186 186 print >>io.stdout, str_toprint
187 187 return
188 188
189 189 #print 'numlines',numlines,'screenlines',screen_lines # dbg
190 190 if numlines <= screen_lines :
191 191 #print '*** normal print' # dbg
192 192 print >>io.stdout, str_toprint
193 193 else:
194 194 # Try to open pager and default to internal one if that fails.
195 195 # All failure modes are tagged as 'retval=1', to match the return
196 196 # value of a failed system command. If any intermediate attempt
197 197 # sets retval to 1, at the end we resort to our own page_dumb() pager.
198 198 pager_cmd = get_pager_cmd(pager_cmd)
199 199 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
200 200 if os.name == 'nt':
201 201 if pager_cmd.startswith('type'):
202 202 # The default WinXP 'type' command is failing on complex strings.
203 203 retval = 1
204 204 else:
205 205 tmpname = tempfile.mktemp('.txt')
206 206 tmpfile = open(tmpname,'wt')
207 207 tmpfile.write(strng)
208 208 tmpfile.close()
209 209 cmd = "%s < %s" % (pager_cmd,tmpname)
210 210 if os.system(cmd):
211 211 retval = 1
212 212 else:
213 213 retval = None
214 214 os.remove(tmpname)
215 215 else:
216 216 try:
217 217 retval = None
218 218 # if I use popen4, things hang. No idea why.
219 219 #pager,shell_out = os.popen4(pager_cmd)
220 220 pager = os.popen(pager_cmd,'w')
221 221 pager.write(strng)
222 222 pager.close()
223 223 retval = pager.close() # success returns None
224 except IOError,msg: # broken pipe when user quits
224 except IOError as msg: # broken pipe when user quits
225 225 if msg.args == (32,'Broken pipe'):
226 226 retval = None
227 227 else:
228 228 retval = 1
229 229 except OSError:
230 230 # Other strange problems, sometimes seen in Win2k/cygwin
231 231 retval = 1
232 232 if retval is not None:
233 233 page_dumb(strng,screen_lines=screen_lines)
234 234
235 235
236 236 def page_file(fname, start=0, pager_cmd=None):
237 237 """Page a file, using an optional pager command and starting line.
238 238 """
239 239
240 240 pager_cmd = get_pager_cmd(pager_cmd)
241 241 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
242 242
243 243 try:
244 244 if os.environ['TERM'] in ['emacs','dumb']:
245 245 raise EnvironmentError
246 246 system(pager_cmd + ' ' + fname)
247 247 except:
248 248 try:
249 249 if start > 0:
250 250 start -= 1
251 251 page(open(fname).read(),start)
252 252 except:
253 253 print 'Unable to show file',`fname`
254 254
255 255
256 256 def get_pager_cmd(pager_cmd=None):
257 257 """Return a pager command.
258 258
259 259 Makes some attempts at finding an OS-correct one.
260 260 """
261 261 if os.name == 'posix':
262 262 default_pager_cmd = 'less -r' # -r for color control sequences
263 263 elif os.name in ['nt','dos']:
264 264 default_pager_cmd = 'type'
265 265
266 266 if pager_cmd is None:
267 267 try:
268 268 pager_cmd = os.environ['PAGER']
269 269 except:
270 270 pager_cmd = default_pager_cmd
271 271 return pager_cmd
272 272
273 273
274 274 def get_pager_start(pager, start):
275 275 """Return the string for paging files with an offset.
276 276
277 277 This is the '+N' argument which less and more (under Unix) accept.
278 278 """
279 279
280 280 if pager in ['less','more']:
281 281 if start:
282 282 start_string = '+' + str(start)
283 283 else:
284 284 start_string = ''
285 285 else:
286 286 start_string = ''
287 287 return start_string
288 288
289 289
290 290 # (X)emacs on win32 doesn't like to be bypassed with msvcrt.getch()
291 291 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
292 292 import msvcrt
293 293 def page_more():
294 294 """ Smart pausing between pages
295 295
296 296 @return: True if need print more lines, False if quit
297 297 """
298 298 io.stdout.write('---Return to continue, q to quit--- ')
299 299 ans = msvcrt.getch()
300 300 if ans in ("q", "Q"):
301 301 result = False
302 302 else:
303 303 result = True
304 304 io.stdout.write("\b"*37 + " "*37 + "\b"*37)
305 305 return result
306 306 else:
307 307 def page_more():
308 308 ans = raw_input('---Return to continue, q to quit--- ')
309 309 if ans.lower().startswith('q'):
310 310 return False
311 311 else:
312 312 return True
313 313
314 314
315 315 def snip_print(str,width = 75,print_full = 0,header = ''):
316 316 """Print a string snipping the midsection to fit in width.
317 317
318 318 print_full: mode control:
319 319 - 0: only snip long strings
320 320 - 1: send to page() directly.
321 321 - 2: snip long strings and ask for full length viewing with page()
322 322 Return 1 if snipping was necessary, 0 otherwise."""
323 323
324 324 if print_full == 1:
325 325 page(header+str)
326 326 return 0
327 327
328 328 print header,
329 329 if len(str) < width:
330 330 print str
331 331 snip = 0
332 332 else:
333 333 whalf = int((width -5)/2)
334 334 print str[:whalf] + ' <...> ' + str[-whalf:]
335 335 snip = 1
336 336 if snip and print_full == 2:
337 337 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
338 338 page(str)
339 339 return snip
340 340
@@ -1,250 +1,250 b''
1 1 # encoding: utf-8
2 2 """Tests for code execution (%run and related), which is particularly tricky.
3 3
4 4 Because of how %run manages namespaces, and the fact that we are trying here to
5 5 verify subtle object deletion and reference counting issues, the %run tests
6 6 will be kept in this separate file. This makes it easier to aggregate in one
7 7 place the tricks needed to handle it; most other magics are much easier to test
8 8 and we do so in a common test_magic file.
9 9 """
10 10 from __future__ import absolute_import
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 import os
17 17 import sys
18 18 import tempfile
19 19
20 20 import nose.tools as nt
21 21 from nose import SkipTest
22 22
23 23 from IPython.testing import decorators as dec
24 24 from IPython.testing import tools as tt
25 25 from IPython.utils import py3compat
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Test functions begin
29 29 #-----------------------------------------------------------------------------
30 30
31 31 def doctest_refbug():
32 32 """Very nasty problem with references held by multiple runs of a script.
33 33 See: https://github.com/ipython/ipython/issues/141
34 34
35 35 In [1]: _ip.clear_main_mod_cache()
36 36 # random
37 37
38 38 In [2]: %run refbug
39 39
40 40 In [3]: call_f()
41 41 lowercased: hello
42 42
43 43 In [4]: %run refbug
44 44
45 45 In [5]: call_f()
46 46 lowercased: hello
47 47 lowercased: hello
48 48 """
49 49
50 50
51 51 def doctest_run_builtins():
52 52 r"""Check that %run doesn't damage __builtins__.
53 53
54 54 In [1]: import tempfile
55 55
56 56 In [2]: bid1 = id(__builtins__)
57 57
58 58 In [3]: fname = tempfile.mkstemp('.py')[1]
59 59
60 60 In [3]: f = open(fname,'w')
61 61
62 62 In [4]: dummy= f.write('pass\n')
63 63
64 64 In [5]: f.flush()
65 65
66 66 In [6]: t1 = type(__builtins__)
67 67
68 68 In [7]: %run $fname
69 69
70 70 In [7]: f.close()
71 71
72 72 In [8]: bid2 = id(__builtins__)
73 73
74 74 In [9]: t2 = type(__builtins__)
75 75
76 76 In [10]: t1 == t2
77 77 Out[10]: True
78 78
79 79 In [10]: bid1 == bid2
80 80 Out[10]: True
81 81
82 82 In [12]: try:
83 83 ....: os.unlink(fname)
84 84 ....: except:
85 85 ....: pass
86 86 ....:
87 87 """
88 88
89 89 @py3compat.doctest_refactor_print
90 90 def doctest_reset_del():
91 91 """Test that resetting doesn't cause errors in __del__ methods.
92 92
93 93 In [2]: class A(object):
94 94 ...: def __del__(self):
95 95 ...: print str("Hi")
96 96 ...:
97 97
98 98 In [3]: a = A()
99 99
100 100 In [4]: get_ipython().reset()
101 101 Hi
102 102
103 103 In [5]: 1+1
104 104 Out[5]: 2
105 105 """
106 106
107 107 # For some tests, it will be handy to organize them in a class with a common
108 108 # setup that makes a temp file
109 109
110 110 class TestMagicRunPass(tt.TempFileMixin):
111 111
112 112 def setup(self):
113 113 """Make a valid python temp file."""
114 114 self.mktmp('pass\n')
115 115
116 116 def run_tmpfile(self):
117 117 _ip = get_ipython()
118 118 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
119 119 # See below and ticket https://bugs.launchpad.net/bugs/366353
120 120 _ip.magic('run %s' % self.fname)
121 121
122 122 def run_tmpfile_p(self):
123 123 _ip = get_ipython()
124 124 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
125 125 # See below and ticket https://bugs.launchpad.net/bugs/366353
126 126 _ip.magic('run -p %s' % self.fname)
127 127
128 128 def test_builtins_id(self):
129 129 """Check that %run doesn't damage __builtins__ """
130 130 _ip = get_ipython()
131 131 # Test that the id of __builtins__ is not modified by %run
132 132 bid1 = id(_ip.user_ns['__builtins__'])
133 133 self.run_tmpfile()
134 134 bid2 = id(_ip.user_ns['__builtins__'])
135 135 tt.assert_equals(bid1, bid2)
136 136
137 137 def test_builtins_type(self):
138 138 """Check that the type of __builtins__ doesn't change with %run.
139 139
140 140 However, the above could pass if __builtins__ was already modified to
141 141 be a dict (it should be a module) by a previous use of %run. So we
142 142 also check explicitly that it really is a module:
143 143 """
144 144 _ip = get_ipython()
145 145 self.run_tmpfile()
146 146 tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys))
147 147
148 148 def test_prompts(self):
149 149 """Test that prompts correctly generate after %run"""
150 150 self.run_tmpfile()
151 151 _ip = get_ipython()
152 152 p2 = _ip.prompt_manager.render('in2').strip()
153 153 nt.assert_equals(p2[:3], '...')
154 154
155 155 def test_run_profile( self ):
156 156 """Test that the option -p, which invokes the profiler, do not
157 157 crash by invoking execfile"""
158 158 _ip = get_ipython()
159 159 self.run_tmpfile_p()
160 160
161 161
162 162 class TestMagicRunSimple(tt.TempFileMixin):
163 163
164 164 def test_simpledef(self):
165 165 """Test that simple class definitions work."""
166 166 src = ("class foo: pass\n"
167 167 "def f(): return foo()")
168 168 self.mktmp(src)
169 169 _ip.magic('run %s' % self.fname)
170 170 _ip.run_cell('t = isinstance(f(), foo)')
171 171 nt.assert_true(_ip.user_ns['t'])
172 172
173 173 def test_obj_del(self):
174 174 """Test that object's __del__ methods are called on exit."""
175 175 if sys.platform == 'win32':
176 176 try:
177 177 import win32api
178 178 except ImportError:
179 179 raise SkipTest("Test requires pywin32")
180 180 src = ("class A(object):\n"
181 181 " def __del__(self):\n"
182 182 " print 'object A deleted'\n"
183 183 "a = A()\n")
184 184 self.mktmp(py3compat.doctest_refactor_print(src))
185 185 if dec.module_not_available('sqlite3'):
186 186 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
187 187 else:
188 188 err = None
189 189 tt.ipexec_validate(self.fname, 'object A deleted', err)
190 190
191 191 @dec.skip_known_failure
192 192 def test_aggressive_namespace_cleanup(self):
193 193 """Test that namespace cleanup is not too aggressive GH-238
194 194
195 195 Returning from another run magic deletes the namespace"""
196 196 # see ticket https://github.com/ipython/ipython/issues/238
197 197 class secondtmp(tt.TempFileMixin): pass
198 198 empty = secondtmp()
199 199 empty.mktmp('')
200 200 src = ("ip = get_ipython()\n"
201 201 "for i in range(5):\n"
202 202 " try:\n"
203 203 " ip.magic('run %s')\n"
204 " except NameError, e:\n"
204 " except NameError as e:\n"
205 205 " print i;break\n" % empty.fname)
206 206 self.mktmp(py3compat.doctest_refactor_print(src))
207 207 _ip.magic('run %s' % self.fname)
208 208 _ip.run_cell('ip == get_ipython()')
209 209 tt.assert_equals(_ip.user_ns['i'], 5)
210 210
211 211 @dec.skip_win32
212 212 def test_tclass(self):
213 213 mydir = os.path.dirname(__file__)
214 214 tc = os.path.join(mydir, 'tclass')
215 215 src = ("%%run '%s' C-first\n"
216 216 "%%run '%s' C-second\n"
217 217 "%%run '%s' C-third\n") % (tc, tc, tc)
218 218 self.mktmp(src, '.ipy')
219 219 out = """\
220 220 ARGV 1-: ['C-first']
221 221 ARGV 1-: ['C-second']
222 222 tclass.py: deleting object: C-first
223 223 ARGV 1-: ['C-third']
224 224 tclass.py: deleting object: C-second
225 225 tclass.py: deleting object: C-third
226 226 """
227 227 if dec.module_not_available('sqlite3'):
228 228 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
229 229 else:
230 230 err = None
231 231 tt.ipexec_validate(self.fname, out, err)
232 232
233 233 def test_run_i_after_reset(self):
234 234 """Check that %run -i still works after %reset (gh-693)"""
235 235 src = "yy = zz\n"
236 236 self.mktmp(src)
237 237 _ip.run_cell("zz = 23")
238 238 _ip.magic('run -i %s' % self.fname)
239 239 tt.assert_equals(_ip.user_ns['yy'], 23)
240 240 _ip.magic('reset -f')
241 241 _ip.run_cell("zz = 23")
242 242 _ip.magic('run -i %s' % self.fname)
243 243 tt.assert_equals(_ip.user_ns['yy'], 23)
244 244
245 245 def test_unicode(self):
246 246 """Check that files in odd encodings are accepted."""
247 247 mydir = os.path.dirname(__file__)
248 248 na = os.path.join(mydir, 'nonascii.py')
249 249 _ip.magic('run "%s"' % na)
250 250 tt.assert_equals(_ip.user_ns['u'], u'Ўт№Ф')
@@ -1,1244 +1,1244 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ultratb.py -- Spice up your tracebacks!
4 4
5 5 * ColorTB
6 6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 7 ColorTB class is a solution to that problem. It colors the different parts of a
8 8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 9 text editor.
10 10
11 11 Installation instructions for ColorTB:
12 12 import sys,ultratb
13 13 sys.excepthook = ultratb.ColorTB()
14 14
15 15 * VerboseTB
16 16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
17 17 of useful info when a traceback occurs. Ping originally had it spit out HTML
18 18 and intended it for CGI programmers, but why should they have all the fun? I
19 19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
20 20 but kind of neat, and maybe useful for long-running programs that you believe
21 21 are bug-free. If a crash *does* occur in that type of program you want details.
22 22 Give it a shot--you'll love it or you'll hate it.
23 23
24 24 Note:
25 25
26 26 The Verbose mode prints the variables currently visible where the exception
27 27 happened (shortening their strings if too long). This can potentially be
28 28 very slow, if you happen to have a huge data structure whose string
29 29 representation is complex to compute. Your computer may appear to freeze for
30 30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
31 31 with Ctrl-C (maybe hitting it more than once).
32 32
33 33 If you encounter this kind of situation often, you may want to use the
34 34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
35 35 variables (but otherwise includes the information and context given by
36 36 Verbose).
37 37
38 38
39 39 Installation instructions for ColorTB:
40 40 import sys,ultratb
41 41 sys.excepthook = ultratb.VerboseTB()
42 42
43 43 Note: Much of the code in this module was lifted verbatim from the standard
44 44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
45 45
46 46 * Color schemes
47 47 The colors are defined in the class TBTools through the use of the
48 48 ColorSchemeTable class. Currently the following exist:
49 49
50 50 - NoColor: allows all of this module to be used in any terminal (the color
51 51 escapes are just dummy blank strings).
52 52
53 53 - Linux: is meant to look good in a terminal like the Linux console (black
54 54 or very dark background).
55 55
56 56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
57 57 in light background terminals.
58 58
59 59 You can implement other color schemes easily, the syntax is fairly
60 60 self-explanatory. Please send back new schemes you develop to the author for
61 61 possible inclusion in future releases.
62 62 """
63 63
64 64 #*****************************************************************************
65 65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
67 67 #
68 68 # Distributed under the terms of the BSD License. The full license is in
69 69 # the file COPYING, distributed as part of this software.
70 70 #*****************************************************************************
71 71
72 72 from __future__ import with_statement
73 73
74 74 import inspect
75 75 import keyword
76 76 import linecache
77 77 import os
78 78 import pydoc
79 79 import re
80 80 import sys
81 81 import time
82 82 import tokenize
83 83 import traceback
84 84 import types
85 85
86 86 try: # Python 2
87 87 generate_tokens = tokenize.generate_tokens
88 88 except AttributeError: # Python 3
89 89 generate_tokens = tokenize.tokenize
90 90
91 91 # For purposes of monkeypatching inspect to fix a bug in it.
92 92 from inspect import getsourcefile, getfile, getmodule,\
93 93 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
94 94
95 95 # IPython's own modules
96 96 # Modified pdb which doesn't damage IPython's readline handling
97 97 from IPython.core import debugger, ipapi
98 98 from IPython.core.display_trap import DisplayTrap
99 99 from IPython.core.excolors import exception_colors
100 100 from IPython.utils import PyColorize
101 101 from IPython.utils import io
102 102 from IPython.utils import py3compat
103 103 from IPython.utils import pyfile
104 104 from IPython.utils.data import uniq_stable
105 105 from IPython.utils.warn import info, error
106 106
107 107 # Globals
108 108 # amount of space to put line numbers before verbose tracebacks
109 109 INDENT_SIZE = 8
110 110
111 111 # Default color scheme. This is used, for example, by the traceback
112 112 # formatter. When running in an actual IPython instance, the user's rc.colors
113 113 # value is used, but havinga module global makes this functionality available
114 114 # to users of ultratb who are NOT running inside ipython.
115 115 DEFAULT_SCHEME = 'NoColor'
116 116
117 117 #---------------------------------------------------------------------------
118 118 # Code begins
119 119
120 120 # Utility functions
121 121 def inspect_error():
122 122 """Print a message about internal inspect errors.
123 123
124 124 These are unfortunately quite common."""
125 125
126 126 error('Internal Python error in the inspect module.\n'
127 127 'Below is the traceback from this internal error.\n')
128 128
129 129
130 130 # N.B. This function is a monkeypatch we are currently not applying.
131 131 # It was written some time ago, to fix an apparent Python bug with
132 132 # codeobj.co_firstlineno . Unfortunately, we don't know under what conditions
133 133 # the bug occurred, so we can't tell if it has been fixed. If it reappears, we
134 134 # will apply the monkeypatch again. Also, note that findsource() is not called
135 135 # by our code at this time - we don't know if it was when the monkeypatch was
136 136 # written, or if the monkeypatch is needed for some other code (like a debugger).
137 137 # For the discussion about not applying it, see gh-1229. TK, Jan 2011.
138 138 def findsource(object):
139 139 """Return the entire source file and starting line number for an object.
140 140
141 141 The argument may be a module, class, method, function, traceback, frame,
142 142 or code object. The source code is returned as a list of all the lines
143 143 in the file and the line number indexes a line in that list. An IOError
144 144 is raised if the source code cannot be retrieved.
145 145
146 146 FIXED version with which we monkeypatch the stdlib to work around a bug."""
147 147
148 148 file = getsourcefile(object) or getfile(object)
149 149 # If the object is a frame, then trying to get the globals dict from its
150 150 # module won't work. Instead, the frame object itself has the globals
151 151 # dictionary.
152 152 globals_dict = None
153 153 if inspect.isframe(object):
154 154 # XXX: can this ever be false?
155 155 globals_dict = object.f_globals
156 156 else:
157 157 module = getmodule(object, file)
158 158 if module:
159 159 globals_dict = module.__dict__
160 160 lines = linecache.getlines(file, globals_dict)
161 161 if not lines:
162 162 raise IOError('could not get source code')
163 163
164 164 if ismodule(object):
165 165 return lines, 0
166 166
167 167 if isclass(object):
168 168 name = object.__name__
169 169 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
170 170 # make some effort to find the best matching class definition:
171 171 # use the one with the least indentation, which is the one
172 172 # that's most probably not inside a function definition.
173 173 candidates = []
174 174 for i in range(len(lines)):
175 175 match = pat.match(lines[i])
176 176 if match:
177 177 # if it's at toplevel, it's already the best one
178 178 if lines[i][0] == 'c':
179 179 return lines, i
180 180 # else add whitespace to candidate list
181 181 candidates.append((match.group(1), i))
182 182 if candidates:
183 183 # this will sort by whitespace, and by line number,
184 184 # less whitespace first
185 185 candidates.sort()
186 186 return lines, candidates[0][1]
187 187 else:
188 188 raise IOError('could not find class definition')
189 189
190 190 if ismethod(object):
191 191 object = object.im_func
192 192 if isfunction(object):
193 193 object = object.func_code
194 194 if istraceback(object):
195 195 object = object.tb_frame
196 196 if isframe(object):
197 197 object = object.f_code
198 198 if iscode(object):
199 199 if not hasattr(object, 'co_firstlineno'):
200 200 raise IOError('could not find function definition')
201 201 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
202 202 pmatch = pat.match
203 203 # fperez - fix: sometimes, co_firstlineno can give a number larger than
204 204 # the length of lines, which causes an error. Safeguard against that.
205 205 lnum = min(object.co_firstlineno,len(lines))-1
206 206 while lnum > 0:
207 207 if pmatch(lines[lnum]): break
208 208 lnum -= 1
209 209
210 210 return lines, lnum
211 211 raise IOError('could not find code object')
212 212
213 213 # Not applying the monkeypatch - see above the function for details. TK, Jan 2012
214 214 # Monkeypatch inspect to apply our bugfix. This code only works with py25
215 215 #if sys.version_info[:2] >= (2,5):
216 216 # inspect.findsource = findsource
217 217
218 218 def fix_frame_records_filenames(records):
219 219 """Try to fix the filenames in each record from inspect.getinnerframes().
220 220
221 221 Particularly, modules loaded from within zip files have useless filenames
222 222 attached to their code object, and inspect.getinnerframes() just uses it.
223 223 """
224 224 fixed_records = []
225 225 for frame, filename, line_no, func_name, lines, index in records:
226 226 # Look inside the frame's globals dictionary for __file__, which should
227 227 # be better.
228 228 better_fn = frame.f_globals.get('__file__', None)
229 229 if isinstance(better_fn, str):
230 230 # Check the type just in case someone did something weird with
231 231 # __file__. It might also be None if the error occurred during
232 232 # import.
233 233 filename = better_fn
234 234 fixed_records.append((frame, filename, line_no, func_name, lines, index))
235 235 return fixed_records
236 236
237 237
238 238 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
239 239 import linecache
240 240 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
241 241
242 242 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
243 243
244 244 # If the error is at the console, don't build any context, since it would
245 245 # otherwise produce 5 blank lines printed out (there is no file at the
246 246 # console)
247 247 rec_check = records[tb_offset:]
248 248 try:
249 249 rname = rec_check[0][1]
250 250 if rname == '<ipython console>' or rname.endswith('<string>'):
251 251 return rec_check
252 252 except IndexError:
253 253 pass
254 254
255 255 aux = traceback.extract_tb(etb)
256 256 assert len(records) == len(aux)
257 257 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
258 258 maybeStart = lnum-1 - context//2
259 259 start = max(maybeStart, 0)
260 260 end = start + context
261 261 lines = linecache.getlines(file)[start:end]
262 262 buf = list(records[i])
263 263 buf[LNUM_POS] = lnum
264 264 buf[INDEX_POS] = lnum - 1 - start
265 265 buf[LINES_POS] = lines
266 266 records[i] = tuple(buf)
267 267 return records[tb_offset:]
268 268
269 269 # Helper function -- largely belongs to VerboseTB, but we need the same
270 270 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
271 271 # can be recognized properly by ipython.el's py-traceback-line-re
272 272 # (SyntaxErrors have to be treated specially because they have no traceback)
273 273
274 274 _parser = PyColorize.Parser()
275 275
276 276 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
277 277 numbers_width = INDENT_SIZE - 1
278 278 res = []
279 279 i = lnum - index
280 280
281 281 # This lets us get fully syntax-highlighted tracebacks.
282 282 if scheme is None:
283 283 ipinst = ipapi.get()
284 284 if ipinst is not None:
285 285 scheme = ipinst.colors
286 286 else:
287 287 scheme = DEFAULT_SCHEME
288 288
289 289 _line_format = _parser.format2
290 290
291 291 for line in lines:
292 292 # FIXME: we need to ensure the source is a pure string at this point,
293 293 # else the coloring code makes a royal mess. This is in need of a
294 294 # serious refactoring, so that all of the ultratb and PyColorize code
295 295 # is unicode-safe. So for now this is rather an ugly hack, but
296 296 # necessary to at least have readable tracebacks. Improvements welcome!
297 297 line = py3compat.cast_bytes_py2(line, 'utf-8')
298 298
299 299 new_line, err = _line_format(line, 'str', scheme)
300 300 if not err: line = new_line
301 301
302 302 if i == lnum:
303 303 # This is the line with the error
304 304 pad = numbers_width - len(str(i))
305 305 if pad >= 3:
306 306 marker = '-'*(pad-3) + '-> '
307 307 elif pad == 2:
308 308 marker = '> '
309 309 elif pad == 1:
310 310 marker = '>'
311 311 else:
312 312 marker = ''
313 313 num = marker + str(i)
314 314 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
315 315 Colors.line, line, Colors.Normal)
316 316 else:
317 317 num = '%*s' % (numbers_width,i)
318 318 line = '%s%s%s %s' %(Colors.lineno, num,
319 319 Colors.Normal, line)
320 320
321 321 res.append(line)
322 322 if lvals and i == lnum:
323 323 res.append(lvals + '\n')
324 324 i = i + 1
325 325 return res
326 326
327 327
328 328 #---------------------------------------------------------------------------
329 329 # Module classes
330 330 class TBTools(object):
331 331 """Basic tools used by all traceback printer classes."""
332 332
333 333 # Number of frames to skip when reporting tracebacks
334 334 tb_offset = 0
335 335
336 336 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
337 337 # Whether to call the interactive pdb debugger after printing
338 338 # tracebacks or not
339 339 self.call_pdb = call_pdb
340 340
341 341 # Output stream to write to. Note that we store the original value in
342 342 # a private attribute and then make the public ostream a property, so
343 343 # that we can delay accessing io.stdout until runtime. The way
344 344 # things are written now, the io.stdout object is dynamically managed
345 345 # so a reference to it should NEVER be stored statically. This
346 346 # property approach confines this detail to a single location, and all
347 347 # subclasses can simply access self.ostream for writing.
348 348 self._ostream = ostream
349 349
350 350 # Create color table
351 351 self.color_scheme_table = exception_colors()
352 352
353 353 self.set_colors(color_scheme)
354 354 self.old_scheme = color_scheme # save initial value for toggles
355 355
356 356 if call_pdb:
357 357 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
358 358 else:
359 359 self.pdb = None
360 360
361 361 def _get_ostream(self):
362 362 """Output stream that exceptions are written to.
363 363
364 364 Valid values are:
365 365
366 366 - None: the default, which means that IPython will dynamically resolve
367 367 to io.stdout. This ensures compatibility with most tools, including
368 368 Windows (where plain stdout doesn't recognize ANSI escapes).
369 369
370 370 - Any object with 'write' and 'flush' attributes.
371 371 """
372 372 return io.stdout if self._ostream is None else self._ostream
373 373
374 374 def _set_ostream(self, val):
375 375 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
376 376 self._ostream = val
377 377
378 378 ostream = property(_get_ostream, _set_ostream)
379 379
380 380 def set_colors(self,*args,**kw):
381 381 """Shorthand access to the color table scheme selector method."""
382 382
383 383 # Set own color table
384 384 self.color_scheme_table.set_active_scheme(*args,**kw)
385 385 # for convenience, set Colors to the active scheme
386 386 self.Colors = self.color_scheme_table.active_colors
387 387 # Also set colors of debugger
388 388 if hasattr(self,'pdb') and self.pdb is not None:
389 389 self.pdb.set_colors(*args,**kw)
390 390
391 391 def color_toggle(self):
392 392 """Toggle between the currently active color scheme and NoColor."""
393 393
394 394 if self.color_scheme_table.active_scheme_name == 'NoColor':
395 395 self.color_scheme_table.set_active_scheme(self.old_scheme)
396 396 self.Colors = self.color_scheme_table.active_colors
397 397 else:
398 398 self.old_scheme = self.color_scheme_table.active_scheme_name
399 399 self.color_scheme_table.set_active_scheme('NoColor')
400 400 self.Colors = self.color_scheme_table.active_colors
401 401
402 402 def stb2text(self, stb):
403 403 """Convert a structured traceback (a list) to a string."""
404 404 return '\n'.join(stb)
405 405
406 406 def text(self, etype, value, tb, tb_offset=None, context=5):
407 407 """Return formatted traceback.
408 408
409 409 Subclasses may override this if they add extra arguments.
410 410 """
411 411 tb_list = self.structured_traceback(etype, value, tb,
412 412 tb_offset, context)
413 413 return self.stb2text(tb_list)
414 414
415 415 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
416 416 context=5, mode=None):
417 417 """Return a list of traceback frames.
418 418
419 419 Must be implemented by each class.
420 420 """
421 421 raise NotImplementedError()
422 422
423 423
424 424 #---------------------------------------------------------------------------
425 425 class ListTB(TBTools):
426 426 """Print traceback information from a traceback list, with optional color.
427 427
428 428 Calling: requires 3 arguments:
429 429 (etype, evalue, elist)
430 430 as would be obtained by:
431 431 etype, evalue, tb = sys.exc_info()
432 432 if tb:
433 433 elist = traceback.extract_tb(tb)
434 434 else:
435 435 elist = None
436 436
437 437 It can thus be used by programs which need to process the traceback before
438 438 printing (such as console replacements based on the code module from the
439 439 standard library).
440 440
441 441 Because they are meant to be called without a full traceback (only a
442 442 list), instances of this class can't call the interactive pdb debugger."""
443 443
444 444 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
445 445 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
446 446 ostream=ostream)
447 447
448 448 def __call__(self, etype, value, elist):
449 449 self.ostream.flush()
450 450 self.ostream.write(self.text(etype, value, elist))
451 451 self.ostream.write('\n')
452 452
453 453 def structured_traceback(self, etype, value, elist, tb_offset=None,
454 454 context=5):
455 455 """Return a color formatted string with the traceback info.
456 456
457 457 Parameters
458 458 ----------
459 459 etype : exception type
460 460 Type of the exception raised.
461 461
462 462 value : object
463 463 Data stored in the exception
464 464
465 465 elist : list
466 466 List of frames, see class docstring for details.
467 467
468 468 tb_offset : int, optional
469 469 Number of frames in the traceback to skip. If not given, the
470 470 instance value is used (set in constructor).
471 471
472 472 context : int, optional
473 473 Number of lines of context information to print.
474 474
475 475 Returns
476 476 -------
477 477 String with formatted exception.
478 478 """
479 479 tb_offset = self.tb_offset if tb_offset is None else tb_offset
480 480 Colors = self.Colors
481 481 out_list = []
482 482 if elist:
483 483
484 484 if tb_offset and len(elist) > tb_offset:
485 485 elist = elist[tb_offset:]
486 486
487 487 out_list.append('Traceback %s(most recent call last)%s:' %
488 488 (Colors.normalEm, Colors.Normal) + '\n')
489 489 out_list.extend(self._format_list(elist))
490 490 # The exception info should be a single entry in the list.
491 491 lines = ''.join(self._format_exception_only(etype, value))
492 492 out_list.append(lines)
493 493
494 494 # Note: this code originally read:
495 495
496 496 ## for line in lines[:-1]:
497 497 ## out_list.append(" "+line)
498 498 ## out_list.append(lines[-1])
499 499
500 500 # This means it was indenting everything but the last line by a little
501 501 # bit. I've disabled this for now, but if we see ugliness somewhre we
502 502 # can restore it.
503 503
504 504 return out_list
505 505
506 506 def _format_list(self, extracted_list):
507 507 """Format a list of traceback entry tuples for printing.
508 508
509 509 Given a list of tuples as returned by extract_tb() or
510 510 extract_stack(), return a list of strings ready for printing.
511 511 Each string in the resulting list corresponds to the item with the
512 512 same index in the argument list. Each string ends in a newline;
513 513 the strings may contain internal newlines as well, for those items
514 514 whose source text line is not None.
515 515
516 516 Lifted almost verbatim from traceback.py
517 517 """
518 518
519 519 Colors = self.Colors
520 520 list = []
521 521 for filename, lineno, name, line in extracted_list[:-1]:
522 522 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
523 523 (Colors.filename, filename, Colors.Normal,
524 524 Colors.lineno, lineno, Colors.Normal,
525 525 Colors.name, name, Colors.Normal)
526 526 if line:
527 527 item += ' %s\n' % line.strip()
528 528 list.append(item)
529 529 # Emphasize the last entry
530 530 filename, lineno, name, line = extracted_list[-1]
531 531 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
532 532 (Colors.normalEm,
533 533 Colors.filenameEm, filename, Colors.normalEm,
534 534 Colors.linenoEm, lineno, Colors.normalEm,
535 535 Colors.nameEm, name, Colors.normalEm,
536 536 Colors.Normal)
537 537 if line:
538 538 item += '%s %s%s\n' % (Colors.line, line.strip(),
539 539 Colors.Normal)
540 540 list.append(item)
541 541 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
542 542 return list
543 543
544 544 def _format_exception_only(self, etype, value):
545 545 """Format the exception part of a traceback.
546 546
547 547 The arguments are the exception type and value such as given by
548 548 sys.exc_info()[:2]. The return value is a list of strings, each ending
549 549 in a newline. Normally, the list contains a single string; however,
550 550 for SyntaxError exceptions, it contains several lines that (when
551 551 printed) display detailed information about where the syntax error
552 552 occurred. The message indicating which exception occurred is the
553 553 always last string in the list.
554 554
555 555 Also lifted nearly verbatim from traceback.py
556 556 """
557 557
558 558 have_filedata = False
559 559 Colors = self.Colors
560 560 list = []
561 561 stype = Colors.excName + etype.__name__ + Colors.Normal
562 562 if value is None:
563 563 # Not sure if this can still happen in Python 2.6 and above
564 564 list.append( str(stype) + '\n')
565 565 else:
566 566 if etype is SyntaxError:
567 567 have_filedata = True
568 568 #print 'filename is',filename # dbg
569 569 if not value.filename: value.filename = "<string>"
570 570 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
571 571 (Colors.normalEm,
572 572 Colors.filenameEm, value.filename, Colors.normalEm,
573 573 Colors.linenoEm, value.lineno, Colors.Normal ))
574 574 if value.text is not None:
575 575 i = 0
576 576 while i < len(value.text) and value.text[i].isspace():
577 577 i += 1
578 578 list.append('%s %s%s\n' % (Colors.line,
579 579 value.text.strip(),
580 580 Colors.Normal))
581 581 if value.offset is not None:
582 582 s = ' '
583 583 for c in value.text[i:value.offset-1]:
584 584 if c.isspace():
585 585 s += c
586 586 else:
587 587 s += ' '
588 588 list.append('%s%s^%s\n' % (Colors.caret, s,
589 589 Colors.Normal) )
590 590
591 591 try:
592 592 s = value.msg
593 593 except Exception:
594 594 s = self._some_str(value)
595 595 if s:
596 596 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
597 597 Colors.Normal, s))
598 598 else:
599 599 list.append('%s\n' % str(stype))
600 600
601 601 # sync with user hooks
602 602 if have_filedata:
603 603 ipinst = ipapi.get()
604 604 if ipinst is not None:
605 605 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
606 606
607 607 return list
608 608
609 609 def get_exception_only(self, etype, value):
610 610 """Only print the exception type and message, without a traceback.
611 611
612 612 Parameters
613 613 ----------
614 614 etype : exception type
615 615 value : exception value
616 616 """
617 617 return ListTB.structured_traceback(self, etype, value, [])
618 618
619 619
620 620 def show_exception_only(self, etype, evalue):
621 621 """Only print the exception type and message, without a traceback.
622 622
623 623 Parameters
624 624 ----------
625 625 etype : exception type
626 626 value : exception value
627 627 """
628 628 # This method needs to use __call__ from *this* class, not the one from
629 629 # a subclass whose signature or behavior may be different
630 630 ostream = self.ostream
631 631 ostream.flush()
632 632 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
633 633 ostream.flush()
634 634
635 635 def _some_str(self, value):
636 636 # Lifted from traceback.py
637 637 try:
638 638 return str(value)
639 639 except:
640 640 return '<unprintable %s object>' % type(value).__name__
641 641
642 642 #----------------------------------------------------------------------------
643 643 class VerboseTB(TBTools):
644 644 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
645 645 of HTML. Requires inspect and pydoc. Crazy, man.
646 646
647 647 Modified version which optionally strips the topmost entries from the
648 648 traceback, to be used with alternate interpreters (because their own code
649 649 would appear in the traceback)."""
650 650
651 651 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
652 652 tb_offset=0, long_header=False, include_vars=True,
653 653 check_cache=None):
654 654 """Specify traceback offset, headers and color scheme.
655 655
656 656 Define how many frames to drop from the tracebacks. Calling it with
657 657 tb_offset=1 allows use of this handler in interpreters which will have
658 658 their own code at the top of the traceback (VerboseTB will first
659 659 remove that frame before printing the traceback info)."""
660 660 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
661 661 ostream=ostream)
662 662 self.tb_offset = tb_offset
663 663 self.long_header = long_header
664 664 self.include_vars = include_vars
665 665 # By default we use linecache.checkcache, but the user can provide a
666 666 # different check_cache implementation. This is used by the IPython
667 667 # kernel to provide tracebacks for interactive code that is cached,
668 668 # by a compiler instance that flushes the linecache but preserves its
669 669 # own code cache.
670 670 if check_cache is None:
671 671 check_cache = linecache.checkcache
672 672 self.check_cache = check_cache
673 673
674 674 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
675 675 context=5):
676 676 """Return a nice text document describing the traceback."""
677 677
678 678 tb_offset = self.tb_offset if tb_offset is None else tb_offset
679 679
680 680 # some locals
681 681 try:
682 682 etype = etype.__name__
683 683 except AttributeError:
684 684 pass
685 685 Colors = self.Colors # just a shorthand + quicker name lookup
686 686 ColorsNormal = Colors.Normal # used a lot
687 687 col_scheme = self.color_scheme_table.active_scheme_name
688 688 indent = ' '*INDENT_SIZE
689 689 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
690 690 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
691 691 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
692 692
693 693 # some internal-use functions
694 694 def text_repr(value):
695 695 """Hopefully pretty robust repr equivalent."""
696 696 # this is pretty horrible but should always return *something*
697 697 try:
698 698 return pydoc.text.repr(value)
699 699 except KeyboardInterrupt:
700 700 raise
701 701 except:
702 702 try:
703 703 return repr(value)
704 704 except KeyboardInterrupt:
705 705 raise
706 706 except:
707 707 try:
708 708 # all still in an except block so we catch
709 709 # getattr raising
710 710 name = getattr(value, '__name__', None)
711 711 if name:
712 712 # ick, recursion
713 713 return text_repr(name)
714 714 klass = getattr(value, '__class__', None)
715 715 if klass:
716 716 return '%s instance' % text_repr(klass)
717 717 except KeyboardInterrupt:
718 718 raise
719 719 except:
720 720 return 'UNRECOVERABLE REPR FAILURE'
721 721 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
722 722 def nullrepr(value, repr=text_repr): return ''
723 723
724 724 # meat of the code begins
725 725 try:
726 726 etype = etype.__name__
727 727 except AttributeError:
728 728 pass
729 729
730 730 if self.long_header:
731 731 # Header with the exception type, python version, and date
732 732 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
733 733 date = time.ctime(time.time())
734 734
735 735 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
736 736 exc, ' '*(75-len(str(etype))-len(pyver)),
737 737 pyver, date.rjust(75) )
738 738 head += "\nA problem occured executing Python code. Here is the sequence of function"\
739 739 "\ncalls leading up to the error, with the most recent (innermost) call last."
740 740 else:
741 741 # Simplified header
742 742 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
743 743 'Traceback (most recent call last)'.\
744 744 rjust(75 - len(str(etype)) ) )
745 745 frames = []
746 746 # Flush cache before calling inspect. This helps alleviate some of the
747 747 # problems with python 2.3's inspect.py.
748 748 ##self.check_cache()
749 749 # Drop topmost frames if requested
750 750 try:
751 751 # Try the default getinnerframes and Alex's: Alex's fixes some
752 752 # problems, but it generates empty tracebacks for console errors
753 753 # (5 blanks lines) where none should be returned.
754 754 #records = inspect.getinnerframes(etb, context)[tb_offset:]
755 755 #print 'python records:', records # dbg
756 756 records = _fixed_getinnerframes(etb, context, tb_offset)
757 757 #print 'alex records:', records # dbg
758 758 except:
759 759
760 760 # FIXME: I've been getting many crash reports from python 2.3
761 761 # users, traceable to inspect.py. If I can find a small test-case
762 762 # to reproduce this, I should either write a better workaround or
763 763 # file a bug report against inspect (if that's the real problem).
764 764 # So far, I haven't been able to find an isolated example to
765 765 # reproduce the problem.
766 766 inspect_error()
767 767 traceback.print_exc(file=self.ostream)
768 768 info('\nUnfortunately, your original traceback can not be constructed.\n')
769 769 return ''
770 770
771 771 # build some color string templates outside these nested loops
772 772 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
773 773 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
774 774 ColorsNormal)
775 775 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
776 776 (Colors.vName, Colors.valEm, ColorsNormal)
777 777 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
778 778 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
779 779 Colors.vName, ColorsNormal)
780 780 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
781 781 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
782 782 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
783 783 ColorsNormal)
784 784
785 785 # now, loop over all records printing context and info
786 786 abspath = os.path.abspath
787 787 for frame, file, lnum, func, lines, index in records:
788 788 #print '*** record:',file,lnum,func,lines,index # dbg
789 789
790 790 if not file:
791 791 file = '?'
792 792 elif not(file.startswith("<") and file.endswith(">")):
793 793 # Guess that filenames like <string> aren't real filenames, so
794 794 # don't call abspath on them.
795 795 try:
796 796 file = abspath(file)
797 797 except OSError:
798 798 # Not sure if this can still happen: abspath now works with
799 799 # file names like <string>
800 800 pass
801 801
802 802 link = tpl_link % file
803 803 args, varargs, varkw, locals = inspect.getargvalues(frame)
804 804
805 805 if func == '?':
806 806 call = ''
807 807 else:
808 808 # Decide whether to include variable details or not
809 809 var_repr = self.include_vars and eqrepr or nullrepr
810 810 try:
811 811 call = tpl_call % (func,inspect.formatargvalues(args,
812 812 varargs, varkw,
813 813 locals,formatvalue=var_repr))
814 814 except KeyError:
815 815 # This happens in situations like errors inside generator
816 816 # expressions, where local variables are listed in the
817 817 # line, but can't be extracted from the frame. I'm not
818 818 # 100% sure this isn't actually a bug in inspect itself,
819 819 # but since there's no info for us to compute with, the
820 820 # best we can do is report the failure and move on. Here
821 821 # we must *not* call any traceback construction again,
822 822 # because that would mess up use of %debug later on. So we
823 823 # simply report the failure and move on. The only
824 824 # limitation will be that this frame won't have locals
825 825 # listed in the call signature. Quite subtle problem...
826 826 # I can't think of a good way to validate this in a unit
827 827 # test, but running a script consisting of:
828 828 # dict( (k,v.strip()) for (k,v) in range(10) )
829 829 # will illustrate the error, if this exception catch is
830 830 # disabled.
831 831 call = tpl_call_fail % func
832 832
833 833 # Don't attempt to tokenize binary files.
834 834 if file.endswith(('.so', '.pyd', '.dll')):
835 835 frames.append('%s %s\n' % (link,call))
836 836 continue
837 837 elif file.endswith(('.pyc','.pyo')):
838 838 # Look up the corresponding source file.
839 839 file = pyfile.source_from_cache(file)
840 840
841 841 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
842 842 line = getline(file, lnum[0])
843 843 lnum[0] += 1
844 844 return line
845 845
846 846 # Build the list of names on this line of code where the exception
847 847 # occurred.
848 848 try:
849 849 names = []
850 850 name_cont = False
851 851
852 852 for token_type, token, start, end, line in generate_tokens(linereader):
853 853 # build composite names
854 854 if token_type == tokenize.NAME and token not in keyword.kwlist:
855 855 if name_cont:
856 856 # Continuation of a dotted name
857 857 try:
858 858 names[-1].append(token)
859 859 except IndexError:
860 860 names.append([token])
861 861 name_cont = False
862 862 else:
863 863 # Regular new names. We append everything, the caller
864 864 # will be responsible for pruning the list later. It's
865 865 # very tricky to try to prune as we go, b/c composite
866 866 # names can fool us. The pruning at the end is easy
867 867 # to do (or the caller can print a list with repeated
868 868 # names if so desired.
869 869 names.append([token])
870 870 elif token == '.':
871 871 name_cont = True
872 872 elif token_type == tokenize.NEWLINE:
873 873 break
874 874
875 875 except (IndexError, UnicodeDecodeError):
876 876 # signals exit of tokenizer
877 877 pass
878 except tokenize.TokenError,msg:
878 except tokenize.TokenError as msg:
879 879 _m = ("An unexpected error occurred while tokenizing input\n"
880 880 "The following traceback may be corrupted or invalid\n"
881 881 "The error message is: %s\n" % msg)
882 882 error(_m)
883 883
884 884 # Join composite names (e.g. "dict.fromkeys")
885 885 names = ['.'.join(n) for n in names]
886 886 # prune names list of duplicates, but keep the right order
887 887 unique_names = uniq_stable(names)
888 888
889 889 # Start loop over vars
890 890 lvals = []
891 891 if self.include_vars:
892 892 for name_full in unique_names:
893 893 name_base = name_full.split('.',1)[0]
894 894 if name_base in frame.f_code.co_varnames:
895 895 if locals.has_key(name_base):
896 896 try:
897 897 value = repr(eval(name_full,locals))
898 898 except:
899 899 value = undefined
900 900 else:
901 901 value = undefined
902 902 name = tpl_local_var % name_full
903 903 else:
904 904 if frame.f_globals.has_key(name_base):
905 905 try:
906 906 value = repr(eval(name_full,frame.f_globals))
907 907 except:
908 908 value = undefined
909 909 else:
910 910 value = undefined
911 911 name = tpl_global_var % name_full
912 912 lvals.append(tpl_name_val % (name,value))
913 913 if lvals:
914 914 lvals = '%s%s' % (indent,em_normal.join(lvals))
915 915 else:
916 916 lvals = ''
917 917
918 918 level = '%s %s\n' % (link,call)
919 919
920 920 if index is None:
921 921 frames.append(level)
922 922 else:
923 923 frames.append('%s%s' % (level,''.join(
924 924 _format_traceback_lines(lnum,index,lines,Colors,lvals,
925 925 col_scheme))))
926 926
927 927 # Get (safely) a string form of the exception info
928 928 try:
929 929 etype_str,evalue_str = map(str,(etype,evalue))
930 930 except:
931 931 # User exception is improperly defined.
932 932 etype,evalue = str,sys.exc_info()[:2]
933 933 etype_str,evalue_str = map(str,(etype,evalue))
934 934 # ... and format it
935 935 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
936 936 ColorsNormal, evalue_str)]
937 937 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
938 938 try:
939 939 names = [w for w in dir(evalue) if isinstance(w, basestring)]
940 940 except:
941 941 # Every now and then, an object with funny inernals blows up
942 942 # when dir() is called on it. We do the best we can to report
943 943 # the problem and continue
944 944 _m = '%sException reporting error (object with broken dir())%s:'
945 945 exception.append(_m % (Colors.excName,ColorsNormal))
946 946 etype_str,evalue_str = map(str,sys.exc_info()[:2])
947 947 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
948 948 ColorsNormal, evalue_str))
949 949 names = []
950 950 for name in names:
951 951 value = text_repr(getattr(evalue, name))
952 952 exception.append('\n%s%s = %s' % (indent, name, value))
953 953
954 954 # vds: >>
955 955 if records:
956 956 filepath, lnum = records[-1][1:3]
957 957 #print "file:", str(file), "linenb", str(lnum) # dbg
958 958 filepath = os.path.abspath(filepath)
959 959 ipinst = ipapi.get()
960 960 if ipinst is not None:
961 961 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
962 962 # vds: <<
963 963
964 964 # return all our info assembled as a single string
965 965 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
966 966 return [head] + frames + [''.join(exception[0])]
967 967
968 968 def debugger(self,force=False):
969 969 """Call up the pdb debugger if desired, always clean up the tb
970 970 reference.
971 971
972 972 Keywords:
973 973
974 974 - force(False): by default, this routine checks the instance call_pdb
975 975 flag and does not actually invoke the debugger if the flag is false.
976 976 The 'force' option forces the debugger to activate even if the flag
977 977 is false.
978 978
979 979 If the call_pdb flag is set, the pdb interactive debugger is
980 980 invoked. In all cases, the self.tb reference to the current traceback
981 981 is deleted to prevent lingering references which hamper memory
982 982 management.
983 983
984 984 Note that each call to pdb() does an 'import readline', so if your app
985 985 requires a special setup for the readline completers, you'll have to
986 986 fix that by hand after invoking the exception handler."""
987 987
988 988 if force or self.call_pdb:
989 989 if self.pdb is None:
990 990 self.pdb = debugger.Pdb(
991 991 self.color_scheme_table.active_scheme_name)
992 992 # the system displayhook may have changed, restore the original
993 993 # for pdb
994 994 display_trap = DisplayTrap(hook=sys.__displayhook__)
995 995 with display_trap:
996 996 self.pdb.reset()
997 997 # Find the right frame so we don't pop up inside ipython itself
998 998 if hasattr(self,'tb') and self.tb is not None:
999 999 etb = self.tb
1000 1000 else:
1001 1001 etb = self.tb = sys.last_traceback
1002 1002 while self.tb is not None and self.tb.tb_next is not None:
1003 1003 self.tb = self.tb.tb_next
1004 1004 if etb and etb.tb_next:
1005 1005 etb = etb.tb_next
1006 1006 self.pdb.botframe = etb.tb_frame
1007 1007 self.pdb.interaction(self.tb.tb_frame, self.tb)
1008 1008
1009 1009 if hasattr(self,'tb'):
1010 1010 del self.tb
1011 1011
1012 1012 def handler(self, info=None):
1013 1013 (etype, evalue, etb) = info or sys.exc_info()
1014 1014 self.tb = etb
1015 1015 ostream = self.ostream
1016 1016 ostream.flush()
1017 1017 ostream.write(self.text(etype, evalue, etb))
1018 1018 ostream.write('\n')
1019 1019 ostream.flush()
1020 1020
1021 1021 # Changed so an instance can just be called as VerboseTB_inst() and print
1022 1022 # out the right info on its own.
1023 1023 def __call__(self, etype=None, evalue=None, etb=None):
1024 1024 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1025 1025 if etb is None:
1026 1026 self.handler()
1027 1027 else:
1028 1028 self.handler((etype, evalue, etb))
1029 1029 try:
1030 1030 self.debugger()
1031 1031 except KeyboardInterrupt:
1032 1032 print "\nKeyboardInterrupt"
1033 1033
1034 1034 #----------------------------------------------------------------------------
1035 1035 class FormattedTB(VerboseTB, ListTB):
1036 1036 """Subclass ListTB but allow calling with a traceback.
1037 1037
1038 1038 It can thus be used as a sys.excepthook for Python > 2.1.
1039 1039
1040 1040 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1041 1041
1042 1042 Allows a tb_offset to be specified. This is useful for situations where
1043 1043 one needs to remove a number of topmost frames from the traceback (such as
1044 1044 occurs with python programs that themselves execute other python code,
1045 1045 like Python shells). """
1046 1046
1047 1047 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1048 1048 ostream=None,
1049 1049 tb_offset=0, long_header=False, include_vars=False,
1050 1050 check_cache=None):
1051 1051
1052 1052 # NEVER change the order of this list. Put new modes at the end:
1053 1053 self.valid_modes = ['Plain','Context','Verbose']
1054 1054 self.verbose_modes = self.valid_modes[1:3]
1055 1055
1056 1056 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1057 1057 ostream=ostream, tb_offset=tb_offset,
1058 1058 long_header=long_header, include_vars=include_vars,
1059 1059 check_cache=check_cache)
1060 1060
1061 1061 # Different types of tracebacks are joined with different separators to
1062 1062 # form a single string. They are taken from this dict
1063 1063 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1064 1064 # set_mode also sets the tb_join_char attribute
1065 1065 self.set_mode(mode)
1066 1066
1067 1067 def _extract_tb(self,tb):
1068 1068 if tb:
1069 1069 return traceback.extract_tb(tb)
1070 1070 else:
1071 1071 return None
1072 1072
1073 1073 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1074 1074 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1075 1075 mode = self.mode
1076 1076 if mode in self.verbose_modes:
1077 1077 # Verbose modes need a full traceback
1078 1078 return VerboseTB.structured_traceback(
1079 1079 self, etype, value, tb, tb_offset, context
1080 1080 )
1081 1081 else:
1082 1082 # We must check the source cache because otherwise we can print
1083 1083 # out-of-date source code.
1084 1084 self.check_cache()
1085 1085 # Now we can extract and format the exception
1086 1086 elist = self._extract_tb(tb)
1087 1087 return ListTB.structured_traceback(
1088 1088 self, etype, value, elist, tb_offset, context
1089 1089 )
1090 1090
1091 1091 def stb2text(self, stb):
1092 1092 """Convert a structured traceback (a list) to a string."""
1093 1093 return self.tb_join_char.join(stb)
1094 1094
1095 1095
1096 1096 def set_mode(self,mode=None):
1097 1097 """Switch to the desired mode.
1098 1098
1099 1099 If mode is not specified, cycles through the available modes."""
1100 1100
1101 1101 if not mode:
1102 1102 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1103 1103 len(self.valid_modes)
1104 1104 self.mode = self.valid_modes[new_idx]
1105 1105 elif mode not in self.valid_modes:
1106 1106 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
1107 1107 'Valid modes: '+str(self.valid_modes)
1108 1108 else:
1109 1109 self.mode = mode
1110 1110 # include variable details only in 'Verbose' mode
1111 1111 self.include_vars = (self.mode == self.valid_modes[2])
1112 1112 # Set the join character for generating text tracebacks
1113 1113 self.tb_join_char = self._join_chars[self.mode]
1114 1114
1115 1115 # some convenient shorcuts
1116 1116 def plain(self):
1117 1117 self.set_mode(self.valid_modes[0])
1118 1118
1119 1119 def context(self):
1120 1120 self.set_mode(self.valid_modes[1])
1121 1121
1122 1122 def verbose(self):
1123 1123 self.set_mode(self.valid_modes[2])
1124 1124
1125 1125 #----------------------------------------------------------------------------
1126 1126 class AutoFormattedTB(FormattedTB):
1127 1127 """A traceback printer which can be called on the fly.
1128 1128
1129 1129 It will find out about exceptions by itself.
1130 1130
1131 1131 A brief example:
1132 1132
1133 1133 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1134 1134 try:
1135 1135 ...
1136 1136 except:
1137 1137 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1138 1138 """
1139 1139
1140 1140 def __call__(self,etype=None,evalue=None,etb=None,
1141 1141 out=None,tb_offset=None):
1142 1142 """Print out a formatted exception traceback.
1143 1143
1144 1144 Optional arguments:
1145 1145 - out: an open file-like object to direct output to.
1146 1146
1147 1147 - tb_offset: the number of frames to skip over in the stack, on a
1148 1148 per-call basis (this overrides temporarily the instance's tb_offset
1149 1149 given at initialization time. """
1150 1150
1151 1151
1152 1152 if out is None:
1153 1153 out = self.ostream
1154 1154 out.flush()
1155 1155 out.write(self.text(etype, evalue, etb, tb_offset))
1156 1156 out.write('\n')
1157 1157 out.flush()
1158 1158 # FIXME: we should remove the auto pdb behavior from here and leave
1159 1159 # that to the clients.
1160 1160 try:
1161 1161 self.debugger()
1162 1162 except KeyboardInterrupt:
1163 1163 print "\nKeyboardInterrupt"
1164 1164
1165 1165 def structured_traceback(self, etype=None, value=None, tb=None,
1166 1166 tb_offset=None, context=5):
1167 1167 if etype is None:
1168 1168 etype,value,tb = sys.exc_info()
1169 1169 self.tb = tb
1170 1170 return FormattedTB.structured_traceback(
1171 1171 self, etype, value, tb, tb_offset, context)
1172 1172
1173 1173 #---------------------------------------------------------------------------
1174 1174
1175 1175 # A simple class to preserve Nathan's original functionality.
1176 1176 class ColorTB(FormattedTB):
1177 1177 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1178 1178 def __init__(self,color_scheme='Linux',call_pdb=0):
1179 1179 FormattedTB.__init__(self,color_scheme=color_scheme,
1180 1180 call_pdb=call_pdb)
1181 1181
1182 1182
1183 1183 class SyntaxTB(ListTB):
1184 1184 """Extension which holds some state: the last exception value"""
1185 1185
1186 1186 def __init__(self,color_scheme = 'NoColor'):
1187 1187 ListTB.__init__(self,color_scheme)
1188 1188 self.last_syntax_error = None
1189 1189
1190 1190 def __call__(self, etype, value, elist):
1191 1191 self.last_syntax_error = value
1192 1192 ListTB.__call__(self,etype,value,elist)
1193 1193
1194 1194 def clear_err_state(self):
1195 1195 """Return the current error state and clear it"""
1196 1196 e = self.last_syntax_error
1197 1197 self.last_syntax_error = None
1198 1198 return e
1199 1199
1200 1200 def stb2text(self, stb):
1201 1201 """Convert a structured traceback (a list) to a string."""
1202 1202 return ''.join(stb)
1203 1203
1204 1204
1205 1205 #----------------------------------------------------------------------------
1206 1206 # module testing (minimal)
1207 1207 if __name__ == "__main__":
1208 1208 def spam(c, (d, e)):
1209 1209 x = c + d
1210 1210 y = c * d
1211 1211 foo(x, y)
1212 1212
1213 1213 def foo(a, b, bar=1):
1214 1214 eggs(a, b + bar)
1215 1215
1216 1216 def eggs(f, g, z=globals()):
1217 1217 h = f + g
1218 1218 i = f - g
1219 1219 return h / i
1220 1220
1221 1221 print ''
1222 1222 print '*** Before ***'
1223 1223 try:
1224 1224 print spam(1, (2, 3))
1225 1225 except:
1226 1226 traceback.print_exc()
1227 1227 print ''
1228 1228
1229 1229 handler = ColorTB()
1230 1230 print '*** ColorTB ***'
1231 1231 try:
1232 1232 print spam(1, (2, 3))
1233 1233 except:
1234 1234 apply(handler, sys.exc_info() )
1235 1235 print ''
1236 1236
1237 1237 handler = VerboseTB()
1238 1238 print '*** VerboseTB ***'
1239 1239 try:
1240 1240 print spam(1, (2, 3))
1241 1241 except:
1242 1242 apply(handler, sys.exc_info() )
1243 1243 print ''
1244 1244
@@ -1,1767 +1,1767 b''
1 1 # -*- coding: iso-8859-1 -*-
2 2
3 3 import curses, fcntl, signal, struct, tty, textwrap, inspect
4 4
5 5 from IPython.core import ipapi
6 6
7 7 import astyle, ipipe
8 8
9 9
10 10 # Python 2.3 compatibility
11 11 try:
12 12 set
13 13 except NameError:
14 14 import sets
15 15 set = sets.Set
16 16
17 17 # Python 2.3 compatibility
18 18 try:
19 19 sorted
20 20 except NameError:
21 21 from ipipe import sorted
22 22
23 23
24 24 class UnassignedKeyError(Exception):
25 25 """
26 26 Exception that is used for reporting unassigned keys.
27 27 """
28 28
29 29
30 30 class UnknownCommandError(Exception):
31 31 """
32 32 Exception that is used for reporting unknown commands (this should never
33 33 happen).
34 34 """
35 35
36 36
37 37 class CommandError(Exception):
38 38 """
39 39 Exception that is used for reporting that a command can't be executed.
40 40 """
41 41
42 42
43 43 class Keymap(dict):
44 44 """
45 45 Stores mapping of keys to commands.
46 46 """
47 47 def __init__(self):
48 48 self._keymap = {}
49 49
50 50 def __setitem__(self, key, command):
51 51 if isinstance(key, str):
52 52 for c in key:
53 53 dict.__setitem__(self, ord(c), command)
54 54 else:
55 55 dict.__setitem__(self, key, command)
56 56
57 57 def __getitem__(self, key):
58 58 if isinstance(key, str):
59 59 key = ord(key)
60 60 return dict.__getitem__(self, key)
61 61
62 62 def __detitem__(self, key):
63 63 if isinstance(key, str):
64 64 key = ord(key)
65 65 dict.__detitem__(self, key)
66 66
67 67 def register(self, command, *keys):
68 68 for key in keys:
69 69 self[key] = command
70 70
71 71 def get(self, key, default=None):
72 72 if isinstance(key, str):
73 73 key = ord(key)
74 74 return dict.get(self, key, default)
75 75
76 76 def findkey(self, command, default=ipipe.noitem):
77 77 for (key, commandcandidate) in self.iteritems():
78 78 if commandcandidate == command:
79 79 return key
80 80 if default is ipipe.noitem:
81 81 raise KeyError(command)
82 82 return default
83 83
84 84
85 85 class _BrowserCachedItem(object):
86 86 # This is used internally by ``ibrowse`` to store a item together with its
87 87 # marked status.
88 88 __slots__ = ("item", "marked")
89 89
90 90 def __init__(self, item):
91 91 self.item = item
92 92 self.marked = False
93 93
94 94
95 95 class _BrowserHelp(object):
96 96 style_header = astyle.Style.fromstr("yellow:black:bold")
97 97 # This is used internally by ``ibrowse`` for displaying the help screen.
98 98 def __init__(self, browser):
99 99 self.browser = browser
100 100
101 101 def __xrepr__(self, mode):
102 102 yield (-1, True)
103 103 if mode == "header" or mode == "footer":
104 104 yield (astyle.style_default, "ibrowse help screen")
105 105 else:
106 106 yield (astyle.style_default, repr(self))
107 107
108 108 def __iter__(self):
109 109 # Get reverse key mapping
110 110 allkeys = {}
111 111 for (key, cmd) in self.browser.keymap.iteritems():
112 112 allkeys.setdefault(cmd, []).append(key)
113 113
114 114 fields = ("key", "description")
115 115
116 116 commands = []
117 117 for name in dir(self.browser):
118 118 if name.startswith("cmd_"):
119 119 command = getattr(self.browser, name)
120 120 commands.append((inspect.getsourcelines(command)[-1], name[4:], command))
121 121 commands.sort()
122 122 commands = [(c[1], c[2]) for c in commands]
123 123 for (i, (name, command)) in enumerate(commands):
124 124 if i:
125 125 yield ipipe.Fields(fields, key="", description="")
126 126
127 127 description = command.__doc__
128 128 if description is None:
129 129 lines = []
130 130 else:
131 131 lines = [l.strip() for l in description.splitlines() if l.strip()]
132 132 description = "\n".join(lines)
133 133 lines = textwrap.wrap(description, 60)
134 134 keys = allkeys.get(name, [])
135 135
136 136 yield ipipe.Fields(fields, key="", description=astyle.Text((self.style_header, name)))
137 137 for i in xrange(max(len(keys), len(lines))):
138 138 try:
139 139 key = self.browser.keylabel(keys[i])
140 140 except IndexError:
141 141 key = ""
142 142 try:
143 143 line = lines[i]
144 144 except IndexError:
145 145 line = ""
146 146 yield ipipe.Fields(fields, key=key, description=line)
147 147
148 148
149 149 class _BrowserLevel(object):
150 150 # This is used internally to store the state (iterator, fetch items,
151 151 # position of cursor and screen, etc.) of one browser level
152 152 # An ``ibrowse`` object keeps multiple ``_BrowserLevel`` objects in
153 153 # a stack.
154 154 def __init__(self, browser, input, mainsizey, *attrs):
155 155 self.browser = browser
156 156 self.input = input
157 157 self.header = [x for x in ipipe.xrepr(input, "header") if not isinstance(x[0], int)]
158 158 # iterator for the input
159 159 self.iterator = ipipe.xiter(input)
160 160
161 161 # is the iterator exhausted?
162 162 self.exhausted = False
163 163
164 164 # attributes to be display (autodetected if empty)
165 165 self.attrs = attrs
166 166
167 167 # fetched items (+ marked flag)
168 168 self.items = ipipe.deque()
169 169
170 170 # Number of marked objects
171 171 self.marked = 0
172 172
173 173 # Vertical cursor position
174 174 self.cury = 0
175 175
176 176 # Horizontal cursor position
177 177 self.curx = 0
178 178
179 179 # Index of first data column
180 180 self.datastartx = 0
181 181
182 182 # Index of first data line
183 183 self.datastarty = 0
184 184
185 185 # height of the data display area
186 186 self.mainsizey = mainsizey
187 187
188 188 # width of the data display area (changes when scrolling)
189 189 self.mainsizex = 0
190 190
191 191 # Size of row number (changes when scrolling)
192 192 self.numbersizex = 0
193 193
194 194 # Attributes to display (in this order)
195 195 self.displayattrs = []
196 196
197 197 # index and attribute under the cursor
198 198 self.displayattr = (None, ipipe.noitem)
199 199
200 200 # Maps attributes to column widths
201 201 self.colwidths = {}
202 202
203 203 # Set of hidden attributes
204 204 self.hiddenattrs = set()
205 205
206 206 # This takes care of all the caches etc.
207 207 self.moveto(0, 0, refresh=True)
208 208
209 209 def fetch(self, count):
210 210 # Try to fill ``self.items`` with at least ``count`` objects.
211 211 have = len(self.items)
212 212 while not self.exhausted and have < count:
213 213 try:
214 214 item = self.iterator.next()
215 215 except StopIteration:
216 216 self.exhausted = True
217 217 break
218 218 except (KeyboardInterrupt, SystemExit):
219 219 raise
220 except Exception, exc:
220 except Exception as exc:
221 221 have += 1
222 222 self.items.append(_BrowserCachedItem(exc))
223 223 self.exhausted = True
224 224 break
225 225 else:
226 226 have += 1
227 227 self.items.append(_BrowserCachedItem(item))
228 228
229 229 def calcdisplayattrs(self):
230 230 # Calculate which attributes are available from the objects that are
231 231 # currently visible on screen (and store it in ``self.displayattrs``)
232 232
233 233 attrs = set()
234 234 self.displayattrs = []
235 235 if self.attrs:
236 236 # If the browser object specifies a fixed list of attributes,
237 237 # simply use it (removing hidden attributes).
238 238 for attr in self.attrs:
239 239 attr = ipipe.upgradexattr(attr)
240 240 if attr not in attrs and attr not in self.hiddenattrs:
241 241 self.displayattrs.append(attr)
242 242 attrs.add(attr)
243 243 else:
244 244 endy = min(self.datastarty+self.mainsizey, len(self.items))
245 245 for i in xrange(self.datastarty, endy):
246 246 for attr in ipipe.xattrs(self.items[i].item, "default"):
247 247 if attr not in attrs and attr not in self.hiddenattrs:
248 248 self.displayattrs.append(attr)
249 249 attrs.add(attr)
250 250
251 251 def getrow(self, i):
252 252 # Return a dictionary with the attributes for the object
253 253 # ``self.items[i]``. Attribute names are taken from
254 254 # ``self.displayattrs`` so ``calcdisplayattrs()`` must have been
255 255 # called before.
256 256 row = {}
257 257 item = self.items[i].item
258 258 for attr in self.displayattrs:
259 259 try:
260 260 value = attr.value(item)
261 261 except (KeyboardInterrupt, SystemExit):
262 262 raise
263 except Exception, exc:
263 except Exception as exc:
264 264 value = exc
265 265 # only store attribute if it exists (or we got an exception)
266 266 if value is not ipipe.noitem:
267 267 # remember alignment, length and colored text
268 268 row[attr] = ipipe.xformat(value, "cell", self.browser.maxattrlength)
269 269 return row
270 270
271 271 def calcwidths(self):
272 272 # Recalculate the displayed fields and their widths.
273 273 # ``calcdisplayattrs()'' must have been called and the cache
274 274 # for attributes of the objects on screen (``self.displayrows``)
275 275 # must have been filled. This sets ``self.colwidths`` which maps
276 276 # attribute descriptors to widths.
277 277 self.colwidths = {}
278 278 for row in self.displayrows:
279 279 for attr in self.displayattrs:
280 280 try:
281 281 length = row[attr][1]
282 282 except KeyError:
283 283 length = 0
284 284 # always add attribute to colwidths, even if it doesn't exist
285 285 if attr not in self.colwidths:
286 286 self.colwidths[attr] = len(attr.name())
287 287 newwidth = max(self.colwidths[attr], length)
288 288 self.colwidths[attr] = newwidth
289 289
290 290 # How many characters do we need to paint the largest item number?
291 291 self.numbersizex = len(str(self.datastarty+self.mainsizey-1))
292 292 # How must space have we got to display data?
293 293 self.mainsizex = self.browser.scrsizex-self.numbersizex-3
294 294 # width of all columns
295 295 self.datasizex = sum(self.colwidths.itervalues()) + len(self.colwidths)
296 296
297 297 def calcdisplayattr(self):
298 298 # Find out which attribute the cursor is on and store this
299 299 # information in ``self.displayattr``.
300 300 pos = 0
301 301 for (i, attr) in enumerate(self.displayattrs):
302 302 if pos+self.colwidths[attr] >= self.curx:
303 303 self.displayattr = (i, attr)
304 304 break
305 305 pos += self.colwidths[attr]+1
306 306 else:
307 307 self.displayattr = (None, ipipe.noitem)
308 308
309 309 def moveto(self, x, y, refresh=False):
310 310 # Move the cursor to the position ``(x,y)`` (in data coordinates,
311 311 # not in screen coordinates). If ``refresh`` is true, all cached
312 312 # values will be recalculated (e.g. because the list has been
313 313 # resorted, so screen positions etc. are no longer valid).
314 314 olddatastarty = self.datastarty
315 315 oldx = self.curx
316 316 oldy = self.cury
317 317 x = int(x+0.5)
318 318 y = int(y+0.5)
319 319 newx = x # remember where we wanted to move
320 320 newy = y # remember where we wanted to move
321 321
322 322 scrollbordery = min(self.browser.scrollbordery, self.mainsizey//2)
323 323 scrollborderx = min(self.browser.scrollborderx, self.mainsizex//2)
324 324
325 325 # Make sure that the cursor didn't leave the main area vertically
326 326 if y < 0:
327 327 y = 0
328 328 # try to get enough items to fill the screen
329 329 self.fetch(max(y+scrollbordery+1, self.mainsizey))
330 330 if y >= len(self.items):
331 331 y = max(0, len(self.items)-1)
332 332
333 333 # Make sure that the cursor stays on screen vertically
334 334 if y < self.datastarty+scrollbordery:
335 335 self.datastarty = max(0, y-scrollbordery)
336 336 elif y >= self.datastarty+self.mainsizey-scrollbordery:
337 337 self.datastarty = max(0, min(y-self.mainsizey+scrollbordery+1,
338 338 len(self.items)-self.mainsizey))
339 339
340 340 if refresh: # Do we need to refresh the complete display?
341 341 self.calcdisplayattrs()
342 342 endy = min(self.datastarty+self.mainsizey, len(self.items))
343 343 self.displayrows = map(self.getrow, xrange(self.datastarty, endy))
344 344 self.calcwidths()
345 345 # Did we scroll vertically => update displayrows
346 346 # and various other attributes
347 347 elif self.datastarty != olddatastarty:
348 348 # Recalculate which attributes we have to display
349 349 olddisplayattrs = self.displayattrs
350 350 self.calcdisplayattrs()
351 351 # If there are new attributes, recreate the cache
352 352 if self.displayattrs != olddisplayattrs:
353 353 endy = min(self.datastarty+self.mainsizey, len(self.items))
354 354 self.displayrows = map(self.getrow, xrange(self.datastarty, endy))
355 355 elif self.datastarty<olddatastarty: # we did scroll up
356 356 # drop rows from the end
357 357 del self.displayrows[self.datastarty-olddatastarty:]
358 358 # fetch new items
359 359 for i in xrange(min(olddatastarty, self.datastarty+self.mainsizey)-1,
360 360 self.datastarty-1, -1):
361 361 try:
362 362 row = self.getrow(i)
363 363 except IndexError:
364 364 # we didn't have enough objects to fill the screen
365 365 break
366 366 self.displayrows.insert(0, row)
367 367 else: # we did scroll down
368 368 # drop rows from the start
369 369 del self.displayrows[:self.datastarty-olddatastarty]
370 370 # fetch new items
371 371 for i in xrange(max(olddatastarty+self.mainsizey, self.datastarty),
372 372 self.datastarty+self.mainsizey):
373 373 try:
374 374 row = self.getrow(i)
375 375 except IndexError:
376 376 # we didn't have enough objects to fill the screen
377 377 break
378 378 self.displayrows.append(row)
379 379 self.calcwidths()
380 380
381 381 # Make sure that the cursor didn't leave the data area horizontally
382 382 if x < 0:
383 383 x = 0
384 384 elif x >= self.datasizex:
385 385 x = max(0, self.datasizex-1)
386 386
387 387 # Make sure that the cursor stays on screen horizontally
388 388 if x < self.datastartx+scrollborderx:
389 389 self.datastartx = max(0, x-scrollborderx)
390 390 elif x >= self.datastartx+self.mainsizex-scrollborderx:
391 391 self.datastartx = max(0, min(x-self.mainsizex+scrollborderx+1,
392 392 self.datasizex-self.mainsizex))
393 393
394 394 if x == oldx and y == oldy and (x != newx or y != newy): # couldn't move
395 395 self.browser.beep()
396 396 else:
397 397 self.curx = x
398 398 self.cury = y
399 399 self.calcdisplayattr()
400 400
401 401 def sort(self, key, reverse=False):
402 402 """
403 403 Sort the currently list of items using the key function ``key``. If
404 404 ``reverse`` is true the sort order is reversed.
405 405 """
406 406 curitem = self.items[self.cury] # Remember where the cursor is now
407 407
408 408 # Sort items
409 409 def realkey(item):
410 410 return key(item.item)
411 411 self.items = ipipe.deque(sorted(self.items, key=realkey, reverse=reverse))
412 412
413 413 # Find out where the object under the cursor went
414 414 cury = self.cury
415 415 for (i, item) in enumerate(self.items):
416 416 if item is curitem:
417 417 cury = i
418 418 break
419 419
420 420 self.moveto(self.curx, cury, refresh=True)
421 421
422 422 def refresh(self):
423 423 """
424 424 Restart iterating the input.
425 425 """
426 426 self.iterator = ipipe.xiter(self.input)
427 427 self.items.clear()
428 428 self.exhausted = False
429 429 self.datastartx = self.datastarty = 0
430 430 self.moveto(0, 0, refresh=True)
431 431
432 432 def refreshfind(self):
433 433 """
434 434 Restart iterating the input and go back to the same object as before
435 435 (if it can be found in the new iterator).
436 436 """
437 437 try:
438 438 oldobject = self.items[self.cury].item
439 439 except IndexError:
440 440 oldobject = ipipe.noitem
441 441 self.iterator = ipipe.xiter(self.input)
442 442 self.items.clear()
443 443 self.exhausted = False
444 444 while True:
445 445 self.fetch(len(self.items)+1)
446 446 if self.exhausted:
447 447 curses.beep()
448 448 self.datastartx = self.datastarty = 0
449 449 self.moveto(self.curx, 0, refresh=True)
450 450 break
451 451 if self.items[-1].item == oldobject:
452 452 self.datastartx = self.datastarty = 0
453 453 self.moveto(self.curx, len(self.items)-1, refresh=True)
454 454 break
455 455
456 456
457 457 class _CommandInput(object):
458 458 keymap = Keymap()
459 459 keymap.register("left", curses.KEY_LEFT)
460 460 keymap.register("right", curses.KEY_RIGHT)
461 461 keymap.register("home", curses.KEY_HOME, "\x01") # Ctrl-A
462 462 keymap.register("end", curses.KEY_END, "\x05") # Ctrl-E
463 463 # FIXME: What's happening here?
464 464 keymap.register("backspace", curses.KEY_BACKSPACE, "\x08\x7f")
465 465 keymap.register("delete", curses.KEY_DC)
466 466 keymap.register("delend", 0x0b) # Ctrl-K
467 467 keymap.register("execute", "\r\n")
468 468 keymap.register("up", curses.KEY_UP)
469 469 keymap.register("down", curses.KEY_DOWN)
470 470 keymap.register("incsearchup", curses.KEY_PPAGE)
471 471 keymap.register("incsearchdown", curses.KEY_NPAGE)
472 472 keymap.register("exit", "\x18"), # Ctrl-X
473 473
474 474 def __init__(self, prompt):
475 475 self.prompt = prompt
476 476 self.history = []
477 477 self.maxhistory = 100
478 478 self.input = ""
479 479 self.curx = 0
480 480 self.cury = -1 # blank line
481 481
482 482 def start(self):
483 483 self.input = ""
484 484 self.curx = 0
485 485 self.cury = -1 # blank line
486 486
487 487 def handlekey(self, browser, key):
488 488 cmdname = self.keymap.get(key, None)
489 489 if cmdname is not None:
490 490 cmdfunc = getattr(self, "cmd_%s" % cmdname, None)
491 491 if cmdfunc is not None:
492 492 return cmdfunc(browser)
493 493 curses.beep()
494 494 elif key != -1:
495 495 try:
496 496 char = chr(key)
497 497 except ValueError:
498 498 curses.beep()
499 499 else:
500 500 return self.handlechar(browser, char)
501 501
502 502 def handlechar(self, browser, char):
503 503 self.input = self.input[:self.curx] + char + self.input[self.curx:]
504 504 self.curx += 1
505 505 return True
506 506
507 507 def dohistory(self):
508 508 self.history.insert(0, self.input)
509 509 del self.history[:-self.maxhistory]
510 510
511 511 def cmd_backspace(self, browser):
512 512 if self.curx:
513 513 self.input = self.input[:self.curx-1] + self.input[self.curx:]
514 514 self.curx -= 1
515 515 return True
516 516 else:
517 517 curses.beep()
518 518
519 519 def cmd_delete(self, browser):
520 520 if self.curx<len(self.input):
521 521 self.input = self.input[:self.curx] + self.input[self.curx+1:]
522 522 return True
523 523 else:
524 524 curses.beep()
525 525
526 526 def cmd_delend(self, browser):
527 527 if self.curx<len(self.input):
528 528 self.input = self.input[:self.curx]
529 529 return True
530 530
531 531 def cmd_left(self, browser):
532 532 if self.curx:
533 533 self.curx -= 1
534 534 return True
535 535 else:
536 536 curses.beep()
537 537
538 538 def cmd_right(self, browser):
539 539 if self.curx < len(self.input):
540 540 self.curx += 1
541 541 return True
542 542 else:
543 543 curses.beep()
544 544
545 545 def cmd_home(self, browser):
546 546 if self.curx:
547 547 self.curx = 0
548 548 return True
549 549 else:
550 550 curses.beep()
551 551
552 552 def cmd_end(self, browser):
553 553 if self.curx < len(self.input):
554 554 self.curx = len(self.input)
555 555 return True
556 556 else:
557 557 curses.beep()
558 558
559 559 def cmd_up(self, browser):
560 560 if self.cury < len(self.history)-1:
561 561 self.cury += 1
562 562 self.input = self.history[self.cury]
563 563 self.curx = len(self.input)
564 564 return True
565 565 else:
566 566 curses.beep()
567 567
568 568 def cmd_down(self, browser):
569 569 if self.cury >= 0:
570 570 self.cury -= 1
571 571 if self.cury>=0:
572 572 self.input = self.history[self.cury]
573 573 else:
574 574 self.input = ""
575 575 self.curx = len(self.input)
576 576 return True
577 577 else:
578 578 curses.beep()
579 579
580 580 def cmd_incsearchup(self, browser):
581 581 prefix = self.input[:self.curx]
582 582 cury = self.cury
583 583 while True:
584 584 cury += 1
585 585 if cury >= len(self.history):
586 586 break
587 587 if self.history[cury].startswith(prefix):
588 588 self.input = self.history[cury]
589 589 self.cury = cury
590 590 return True
591 591 curses.beep()
592 592
593 593 def cmd_incsearchdown(self, browser):
594 594 prefix = self.input[:self.curx]
595 595 cury = self.cury
596 596 while True:
597 597 cury -= 1
598 598 if cury <= 0:
599 599 break
600 600 if self.history[cury].startswith(prefix):
601 601 self.input = self.history[self.cury]
602 602 self.cury = cury
603 603 return True
604 604 curses.beep()
605 605
606 606 def cmd_exit(self, browser):
607 607 browser.mode = "default"
608 608 return True
609 609
610 610 def cmd_execute(self, browser):
611 611 raise NotImplementedError
612 612
613 613
614 614 class _CommandGoto(_CommandInput):
615 615 def __init__(self):
616 616 _CommandInput.__init__(self, "goto object #")
617 617
618 618 def handlechar(self, browser, char):
619 619 # Only accept digits
620 620 if not "0" <= char <= "9":
621 621 curses.beep()
622 622 else:
623 623 return _CommandInput.handlechar(self, browser, char)
624 624
625 625 def cmd_execute(self, browser):
626 626 level = browser.levels[-1]
627 627 if self.input:
628 628 self.dohistory()
629 629 level.moveto(level.curx, int(self.input))
630 630 browser.mode = "default"
631 631 return True
632 632
633 633
634 634 class _CommandFind(_CommandInput):
635 635 def __init__(self):
636 636 _CommandInput.__init__(self, "find expression")
637 637
638 638 def cmd_execute(self, browser):
639 639 level = browser.levels[-1]
640 640 if self.input:
641 641 self.dohistory()
642 642 while True:
643 643 cury = level.cury
644 644 level.moveto(level.curx, cury+1)
645 645 if cury == level.cury:
646 646 curses.beep()
647 647 break # hit end
648 648 item = level.items[level.cury].item
649 649 try:
650 650 globals = ipipe.getglobals(None)
651 651 if eval(self.input, globals, ipipe.AttrNamespace(item)):
652 652 break # found something
653 653 except (KeyboardInterrupt, SystemExit):
654 654 raise
655 except Exception, exc:
655 except Exception as exc:
656 656 browser.report(exc)
657 657 curses.beep()
658 658 break # break on error
659 659 browser.mode = "default"
660 660 return True
661 661
662 662
663 663 class _CommandFindBackwards(_CommandInput):
664 664 def __init__(self):
665 665 _CommandInput.__init__(self, "find backwards expression")
666 666
667 667 def cmd_execute(self, browser):
668 668 level = browser.levels[-1]
669 669 if self.input:
670 670 self.dohistory()
671 671 while level.cury:
672 672 level.moveto(level.curx, level.cury-1)
673 673 item = level.items[level.cury].item
674 674 try:
675 675 globals = ipipe.getglobals(None)
676 676 if eval(self.input, globals, ipipe.AttrNamespace(item)):
677 677 break # found something
678 678 except (KeyboardInterrupt, SystemExit):
679 679 raise
680 except Exception, exc:
680 except Exception as exc:
681 681 browser.report(exc)
682 682 curses.beep()
683 683 break # break on error
684 684 else:
685 685 curses.beep()
686 686 browser.mode = "default"
687 687 return True
688 688
689 689
690 690 class ibrowse(ipipe.Display):
691 691 # Show this many lines from the previous screen when paging horizontally
692 692 pageoverlapx = 1
693 693
694 694 # Show this many lines from the previous screen when paging vertically
695 695 pageoverlapy = 1
696 696
697 697 # Start scrolling when the cursor is less than this number of columns
698 698 # away from the left or right screen edge
699 699 scrollborderx = 10
700 700
701 701 # Start scrolling when the cursor is less than this number of lines
702 702 # away from the top or bottom screen edge
703 703 scrollbordery = 5
704 704
705 705 # Accelerate by this factor when scrolling horizontally
706 706 acceleratex = 1.05
707 707
708 708 # Accelerate by this factor when scrolling vertically
709 709 acceleratey = 1.05
710 710
711 711 # The maximum horizontal scroll speed
712 712 # (as a factor of the screen width (i.e. 0.5 == half a screen width)
713 713 maxspeedx = 0.5
714 714
715 715 # The maximum vertical scroll speed
716 716 # (as a factor of the screen height (i.e. 0.5 == half a screen height)
717 717 maxspeedy = 0.5
718 718
719 719 # The maximum number of header lines for browser level
720 720 # if the nesting is deeper, only the innermost levels are displayed
721 721 maxheaders = 5
722 722
723 723 # The approximate maximum length of a column entry
724 724 maxattrlength = 200
725 725
726 726 # Styles for various parts of the GUI
727 727 style_objheadertext = astyle.Style.fromstr("white:black:bold|reverse")
728 728 style_objheadernumber = astyle.Style.fromstr("white:blue:bold|reverse")
729 729 style_objheaderobject = astyle.Style.fromstr("white:black:reverse")
730 730 style_colheader = astyle.Style.fromstr("blue:white:reverse")
731 731 style_colheaderhere = astyle.Style.fromstr("green:black:bold|reverse")
732 732 style_colheadersep = astyle.Style.fromstr("blue:black:reverse")
733 733 style_number = astyle.Style.fromstr("blue:white:reverse")
734 734 style_numberhere = astyle.Style.fromstr("green:black:bold|reverse")
735 735 style_sep = astyle.Style.fromstr("blue:black")
736 736 style_data = astyle.Style.fromstr("white:black")
737 737 style_datapad = astyle.Style.fromstr("blue:black:bold")
738 738 style_footer = astyle.Style.fromstr("black:white")
739 739 style_report = astyle.Style.fromstr("white:black")
740 740
741 741 # Column separator in header
742 742 headersepchar = "|"
743 743
744 744 # Character for padding data cell entries
745 745 datapadchar = "."
746 746
747 747 # Column separator in data area
748 748 datasepchar = "|"
749 749
750 750 # Character to use for "empty" cell (i.e. for non-existing attributes)
751 751 nodatachar = "-"
752 752
753 753 # Prompts for modes that require keyboard input
754 754 prompts = {
755 755 "goto": _CommandGoto(),
756 756 "find": _CommandFind(),
757 757 "findbackwards": _CommandFindBackwards()
758 758 }
759 759
760 760 # Maps curses key codes to "function" names
761 761 keymap = Keymap()
762 762 keymap.register("quit", "q")
763 763 keymap.register("up", curses.KEY_UP)
764 764 keymap.register("down", curses.KEY_DOWN)
765 765 keymap.register("pageup", curses.KEY_PPAGE)
766 766 keymap.register("pagedown", curses.KEY_NPAGE)
767 767 keymap.register("left", curses.KEY_LEFT)
768 768 keymap.register("right", curses.KEY_RIGHT)
769 769 keymap.register("home", curses.KEY_HOME, "\x01")
770 770 keymap.register("end", curses.KEY_END, "\x05")
771 771 keymap.register("prevattr", "<\x1b")
772 772 keymap.register("nextattr", ">\t")
773 773 keymap.register("pick", "p")
774 774 keymap.register("pickattr", "P")
775 775 keymap.register("pickallattrs", "C")
776 776 keymap.register("pickmarked", "m")
777 777 keymap.register("pickmarkedattr", "M")
778 778 keymap.register("pickinput", "i")
779 779 keymap.register("pickinputattr", "I")
780 780 keymap.register("hideattr", "h")
781 781 keymap.register("unhideattrs", "H")
782 782 keymap.register("help", "?")
783 783 keymap.register("enter", "\r\n")
784 784 keymap.register("enterattr", "E")
785 785 # FIXME: What's happening here?
786 786 keymap.register("leave", curses.KEY_BACKSPACE, "x\x08\x7f")
787 787 keymap.register("detail", "d")
788 788 keymap.register("detailattr", "D")
789 789 keymap.register("tooglemark", " ")
790 790 keymap.register("markrange", "%")
791 791 keymap.register("sortattrasc", "v")
792 792 keymap.register("sortattrdesc", "V")
793 793 keymap.register("goto", "g")
794 794 keymap.register("find", "f")
795 795 keymap.register("findbackwards", "b")
796 796 keymap.register("refresh", "r")
797 797 keymap.register("refreshfind", "R")
798 798
799 799 def __init__(self, input=None, *attrs):
800 800 """
801 801 Create a new browser. If ``attrs`` is not empty, it is the list
802 802 of attributes that will be displayed in the browser, otherwise
803 803 these will be determined by the objects on screen.
804 804 """
805 805 ipipe.Display.__init__(self, input)
806 806
807 807 self.attrs = attrs
808 808
809 809 # Stack of browser levels
810 810 self.levels = []
811 811 # how many colums to scroll (Changes when accelerating)
812 812 self.stepx = 1.
813 813
814 814 # how many rows to scroll (Changes when accelerating)
815 815 self.stepy = 1.
816 816
817 817 # Beep on the edges of the data area? (Will be set to ``False``
818 818 # once the cursor hits the edge of the screen, so we don't get
819 819 # multiple beeps).
820 820 self._dobeep = True
821 821
822 822 # Cache for registered ``curses`` colors and styles.
823 823 self._styles = {}
824 824 self._colors = {}
825 825 self._maxcolor = 1
826 826
827 827 # How many header lines do we want to paint (the numbers of levels
828 828 # we have, but with an upper bound)
829 829 self._headerlines = 1
830 830
831 831 # Index of first header line
832 832 self._firstheaderline = 0
833 833
834 834 # curses window
835 835 self.scr = None
836 836 # report in the footer line (error, executed command etc.)
837 837 self._report = None
838 838
839 839 # value to be returned to the caller (set by commands)
840 840 self.returnvalue = None
841 841
842 842 # The mode the browser is in
843 843 # e.g. normal browsing or entering an argument for a command
844 844 self.mode = "default"
845 845
846 846 # set by the SIGWINCH signal handler
847 847 self.resized = False
848 848
849 849 def nextstepx(self, step):
850 850 """
851 851 Accelerate horizontally.
852 852 """
853 853 return max(1., min(step*self.acceleratex,
854 854 self.maxspeedx*self.levels[-1].mainsizex))
855 855
856 856 def nextstepy(self, step):
857 857 """
858 858 Accelerate vertically.
859 859 """
860 860 return max(1., min(step*self.acceleratey,
861 861 self.maxspeedy*self.levels[-1].mainsizey))
862 862
863 863 def getstyle(self, style):
864 864 """
865 865 Register the ``style`` with ``curses`` or get it from the cache,
866 866 if it has been registered before.
867 867 """
868 868 try:
869 869 return self._styles[style.fg, style.bg, style.attrs]
870 870 except KeyError:
871 871 attrs = 0
872 872 for b in astyle.A2CURSES:
873 873 if style.attrs & b:
874 874 attrs |= astyle.A2CURSES[b]
875 875 try:
876 876 color = self._colors[style.fg, style.bg]
877 877 except KeyError:
878 878 curses.init_pair(
879 879 self._maxcolor,
880 880 astyle.COLOR2CURSES[style.fg],
881 881 astyle.COLOR2CURSES[style.bg]
882 882 )
883 883 color = curses.color_pair(self._maxcolor)
884 884 self._colors[style.fg, style.bg] = color
885 885 self._maxcolor += 1
886 886 c = color | attrs
887 887 self._styles[style.fg, style.bg, style.attrs] = c
888 888 return c
889 889
890 890 def addstr(self, y, x, begx, endx, text, style):
891 891 """
892 892 A version of ``curses.addstr()`` that can handle ``x`` coordinates
893 893 that are outside the screen.
894 894 """
895 895 text2 = text[max(0, begx-x):max(0, endx-x)]
896 896 if text2:
897 897 self.scr.addstr(y, max(x, begx), text2, self.getstyle(style))
898 898 return len(text)
899 899
900 900 def addchr(self, y, x, begx, endx, c, l, style):
901 901 x0 = max(x, begx)
902 902 x1 = min(x+l, endx)
903 903 if x1>x0:
904 904 self.scr.addstr(y, x0, c*(x1-x0), self.getstyle(style))
905 905 return l
906 906
907 907 def _calcheaderlines(self, levels):
908 908 # Calculate how many headerlines do we have to display, if we have
909 909 # ``levels`` browser levels
910 910 if levels is None:
911 911 levels = len(self.levels)
912 912 self._headerlines = min(self.maxheaders, levels)
913 913 self._firstheaderline = levels-self._headerlines
914 914
915 915 def getstylehere(self, style):
916 916 """
917 917 Return a style for displaying the original style ``style``
918 918 in the row the cursor is on.
919 919 """
920 920 return astyle.Style(style.fg, astyle.COLOR_BLUE, style.attrs | astyle.A_BOLD)
921 921
922 922 def report(self, msg):
923 923 """
924 924 Store the message ``msg`` for display below the footer line. This
925 925 will be displayed as soon as the screen is redrawn.
926 926 """
927 927 self._report = msg
928 928
929 929 def enter(self, item, *attrs):
930 930 """
931 931 Enter the object ``item``. If ``attrs`` is specified, it will be used
932 932 as a fixed list of attributes to display.
933 933 """
934 934 if self.levels and item is self.levels[-1].input:
935 935 curses.beep()
936 936 self.report(CommandError("Recursion on input object"))
937 937 else:
938 938 oldlevels = len(self.levels)
939 939 self._calcheaderlines(oldlevels+1)
940 940 try:
941 941 level = _BrowserLevel(
942 942 self,
943 943 item,
944 944 self.scrsizey-1-self._headerlines-2,
945 945 *attrs
946 946 )
947 947 except (KeyboardInterrupt, SystemExit):
948 948 raise
949 except Exception, exc:
949 except Exception as exc:
950 950 if not self.levels:
951 951 raise
952 952 self._calcheaderlines(oldlevels)
953 953 curses.beep()
954 954 self.report(exc)
955 955 else:
956 956 self.levels.append(level)
957 957
958 958 def startkeyboardinput(self, mode):
959 959 """
960 960 Enter mode ``mode``, which requires keyboard input.
961 961 """
962 962 self.mode = mode
963 963 self.prompts[mode].start()
964 964
965 965 def keylabel(self, keycode):
966 966 """
967 967 Return a pretty name for the ``curses`` key ``keycode`` (used in the
968 968 help screen and in reports about unassigned keys).
969 969 """
970 970 if keycode <= 0xff:
971 971 specialsnames = {
972 972 ord("\n"): "RETURN",
973 973 ord(" "): "SPACE",
974 974 ord("\t"): "TAB",
975 975 ord("\x7f"): "DELETE",
976 976 ord("\x08"): "BACKSPACE",
977 977 }
978 978 if keycode in specialsnames:
979 979 return specialsnames[keycode]
980 980 elif 0x00 < keycode < 0x20:
981 981 return "CTRL-%s" % chr(keycode + 64)
982 982 return repr(chr(keycode))
983 983 for name in dir(curses):
984 984 if name.startswith("KEY_") and getattr(curses, name) == keycode:
985 985 return name
986 986 return str(keycode)
987 987
988 988 def beep(self, force=False):
989 989 if force or self._dobeep:
990 990 curses.beep()
991 991 # don't beep again (as long as the same key is pressed)
992 992 self._dobeep = False
993 993
994 994 def cmd_up(self):
995 995 """
996 996 Move the cursor to the previous row.
997 997 """
998 998 level = self.levels[-1]
999 999 self.report("up")
1000 1000 level.moveto(level.curx, level.cury-self.stepy)
1001 1001
1002 1002 def cmd_down(self):
1003 1003 """
1004 1004 Move the cursor to the next row.
1005 1005 """
1006 1006 level = self.levels[-1]
1007 1007 self.report("down")
1008 1008 level.moveto(level.curx, level.cury+self.stepy)
1009 1009
1010 1010 def cmd_pageup(self):
1011 1011 """
1012 1012 Move the cursor up one page.
1013 1013 """
1014 1014 level = self.levels[-1]
1015 1015 self.report("page up")
1016 1016 level.moveto(level.curx, level.cury-level.mainsizey+self.pageoverlapy)
1017 1017
1018 1018 def cmd_pagedown(self):
1019 1019 """
1020 1020 Move the cursor down one page.
1021 1021 """
1022 1022 level = self.levels[-1]
1023 1023 self.report("page down")
1024 1024 level.moveto(level.curx, level.cury+level.mainsizey-self.pageoverlapy)
1025 1025
1026 1026 def cmd_left(self):
1027 1027 """
1028 1028 Move the cursor left.
1029 1029 """
1030 1030 level = self.levels[-1]
1031 1031 self.report("left")
1032 1032 level.moveto(level.curx-self.stepx, level.cury)
1033 1033
1034 1034 def cmd_right(self):
1035 1035 """
1036 1036 Move the cursor right.
1037 1037 """
1038 1038 level = self.levels[-1]
1039 1039 self.report("right")
1040 1040 level.moveto(level.curx+self.stepx, level.cury)
1041 1041
1042 1042 def cmd_home(self):
1043 1043 """
1044 1044 Move the cursor to the first column.
1045 1045 """
1046 1046 level = self.levels[-1]
1047 1047 self.report("home")
1048 1048 level.moveto(0, level.cury)
1049 1049
1050 1050 def cmd_end(self):
1051 1051 """
1052 1052 Move the cursor to the last column.
1053 1053 """
1054 1054 level = self.levels[-1]
1055 1055 self.report("end")
1056 1056 level.moveto(level.datasizex+level.mainsizey-self.pageoverlapx, level.cury)
1057 1057
1058 1058 def cmd_prevattr(self):
1059 1059 """
1060 1060 Move the cursor one attribute column to the left.
1061 1061 """
1062 1062 level = self.levels[-1]
1063 1063 if level.displayattr[0] is None or level.displayattr[0] == 0:
1064 1064 self.beep()
1065 1065 else:
1066 1066 self.report("prevattr")
1067 1067 pos = 0
1068 1068 for (i, attrname) in enumerate(level.displayattrs):
1069 1069 if i == level.displayattr[0]-1:
1070 1070 break
1071 1071 pos += level.colwidths[attrname] + 1
1072 1072 level.moveto(pos, level.cury)
1073 1073
1074 1074 def cmd_nextattr(self):
1075 1075 """
1076 1076 Move the cursor one attribute column to the right.
1077 1077 """
1078 1078 level = self.levels[-1]
1079 1079 if level.displayattr[0] is None or level.displayattr[0] == len(level.displayattrs)-1:
1080 1080 self.beep()
1081 1081 else:
1082 1082 self.report("nextattr")
1083 1083 pos = 0
1084 1084 for (i, attrname) in enumerate(level.displayattrs):
1085 1085 if i == level.displayattr[0]+1:
1086 1086 break
1087 1087 pos += level.colwidths[attrname] + 1
1088 1088 level.moveto(pos, level.cury)
1089 1089
1090 1090 def cmd_pick(self):
1091 1091 """
1092 1092 'Pick' the object under the cursor (i.e. the row the cursor is on).
1093 1093 This leaves the browser and returns the picked object to the caller.
1094 1094 (In IPython this object will be available as the ``_`` variable.)
1095 1095 """
1096 1096 level = self.levels[-1]
1097 1097 self.returnvalue = level.items[level.cury].item
1098 1098 return True
1099 1099
1100 1100 def cmd_pickattr(self):
1101 1101 """
1102 1102 'Pick' the attribute under the cursor (i.e. the row/column the
1103 1103 cursor is on).
1104 1104 """
1105 1105 level = self.levels[-1]
1106 1106 attr = level.displayattr[1]
1107 1107 if attr is ipipe.noitem:
1108 1108 curses.beep()
1109 1109 self.report(CommandError("no column under cursor"))
1110 1110 return
1111 1111 value = attr.value(level.items[level.cury].item)
1112 1112 if value is ipipe.noitem:
1113 1113 curses.beep()
1114 1114 self.report(AttributeError(attr.name()))
1115 1115 else:
1116 1116 self.returnvalue = value
1117 1117 return True
1118 1118
1119 1119 def cmd_pickallattrs(self):
1120 1120 """
1121 1121 Pick' the complete column under the cursor (i.e. the attribute under
1122 1122 the cursor) from all currently fetched objects. These attributes
1123 1123 will be returned as a list.
1124 1124 """
1125 1125 level = self.levels[-1]
1126 1126 attr = level.displayattr[1]
1127 1127 if attr is ipipe.noitem:
1128 1128 curses.beep()
1129 1129 self.report(CommandError("no column under cursor"))
1130 1130 return
1131 1131 result = []
1132 1132 for cache in level.items:
1133 1133 value = attr.value(cache.item)
1134 1134 if value is not ipipe.noitem:
1135 1135 result.append(value)
1136 1136 self.returnvalue = result
1137 1137 return True
1138 1138
1139 1139 def cmd_pickmarked(self):
1140 1140 """
1141 1141 'Pick' marked objects. Marked objects will be returned as a list.
1142 1142 """
1143 1143 level = self.levels[-1]
1144 1144 self.returnvalue = [cache.item for cache in level.items if cache.marked]
1145 1145 return True
1146 1146
1147 1147 def cmd_pickmarkedattr(self):
1148 1148 """
1149 1149 'Pick' the attribute under the cursor from all marked objects
1150 1150 (This returns a list).
1151 1151 """
1152 1152
1153 1153 level = self.levels[-1]
1154 1154 attr = level.displayattr[1]
1155 1155 if attr is ipipe.noitem:
1156 1156 curses.beep()
1157 1157 self.report(CommandError("no column under cursor"))
1158 1158 return
1159 1159 result = []
1160 1160 for cache in level.items:
1161 1161 if cache.marked:
1162 1162 value = attr.value(cache.item)
1163 1163 if value is not ipipe.noitem:
1164 1164 result.append(value)
1165 1165 self.returnvalue = result
1166 1166 return True
1167 1167
1168 1168 def cmd_pickinput(self):
1169 1169 """
1170 1170 Use the object under the cursor (i.e. the row the cursor is on) as
1171 1171 the next input line. This leaves the browser and puts the picked object
1172 1172 in the input.
1173 1173 """
1174 1174 level = self.levels[-1]
1175 1175 value = level.items[level.cury].item
1176 1176 self.returnvalue = None
1177 1177 api = ipapi.get()
1178 1178 api.set_next_input(str(value))
1179 1179 return True
1180 1180
1181 1181 def cmd_pickinputattr(self):
1182 1182 """
1183 1183 Use the attribute under the cursor i.e. the row/column the cursor is on)
1184 1184 as the next input line. This leaves the browser and puts the picked
1185 1185 object in the input.
1186 1186 """
1187 1187 level = self.levels[-1]
1188 1188 attr = level.displayattr[1]
1189 1189 if attr is ipipe.noitem:
1190 1190 curses.beep()
1191 1191 self.report(CommandError("no column under cursor"))
1192 1192 return
1193 1193 value = attr.value(level.items[level.cury].item)
1194 1194 if value is ipipe.noitem:
1195 1195 curses.beep()
1196 1196 self.report(AttributeError(attr.name()))
1197 1197 self.returnvalue = None
1198 1198 api = ipapi.get()
1199 1199 api.set_next_input(str(value))
1200 1200 return True
1201 1201
1202 1202 def cmd_markrange(self):
1203 1203 """
1204 1204 Mark all objects from the last marked object before the current cursor
1205 1205 position to the cursor position.
1206 1206 """
1207 1207 level = self.levels[-1]
1208 1208 self.report("markrange")
1209 1209 start = None
1210 1210 if level.items:
1211 1211 for i in xrange(level.cury, -1, -1):
1212 1212 if level.items[i].marked:
1213 1213 start = i
1214 1214 break
1215 1215 if start is None:
1216 1216 self.report(CommandError("no mark before cursor"))
1217 1217 curses.beep()
1218 1218 else:
1219 1219 for i in xrange(start, level.cury+1):
1220 1220 cache = level.items[i]
1221 1221 if not cache.marked:
1222 1222 cache.marked = True
1223 1223 level.marked += 1
1224 1224
1225 1225 def cmd_enter(self):
1226 1226 """
1227 1227 Enter the object under the cursor. (what this mean depends on the object
1228 1228 itself (i.e. how it implements iteration). This opens a new browser 'level'.
1229 1229 """
1230 1230 level = self.levels[-1]
1231 1231 try:
1232 1232 item = level.items[level.cury].item
1233 1233 except IndexError:
1234 1234 self.report(CommandError("No object"))
1235 1235 curses.beep()
1236 1236 else:
1237 1237 self.report("entering object...")
1238 1238 self.enter(item)
1239 1239
1240 1240 def cmd_leave(self):
1241 1241 """
1242 1242 Leave the current browser level and go back to the previous one.
1243 1243 """
1244 1244 self.report("leave")
1245 1245 if len(self.levels) > 1:
1246 1246 self._calcheaderlines(len(self.levels)-1)
1247 1247 self.levels.pop(-1)
1248 1248 else:
1249 1249 self.report(CommandError("This is the last level"))
1250 1250 curses.beep()
1251 1251
1252 1252 def cmd_enterattr(self):
1253 1253 """
1254 1254 Enter the attribute under the cursor.
1255 1255 """
1256 1256 level = self.levels[-1]
1257 1257 attr = level.displayattr[1]
1258 1258 if attr is ipipe.noitem:
1259 1259 curses.beep()
1260 1260 self.report(CommandError("no column under cursor"))
1261 1261 return
1262 1262 try:
1263 1263 item = level.items[level.cury].item
1264 1264 except IndexError:
1265 1265 self.report(CommandError("No object"))
1266 1266 curses.beep()
1267 1267 else:
1268 1268 value = attr.value(item)
1269 1269 name = attr.name()
1270 1270 if value is ipipe.noitem:
1271 1271 self.report(AttributeError(name))
1272 1272 else:
1273 1273 self.report("entering object attribute %s..." % name)
1274 1274 self.enter(value)
1275 1275
1276 1276 def cmd_detail(self):
1277 1277 """
1278 1278 Show a detail view of the object under the cursor. This shows the
1279 1279 name, type, doc string and value of the object attributes (and it
1280 1280 might show more attributes than in the list view, depending on
1281 1281 the object).
1282 1282 """
1283 1283 level = self.levels[-1]
1284 1284 try:
1285 1285 item = level.items[level.cury].item
1286 1286 except IndexError:
1287 1287 self.report(CommandError("No object"))
1288 1288 curses.beep()
1289 1289 else:
1290 1290 self.report("entering detail view for object...")
1291 1291 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
1292 1292 self.enter(attrs)
1293 1293
1294 1294 def cmd_detailattr(self):
1295 1295 """
1296 1296 Show a detail view of the attribute under the cursor.
1297 1297 """
1298 1298 level = self.levels[-1]
1299 1299 attr = level.displayattr[1]
1300 1300 if attr is ipipe.noitem:
1301 1301 curses.beep()
1302 1302 self.report(CommandError("no attribute"))
1303 1303 return
1304 1304 try:
1305 1305 item = level.items[level.cury].item
1306 1306 except IndexError:
1307 1307 self.report(CommandError("No object"))
1308 1308 curses.beep()
1309 1309 else:
1310 1310 try:
1311 1311 item = attr.value(item)
1312 1312 except (KeyboardInterrupt, SystemExit):
1313 1313 raise
1314 except Exception, exc:
1314 except Exception as exc:
1315 1315 self.report(exc)
1316 1316 else:
1317 1317 self.report("entering detail view for attribute %s..." % attr.name())
1318 1318 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
1319 1319 self.enter(attrs)
1320 1320
1321 1321 def cmd_tooglemark(self):
1322 1322 """
1323 1323 Mark/unmark the object under the cursor. Marked objects have a '!'
1324 1324 after the row number).
1325 1325 """
1326 1326 level = self.levels[-1]
1327 1327 self.report("toggle mark")
1328 1328 try:
1329 1329 item = level.items[level.cury]
1330 1330 except IndexError: # no items?
1331 1331 pass
1332 1332 else:
1333 1333 if item.marked:
1334 1334 item.marked = False
1335 1335 level.marked -= 1
1336 1336 else:
1337 1337 item.marked = True
1338 1338 level.marked += 1
1339 1339
1340 1340 def cmd_sortattrasc(self):
1341 1341 """
1342 1342 Sort the objects (in ascending order) using the attribute under
1343 1343 the cursor as the sort key.
1344 1344 """
1345 1345 level = self.levels[-1]
1346 1346 attr = level.displayattr[1]
1347 1347 if attr is ipipe.noitem:
1348 1348 curses.beep()
1349 1349 self.report(CommandError("no column under cursor"))
1350 1350 return
1351 1351 self.report("sort by %s (ascending)" % attr.name())
1352 1352 def key(item):
1353 1353 try:
1354 1354 return attr.value(item)
1355 1355 except (KeyboardInterrupt, SystemExit):
1356 1356 raise
1357 1357 except Exception:
1358 1358 return None
1359 1359 level.sort(key)
1360 1360
1361 1361 def cmd_sortattrdesc(self):
1362 1362 """
1363 1363 Sort the objects (in descending order) using the attribute under
1364 1364 the cursor as the sort key.
1365 1365 """
1366 1366 level = self.levels[-1]
1367 1367 attr = level.displayattr[1]
1368 1368 if attr is ipipe.noitem:
1369 1369 curses.beep()
1370 1370 self.report(CommandError("no column under cursor"))
1371 1371 return
1372 1372 self.report("sort by %s (descending)" % attr.name())
1373 1373 def key(item):
1374 1374 try:
1375 1375 return attr.value(item)
1376 1376 except (KeyboardInterrupt, SystemExit):
1377 1377 raise
1378 1378 except Exception:
1379 1379 return None
1380 1380 level.sort(key, reverse=True)
1381 1381
1382 1382 def cmd_hideattr(self):
1383 1383 """
1384 1384 Hide the attribute under the cursor.
1385 1385 """
1386 1386 level = self.levels[-1]
1387 1387 if level.displayattr[0] is None:
1388 1388 self.beep()
1389 1389 else:
1390 1390 self.report("hideattr")
1391 1391 level.hiddenattrs.add(level.displayattr[1])
1392 1392 level.moveto(level.curx, level.cury, refresh=True)
1393 1393
1394 1394 def cmd_unhideattrs(self):
1395 1395 """
1396 1396 Make all attributes visible again.
1397 1397 """
1398 1398 level = self.levels[-1]
1399 1399 self.report("unhideattrs")
1400 1400 level.hiddenattrs.clear()
1401 1401 level.moveto(level.curx, level.cury, refresh=True)
1402 1402
1403 1403 def cmd_goto(self):
1404 1404 """
1405 1405 Jump to a row. The row number can be entered at the
1406 1406 bottom of the screen.
1407 1407 """
1408 1408 self.startkeyboardinput("goto")
1409 1409
1410 1410 def cmd_find(self):
1411 1411 """
1412 1412 Search forward for a row. The search condition can be entered at the
1413 1413 bottom of the screen.
1414 1414 """
1415 1415 self.startkeyboardinput("find")
1416 1416
1417 1417 def cmd_findbackwards(self):
1418 1418 """
1419 1419 Search backward for a row. The search condition can be entered at the
1420 1420 bottom of the screen.
1421 1421 """
1422 1422 self.startkeyboardinput("findbackwards")
1423 1423
1424 1424 def cmd_refresh(self):
1425 1425 """
1426 1426 Refreshes the display by restarting the iterator.
1427 1427 """
1428 1428 level = self.levels[-1]
1429 1429 self.report("refresh")
1430 1430 level.refresh()
1431 1431
1432 1432 def cmd_refreshfind(self):
1433 1433 """
1434 1434 Refreshes the display by restarting the iterator and goes back to the
1435 1435 same object the cursor was on before restarting (if this object can't be
1436 1436 found the cursor jumps back to the first object).
1437 1437 """
1438 1438 level = self.levels[-1]
1439 1439 self.report("refreshfind")
1440 1440 level.refreshfind()
1441 1441
1442 1442 def cmd_help(self):
1443 1443 """
1444 1444 Opens the help screen as a new browser level, describing keyboard
1445 1445 shortcuts.
1446 1446 """
1447 1447 for level in self.levels:
1448 1448 if isinstance(level.input, _BrowserHelp):
1449 1449 curses.beep()
1450 1450 self.report(CommandError("help already active"))
1451 1451 return
1452 1452
1453 1453 self.enter(_BrowserHelp(self))
1454 1454
1455 1455 def cmd_quit(self):
1456 1456 """
1457 1457 Quit the browser and return to the IPython prompt.
1458 1458 """
1459 1459 self.returnvalue = None
1460 1460 return True
1461 1461
1462 1462 def sigwinchhandler(self, signal, frame):
1463 1463 self.resized = True
1464 1464
1465 1465 def _dodisplay(self, scr):
1466 1466 """
1467 1467 This method is the workhorse of the browser. It handles screen
1468 1468 drawing and the keyboard.
1469 1469 """
1470 1470 self.scr = scr
1471 1471 curses.halfdelay(1)
1472 1472 footery = 2
1473 1473
1474 1474 keys = []
1475 1475 for cmd in ("quit", "help"):
1476 1476 key = self.keymap.findkey(cmd, None)
1477 1477 if key is not None:
1478 1478 keys.append("%s=%s" % (self.keylabel(key), cmd))
1479 1479 helpmsg = " | %s" % " ".join(keys)
1480 1480
1481 1481 scr.clear()
1482 1482 msg = "Fetching first batch of objects..."
1483 1483 (self.scrsizey, self.scrsizex) = scr.getmaxyx()
1484 1484 scr.addstr(self.scrsizey//2, (self.scrsizex-len(msg))//2, msg)
1485 1485 scr.refresh()
1486 1486
1487 1487 lastc = -1
1488 1488
1489 1489 self.levels = []
1490 1490 # enter the first level
1491 1491 self.enter(self.input, *self.attrs)
1492 1492
1493 1493 self._calcheaderlines(None)
1494 1494
1495 1495 while True:
1496 1496 level = self.levels[-1]
1497 1497 (self.scrsizey, self.scrsizex) = scr.getmaxyx()
1498 1498 level.mainsizey = self.scrsizey-1-self._headerlines-footery
1499 1499
1500 1500 # Paint object header
1501 1501 for i in xrange(self._firstheaderline, self._firstheaderline+self._headerlines):
1502 1502 lv = self.levels[i]
1503 1503 posx = 0
1504 1504 posy = i-self._firstheaderline
1505 1505 endx = self.scrsizex
1506 1506 if i: # not the first level
1507 1507 msg = " (%d/%d" % (self.levels[i-1].cury, len(self.levels[i-1].items))
1508 1508 if not self.levels[i-1].exhausted:
1509 1509 msg += "+"
1510 1510 msg += ") "
1511 1511 endx -= len(msg)+1
1512 1512 posx += self.addstr(posy, posx, 0, endx, " ibrowse #%d: " % i, self.style_objheadertext)
1513 1513 for (style, text) in lv.header:
1514 1514 posx += self.addstr(posy, posx, 0, endx, text, self.style_objheaderobject)
1515 1515 if posx >= endx:
1516 1516 break
1517 1517 if i:
1518 1518 posx += self.addstr(posy, posx, 0, self.scrsizex, msg, self.style_objheadernumber)
1519 1519 posx += self.addchr(posy, posx, 0, self.scrsizex, " ", self.scrsizex-posx, self.style_objheadernumber)
1520 1520
1521 1521 if not level.items:
1522 1522 self.addchr(self._headerlines, 0, 0, self.scrsizex, " ", self.scrsizex, self.style_colheader)
1523 1523 self.addstr(self._headerlines+1, 0, 0, self.scrsizex, " <empty>", astyle.style_error)
1524 1524 scr.clrtobot()
1525 1525 else:
1526 1526 # Paint column headers
1527 1527 scr.move(self._headerlines, 0)
1528 1528 scr.addstr(" %*s " % (level.numbersizex, "#"), self.getstyle(self.style_colheader))
1529 1529 scr.addstr(self.headersepchar, self.getstyle(self.style_colheadersep))
1530 1530 begx = level.numbersizex+3
1531 1531 posx = begx-level.datastartx
1532 1532 for attr in level.displayattrs:
1533 1533 attrname = attr.name()
1534 1534 cwidth = level.colwidths[attr]
1535 1535 header = attrname.ljust(cwidth)
1536 1536 if attr is level.displayattr[1]:
1537 1537 style = self.style_colheaderhere
1538 1538 else:
1539 1539 style = self.style_colheader
1540 1540 posx += self.addstr(self._headerlines, posx, begx, self.scrsizex, header, style)
1541 1541 posx += self.addstr(self._headerlines, posx, begx, self.scrsizex, self.headersepchar, self.style_colheadersep)
1542 1542 if posx >= self.scrsizex:
1543 1543 break
1544 1544 else:
1545 1545 scr.addstr(" "*(self.scrsizex-posx), self.getstyle(self.style_colheader))
1546 1546
1547 1547 # Paint rows
1548 1548 posy = self._headerlines+1+level.datastarty
1549 1549 for i in xrange(level.datastarty, min(level.datastarty+level.mainsizey, len(level.items))):
1550 1550 cache = level.items[i]
1551 1551 if i == level.cury:
1552 1552 style = self.style_numberhere
1553 1553 else:
1554 1554 style = self.style_number
1555 1555
1556 1556 posy = self._headerlines+1+i-level.datastarty
1557 1557 posx = begx-level.datastartx
1558 1558
1559 1559 scr.move(posy, 0)
1560 1560 scr.addstr(" %*d%s" % (level.numbersizex, i, " !"[cache.marked]), self.getstyle(style))
1561 1561 scr.addstr(self.headersepchar, self.getstyle(self.style_sep))
1562 1562
1563 1563 for attrname in level.displayattrs:
1564 1564 cwidth = level.colwidths[attrname]
1565 1565 try:
1566 1566 (align, length, parts) = level.displayrows[i-level.datastarty][attrname]
1567 1567 except KeyError:
1568 1568 align = 2
1569 1569 style = astyle.style_nodata
1570 1570 if i == level.cury:
1571 1571 style = self.getstylehere(style)
1572 1572 padstyle = self.style_datapad
1573 1573 sepstyle = self.style_sep
1574 1574 if i == level.cury:
1575 1575 padstyle = self.getstylehere(padstyle)
1576 1576 sepstyle = self.getstylehere(sepstyle)
1577 1577 if align == 2:
1578 1578 posx += self.addchr(posy, posx, begx, self.scrsizex, self.nodatachar, cwidth, style)
1579 1579 else:
1580 1580 if align == 1:
1581 1581 posx += self.addchr(posy, posx, begx, self.scrsizex, self.datapadchar, cwidth-length, padstyle)
1582 1582 elif align == 0:
1583 1583 pad1 = (cwidth-length)//2
1584 1584 pad2 = cwidth-length-len(pad1)
1585 1585 posx += self.addchr(posy, posx, begx, self.scrsizex, self.datapadchar, pad1, padstyle)
1586 1586 for (style, text) in parts:
1587 1587 if i == level.cury:
1588 1588 style = self.getstylehere(style)
1589 1589 posx += self.addstr(posy, posx, begx, self.scrsizex, text, style)
1590 1590 if posx >= self.scrsizex:
1591 1591 break
1592 1592 if align == -1:
1593 1593 posx += self.addchr(posy, posx, begx, self.scrsizex, self.datapadchar, cwidth-length, padstyle)
1594 1594 elif align == 0:
1595 1595 posx += self.addchr(posy, posx, begx, self.scrsizex, self.datapadchar, pad2, padstyle)
1596 1596 posx += self.addstr(posy, posx, begx, self.scrsizex, self.datasepchar, sepstyle)
1597 1597 else:
1598 1598 scr.clrtoeol()
1599 1599
1600 1600 # Add blank row headers for the rest of the screen
1601 1601 for posy in xrange(posy+1, self.scrsizey-2):
1602 1602 scr.addstr(posy, 0, " " * (level.numbersizex+2), self.getstyle(self.style_colheader))
1603 1603 scr.clrtoeol()
1604 1604
1605 1605 posy = self.scrsizey-footery
1606 1606 # Display footer
1607 1607 scr.addstr(posy, 0, " "*self.scrsizex, self.getstyle(self.style_footer))
1608 1608
1609 1609 if level.exhausted:
1610 1610 flag = ""
1611 1611 else:
1612 1612 flag = "+"
1613 1613
1614 1614 endx = self.scrsizex-len(helpmsg)-1
1615 1615 scr.addstr(posy, endx, helpmsg, self.getstyle(self.style_footer))
1616 1616
1617 1617 posx = 0
1618 1618 msg = " %d%s objects (%d marked): " % (len(level.items), flag, level.marked)
1619 1619 posx += self.addstr(posy, posx, 0, endx, msg, self.style_footer)
1620 1620 try:
1621 1621 item = level.items[level.cury].item
1622 1622 except IndexError: # empty
1623 1623 pass
1624 1624 else:
1625 1625 for (nostyle, text) in ipipe.xrepr(item, "footer"):
1626 1626 if not isinstance(nostyle, int):
1627 1627 posx += self.addstr(posy, posx, 0, endx, text, self.style_footer)
1628 1628 if posx >= endx:
1629 1629 break
1630 1630
1631 1631 attrstyle = [(astyle.style_default, "no attribute")]
1632 1632 attr = level.displayattr[1]
1633 1633 if attr is not ipipe.noitem and not isinstance(attr, ipipe.SelfDescriptor):
1634 1634 posx += self.addstr(posy, posx, 0, endx, " | ", self.style_footer)
1635 1635 posx += self.addstr(posy, posx, 0, endx, attr.name(), self.style_footer)
1636 1636 posx += self.addstr(posy, posx, 0, endx, ": ", self.style_footer)
1637 1637 try:
1638 1638 value = attr.value(item)
1639 1639 except (SystemExit, KeyboardInterrupt):
1640 1640 raise
1641 except Exception, exc:
1641 except Exception as exc:
1642 1642 value = exc
1643 1643 if value is not ipipe.noitem:
1644 1644 attrstyle = ipipe.xrepr(value, "footer")
1645 1645 for (nostyle, text) in attrstyle:
1646 1646 if not isinstance(nostyle, int):
1647 1647 posx += self.addstr(posy, posx, 0, endx, text, self.style_footer)
1648 1648 if posx >= endx:
1649 1649 break
1650 1650
1651 1651 try:
1652 1652 # Display input prompt
1653 1653 if self.mode in self.prompts:
1654 1654 history = self.prompts[self.mode]
1655 1655 posx = 0
1656 1656 posy = self.scrsizey-1
1657 1657 posx += self.addstr(posy, posx, 0, endx, history.prompt, astyle.style_default)
1658 1658 posx += self.addstr(posy, posx, 0, endx, " [", astyle.style_default)
1659 1659 if history.cury==-1:
1660 1660 text = "new"
1661 1661 else:
1662 1662 text = str(history.cury+1)
1663 1663 posx += self.addstr(posy, posx, 0, endx, text, astyle.style_type_number)
1664 1664 if history.history:
1665 1665 posx += self.addstr(posy, posx, 0, endx, "/", astyle.style_default)
1666 1666 posx += self.addstr(posy, posx, 0, endx, str(len(history.history)), astyle.style_type_number)
1667 1667 posx += self.addstr(posy, posx, 0, endx, "]: ", astyle.style_default)
1668 1668 inputstartx = posx
1669 1669 posx += self.addstr(posy, posx, 0, endx, history.input, astyle.style_default)
1670 1670 # Display report
1671 1671 else:
1672 1672 if self._report is not None:
1673 1673 if isinstance(self._report, Exception):
1674 1674 style = self.getstyle(astyle.style_error)
1675 1675 if self._report.__class__.__module__ == "exceptions":
1676 1676 msg = "%s: %s" % \
1677 1677 (self._report.__class__.__name__, self._report)
1678 1678 else:
1679 1679 msg = "%s.%s: %s" % \
1680 1680 (self._report.__class__.__module__,
1681 1681 self._report.__class__.__name__, self._report)
1682 1682 else:
1683 1683 style = self.getstyle(self.style_report)
1684 1684 msg = self._report
1685 1685 scr.addstr(self.scrsizey-1, 0, msg[:self.scrsizex], style)
1686 1686 self._report = None
1687 1687 else:
1688 1688 scr.move(self.scrsizey-1, 0)
1689 1689 except curses.error:
1690 1690 # Protect against errors from writing to the last line
1691 1691 pass
1692 1692 scr.clrtoeol()
1693 1693
1694 1694 # Position cursor
1695 1695 if self.mode in self.prompts:
1696 1696 history = self.prompts[self.mode]
1697 1697 scr.move(self.scrsizey-1, inputstartx+history.curx)
1698 1698 else:
1699 1699 scr.move(
1700 1700 1+self._headerlines+level.cury-level.datastarty,
1701 1701 level.numbersizex+3+level.curx-level.datastartx
1702 1702 )
1703 1703 scr.refresh()
1704 1704
1705 1705 # Check keyboard
1706 1706 while True:
1707 1707 c = scr.getch()
1708 1708 if self.resized:
1709 1709 size = fcntl.ioctl(0, tty.TIOCGWINSZ, "12345678")
1710 1710 size = struct.unpack("4H", size)
1711 1711 oldsize = scr.getmaxyx()
1712 1712 scr.erase()
1713 1713 curses.resize_term(size[0], size[1])
1714 1714 newsize = scr.getmaxyx()
1715 1715 scr.erase()
1716 1716 for l in self.levels:
1717 1717 l.mainsizey += newsize[0]-oldsize[0]
1718 1718 l.moveto(l.curx, l.cury, refresh=True)
1719 1719 scr.refresh()
1720 1720 self.resized = False
1721 1721 break # Redisplay
1722 1722 if self.mode in self.prompts:
1723 1723 if self.prompts[self.mode].handlekey(self, c):
1724 1724 break # Redisplay
1725 1725 else:
1726 1726 # if no key is pressed slow down and beep again
1727 1727 if c == -1:
1728 1728 self.stepx = 1.
1729 1729 self.stepy = 1.
1730 1730 self._dobeep = True
1731 1731 else:
1732 1732 # if a different key was pressed slow down and beep too
1733 1733 if c != lastc:
1734 1734 lastc = c
1735 1735 self.stepx = 1.
1736 1736 self.stepy = 1.
1737 1737 self._dobeep = True
1738 1738 cmdname = self.keymap.get(c, None)
1739 1739 if cmdname is None:
1740 1740 self.report(
1741 1741 UnassignedKeyError("Unassigned key %s" %
1742 1742 self.keylabel(c)))
1743 1743 else:
1744 1744 cmdfunc = getattr(self, "cmd_%s" % cmdname, None)
1745 1745 if cmdfunc is None:
1746 1746 self.report(
1747 1747 UnknownCommandError("Unknown command %r" %
1748 1748 (cmdname,)))
1749 1749 elif cmdfunc():
1750 1750 returnvalue = self.returnvalue
1751 1751 self.returnvalue = None
1752 1752 return returnvalue
1753 1753 self.stepx = self.nextstepx(self.stepx)
1754 1754 self.stepy = self.nextstepy(self.stepy)
1755 1755 curses.flushinp() # get rid of type ahead
1756 1756 break # Redisplay
1757 1757 self.scr = None
1758 1758
1759 1759 def display(self):
1760 1760 if hasattr(curses, "resize_term") and hasattr(signal, 'SIGWINCH'):
1761 1761 oldhandler = signal.signal(signal.SIGWINCH, self.sigwinchhandler)
1762 1762 try:
1763 1763 return curses.wrapper(self._dodisplay)
1764 1764 finally:
1765 1765 signal.signal(signal.SIGWINCH, oldhandler)
1766 1766 else:
1767 1767 return curses.wrapper(self._dodisplay)
@@ -1,1126 +1,1126 b''
1 1 # -*- coding: iso-8859-1 -*-
2 2
3 3 import ipipe, os, webbrowser, urllib
4 4 from IPython.core import ipapi
5 5 import wx
6 6 import wx.grid, wx.html
7 7
8 8 try:
9 9 sorted
10 10 except NameError:
11 11 from ipipe import sorted
12 12 try:
13 13 set
14 14 except:
15 15 from sets import Set as set
16 16
17 17
18 18 __all__ = ["igrid"]
19 19
20 20
21 21 help = """
22 22 <?xml version='1.0' encoding='iso-8859-1'?>
23 23 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
24 24 <html>
25 25 <head>
26 26 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
27 27 <link rel="stylesheet" href="igrid_help.css" type="text/css" />
28 28 <title>igrid help</title>
29 29 </head>
30 30 <body>
31 31 <h1>igrid help</h1>
32 32
33 33
34 34 <h2>Commands</h2>
35 35
36 36
37 37 <h3>pick (P)</h3>
38 38 <p>Pick the whole row (object is available as "_")</p>
39 39
40 40 <h3>pickattr (Shift-P)</h3>
41 41 <p>Pick the attribute under the cursor</p>
42 42
43 43 <h3>pickallattrs (Shift-C)</h3>
44 44 <p>Pick the complete column under the cursor (i.e. the attribute under the
45 45 cursor) from all currently fetched objects. These attributes will be returned
46 46 as a list.</p>
47 47
48 48 <h3>pickinput (I)</h3>
49 49 <p>Pick the current row as next input line in IPython. Additionally the row is stored as "_"</p>
50 50
51 51 <h3>pickinputattr (Shift-I)</h3>
52 52 <p>Pick the attribute under the cursor as next input line in IPython. Additionally the row is stored as "_"</p>
53 53
54 54 <h3>enter (E)</h3>
55 55 <p>Enter the object under the cursor. (what this mean depends on the object
56 56 itself, i.e. how it implements iteration). This opens a new browser 'level'.</p>
57 57
58 58 <h3>enterattr (Shift-E)</h3>
59 59 <p>Enter the attribute under the cursor.</p>
60 60
61 61 <h3>detail (D)</h3>
62 62 <p>Show a detail view of the object under the cursor. This shows the name,
63 63 type, doc string and value of the object attributes (and it might show more
64 64 attributes than in the list view, depending on the object).</p>
65 65
66 66 <h3>detailattr (Shift-D)</h3>
67 67 <p>Show a detail view of the attribute under the cursor.</p>
68 68
69 69 <h3>pickrows (M)</h3>
70 70 <p>Pick multiple selected rows (M)</p>
71 71
72 72 <h3>pickrowsattr (CTRL-M)</h3>
73 73 <p>From multiple selected rows pick the cells matching the attribute the cursor is in (CTRL-M)</p>
74 74
75 75 <h3>find (CTRL-F)</h3>
76 76 <p>Find text</p>
77 77
78 78 <h3>find_expression (CTRL-Shift-F)</h3>
79 79 <p>Find entries matching an expression</p>
80 80
81 81 <h3>find_next (F3)</h3>
82 82 <p>Find next occurrence</p>
83 83
84 84 <h3>find_previous (Shift-F3)</h3>
85 85 <p>Find previous occurrence</p>
86 86
87 87 <h3>sortattrasc (V)</h3>
88 88 <p>Sort the objects (in ascending order) using the attribute under the cursor as the sort key.</p>
89 89
90 90 <h3>sortattrdesc (Shift-V)</h3>
91 91 <p>Sort the objects (in descending order) using the attribute under the cursor as the sort key.</p>
92 92
93 93 <h3>refresh_once (R, F5)</h3>
94 94 <p>Refreshes the display by restarting the iterator</p>
95 95
96 96 <h3>refresh_every_second</h3>
97 97 <p>Refreshes the display by restarting the iterator every second until stopped by stop_refresh.</p>
98 98
99 99 <h3>refresh_interval</h3>
100 100 <p>Refreshes the display by restarting the iterator every X ms (X is a custom interval set by the user) until stopped by stop_refresh.</p>
101 101
102 102 <h3>stop_refresh</h3>
103 103 <p>Stops all refresh timers.</p>
104 104
105 105 <h3>leave (Backspace, DEL, X)</h3>
106 106 <p>Close current tab (and all the tabs to the right of the current one).</h3>
107 107
108 108 <h3>quit (ESC,Q)</h3>
109 109 <p>Quit igrid and return to the IPython prompt.</p>
110 110
111 111
112 112 <h2>Navigation</h2>
113 113
114 114
115 115 <h3>Jump to the last column of the current row (END, CTRL-E, CTRL-Right)</h3>
116 116
117 117 <h3>Jump to the first column of the current row (HOME, CTRL-A, CTRL-Left)</h3>
118 118
119 119 <h3>Move the cursor one column to the left (&lt;)</h3>
120 120
121 121 <h3>Move the cursor one column to the right (&gt;)</h3>
122 122
123 123 <h3>Jump to the first row in the current column (CTRL-Up)</h3>
124 124
125 125 <h3>Jump to the last row in the current column (CTRL-Down)</h3>
126 126
127 127 </body>
128 128 </html>
129 129
130 130 """
131 131
132 132
133 133 class IGridRenderer(wx.grid.PyGridCellRenderer):
134 134 """
135 135 This is a custom renderer for our IGridGrid
136 136 """
137 137 def __init__(self, table):
138 138 self.maxchars = 200
139 139 self.table = table
140 140 self.colormap = (
141 141 ( 0, 0, 0),
142 142 (174, 0, 0),
143 143 ( 0, 174, 0),
144 144 (174, 174, 0),
145 145 ( 0, 0, 174),
146 146 (174, 0, 174),
147 147 ( 0, 174, 174),
148 148 ( 64, 64, 64)
149 149 )
150 150
151 151 wx.grid.PyGridCellRenderer.__init__(self)
152 152
153 153 def _getvalue(self, row, col):
154 154 try:
155 155 value = self.table._displayattrs[col].value(self.table.items[row])
156 156 (align, width, text) = ipipe.xformat(value, "cell", self.maxchars)
157 except Exception, exc:
157 except Exception as exc:
158 158 (align, width, text) = ipipe.xformat(exc, "cell", self.maxchars)
159 159 return (align, text)
160 160
161 161 def GetBestSize(self, grid, attr, dc, row, col):
162 162 text = grid.GetCellValue(row, col)
163 163 (align, text) = self._getvalue(row, col)
164 164 dc.SetFont(attr.GetFont())
165 165 (w, h) = dc.GetTextExtent(str(text))
166 166 return wx.Size(min(w+2, 600), h+2) # add border
167 167
168 168 def Draw(self, grid, attr, dc, rect, row, col, isSelected):
169 169 """
170 170 Takes care of drawing everything in the cell; aligns the text
171 171 """
172 172 text = grid.GetCellValue(row, col)
173 173 (align, text) = self._getvalue(row, col)
174 174 if isSelected:
175 175 bg = grid.GetSelectionBackground()
176 176 else:
177 177 bg = ["white", (240, 240, 240)][row%2]
178 178 dc.SetTextBackground(bg)
179 179 dc.SetBrush(wx.Brush(bg, wx.SOLID))
180 180 dc.SetPen(wx.TRANSPARENT_PEN)
181 181 dc.SetFont(attr.GetFont())
182 182 dc.DrawRectangleRect(rect)
183 183 dc.SetClippingRect(rect)
184 184 # Format the text
185 185 if align == -1: # left alignment
186 186 (width, height) = dc.GetTextExtent(str(text))
187 187 x = rect[0]+1
188 188 y = rect[1]+0.5*(rect[3]-height)
189 189
190 190 for (style, part) in text:
191 191 if isSelected:
192 192 fg = grid.GetSelectionForeground()
193 193 else:
194 194 fg = self.colormap[style.fg]
195 195 dc.SetTextForeground(fg)
196 196 (w, h) = dc.GetTextExtent(part)
197 197 dc.DrawText(part, x, y)
198 198 x += w
199 199 elif align == 0: # center alignment
200 200 (width, height) = dc.GetTextExtent(str(text))
201 201 x = rect[0]+0.5*(rect[2]-width)
202 202 y = rect[1]+0.5*(rect[3]-height)
203 203 for (style, part) in text:
204 204 if isSelected:
205 205 fg = grid.GetSelectionForeground()
206 206 else:
207 207 fg = self.colormap[style.fg]
208 208 dc.SetTextForeground(fg)
209 209 (w, h) = dc.GetTextExtent(part)
210 210 dc.DrawText(part, x, y)
211 211 x += w
212 212 else: # right alignment
213 213 (width, height) = dc.GetTextExtent(str(text))
214 214 x = rect[0]+rect[2]-1
215 215 y = rect[1]+0.5*(rect[3]-height)
216 216 for (style, part) in reversed(text):
217 217 (w, h) = dc.GetTextExtent(part)
218 218 x -= w
219 219 if isSelected:
220 220 fg = grid.GetSelectionForeground()
221 221 else:
222 222 fg = self.colormap[style.fg]
223 223 dc.SetTextForeground(fg)
224 224 dc.DrawText(part, x, y)
225 225 dc.DestroyClippingRegion()
226 226
227 227 def Clone(self):
228 228 return IGridRenderer(self.table)
229 229
230 230
231 231 class IGridTable(wx.grid.PyGridTableBase):
232 232 # The data table for the ``IGridGrid``. Some dirty tricks were used here:
233 233 # ``GetValue()`` does not get any values (or at least it does not return
234 234 # anything, accessing the values is done by the renderer)
235 235 # but rather tries to fetch the objects which were requested into the table.
236 236 # General behaviour is: Fetch the first X objects. If the user scrolls down
237 237 # to the last object another bunch of X objects is fetched (if possible)
238 238 def __init__(self, input, fontsize, *attrs):
239 239 wx.grid.PyGridTableBase.__init__(self)
240 240 self.input = input
241 241 self.iterator = ipipe.xiter(input)
242 242 self.items = []
243 243 self.attrs = [ipipe.upgradexattr(attr) for attr in attrs]
244 244 self._displayattrs = self.attrs[:]
245 245 self._displayattrset = set(self.attrs)
246 246 self.fontsize = fontsize
247 247 self._fetch(1)
248 248 self.timer = wx.Timer()
249 249 self.timer.Bind(wx.EVT_TIMER, self.refresh_content)
250 250
251 251 def GetAttr(self, *args):
252 252 attr = wx.grid.GridCellAttr()
253 253 attr.SetFont(wx.Font(self.fontsize, wx.TELETYPE, wx.NORMAL, wx.NORMAL))
254 254 return attr
255 255
256 256 def GetNumberRows(self):
257 257 return len(self.items)
258 258
259 259 def GetNumberCols(self):
260 260 return len(self._displayattrs)
261 261
262 262 def GetColLabelValue(self, col):
263 263 if col < len(self._displayattrs):
264 264 return self._displayattrs[col].name()
265 265 else:
266 266 return ""
267 267
268 268 def GetRowLabelValue(self, row):
269 269 return str(row)
270 270
271 271 def IsEmptyCell(self, row, col):
272 272 return False
273 273
274 274 def _append(self, item):
275 275 self.items.append(item)
276 276 # Nothing to do if the set of attributes has been fixed by the user
277 277 if not self.attrs:
278 278 for attr in ipipe.xattrs(item):
279 279 attr = ipipe.upgradexattr(attr)
280 280 if attr not in self._displayattrset:
281 281 self._displayattrs.append(attr)
282 282 self._displayattrset.add(attr)
283 283
284 284 def _fetch(self, count):
285 285 # Try to fill ``self.items`` with at least ``count`` objects.
286 286 have = len(self.items)
287 287 while self.iterator is not None and have < count:
288 288 try:
289 289 item = self.iterator.next()
290 290 except StopIteration:
291 291 self.iterator = None
292 292 break
293 293 except (KeyboardInterrupt, SystemExit):
294 294 raise
295 except Exception, exc:
295 except Exception as exc:
296 296 have += 1
297 297 self._append(exc)
298 298 self.iterator = None
299 299 break
300 300 else:
301 301 have += 1
302 302 self._append(item)
303 303
304 304 def GetValue(self, row, col):
305 305 # some kind of dummy-function: does not return anything but "";
306 306 # (The value isn't use anyway)
307 307 # its main task is to trigger the fetch of new objects
308 308 sizing_needed = False
309 309 had_cols = len(self._displayattrs)
310 310 had_rows = len(self.items)
311 311 if row == had_rows - 1 and self.iterator is not None:
312 312 self._fetch(row + 20)
313 313 sizing_needed = True
314 314 have_rows = len(self.items)
315 315 have_cols = len(self._displayattrs)
316 316 if have_rows > had_rows:
317 317 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, have_rows - had_rows)
318 318 self.GetView().ProcessTableMessage(msg)
319 319 sizing_needed = True
320 320 if row >= have_rows:
321 321 return ""
322 322 if have_cols != had_cols:
323 323 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED, have_cols - had_cols)
324 324 self.GetView().ProcessTableMessage(msg)
325 325 sizing_needed = True
326 326 if sizing_needed:
327 327 self.GetView().AutoSizeColumns(False)
328 328 return ""
329 329
330 330 def SetValue(self, row, col, value):
331 331 pass
332 332
333 333 def refresh_content(self, event):
334 334 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, 0, self.GetNumberRows())
335 335 self.GetView().ProcessTableMessage(msg)
336 336 self.iterator = ipipe.xiter(self.input)
337 337 self.items = []
338 338 self.attrs = [] # _append will calculate new displayattrs
339 339 self._fetch(1) # fetch one...
340 340 if self.items:
341 341 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, 1)
342 342 self.GetView().ProcessTableMessage(msg)
343 343 self.GetValue(0, 0) # and trigger "fetch next 20"
344 344 item = self.items[0]
345 345 self.GetView().AutoSizeColumns(False)
346 346 panel = self.GetView().GetParent()
347 347 nb = panel.GetParent()
348 348 current = nb.GetSelection()
349 349 if nb.GetPage(current) == panel:
350 350 self.GetView().set_footer(item)
351 351
352 352 class IGridGrid(wx.grid.Grid):
353 353 # The actual grid
354 354 # all methods for selecting/sorting/picking/... data are implemented here
355 355 def __init__(self, panel, input, *attrs):
356 356 wx.grid.Grid.__init__(self, panel)
357 357 fontsize = 9
358 358 self.input = input
359 359 self.table = IGridTable(self.input, fontsize, *attrs)
360 360 self.SetTable(self.table, True)
361 361 self.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
362 362 self.SetDefaultRenderer(IGridRenderer(self.table))
363 363 self.EnableEditing(False)
364 364 self.Bind(wx.EVT_KEY_DOWN, self.key_pressed)
365 365 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.cell_doubleclicked)
366 366 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.cell_leftclicked)
367 367 self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_DCLICK, self.label_doubleclicked)
368 368 self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_label_leftclick)
369 369 self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self._on_selected_range)
370 370 self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self._on_selected_cell)
371 371 self.current_selection = set()
372 372 self.maxchars = 200
373 373
374 374 def on_label_leftclick(self, event):
375 375 event.Skip()
376 376
377 377 def error_output(self, text):
378 378 wx.Bell()
379 379 frame = self.GetParent().GetParent().GetParent()
380 380 frame.SetStatusText(str(text))
381 381
382 382 def _on_selected_range(self, event):
383 383 # Internal update to the selection tracking lists
384 384 if event.Selecting():
385 385 # adding to the list...
386 386 self.current_selection.update(xrange(event.GetTopRow(), event.GetBottomRow()+1))
387 387 else:
388 388 # removal from list
389 389 for index in xrange(event.GetTopRow(), event.GetBottomRow()+1):
390 390 self.current_selection.discard(index)
391 391 event.Skip()
392 392
393 393 def _on_selected_cell(self, event):
394 394 # Internal update to the selection tracking list
395 395 self.current_selection = set([event.GetRow()])
396 396 event.Skip()
397 397
398 398 def sort(self, key, reverse=False):
399 399 """
400 400 Sort the current list of items using the key function ``key``. If
401 401 ``reverse`` is true the sort order is reversed.
402 402 """
403 403 row = self.GetGridCursorRow()
404 404 col = self.GetGridCursorCol()
405 405 curitem = self.table.items[row] # Remember where the cursor is now
406 406 # Sort items
407 407 def realkey(item):
408 408 try:
409 409 return key(item)
410 410 except (KeyboardInterrupt, SystemExit):
411 411 raise
412 412 except Exception:
413 413 return None
414 414 try:
415 415 self.table.items = ipipe.deque(sorted(self.table.items, key=realkey, reverse=reverse))
416 except TypeError, exc:
416 except TypeError as exc:
417 417 self.error_output("Exception encountered: %s" % exc)
418 418 return
419 419 # Find out where the object under the cursor went
420 420 for (i, item) in enumerate(self.table.items):
421 421 if item is curitem:
422 422 self.SetGridCursor(i,col)
423 423 self.MakeCellVisible(i,col)
424 424 self.Refresh()
425 425
426 426 def sortattrasc(self):
427 427 """
428 428 Sort in ascending order; sorting criteria is the current attribute
429 429 """
430 430 col = self.GetGridCursorCol()
431 431 attr = self.table._displayattrs[col]
432 432 frame = self.GetParent().GetParent().GetParent()
433 433 if attr is ipipe.noitem:
434 434 self.error_output("no column under cursor")
435 435 return
436 436 frame.SetStatusText("sort by %s (ascending)" % attr.name())
437 437 def key(item):
438 438 try:
439 439 return attr.value(item)
440 440 except (KeyboardInterrupt, SystemExit):
441 441 raise
442 442 except Exception:
443 443 return None
444 444 self.sort(key)
445 445
446 446 def sortattrdesc(self):
447 447 """
448 448 Sort in descending order; sorting criteria is the current attribute
449 449 """
450 450 col = self.GetGridCursorCol()
451 451 attr = self.table._displayattrs[col]
452 452 frame = self.GetParent().GetParent().GetParent()
453 453 if attr is ipipe.noitem:
454 454 self.error_output("no column under cursor")
455 455 return
456 456 frame.SetStatusText("sort by %s (descending)" % attr.name())
457 457 def key(item):
458 458 try:
459 459 return attr.value(item)
460 460 except (KeyboardInterrupt, SystemExit):
461 461 raise
462 462 except Exception:
463 463 return None
464 464 self.sort(key, reverse=True)
465 465
466 466 def label_doubleclicked(self, event):
467 467 row = event.GetRow()
468 468 col = event.GetCol()
469 469 if col == -1:
470 470 self.enter(row)
471 471
472 472 def _getvalue(self, row, col):
473 473 """
474 474 Gets the text which is displayed at ``(row, col)``
475 475 """
476 476 try:
477 477 value = self.table._displayattrs[col].value(self.table.items[row])
478 478 (align, width, text) = ipipe.xformat(value, "cell", self.maxchars)
479 479 except IndexError:
480 480 raise IndexError
481 except Exception, exc:
481 except Exception as exc:
482 482 (align, width, text) = ipipe.xformat(exc, "cell", self.maxchars)
483 483 return text
484 484
485 485 def searchexpression(self, searchexp, startrow=None, search_forward=True ):
486 486 """
487 487 Find by expression
488 488 """
489 489 frame = self.GetParent().GetParent().GetParent()
490 490 if searchexp:
491 491 if search_forward:
492 492 if not startrow:
493 493 row = self.GetGridCursorRow()+1
494 494 else:
495 495 row = startrow + 1
496 496 while True:
497 497 try:
498 498 foo = self.table.GetValue(row, 0)
499 499 item = self.table.items[row]
500 500 try:
501 501 globals = ipipe.getglobals(None)
502 502 if eval(searchexp, globals, ipipe.AttrNamespace(item)):
503 503 self.SetGridCursor(row, 0) # found something
504 504 self.MakeCellVisible(row, 0)
505 505 break
506 506 except (KeyboardInterrupt, SystemExit):
507 507 raise
508 except Exception, exc:
508 except Exception as exc:
509 509 frame.SetStatusText(str(exc))
510 510 wx.Bell()
511 511 break # break on error
512 512 except IndexError:
513 513 return
514 514 row += 1
515 515 else:
516 516 if not startrow:
517 517 row = self.GetGridCursorRow() - 1
518 518 else:
519 519 row = startrow - 1
520 520 while True:
521 521 try:
522 522 foo = self.table.GetValue(row, 0)
523 523 item = self.table.items[row]
524 524 try:
525 525 globals = ipipe.getglobals(None)
526 526 if eval(searchexp, globals, ipipe.AttrNamespace(item)):
527 527 self.SetGridCursor(row, 0) # found something
528 528 self.MakeCellVisible(row, 0)
529 529 break
530 530 except (KeyboardInterrupt, SystemExit):
531 531 raise
532 except Exception, exc:
532 except Exception as exc:
533 533 frame.SetStatusText(str(exc))
534 534 wx.Bell()
535 535 break # break on error
536 536 except IndexError:
537 537 return
538 538 row -= 1
539 539
540 540
541 541 def search(self, searchtext, startrow=None, startcol=None, search_forward=True):
542 542 """
543 543 search for ``searchtext``, starting in ``(startrow, startcol)``;
544 544 if ``search_forward`` is true the direction is "forward"
545 545 """
546 546 searchtext = searchtext.lower()
547 547 if search_forward:
548 548 if startrow is not None and startcol is not None:
549 549 row = startrow
550 550 else:
551 551 startcol = self.GetGridCursorCol() + 1
552 552 row = self.GetGridCursorRow()
553 553 if startcol >= self.GetNumberCols():
554 554 startcol = 0
555 555 row += 1
556 556 while True:
557 557 for col in xrange(startcol, self.table.GetNumberCols()):
558 558 try:
559 559 foo = self.table.GetValue(row, col)
560 560 text = self._getvalue(row, col)
561 561 if searchtext in text.string().lower():
562 562 self.SetGridCursor(row, col)
563 563 self.MakeCellVisible(row, col)
564 564 return
565 565 except IndexError:
566 566 return
567 567 startcol = 0
568 568 row += 1
569 569 else:
570 570 if startrow is not None and startcol is not None:
571 571 row = startrow
572 572 else:
573 573 startcol = self.GetGridCursorCol() - 1
574 574 row = self.GetGridCursorRow()
575 575 if startcol < 0:
576 576 startcol = self.GetNumberCols() - 1
577 577 row -= 1
578 578 while True:
579 579 for col in xrange(startcol, -1, -1):
580 580 try:
581 581 foo = self.table.GetValue(row, col)
582 582 text = self._getvalue(row, col)
583 583 if searchtext in text.string().lower():
584 584 self.SetGridCursor(row, col)
585 585 self.MakeCellVisible(row, col)
586 586 return
587 587 except IndexError:
588 588 return
589 589 startcol = self.table.GetNumberCols()-1
590 590 row -= 1
591 591
592 592 def key_pressed(self, event):
593 593 """
594 594 Maps pressed keys to functions
595 595 """
596 596 frame = self.GetParent().GetParent().GetParent()
597 597 frame.SetStatusText("")
598 598 sh = event.ShiftDown()
599 599 ctrl = event.ControlDown()
600 600
601 601 keycode = event.GetKeyCode()
602 602 if keycode == ord("P"):
603 603 row = self.GetGridCursorRow()
604 604 if sh:
605 605 col = self.GetGridCursorCol()
606 606 self.pickattr(row, col)
607 607 else:
608 608 self.pick(row)
609 609 elif keycode == ord("M"):
610 610 if ctrl:
611 611 col = self.GetGridCursorCol()
612 612 self.pickrowsattr(sorted(self.current_selection), col)
613 613 else:
614 614 self.pickrows(sorted(self.current_selection))
615 615 elif keycode in (wx.WXK_BACK, wx.WXK_DELETE, ord("X")) and not (ctrl or sh):
616 616 self.delete_current_notebook()
617 617 elif keycode in (ord("E"), ord("\r")):
618 618 row = self.GetGridCursorRow()
619 619 if sh:
620 620 col = self.GetGridCursorCol()
621 621 self.enterattr(row, col)
622 622 else:
623 623 self.enter(row)
624 624 elif keycode == ord("E") and ctrl:
625 625 row = self.GetGridCursorRow()
626 626 self.SetGridCursor(row, self.GetNumberCols()-1)
627 627 elif keycode == wx.WXK_HOME or (keycode == ord("A") and ctrl):
628 628 row = self.GetGridCursorRow()
629 629 self.SetGridCursor(row, 0)
630 630 elif keycode == ord("C") and sh:
631 631 col = self.GetGridCursorCol()
632 632 attr = self.table._displayattrs[col]
633 633 result = []
634 634 for i in xrange(self.GetNumberRows()):
635 635 result.append(self.table._displayattrs[col].value(self.table.items[i]))
636 636 self.quit(result)
637 637 elif keycode in (wx.WXK_ESCAPE, ord("Q")) and not (ctrl or sh):
638 638 self.quit()
639 639 elif keycode == ord("<"):
640 640 row = self.GetGridCursorRow()
641 641 col = self.GetGridCursorCol()
642 642 if not event.ShiftDown():
643 643 newcol = col - 1
644 644 if newcol >= 0:
645 645 self.SetGridCursor(row, col - 1)
646 646 else:
647 647 newcol = col + 1
648 648 if newcol < self.GetNumberCols():
649 649 self.SetGridCursor(row, col + 1)
650 650 elif keycode == ord("D"):
651 651 col = self.GetGridCursorCol()
652 652 row = self.GetGridCursorRow()
653 653 if not sh:
654 654 self.detail(row, col)
655 655 else:
656 656 self.detail_attr(row, col)
657 657 elif keycode == ord("F") and ctrl:
658 658 if sh:
659 659 frame.enter_searchexpression(event)
660 660 else:
661 661 frame.enter_searchtext(event)
662 662 elif keycode == wx.WXK_F3:
663 663 if sh:
664 664 frame.find_previous(event)
665 665 else:
666 666 frame.find_next(event)
667 667 elif keycode == ord("V"):
668 668 if sh:
669 669 self.sortattrdesc()
670 670 else:
671 671 self.sortattrasc()
672 672 elif keycode == wx.WXK_DOWN:
673 673 row = self.GetGridCursorRow()
674 674 try:
675 675 item = self.table.items[row+1]
676 676 except IndexError:
677 677 item = self.table.items[row]
678 678 self.set_footer(item)
679 679 event.Skip()
680 680 elif keycode == wx.WXK_UP:
681 681 row = self.GetGridCursorRow()
682 682 if row >= 1:
683 683 item = self.table.items[row-1]
684 684 else:
685 685 item = self.table.items[row]
686 686 self.set_footer(item)
687 687 event.Skip()
688 688 elif keycode == wx.WXK_RIGHT:
689 689 row = self.GetGridCursorRow()
690 690 item = self.table.items[row]
691 691 self.set_footer(item)
692 692 event.Skip()
693 693 elif keycode == wx.WXK_LEFT:
694 694 row = self.GetGridCursorRow()
695 695 item = self.table.items[row]
696 696 self.set_footer(item)
697 697 event.Skip()
698 698 elif keycode == ord("R") or keycode == wx.WXK_F5:
699 699 self.table.refresh_content(event)
700 700 elif keycode == ord("I"):
701 701 row = self.GetGridCursorRow()
702 702 if not sh:
703 703 self.pickinput(row)
704 704 else:
705 705 col = self.GetGridCursorCol()
706 706 self.pickinputattr(row, col)
707 707 else:
708 708 event.Skip()
709 709
710 710 def delete_current_notebook(self):
711 711 """
712 712 deletes the current notebook tab
713 713 """
714 714 panel = self.GetParent()
715 715 nb = panel.GetParent()
716 716 current = nb.GetSelection()
717 717 count = nb.GetPageCount()
718 718 if count > 1:
719 719 for i in xrange(count-1, current-1, -1):
720 720 nb.DeletePage(i)
721 721 nb.GetCurrentPage().grid.SetFocus()
722 722 else:
723 723 frame = nb.GetParent()
724 724 frame.SetStatusText("This is the last level!")
725 725
726 726 def _doenter(self, value, *attrs):
727 727 """
728 728 "enter" a special item resulting in a new notebook tab
729 729 """
730 730 panel = self.GetParent()
731 731 nb = panel.GetParent()
732 732 frame = nb.GetParent()
733 733 current = nb.GetSelection()
734 734 count = nb.GetPageCount()
735 735 try: # if we want to enter something non-iterable, e.g. a function
736 736 if current + 1 == count and value is not self.input: # we have an event in the last tab
737 737 frame._add_notebook(value, *attrs)
738 738 elif value != self.input: # we have to delete all tabs newer than [panel] first
739 739 for i in xrange(count-1, current, -1): # some tabs don't close if we don't close in *reverse* order
740 740 nb.DeletePage(i)
741 741 frame._add_notebook(value)
742 except TypeError, exc:
742 except TypeError as exc:
743 743 if exc.__class__.__module__ == "exceptions":
744 744 msg = "%s: %s" % (exc.__class__.__name__, exc)
745 745 else:
746 746 msg = "%s.%s: %s" % (exc.__class__.__module__, exc.__class__.__name__, exc)
747 747 frame.SetStatusText(msg)
748 748
749 749 def enterattr(self, row, col):
750 750 try:
751 751 attr = self.table._displayattrs[col]
752 752 value = attr.value(self.table.items[row])
753 except Exception, exc:
753 except Exception as exc:
754 754 self.error_output(str(exc))
755 755 else:
756 756 self._doenter(value)
757 757
758 758 def set_footer(self, item):
759 759 frame = self.GetParent().GetParent().GetParent()
760 760 frame.SetStatusText(" ".join([str(text) for (style, text) in ipipe.xformat(item, "footer", 20)[2]]), 0)
761 761
762 762 def enter(self, row):
763 763 try:
764 764 value = self.table.items[row]
765 except Exception, exc:
765 except Exception as exc:
766 766 self.error_output(str(exc))
767 767 else:
768 768 self._doenter(value)
769 769
770 770 def detail(self, row, col):
771 771 """
772 772 shows a detail-view of the current cell
773 773 """
774 774 try:
775 775 attr = self.table._displayattrs[col]
776 776 item = self.table.items[row]
777 except Exception, exc:
777 except Exception as exc:
778 778 self.error_output(str(exc))
779 779 else:
780 780 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
781 781 self._doenter(attrs)
782 782
783 783 def detail_attr(self, row, col):
784 784 try:
785 785 attr = self.table._displayattrs[col]
786 786 item = attr.value(self.table.items[row])
787 except Exception, exc:
787 except Exception as exc:
788 788 self.error_output(str(exc))
789 789 else:
790 790 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
791 791 self._doenter(attrs)
792 792
793 793 def quit(self, result=None):
794 794 """
795 795 quit
796 796 """
797 797 frame = self.GetParent().GetParent().GetParent()
798 798 if frame.helpdialog:
799 799 frame.helpdialog.Destroy()
800 800 app = frame.parent
801 801 if app is not None:
802 802 app.result = result
803 803 frame.Close()
804 804 frame.Destroy()
805 805
806 806 def cell_doubleclicked(self, event):
807 807 self.enterattr(event.GetRow(), event.GetCol())
808 808 event.Skip()
809 809
810 810 def cell_leftclicked(self, event):
811 811 row = event.GetRow()
812 812 item = self.table.items[row]
813 813 self.set_footer(item)
814 814 event.Skip()
815 815
816 816 def pick(self, row):
817 817 """
818 818 pick a single row and return to the IPython prompt
819 819 """
820 820 try:
821 821 value = self.table.items[row]
822 except Exception, exc:
822 except Exception as exc:
823 823 self.error_output(str(exc))
824 824 else:
825 825 self.quit(value)
826 826
827 827 def pickinput(self, row):
828 828 try:
829 829 value = self.table.items[row]
830 except Exception, exc:
830 except Exception as exc:
831 831 self.error_output(str(exc))
832 832 else:
833 833 api = ipapi.get()
834 834 api.set_next_input(str(value))
835 835 self.quit(value)
836 836
837 837 def pickinputattr(self, row, col):
838 838 try:
839 839 attr = self.table._displayattrs[col]
840 840 value = attr.value(self.table.items[row])
841 except Exception, exc:
841 except Exception as exc:
842 842 self.error_output(str(exc))
843 843 else:
844 844 api = ipapi.get()
845 845 api.set_next_input(str(value))
846 846 self.quit(value)
847 847
848 848 def pickrows(self, rows):
849 849 """
850 850 pick multiple rows and return to the IPython prompt
851 851 """
852 852 try:
853 853 value = [self.table.items[row] for row in rows]
854 except Exception, exc:
854 except Exception as exc:
855 855 self.error_output(str(exc))
856 856 else:
857 857 self.quit(value)
858 858
859 859 def pickrowsattr(self, rows, col):
860 860 """"
861 861 pick one column from multiple rows
862 862 """
863 863 values = []
864 864 try:
865 865 attr = self.table._displayattrs[col]
866 866 for row in rows:
867 867 try:
868 868 values.append(attr.value(self.table.items[row]))
869 869 except (SystemExit, KeyboardInterrupt):
870 870 raise
871 871 except Exception:
872 872 raise #pass
873 except Exception, exc:
873 except Exception as exc:
874 874 self.error_output(str(exc))
875 875 else:
876 876 self.quit(values)
877 877
878 878 def pickattr(self, row, col):
879 879 try:
880 880 attr = self.table._displayattrs[col]
881 881 value = attr.value(self.table.items[row])
882 except Exception, exc:
882 except Exception as exc:
883 883 self.error_output(str(exc))
884 884 else:
885 885 self.quit(value)
886 886
887 887
888 888 class IGridPanel(wx.Panel):
889 889 # Each IGridPanel contains an IGridGrid
890 890 def __init__(self, parent, input, *attrs):
891 891 wx.Panel.__init__(self, parent, -1)
892 892 self.grid = IGridGrid(self, input, *attrs)
893 893 self.grid.FitInside()
894 894 sizer = wx.BoxSizer(wx.VERTICAL)
895 895 sizer.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
896 896 self.SetSizer(sizer)
897 897 sizer.Fit(self)
898 898 sizer.SetSizeHints(self)
899 899
900 900
901 901 class IGridHTMLHelp(wx.Frame):
902 902 def __init__(self, parent, title, size):
903 903 wx.Frame.__init__(self, parent, -1, title, size=size)
904 904 html = wx.html.HtmlWindow(self)
905 905 if "gtk2" in wx.PlatformInfo:
906 906 html.SetStandardFonts()
907 907 html.SetPage(help)
908 908
909 909
910 910 class IGridFrame(wx.Frame):
911 911 maxtitlelen = 30
912 912
913 913 def __init__(self, parent, input):
914 914 title = " ".join([str(text) for (style, text) in ipipe.xformat(input, "header", 20)[2]])
915 915 wx.Frame.__init__(self, None, title=title, size=(640, 480))
916 916 self.menubar = wx.MenuBar()
917 917 self.menucounter = 100
918 918 self.m_help = wx.Menu()
919 919 self.m_search = wx.Menu()
920 920 self.m_sort = wx.Menu()
921 921 self.m_refresh = wx.Menu()
922 922 self.notebook = wx.Notebook(self, -1, style=0)
923 923 self.statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP)
924 924 self.statusbar.SetFieldsCount(2)
925 925 self.SetStatusWidths([-1, 200])
926 926 self.parent = parent
927 927 self._add_notebook(input)
928 928 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
929 929 self.makemenu(self.m_sort, "&Sort (asc)\tV", "Sort ascending", self.sortasc)
930 930 self.makemenu(self.m_sort, "Sort (&desc)\tShift-V", "Sort descending", self.sortdesc)
931 931 self.makemenu(self.m_help, "&Help\tF1", "Help", self.display_help)
932 932 # self.makemenu(self.m_help, "&Show help in browser", "Show help in browser", self.display_help_in_browser)
933 933 self.makemenu(self.m_search, "&Find text\tCTRL-F", "Find text", self.enter_searchtext)
934 934 self.makemenu(self.m_search, "Find by &expression\tCTRL-Shift-F", "Find by expression", self.enter_searchexpression)
935 935 self.makemenu(self.m_search, "Find &next\tF3", "Find next", self.find_next)
936 936 self.makemenu(self.m_search, "Find &previous\tShift-F3", "Find previous", self.find_previous)
937 937 self.makemenu(self.m_refresh, "&Refresh once \tF5", "Refresh once", self.refresh_once)
938 938 self.makemenu(self.m_refresh, "Refresh every &1s", "Refresh every second", self.refresh_every_second)
939 939 self.makemenu(self.m_refresh, "Refresh every &X seconds", "Refresh every X seconds", self.refresh_interval)
940 940 self.makemenu(self.m_refresh, "&Stop all refresh timers", "Stop refresh timers", self.stop_refresh)
941 941 self.menubar.Append(self.m_search, "&Find")
942 942 self.menubar.Append(self.m_sort, "&Sort")
943 943 self.menubar.Append(self.m_refresh, "&Refresh")
944 944 self.menubar.Append(self.m_help, "&Help")
945 945 self.SetMenuBar(self.menubar)
946 946 self.searchtext = ""
947 947 self.searchexpression = ""
948 948 self.helpdialog = None
949 949 self.refresh_interval = 1000
950 950 self.SetStatusText("Refreshing inactive", 1)
951 951
952 952 def refresh_once(self, event):
953 953 table = self.notebook.GetPage(self.notebook.GetSelection()).grid.table
954 954 table.refresh_content(event)
955 955
956 956 def refresh_interval(self, event):
957 957 table = self.notebook.GetPage(self.notebook.GetSelection()).grid.table
958 958 dlg = wx.TextEntryDialog(self, "Enter refresh interval (milliseconds):", "Refresh timer:", defaultValue=str(self.refresh_interval))
959 959 if dlg.ShowModal() == wx.ID_OK:
960 960 try:
961 961 milliseconds = int(dlg.GetValue())
962 except ValueError, exc:
962 except ValueError as exc:
963 963 self.SetStatusText(str(exc))
964 964 else:
965 965 table.timer.Start(milliseconds=milliseconds, oneShot=False)
966 966 self.SetStatusText("Refresh timer set to %s ms" % milliseconds)
967 967 self.SetStatusText("Refresh interval: %s ms" % milliseconds, 1)
968 968 self.refresh_interval = milliseconds
969 969 dlg.Destroy()
970 970
971 971 def stop_refresh(self, event):
972 972 for i in xrange(self.notebook.GetPageCount()):
973 973 nb = self.notebook.GetPage(i)
974 974 nb.grid.table.timer.Stop()
975 975 self.SetStatusText("Refreshing inactive", 1)
976 976
977 977 def refresh_every_second(self, event):
978 978 table = self.notebook.GetPage(self.notebook.GetSelection()).grid.table
979 979 table.timer.Start(milliseconds=1000, oneShot=False)
980 980 self.SetStatusText("Refresh interval: 1000 ms", 1)
981 981
982 982 def sortasc(self, event):
983 983 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
984 984 grid.sortattrasc()
985 985
986 986 def sortdesc(self, event):
987 987 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
988 988 grid.sortattrdesc()
989 989
990 990 def find_previous(self, event):
991 991 """
992 992 find previous occurrences
993 993 """
994 994 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
995 995 if self.searchtext:
996 996 row = grid.GetGridCursorRow()
997 997 col = grid.GetGridCursorCol()
998 998 self.SetStatusText('Search mode: text; looking for %s' % self.searchtext)
999 999 if col-1 >= 0:
1000 1000 grid.search(self.searchtext, row, col-1, False)
1001 1001 else:
1002 1002 grid.search(self.searchtext, row-1, grid.table.GetNumberCols()-1, False)
1003 1003 elif self.searchexpression:
1004 1004 self.SetStatusText("Search mode: expression; looking for %s" % repr(self.searchexpression)[2:-1])
1005 1005 grid.searchexpression(searchexp=self.searchexpression, search_forward=False)
1006 1006 else:
1007 1007 self.SetStatusText("No search yet: please enter search-text or -expression")
1008 1008
1009 1009 def find_next(self, event):
1010 1010 """
1011 1011 find the next occurrence
1012 1012 """
1013 1013 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
1014 1014 if self.searchtext != "":
1015 1015 row = grid.GetGridCursorRow()
1016 1016 col = grid.GetGridCursorCol()
1017 1017 self.SetStatusText('Search mode: text; looking for %s' % self.searchtext)
1018 1018 if col+1 < grid.table.GetNumberCols():
1019 1019 grid.search(self.searchtext, row, col+1)
1020 1020 else:
1021 1021 grid.search(self.searchtext, row+1, 0)
1022 1022 elif self.searchexpression != "":
1023 1023 self.SetStatusText('Search mode: expression; looking for %s' % repr(self.searchexpression)[2:-1])
1024 1024 grid.searchexpression(searchexp=self.searchexpression)
1025 1025 else:
1026 1026 self.SetStatusText("No search yet: please enter search-text or -expression")
1027 1027
1028 1028 def display_help(self, event):
1029 1029 """
1030 1030 Display a help dialog
1031 1031 """
1032 1032 if self.helpdialog:
1033 1033 self.helpdialog.Destroy()
1034 1034 self.helpdialog = IGridHTMLHelp(None, title="Help", size=wx.Size(600,400))
1035 1035 self.helpdialog.Show()
1036 1036
1037 1037 def display_help_in_browser(self, event):
1038 1038 """
1039 1039 Show the help-HTML in a browser (as a ``HtmlWindow`` does not understand
1040 1040 CSS this looks better)
1041 1041 """
1042 1042 filename = urllib.pathname2url(os.path.abspath(os.path.join(os.path.dirname(__file__), "igrid_help.html")))
1043 1043 if not filename.startswith("file"):
1044 1044 filename = "file:" + filename
1045 1045 webbrowser.open(filename, new=1, autoraise=True)
1046 1046
1047 1047 def enter_searchexpression(self, event):
1048 1048 dlg = wx.TextEntryDialog(self, "Find:", "Find matching expression:", defaultValue=self.searchexpression)
1049 1049 if dlg.ShowModal() == wx.ID_OK:
1050 1050 self.searchexpression = dlg.GetValue()
1051 1051 self.searchtext = ""
1052 1052 self.SetStatusText('Search mode: expression; looking for %s' % repr(self.searchexpression)[2:-1])
1053 1053 self.notebook.GetPage(self.notebook.GetSelection()).grid.searchexpression(self.searchexpression)
1054 1054 dlg.Destroy()
1055 1055
1056 1056 def makemenu(self, menu, label, help, cmd):
1057 1057 menu.Append(self.menucounter, label, help)
1058 1058 self.Bind(wx.EVT_MENU, cmd, id=self.menucounter)
1059 1059 self.menucounter += 1
1060 1060
1061 1061 def _add_notebook(self, input, *attrs):
1062 1062 # Adds another notebook which has the starting object ``input``
1063 1063 panel = IGridPanel(self.notebook, input, *attrs)
1064 1064 text = str(ipipe.xformat(input, "header", self.maxtitlelen)[2])
1065 1065 if len(text) >= self.maxtitlelen:
1066 1066 text = text[:self.maxtitlelen].rstrip(".") + "..."
1067 1067 self.notebook.AddPage(panel, text, True)
1068 1068 panel.grid.SetFocus()
1069 1069 self.Layout()
1070 1070
1071 1071 def OnCloseWindow(self, event):
1072 1072 self.Destroy()
1073 1073
1074 1074 def enter_searchtext(self, event):
1075 1075 # Displays a dialog asking for the searchtext
1076 1076 dlg = wx.TextEntryDialog(self, "Find:", "Find in list", defaultValue=self.searchtext)
1077 1077 if dlg.ShowModal() == wx.ID_OK:
1078 1078 self.searchtext = dlg.GetValue()
1079 1079 self.searchexpression = ""
1080 1080 self.SetStatusText('Search mode: text; looking for %s' % self.searchtext)
1081 1081 self.notebook.GetPage(self.notebook.GetSelection()).grid.search(self.searchtext)
1082 1082 dlg.Destroy()
1083 1083
1084 1084
1085 1085 class App(wx.App):
1086 1086 def __init__(self, input):
1087 1087 self.input = input
1088 1088 self.result = None # Result to be returned to IPython. Set by quit().
1089 1089 wx.App.__init__(self)
1090 1090
1091 1091 def OnInit(self):
1092 1092 frame = IGridFrame(self, self.input)
1093 1093 frame.Show()
1094 1094 self.SetTopWindow(frame)
1095 1095 frame.Raise()
1096 1096 return True
1097 1097
1098 1098
1099 1099 class igrid(ipipe.Display):
1100 1100 """
1101 1101 This is a wx-based display object that can be used instead of ``ibrowse``
1102 1102 (which is curses-based) or ``idump`` (which simply does a print).
1103 1103 """
1104 1104
1105 1105 if wx.VERSION < (2, 7):
1106 1106 def display(self):
1107 1107 try:
1108 1108 # Try to create a "standalone" frame. If this works we're probably
1109 1109 # running with -wthread.
1110 1110 # Note that this sets the parent of the frame to None, but we can't
1111 1111 # pass a result object back to the shell anyway.
1112 1112 frame = IGridFrame(None, self.input)
1113 1113 frame.Show()
1114 1114 frame.Raise()
1115 1115 except wx.PyNoAppError:
1116 1116 # There's no wx application yet => create one.
1117 1117 app = App(self.input)
1118 1118 app.MainLoop()
1119 1119 return app.result
1120 1120 else:
1121 1121 # With wx 2.7 it gets simpler.
1122 1122 def display(self):
1123 1123 app = App(self.input)
1124 1124 app.MainLoop()
1125 1125 return app.result
1126 1126
@@ -1,2328 +1,2328 b''
1 1 # -*- coding: iso-8859-1 -*-
2 2
3 3 """
4 4 ``ipipe`` provides classes to be used in an interactive Python session. Doing a
5 5 ``from ipipe import *`` is the preferred way to do this. The name of all
6 6 objects imported this way starts with ``i`` to minimize collisions.
7 7
8 8 ``ipipe`` supports "pipeline expressions", which is something resembling Unix
9 9 pipes. An example is::
10 10
11 11 >>> ienv | isort("key.lower()")
12 12
13 13 This gives a listing of all environment variables sorted by name.
14 14
15 15
16 16 There are three types of objects in a pipeline expression:
17 17
18 18 * ``Table``s: These objects produce items. Examples are ``ils`` (listing the
19 19 current directory, ``ienv`` (listing environment variables), ``ipwd`` (listing
20 20 user accounts) and ``igrp`` (listing user groups). A ``Table`` must be the
21 21 first object in a pipe expression.
22 22
23 23 * ``Pipe``s: These objects sit in the middle of a pipe expression. They
24 24 transform the input in some way (e.g. filtering or sorting it). Examples are:
25 25 ``ifilter`` (which filters the input pipe), ``isort`` (which sorts the input
26 26 pipe) and ``ieval`` (which evaluates a function or expression for each object
27 27 in the input pipe).
28 28
29 29 * ``Display``s: These objects can be put as the last object in a pipeline
30 30 expression. There are responsible for displaying the result of the pipeline
31 31 expression. If a pipeline expression doesn't end in a display object a default
32 32 display objects will be used. One example is ``ibrowse`` which is a ``curses``
33 33 based browser.
34 34
35 35
36 36 Adding support for pipeline expressions to your own objects can be done through
37 37 three extensions points (all of them optional):
38 38
39 39 * An object that will be displayed as a row by a ``Display`` object should
40 40 implement the method ``__xattrs__(self, mode)`` method or register an
41 41 implementation of the generic function ``xattrs``. For more info see ``xattrs``.
42 42
43 43 * When an object ``foo`` is displayed by a ``Display`` object, the generic
44 44 function ``xrepr`` is used.
45 45
46 46 * Objects that can be iterated by ``Pipe``s must iterable. For special cases,
47 47 where iteration for display is different than the normal iteration a special
48 48 implementation can be registered with the generic function ``xiter``. This
49 49 makes it possible to use dictionaries and modules in pipeline expressions,
50 50 for example::
51 51
52 52 >>> import sys
53 53 >>> sys | ifilter("isinstance(value, int)") | idump
54 54 key |value
55 55 api_version| 1012
56 56 dllhandle | 503316480
57 57 hexversion | 33817328
58 58 maxint |2147483647
59 59 maxunicode | 65535
60 60 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
61 61 ...
62 62
63 63 Note: The expression strings passed to ``ifilter()`` and ``isort()`` can
64 64 refer to the object to be filtered or sorted via the variable ``_`` and to any
65 65 of the attributes of the object, i.e.::
66 66
67 67 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
68 68
69 69 does the same as::
70 70
71 71 >>> sys.modules | ifilter("value is not None") | isort("key.lower()")
72 72
73 73 In addition to expression strings, it's possible to pass callables (taking
74 74 the object as an argument) to ``ifilter()``, ``isort()`` and ``ieval()``::
75 75
76 76 >>> sys | ifilter(lambda _:isinstance(_.value, int)) \
77 77 ... | ieval(lambda _: (_.key, hex(_.value))) | idump
78 78 0 |1
79 79 api_version|0x3f4
80 80 dllhandle |0x1e000000
81 81 hexversion |0x20402f0
82 82 maxint |0x7fffffff
83 83 maxunicode |0xffff
84 84 """
85 85
86 86 skip_doctest = True # ignore top-level docstring as a doctest.
87 87
88 88 import sys, os, os.path, stat, glob, new, csv, datetime, types
89 89 import itertools, mimetypes, StringIO
90 90
91 91 try: # Python 2.3 compatibility
92 92 import collections
93 93 except ImportError:
94 94 deque = list
95 95 else:
96 96 deque = collections.deque
97 97
98 98 try: # Python 2.3 compatibility
99 99 set
100 100 except NameError:
101 101 import sets
102 102 set = sets.Set
103 103
104 104 try: # Python 2.3 compatibility
105 105 sorted
106 106 except NameError:
107 107 def sorted(iterator, key=None, reverse=False):
108 108 items = list(iterator)
109 109 if key is not None:
110 110 items.sort(lambda i1, i2: cmp(key(i1), key(i2)))
111 111 else:
112 112 items.sort()
113 113 if reverse:
114 114 items.reverse()
115 115 return items
116 116
117 117 try: # Python 2.4 compatibility
118 118 GeneratorExit
119 119 except NameError:
120 120 GeneratorExit = SystemExit
121 121
122 122 try:
123 123 import pwd
124 124 except ImportError:
125 125 pwd = None
126 126
127 127 try:
128 128 import grp
129 129 except ImportError:
130 130 grp = None
131 131
132 132 from IPython.external import simplegeneric
133 133 from IPython.external import path
134 134
135 135 try:
136 136 import IPython.utils.io
137 137 from IPython.utils import generics
138 138 except ImportError:
139 139 Term = None
140 140 generics = None
141 141
142 142 from IPython.core import ipapi
143 143
144 144
145 145 __all__ = [
146 146 "ifile", "ils", "iglob", "iwalk", "ipwdentry", "ipwd", "igrpentry", "igrp",
147 147 "icsv", "ix", "ichain", "isort", "ifilter", "ieval", "ienum",
148 148 "ienv", "ihist", "ialias", "icap", "idump", "iless"
149 149 ]
150 150
151 151
152 152 os.stat_float_times(True) # enable microseconds
153 153
154 154
155 155 class AttrNamespace(object):
156 156 """
157 157 Helper class that is used for providing a namespace for evaluating
158 158 expressions containing attribute names of an object.
159 159 """
160 160 def __init__(self, wrapped):
161 161 self.wrapped = wrapped
162 162
163 163 def __getitem__(self, name):
164 164 if name == "_":
165 165 return self.wrapped
166 166 try:
167 167 return getattr(self.wrapped, name)
168 168 except AttributeError:
169 169 raise KeyError(name)
170 170
171 171 # Python 2.3 compatibility
172 172 # use eval workaround to find out which names are used in the
173 173 # eval string and put them into the locals. This works for most
174 174 # normal uses case, bizarre ones like accessing the locals()
175 175 # will fail
176 176 try:
177 177 eval("_", None, AttrNamespace(None))
178 178 except TypeError:
179 179 real_eval = eval
180 180 def eval(codestring, _globals, _locals):
181 181 """
182 182 eval(source[, globals[, locals]]) -> value
183 183
184 184 Evaluate the source in the context of globals and locals.
185 185 The source may be a string representing a Python expression
186 186 or a code object as returned by compile().
187 187 The globals must be a dictionary and locals can be any mappping.
188 188
189 189 This function is a workaround for the shortcomings of
190 190 Python 2.3's eval.
191 191 """
192 192
193 193 if isinstance(codestring, basestring):
194 194 code = compile(codestring, "_eval", "eval")
195 195 else:
196 196 code = codestring
197 197 newlocals = {}
198 198 for name in code.co_names:
199 199 try:
200 200 newlocals[name] = _locals[name]
201 201 except KeyError:
202 202 pass
203 203 return real_eval(code, _globals, newlocals)
204 204
205 205
206 206 noitem = object()
207 207
208 208
209 209 def item(iterator, index, default=noitem):
210 210 """
211 211 Return the ``index``th item from the iterator ``iterator``.
212 212 ``index`` must be an integer (negative integers are relative to the
213 213 end (i.e. the last items produced by the iterator)).
214 214
215 215 If ``default`` is given, this will be the default value when
216 216 the iterator doesn't contain an item at this position. Otherwise an
217 217 ``IndexError`` will be raised.
218 218
219 219 Note that using this function will partially or totally exhaust the
220 220 iterator.
221 221 """
222 222 i = index
223 223 if i>=0:
224 224 for item in iterator:
225 225 if not i:
226 226 return item
227 227 i -= 1
228 228 else:
229 229 i = -index
230 230 cache = deque()
231 231 for item in iterator:
232 232 cache.append(item)
233 233 if len(cache)>i:
234 234 cache.popleft()
235 235 if len(cache)==i:
236 236 return cache.popleft()
237 237 if default is noitem:
238 238 raise IndexError(index)
239 239 else:
240 240 return default
241 241
242 242
243 243 def getglobals(g):
244 244 """
245 245 Return the global namespace that is used for expression strings in
246 246 ``ifilter`` and others. This is ``g`` or (if ``g`` is ``None``) IPython's
247 247 user namespace.
248 248 """
249 249 if g is None:
250 250 if ipapi is not None:
251 251 api = ipapi.get()
252 252 if api is not None:
253 253 return api.user_ns
254 254 return globals()
255 255 return g
256 256
257 257
258 258 class Descriptor(object):
259 259 """
260 260 A ``Descriptor`` object is used for describing the attributes of objects.
261 261 """
262 262 def __hash__(self):
263 263 return hash(self.__class__) ^ hash(self.key())
264 264
265 265 def __eq__(self, other):
266 266 return self.__class__ is other.__class__ and self.key() == other.key()
267 267
268 268 def __ne__(self, other):
269 269 return self.__class__ is not other.__class__ or self.key() != other.key()
270 270
271 271 def key(self):
272 272 pass
273 273
274 274 def name(self):
275 275 """
276 276 Return the name of this attribute for display by a ``Display`` object
277 277 (e.g. as a column title).
278 278 """
279 279 key = self.key()
280 280 if key is None:
281 281 return "_"
282 282 return str(key)
283 283
284 284 def attrtype(self, obj):
285 285 """
286 286 Return the type of this attribute (i.e. something like "attribute" or
287 287 "method").
288 288 """
289 289
290 290 def valuetype(self, obj):
291 291 """
292 292 Return the type of this attribute value of the object ``obj``.
293 293 """
294 294
295 295 def value(self, obj):
296 296 """
297 297 Return the value of this attribute of the object ``obj``.
298 298 """
299 299
300 300 def doc(self, obj):
301 301 """
302 302 Return the documentation for this attribute.
303 303 """
304 304
305 305 def shortdoc(self, obj):
306 306 """
307 307 Return a short documentation for this attribute (defaulting to the
308 308 first line).
309 309 """
310 310 doc = self.doc(obj)
311 311 if doc is not None:
312 312 doc = doc.strip().splitlines()[0].strip()
313 313 return doc
314 314
315 315 def iter(self, obj):
316 316 """
317 317 Return an iterator for this attribute of the object ``obj``.
318 318 """
319 319 return xiter(self.value(obj))
320 320
321 321
322 322 class SelfDescriptor(Descriptor):
323 323 """
324 324 A ``SelfDescriptor`` describes the object itself.
325 325 """
326 326 def key(self):
327 327 return None
328 328
329 329 def attrtype(self, obj):
330 330 return "self"
331 331
332 332 def valuetype(self, obj):
333 333 return type(obj)
334 334
335 335 def value(self, obj):
336 336 return obj
337 337
338 338 def __repr__(self):
339 339 return "Self"
340 340
341 341 selfdescriptor = SelfDescriptor() # there's no need for more than one
342 342
343 343
344 344 class AttributeDescriptor(Descriptor):
345 345 """
346 346 An ``AttributeDescriptor`` describes a simple attribute of an object.
347 347 """
348 348 __slots__ = ("_name", "_doc")
349 349
350 350 def __init__(self, name, doc=None):
351 351 self._name = name
352 352 self._doc = doc
353 353
354 354 def key(self):
355 355 return self._name
356 356
357 357 def doc(self, obj):
358 358 return self._doc
359 359
360 360 def attrtype(self, obj):
361 361 return "attr"
362 362
363 363 def valuetype(self, obj):
364 364 return type(getattr(obj, self._name))
365 365
366 366 def value(self, obj):
367 367 return getattr(obj, self._name)
368 368
369 369 def __repr__(self):
370 370 if self._doc is None:
371 371 return "Attribute(%r)" % self._name
372 372 else:
373 373 return "Attribute(%r, %r)" % (self._name, self._doc)
374 374
375 375
376 376 class IndexDescriptor(Descriptor):
377 377 """
378 378 An ``IndexDescriptor`` describes an "attribute" of an object that is fetched
379 379 via ``__getitem__``.
380 380 """
381 381 __slots__ = ("_index",)
382 382
383 383 def __init__(self, index):
384 384 self._index = index
385 385
386 386 def key(self):
387 387 return self._index
388 388
389 389 def attrtype(self, obj):
390 390 return "item"
391 391
392 392 def valuetype(self, obj):
393 393 return type(obj[self._index])
394 394
395 395 def value(self, obj):
396 396 return obj[self._index]
397 397
398 398 def __repr__(self):
399 399 return "Index(%r)" % self._index
400 400
401 401
402 402 class MethodDescriptor(Descriptor):
403 403 """
404 404 A ``MethodDescriptor`` describes a method of an object that can be called
405 405 without argument. Note that this method shouldn't change the object.
406 406 """
407 407 __slots__ = ("_name", "_doc")
408 408
409 409 def __init__(self, name, doc=None):
410 410 self._name = name
411 411 self._doc = doc
412 412
413 413 def key(self):
414 414 return self._name
415 415
416 416 def doc(self, obj):
417 417 if self._doc is None:
418 418 return getattr(obj, self._name).__doc__
419 419 return self._doc
420 420
421 421 def attrtype(self, obj):
422 422 return "method"
423 423
424 424 def valuetype(self, obj):
425 425 return type(self.value(obj))
426 426
427 427 def value(self, obj):
428 428 return getattr(obj, self._name)()
429 429
430 430 def __repr__(self):
431 431 if self._doc is None:
432 432 return "Method(%r)" % self._name
433 433 else:
434 434 return "Method(%r, %r)" % (self._name, self._doc)
435 435
436 436
437 437 class IterAttributeDescriptor(Descriptor):
438 438 """
439 439 An ``IterAttributeDescriptor`` works like an ``AttributeDescriptor`` but
440 440 doesn't return an attribute values (because this value might be e.g. a large
441 441 list).
442 442 """
443 443 __slots__ = ("_name", "_doc")
444 444
445 445 def __init__(self, name, doc=None):
446 446 self._name = name
447 447 self._doc = doc
448 448
449 449 def key(self):
450 450 return self._name
451 451
452 452 def doc(self, obj):
453 453 return self._doc
454 454
455 455 def attrtype(self, obj):
456 456 return "iter"
457 457
458 458 def valuetype(self, obj):
459 459 return noitem
460 460
461 461 def value(self, obj):
462 462 return noitem
463 463
464 464 def iter(self, obj):
465 465 return xiter(getattr(obj, self._name))
466 466
467 467 def __repr__(self):
468 468 if self._doc is None:
469 469 return "IterAttribute(%r)" % self._name
470 470 else:
471 471 return "IterAttribute(%r, %r)" % (self._name, self._doc)
472 472
473 473
474 474 class IterMethodDescriptor(Descriptor):
475 475 """
476 476 An ``IterMethodDescriptor`` works like an ``MethodDescriptor`` but doesn't
477 477 return an attribute values (because this value might be e.g. a large list).
478 478 """
479 479 __slots__ = ("_name", "_doc")
480 480
481 481 def __init__(self, name, doc=None):
482 482 self._name = name
483 483 self._doc = doc
484 484
485 485 def key(self):
486 486 return self._name
487 487
488 488 def doc(self, obj):
489 489 if self._doc is None:
490 490 return getattr(obj, self._name).__doc__
491 491 return self._doc
492 492
493 493 def attrtype(self, obj):
494 494 return "itermethod"
495 495
496 496 def valuetype(self, obj):
497 497 return noitem
498 498
499 499 def value(self, obj):
500 500 return noitem
501 501
502 502 def iter(self, obj):
503 503 return xiter(getattr(obj, self._name)())
504 504
505 505 def __repr__(self):
506 506 if self._doc is None:
507 507 return "IterMethod(%r)" % self._name
508 508 else:
509 509 return "IterMethod(%r, %r)" % (self._name, self._doc)
510 510
511 511
512 512 class FunctionDescriptor(Descriptor):
513 513 """
514 514 A ``FunctionDescriptor`` turns a function into a descriptor. The function
515 515 will be called with the object to get the type and value of the attribute.
516 516 """
517 517 __slots__ = ("_function", "_name", "_doc")
518 518
519 519 def __init__(self, function, name=None, doc=None):
520 520 self._function = function
521 521 self._name = name
522 522 self._doc = doc
523 523
524 524 def key(self):
525 525 return self._function
526 526
527 527 def name(self):
528 528 if self._name is not None:
529 529 return self._name
530 530 return getattr(self._function, "__xname__", self._function.__name__)
531 531
532 532 def doc(self, obj):
533 533 if self._doc is None:
534 534 return self._function.__doc__
535 535 return self._doc
536 536
537 537 def attrtype(self, obj):
538 538 return "function"
539 539
540 540 def valuetype(self, obj):
541 541 return type(self._function(obj))
542 542
543 543 def value(self, obj):
544 544 return self._function(obj)
545 545
546 546 def __repr__(self):
547 547 if self._doc is None:
548 548 return "Function(%r)" % self._name
549 549 else:
550 550 return "Function(%r, %r)" % (self._name, self._doc)
551 551
552 552
553 553 class Table(object):
554 554 """
555 555 A ``Table`` is an object that produces items (just like a normal Python
556 556 iterator/generator does) and can be used as the first object in a pipeline
557 557 expression. The displayhook will open the default browser for such an object
558 558 (instead of simply printing the ``repr()`` result).
559 559 """
560 560
561 561 # We want to support ``foo`` and ``foo()`` in pipeline expression:
562 562 # So we implement the required operators (``|`` and ``+``) in the metaclass,
563 563 # instantiate the class and forward the operator to the instance
564 564 class __metaclass__(type):
565 565 def __iter__(self):
566 566 return iter(self())
567 567
568 568 def __or__(self, other):
569 569 return self() | other
570 570
571 571 def __add__(self, other):
572 572 return self() + other
573 573
574 574 def __radd__(self, other):
575 575 return other + self()
576 576
577 577 def __getitem__(self, index):
578 578 return self()[index]
579 579
580 580 def __getitem__(self, index):
581 581 return item(self, index)
582 582
583 583 def __contains__(self, item):
584 584 for haveitem in self:
585 585 if item == haveitem:
586 586 return True
587 587 return False
588 588
589 589 def __or__(self, other):
590 590 # autoinstantiate right hand side
591 591 if isinstance(other, type) and issubclass(other, (Table, Display)):
592 592 other = other()
593 593 # treat simple strings and functions as ``ieval`` instances
594 594 elif not isinstance(other, Display) and not isinstance(other, Table):
595 595 other = ieval(other)
596 596 # forward operations to the right hand side
597 597 return other.__ror__(self)
598 598
599 599 def __add__(self, other):
600 600 # autoinstantiate right hand side
601 601 if isinstance(other, type) and issubclass(other, Table):
602 602 other = other()
603 603 return ichain(self, other)
604 604
605 605 def __radd__(self, other):
606 606 # autoinstantiate left hand side
607 607 if isinstance(other, type) and issubclass(other, Table):
608 608 other = other()
609 609 return ichain(other, self)
610 610
611 611
612 612 class Pipe(Table):
613 613 """
614 614 A ``Pipe`` is an object that can be used in a pipeline expression. It
615 615 processes the objects it gets from its input ``Table``/``Pipe``. Note that
616 616 a ``Pipe`` object can't be used as the first object in a pipeline
617 617 expression, as it doesn't produces items itself.
618 618 """
619 619 class __metaclass__(Table.__metaclass__):
620 620 def __ror__(self, input):
621 621 return input | self()
622 622
623 623 def __ror__(self, input):
624 624 # autoinstantiate left hand side
625 625 if isinstance(input, type) and issubclass(input, Table):
626 626 input = input()
627 627 self.input = input
628 628 return self
629 629
630 630
631 631 def xrepr(item, mode="default"):
632 632 """
633 633 Generic function that adds color output and different display modes to ``repr``.
634 634
635 635 The result of an ``xrepr`` call is iterable and consists of ``(style, string)``
636 636 tuples. The ``style`` in this tuple must be a ``Style`` object from the
637 637 ``astring`` module. To reconfigure the output the first yielded tuple can be
638 638 a ``(aligment, full)`` tuple instead of a ``(style, string)`` tuple.
639 639 ``alignment`` can be -1 for left aligned, 0 for centered and 1 for right
640 640 aligned (the default is left alignment). ``full`` is a boolean that specifies
641 641 whether the complete output must be displayed or the ``Display`` object is
642 642 allowed to stop output after enough text has been produced (e.g. a syntax
643 643 highlighted text line would use ``True``, but for a large data structure
644 644 (i.e. a nested list, tuple or dictionary) ``False`` would be used).
645 645 The default is full output.
646 646
647 647 There are four different possible values for ``mode`` depending on where
648 648 the ``Display`` object will display ``item``:
649 649
650 650 ``"header"``
651 651 ``item`` will be displayed in a header line (this is used by ``ibrowse``).
652 652
653 653 ``"footer"``
654 654 ``item`` will be displayed in a footer line (this is used by ``ibrowse``).
655 655
656 656 ``"cell"``
657 657 ``item`` will be displayed in a table cell/list.
658 658
659 659 ``"default"``
660 660 default mode. If an ``xrepr`` implementation recursively outputs objects,
661 661 ``"default"`` must be passed in the recursive calls to ``xrepr``.
662 662
663 663 If no implementation is registered for ``item``, ``xrepr`` will try the
664 664 ``__xrepr__`` method on ``item``. If ``item`` doesn't have an ``__xrepr__``
665 665 method it falls back to ``repr``/``__repr__`` for all modes.
666 666 """
667 667 try:
668 668 func = item.__xrepr__
669 669 except AttributeError:
670 670 yield (astyle.style_default, repr(item))
671 671 else:
672 672 try:
673 673 for x in func(mode):
674 674 yield x
675 675 except (KeyboardInterrupt, SystemExit, GeneratorExit):
676 676 raise
677 677 except Exception:
678 678 yield (astyle.style_default, repr(item))
679 679 xrepr = simplegeneric.generic(xrepr)
680 680
681 681
682 682 def xrepr_none(self, mode="default"):
683 683 yield (astyle.style_type_none, repr(self))
684 684 xrepr.when_object(None)(xrepr_none)
685 685
686 686
687 687 def xrepr_noitem(self, mode="default"):
688 688 yield (2, True)
689 689 yield (astyle.style_nodata, "<?>")
690 690 xrepr.when_object(noitem)(xrepr_noitem)
691 691
692 692
693 693 def xrepr_bool(self, mode="default"):
694 694 yield (astyle.style_type_bool, repr(self))
695 695 xrepr.when_type(bool)(xrepr_bool)
696 696
697 697
698 698 def xrepr_str(self, mode="default"):
699 699 if mode == "cell":
700 700 yield (astyle.style_default, repr(self.expandtabs(tab))[1:-1])
701 701 else:
702 702 yield (astyle.style_default, repr(self))
703 703 xrepr.when_type(str)(xrepr_str)
704 704
705 705
706 706 def xrepr_unicode(self, mode="default"):
707 707 if mode == "cell":
708 708 yield (astyle.style_default, repr(self.expandtabs(tab))[2:-1])
709 709 else:
710 710 yield (astyle.style_default, repr(self))
711 711 xrepr.when_type(unicode)(xrepr_unicode)
712 712
713 713
714 714 def xrepr_number(self, mode="default"):
715 715 yield (1, True)
716 716 yield (astyle.style_type_number, repr(self))
717 717 xrepr.when_type(int)(xrepr_number)
718 718 xrepr.when_type(long)(xrepr_number)
719 719 xrepr.when_type(float)(xrepr_number)
720 720
721 721
722 722 def xrepr_complex(self, mode="default"):
723 723 yield (astyle.style_type_number, repr(self))
724 724 xrepr.when_type(complex)(xrepr_number)
725 725
726 726
727 727 def xrepr_datetime(self, mode="default"):
728 728 if mode == "cell":
729 729 # Don't use strftime() here, as this requires year >= 1900
730 730 yield (astyle.style_type_datetime,
731 731 "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
732 732 (self.year, self.month, self.day,
733 733 self.hour, self.minute, self.second,
734 734 self.microsecond),
735 735 )
736 736 else:
737 737 yield (astyle.style_type_datetime, repr(self))
738 738 xrepr.when_type(datetime.datetime)(xrepr_datetime)
739 739
740 740
741 741 def xrepr_date(self, mode="default"):
742 742 if mode == "cell":
743 743 yield (astyle.style_type_datetime,
744 744 "%04d-%02d-%02d" % (self.year, self.month, self.day))
745 745 else:
746 746 yield (astyle.style_type_datetime, repr(self))
747 747 xrepr.when_type(datetime.date)(xrepr_date)
748 748
749 749
750 750 def xrepr_time(self, mode="default"):
751 751 if mode == "cell":
752 752 yield (astyle.style_type_datetime,
753 753 "%02d:%02d:%02d.%06d" % \
754 754 (self.hour, self.minute, self.second, self.microsecond))
755 755 else:
756 756 yield (astyle.style_type_datetime, repr(self))
757 757 xrepr.when_type(datetime.time)(xrepr_time)
758 758
759 759
760 760 def xrepr_timedelta(self, mode="default"):
761 761 yield (astyle.style_type_datetime, repr(self))
762 762 xrepr.when_type(datetime.timedelta)(xrepr_timedelta)
763 763
764 764
765 765 def xrepr_type(self, mode="default"):
766 766 if self.__module__ == "__builtin__":
767 767 yield (astyle.style_type_type, self.__name__)
768 768 else:
769 769 yield (astyle.style_type_type, "%s.%s" % (self.__module__, self.__name__))
770 770 xrepr.when_type(type)(xrepr_type)
771 771
772 772
773 773 def xrepr_exception(self, mode="default"):
774 774 if self.__class__.__module__ == "exceptions":
775 775 classname = self.__class__.__name__
776 776 else:
777 777 classname = "%s.%s" % \
778 778 (self.__class__.__module__, self.__class__.__name__)
779 779 if mode == "header" or mode == "footer":
780 780 yield (astyle.style_error, "%s: %s" % (classname, self))
781 781 else:
782 782 yield (astyle.style_error, classname)
783 783 xrepr.when_type(Exception)(xrepr_exception)
784 784
785 785
786 786 def xrepr_listtuple(self, mode="default"):
787 787 if mode == "header" or mode == "footer":
788 788 if self.__class__.__module__ == "__builtin__":
789 789 classname = self.__class__.__name__
790 790 else:
791 791 classname = "%s.%s" % \
792 792 (self.__class__.__module__,self.__class__.__name__)
793 793 yield (astyle.style_default,
794 794 "<%s object with %d items at 0x%x>" % \
795 795 (classname, len(self), id(self)))
796 796 else:
797 797 yield (-1, False)
798 798 if isinstance(self, list):
799 799 yield (astyle.style_default, "[")
800 800 end = "]"
801 801 else:
802 802 yield (astyle.style_default, "(")
803 803 end = ")"
804 804 for (i, subself) in enumerate(self):
805 805 if i:
806 806 yield (astyle.style_default, ", ")
807 807 for part in xrepr(subself, "default"):
808 808 yield part
809 809 yield (astyle.style_default, end)
810 810 xrepr.when_type(list)(xrepr_listtuple)
811 811 xrepr.when_type(tuple)(xrepr_listtuple)
812 812
813 813
814 814 def xrepr_dict(self, mode="default"):
815 815 if mode == "header" or mode == "footer":
816 816 if self.__class__.__module__ == "__builtin__":
817 817 classname = self.__class__.__name__
818 818 else:
819 819 classname = "%s.%s" % \
820 820 (self.__class__.__module__,self.__class__.__name__)
821 821 yield (astyle.style_default,
822 822 "<%s object with %d items at 0x%x>" % \
823 823 (classname, len(self), id(self)))
824 824 else:
825 825 yield (-1, False)
826 826 if isinstance(self, dict):
827 827 yield (astyle.style_default, "{")
828 828 end = "}"
829 829 else:
830 830 yield (astyle.style_default, "dictproxy((")
831 831 end = "})"
832 832 for (i, (key, value)) in enumerate(self.iteritems()):
833 833 if i:
834 834 yield (astyle.style_default, ", ")
835 835 for part in xrepr(key, "default"):
836 836 yield part
837 837 yield (astyle.style_default, ": ")
838 838 for part in xrepr(value, "default"):
839 839 yield part
840 840 yield (astyle.style_default, end)
841 841 xrepr.when_type(dict)(xrepr_dict)
842 842 xrepr.when_type(types.DictProxyType)(xrepr_dict)
843 843
844 844
845 845 def upgradexattr(attr):
846 846 """
847 847 Convert an attribute descriptor string to a real descriptor object.
848 848
849 849 If attr already is a descriptor object return it unmodified. A
850 850 ``SelfDescriptor`` will be returned if ``attr`` is ``None``. ``"foo"``
851 851 returns an ``AttributeDescriptor`` for the attribute named ``"foo"``.
852 852 ``"foo()"`` returns a ``MethodDescriptor`` for the method named ``"foo"``.
853 853 ``"-foo"`` will return an ``IterAttributeDescriptor`` for the attribute
854 854 named ``"foo"`` and ``"-foo()"`` will return an ``IterMethodDescriptor``
855 855 for the method named ``"foo"``. Furthermore integers will return the appropriate
856 856 ``IndexDescriptor`` and callables will return a ``FunctionDescriptor``.
857 857 """
858 858 if attr is None:
859 859 return selfdescriptor
860 860 elif isinstance(attr, Descriptor):
861 861 return attr
862 862 elif isinstance(attr, basestring):
863 863 if attr.endswith("()"):
864 864 if attr.startswith("-"):
865 865 return IterMethodDescriptor(attr[1:-2])
866 866 else:
867 867 return MethodDescriptor(attr[:-2])
868 868 else:
869 869 if attr.startswith("-"):
870 870 return IterAttributeDescriptor(attr[1:])
871 871 else:
872 872 return AttributeDescriptor(attr)
873 873 elif isinstance(attr, (int, long)):
874 874 return IndexDescriptor(attr)
875 875 elif callable(attr):
876 876 return FunctionDescriptor(attr)
877 877 else:
878 878 raise TypeError("can't handle descriptor %r" % attr)
879 879
880 880
881 881 def xattrs(item, mode="default"):
882 882 """
883 883 Generic function that returns an iterable of attribute descriptors
884 884 to be used for displaying the attributes ob the object ``item`` in display
885 885 mode ``mode``.
886 886
887 887 There are two possible modes:
888 888
889 889 ``"detail"``
890 890 The ``Display`` object wants to display a detailed list of the object
891 891 attributes.
892 892
893 893 ``"default"``
894 894 The ``Display`` object wants to display the object in a list view.
895 895
896 896 If no implementation is registered for the object ``item`` ``xattrs`` falls
897 897 back to trying the ``__xattrs__`` method of the object. If this doesn't
898 898 exist either, ``dir(item)`` is used for ``"detail"`` mode and ``(None,)``
899 899 for ``"default"`` mode.
900 900
901 901 The implementation must yield attribute descriptors (see the class
902 902 ``Descriptor`` for more info). The ``__xattrs__`` method may also return
903 903 attribute descriptor strings (and ``None``) which will be converted to real
904 904 descriptors by ``upgradexattr()``.
905 905 """
906 906 try:
907 907 func = item.__xattrs__
908 908 except AttributeError:
909 909 if mode == "detail":
910 910 for attrname in dir(item):
911 911 yield AttributeDescriptor(attrname)
912 912 else:
913 913 yield selfdescriptor
914 914 else:
915 915 for attr in func(mode):
916 916 yield upgradexattr(attr)
917 917 xattrs = simplegeneric.generic(xattrs)
918 918
919 919
920 920 def xattrs_complex(self, mode="default"):
921 921 if mode == "detail":
922 922 return (AttributeDescriptor("real"), AttributeDescriptor("imag"))
923 923 return (selfdescriptor,)
924 924 xattrs.when_type(complex)(xattrs_complex)
925 925
926 926
927 927 def _isdict(item):
928 928 try:
929 929 itermeth = item.__class__.__iter__
930 930 except (AttributeError, TypeError):
931 931 return False
932 932 return itermeth is dict.__iter__ or itermeth is types.DictProxyType.__iter__
933 933
934 934
935 935 def _isstr(item):
936 936 if not isinstance(item, basestring):
937 937 return False
938 938 try:
939 939 itermeth = item.__class__.__iter__
940 940 except AttributeError:
941 941 return True
942 942 return False # ``__iter__`` has been redefined
943 943
944 944
945 945 def xiter(item):
946 946 """
947 947 Generic function that implements iteration for pipeline expression. If no
948 948 implementation is registered for ``item`` ``xiter`` falls back to ``iter``.
949 949 """
950 950 try:
951 951 func = item.__xiter__
952 952 except AttributeError:
953 953 if _isdict(item):
954 954 def items(item):
955 955 fields = ("key", "value")
956 956 for (key, value) in item.iteritems():
957 957 yield Fields(fields, key=key, value=value)
958 958 return items(item)
959 959 elif isinstance(item, new.module):
960 960 def items(item):
961 961 fields = ("key", "value")
962 962 for key in sorted(item.__dict__):
963 963 yield Fields(fields, key=key, value=getattr(item, key))
964 964 return items(item)
965 965 elif _isstr(item):
966 966 if not item:
967 967 raise ValueError("can't enter empty string")
968 968 lines = item.splitlines()
969 969 if len(lines) == 1:
970 970 def iterone(item):
971 971 yield item
972 972 return iterone(item)
973 973 else:
974 974 return iter(lines)
975 975 return iter(item)
976 976 else:
977 977 return iter(func()) # iter() just to be safe
978 978 xiter = simplegeneric.generic(xiter)
979 979
980 980
981 981 class ichain(Pipe):
982 982 """
983 983 Chains multiple ``Table``s into one.
984 984 """
985 985
986 986 def __init__(self, *iters):
987 987 self.iters = iters
988 988
989 989 def __iter__(self):
990 990 return itertools.chain(*self.iters)
991 991
992 992 def __xrepr__(self, mode="default"):
993 993 if mode == "header" or mode == "footer":
994 994 for (i, item) in enumerate(self.iters):
995 995 if i:
996 996 yield (astyle.style_default, "+")
997 997 if isinstance(item, Pipe):
998 998 yield (astyle.style_default, "(")
999 999 for part in xrepr(item, mode):
1000 1000 yield part
1001 1001 if isinstance(item, Pipe):
1002 1002 yield (astyle.style_default, ")")
1003 1003 else:
1004 1004 yield (astyle.style_default, repr(self))
1005 1005
1006 1006 def __repr__(self):
1007 1007 args = ", ".join([repr(it) for it in self.iters])
1008 1008 return "%s.%s(%s)" % \
1009 1009 (self.__class__.__module__, self.__class__.__name__, args)
1010 1010
1011 1011
1012 1012 class ifile(path.path):
1013 1013 """
1014 1014 file (or directory) object.
1015 1015 """
1016 1016
1017 1017 def getmode(self):
1018 1018 return self.stat().st_mode
1019 1019 mode = property(getmode, None, None, "Access mode")
1020 1020
1021 1021 def gettype(self):
1022 1022 data = [
1023 1023 (stat.S_ISREG, "file"),
1024 1024 (stat.S_ISDIR, "dir"),
1025 1025 (stat.S_ISCHR, "chardev"),
1026 1026 (stat.S_ISBLK, "blockdev"),
1027 1027 (stat.S_ISFIFO, "fifo"),
1028 1028 (stat.S_ISLNK, "symlink"),
1029 1029 (stat.S_ISSOCK,"socket"),
1030 1030 ]
1031 1031 lstat = self.lstat()
1032 1032 if lstat is not None:
1033 1033 types = set([text for (func, text) in data if func(lstat.st_mode)])
1034 1034 else:
1035 1035 types = set()
1036 1036 m = self.mode
1037 1037 types.update([text for (func, text) in data if func(m)])
1038 1038 return ", ".join(types)
1039 1039 type = property(gettype, None, None, "file type (file, directory, link, etc.)")
1040 1040
1041 1041 def getmodestr(self):
1042 1042 m = self.mode
1043 1043 data = [
1044 1044 (stat.S_IRUSR, "-r"),
1045 1045 (stat.S_IWUSR, "-w"),
1046 1046 (stat.S_IXUSR, "-x"),
1047 1047 (stat.S_IRGRP, "-r"),
1048 1048 (stat.S_IWGRP, "-w"),
1049 1049 (stat.S_IXGRP, "-x"),
1050 1050 (stat.S_IROTH, "-r"),
1051 1051 (stat.S_IWOTH, "-w"),
1052 1052 (stat.S_IXOTH, "-x"),
1053 1053 ]
1054 1054 return "".join([text[bool(m&bit)] for (bit, text) in data])
1055 1055
1056 1056 modestr = property(getmodestr, None, None, "Access mode as string")
1057 1057
1058 1058 def getblocks(self):
1059 1059 return self.stat().st_blocks
1060 1060 blocks = property(getblocks, None, None, "File size in blocks")
1061 1061
1062 1062 def getblksize(self):
1063 1063 return self.stat().st_blksize
1064 1064 blksize = property(getblksize, None, None, "Filesystem block size")
1065 1065
1066 1066 def getdev(self):
1067 1067 return self.stat().st_dev
1068 1068 dev = property(getdev)
1069 1069
1070 1070 def getnlink(self):
1071 1071 return self.stat().st_nlink
1072 1072 nlink = property(getnlink, None, None, "Number of links")
1073 1073
1074 1074 def getuid(self):
1075 1075 return self.stat().st_uid
1076 1076 uid = property(getuid, None, None, "User id of file owner")
1077 1077
1078 1078 def getgid(self):
1079 1079 return self.stat().st_gid
1080 1080 gid = property(getgid, None, None, "Group id of file owner")
1081 1081
1082 1082 def getowner(self):
1083 1083 stat = self.stat()
1084 1084 try:
1085 1085 return pwd.getpwuid(stat.st_uid).pw_name
1086 1086 except KeyError:
1087 1087 return stat.st_uid
1088 1088 owner = property(getowner, None, None, "Owner name (or id)")
1089 1089
1090 1090 def getgroup(self):
1091 1091 stat = self.stat()
1092 1092 try:
1093 1093 return grp.getgrgid(stat.st_gid).gr_name
1094 1094 except KeyError:
1095 1095 return stat.st_gid
1096 1096 group = property(getgroup, None, None, "Group name (or id)")
1097 1097
1098 1098 def getadate(self):
1099 1099 return datetime.datetime.utcfromtimestamp(self.atime)
1100 1100 adate = property(getadate, None, None, "Access date")
1101 1101
1102 1102 def getcdate(self):
1103 1103 return datetime.datetime.utcfromtimestamp(self.ctime)
1104 1104 cdate = property(getcdate, None, None, "Creation date")
1105 1105
1106 1106 def getmdate(self):
1107 1107 return datetime.datetime.utcfromtimestamp(self.mtime)
1108 1108 mdate = property(getmdate, None, None, "Modification date")
1109 1109
1110 1110 def mimetype(self):
1111 1111 """
1112 1112 Return MIME type guessed from the extension.
1113 1113 """
1114 1114 return mimetypes.guess_type(self.basename())[0]
1115 1115
1116 1116 def encoding(self):
1117 1117 """
1118 1118 Return guessed compression (like "compress" or "gzip").
1119 1119 """
1120 1120 return mimetypes.guess_type(self.basename())[1]
1121 1121
1122 1122 def __repr__(self):
1123 1123 return "ifile(%s)" % path._base.__repr__(self)
1124 1124
1125 1125 if sys.platform == "win32":
1126 1126 defaultattrs = (None, "type", "size", "modestr", "mdate")
1127 1127 else:
1128 1128 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
1129 1129
1130 1130 def __xattrs__(self, mode="default"):
1131 1131 if mode == "detail":
1132 1132 return (
1133 1133 "name",
1134 1134 "basename()",
1135 1135 "abspath()",
1136 1136 "realpath()",
1137 1137 "type",
1138 1138 "mode",
1139 1139 "modestr",
1140 1140 "stat()",
1141 1141 "lstat()",
1142 1142 "uid",
1143 1143 "gid",
1144 1144 "owner",
1145 1145 "group",
1146 1146 "dev",
1147 1147 "nlink",
1148 1148 "ctime",
1149 1149 "mtime",
1150 1150 "atime",
1151 1151 "cdate",
1152 1152 "mdate",
1153 1153 "adate",
1154 1154 "size",
1155 1155 "blocks",
1156 1156 "blksize",
1157 1157 "isdir()",
1158 1158 "islink()",
1159 1159 "mimetype()",
1160 1160 "encoding()",
1161 1161 "-listdir()",
1162 1162 "-dirs()",
1163 1163 "-files()",
1164 1164 "-walk()",
1165 1165 "-walkdirs()",
1166 1166 "-walkfiles()",
1167 1167 )
1168 1168 else:
1169 1169 return self.defaultattrs
1170 1170
1171 1171
1172 1172 def xiter_ifile(self):
1173 1173 if self.isdir():
1174 1174 yield (self / os.pardir).abspath()
1175 1175 for child in sorted(self.listdir()):
1176 1176 yield child
1177 1177 else:
1178 1178 f = self.open("rb")
1179 1179 for line in f:
1180 1180 yield line
1181 1181 f.close()
1182 1182 xiter.when_type(ifile)(xiter_ifile)
1183 1183
1184 1184
1185 1185 # We need to implement ``xrepr`` for ``ifile`` as a generic function, because
1186 1186 # otherwise ``xrepr_str`` would kick in.
1187 1187 def xrepr_ifile(self, mode="default"):
1188 1188 try:
1189 1189 if self.isdir():
1190 1190 name = "idir"
1191 1191 style = astyle.style_dir
1192 1192 else:
1193 1193 name = "ifile"
1194 1194 style = astyle.style_file
1195 1195 except IOError:
1196 1196 name = "ifile"
1197 1197 style = astyle.style_default
1198 1198 if mode in ("cell", "header", "footer"):
1199 1199 abspath = repr(path._base(self.normpath()))
1200 1200 if abspath.startswith("u"):
1201 1201 abspath = abspath[2:-1]
1202 1202 else:
1203 1203 abspath = abspath[1:-1]
1204 1204 if mode == "cell":
1205 1205 yield (style, abspath)
1206 1206 else:
1207 1207 yield (style, "%s(%s)" % (name, abspath))
1208 1208 else:
1209 1209 yield (style, repr(self))
1210 1210 xrepr.when_type(ifile)(xrepr_ifile)
1211 1211
1212 1212
1213 1213 class ils(Table):
1214 1214 """
1215 1215 List the current (or a specified) directory.
1216 1216
1217 1217 Examples::
1218 1218
1219 1219 >>> ils
1220 1220 <class 'IPython.extensions.ipipe.ils'>
1221 1221 >>> ils("/usr/local/lib/python2.4")
1222 1222 IPython.extensions.ipipe.ils('/usr/local/lib/python2.4')
1223 1223 >>> ils("~")
1224 1224 IPython.extensions.ipipe.ils('/home/fperez')
1225 1225 # all-random
1226 1226 """
1227 1227 def __init__(self, base=os.curdir, dirs=True, files=True):
1228 1228 self.base = os.path.expanduser(base)
1229 1229 self.dirs = dirs
1230 1230 self.files = files
1231 1231
1232 1232 def __iter__(self):
1233 1233 base = ifile(self.base)
1234 1234 yield (base / os.pardir).abspath()
1235 1235 for child in sorted(base.listdir()):
1236 1236 if self.dirs:
1237 1237 if self.files:
1238 1238 yield child
1239 1239 else:
1240 1240 if child.isdir():
1241 1241 yield child
1242 1242 elif self.files:
1243 1243 if not child.isdir():
1244 1244 yield child
1245 1245
1246 1246 def __xrepr__(self, mode="default"):
1247 1247 return xrepr(ifile(self.base), mode)
1248 1248
1249 1249 def __repr__(self):
1250 1250 return "%s.%s(%r)" % \
1251 1251 (self.__class__.__module__, self.__class__.__name__, self.base)
1252 1252
1253 1253
1254 1254 class iglob(Table):
1255 1255 """
1256 1256 List all files and directories matching a specified pattern.
1257 1257 (See ``glob.glob()`` for more info.).
1258 1258
1259 1259 Examples::
1260 1260
1261 1261 >>> iglob("*.py")
1262 1262 IPython.extensions.ipipe.iglob('*.py')
1263 1263 """
1264 1264 def __init__(self, glob):
1265 1265 self.glob = glob
1266 1266
1267 1267 def __iter__(self):
1268 1268 for name in glob.glob(self.glob):
1269 1269 yield ifile(name)
1270 1270
1271 1271 def __xrepr__(self, mode="default"):
1272 1272 if mode == "header" or mode == "footer" or mode == "cell":
1273 1273 yield (astyle.style_default,
1274 1274 "%s(%r)" % (self.__class__.__name__, self.glob))
1275 1275 else:
1276 1276 yield (astyle.style_default, repr(self))
1277 1277
1278 1278 def __repr__(self):
1279 1279 return "%s.%s(%r)" % \
1280 1280 (self.__class__.__module__, self.__class__.__name__, self.glob)
1281 1281
1282 1282
1283 1283 class iwalk(Table):
1284 1284 """
1285 1285 List all files and directories in a directory and it's subdirectory::
1286 1286
1287 1287 >>> iwalk
1288 1288 <class 'IPython.extensions.ipipe.iwalk'>
1289 1289 >>> iwalk("/usr/lib")
1290 1290 IPython.extensions.ipipe.iwalk('/usr/lib')
1291 1291 >>> iwalk("~")
1292 1292 IPython.extensions.ipipe.iwalk('/home/fperez') # random
1293 1293
1294 1294 """
1295 1295 def __init__(self, base=os.curdir, dirs=True, files=True):
1296 1296 self.base = os.path.expanduser(base)
1297 1297 self.dirs = dirs
1298 1298 self.files = files
1299 1299
1300 1300 def __iter__(self):
1301 1301 for (dirpath, dirnames, filenames) in os.walk(self.base):
1302 1302 if self.dirs:
1303 1303 for name in sorted(dirnames):
1304 1304 yield ifile(os.path.join(dirpath, name))
1305 1305 if self.files:
1306 1306 for name in sorted(filenames):
1307 1307 yield ifile(os.path.join(dirpath, name))
1308 1308
1309 1309 def __xrepr__(self, mode="default"):
1310 1310 if mode == "header" or mode == "footer" or mode == "cell":
1311 1311 yield (astyle.style_default,
1312 1312 "%s(%r)" % (self.__class__.__name__, self.base))
1313 1313 else:
1314 1314 yield (astyle.style_default, repr(self))
1315 1315
1316 1316 def __repr__(self):
1317 1317 return "%s.%s(%r)" % \
1318 1318 (self.__class__.__module__, self.__class__.__name__, self.base)
1319 1319
1320 1320
1321 1321 class ipwdentry(object):
1322 1322 """
1323 1323 ``ipwdentry`` objects encapsulate entries in the Unix user account and
1324 1324 password database.
1325 1325 """
1326 1326 def __init__(self, id):
1327 1327 self._id = id
1328 1328 self._entry = None
1329 1329
1330 1330 def __eq__(self, other):
1331 1331 return self.__class__ is other.__class__ and self._id == other._id
1332 1332
1333 1333 def __ne__(self, other):
1334 1334 return self.__class__ is not other.__class__ or self._id != other._id
1335 1335
1336 1336 def _getentry(self):
1337 1337 if self._entry is None:
1338 1338 if isinstance(self._id, basestring):
1339 1339 self._entry = pwd.getpwnam(self._id)
1340 1340 else:
1341 1341 self._entry = pwd.getpwuid(self._id)
1342 1342 return self._entry
1343 1343
1344 1344 def getname(self):
1345 1345 if isinstance(self._id, basestring):
1346 1346 return self._id
1347 1347 else:
1348 1348 return self._getentry().pw_name
1349 1349 name = property(getname, None, None, "User name")
1350 1350
1351 1351 def getpasswd(self):
1352 1352 return self._getentry().pw_passwd
1353 1353 passwd = property(getpasswd, None, None, "Password")
1354 1354
1355 1355 def getuid(self):
1356 1356 if isinstance(self._id, basestring):
1357 1357 return self._getentry().pw_uid
1358 1358 else:
1359 1359 return self._id
1360 1360 uid = property(getuid, None, None, "User id")
1361 1361
1362 1362 def getgid(self):
1363 1363 return self._getentry().pw_gid
1364 1364 gid = property(getgid, None, None, "Primary group id")
1365 1365
1366 1366 def getgroup(self):
1367 1367 return igrpentry(self.gid)
1368 1368 group = property(getgroup, None, None, "Group")
1369 1369
1370 1370 def getgecos(self):
1371 1371 return self._getentry().pw_gecos
1372 1372 gecos = property(getgecos, None, None, "Information (e.g. full user name)")
1373 1373
1374 1374 def getdir(self):
1375 1375 return self._getentry().pw_dir
1376 1376 dir = property(getdir, None, None, "$HOME directory")
1377 1377
1378 1378 def getshell(self):
1379 1379 return self._getentry().pw_shell
1380 1380 shell = property(getshell, None, None, "Login shell")
1381 1381
1382 1382 def __xattrs__(self, mode="default"):
1383 1383 return ("name", "passwd", "uid", "gid", "gecos", "dir", "shell")
1384 1384
1385 1385 def __repr__(self):
1386 1386 return "%s.%s(%r)" % \
1387 1387 (self.__class__.__module__, self.__class__.__name__, self._id)
1388 1388
1389 1389
1390 1390 class ipwd(Table):
1391 1391 """
1392 1392 List all entries in the Unix user account and password database.
1393 1393
1394 1394 Example::
1395 1395
1396 1396 >>> ipwd | isort("uid")
1397 1397 <IPython.extensions.ipipe.isort key='uid' reverse=False at 0x849efec>
1398 1398 # random
1399 1399 """
1400 1400 def __iter__(self):
1401 1401 for entry in pwd.getpwall():
1402 1402 yield ipwdentry(entry.pw_name)
1403 1403
1404 1404 def __xrepr__(self, mode="default"):
1405 1405 if mode == "header" or mode == "footer" or mode == "cell":
1406 1406 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1407 1407 else:
1408 1408 yield (astyle.style_default, repr(self))
1409 1409
1410 1410
1411 1411 class igrpentry(object):
1412 1412 """
1413 1413 ``igrpentry`` objects encapsulate entries in the Unix group database.
1414 1414 """
1415 1415 def __init__(self, id):
1416 1416 self._id = id
1417 1417 self._entry = None
1418 1418
1419 1419 def __eq__(self, other):
1420 1420 return self.__class__ is other.__class__ and self._id == other._id
1421 1421
1422 1422 def __ne__(self, other):
1423 1423 return self.__class__ is not other.__class__ or self._id != other._id
1424 1424
1425 1425 def _getentry(self):
1426 1426 if self._entry is None:
1427 1427 if isinstance(self._id, basestring):
1428 1428 self._entry = grp.getgrnam(self._id)
1429 1429 else:
1430 1430 self._entry = grp.getgrgid(self._id)
1431 1431 return self._entry
1432 1432
1433 1433 def getname(self):
1434 1434 if isinstance(self._id, basestring):
1435 1435 return self._id
1436 1436 else:
1437 1437 return self._getentry().gr_name
1438 1438 name = property(getname, None, None, "Group name")
1439 1439
1440 1440 def getpasswd(self):
1441 1441 return self._getentry().gr_passwd
1442 1442 passwd = property(getpasswd, None, None, "Password")
1443 1443
1444 1444 def getgid(self):
1445 1445 if isinstance(self._id, basestring):
1446 1446 return self._getentry().gr_gid
1447 1447 else:
1448 1448 return self._id
1449 1449 gid = property(getgid, None, None, "Group id")
1450 1450
1451 1451 def getmem(self):
1452 1452 return self._getentry().gr_mem
1453 1453 mem = property(getmem, None, None, "Members")
1454 1454
1455 1455 def __xattrs__(self, mode="default"):
1456 1456 return ("name", "passwd", "gid", "mem")
1457 1457
1458 1458 def __xrepr__(self, mode="default"):
1459 1459 if mode == "header" or mode == "footer" or mode == "cell":
1460 1460 yield (astyle.style_default, "group ")
1461 1461 try:
1462 1462 yield (astyle.style_default, self.name)
1463 1463 except KeyError:
1464 1464 if isinstance(self._id, basestring):
1465 1465 yield (astyle.style_default, self.name_id)
1466 1466 else:
1467 1467 yield (astyle.style_type_number, str(self._id))
1468 1468 else:
1469 1469 yield (astyle.style_default, repr(self))
1470 1470
1471 1471 def __iter__(self):
1472 1472 for member in self.mem:
1473 1473 yield ipwdentry(member)
1474 1474
1475 1475 def __repr__(self):
1476 1476 return "%s.%s(%r)" % \
1477 1477 (self.__class__.__module__, self.__class__.__name__, self._id)
1478 1478
1479 1479
1480 1480 class igrp(Table):
1481 1481 """
1482 1482 This ``Table`` lists all entries in the Unix group database.
1483 1483 """
1484 1484 def __iter__(self):
1485 1485 for entry in grp.getgrall():
1486 1486 yield igrpentry(entry.gr_name)
1487 1487
1488 1488 def __xrepr__(self, mode="default"):
1489 1489 if mode == "header" or mode == "footer":
1490 1490 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1491 1491 else:
1492 1492 yield (astyle.style_default, repr(self))
1493 1493
1494 1494
1495 1495 class Fields(object):
1496 1496 def __init__(self, fieldnames, **fields):
1497 1497 self.__fieldnames = [upgradexattr(fieldname) for fieldname in fieldnames]
1498 1498 for (key, value) in fields.iteritems():
1499 1499 setattr(self, key, value)
1500 1500
1501 1501 def __xattrs__(self, mode="default"):
1502 1502 return self.__fieldnames
1503 1503
1504 1504 def __xrepr__(self, mode="default"):
1505 1505 yield (-1, False)
1506 1506 if mode == "header" or mode == "cell":
1507 1507 yield (astyle.style_default, self.__class__.__name__)
1508 1508 yield (astyle.style_default, "(")
1509 1509 for (i, f) in enumerate(self.__fieldnames):
1510 1510 if i:
1511 1511 yield (astyle.style_default, ", ")
1512 1512 yield (astyle.style_default, f.name())
1513 1513 yield (astyle.style_default, "=")
1514 1514 for part in xrepr(getattr(self, f), "default"):
1515 1515 yield part
1516 1516 yield (astyle.style_default, ")")
1517 1517 elif mode == "footer":
1518 1518 yield (astyle.style_default, self.__class__.__name__)
1519 1519 yield (astyle.style_default, "(")
1520 1520 for (i, f) in enumerate(self.__fieldnames):
1521 1521 if i:
1522 1522 yield (astyle.style_default, ", ")
1523 1523 yield (astyle.style_default, f.name())
1524 1524 yield (astyle.style_default, ")")
1525 1525 else:
1526 1526 yield (astyle.style_default, repr(self))
1527 1527
1528 1528
1529 1529 class FieldTable(Table, list):
1530 1530 def __init__(self, *fields):
1531 1531 Table.__init__(self)
1532 1532 list.__init__(self)
1533 1533 self.fields = fields
1534 1534
1535 1535 def add(self, **fields):
1536 1536 self.append(Fields(self.fields, **fields))
1537 1537
1538 1538 def __xrepr__(self, mode="default"):
1539 1539 yield (-1, False)
1540 1540 if mode == "header" or mode == "footer":
1541 1541 yield (astyle.style_default, self.__class__.__name__)
1542 1542 yield (astyle.style_default, "(")
1543 1543 for (i, f) in enumerate(self.__fieldnames):
1544 1544 if i:
1545 1545 yield (astyle.style_default, ", ")
1546 1546 yield (astyle.style_default, f)
1547 1547 yield (astyle.style_default, ")")
1548 1548 else:
1549 1549 yield (astyle.style_default, repr(self))
1550 1550
1551 1551 def __repr__(self):
1552 1552 return "<%s.%s object with fields=%r at 0x%x>" % \
1553 1553 (self.__class__.__module__, self.__class__.__name__,
1554 1554 ", ".join(map(repr, self.fields)), id(self))
1555 1555
1556 1556
1557 1557 class List(list):
1558 1558 def __xattrs__(self, mode="default"):
1559 1559 return xrange(len(self))
1560 1560
1561 1561 def __xrepr__(self, mode="default"):
1562 1562 yield (-1, False)
1563 1563 if mode == "header" or mode == "cell" or mode == "footer" or mode == "default":
1564 1564 yield (astyle.style_default, self.__class__.__name__)
1565 1565 yield (astyle.style_default, "(")
1566 1566 for (i, item) in enumerate(self):
1567 1567 if i:
1568 1568 yield (astyle.style_default, ", ")
1569 1569 for part in xrepr(item, "default"):
1570 1570 yield part
1571 1571 yield (astyle.style_default, ")")
1572 1572 else:
1573 1573 yield (astyle.style_default, repr(self))
1574 1574
1575 1575
1576 1576 class ienv(Table):
1577 1577 """
1578 1578 List environment variables.
1579 1579
1580 1580 Example::
1581 1581
1582 1582 >>> ienv
1583 1583 <class 'IPython.extensions.ipipe.ienv'>
1584 1584 """
1585 1585
1586 1586 def __iter__(self):
1587 1587 fields = ("key", "value")
1588 1588 for (key, value) in os.environ.iteritems():
1589 1589 yield Fields(fields, key=key, value=value)
1590 1590
1591 1591 def __xrepr__(self, mode="default"):
1592 1592 if mode == "header" or mode == "cell":
1593 1593 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1594 1594 else:
1595 1595 yield (astyle.style_default, repr(self))
1596 1596
1597 1597
1598 1598 class ihist(Table):
1599 1599 """
1600 1600 IPython input history
1601 1601
1602 1602 Example::
1603 1603
1604 1604 >>> ihist
1605 1605 <class 'IPython.extensions.ipipe.ihist'>
1606 1606 >>> ihist(True) # raw mode
1607 1607 <IPython.extensions.ipipe.ihist object at 0x849602c> # random
1608 1608 """
1609 1609 def __init__(self, raw=True):
1610 1610 self.raw = raw
1611 1611
1612 1612 def __iter__(self):
1613 1613 api = ipapi.get()
1614 1614 if self.raw:
1615 1615 for line in api.input_hist_raw:
1616 1616 yield line.rstrip("\n")
1617 1617 else:
1618 1618 for line in api.input_hist:
1619 1619 yield line.rstrip("\n")
1620 1620
1621 1621
1622 1622 class Alias(object):
1623 1623 """
1624 1624 Entry in the alias table
1625 1625 """
1626 1626 def __init__(self, name, args, command):
1627 1627 self.name = name
1628 1628 self.args = args
1629 1629 self.command = command
1630 1630
1631 1631 def __xattrs__(self, mode="default"):
1632 1632 return ("name", "args", "command")
1633 1633
1634 1634
1635 1635 class ialias(Table):
1636 1636 """
1637 1637 IPython alias list
1638 1638
1639 1639 Example::
1640 1640
1641 1641 >>> ialias
1642 1642 <class 'IPython.extensions.ipipe.ialias'>
1643 1643 """
1644 1644 def __iter__(self):
1645 1645 api = ipapi.get()
1646 1646
1647 1647 for (name, (args, command)) in api.alias_manager.alias_table.iteritems():
1648 1648 yield Alias(name, args, command)
1649 1649
1650 1650
1651 1651 class icsv(Pipe):
1652 1652 """
1653 1653 This ``Pipe`` turns the input (with must be a pipe outputting lines
1654 1654 or an ``ifile``) into lines of CVS columns.
1655 1655 """
1656 1656 def __init__(self, **csvargs):
1657 1657 """
1658 1658 Create an ``icsv`` object. ``cvsargs`` will be passed through as
1659 1659 keyword arguments to ``cvs.reader()``.
1660 1660 """
1661 1661 self.csvargs = csvargs
1662 1662
1663 1663 def __iter__(self):
1664 1664 input = self.input
1665 1665 if isinstance(input, ifile):
1666 1666 input = input.open("rb")
1667 1667 reader = csv.reader(input, **self.csvargs)
1668 1668 for line in reader:
1669 1669 yield List(line)
1670 1670
1671 1671 def __xrepr__(self, mode="default"):
1672 1672 yield (-1, False)
1673 1673 if mode == "header" or mode == "footer":
1674 1674 input = getattr(self, "input", None)
1675 1675 if input is not None:
1676 1676 for part in xrepr(input, mode):
1677 1677 yield part
1678 1678 yield (astyle.style_default, " | ")
1679 1679 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1680 1680 for (i, (name, value)) in enumerate(self.csvargs.iteritems()):
1681 1681 if i:
1682 1682 yield (astyle.style_default, ", ")
1683 1683 yield (astyle.style_default, name)
1684 1684 yield (astyle.style_default, "=")
1685 1685 for part in xrepr(value, "default"):
1686 1686 yield part
1687 1687 yield (astyle.style_default, ")")
1688 1688 else:
1689 1689 yield (astyle.style_default, repr(self))
1690 1690
1691 1691 def __repr__(self):
1692 1692 args = ", ".join(["%s=%r" % item for item in self.csvargs.iteritems()])
1693 1693 return "<%s.%s %s at 0x%x>" % \
1694 1694 (self.__class__.__module__, self.__class__.__name__, args, id(self))
1695 1695
1696 1696
1697 1697 class ix(Table):
1698 1698 """
1699 1699 Execute a system command and list its output as lines
1700 1700 (similar to ``os.popen()``).
1701 1701
1702 1702 Examples::
1703 1703
1704 1704 >>> ix("ps x")
1705 1705 IPython.extensions.ipipe.ix('ps x')
1706 1706
1707 1707 >>> ix("find .") | ifile
1708 1708 <IPython.extensions.ipipe.ieval expr=<class 'IPython.extensions.ipipe.ifile'> at 0x8509d2c>
1709 1709 # random
1710 1710 """
1711 1711 def __init__(self, cmd):
1712 1712 self.cmd = cmd
1713 1713 self._pipeout = None
1714 1714
1715 1715 def __iter__(self):
1716 1716 (_pipein, self._pipeout) = os.popen4(self.cmd)
1717 1717 _pipein.close()
1718 1718 for l in self._pipeout:
1719 1719 yield l.rstrip("\r\n")
1720 1720 self._pipeout.close()
1721 1721 self._pipeout = None
1722 1722
1723 1723 def __del__(self):
1724 1724 if self._pipeout is not None and not self._pipeout.closed:
1725 1725 self._pipeout.close()
1726 1726 self._pipeout = None
1727 1727
1728 1728 def __xrepr__(self, mode="default"):
1729 1729 if mode == "header" or mode == "footer":
1730 1730 yield (astyle.style_default,
1731 1731 "%s(%r)" % (self.__class__.__name__, self.cmd))
1732 1732 else:
1733 1733 yield (astyle.style_default, repr(self))
1734 1734
1735 1735 def __repr__(self):
1736 1736 return "%s.%s(%r)" % \
1737 1737 (self.__class__.__module__, self.__class__.__name__, self.cmd)
1738 1738
1739 1739
1740 1740 class ifilter(Pipe):
1741 1741 """
1742 1742 Filter an input pipe. Only objects where an expression evaluates to true
1743 1743 (and doesn't raise an exception) are listed.
1744 1744
1745 1745 Examples::
1746 1746
1747 1747 >>> ils | ifilter("_.isfile() and size>1000")
1748 1748 >>> igrp | ifilter("len(mem)")
1749 1749 >>> sys.modules | ifilter(lambda _:_.value is not None)
1750 1750 # all-random
1751 1751 """
1752 1752
1753 1753 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1754 1754 """
1755 1755 Create an ``ifilter`` object. ``expr`` can be a callable or a string
1756 1756 containing an expression. ``globals`` will be used as the global
1757 1757 namespace for calling string expressions (defaulting to IPython's
1758 1758 user namespace). ``errors`` specifies how exception during evaluation
1759 1759 of ``expr`` are handled:
1760 1760
1761 1761 ``"drop"``
1762 1762 drop all items that have errors;
1763 1763
1764 1764 ``"keep"``
1765 1765 keep all items that have errors;
1766 1766
1767 1767 ``"keeperror"``
1768 1768 keep the exception of all items that have errors;
1769 1769
1770 1770 ``"raise"``
1771 1771 raise the exception;
1772 1772
1773 1773 ``"raiseifallfail"``
1774 1774 raise the first exception if all items have errors; otherwise drop
1775 1775 those with errors (this is the default).
1776 1776 """
1777 1777 self.expr = expr
1778 1778 self.globals = globals
1779 1779 self.errors = errors
1780 1780
1781 1781 def __iter__(self):
1782 1782 if callable(self.expr):
1783 1783 test = self.expr
1784 1784 else:
1785 1785 g = getglobals(self.globals)
1786 1786 expr = compile(self.expr, "ipipe-expression", "eval")
1787 1787 def test(item):
1788 1788 return eval(expr, g, AttrNamespace(item))
1789 1789
1790 1790 ok = 0
1791 1791 exc_info = None
1792 1792 for item in xiter(self.input):
1793 1793 try:
1794 1794 if test(item):
1795 1795 yield item
1796 1796 ok += 1
1797 1797 except (KeyboardInterrupt, SystemExit):
1798 1798 raise
1799 except Exception, exc:
1799 except Exception as exc:
1800 1800 if self.errors == "drop":
1801 1801 pass # Ignore errors
1802 1802 elif self.errors == "keep":
1803 1803 yield item
1804 1804 elif self.errors == "keeperror":
1805 1805 yield exc
1806 1806 elif self.errors == "raise":
1807 1807 raise
1808 1808 elif self.errors == "raiseifallfail":
1809 1809 if exc_info is None:
1810 1810 exc_info = sys.exc_info()
1811 1811 if not ok and exc_info is not None:
1812 1812 raise exc_info[0], exc_info[1], exc_info[2]
1813 1813
1814 1814 def __xrepr__(self, mode="default"):
1815 1815 if mode == "header" or mode == "footer":
1816 1816 input = getattr(self, "input", None)
1817 1817 if input is not None:
1818 1818 for part in xrepr(input, mode):
1819 1819 yield part
1820 1820 yield (astyle.style_default, " | ")
1821 1821 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1822 1822 for part in xrepr(self.expr, "default"):
1823 1823 yield part
1824 1824 yield (astyle.style_default, ")")
1825 1825 else:
1826 1826 yield (astyle.style_default, repr(self))
1827 1827
1828 1828 def __repr__(self):
1829 1829 return "<%s.%s expr=%r at 0x%x>" % \
1830 1830 (self.__class__.__module__, self.__class__.__name__,
1831 1831 self.expr, id(self))
1832 1832
1833 1833
1834 1834 class ieval(Pipe):
1835 1835 """
1836 1836 Evaluate an expression for each object in the input pipe.
1837 1837
1838 1838 Examples::
1839 1839
1840 1840 >>> ils | ieval("_.abspath()")
1841 1841 # random
1842 1842 >>> sys.path | ieval(ifile)
1843 1843 # random
1844 1844 """
1845 1845
1846 1846 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1847 1847 """
1848 1848 Create an ``ieval`` object. ``expr`` can be a callable or a string
1849 1849 containing an expression. For the meaning of ``globals`` and
1850 1850 ``errors`` see ``ifilter``.
1851 1851 """
1852 1852 self.expr = expr
1853 1853 self.globals = globals
1854 1854 self.errors = errors
1855 1855
1856 1856 def __iter__(self):
1857 1857 if callable(self.expr):
1858 1858 do = self.expr
1859 1859 else:
1860 1860 g = getglobals(self.globals)
1861 1861 expr = compile(self.expr, "ipipe-expression", "eval")
1862 1862 def do(item):
1863 1863 return eval(expr, g, AttrNamespace(item))
1864 1864
1865 1865 ok = 0
1866 1866 exc_info = None
1867 1867 for item in xiter(self.input):
1868 1868 try:
1869 1869 yield do(item)
1870 1870 except (KeyboardInterrupt, SystemExit):
1871 1871 raise
1872 except Exception, exc:
1872 except Exception as exc:
1873 1873 if self.errors == "drop":
1874 1874 pass # Ignore errors
1875 1875 elif self.errors == "keep":
1876 1876 yield item
1877 1877 elif self.errors == "keeperror":
1878 1878 yield exc
1879 1879 elif self.errors == "raise":
1880 1880 raise
1881 1881 elif self.errors == "raiseifallfail":
1882 1882 if exc_info is None:
1883 1883 exc_info = sys.exc_info()
1884 1884 if not ok and exc_info is not None:
1885 1885 raise exc_info[0], exc_info[1], exc_info[2]
1886 1886
1887 1887 def __xrepr__(self, mode="default"):
1888 1888 if mode == "header" or mode == "footer":
1889 1889 input = getattr(self, "input", None)
1890 1890 if input is not None:
1891 1891 for part in xrepr(input, mode):
1892 1892 yield part
1893 1893 yield (astyle.style_default, " | ")
1894 1894 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1895 1895 for part in xrepr(self.expr, "default"):
1896 1896 yield part
1897 1897 yield (astyle.style_default, ")")
1898 1898 else:
1899 1899 yield (astyle.style_default, repr(self))
1900 1900
1901 1901 def __repr__(self):
1902 1902 return "<%s.%s expr=%r at 0x%x>" % \
1903 1903 (self.__class__.__module__, self.__class__.__name__,
1904 1904 self.expr, id(self))
1905 1905
1906 1906
1907 1907 class ienum(Pipe):
1908 1908 """
1909 1909 Enumerate the input pipe (i.e. wrap each input object in an object
1910 1910 with ``index`` and ``object`` attributes).
1911 1911
1912 1912 Examples::
1913 1913
1914 1914 >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object")
1915 1915 """
1916 1916 skip_doctest = True
1917 1917
1918 1918 def __iter__(self):
1919 1919 fields = ("index", "object")
1920 1920 for (index, object) in enumerate(xiter(self.input)):
1921 1921 yield Fields(fields, index=index, object=object)
1922 1922
1923 1923
1924 1924 class isort(Pipe):
1925 1925 """
1926 1926 Sorts the input pipe.
1927 1927
1928 1928 Examples::
1929 1929
1930 1930 >>> ils | isort("size")
1931 1931 <IPython.extensions.ipipe.isort key='size' reverse=False at 0x849ec2c>
1932 1932 >>> ils | isort("_.isdir(), _.lower()", reverse=True)
1933 1933 <IPython.extensions.ipipe.isort key='_.isdir(), _.lower()' reverse=True at 0x849eacc>
1934 1934 # all-random
1935 1935 """
1936 1936
1937 1937 def __init__(self, key=None, globals=None, reverse=False):
1938 1938 """
1939 1939 Create an ``isort`` object. ``key`` can be a callable or a string
1940 1940 containing an expression (or ``None`` in which case the items
1941 1941 themselves will be sorted). If ``reverse`` is true the sort order
1942 1942 will be reversed. For the meaning of ``globals`` see ``ifilter``.
1943 1943 """
1944 1944 self.key = key
1945 1945 self.globals = globals
1946 1946 self.reverse = reverse
1947 1947
1948 1948 def __iter__(self):
1949 1949 if self.key is None:
1950 1950 items = sorted(xiter(self.input), reverse=self.reverse)
1951 1951 elif callable(self.key):
1952 1952 items = sorted(xiter(self.input), key=self.key, reverse=self.reverse)
1953 1953 else:
1954 1954 g = getglobals(self.globals)
1955 1955 key = compile(self.key, "ipipe-expression", "eval")
1956 1956 def realkey(item):
1957 1957 return eval(key, g, AttrNamespace(item))
1958 1958 items = sorted(xiter(self.input), key=realkey, reverse=self.reverse)
1959 1959 for item in items:
1960 1960 yield item
1961 1961
1962 1962 def __xrepr__(self, mode="default"):
1963 1963 if mode == "header" or mode == "footer":
1964 1964 input = getattr(self, "input", None)
1965 1965 if input is not None:
1966 1966 for part in xrepr(input, mode):
1967 1967 yield part
1968 1968 yield (astyle.style_default, " | ")
1969 1969 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1970 1970 for part in xrepr(self.key, "default"):
1971 1971 yield part
1972 1972 if self.reverse:
1973 1973 yield (astyle.style_default, ", ")
1974 1974 for part in xrepr(True, "default"):
1975 1975 yield part
1976 1976 yield (astyle.style_default, ")")
1977 1977 else:
1978 1978 yield (astyle.style_default, repr(self))
1979 1979
1980 1980 def __repr__(self):
1981 1981 return "<%s.%s key=%r reverse=%r at 0x%x>" % \
1982 1982 (self.__class__.__module__, self.__class__.__name__,
1983 1983 self.key, self.reverse, id(self))
1984 1984
1985 1985
1986 1986 tab = 3 # for expandtabs()
1987 1987
1988 1988 def _format(field):
1989 1989 if isinstance(field, str):
1990 1990 text = repr(field.expandtabs(tab))[1:-1]
1991 1991 elif isinstance(field, unicode):
1992 1992 text = repr(field.expandtabs(tab))[2:-1]
1993 1993 elif isinstance(field, datetime.datetime):
1994 1994 # Don't use strftime() here, as this requires year >= 1900
1995 1995 text = "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
1996 1996 (field.year, field.month, field.day,
1997 1997 field.hour, field.minute, field.second, field.microsecond)
1998 1998 elif isinstance(field, datetime.date):
1999 1999 text = "%04d-%02d-%02d" % (field.year, field.month, field.day)
2000 2000 else:
2001 2001 text = repr(field)
2002 2002 return text
2003 2003
2004 2004
2005 2005 class Display(object):
2006 2006 class __metaclass__(type):
2007 2007 def __ror__(self, input):
2008 2008 return input | self()
2009 2009
2010 2010 def __init__(self, input=None):
2011 2011 self.input = input
2012 2012
2013 2013 def __ror__(self, input):
2014 2014 self.input = input
2015 2015 return self
2016 2016
2017 2017 def display(self):
2018 2018 pass
2019 2019
2020 2020
2021 2021 class iless(Display):
2022 2022 cmd = "less --quit-if-one-screen --LONG-PROMPT --LINE-NUMBERS --chop-long-lines --shift=8 --RAW-CONTROL-CHARS"
2023 2023
2024 2024 def display(self):
2025 2025 try:
2026 2026 pager = os.popen(self.cmd, "w")
2027 2027 try:
2028 2028 for item in xiter(self.input):
2029 2029 first = False
2030 2030 for attr in xattrs(item, "default"):
2031 2031 if first:
2032 2032 first = False
2033 2033 else:
2034 2034 pager.write(" ")
2035 2035 attr = upgradexattr(attr)
2036 2036 if not isinstance(attr, SelfDescriptor):
2037 2037 pager.write(attr.name())
2038 2038 pager.write("=")
2039 2039 pager.write(str(attr.value(item)))
2040 2040 pager.write("\n")
2041 2041 finally:
2042 2042 pager.close()
2043 except Exception, exc:
2043 except Exception as exc:
2044 2044 print "%s: %s" % (exc.__class__.__name__, str(exc))
2045 2045
2046 2046
2047 2047 class _RedirectIO(object):
2048 2048 def __init__(self,*args,**kwargs):
2049 2049 """
2050 2050 Map the system output streams to self.
2051 2051 """
2052 2052 self.stream = StringIO.StringIO()
2053 2053 self.stdout = sys.stdout
2054 2054 sys.stdout = self
2055 2055 self.stderr = sys.stderr
2056 2056 sys.stderr = self
2057 2057
2058 2058 def write(self, text):
2059 2059 """
2060 2060 Write both to screen and to self.
2061 2061 """
2062 2062 self.stream.write(text)
2063 2063 self.stdout.write(text)
2064 2064 if "\n" in text:
2065 2065 self.stdout.flush()
2066 2066
2067 2067 def writelines(self, lines):
2068 2068 """
2069 2069 Write lines both to screen and to self.
2070 2070 """
2071 2071 self.stream.writelines(lines)
2072 2072 self.stdout.writelines(lines)
2073 2073 self.stdout.flush()
2074 2074
2075 2075 def restore(self):
2076 2076 """
2077 2077 Restore the default system streams.
2078 2078 """
2079 2079 self.stdout.flush()
2080 2080 self.stderr.flush()
2081 2081 sys.stdout = self.stdout
2082 2082 sys.stderr = self.stderr
2083 2083
2084 2084
2085 2085 class icap(Table):
2086 2086 """
2087 2087 Execute a python string and capture any output to stderr/stdout.
2088 2088
2089 2089 Examples::
2090 2090
2091 2091 >>> import time
2092 2092 >>> icap("for i in range(10): print i, time.sleep(0.1)")
2093 2093
2094 2094 """
2095 2095 skip_doctest = True
2096 2096
2097 2097 def __init__(self, expr, globals=None):
2098 2098 self.expr = expr
2099 2099 self.globals = globals
2100 2100 log = _RedirectIO()
2101 2101 try:
2102 2102 exec(expr, getglobals(globals))
2103 2103 finally:
2104 2104 log.restore()
2105 2105 self.stream = log.stream
2106 2106
2107 2107 def __iter__(self):
2108 2108 self.stream.seek(0)
2109 2109 for line in self.stream:
2110 2110 yield line.rstrip("\r\n")
2111 2111
2112 2112 def __xrepr__(self, mode="default"):
2113 2113 if mode == "header" or mode == "footer":
2114 2114 yield (astyle.style_default,
2115 2115 "%s(%r)" % (self.__class__.__name__, self.expr))
2116 2116 else:
2117 2117 yield (astyle.style_default, repr(self))
2118 2118
2119 2119 def __repr__(self):
2120 2120 return "%s.%s(%r)" % \
2121 2121 (self.__class__.__module__, self.__class__.__name__, self.expr)
2122 2122
2123 2123
2124 2124 def xformat(value, mode, maxlength):
2125 2125 align = None
2126 2126 full = True
2127 2127 width = 0
2128 2128 text = astyle.Text()
2129 2129 for (style, part) in xrepr(value, mode):
2130 2130 # only consider the first result
2131 2131 if align is None:
2132 2132 if isinstance(style, int):
2133 2133 # (style, text) really is (alignment, stop)
2134 2134 align = style
2135 2135 full = part
2136 2136 continue
2137 2137 else:
2138 2138 align = -1
2139 2139 full = True
2140 2140 if not isinstance(style, int):
2141 2141 text.append((style, part))
2142 2142 width += len(part)
2143 2143 if width >= maxlength and not full:
2144 2144 text.append((astyle.style_ellisis, "..."))
2145 2145 width += 3
2146 2146 break
2147 2147 if align is None: # default to left alignment
2148 2148 align = -1
2149 2149 return (align, width, text)
2150 2150
2151 2151
2152 2152
2153 2153 import astyle
2154 2154
2155 2155 class idump(Display):
2156 2156 # The approximate maximum length of a column entry
2157 2157 maxattrlength = 200
2158 2158
2159 2159 # Style for column names
2160 2160 style_header = astyle.Style.fromstr("white:black:bold")
2161 2161
2162 2162 def __init__(self, input=None, *attrs):
2163 2163 Display.__init__(self, input)
2164 2164 self.attrs = [upgradexattr(attr) for attr in attrs]
2165 2165 self.headerpadchar = " "
2166 2166 self.headersepchar = "|"
2167 2167 self.datapadchar = " "
2168 2168 self.datasepchar = "|"
2169 2169
2170 2170 def display(self):
2171 2171 stream = Term.cout
2172 2172 allattrs = []
2173 2173 attrset = set()
2174 2174 colwidths = {}
2175 2175 rows = []
2176 2176 for item in xiter(self.input):
2177 2177 row = {}
2178 2178 attrs = self.attrs
2179 2179 if not attrs:
2180 2180 attrs = xattrs(item, "default")
2181 2181 for attr in attrs:
2182 2182 if attr not in attrset:
2183 2183 allattrs.append(attr)
2184 2184 attrset.add(attr)
2185 2185 colwidths[attr] = len(attr.name())
2186 2186 try:
2187 2187 value = attr.value(item)
2188 2188 except (KeyboardInterrupt, SystemExit):
2189 2189 raise
2190 except Exception, exc:
2190 except Exception as exc:
2191 2191 value = exc
2192 2192 (align, width, text) = xformat(value, "cell", self.maxattrlength)
2193 2193 colwidths[attr] = max(colwidths[attr], width)
2194 2194 # remember alignment, length and colored parts
2195 2195 row[attr] = (align, width, text)
2196 2196 rows.append(row)
2197 2197
2198 2198 stream.write("\n")
2199 2199 for (i, attr) in enumerate(allattrs):
2200 2200 attrname = attr.name()
2201 2201 self.style_header(attrname).write(stream)
2202 2202 spc = colwidths[attr] - len(attrname)
2203 2203 if i < len(colwidths)-1:
2204 2204 stream.write(self.headerpadchar*spc)
2205 2205 stream.write(self.headersepchar)
2206 2206 stream.write("\n")
2207 2207
2208 2208 for row in rows:
2209 2209 for (i, attr) in enumerate(allattrs):
2210 2210 (align, width, text) = row[attr]
2211 2211 spc = colwidths[attr] - width
2212 2212 if align == -1:
2213 2213 text.write(stream)
2214 2214 if i < len(colwidths)-1:
2215 2215 stream.write(self.datapadchar*spc)
2216 2216 elif align == 0:
2217 2217 spc = colwidths[attr] - width
2218 2218 spc1 = spc//2
2219 2219 spc2 = spc-spc1
2220 2220 stream.write(self.datapadchar*spc1)
2221 2221 text.write(stream)
2222 2222 if i < len(colwidths)-1:
2223 2223 stream.write(self.datapadchar*spc2)
2224 2224 else:
2225 2225 stream.write(self.datapadchar*spc)
2226 2226 text.write(stream)
2227 2227 if i < len(colwidths)-1:
2228 2228 stream.write(self.datasepchar)
2229 2229 stream.write("\n")
2230 2230
2231 2231
2232 2232 class AttributeDetail(Table):
2233 2233 """
2234 2234 ``AttributeDetail`` objects are use for displaying a detailed list of object
2235 2235 attributes.
2236 2236 """
2237 2237 def __init__(self, object, descriptor):
2238 2238 self.object = object
2239 2239 self.descriptor = descriptor
2240 2240
2241 2241 def __iter__(self):
2242 2242 return self.descriptor.iter(self.object)
2243 2243
2244 2244 def name(self):
2245 2245 return self.descriptor.name()
2246 2246
2247 2247 def attrtype(self):
2248 2248 return self.descriptor.attrtype(self.object)
2249 2249
2250 2250 def valuetype(self):
2251 2251 return self.descriptor.valuetype(self.object)
2252 2252
2253 2253 def doc(self):
2254 2254 return self.descriptor.doc(self.object)
2255 2255
2256 2256 def shortdoc(self):
2257 2257 return self.descriptor.shortdoc(self.object)
2258 2258
2259 2259 def value(self):
2260 2260 return self.descriptor.value(self.object)
2261 2261
2262 2262 def __xattrs__(self, mode="default"):
2263 2263 attrs = ("name()", "attrtype()", "valuetype()", "value()", "shortdoc()")
2264 2264 if mode == "detail":
2265 2265 attrs += ("doc()",)
2266 2266 return attrs
2267 2267
2268 2268 def __xrepr__(self, mode="default"):
2269 2269 yield (-1, True)
2270 2270 valuetype = self.valuetype()
2271 2271 if valuetype is not noitem:
2272 2272 for part in xrepr(valuetype):
2273 2273 yield part
2274 2274 yield (astyle.style_default, " ")
2275 2275 yield (astyle.style_default, self.attrtype())
2276 2276 yield (astyle.style_default, " ")
2277 2277 yield (astyle.style_default, self.name())
2278 2278 yield (astyle.style_default, " of ")
2279 2279 for part in xrepr(self.object):
2280 2280 yield part
2281 2281
2282 2282
2283 2283 try:
2284 2284 from ibrowse import ibrowse
2285 2285 except ImportError:
2286 2286 # No curses (probably Windows) => try igrid
2287 2287 try:
2288 2288 from igrid import igrid
2289 2289 except ImportError:
2290 2290 # no wx either => use ``idump`` as the default display.
2291 2291 defaultdisplay = idump
2292 2292 else:
2293 2293 defaultdisplay = igrid
2294 2294 __all__.append("igrid")
2295 2295 else:
2296 2296 defaultdisplay = ibrowse
2297 2297 __all__.append("ibrowse")
2298 2298
2299 2299
2300 2300 # If we're running under IPython, register our objects with IPython's
2301 2301 # generic function ``result_display``, else install a displayhook
2302 2302 # directly as sys.displayhook
2303 2303 if generics is not None:
2304 2304 def display_display(obj):
2305 2305 return obj.display()
2306 2306 generics.result_display.when_type(Display)(display_display)
2307 2307
2308 2308 def display_tableobject(obj):
2309 2309 return display_display(defaultdisplay(obj))
2310 2310 generics.result_display.when_type(Table)(display_tableobject)
2311 2311
2312 2312 def display_tableclass(obj):
2313 2313 return display_tableobject(obj())
2314 2314 generics.result_display.when_type(Table.__metaclass__)(display_tableclass)
2315 2315 else:
2316 2316 def installdisplayhook():
2317 2317 _originalhook = sys.displayhook
2318 2318 def displayhook(obj):
2319 2319 if isinstance(obj, type) and issubclass(obj, Table):
2320 2320 obj = obj()
2321 2321 if isinstance(obj, Table):
2322 2322 obj = defaultdisplay(obj)
2323 2323 if isinstance(obj, Display):
2324 2324 return obj.display()
2325 2325 else:
2326 2326 _originalhook(obj)
2327 2327 sys.displayhook = displayhook
2328 2328 installdisplayhook()
@@ -1,343 +1,343 b''
1 1 # encoding: utf-8
2 2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
3 3 """
4 4 frontendbase provides an interface and base class for GUI frontends for
5 5 IPython.kernel/IPython.kernel.core.
6 6
7 7 Frontend implementations will likely want to subclass FrontEndBase.
8 8
9 9 Author: Barry Wark
10 10 """
11 11 __docformat__ = "restructuredtext en"
12 12
13 13 #-------------------------------------------------------------------------------
14 14 # Copyright (C) 2008-2011 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-------------------------------------------------------------------------------
19 19
20 20 #-------------------------------------------------------------------------------
21 21 # Imports
22 22 #-------------------------------------------------------------------------------
23 23 import string
24 24 import codeop
25 25 import uuid
26 26
27 27
28 28 from IPython.frontend.zopeinterface import (
29 29 Interface,
30 30 Attribute,
31 31 )
32 32 from IPython.kernel.core.history import FrontEndHistory
33 33 from IPython.kernel.core.util import Bunch
34 34
35 35 ##############################################################################
36 36 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
37 37 # not
38 38
39 39 rc = Bunch()
40 40 rc.prompt_in1 = r'In [$number]: '
41 41 rc.prompt_in2 = r'...'
42 42 rc.prompt_out = r'Out [$number]: '
43 43
44 44 ##############################################################################
45 45 # Interface definitions
46 46 ##############################################################################
47 47
48 48 class IFrontEndFactory(Interface):
49 49 """Factory interface for frontends."""
50 50
51 51 def __call__(engine=None, history=None):
52 52 """
53 53 Parameters:
54 54 interpreter : IPython.kernel.engineservice.IEngineCore
55 55 """
56 56
57 57 pass
58 58
59 59
60 60 class IFrontEnd(Interface):
61 61 """Interface for frontends. All methods return t.i.d.Deferred"""
62 62
63 63 Attribute("input_prompt_template", "string.Template instance\
64 64 substituteable with execute result.")
65 65 Attribute("output_prompt_template", "string.Template instance\
66 66 substituteable with execute result.")
67 67 Attribute("continuation_prompt_template", "string.Template instance\
68 68 substituteable with execute result.")
69 69
70 70 def update_cell_prompt(result, blockID=None):
71 71 """Subclass may override to update the input prompt for a block.
72 72
73 73 In asynchronous frontends, this method will be called as a
74 74 twisted.internet.defer.Deferred's callback/errback.
75 75 Implementations should thus return result when finished.
76 76
77 77 Result is a result dict in case of success, and a
78 78 twisted.python.util.failure.Failure in case of an error
79 79 """
80 80
81 81 pass
82 82
83 83 def render_result(result):
84 84 """Render the result of an execute call. Implementors may choose the
85 85 method of rendering.
86 86 For example, a notebook-style frontend might render a Chaco plot
87 87 inline.
88 88
89 89 Parameters:
90 90 result : dict (result of IEngineBase.execute )
91 91 blockID = result['blockID']
92 92
93 93 Result:
94 94 Output of frontend rendering
95 95 """
96 96
97 97 pass
98 98
99 99 def render_error(failure):
100 100 """Subclasses must override to render the failure.
101 101
102 102 In asynchronous frontend, since this method will be called as a
103 103 twisted.internet.defer.Deferred's callback. Implementations
104 104 should thus return result when finished.
105 105
106 106 blockID = failure.blockID
107 107 """
108 108
109 109 pass
110 110
111 111 def input_prompt(number=''):
112 112 """Returns the input prompt by subsituting into
113 113 self.input_prompt_template
114 114 """
115 115 pass
116 116
117 117 def output_prompt(number=''):
118 118 """Returns the output prompt by subsituting into
119 119 self.output_prompt_template
120 120 """
121 121
122 122 pass
123 123
124 124 def continuation_prompt():
125 125 """Returns the continuation prompt by subsituting into
126 126 self.continuation_prompt_template
127 127 """
128 128
129 129 pass
130 130
131 131 def is_complete(block):
132 132 """Returns True if block is complete, False otherwise."""
133 133
134 134 pass
135 135
136 136
137 137 def get_history_previous(current_block):
138 138 """Returns the block previous in the history. Saves currentBlock if
139 139 the history_cursor is currently at the end of the input history"""
140 140 pass
141 141
142 142 def get_history_next():
143 143 """Returns the next block in the history."""
144 144
145 145 pass
146 146
147 147 def complete(self, line):
148 148 """Returns the list of possible completions, and the completed
149 149 line.
150 150
151 151 The input argument is the full line to be completed. This method
152 152 returns both the line completed as much as possible, and the list
153 153 of further possible completions (full words).
154 154 """
155 155 pass
156 156
157 157
158 158 ##############################################################################
159 159 # Base class for all the frontends.
160 160 ##############################################################################
161 161
162 162 class FrontEndBase(object):
163 163 """
164 164 FrontEndBase manages the state tasks for a CLI frontend:
165 165 - Input and output history management
166 166 - Input/continuation and output prompt generation
167 167
168 168 Some issues (due to possibly unavailable engine):
169 169 - How do we get the current cell number for the engine?
170 170 - How do we handle completions?
171 171 """
172 172
173 173 history_cursor = 0
174 174
175 175 input_prompt_template = string.Template(rc.prompt_in1)
176 176 output_prompt_template = string.Template(rc.prompt_out)
177 177 continuation_prompt_template = string.Template(rc.prompt_in2)
178 178
179 179 def __init__(self, shell=None, history=None):
180 180 self.shell = shell
181 181 if history is None:
182 182 self.history = FrontEndHistory(input_cache=[''])
183 183 else:
184 184 self.history = history
185 185
186 186
187 187 def input_prompt(self, number=''):
188 188 """Returns the current input prompt
189 189
190 190 It would be great to use ipython1.core.prompts.Prompt1 here
191 191 """
192 192 return self.input_prompt_template.safe_substitute({'number':number})
193 193
194 194
195 195 def continuation_prompt(self):
196 196 """Returns the current continuation prompt"""
197 197
198 198 return self.continuation_prompt_template.safe_substitute()
199 199
200 200 def output_prompt(self, number=''):
201 201 """Returns the output prompt for result"""
202 202
203 203 return self.output_prompt_template.safe_substitute({'number':number})
204 204
205 205
206 206 def is_complete(self, block):
207 207 """Determine if block is complete.
208 208
209 209 Parameters
210 210 block : string
211 211
212 212 Result
213 213 True if block can be sent to the engine without compile errors.
214 214 False otherwise.
215 215 """
216 216
217 217 try:
218 218 is_complete = codeop.compile_command(block.rstrip() + '\n\n',
219 219 "<string>", "exec")
220 220 except:
221 221 return False
222 222
223 223 lines = block.split('\n')
224 224 return ((is_complete is not None)
225 225 and (len(lines)==1 or str(lines[-1])==''))
226 226
227 227
228 228 def execute(self, block, blockID=None):
229 229 """Execute the block and return the result.
230 230
231 231 Parameters:
232 232 block : {str, AST}
233 233 blockID : any
234 234 Caller may provide an ID to identify this block.
235 235 result['blockID'] := blockID
236 236
237 237 Result:
238 238 Deferred result of self.interpreter.execute
239 239 """
240 240
241 241 if(not self.is_complete(block)):
242 242 raise Exception("Block is not compilable")
243 243
244 244 if(blockID == None):
245 245 blockID = uuid.uuid4()
246 246
247 247 try:
248 248 result = self.shell.execute(block)
249 except Exception,e:
249 except Exception as e:
250 250 e = self._add_block_id_for_failure(e, blockID=blockID)
251 251 e = self.update_cell_prompt(e, blockID=blockID)
252 252 e = self.render_error(e)
253 253 else:
254 254 result = self._add_block_id_for_result(result, blockID=blockID)
255 255 result = self.update_cell_prompt(result, blockID=blockID)
256 256 result = self.render_result(result)
257 257
258 258 return result
259 259
260 260
261 261 def _add_block_id_for_result(self, result, blockID):
262 262 """Add the blockID to result or failure. Unfortunatley, we have to
263 263 treat failures differently than result dicts.
264 264 """
265 265
266 266 result['blockID'] = blockID
267 267
268 268 return result
269 269
270 270 def _add_block_id_for_failure(self, failure, blockID):
271 271 """_add_block_id_for_failure"""
272 272 failure.blockID = blockID
273 273 return failure
274 274
275 275
276 276 def _add_history(self, result, block=None):
277 277 """Add block to the history"""
278 278
279 279 assert(block != None)
280 280 self.history.add_items([block])
281 281 self.history_cursor += 1
282 282
283 283 return result
284 284
285 285
286 286 def get_history_previous(self, current_block):
287 287 """ Returns previous history string and decrement history cursor.
288 288 """
289 289 command = self.history.get_history_item(self.history_cursor - 1)
290 290
291 291 if command is not None:
292 292 if(self.history_cursor+1 == len(self.history.input_cache)):
293 293 self.history.input_cache[self.history_cursor] = current_block
294 294 self.history_cursor -= 1
295 295 return command
296 296
297 297
298 298 def get_history_next(self):
299 299 """ Returns next history string and increment history cursor.
300 300 """
301 301 command = self.history.get_history_item(self.history_cursor+1)
302 302
303 303 if command is not None:
304 304 self.history_cursor += 1
305 305 return command
306 306
307 307 ###
308 308 # Subclasses probably want to override these methods...
309 309 ###
310 310
311 311 def update_cell_prompt(self, result, blockID=None):
312 312 """Subclass may override to update the input prompt for a block.
313 313
314 314 This method only really makes sens in asyncrhonous frontend.
315 315 Since this method will be called as a
316 316 twisted.internet.defer.Deferred's callback, implementations should
317 317 return result when finished.
318 318 """
319 319
320 320 raise NotImplementedError
321 321
322 322
323 323 def render_result(self, result):
324 324 """Subclasses must override to render result.
325 325
326 326 In asynchronous frontends, this method will be called as a
327 327 twisted.internet.defer.Deferred's callback. Implementations
328 328 should thus return result when finished.
329 329 """
330 330
331 331 raise NotImplementedError
332 332
333 333
334 334 def render_error(self, failure):
335 335 """Subclasses must override to render the failure.
336 336
337 337 In asynchronous frontends, this method will be called as a
338 338 twisted.internet.defer.Deferred's callback. Implementations
339 339 should thus return result when finished.
340 340 """
341 341
342 342 raise NotImplementedError
343 343
@@ -1,373 +1,373 b''
1 1 """
2 2 Base front end class for all line-oriented frontends, rather than
3 3 block-oriented.
4 4
5 5 Currently this focuses on synchronous frontends.
6 6 """
7 7 __docformat__ = "restructuredtext en"
8 8
9 9 #-------------------------------------------------------------------------------
10 10 # Copyright (C) 2008-2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-------------------------------------------------------------------------------
15 15
16 16 #-------------------------------------------------------------------------------
17 17 # Imports
18 18 #-------------------------------------------------------------------------------
19 19 import re
20 20
21 21 import sys
22 22 import codeop
23 23
24 24 from frontendbase import FrontEndBase
25 25 from IPython.kernel.core.interpreter import Interpreter
26 26
27 27 def common_prefix(strings):
28 28 """ Given a list of strings, return the common prefix between all
29 29 these strings.
30 30 """
31 31 ref = strings[0]
32 32 prefix = ''
33 33 for size in range(len(ref)):
34 34 test_prefix = ref[:size+1]
35 35 for string in strings[1:]:
36 36 if not string.startswith(test_prefix):
37 37 return prefix
38 38 prefix = test_prefix
39 39
40 40 return prefix
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Base class for the line-oriented front ends
44 44 #-----------------------------------------------------------------------------
45 45
46 46 class LineFrontEndBase(FrontEndBase):
47 47 """ Concrete implementation of the FrontEndBase class. This is meant
48 48 to be the base class behind all the frontend that are line-oriented,
49 49 rather than block-oriented.
50 50 """
51 51
52 52 # We need to keep the prompt number, to be able to increment
53 53 # it when there is an exception.
54 54 prompt_number = 1
55 55
56 56 # We keep a reference to the last result: it helps testing and
57 57 # programatic control of the frontend.
58 58 last_result = dict(number=0)
59 59
60 60 # The last prompt displayed. Useful for continuation prompts.
61 61 last_prompt = ''
62 62
63 63 # The input buffer being edited
64 64 input_buffer = ''
65 65
66 66 # Set to true for debug output
67 67 debug = False
68 68
69 69 # A banner to print at startup
70 70 banner = None
71 71
72 72 #--------------------------------------------------------------------------
73 73 # FrontEndBase interface
74 74 #--------------------------------------------------------------------------
75 75
76 76 def __init__(self, shell=None, history=None, banner=None, *args, **kwargs):
77 77 if shell is None:
78 78 shell = Interpreter()
79 79 FrontEndBase.__init__(self, shell=shell, history=history)
80 80
81 81 if banner is not None:
82 82 self.banner = banner
83 83
84 84 def start(self):
85 85 """ Put the frontend in a state where it is ready for user
86 86 interaction.
87 87 """
88 88 if self.banner is not None:
89 89 self.write(self.banner, refresh=False)
90 90
91 91 self.new_prompt(self.input_prompt_template.substitute(number=1))
92 92
93 93
94 94 def complete(self, line):
95 95 """Complete line in engine's user_ns
96 96
97 97 Parameters
98 98 ----------
99 99 line : string
100 100
101 101 Returns
102 102 -------
103 103 The replacement for the line and the list of possible completions.
104 104 """
105 105 completions = self.shell.complete(line)
106 106 complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
107 107 if completions:
108 108 prefix = common_prefix(completions)
109 109 residual = complete_sep.split(line)[:-1]
110 110 line = line[:-len(residual)] + prefix
111 111 return line, completions
112 112
113 113
114 114 def render_result(self, result):
115 115 """ Frontend-specific rendering of the result of a calculation
116 116 that has been sent to an engine.
117 117 """
118 118 if 'stdout' in result and result['stdout']:
119 119 self.write('\n' + result['stdout'])
120 120 if 'display' in result and result['display']:
121 121 self.write("%s%s\n" % (
122 122 self.output_prompt_template.substitute(
123 123 number=result['number']),
124 124 result['display']['pprint']
125 125 ) )
126 126
127 127
128 128 def render_error(self, failure):
129 129 """ Frontend-specific rendering of error.
130 130 """
131 131 self.write('\n\n'+str(failure)+'\n\n')
132 132 return failure
133 133
134 134
135 135 def is_complete(self, string):
136 136 """ Check if a string forms a complete, executable set of
137 137 commands.
138 138
139 139 For the line-oriented frontend, multi-line code is not executed
140 140 as soon as it is complete: the users has to enter two line
141 141 returns.
142 142 """
143 143 if string in ('', '\n'):
144 144 # Prefiltering, eg through ipython0, may return an empty
145 145 # string although some operations have been accomplished. We
146 146 # thus want to consider an empty string as a complete
147 147 # statement.
148 148 return True
149 149 elif ( len(self.input_buffer.split('\n'))>2
150 150 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
151 151 return False
152 152 else:
153 153 self.capture_output()
154 154 try:
155 155 # Add line returns here, to make sure that the statement is
156 156 # complete (except if '\' was used).
157 157 # This should probably be done in a different place (like
158 158 # maybe 'prefilter_input' method? For now, this works.
159 159 clean_string = string.rstrip('\n')
160 160 if not clean_string.endswith('\\'): clean_string +='\n\n'
161 161 is_complete = codeop.compile_command(clean_string,
162 162 "<string>", "exec")
163 163 self.release_output()
164 except Exception, e:
164 except Exception as e:
165 165 # XXX: Hack: return True so that the
166 166 # code gets executed and the error captured.
167 167 is_complete = True
168 168 return is_complete
169 169
170 170
171 171 def write(self, string, refresh=True):
172 172 """ Write some characters to the display.
173 173
174 174 Subclass should overide this method.
175 175
176 176 The refresh keyword argument is used in frontends with an
177 177 event loop, to choose whether the write should trigget an UI
178 178 refresh, and thus be syncrhonous, or not.
179 179 """
180 180 print >>sys.__stderr__, string
181 181
182 182
183 183 def execute(self, python_string, raw_string=None):
184 184 """ Stores the raw_string in the history, and sends the
185 185 python string to the interpreter.
186 186 """
187 187 if raw_string is None:
188 188 raw_string = python_string
189 189 # Create a false result, in case there is an exception
190 190 self.last_result = dict(number=self.prompt_number)
191 191
192 192 try:
193 193 try:
194 194 self.history.input_cache[-1] = raw_string.rstrip()
195 195 result = self.shell.execute(python_string)
196 196 self.last_result = result
197 197 self.render_result(result)
198 198 except:
199 199 self.show_traceback()
200 200 finally:
201 201 self.after_execute()
202 202
203 203
204 204 #--------------------------------------------------------------------------
205 205 # LineFrontEndBase interface
206 206 #--------------------------------------------------------------------------
207 207
208 208 def prefilter_input(self, string):
209 209 """ Prefilter the input to turn it in valid python.
210 210 """
211 211 string = string.replace('\r\n', '\n')
212 212 string = string.replace('\t', 4*' ')
213 213 # Clean the trailing whitespace
214 214 string = '\n'.join(l.rstrip() for l in string.split('\n'))
215 215 return string
216 216
217 217
218 218 def after_execute(self):
219 219 """ All the operations required after an execution to put the
220 220 terminal back in a shape where it is usable.
221 221 """
222 222 self.prompt_number += 1
223 223 self.new_prompt(self.input_prompt_template.substitute(
224 224 number=(self.last_result['number'] + 1)))
225 225 # Start a new empty history entry
226 226 self._add_history(None, '')
227 227 self.history_cursor = len(self.history.input_cache) - 1
228 228
229 229
230 230 def complete_current_input(self):
231 231 """ Do code completion on current line.
232 232 """
233 233 if self.debug:
234 234 print >>sys.__stdout__, "complete_current_input",
235 235 line = self.input_buffer
236 236 new_line, completions = self.complete(line)
237 237 if len(completions)>1:
238 238 self.write_completion(completions, new_line=new_line)
239 239 elif not line == new_line:
240 240 self.input_buffer = new_line
241 241 if self.debug:
242 242 print >>sys.__stdout__, 'line', line
243 243 print >>sys.__stdout__, 'new_line', new_line
244 244 print >>sys.__stdout__, completions
245 245
246 246
247 247 def get_line_width(self):
248 248 """ Return the width of the line in characters.
249 249 """
250 250 return 80
251 251
252 252
253 253 def write_completion(self, possibilities, new_line=None):
254 254 """ Write the list of possible completions.
255 255
256 256 new_line is the completed input line that should be displayed
257 257 after the completion are writen. If None, the input_buffer
258 258 before the completion is used.
259 259 """
260 260 if new_line is None:
261 261 new_line = self.input_buffer
262 262
263 263 self.write('\n')
264 264 max_len = len(max(possibilities, key=len)) + 1
265 265
266 266 # Now we check how much symbol we can put on a line...
267 267 chars_per_line = self.get_line_width()
268 268 symbols_per_line = max(1, chars_per_line/max_len)
269 269
270 270 pos = 1
271 271 completion_string = []
272 272 for symbol in possibilities:
273 273 if pos < symbols_per_line:
274 274 completion_string.append(symbol.ljust(max_len))
275 275 pos += 1
276 276 else:
277 277 completion_string.append(symbol.rstrip() + '\n')
278 278 pos = 1
279 279 self.write(''.join(completion_string))
280 280 self.new_prompt(self.input_prompt_template.substitute(
281 281 number=self.last_result['number'] + 1))
282 282 self.input_buffer = new_line
283 283
284 284
285 285 def new_prompt(self, prompt):
286 286 """ Prints a prompt and starts a new editing buffer.
287 287
288 288 Subclasses should use this method to make sure that the
289 289 terminal is put in a state favorable for a new line
290 290 input.
291 291 """
292 292 self.input_buffer = ''
293 293 self.write(prompt)
294 294
295 295
296 296 def continuation_prompt(self):
297 297 """Returns the current continuation prompt.
298 298 """
299 299 return ("."*(len(self.last_prompt)-2) + ': ')
300 300
301 301
302 302 def execute_command(self, command, hidden=False):
303 303 """ Execute a command, not only in the model, but also in the
304 304 view, if any.
305 305 """
306 306 return self.shell.execute(command)
307 307
308 308 #--------------------------------------------------------------------------
309 309 # Private API
310 310 #--------------------------------------------------------------------------
311 311
312 312 def _on_enter(self, new_line_pos=0):
313 313 """ Called when the return key is pressed in a line editing
314 314 buffer.
315 315
316 316 Parameters
317 317 ----------
318 318 new_line_pos : integer, optional
319 319 Position of the new line to add, starting from the
320 320 end (0 adds a new line after the last line, -1 before
321 321 the last line...)
322 322
323 323 Returns
324 324 -------
325 325 True if execution is triggered
326 326 """
327 327 current_buffer = self.input_buffer
328 328 # XXX: This string replace is ugly, but there should be no way it
329 329 # fails.
330 330 prompt_less_buffer = re.sub('^' + self.continuation_prompt(),
331 331 '', current_buffer).replace('\n' + self.continuation_prompt(),
332 332 '\n')
333 333 cleaned_buffer = self.prefilter_input(prompt_less_buffer)
334 334 if self.is_complete(cleaned_buffer):
335 335 self.execute(cleaned_buffer, raw_string=current_buffer)
336 336 return True
337 337 else:
338 338 # Start a new line.
339 339 new_line_pos = -new_line_pos
340 340 lines = current_buffer.split('\n')[:-1]
341 341 prompt_less_lines = prompt_less_buffer.split('\n')
342 342 # Create the new line, with the continuation prompt, and the
343 343 # same amount of indent than the line above it.
344 344 new_line = self.continuation_prompt() + \
345 345 self._get_indent_string('\n'.join(
346 346 prompt_less_lines[:new_line_pos-1]))
347 347 if len(lines) == 1:
348 348 # We are starting a first continuation line. Indent it.
349 349 new_line += '\t'
350 350 elif current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
351 351 # The last line ends with ":", autoindent the new line.
352 352 new_line += '\t'
353 353
354 354 if new_line_pos == 0:
355 355 lines.append(new_line)
356 356 else:
357 357 lines.insert(new_line_pos, new_line)
358 358 self.input_buffer = '\n'.join(lines)
359 359
360 360
361 361 def _get_indent_string(self, string):
362 362 """ Return the string of whitespace that prefixes a line. Used to
363 363 add the right amount of indendation when creating a new line.
364 364 """
365 365 string = string.replace('\t', ' '*4)
366 366 string = string.split('\n')[-1]
367 367 indent_chars = len(string) - len(string.lstrip())
368 368 indent_string = '\t'*(indent_chars // 4) + \
369 369 ' '*(indent_chars % 4)
370 370
371 371 return indent_string
372 372
373 373
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now