##// END OF EJS Templates
2to3: Apply has_key fixer.
Bradley M. Froehle -
Show More
@@ -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 if not self.has_key(k):
85 if k not in self:
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 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 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 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 Tests for IPython.config.loader
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Fernando Perez (design help)
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. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import os
23 23 import sys
24 24 from tempfile import mkstemp
25 25 from unittest import TestCase
26 26
27 27 from nose import SkipTest
28 28
29 29 from IPython.testing.tools import mute_warn
30 30
31 31 from IPython.utils.traitlets import Unicode
32 32 from IPython.config.configurable import Configurable
33 33 from IPython.config.loader import (
34 34 Config,
35 35 PyFileConfigLoader,
36 36 KeyValueConfigLoader,
37 37 ArgParseConfigLoader,
38 38 KVArgParseConfigLoader,
39 39 ConfigError
40 40 )
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Actual tests
44 44 #-----------------------------------------------------------------------------
45 45
46 46
47 47 pyfile = """
48 48 c = get_config()
49 49 c.a=10
50 50 c.b=20
51 51 c.Foo.Bar.value=10
52 52 c.Foo.Bam.value=list(range(10)) # list() is just so it's the same on Python 3
53 53 c.D.C.value='hi there'
54 54 """
55 55
56 56 class TestPyFileCL(TestCase):
57 57
58 58 def test_basic(self):
59 59 fd, fname = mkstemp('.py')
60 60 f = os.fdopen(fd, 'w')
61 61 f.write(pyfile)
62 62 f.close()
63 63 # Unlink the file
64 64 cl = PyFileConfigLoader(fname)
65 65 config = cl.load_config()
66 66 self.assertEquals(config.a, 10)
67 67 self.assertEquals(config.b, 20)
68 68 self.assertEquals(config.Foo.Bar.value, 10)
69 69 self.assertEquals(config.Foo.Bam.value, range(10))
70 70 self.assertEquals(config.D.C.value, 'hi there')
71 71
72 72 class MyLoader1(ArgParseConfigLoader):
73 73 def _add_arguments(self, aliases=None, flags=None):
74 74 p = self.parser
75 75 p.add_argument('-f', '--foo', dest='Global.foo', type=str)
76 76 p.add_argument('-b', dest='MyClass.bar', type=int)
77 77 p.add_argument('-n', dest='n', action='store_true')
78 78 p.add_argument('Global.bam', type=str)
79 79
80 80 class MyLoader2(ArgParseConfigLoader):
81 81 def _add_arguments(self, aliases=None, flags=None):
82 82 subparsers = self.parser.add_subparsers(dest='subparser_name')
83 83 subparser1 = subparsers.add_parser('1')
84 84 subparser1.add_argument('-x',dest='Global.x')
85 85 subparser2 = subparsers.add_parser('2')
86 86 subparser2.add_argument('y')
87 87
88 88 class TestArgParseCL(TestCase):
89 89
90 90 def test_basic(self):
91 91 cl = MyLoader1()
92 92 config = cl.load_config('-f hi -b 10 -n wow'.split())
93 93 self.assertEquals(config.Global.foo, 'hi')
94 94 self.assertEquals(config.MyClass.bar, 10)
95 95 self.assertEquals(config.n, True)
96 96 self.assertEquals(config.Global.bam, 'wow')
97 97 config = cl.load_config(['wow'])
98 98 self.assertEquals(config.keys(), ['Global'])
99 99 self.assertEquals(config.Global.keys(), ['bam'])
100 100 self.assertEquals(config.Global.bam, 'wow')
101 101
102 102 def test_add_arguments(self):
103 103 cl = MyLoader2()
104 104 config = cl.load_config('2 frobble'.split())
105 105 self.assertEquals(config.subparser_name, '2')
106 106 self.assertEquals(config.y, 'frobble')
107 107 config = cl.load_config('1 -x frobble'.split())
108 108 self.assertEquals(config.subparser_name, '1')
109 109 self.assertEquals(config.Global.x, 'frobble')
110 110
111 111 def test_argv(self):
112 112 cl = MyLoader1(argv='-f hi -b 10 -n wow'.split())
113 113 config = cl.load_config()
114 114 self.assertEquals(config.Global.foo, 'hi')
115 115 self.assertEquals(config.MyClass.bar, 10)
116 116 self.assertEquals(config.n, True)
117 117 self.assertEquals(config.Global.bam, 'wow')
118 118
119 119
120 120 class TestKeyValueCL(TestCase):
121 121 klass = KeyValueConfigLoader
122 122
123 123 def test_basic(self):
124 124 cl = self.klass()
125 125 argv = ['--'+s.strip('c.') for s in pyfile.split('\n')[2:-1]]
126 126 with mute_warn():
127 127 config = cl.load_config(argv)
128 128 self.assertEquals(config.a, 10)
129 129 self.assertEquals(config.b, 20)
130 130 self.assertEquals(config.Foo.Bar.value, 10)
131 131 self.assertEquals(config.Foo.Bam.value, range(10))
132 132 self.assertEquals(config.D.C.value, 'hi there')
133 133
134 134 def test_expanduser(self):
135 135 cl = self.klass()
136 136 argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"']
137 137 with mute_warn():
138 138 config = cl.load_config(argv)
139 139 self.assertEquals(config.a, os.path.expanduser('~/1/2/3'))
140 140 self.assertEquals(config.b, os.path.expanduser('~'))
141 141 self.assertEquals(config.c, os.path.expanduser('~/'))
142 142 self.assertEquals(config.d, '~/')
143 143
144 144 def test_extra_args(self):
145 145 cl = self.klass()
146 146 with mute_warn():
147 147 config = cl.load_config(['--a=5', 'b', '--c=10', 'd'])
148 148 self.assertEquals(cl.extra_args, ['b', 'd'])
149 149 self.assertEquals(config.a, 5)
150 150 self.assertEquals(config.c, 10)
151 151 with mute_warn():
152 152 config = cl.load_config(['--', '--a=5', '--c=10'])
153 153 self.assertEquals(cl.extra_args, ['--a=5', '--c=10'])
154 154
155 155 def test_unicode_args(self):
156 156 cl = self.klass()
157 157 argv = [u'--a=épsîlön']
158 158 with mute_warn():
159 159 config = cl.load_config(argv)
160 160 self.assertEquals(config.a, u'épsîlön')
161 161
162 162 def test_unicode_bytes_args(self):
163 163 uarg = u'--a=é'
164 164 try:
165 165 barg = uarg.encode(sys.stdin.encoding)
166 166 except (TypeError, UnicodeEncodeError):
167 167 raise SkipTest("sys.stdin.encoding can't handle 'é'")
168 168
169 169 cl = self.klass()
170 170 with mute_warn():
171 171 config = cl.load_config([barg])
172 172 self.assertEquals(config.a, u'é')
173 173
174 174 def test_unicode_alias(self):
175 175 cl = self.klass()
176 176 argv = [u'--a=épsîlön']
177 177 with mute_warn():
178 178 config = cl.load_config(argv, aliases=dict(a='A.a'))
179 179 self.assertEquals(config.A.a, u'épsîlön')
180 180
181 181
182 182 class TestArgParseKVCL(TestKeyValueCL):
183 183 klass = KVArgParseConfigLoader
184 184
185 185 def test_expanduser2(self):
186 186 cl = self.klass()
187 187 argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"]
188 188 with mute_warn():
189 189 config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b'))
190 190 self.assertEquals(config.A.a, os.path.expanduser('~/1/2/3'))
191 191 self.assertEquals(config.A.b, '~/1/2/3')
192 192
193 193 def test_eval(self):
194 194 cl = self.klass()
195 195 argv = ['-c', 'a=5']
196 196 with mute_warn():
197 197 config = cl.load_config(argv, aliases=dict(c='A.c'))
198 198 self.assertEquals(config.A.c, u"a=5")
199 199
200 200
201 201 class TestConfig(TestCase):
202 202
203 203 def test_setget(self):
204 204 c = Config()
205 205 c.a = 10
206 206 self.assertEquals(c.a, 10)
207 self.assertEquals(c.has_key('b'), False)
207 self.assertEquals('b' in c, False)
208 208
209 209 def test_auto_section(self):
210 210 c = Config()
211 self.assertEquals(c.has_key('A'), True)
211 self.assertEquals('A' in c, True)
212 212 self.assertEquals(c._has_section('A'), False)
213 213 A = c.A
214 214 A.foo = 'hi there'
215 215 self.assertEquals(c._has_section('A'), True)
216 216 self.assertEquals(c.A.foo, 'hi there')
217 217 del c.A
218 218 self.assertEquals(len(c.A.keys()),0)
219 219
220 220 def test_merge_doesnt_exist(self):
221 221 c1 = Config()
222 222 c2 = Config()
223 223 c2.bar = 10
224 224 c2.Foo.bar = 10
225 225 c1._merge(c2)
226 226 self.assertEquals(c1.Foo.bar, 10)
227 227 self.assertEquals(c1.bar, 10)
228 228 c2.Bar.bar = 10
229 229 c1._merge(c2)
230 230 self.assertEquals(c1.Bar.bar, 10)
231 231
232 232 def test_merge_exists(self):
233 233 c1 = Config()
234 234 c2 = Config()
235 235 c1.Foo.bar = 10
236 236 c1.Foo.bam = 30
237 237 c2.Foo.bar = 20
238 238 c2.Foo.wow = 40
239 239 c1._merge(c2)
240 240 self.assertEquals(c1.Foo.bam, 30)
241 241 self.assertEquals(c1.Foo.bar, 20)
242 242 self.assertEquals(c1.Foo.wow, 40)
243 243 c2.Foo.Bam.bam = 10
244 244 c1._merge(c2)
245 245 self.assertEquals(c1.Foo.Bam.bam, 10)
246 246
247 247 def test_deepcopy(self):
248 248 c1 = Config()
249 249 c1.Foo.bar = 10
250 250 c1.Foo.bam = 30
251 251 c1.a = 'asdf'
252 252 c1.b = range(10)
253 253 import copy
254 254 c2 = copy.deepcopy(c1)
255 255 self.assertEquals(c1, c2)
256 256 self.assert_(c1 is not c2)
257 257 self.assert_(c1.Foo is not c2.Foo)
258 258
259 259 def test_builtin(self):
260 260 c1 = Config()
261 261 exec 'foo = True' in c1
262 262 self.assertEquals(c1.foo, True)
263 263 self.assertRaises(ConfigError, setattr, c1, 'ValueError', 10)
@@ -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 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 if self.alias_table.has_key(name):
167 if name in self.alias_table:
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,309 +1,309 b''
1 1 """An interface for publishing rich data to frontends.
2 2
3 3 There are two components of the display system:
4 4
5 5 * Display formatters, which take a Python object and compute the
6 6 representation of the object in various formats (text, HTML, SVg, etc.).
7 7 * The display publisher that is used to send the representation data to the
8 8 various frontends.
9 9
10 10 This module defines the logic display publishing. The display publisher uses
11 11 the ``display_data`` message type that is defined in the IPython messaging
12 12 spec.
13 13
14 14 Authors:
15 15
16 16 * Brian Granger
17 17 """
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Copyright (C) 2008-2011 The IPython Development Team
21 21 #
22 22 # Distributed under the terms of the BSD License. The full license is in
23 23 # the file COPYING, distributed as part of this software.
24 24 #-----------------------------------------------------------------------------
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Imports
28 28 #-----------------------------------------------------------------------------
29 29
30 30 from __future__ import print_function
31 31
32 32 from IPython.config.configurable import Configurable
33 33 from IPython.utils import io
34 34
35 35 #-----------------------------------------------------------------------------
36 36 # Main payload class
37 37 #-----------------------------------------------------------------------------
38 38
39 39 class DisplayPublisher(Configurable):
40 40 """A traited class that publishes display data to frontends.
41 41
42 42 Instances of this class are created by the main IPython object and should
43 43 be accessed there.
44 44 """
45 45
46 46 def _validate_data(self, source, data, metadata=None):
47 47 """Validate the display data.
48 48
49 49 Parameters
50 50 ----------
51 51 source : str
52 52 The fully dotted name of the callable that created the data, like
53 53 :func:`foo.bar.my_formatter`.
54 54 data : dict
55 55 The formata data dictionary.
56 56 metadata : dict
57 57 Any metadata for the data.
58 58 """
59 59
60 60 if not isinstance(source, basestring):
61 61 raise TypeError('source must be a str, got: %r' % source)
62 62 if not isinstance(data, dict):
63 63 raise TypeError('data must be a dict, got: %r' % data)
64 64 if metadata is not None:
65 65 if not isinstance(metadata, dict):
66 66 raise TypeError('metadata must be a dict, got: %r' % data)
67 67
68 68 def publish(self, source, data, metadata=None):
69 69 """Publish data and metadata to all frontends.
70 70
71 71 See the ``display_data`` message in the messaging documentation for
72 72 more details about this message type.
73 73
74 74 The following MIME types are currently implemented:
75 75
76 76 * text/plain
77 77 * text/html
78 78 * text/latex
79 79 * application/json
80 80 * application/javascript
81 81 * image/png
82 82 * image/jpeg
83 83 * image/svg+xml
84 84
85 85 Parameters
86 86 ----------
87 87 source : str
88 88 A string that give the function or method that created the data,
89 89 such as 'IPython.core.page'.
90 90 data : dict
91 91 A dictionary having keys that are valid MIME types (like
92 92 'text/plain' or 'image/svg+xml') and values that are the data for
93 93 that MIME type. The data itself must be a JSON'able data
94 94 structure. Minimally all data should have the 'text/plain' data,
95 95 which can be displayed by all frontends. If more than the plain
96 96 text is given, it is up to the frontend to decide which
97 97 representation to use.
98 98 metadata : dict
99 99 A dictionary for metadata related to the data. This can contain
100 100 arbitrary key, value pairs that frontends can use to interpret
101 101 the data.
102 102 """
103 103
104 104 # The default is to simply write the plain text data using io.stdout.
105 if data.has_key('text/plain'):
105 if 'text/plain' in data:
106 106 print(data['text/plain'], file=io.stdout)
107 107
108 108 def clear_output(self, stdout=True, stderr=True, other=True):
109 109 """Clear the output of the cell receiving output."""
110 110 if stdout:
111 111 print('\033[2K\r', file=io.stdout, end='')
112 112 io.stdout.flush()
113 113 if stderr:
114 114 print('\033[2K\r', file=io.stderr, end='')
115 115 io.stderr.flush()
116 116
117 117
118 118
119 119 def publish_display_data(source, data, metadata=None):
120 120 """Publish data and metadata to all frontends.
121 121
122 122 See the ``display_data`` message in the messaging documentation for
123 123 more details about this message type.
124 124
125 125 The following MIME types are currently implemented:
126 126
127 127 * text/plain
128 128 * text/html
129 129 * text/latex
130 130 * application/json
131 131 * application/javascript
132 132 * image/png
133 133 * image/jpeg
134 134 * image/svg+xml
135 135
136 136 Parameters
137 137 ----------
138 138 source : str
139 139 A string that give the function or method that created the data,
140 140 such as 'IPython.core.page'.
141 141 data : dict
142 142 A dictionary having keys that are valid MIME types (like
143 143 'text/plain' or 'image/svg+xml') and values that are the data for
144 144 that MIME type. The data itself must be a JSON'able data
145 145 structure. Minimally all data should have the 'text/plain' data,
146 146 which can be displayed by all frontends. If more than the plain
147 147 text is given, it is up to the frontend to decide which
148 148 representation to use.
149 149 metadata : dict
150 150 A dictionary for metadata related to the data. This can contain
151 151 arbitrary key, value pairs that frontends can use to interpret
152 152 the data.
153 153 """
154 154 from IPython.core.interactiveshell import InteractiveShell
155 155 InteractiveShell.instance().display_pub.publish(
156 156 source,
157 157 data,
158 158 metadata
159 159 )
160 160
161 161
162 162 def publish_pretty(data, metadata=None):
163 163 """Publish raw text data to all frontends.
164 164
165 165 Parameters
166 166 ----------
167 167 data : unicode
168 168 The raw text data to publish.
169 169 metadata : dict
170 170 A dictionary for metadata related to the data. This can contain
171 171 arbitrary key, value pairs that frontends can use to interpret
172 172 the data.
173 173 """
174 174 publish_display_data(
175 175 u'IPython.core.displaypub.publish_pretty',
176 176 {'text/plain':data},
177 177 metadata=metadata
178 178 )
179 179
180 180
181 181 def publish_html(data, metadata=None):
182 182 """Publish raw HTML data to all frontends.
183 183
184 184 Parameters
185 185 ----------
186 186 data : unicode
187 187 The raw HTML data to publish.
188 188 metadata : dict
189 189 A dictionary for metadata related to the data. This can contain
190 190 arbitrary key, value pairs that frontends can use to interpret
191 191 the data.
192 192 """
193 193 publish_display_data(
194 194 u'IPython.core.displaypub.publish_html',
195 195 {'text/html':data},
196 196 metadata=metadata
197 197 )
198 198
199 199
200 200 def publish_latex(data, metadata=None):
201 201 """Publish raw LaTeX data to all frontends.
202 202
203 203 Parameters
204 204 ----------
205 205 data : unicode
206 206 The raw LaTeX data to publish.
207 207 metadata : dict
208 208 A dictionary for metadata related to the data. This can contain
209 209 arbitrary key, value pairs that frontends can use to interpret
210 210 the data.
211 211 """
212 212 publish_display_data(
213 213 u'IPython.core.displaypub.publish_latex',
214 214 {'text/latex':data},
215 215 metadata=metadata
216 216 )
217 217
218 218 def publish_png(data, metadata=None):
219 219 """Publish raw binary PNG data to all frontends.
220 220
221 221 Parameters
222 222 ----------
223 223 data : str/bytes
224 224 The raw binary PNG data to publish.
225 225 metadata : dict
226 226 A dictionary for metadata related to the data. This can contain
227 227 arbitrary key, value pairs that frontends can use to interpret
228 228 the data.
229 229 """
230 230 publish_display_data(
231 231 u'IPython.core.displaypub.publish_png',
232 232 {'image/png':data},
233 233 metadata=metadata
234 234 )
235 235
236 236
237 237 def publish_jpeg(data, metadata=None):
238 238 """Publish raw binary JPEG data to all frontends.
239 239
240 240 Parameters
241 241 ----------
242 242 data : str/bytes
243 243 The raw binary JPEG data to publish.
244 244 metadata : dict
245 245 A dictionary for metadata related to the data. This can contain
246 246 arbitrary key, value pairs that frontends can use to interpret
247 247 the data.
248 248 """
249 249 publish_display_data(
250 250 u'IPython.core.displaypub.publish_jpeg',
251 251 {'image/jpeg':data},
252 252 metadata=metadata
253 253 )
254 254
255 255
256 256 def publish_svg(data, metadata=None):
257 257 """Publish raw SVG data to all frontends.
258 258
259 259 Parameters
260 260 ----------
261 261 data : unicode
262 262 The raw SVG data to publish.
263 263 metadata : dict
264 264 A dictionary for metadata related to the data. This can contain
265 265 arbitrary key, value pairs that frontends can use to interpret
266 266 the data.
267 267 """
268 268 publish_display_data(
269 269 u'IPython.core.displaypub.publish_svg',
270 270 {'image/svg+xml':data},
271 271 metadata=metadata
272 272 )
273 273
274 274 def publish_json(data, metadata=None):
275 275 """Publish raw JSON data to all frontends.
276 276
277 277 Parameters
278 278 ----------
279 279 data : unicode
280 280 The raw JSON data to publish.
281 281 metadata : dict
282 282 A dictionary for metadata related to the data. This can contain
283 283 arbitrary key, value pairs that frontends can use to interpret
284 284 the data.
285 285 """
286 286 publish_display_data(
287 287 u'IPython.core.displaypub.publish_json',
288 288 {'application/json':data},
289 289 metadata=metadata
290 290 )
291 291
292 292 def publish_javascript(data, metadata=None):
293 293 """Publish raw Javascript data to all frontends.
294 294
295 295 Parameters
296 296 ----------
297 297 data : unicode
298 298 The raw Javascript data to publish.
299 299 metadata : dict
300 300 A dictionary for metadata related to the data. This can contain
301 301 arbitrary key, value pairs that frontends can use to interpret
302 302 the data.
303 303 """
304 304 publish_display_data(
305 305 u'IPython.core.displaypub.publish_javascript',
306 306 {'application/javascript':data},
307 307 metadata=metadata
308 308 )
309 309
@@ -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 if not shell.user_ns.has_key(args):
221 if args not in shell.user_ns:
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 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,1022 +1,1022 b''
1 1 """Implementation of execution-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 __builtin__ as builtin_mod
17 17 import bdb
18 18 import os
19 19 import sys
20 20 import time
21 21 from StringIO import StringIO
22 22
23 23 # cProfile was added in Python2.5
24 24 try:
25 25 import cProfile as profile
26 26 import pstats
27 27 except ImportError:
28 28 # profile isn't bundled by default in Debian for license reasons
29 29 try:
30 30 import profile, pstats
31 31 except ImportError:
32 32 profile = pstats = None
33 33
34 34 # Our own packages
35 35 from IPython.core import debugger, oinspect
36 36 from IPython.core import magic_arguments
37 37 from IPython.core import page
38 38 from IPython.core.error import UsageError
39 39 from IPython.core.macro import Macro
40 40 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
41 41 line_cell_magic, on_off, needs_local_scope)
42 42 from IPython.testing.skipdoctest import skip_doctest
43 43 from IPython.utils import py3compat
44 44 from IPython.utils.io import capture_output
45 45 from IPython.utils.ipstruct import Struct
46 46 from IPython.utils.module_paths import find_mod
47 47 from IPython.utils.path import get_py_filename, unquote_filename
48 48 from IPython.utils.timing import clock, clock2
49 49 from IPython.utils.warn import warn, error
50 50
51 51 #-----------------------------------------------------------------------------
52 52 # Magic implementation classes
53 53 #-----------------------------------------------------------------------------
54 54
55 55 @magics_class
56 56 class ExecutionMagics(Magics):
57 57 """Magics related to code execution, debugging, profiling, etc.
58 58
59 59 """
60 60
61 61 def __init__(self, shell):
62 62 super(ExecutionMagics, self).__init__(shell)
63 63 if profile is None:
64 64 self.prun = self.profile_missing_notice
65 65 # Default execution function used to actually run user code.
66 66 self.default_runner = None
67 67
68 68 def profile_missing_notice(self, *args, **kwargs):
69 69 error("""\
70 70 The profile module could not be found. It has been removed from the standard
71 71 python packages because of its non-free license. To use profiling, install the
72 72 python-profiler package from non-free.""")
73 73
74 74 @skip_doctest
75 75 @line_cell_magic
76 76 def prun(self, parameter_s='', cell=None, user_mode=True,
77 77 opts=None,arg_lst=None,prog_ns=None):
78 78
79 79 """Run a statement through the python code profiler.
80 80
81 81 Usage, in line mode:
82 82 %prun [options] statement
83 83
84 84 Usage, in cell mode:
85 85 %%prun [options] [statement]
86 86 code...
87 87 code...
88 88
89 89 In cell mode, the additional code lines are appended to the (possibly
90 90 empty) statement in the first line. Cell mode allows you to easily
91 91 profile multiline blocks without having to put them in a separate
92 92 function.
93 93
94 94 The given statement (which doesn't require quote marks) is run via the
95 95 python profiler in a manner similar to the profile.run() function.
96 96 Namespaces are internally managed to work correctly; profile.run
97 97 cannot be used in IPython because it makes certain assumptions about
98 98 namespaces which do not hold under IPython.
99 99
100 100 Options:
101 101
102 102 -l <limit>: you can place restrictions on what or how much of the
103 103 profile gets printed. The limit value can be:
104 104
105 105 * A string: only information for function names containing this string
106 106 is printed.
107 107
108 108 * An integer: only these many lines are printed.
109 109
110 110 * A float (between 0 and 1): this fraction of the report is printed
111 111 (for example, use a limit of 0.4 to see the topmost 40% only).
112 112
113 113 You can combine several limits with repeated use of the option. For
114 114 example, '-l __init__ -l 5' will print only the topmost 5 lines of
115 115 information about class constructors.
116 116
117 117 -r: return the pstats.Stats object generated by the profiling. This
118 118 object has all the information about the profile in it, and you can
119 119 later use it for further analysis or in other functions.
120 120
121 121 -s <key>: sort profile by given key. You can provide more than one key
122 122 by using the option several times: '-s key1 -s key2 -s key3...'. The
123 123 default sorting key is 'time'.
124 124
125 125 The following is copied verbatim from the profile documentation
126 126 referenced below:
127 127
128 128 When more than one key is provided, additional keys are used as
129 129 secondary criteria when the there is equality in all keys selected
130 130 before them.
131 131
132 132 Abbreviations can be used for any key names, as long as the
133 133 abbreviation is unambiguous. The following are the keys currently
134 134 defined:
135 135
136 136 Valid Arg Meaning
137 137 "calls" call count
138 138 "cumulative" cumulative time
139 139 "file" file name
140 140 "module" file name
141 141 "pcalls" primitive call count
142 142 "line" line number
143 143 "name" function name
144 144 "nfl" name/file/line
145 145 "stdname" standard name
146 146 "time" internal time
147 147
148 148 Note that all sorts on statistics are in descending order (placing
149 149 most time consuming items first), where as name, file, and line number
150 150 searches are in ascending order (i.e., alphabetical). The subtle
151 151 distinction between "nfl" and "stdname" is that the standard name is a
152 152 sort of the name as printed, which means that the embedded line
153 153 numbers get compared in an odd way. For example, lines 3, 20, and 40
154 154 would (if the file names were the same) appear in the string order
155 155 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
156 156 line numbers. In fact, sort_stats("nfl") is the same as
157 157 sort_stats("name", "file", "line").
158 158
159 159 -T <filename>: save profile results as shown on screen to a text
160 160 file. The profile is still shown on screen.
161 161
162 162 -D <filename>: save (via dump_stats) profile statistics to given
163 163 filename. This data is in a format understood by the pstats module, and
164 164 is generated by a call to the dump_stats() method of profile
165 165 objects. The profile is still shown on screen.
166 166
167 167 -q: suppress output to the pager. Best used with -T and/or -D above.
168 168
169 169 If you want to run complete programs under the profiler's control, use
170 170 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
171 171 contains profiler specific options as described here.
172 172
173 173 You can read the complete documentation for the profile module with::
174 174
175 175 In [1]: import profile; profile.help()
176 176 """
177 177
178 178 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
179 179
180 180 if user_mode: # regular user call
181 181 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:q',
182 182 list_all=True, posix=False)
183 183 namespace = self.shell.user_ns
184 184 if cell is not None:
185 185 arg_str += '\n' + cell
186 186 else: # called to run a program by %run -p
187 187 try:
188 188 filename = get_py_filename(arg_lst[0])
189 189 except IOError as e:
190 190 try:
191 191 msg = str(e)
192 192 except UnicodeError:
193 193 msg = e.message
194 194 error(msg)
195 195 return
196 196
197 197 arg_str = 'execfile(filename,prog_ns)'
198 198 namespace = {
199 199 'execfile': self.shell.safe_execfile,
200 200 'prog_ns': prog_ns,
201 201 'filename': filename
202 202 }
203 203
204 204 opts.merge(opts_def)
205 205
206 206 prof = profile.Profile()
207 207 try:
208 208 prof = prof.runctx(arg_str,namespace,namespace)
209 209 sys_exit = ''
210 210 except SystemExit:
211 211 sys_exit = """*** SystemExit exception caught in code being profiled."""
212 212
213 213 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
214 214
215 215 lims = opts.l
216 216 if lims:
217 217 lims = [] # rebuild lims with ints/floats/strings
218 218 for lim in opts.l:
219 219 try:
220 220 lims.append(int(lim))
221 221 except ValueError:
222 222 try:
223 223 lims.append(float(lim))
224 224 except ValueError:
225 225 lims.append(lim)
226 226
227 227 # Trap output.
228 228 stdout_trap = StringIO()
229 229
230 230 if hasattr(stats,'stream'):
231 231 # In newer versions of python, the stats object has a 'stream'
232 232 # attribute to write into.
233 233 stats.stream = stdout_trap
234 234 stats.print_stats(*lims)
235 235 else:
236 236 # For older versions, we manually redirect stdout during printing
237 237 sys_stdout = sys.stdout
238 238 try:
239 239 sys.stdout = stdout_trap
240 240 stats.print_stats(*lims)
241 241 finally:
242 242 sys.stdout = sys_stdout
243 243
244 244 output = stdout_trap.getvalue()
245 245 output = output.rstrip()
246 246
247 247 if 'q' not in opts:
248 248 page.page(output)
249 249 print sys_exit,
250 250
251 251 dump_file = opts.D[0]
252 252 text_file = opts.T[0]
253 253 if dump_file:
254 254 dump_file = unquote_filename(dump_file)
255 255 prof.dump_stats(dump_file)
256 256 print '\n*** Profile stats marshalled to file',\
257 257 repr(dump_file)+'.',sys_exit
258 258 if text_file:
259 259 text_file = unquote_filename(text_file)
260 260 pfile = open(text_file,'w')
261 261 pfile.write(output)
262 262 pfile.close()
263 263 print '\n*** Profile printout saved to text file',\
264 264 repr(text_file)+'.',sys_exit
265 265
266 if opts.has_key('r'):
266 if 'r' in opts:
267 267 return stats
268 268 else:
269 269 return None
270 270
271 271 @line_magic
272 272 def pdb(self, parameter_s=''):
273 273 """Control the automatic calling of the pdb interactive debugger.
274 274
275 275 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
276 276 argument it works as a toggle.
277 277
278 278 When an exception is triggered, IPython can optionally call the
279 279 interactive pdb debugger after the traceback printout. %pdb toggles
280 280 this feature on and off.
281 281
282 282 The initial state of this feature is set in your configuration
283 283 file (the option is ``InteractiveShell.pdb``).
284 284
285 285 If you want to just activate the debugger AFTER an exception has fired,
286 286 without having to type '%pdb on' and rerunning your code, you can use
287 287 the %debug magic."""
288 288
289 289 par = parameter_s.strip().lower()
290 290
291 291 if par:
292 292 try:
293 293 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
294 294 except KeyError:
295 295 print ('Incorrect argument. Use on/1, off/0, '
296 296 'or nothing for a toggle.')
297 297 return
298 298 else:
299 299 # toggle
300 300 new_pdb = not self.shell.call_pdb
301 301
302 302 # set on the shell
303 303 self.shell.call_pdb = new_pdb
304 304 print 'Automatic pdb calling has been turned',on_off(new_pdb)
305 305
306 306 @line_magic
307 307 def debug(self, parameter_s=''):
308 308 """Activate the interactive debugger in post-mortem mode.
309 309
310 310 If an exception has just occurred, this lets you inspect its stack
311 311 frames interactively. Note that this will always work only on the last
312 312 traceback that occurred, so you must call this quickly after an
313 313 exception that you wish to inspect has fired, because if another one
314 314 occurs, it clobbers the previous one.
315 315
316 316 If you want IPython to automatically do this on every exception, see
317 317 the %pdb magic for more details.
318 318 """
319 319 self.shell.debugger(force=True)
320 320
321 321 @line_magic
322 322 def tb(self, s):
323 323 """Print the last traceback with the currently active exception mode.
324 324
325 325 See %xmode for changing exception reporting modes."""
326 326 self.shell.showtraceback()
327 327
328 328 @skip_doctest
329 329 @line_magic
330 330 def run(self, parameter_s='', runner=None,
331 331 file_finder=get_py_filename):
332 332 """Run the named file inside IPython as a program.
333 333
334 334 Usage:\\
335 335 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
336 336
337 337 Parameters after the filename are passed as command-line arguments to
338 338 the program (put in sys.argv). Then, control returns to IPython's
339 339 prompt.
340 340
341 341 This is similar to running at a system prompt:\\
342 342 $ python file args\\
343 343 but with the advantage of giving you IPython's tracebacks, and of
344 344 loading all variables into your interactive namespace for further use
345 345 (unless -p is used, see below).
346 346
347 347 The file is executed in a namespace initially consisting only of
348 348 __name__=='__main__' and sys.argv constructed as indicated. It thus
349 349 sees its environment as if it were being run as a stand-alone program
350 350 (except for sharing global objects such as previously imported
351 351 modules). But after execution, the IPython interactive namespace gets
352 352 updated with all variables defined in the program (except for __name__
353 353 and sys.argv). This allows for very convenient loading of code for
354 354 interactive work, while giving each program a 'clean sheet' to run in.
355 355
356 356 Options:
357 357
358 358 -n: __name__ is NOT set to '__main__', but to the running file's name
359 359 without extension (as python does under import). This allows running
360 360 scripts and reloading the definitions in them without calling code
361 361 protected by an ' if __name__ == "__main__" ' clause.
362 362
363 363 -i: run the file in IPython's namespace instead of an empty one. This
364 364 is useful if you are experimenting with code written in a text editor
365 365 which depends on variables defined interactively.
366 366
367 367 -e: ignore sys.exit() calls or SystemExit exceptions in the script
368 368 being run. This is particularly useful if IPython is being used to
369 369 run unittests, which always exit with a sys.exit() call. In such
370 370 cases you are interested in the output of the test results, not in
371 371 seeing a traceback of the unittest module.
372 372
373 373 -t: print timing information at the end of the run. IPython will give
374 374 you an estimated CPU time consumption for your script, which under
375 375 Unix uses the resource module to avoid the wraparound problems of
376 376 time.clock(). Under Unix, an estimate of time spent on system tasks
377 377 is also given (for Windows platforms this is reported as 0.0).
378 378
379 379 If -t is given, an additional -N<N> option can be given, where <N>
380 380 must be an integer indicating how many times you want the script to
381 381 run. The final timing report will include total and per run results.
382 382
383 383 For example (testing the script uniq_stable.py)::
384 384
385 385 In [1]: run -t uniq_stable
386 386
387 387 IPython CPU timings (estimated):\\
388 388 User : 0.19597 s.\\
389 389 System: 0.0 s.\\
390 390
391 391 In [2]: run -t -N5 uniq_stable
392 392
393 393 IPython CPU timings (estimated):\\
394 394 Total runs performed: 5\\
395 395 Times : Total Per run\\
396 396 User : 0.910862 s, 0.1821724 s.\\
397 397 System: 0.0 s, 0.0 s.
398 398
399 399 -d: run your program under the control of pdb, the Python debugger.
400 400 This allows you to execute your program step by step, watch variables,
401 401 etc. Internally, what IPython does is similar to calling:
402 402
403 403 pdb.run('execfile("YOURFILENAME")')
404 404
405 405 with a breakpoint set on line 1 of your file. You can change the line
406 406 number for this automatic breakpoint to be <N> by using the -bN option
407 407 (where N must be an integer). For example::
408 408
409 409 %run -d -b40 myscript
410 410
411 411 will set the first breakpoint at line 40 in myscript.py. Note that
412 412 the first breakpoint must be set on a line which actually does
413 413 something (not a comment or docstring) for it to stop execution.
414 414
415 415 When the pdb debugger starts, you will see a (Pdb) prompt. You must
416 416 first enter 'c' (without quotes) to start execution up to the first
417 417 breakpoint.
418 418
419 419 Entering 'help' gives information about the use of the debugger. You
420 420 can easily see pdb's full documentation with "import pdb;pdb.help()"
421 421 at a prompt.
422 422
423 423 -p: run program under the control of the Python profiler module (which
424 424 prints a detailed report of execution times, function calls, etc).
425 425
426 426 You can pass other options after -p which affect the behavior of the
427 427 profiler itself. See the docs for %prun for details.
428 428
429 429 In this mode, the program's variables do NOT propagate back to the
430 430 IPython interactive namespace (because they remain in the namespace
431 431 where the profiler executes them).
432 432
433 433 Internally this triggers a call to %prun, see its documentation for
434 434 details on the options available specifically for profiling.
435 435
436 436 There is one special usage for which the text above doesn't apply:
437 437 if the filename ends with .ipy, the file is run as ipython script,
438 438 just as if the commands were written on IPython prompt.
439 439
440 440 -m: specify module name to load instead of script path. Similar to
441 441 the -m option for the python interpreter. Use this option last if you
442 442 want to combine with other %run options. Unlike the python interpreter
443 443 only source modules are allowed no .pyc or .pyo files.
444 444 For example::
445 445
446 446 %run -m example
447 447
448 448 will run the example module.
449 449
450 450 """
451 451
452 452 # get arguments and set sys.argv for program to be run.
453 453 opts, arg_lst = self.parse_options(parameter_s, 'nidtN:b:pD:l:rs:T:em:',
454 454 mode='list', list_all=1)
455 455 if "m" in opts:
456 456 modulename = opts["m"][0]
457 457 modpath = find_mod(modulename)
458 458 if modpath is None:
459 459 warn('%r is not a valid modulename on sys.path'%modulename)
460 460 return
461 461 arg_lst = [modpath] + arg_lst
462 462 try:
463 463 filename = file_finder(arg_lst[0])
464 464 except IndexError:
465 465 warn('you must provide at least a filename.')
466 466 print '\n%run:\n', oinspect.getdoc(self.run)
467 467 return
468 468 except IOError as e:
469 469 try:
470 470 msg = str(e)
471 471 except UnicodeError:
472 472 msg = e.message
473 473 error(msg)
474 474 return
475 475
476 476 if filename.lower().endswith('.ipy'):
477 477 self.shell.safe_execfile_ipy(filename)
478 478 return
479 479
480 480 # Control the response to exit() calls made by the script being run
481 481 exit_ignore = 'e' in opts
482 482
483 483 # Make sure that the running script gets a proper sys.argv as if it
484 484 # were run from a system shell.
485 485 save_argv = sys.argv # save it for later restoring
486 486
487 487 # simulate shell expansion on arguments, at least tilde expansion
488 488 args = [ os.path.expanduser(a) for a in arg_lst[1:] ]
489 489
490 490 sys.argv = [filename] + args # put in the proper filename
491 491 # protect sys.argv from potential unicode strings on Python 2:
492 492 if not py3compat.PY3:
493 493 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
494 494
495 495 if 'i' in opts:
496 496 # Run in user's interactive namespace
497 497 prog_ns = self.shell.user_ns
498 498 __name__save = self.shell.user_ns['__name__']
499 499 prog_ns['__name__'] = '__main__'
500 500 main_mod = self.shell.new_main_mod(prog_ns)
501 501 else:
502 502 # Run in a fresh, empty namespace
503 503 if 'n' in opts:
504 504 name = os.path.splitext(os.path.basename(filename))[0]
505 505 else:
506 506 name = '__main__'
507 507
508 508 main_mod = self.shell.new_main_mod()
509 509 prog_ns = main_mod.__dict__
510 510 prog_ns['__name__'] = name
511 511
512 512 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
513 513 # set the __file__ global in the script's namespace
514 514 prog_ns['__file__'] = filename
515 515
516 516 # pickle fix. See interactiveshell for an explanation. But we need to
517 517 # make sure that, if we overwrite __main__, we replace it at the end
518 518 main_mod_name = prog_ns['__name__']
519 519
520 520 if main_mod_name == '__main__':
521 521 restore_main = sys.modules['__main__']
522 522 else:
523 523 restore_main = False
524 524
525 525 # This needs to be undone at the end to prevent holding references to
526 526 # every single object ever created.
527 527 sys.modules[main_mod_name] = main_mod
528 528
529 529 try:
530 530 stats = None
531 531 with self.shell.readline_no_record:
532 532 if 'p' in opts:
533 533 stats = self.prun('', None, False, opts, arg_lst, prog_ns)
534 534 else:
535 535 if 'd' in opts:
536 536 deb = debugger.Pdb(self.shell.colors)
537 537 # reset Breakpoint state, which is moronically kept
538 538 # in a class
539 539 bdb.Breakpoint.next = 1
540 540 bdb.Breakpoint.bplist = {}
541 541 bdb.Breakpoint.bpbynumber = [None]
542 542 # Set an initial breakpoint to stop execution
543 543 maxtries = 10
544 544 bp = int(opts.get('b', [1])[0])
545 545 checkline = deb.checkline(filename, bp)
546 546 if not checkline:
547 547 for bp in range(bp + 1, bp + maxtries + 1):
548 548 if deb.checkline(filename, bp):
549 549 break
550 550 else:
551 551 msg = ("\nI failed to find a valid line to set "
552 552 "a breakpoint\n"
553 553 "after trying up to line: %s.\n"
554 554 "Please set a valid breakpoint manually "
555 555 "with the -b option." % bp)
556 556 error(msg)
557 557 return
558 558 # if we find a good linenumber, set the breakpoint
559 559 deb.do_break('%s:%s' % (filename, bp))
560 560 # Start file run
561 561 print "NOTE: Enter 'c' at the",
562 562 print "%s prompt to start your script." % deb.prompt
563 563 ns = {'execfile': py3compat.execfile, 'prog_ns': prog_ns}
564 564 try:
565 565 deb.run('execfile("%s", prog_ns)' % filename, ns)
566 566
567 567 except:
568 568 etype, value, tb = sys.exc_info()
569 569 # Skip three frames in the traceback: the %run one,
570 570 # one inside bdb.py, and the command-line typed by the
571 571 # user (run by exec in pdb itself).
572 572 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
573 573 else:
574 574 if runner is None:
575 575 runner = self.default_runner
576 576 if runner is None:
577 577 runner = self.shell.safe_execfile
578 578 if 't' in opts:
579 579 # timed execution
580 580 try:
581 581 nruns = int(opts['N'][0])
582 582 if nruns < 1:
583 583 error('Number of runs must be >=1')
584 584 return
585 585 except (KeyError):
586 586 nruns = 1
587 587 twall0 = time.time()
588 588 if nruns == 1:
589 589 t0 = clock2()
590 590 runner(filename, prog_ns, prog_ns,
591 591 exit_ignore=exit_ignore)
592 592 t1 = clock2()
593 593 t_usr = t1[0] - t0[0]
594 594 t_sys = t1[1] - t0[1]
595 595 print "\nIPython CPU timings (estimated):"
596 596 print " User : %10.2f s." % t_usr
597 597 print " System : %10.2f s." % t_sys
598 598 else:
599 599 runs = range(nruns)
600 600 t0 = clock2()
601 601 for nr in runs:
602 602 runner(filename, prog_ns, prog_ns,
603 603 exit_ignore=exit_ignore)
604 604 t1 = clock2()
605 605 t_usr = t1[0] - t0[0]
606 606 t_sys = t1[1] - t0[1]
607 607 print "\nIPython CPU timings (estimated):"
608 608 print "Total runs performed:", nruns
609 609 print " Times : %10.2f %10.2f" % ('Total', 'Per run')
610 610 print " User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)
611 611 print " System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)
612 612 twall1 = time.time()
613 613 print "Wall time: %10.2f s." % (twall1 - twall0)
614 614
615 615 else:
616 616 # regular execution
617 617 runner(filename, prog_ns, prog_ns, exit_ignore=exit_ignore)
618 618
619 619 if 'i' in opts:
620 620 self.shell.user_ns['__name__'] = __name__save
621 621 else:
622 622 # The shell MUST hold a reference to prog_ns so after %run
623 623 # exits, the python deletion mechanism doesn't zero it out
624 624 # (leaving dangling references).
625 625 self.shell.cache_main_mod(prog_ns, filename)
626 626 # update IPython interactive namespace
627 627
628 628 # Some forms of read errors on the file may mean the
629 629 # __name__ key was never set; using pop we don't have to
630 630 # worry about a possible KeyError.
631 631 prog_ns.pop('__name__', None)
632 632
633 633 self.shell.user_ns.update(prog_ns)
634 634 finally:
635 635 # It's a bit of a mystery why, but __builtins__ can change from
636 636 # being a module to becoming a dict missing some key data after
637 637 # %run. As best I can see, this is NOT something IPython is doing
638 638 # at all, and similar problems have been reported before:
639 639 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
640 640 # Since this seems to be done by the interpreter itself, the best
641 641 # we can do is to at least restore __builtins__ for the user on
642 642 # exit.
643 643 self.shell.user_ns['__builtins__'] = builtin_mod
644 644
645 645 # Ensure key global structures are restored
646 646 sys.argv = save_argv
647 647 if restore_main:
648 648 sys.modules['__main__'] = restore_main
649 649 else:
650 650 # Remove from sys.modules the reference to main_mod we'd
651 651 # added. Otherwise it will trap references to objects
652 652 # contained therein.
653 653 del sys.modules[main_mod_name]
654 654
655 655 return stats
656 656
657 657 @skip_doctest
658 658 @line_cell_magic
659 659 def timeit(self, line='', cell=None):
660 660 """Time execution of a Python statement or expression
661 661
662 662 Usage, in line mode:
663 663 %timeit [-n<N> -r<R> [-t|-c]] statement
664 664 or in cell mode:
665 665 %%timeit [-n<N> -r<R> [-t|-c]] setup_code
666 666 code
667 667 code...
668 668
669 669 Time execution of a Python statement or expression using the timeit
670 670 module. This function can be used both as a line and cell magic:
671 671
672 672 - In line mode you can time a single-line statement (though multiple
673 673 ones can be chained with using semicolons).
674 674
675 675 - In cell mode, the statement in the first line is used as setup code
676 676 (executed but not timed) and the body of the cell is timed. The cell
677 677 body has access to any variables created in the setup code.
678 678
679 679 Options:
680 680 -n<N>: execute the given statement <N> times in a loop. If this value
681 681 is not given, a fitting value is chosen.
682 682
683 683 -r<R>: repeat the loop iteration <R> times and take the best result.
684 684 Default: 3
685 685
686 686 -t: use time.time to measure the time, which is the default on Unix.
687 687 This function measures wall time.
688 688
689 689 -c: use time.clock to measure the time, which is the default on
690 690 Windows and measures wall time. On Unix, resource.getrusage is used
691 691 instead and returns the CPU user time.
692 692
693 693 -p<P>: use a precision of <P> digits to display the timing result.
694 694 Default: 3
695 695
696 696
697 697 Examples
698 698 --------
699 699 ::
700 700
701 701 In [1]: %timeit pass
702 702 10000000 loops, best of 3: 53.3 ns per loop
703 703
704 704 In [2]: u = None
705 705
706 706 In [3]: %timeit u is None
707 707 10000000 loops, best of 3: 184 ns per loop
708 708
709 709 In [4]: %timeit -r 4 u == None
710 710 1000000 loops, best of 4: 242 ns per loop
711 711
712 712 In [5]: import time
713 713
714 714 In [6]: %timeit -n1 time.sleep(2)
715 715 1 loops, best of 3: 2 s per loop
716 716
717 717
718 718 The times reported by %timeit will be slightly higher than those
719 719 reported by the timeit.py script when variables are accessed. This is
720 720 due to the fact that %timeit executes the statement in the namespace
721 721 of the shell, compared with timeit.py, which uses a single setup
722 722 statement to import function or create variables. Generally, the bias
723 723 does not matter as long as results from timeit.py are not mixed with
724 724 those from %timeit."""
725 725
726 726 import timeit
727 727 import math
728 728
729 729 # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
730 730 # certain terminals. Until we figure out a robust way of
731 731 # auto-detecting if the terminal can deal with it, use plain 'us' for
732 732 # microseconds. I am really NOT happy about disabling the proper
733 733 # 'micro' prefix, but crashing is worse... If anyone knows what the
734 734 # right solution for this is, I'm all ears...
735 735 #
736 736 # Note: using
737 737 #
738 738 # s = u'\xb5'
739 739 # s.encode(sys.getdefaultencoding())
740 740 #
741 741 # is not sufficient, as I've seen terminals where that fails but
742 742 # print s
743 743 #
744 744 # succeeds
745 745 #
746 746 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
747 747
748 748 #units = [u"s", u"ms",u'\xb5',"ns"]
749 749 units = [u"s", u"ms",u'us',"ns"]
750 750
751 751 scaling = [1, 1e3, 1e6, 1e9]
752 752
753 753 opts, stmt = self.parse_options(line,'n:r:tcp:',
754 754 posix=False, strict=False)
755 755 if stmt == "" and cell is None:
756 756 return
757 757 timefunc = timeit.default_timer
758 758 number = int(getattr(opts, "n", 0))
759 759 repeat = int(getattr(opts, "r", timeit.default_repeat))
760 760 precision = int(getattr(opts, "p", 3))
761 761 if hasattr(opts, "t"):
762 762 timefunc = time.time
763 763 if hasattr(opts, "c"):
764 764 timefunc = clock
765 765
766 766 timer = timeit.Timer(timer=timefunc)
767 767 # this code has tight coupling to the inner workings of timeit.Timer,
768 768 # but is there a better way to achieve that the code stmt has access
769 769 # to the shell namespace?
770 770 transform = self.shell.input_splitter.transform_cell
771 771 if cell is None:
772 772 # called as line magic
773 773 setup = 'pass'
774 774 stmt = timeit.reindent(transform(stmt), 8)
775 775 else:
776 776 setup = timeit.reindent(transform(stmt), 4)
777 777 stmt = timeit.reindent(transform(cell), 8)
778 778
779 779 # From Python 3.3, this template uses new-style string formatting.
780 780 if sys.version_info >= (3, 3):
781 781 src = timeit.template.format(stmt=stmt, setup=setup)
782 782 else:
783 783 src = timeit.template % dict(stmt=stmt, setup=setup)
784 784
785 785 # Track compilation time so it can be reported if too long
786 786 # Minimum time above which compilation time will be reported
787 787 tc_min = 0.1
788 788
789 789 t0 = clock()
790 790 code = compile(src, "<magic-timeit>", "exec")
791 791 tc = clock()-t0
792 792
793 793 ns = {}
794 794 exec code in self.shell.user_ns, ns
795 795 timer.inner = ns["inner"]
796 796
797 797 if number == 0:
798 798 # determine number so that 0.2 <= total time < 2.0
799 799 number = 1
800 800 for i in range(1, 10):
801 801 if timer.timeit(number) >= 0.2:
802 802 break
803 803 number *= 10
804 804
805 805 best = min(timer.repeat(repeat, number)) / number
806 806
807 807 if best > 0.0 and best < 1000.0:
808 808 order = min(-int(math.floor(math.log10(best)) // 3), 3)
809 809 elif best >= 1000.0:
810 810 order = 0
811 811 else:
812 812 order = 3
813 813 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
814 814 precision,
815 815 best * scaling[order],
816 816 units[order])
817 817 if tc > tc_min:
818 818 print "Compiler time: %.2f s" % tc
819 819
820 820 @skip_doctest
821 821 @needs_local_scope
822 822 @line_magic
823 823 def time(self,parameter_s, user_locals):
824 824 """Time execution of a Python statement or expression.
825 825
826 826 The CPU and wall clock times are printed, and the value of the
827 827 expression (if any) is returned. Note that under Win32, system time
828 828 is always reported as 0, since it can not be measured.
829 829
830 830 This function provides very basic timing functionality. In Python
831 831 2.3, the timeit module offers more control and sophistication, so this
832 832 could be rewritten to use it (patches welcome).
833 833
834 834 Examples
835 835 --------
836 836 ::
837 837
838 838 In [1]: time 2**128
839 839 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
840 840 Wall time: 0.00
841 841 Out[1]: 340282366920938463463374607431768211456L
842 842
843 843 In [2]: n = 1000000
844 844
845 845 In [3]: time sum(range(n))
846 846 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
847 847 Wall time: 1.37
848 848 Out[3]: 499999500000L
849 849
850 850 In [4]: time print 'hello world'
851 851 hello world
852 852 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
853 853 Wall time: 0.00
854 854
855 855 Note that the time needed by Python to compile the given expression
856 856 will be reported if it is more than 0.1s. In this example, the
857 857 actual exponentiation is done by Python at compilation time, so while
858 858 the expression can take a noticeable amount of time to compute, that
859 859 time is purely due to the compilation:
860 860
861 861 In [5]: time 3**9999;
862 862 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
863 863 Wall time: 0.00 s
864 864
865 865 In [6]: time 3**999999;
866 866 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
867 867 Wall time: 0.00 s
868 868 Compiler : 0.78 s
869 869 """
870 870
871 871 # fail immediately if the given expression can't be compiled
872 872
873 873 expr = self.shell.prefilter(parameter_s,False)
874 874
875 875 # Minimum time above which compilation time will be reported
876 876 tc_min = 0.1
877 877
878 878 try:
879 879 mode = 'eval'
880 880 t0 = clock()
881 881 code = compile(expr,'<timed eval>',mode)
882 882 tc = clock()-t0
883 883 except SyntaxError:
884 884 mode = 'exec'
885 885 t0 = clock()
886 886 code = compile(expr,'<timed exec>',mode)
887 887 tc = clock()-t0
888 888 # skew measurement as little as possible
889 889 glob = self.shell.user_ns
890 890 wtime = time.time
891 891 # time execution
892 892 wall_st = wtime()
893 893 if mode=='eval':
894 894 st = clock2()
895 895 out = eval(code, glob, user_locals)
896 896 end = clock2()
897 897 else:
898 898 st = clock2()
899 899 exec code in glob, user_locals
900 900 end = clock2()
901 901 out = None
902 902 wall_end = wtime()
903 903 # Compute actual times and report
904 904 wall_time = wall_end-wall_st
905 905 cpu_user = end[0]-st[0]
906 906 cpu_sys = end[1]-st[1]
907 907 cpu_tot = cpu_user+cpu_sys
908 908 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
909 909 (cpu_user,cpu_sys,cpu_tot)
910 910 print "Wall time: %.2f s" % wall_time
911 911 if tc > tc_min:
912 912 print "Compiler : %.2f s" % tc
913 913 return out
914 914
915 915 @skip_doctest
916 916 @line_magic
917 917 def macro(self, parameter_s=''):
918 918 """Define a macro for future re-execution. It accepts ranges of history,
919 919 filenames or string objects.
920 920
921 921 Usage:\\
922 922 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
923 923
924 924 Options:
925 925
926 926 -r: use 'raw' input. By default, the 'processed' history is used,
927 927 so that magics are loaded in their transformed version to valid
928 928 Python. If this option is given, the raw input as typed as the
929 929 command line is used instead.
930 930
931 931 This will define a global variable called `name` which is a string
932 932 made of joining the slices and lines you specify (n1,n2,... numbers
933 933 above) from your input history into a single string. This variable
934 934 acts like an automatic function which re-executes those lines as if
935 935 you had typed them. You just type 'name' at the prompt and the code
936 936 executes.
937 937
938 938 The syntax for indicating input ranges is described in %history.
939 939
940 940 Note: as a 'hidden' feature, you can also use traditional python slice
941 941 notation, where N:M means numbers N through M-1.
942 942
943 943 For example, if your history contains (%hist prints it)::
944 944
945 945 44: x=1
946 946 45: y=3
947 947 46: z=x+y
948 948 47: print x
949 949 48: a=5
950 950 49: print 'x',x,'y',y
951 951
952 952 you can create a macro with lines 44 through 47 (included) and line 49
953 953 called my_macro with::
954 954
955 955 In [55]: %macro my_macro 44-47 49
956 956
957 957 Now, typing `my_macro` (without quotes) will re-execute all this code
958 958 in one pass.
959 959
960 960 You don't need to give the line-numbers in order, and any given line
961 961 number can appear multiple times. You can assemble macros with any
962 962 lines from your input history in any order.
963 963
964 964 The macro is a simple object which holds its value in an attribute,
965 965 but IPython's display system checks for macros and executes them as
966 966 code instead of printing them when you type their name.
967 967
968 968 You can view a macro's contents by explicitly printing it with::
969 969
970 970 print macro_name
971 971
972 972 """
973 973 opts,args = self.parse_options(parameter_s,'r',mode='list')
974 974 if not args: # List existing macros
975 975 return sorted(k for k,v in self.shell.user_ns.iteritems() if\
976 976 isinstance(v, Macro))
977 977 if len(args) == 1:
978 978 raise UsageError(
979 979 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
980 980 name, codefrom = args[0], " ".join(args[1:])
981 981
982 982 #print 'rng',ranges # dbg
983 983 try:
984 984 lines = self.shell.find_user_code(codefrom, 'r' in opts)
985 985 except (ValueError, TypeError) as e:
986 986 print e.args[0]
987 987 return
988 988 macro = Macro(lines)
989 989 self.shell.define_macro(name, macro)
990 990 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
991 991 print '=== Macro contents: ==='
992 992 print macro,
993 993
994 994 @magic_arguments.magic_arguments()
995 995 @magic_arguments.argument('output', type=str, default='', nargs='?',
996 996 help="""The name of the variable in which to store output.
997 997 This is a utils.io.CapturedIO object with stdout/err attributes
998 998 for the text of the captured output.
999 999
1000 1000 CapturedOutput also has a show() method for displaying the output,
1001 1001 and __call__ as well, so you can use that to quickly display the
1002 1002 output.
1003 1003
1004 1004 If unspecified, captured output is discarded.
1005 1005 """
1006 1006 )
1007 1007 @magic_arguments.argument('--no-stderr', action="store_true",
1008 1008 help="""Don't capture stderr."""
1009 1009 )
1010 1010 @magic_arguments.argument('--no-stdout', action="store_true",
1011 1011 help="""Don't capture stdout."""
1012 1012 )
1013 1013 @cell_magic
1014 1014 def capture(self, line, cell):
1015 1015 """run the cell, capturing stdout/err"""
1016 1016 args = magic_arguments.parse_argstring(self.capture, line)
1017 1017 out = not args.no_stdout
1018 1018 err = not args.no_stderr
1019 1019 with capture_output(out, err) as io:
1020 1020 self.shell.run_cell(cell)
1021 1021 if args.output:
1022 1022 self.shell.user_ns[args.output] = io
@@ -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 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 if opts.has_key('i'):
217 if 'i' in opts:
218 218 ignore_case = True
219 elif opts.has_key('c'):
219 elif 'c' in opts:
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 if opts.has_key('f'):
659 if 'f' in opts:
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,51 +1,51 b''
1 1 # encoding: utf-8
2 2 """IPython plugins.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010-2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 from IPython.config.configurable import Configurable
21 21 from IPython.utils.traitlets import Dict
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Main class
25 25 #-----------------------------------------------------------------------------
26 26
27 27 class PluginManager(Configurable):
28 28 """A manager for IPython plugins."""
29 29
30 30 plugins = Dict({})
31 31
32 32 def __init__(self, config=None):
33 33 super(PluginManager, self).__init__(config=config)
34 34
35 35 def register_plugin(self, name, plugin):
36 36 if not isinstance(plugin, Plugin):
37 37 raise TypeError('Expected Plugin, got: %r' % plugin)
38 if self.plugins.has_key(name):
38 if name in self.plugins:
39 39 raise KeyError('Plugin with name already exists: %r' % name)
40 40 self.plugins[name] = plugin
41 41
42 42 def unregister_plugin(self, name):
43 43 del self.plugins[name]
44 44
45 45 def get_plugin(self, name, default=None):
46 46 return self.plugins.get(name, default)
47 47
48 48
49 49 class Plugin(Configurable):
50 50 """Base class for IPython plugins."""
51 51 pass
@@ -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 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 if locals.has_key(name_base):
895 if name_base in locals:
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 if frame.f_globals.has_key(name_base):
904 if name_base in frame.f_globals:
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 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 handler(*sys.exc_info())
1243 1243 print ''
1244 1244
@@ -1,234 +1,234 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 %store magic for lightweight persistence.
4 4
5 5 Stores variables, aliases and macros in IPython's database.
6 6
7 7 To automatically restore stored variables at startup, add this to your
8 8 :file:`ipython_config.py` file::
9 9
10 10 c.StoreMagic.autorestore = True
11 11 """
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (c) 2012, The IPython Development Team.
14 14 #
15 15 # Distributed under the terms of the Modified BSD License.
16 16 #
17 17 # The full license is in the file COPYING.txt, distributed with this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Imports
22 22 #-----------------------------------------------------------------------------
23 23
24 24 # Stdlib
25 25 import inspect, os, sys, textwrap
26 26
27 27 # Our own
28 28 from IPython.core.error import UsageError
29 29 from IPython.core.fakemodule import FakeModule
30 30 from IPython.core.magic import Magics, magics_class, line_magic
31 31 from IPython.core.plugin import Plugin
32 32 from IPython.testing.skipdoctest import skip_doctest
33 33 from IPython.utils.traitlets import Bool, Instance
34 34
35 35 #-----------------------------------------------------------------------------
36 36 # Functions and classes
37 37 #-----------------------------------------------------------------------------
38 38
39 39 def restore_aliases(ip):
40 40 staliases = ip.db.get('stored_aliases', {})
41 41 for k,v in staliases.items():
42 42 #print "restore alias",k,v # dbg
43 43 #self.alias_table[k] = v
44 44 ip.alias_manager.define_alias(k,v)
45 45
46 46
47 47 def refresh_variables(ip):
48 48 db = ip.db
49 49 for key in db.keys('autorestore/*'):
50 50 # strip autorestore
51 51 justkey = os.path.basename(key)
52 52 try:
53 53 obj = db[key]
54 54 except KeyError:
55 55 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
56 56 print "The error was:", sys.exc_info()[0]
57 57 else:
58 58 #print "restored",justkey,"=",obj #dbg
59 59 ip.user_ns[justkey] = obj
60 60
61 61
62 62 def restore_dhist(ip):
63 63 ip.user_ns['_dh'] = ip.db.get('dhist',[])
64 64
65 65
66 66 def restore_data(ip):
67 67 refresh_variables(ip)
68 68 restore_aliases(ip)
69 69 restore_dhist(ip)
70 70
71 71
72 72 @magics_class
73 73 class StoreMagics(Magics):
74 74 """Lightweight persistence for python variables.
75 75
76 76 Provides the %store magic."""
77 77
78 78 @skip_doctest
79 79 @line_magic
80 80 def store(self, parameter_s=''):
81 81 """Lightweight persistence for python variables.
82 82
83 83 Example::
84 84
85 85 In [1]: l = ['hello',10,'world']
86 86 In [2]: %store l
87 87 In [3]: exit
88 88
89 89 (IPython session is closed and started again...)
90 90
91 91 ville@badger:~$ ipython
92 92 In [1]: l
93 93 Out[1]: ['hello', 10, 'world']
94 94
95 95 Usage:
96 96
97 97 * ``%store`` - Show list of all variables and their current
98 98 values
99 99 * ``%store spam`` - Store the *current* value of the variable spam
100 100 to disk
101 101 * ``%store -d spam`` - Remove the variable and its value from storage
102 102 * ``%store -z`` - Remove all variables from storage
103 103 * ``%store -r`` - Refresh all variables from store (delete
104 104 current vals)
105 105 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
106 106 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
107 107
108 108 It should be noted that if you change the value of a variable, you
109 109 need to %store it again if you want to persist the new value.
110 110
111 111 Note also that the variables will need to be pickleable; most basic
112 112 python types can be safely %store'd.
113 113
114 114 Also aliases can be %store'd across sessions.
115 115 """
116 116
117 117 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
118 118 args = argsl.split(None,1)
119 119 ip = self.shell
120 120 db = ip.db
121 121 # delete
122 if opts.has_key('d'):
122 if 'd' in opts:
123 123 try:
124 124 todel = args[0]
125 125 except IndexError:
126 126 raise UsageError('You must provide the variable to forget')
127 127 else:
128 128 try:
129 129 del db['autorestore/' + todel]
130 130 except:
131 131 raise UsageError("Can't delete variable '%s'" % todel)
132 132 # reset
133 elif opts.has_key('z'):
133 elif 'z' in opts:
134 134 for k in db.keys('autorestore/*'):
135 135 del db[k]
136 136
137 elif opts.has_key('r'):
137 elif 'r' in opts:
138 138 refresh_variables(ip)
139 139
140 140
141 141 # run without arguments -> list variables & values
142 142 elif not args:
143 143 vars = self.db.keys('autorestore/*')
144 144 vars.sort()
145 145 if vars:
146 146 size = max(map(len, vars))
147 147 else:
148 148 size = 0
149 149
150 150 print 'Stored variables and their in-db values:'
151 151 fmt = '%-'+str(size)+'s -> %s'
152 152 get = db.get
153 153 for var in vars:
154 154 justkey = os.path.basename(var)
155 155 # print 30 first characters from every var
156 156 print fmt % (justkey, repr(get(var, '<unavailable>'))[:50])
157 157
158 158 # default action - store the variable
159 159 else:
160 160 # %store foo >file.txt or >>file.txt
161 161 if len(args) > 1 and args[1].startswith('>'):
162 162 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
163 163 if args[1].startswith('>>'):
164 164 fil = open(fnam, 'a')
165 165 else:
166 166 fil = open(fnam, 'w')
167 167 obj = ip.ev(args[0])
168 168 print "Writing '%s' (%s) to file '%s'." % (args[0],
169 169 obj.__class__.__name__, fnam)
170 170
171 171
172 172 if not isinstance (obj, basestring):
173 173 from pprint import pprint
174 174 pprint(obj, fil)
175 175 else:
176 176 fil.write(obj)
177 177 if not obj.endswith('\n'):
178 178 fil.write('\n')
179 179
180 180 fil.close()
181 181 return
182 182
183 183 # %store foo
184 184 try:
185 185 obj = ip.user_ns[args[0]]
186 186 except KeyError:
187 187 # it might be an alias
188 188 # This needs to be refactored to use the new AliasManager stuff.
189 189 if args[0] in self.alias_manager:
190 190 name = args[0]
191 191 nargs, cmd = self.alias_manager.alias_table[ name ]
192 192 staliases = db.get('stored_aliases',{})
193 193 staliases[ name ] = cmd
194 194 db['stored_aliases'] = staliases
195 195 print "Alias stored: %s (%s)" % (name, cmd)
196 196 return
197 197 else:
198 198 raise UsageError("Unknown variable '%s'" % args[0])
199 199
200 200 else:
201 201 if isinstance(inspect.getmodule(obj), FakeModule):
202 202 print textwrap.dedent("""\
203 203 Warning:%s is %s
204 204 Proper storage of interactively declared classes (or instances
205 205 of those classes) is not possible! Only instances
206 206 of classes in real modules on file system can be %%store'd.
207 207 """ % (args[0], obj) )
208 208 return
209 209 #pickled = pickle.dumps(obj)
210 210 self.db[ 'autorestore/' + args[0] ] = obj
211 211 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
212 212
213 213
214 214 class StoreMagic(Plugin):
215 215 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
216 216 autorestore = Bool(False, config=True)
217 217
218 218 def __init__(self, shell, config):
219 219 super(StoreMagic, self).__init__(shell=shell, config=config)
220 220 shell.register_magics(StoreMagics)
221 221
222 222 if self.autorestore:
223 223 restore_data(shell)
224 224
225 225
226 226 _loaded = False
227 227
228 228 def load_ipython_extension(ip):
229 229 """Load the extension in IPython."""
230 230 global _loaded
231 231 if not _loaded:
232 232 plugin = StoreMagic(shell=ip, config=ip.config)
233 233 ip.plugin_manager.register_plugin('storemagic', plugin)
234 234 _loaded = True
@@ -1,1903 +1,1903 b''
1 1 """Pexpect is a Python module for spawning child applications and controlling
2 2 them automatically. Pexpect can be used for automating interactive applications
3 3 such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
4 4 scripts for duplicating software package installations on different servers. It
5 5 can be used for automated software testing. Pexpect is in the spirit of Don
6 6 Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
7 7 require TCL and Expect or require C extensions to be compiled. Pexpect does not
8 8 use C, Expect, or TCL extensions. It should work on any platform that supports
9 9 the standard Python pty module. The Pexpect interface focuses on ease of use so
10 10 that simple tasks are easy.
11 11
12 12 There are two main interfaces to the Pexpect system; these are the function,
13 13 run() and the class, spawn. The spawn class is more powerful. The run()
14 14 function is simpler than spawn, and is good for quickly calling program. When
15 15 you call the run() function it executes a given program and then returns the
16 16 output. This is a handy replacement for os.system().
17 17
18 18 For example::
19 19
20 20 pexpect.run('ls -la')
21 21
22 22 The spawn class is the more powerful interface to the Pexpect system. You can
23 23 use this to spawn a child program then interact with it by sending input and
24 24 expecting responses (waiting for patterns in the child's output).
25 25
26 26 For example::
27 27
28 28 child = pexpect.spawn('scp foo myname@host.example.com:.')
29 29 child.expect ('Password:')
30 30 child.sendline (mypassword)
31 31
32 32 This works even for commands that ask for passwords or other input outside of
33 33 the normal stdio streams. For example, ssh reads input directly from the TTY
34 34 device which bypasses stdin.
35 35
36 36 Credits: Noah Spurrier, Richard Holden, Marco Molteni, Kimberley Burchett,
37 37 Robert Stone, Hartmut Goebel, Chad Schroeder, Erick Tryzelaar, Dave Kirby, Ids
38 38 vander Molen, George Todd, Noel Taylor, Nicolas D. Cesar, Alexander Gattin,
39 39 Jacques-Etienne Baudoux, Geoffrey Marshall, Francisco Lourenco, Glen Mabey,
40 40 Karthik Gurusamy, Fernando Perez, Corey Minyard, Jon Cohen, Guillaume
41 41 Chazarain, Andrew Ryan, Nick Craig-Wood, Andrew Stone, Jorgen Grahn, John
42 42 Spiegel, Jan Grant, Shane Kerr and Thomas Kluyver. Let me know if I forgot anyone.
43 43
44 44 Pexpect is free, open source, and all that good stuff.
45 45
46 46 Permission is hereby granted, free of charge, to any person obtaining a copy of
47 47 this software and associated documentation files (the "Software"), to deal in
48 48 the Software without restriction, including without limitation the rights to
49 49 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
50 50 of the Software, and to permit persons to whom the Software is furnished to do
51 51 so, subject to the following conditions:
52 52
53 53 The above copyright notice and this permission notice shall be included in all
54 54 copies or substantial portions of the Software.
55 55
56 56 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57 57 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58 58 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
59 59 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
60 60 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
61 61 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
62 62 SOFTWARE.
63 63
64 64 Pexpect Copyright (c) 2008-2011 Noah Spurrier
65 65 http://pexpect.sourceforge.net/
66 66 """
67 67
68 68 try:
69 69 import os, sys, time
70 70 import select
71 71 import re
72 72 import struct
73 73 import resource
74 74 import types
75 75 import pty
76 76 import tty
77 77 import termios
78 78 import fcntl
79 79 import errno
80 80 import traceback
81 81 import signal
82 82 except ImportError as e:
83 83 raise ImportError (str(e) + """
84 84
85 85 A critical module was not found. Probably this operating system does not
86 86 support it. Pexpect is intended for UNIX-like operating systems.""")
87 87
88 88 __version__ = '2.6.dev'
89 89 version = __version__
90 90 version_info = (2,6,'dev')
91 91 __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnb', 'run', 'which',
92 92 'split_command_line', '__version__']
93 93
94 94 # Exception classes used by this module.
95 95 class ExceptionPexpect(Exception):
96 96
97 97 """Base class for all exceptions raised by this module.
98 98 """
99 99
100 100 def __init__(self, value):
101 101
102 102 self.value = value
103 103
104 104 def __str__(self):
105 105
106 106 return str(self.value)
107 107
108 108 def get_trace(self):
109 109
110 110 """This returns an abbreviated stack trace with lines that only concern
111 111 the caller. In other words, the stack trace inside the Pexpect module
112 112 is not included. """
113 113
114 114 tblist = traceback.extract_tb(sys.exc_info()[2])
115 115 #tblist = filter(self.__filter_not_pexpect, tblist)
116 116 tblist = [item for item in tblist if self.__filter_not_pexpect(item)]
117 117 tblist = traceback.format_list(tblist)
118 118 return ''.join(tblist)
119 119
120 120 def __filter_not_pexpect(self, trace_list_item):
121 121
122 122 """This returns True if list item 0 the string 'pexpect.py' in it. """
123 123
124 124 if trace_list_item[0].find('pexpect.py') == -1:
125 125 return True
126 126 else:
127 127 return False
128 128
129 129 class EOF(ExceptionPexpect):
130 130
131 131 """Raised when EOF is read from a child. This usually means the child has exited."""
132 132
133 133 class TIMEOUT(ExceptionPexpect):
134 134
135 135 """Raised when a read time exceeds the timeout. """
136 136
137 137 ##class TIMEOUT_PATTERN(TIMEOUT):
138 138 ## """Raised when the pattern match time exceeds the timeout.
139 139 ## This is different than a read TIMEOUT because the child process may
140 140 ## give output, thus never give a TIMEOUT, but the output
141 141 ## may never match a pattern.
142 142 ## """
143 143 ##class MAXBUFFER(ExceptionPexpect):
144 144 ## """Raised when a scan buffer fills before matching an expected pattern."""
145 145
146 146 PY3 = (sys.version_info[0] >= 3)
147 147
148 148 def _cast_bytes(s, enc):
149 149 if isinstance(s, unicode):
150 150 return s.encode(enc)
151 151 return s
152 152
153 153 def _cast_unicode(s, enc):
154 154 if isinstance(s, bytes):
155 155 return s.decode(enc)
156 156 return s
157 157
158 158 re_type = type(re.compile(''))
159 159
160 160 def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None,
161 161 logfile=None, cwd=None, env=None, encoding='utf-8'):
162 162
163 163 """
164 164 This function runs the given command; waits for it to finish; then
165 165 returns all output as a string. STDERR is included in output. If the full
166 166 path to the command is not given then the path is searched.
167 167
168 168 Note that lines are terminated by CR/LF (\\r\\n) combination even on
169 169 UNIX-like systems because this is the standard for pseudo ttys. If you set
170 170 'withexitstatus' to true, then run will return a tuple of (command_output,
171 171 exitstatus). If 'withexitstatus' is false then this returns just
172 172 command_output.
173 173
174 174 The run() function can often be used instead of creating a spawn instance.
175 175 For example, the following code uses spawn::
176 176
177 177 from pexpect import *
178 178 child = spawn('scp foo myname@host.example.com:.')
179 179 child.expect ('(?i)password')
180 180 child.sendline (mypassword)
181 181
182 182 The previous code can be replace with the following::
183 183
184 184 from pexpect import *
185 185 run ('scp foo myname@host.example.com:.', events={'(?i)password': mypassword})
186 186
187 187 Examples
188 188 ========
189 189
190 190 Start the apache daemon on the local machine::
191 191
192 192 from pexpect import *
193 193 run ("/usr/local/apache/bin/apachectl start")
194 194
195 195 Check in a file using SVN::
196 196
197 197 from pexpect import *
198 198 run ("svn ci -m 'automatic commit' my_file.py")
199 199
200 200 Run a command and capture exit status::
201 201
202 202 from pexpect import *
203 203 (command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
204 204
205 205 Tricky Examples
206 206 ===============
207 207
208 208 The following will run SSH and execute 'ls -l' on the remote machine. The
209 209 password 'secret' will be sent if the '(?i)password' pattern is ever seen::
210 210
211 211 run ("ssh username@machine.example.com 'ls -l'", events={'(?i)password':'secret\\n'})
212 212
213 213 This will start mencoder to rip a video from DVD. This will also display
214 214 progress ticks every 5 seconds as it runs. For example::
215 215
216 216 from pexpect import *
217 217 def print_ticks(d):
218 218 print d['event_count'],
219 219 run ("mencoder dvd://1 -o video.avi -oac copy -ovc copy", events={TIMEOUT:print_ticks}, timeout=5)
220 220
221 221 The 'events' argument should be a dictionary of patterns and responses.
222 222 Whenever one of the patterns is seen in the command out run() will send the
223 223 associated response string. Note that you should put newlines in your
224 224 string if Enter is necessary. The responses may also contain callback
225 225 functions. Any callback is function that takes a dictionary as an argument.
226 226 The dictionary contains all the locals from the run() function, so you can
227 227 access the child spawn object or any other variable defined in run()
228 228 (event_count, child, and extra_args are the most useful). A callback may
229 229 return True to stop the current run process otherwise run() continues until
230 230 the next event. A callback may also return a string which will be sent to
231 231 the child. 'extra_args' is not used by directly run(). It provides a way to
232 232 pass data to a callback function through run() through the locals
233 233 dictionary passed to a callback."""
234 234
235 235 if timeout == -1:
236 236 child = spawn(command, maxread=2000, logfile=logfile, cwd=cwd, env=env,
237 237 encoding=encoding)
238 238 else:
239 239 child = spawn(command, timeout=timeout, maxread=2000, logfile=logfile,
240 240 cwd=cwd, env=env, encoding=encoding)
241 241 if events is not None:
242 242 patterns = events.keys()
243 243 responses = events.values()
244 244 else:
245 245 patterns=None # We assume that EOF or TIMEOUT will save us.
246 246 responses=None
247 247 child_result_list = []
248 248 event_count = 0
249 249 while 1:
250 250 try:
251 251 index = child.expect (patterns)
252 252 if isinstance(child.after, basestring):
253 253 child_result_list.append(child.before + child.after)
254 254 else: # child.after may have been a TIMEOUT or EOF, so don't cat those.
255 255 child_result_list.append(child.before)
256 256 if isinstance(responses[index], basestring):
257 257 child.send(responses[index])
258 258 elif type(responses[index]) is types.FunctionType:
259 259 callback_result = responses[index](locals())
260 260 sys.stdout.flush()
261 261 if isinstance(callback_result, basestring):
262 262 child.send(callback_result)
263 263 elif callback_result:
264 264 break
265 265 else:
266 266 raise TypeError ('The callback must be a string or function type.')
267 267 event_count = event_count + 1
268 268 except TIMEOUT as e:
269 269 child_result_list.append(child.before)
270 270 break
271 271 except EOF as e:
272 272 child_result_list.append(child.before)
273 273 break
274 274 child_result = child._empty_buffer.join(child_result_list)
275 275 if withexitstatus:
276 276 child.close()
277 277 return (child_result, child.exitstatus)
278 278 else:
279 279 return child_result
280 280
281 281 class spawnb(object):
282 282 """Use this class to start and control child applications with a pure-bytes
283 283 interface."""
284 284
285 285 _buffer_type = bytes
286 286 def _cast_buffer_type(self, s):
287 287 return _cast_bytes(s, self.encoding)
288 288 _empty_buffer = b''
289 289 _pty_newline = b'\r\n'
290 290
291 291 # Some code needs this to exist, but it's mainly for the spawn subclass.
292 292 encoding = 'utf-8'
293 293
294 294 def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None,
295 295 logfile=None, cwd=None, env=None):
296 296
297 297 """This is the constructor. The command parameter may be a string that
298 298 includes a command and any arguments to the command. For example::
299 299
300 300 child = pexpect.spawn ('/usr/bin/ftp')
301 301 child = pexpect.spawn ('/usr/bin/ssh user@example.com')
302 302 child = pexpect.spawn ('ls -latr /tmp')
303 303
304 304 You may also construct it with a list of arguments like so::
305 305
306 306 child = pexpect.spawn ('/usr/bin/ftp', [])
307 307 child = pexpect.spawn ('/usr/bin/ssh', ['user@example.com'])
308 308 child = pexpect.spawn ('ls', ['-latr', '/tmp'])
309 309
310 310 After this the child application will be created and will be ready to
311 311 talk to. For normal use, see expect() and send() and sendline().
312 312
313 313 Remember that Pexpect does NOT interpret shell meta characters such as
314 314 redirect, pipe, or wild cards (>, |, or *). This is a common mistake.
315 315 If you want to run a command and pipe it through another command then
316 316 you must also start a shell. For example::
317 317
318 318 child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > log_list.txt"')
319 319 child.expect(pexpect.EOF)
320 320
321 321 The second form of spawn (where you pass a list of arguments) is useful
322 322 in situations where you wish to spawn a command and pass it its own
323 323 argument list. This can make syntax more clear. For example, the
324 324 following is equivalent to the previous example::
325 325
326 326 shell_cmd = 'ls -l | grep LOG > log_list.txt'
327 327 child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])
328 328 child.expect(pexpect.EOF)
329 329
330 330 The maxread attribute sets the read buffer size. This is maximum number
331 331 of bytes that Pexpect will try to read from a TTY at one time. Setting
332 332 the maxread size to 1 will turn off buffering. Setting the maxread
333 333 value higher may help performance in cases where large amounts of
334 334 output are read back from the child. This feature is useful in
335 335 conjunction with searchwindowsize.
336 336
337 337 The searchwindowsize attribute sets the how far back in the incomming
338 338 seach buffer Pexpect will search for pattern matches. Every time
339 339 Pexpect reads some data from the child it will append the data to the
340 340 incomming buffer. The default is to search from the beginning of the
341 341 imcomming buffer each time new data is read from the child. But this is
342 342 very inefficient if you are running a command that generates a large
343 343 amount of data where you want to match The searchwindowsize does not
344 344 effect the size of the incomming data buffer. You will still have
345 345 access to the full buffer after expect() returns.
346 346
347 347 The logfile member turns on or off logging. All input and output will
348 348 be copied to the given file object. Set logfile to None to stop
349 349 logging. This is the default. Set logfile to sys.stdout to echo
350 350 everything to standard output. The logfile is flushed after each write.
351 351
352 352 Example log input and output to a file::
353 353
354 354 child = pexpect.spawn('some_command')
355 355 fout = open('mylog.txt','w')
356 356 child.logfile = fout
357 357
358 358 Example log to stdout::
359 359
360 360 child = pexpect.spawn('some_command')
361 361 child.logfile = sys.stdout
362 362
363 363 The logfile_read and logfile_send members can be used to separately log
364 364 the input from the child and output sent to the child. Sometimes you
365 365 don't want to see everything you write to the child. You only want to
366 366 log what the child sends back. For example::
367 367
368 368 child = pexpect.spawn('some_command')
369 369 child.logfile_read = sys.stdout
370 370
371 371 To separately log output sent to the child use logfile_send::
372 372
373 373 self.logfile_send = fout
374 374
375 375 The delaybeforesend helps overcome a weird behavior that many users
376 376 were experiencing. The typical problem was that a user would expect() a
377 377 "Password:" prompt and then immediately call sendline() to send the
378 378 password. The user would then see that their password was echoed back
379 379 to them. Passwords don't normally echo. The problem is caused by the
380 380 fact that most applications print out the "Password" prompt and then
381 381 turn off stdin echo, but if you send your password before the
382 382 application turned off echo, then you get your password echoed.
383 383 Normally this wouldn't be a problem when interacting with a human at a
384 384 real keyboard. If you introduce a slight delay just before writing then
385 385 this seems to clear up the problem. This was such a common problem for
386 386 many users that I decided that the default pexpect behavior should be
387 387 to sleep just before writing to the child application. 1/20th of a
388 388 second (50 ms) seems to be enough to clear up the problem. You can set
389 389 delaybeforesend to 0 to return to the old behavior. Most Linux machines
390 390 don't like this to be below 0.03. I don't know why.
391 391
392 392 Note that spawn is clever about finding commands on your path.
393 393 It uses the same logic that "which" uses to find executables.
394 394
395 395 If you wish to get the exit status of the child you must call the
396 396 close() method. The exit or signal status of the child will be stored
397 397 in self.exitstatus or self.signalstatus. If the child exited normally
398 398 then exitstatus will store the exit return code and signalstatus will
399 399 be None. If the child was terminated abnormally with a signal then
400 400 signalstatus will store the signal value and exitstatus will be None.
401 401 If you need more detail you can also read the self.status member which
402 402 stores the status returned by os.waitpid. You can interpret this using
403 403 os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. """
404 404
405 405 self.STDIN_FILENO = pty.STDIN_FILENO
406 406 self.STDOUT_FILENO = pty.STDOUT_FILENO
407 407 self.STDERR_FILENO = pty.STDERR_FILENO
408 408 self.stdin = sys.stdin
409 409 self.stdout = sys.stdout
410 410 self.stderr = sys.stderr
411 411
412 412 self.searcher = None
413 413 self.ignorecase = False
414 414 self.before = None
415 415 self.after = None
416 416 self.match = None
417 417 self.match_index = None
418 418 self.terminated = True
419 419 self.exitstatus = None
420 420 self.signalstatus = None
421 421 self.status = None # status returned by os.waitpid
422 422 self.flag_eof = False
423 423 self.pid = None
424 424 self.child_fd = -1 # initially closed
425 425 self.timeout = timeout
426 426 self.delimiter = EOF
427 427 self.logfile = logfile
428 428 self.logfile_read = None # input from child (read_nonblocking)
429 429 self.logfile_send = None # output to send (send, sendline)
430 430 self.maxread = maxread # max bytes to read at one time into buffer
431 431 self.buffer = self._empty_buffer # This is the read buffer. See maxread.
432 432 self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
433 433 # Most Linux machines don't like delaybeforesend to be below 0.03 (30 ms).
434 434 self.delaybeforesend = 0.05 # Sets sleep time used just before sending data to child. Time in seconds.
435 435 self.delayafterclose = 0.1 # Sets delay in close() method to allow kernel time to update process status. Time in seconds.
436 436 self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
437 437 self.softspace = False # File-like object.
438 438 self.name = '<' + repr(self) + '>' # File-like object.
439 439 self.closed = True # File-like object.
440 440 self.cwd = cwd
441 441 self.env = env
442 442 self.__irix_hack = (sys.platform.lower().find('irix')>=0) # This flags if we are running on irix
443 443 # Solaris uses internal __fork_pty(). All others use pty.fork().
444 444 if 'solaris' in sys.platform.lower() or 'sunos5' in sys.platform.lower():
445 445 self.use_native_pty_fork = False
446 446 else:
447 447 self.use_native_pty_fork = True
448 448
449 449
450 450 # allow dummy instances for subclasses that may not use command or args.
451 451 if command is None:
452 452 self.command = None
453 453 self.args = None
454 454 self.name = '<pexpect factory incomplete>'
455 455 else:
456 456 self._spawn (command, args)
457 457
458 458 def __del__(self):
459 459
460 460 """This makes sure that no system resources are left open. Python only
461 461 garbage collects Python objects. OS file descriptors are not Python
462 462 objects, so they must be handled explicitly. If the child file
463 463 descriptor was opened outside of this class (passed to the constructor)
464 464 then this does not close it. """
465 465
466 466 if not self.closed:
467 467 # It is possible for __del__ methods to execute during the
468 468 # teardown of the Python VM itself. Thus self.close() may
469 469 # trigger an exception because os.close may be None.
470 470 # -- Fernando Perez
471 471 try:
472 472 self.close()
473 473 except:
474 474 pass
475 475
476 476 def __str__(self):
477 477
478 478 """This returns a human-readable string that represents the state of
479 479 the object. """
480 480
481 481 s = []
482 482 s.append(repr(self))
483 483 s.append('version: ' + __version__)
484 484 s.append('command: ' + str(self.command))
485 485 s.append('args: ' + str(self.args))
486 486 s.append('searcher: ' + str(self.searcher))
487 487 s.append('buffer (last 100 chars): ' + str(self.buffer)[-100:])
488 488 s.append('before (last 100 chars): ' + str(self.before)[-100:])
489 489 s.append('after: ' + str(self.after))
490 490 s.append('match: ' + str(self.match))
491 491 s.append('match_index: ' + str(self.match_index))
492 492 s.append('exitstatus: ' + str(self.exitstatus))
493 493 s.append('flag_eof: ' + str(self.flag_eof))
494 494 s.append('pid: ' + str(self.pid))
495 495 s.append('child_fd: ' + str(self.child_fd))
496 496 s.append('closed: ' + str(self.closed))
497 497 s.append('timeout: ' + str(self.timeout))
498 498 s.append('delimiter: ' + str(self.delimiter))
499 499 s.append('logfile: ' + str(self.logfile))
500 500 s.append('logfile_read: ' + str(self.logfile_read))
501 501 s.append('logfile_send: ' + str(self.logfile_send))
502 502 s.append('maxread: ' + str(self.maxread))
503 503 s.append('ignorecase: ' + str(self.ignorecase))
504 504 s.append('searchwindowsize: ' + str(self.searchwindowsize))
505 505 s.append('delaybeforesend: ' + str(self.delaybeforesend))
506 506 s.append('delayafterclose: ' + str(self.delayafterclose))
507 507 s.append('delayafterterminate: ' + str(self.delayafterterminate))
508 508 return '\n'.join(s)
509 509
510 510 def _spawn(self,command,args=[]):
511 511
512 512 """This starts the given command in a child process. This does all the
513 513 fork/exec type of stuff for a pty. This is called by __init__. If args
514 514 is empty then command will be parsed (split on spaces) and args will be
515 515 set to parsed arguments. """
516 516
517 517 # The pid and child_fd of this object get set by this method.
518 518 # Note that it is difficult for this method to fail.
519 519 # You cannot detect if the child process cannot start.
520 520 # So the only way you can tell if the child process started
521 521 # or not is to try to read from the file descriptor. If you get
522 522 # EOF immediately then it means that the child is already dead.
523 523 # That may not necessarily be bad because you may haved spawned a child
524 524 # that performs some task; creates no stdout output; and then dies.
525 525
526 526 # If command is an int type then it may represent a file descriptor.
527 527 if type(command) == type(0):
528 528 raise ExceptionPexpect ('Command is an int type. If this is a file descriptor then maybe you want to use fdpexpect.fdspawn which takes an existing file descriptor instead of a command string.')
529 529
530 530 if type (args) != type([]):
531 531 raise TypeError ('The argument, args, must be a list.')
532 532
533 533 if args == []:
534 534 self.args = split_command_line(command)
535 535 self.command = self.args[0]
536 536 else:
537 537 self.args = args[:] # work with a copy
538 538 self.args.insert (0, command)
539 539 self.command = command
540 540
541 541 command_with_path = which(self.command)
542 542 if command_with_path is None:
543 543 raise ExceptionPexpect ('The command was not found or was not executable: %s.' % self.command)
544 544 self.command = command_with_path
545 545 self.args[0] = self.command
546 546
547 547 self.name = '<' + ' '.join (self.args) + '>'
548 548
549 549 assert self.pid is None, 'The pid member should be None.'
550 550 assert self.command is not None, 'The command member should not be None.'
551 551
552 552 if self.use_native_pty_fork:
553 553 try:
554 554 self.pid, self.child_fd = pty.fork()
555 555 except OSError as e:
556 556 raise ExceptionPexpect('Error! pty.fork() failed: ' + str(e))
557 557 else: # Use internal __fork_pty
558 558 self.pid, self.child_fd = self.__fork_pty()
559 559
560 560 if self.pid == 0: # Child
561 561 try:
562 562 self.child_fd = sys.stdout.fileno() # used by setwinsize()
563 563 self.setwinsize(24, 80)
564 564 except:
565 565 # Some platforms do not like setwinsize (Cygwin).
566 566 # This will cause problem when running applications that
567 567 # are very picky about window size.
568 568 # This is a serious limitation, but not a show stopper.
569 569 pass
570 570 # Do not allow child to inherit open file descriptors from parent.
571 571 max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
572 572 for i in range (3, max_fd):
573 573 try:
574 574 os.close (i)
575 575 except OSError:
576 576 pass
577 577
578 578 # I don't know why this works, but ignoring SIGHUP fixes a
579 579 # problem when trying to start a Java daemon with sudo
580 580 # (specifically, Tomcat).
581 581 signal.signal(signal.SIGHUP, signal.SIG_IGN)
582 582
583 583 if self.cwd is not None:
584 584 os.chdir(self.cwd)
585 585 if self.env is None:
586 586 os.execv(self.command, self.args)
587 587 else:
588 588 os.execvpe(self.command, self.args, self.env)
589 589
590 590 # Parent
591 591 self.terminated = False
592 592 self.closed = False
593 593
594 594 def __fork_pty(self):
595 595
596 596 """This implements a substitute for the forkpty system call. This
597 597 should be more portable than the pty.fork() function. Specifically,
598 598 this should work on Solaris.
599 599
600 600 Modified 10.06.05 by Geoff Marshall: Implemented __fork_pty() method to
601 601 resolve the issue with Python's pty.fork() not supporting Solaris,
602 602 particularly ssh. Based on patch to posixmodule.c authored by Noah
603 603 Spurrier::
604 604
605 605 http://mail.python.org/pipermail/python-dev/2003-May/035281.html
606 606
607 607 """
608 608
609 609 parent_fd, child_fd = os.openpty()
610 610 if parent_fd < 0 or child_fd < 0:
611 611 raise ExceptionPexpect("Error! Could not open pty with os.openpty().")
612 612
613 613 pid = os.fork()
614 614 if pid < 0:
615 615 raise ExceptionPexpect("Error! Failed os.fork().")
616 616 elif pid == 0:
617 617 # Child.
618 618 os.close(parent_fd)
619 619 self.__pty_make_controlling_tty(child_fd)
620 620
621 621 os.dup2(child_fd, 0)
622 622 os.dup2(child_fd, 1)
623 623 os.dup2(child_fd, 2)
624 624
625 625 if child_fd > 2:
626 626 os.close(child_fd)
627 627 else:
628 628 # Parent.
629 629 os.close(child_fd)
630 630
631 631 return pid, parent_fd
632 632
633 633 def __pty_make_controlling_tty(self, tty_fd):
634 634
635 635 """This makes the pseudo-terminal the controlling tty. This should be
636 636 more portable than the pty.fork() function. Specifically, this should
637 637 work on Solaris. """
638 638
639 639 child_name = os.ttyname(tty_fd)
640 640
641 641 # Disconnect from controlling tty. Harmless if not already connected.
642 642 try:
643 643 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
644 644 if fd >= 0:
645 645 os.close(fd)
646 646 except:
647 647 # Already disconnected. This happens if running inside cron.
648 648 pass
649 649
650 650 os.setsid()
651 651
652 652 # Verify we are disconnected from controlling tty
653 653 # by attempting to open it again.
654 654 try:
655 655 fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY);
656 656 if fd >= 0:
657 657 os.close(fd)
658 658 raise ExceptionPexpect("Error! Failed to disconnect from controlling tty. It is still possible to open /dev/tty.")
659 659 except:
660 660 # Good! We are disconnected from a controlling tty.
661 661 pass
662 662
663 663 # Verify we can open child pty.
664 664 fd = os.open(child_name, os.O_RDWR);
665 665 if fd < 0:
666 666 raise ExceptionPexpect("Error! Could not open child pty, " + child_name)
667 667 else:
668 668 os.close(fd)
669 669
670 670 # Verify we now have a controlling tty.
671 671 fd = os.open("/dev/tty", os.O_WRONLY)
672 672 if fd < 0:
673 673 raise ExceptionPexpect("Error! Could not open controlling tty, /dev/tty")
674 674 else:
675 675 os.close(fd)
676 676
677 677 def fileno (self): # File-like object.
678 678
679 679 """This returns the file descriptor of the pty for the child.
680 680 """
681 681
682 682 return self.child_fd
683 683
684 684 def close (self, force=True): # File-like object.
685 685
686 686 """This closes the connection with the child application. Note that
687 687 calling close() more than once is valid. This emulates standard Python
688 688 behavior with files. Set force to True if you want to make sure that
689 689 the child is terminated (SIGKILL is sent if the child ignores SIGHUP
690 690 and SIGINT). """
691 691
692 692 if not self.closed:
693 693 self.flush()
694 694 os.close (self.child_fd)
695 695 time.sleep(self.delayafterclose) # Give kernel time to update process status.
696 696 if self.isalive():
697 697 if not self.terminate(force):
698 698 raise ExceptionPexpect ('close() could not terminate the child using terminate()')
699 699 self.child_fd = -1
700 700 self.closed = True
701 701 #self.pid = None
702 702
703 703 def flush (self): # File-like object.
704 704
705 705 """This does nothing. It is here to support the interface for a
706 706 File-like object. """
707 707
708 708 pass
709 709
710 710 def isatty (self): # File-like object.
711 711
712 712 """This returns True if the file descriptor is open and connected to a
713 713 tty(-like) device, else False. """
714 714
715 715 return os.isatty(self.child_fd)
716 716
717 717 def waitnoecho (self, timeout=-1):
718 718
719 719 """This waits until the terminal ECHO flag is set False. This returns
720 720 True if the echo mode is off. This returns False if the ECHO flag was
721 721 not set False before the timeout. This can be used to detect when the
722 722 child is waiting for a password. Usually a child application will turn
723 723 off echo mode when it is waiting for the user to enter a password. For
724 724 example, instead of expecting the "password:" prompt you can wait for
725 725 the child to set ECHO off::
726 726
727 727 p = pexpect.spawn ('ssh user@example.com')
728 728 p.waitnoecho()
729 729 p.sendline(mypassword)
730 730
731 731 If timeout==-1 then this method will use the value in self.timeout.
732 732 If timeout==None then this method to block until ECHO flag is False.
733 733 """
734 734
735 735 if timeout == -1:
736 736 timeout = self.timeout
737 737 if timeout is not None:
738 738 end_time = time.time() + timeout
739 739 while True:
740 740 if not self.getecho():
741 741 return True
742 742 if timeout < 0 and timeout is not None:
743 743 return False
744 744 if timeout is not None:
745 745 timeout = end_time - time.time()
746 746 time.sleep(0.1)
747 747
748 748 def getecho (self):
749 749
750 750 """This returns the terminal echo mode. This returns True if echo is
751 751 on or False if echo is off. Child applications that are expecting you
752 752 to enter a password often set ECHO False. See waitnoecho(). """
753 753
754 754 attr = termios.tcgetattr(self.child_fd)
755 755 if attr[3] & termios.ECHO:
756 756 return True
757 757 return False
758 758
759 759 def setecho (self, state):
760 760
761 761 """This sets the terminal echo mode on or off. Note that anything the
762 762 child sent before the echo will be lost, so you should be sure that
763 763 your input buffer is empty before you call setecho(). For example, the
764 764 following will work as expected::
765 765
766 766 p = pexpect.spawn('cat')
767 767 p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
768 768 p.expect (['1234'])
769 769 p.expect (['1234'])
770 770 p.setecho(False) # Turn off tty echo
771 771 p.sendline ('abcd') # We will set this only once (echoed by cat).
772 772 p.sendline ('wxyz') # We will set this only once (echoed by cat)
773 773 p.expect (['abcd'])
774 774 p.expect (['wxyz'])
775 775
776 776 The following WILL NOT WORK because the lines sent before the setecho
777 777 will be lost::
778 778
779 779 p = pexpect.spawn('cat')
780 780 p.sendline ('1234') # We will see this twice (once from tty echo and again from cat).
781 781 p.setecho(False) # Turn off tty echo
782 782 p.sendline ('abcd') # We will set this only once (echoed by cat).
783 783 p.sendline ('wxyz') # We will set this only once (echoed by cat)
784 784 p.expect (['1234'])
785 785 p.expect (['1234'])
786 786 p.expect (['abcd'])
787 787 p.expect (['wxyz'])
788 788 """
789 789
790 790 self.child_fd
791 791 attr = termios.tcgetattr(self.child_fd)
792 792 if state:
793 793 attr[3] = attr[3] | termios.ECHO
794 794 else:
795 795 attr[3] = attr[3] & ~termios.ECHO
796 796 # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent
797 797 # and blocked on some platforms. TCSADRAIN is probably ideal if it worked.
798 798 termios.tcsetattr(self.child_fd, termios.TCSANOW, attr)
799 799
800 800 def read_nonblocking (self, size = 1, timeout = -1):
801 801
802 802 """This reads at most size bytes from the child application. It
803 803 includes a timeout. If the read does not complete within the timeout
804 804 period then a TIMEOUT exception is raised. If the end of file is read
805 805 then an EOF exception will be raised. If a log file was set using
806 806 setlog() then all data will also be written to the log file.
807 807
808 808 If timeout is None then the read may block indefinitely. If timeout is -1
809 809 then the self.timeout value is used. If timeout is 0 then the child is
810 810 polled and if there was no data immediately ready then this will raise
811 811 a TIMEOUT exception.
812 812
813 813 The timeout refers only to the amount of time to read at least one
814 814 character. This is not effected by the 'size' parameter, so if you call
815 815 read_nonblocking(size=100, timeout=30) and only one character is
816 816 available right away then one character will be returned immediately.
817 817 It will not wait for 30 seconds for another 99 characters to come in.
818 818
819 819 This is a wrapper around os.read(). It uses select.select() to
820 820 implement the timeout. """
821 821
822 822 if self.closed:
823 823 raise ValueError ('I/O operation on closed file in read_nonblocking().')
824 824
825 825 if timeout == -1:
826 826 timeout = self.timeout
827 827
828 828 # Note that some systems such as Solaris do not give an EOF when
829 829 # the child dies. In fact, you can still try to read
830 830 # from the child_fd -- it will block forever or until TIMEOUT.
831 831 # For this case, I test isalive() before doing any reading.
832 832 # If isalive() is false, then I pretend that this is the same as EOF.
833 833 if not self.isalive():
834 834 r,w,e = self.__select([self.child_fd], [], [], 0) # timeout of 0 means "poll"
835 835 if not r:
836 836 self.flag_eof = True
837 837 raise EOF ('End Of File (EOF) in read_nonblocking(). Braindead platform.')
838 838 elif self.__irix_hack:
839 839 # This is a hack for Irix. It seems that Irix requires a long delay before checking isalive.
840 840 # This adds a 2 second delay, but only when the child is terminated.
841 841 r, w, e = self.__select([self.child_fd], [], [], 2)
842 842 if not r and not self.isalive():
843 843 self.flag_eof = True
844 844 raise EOF ('End Of File (EOF) in read_nonblocking(). Pokey platform.')
845 845
846 846 r,w,e = self.__select([self.child_fd], [], [], timeout)
847 847
848 848 if not r:
849 849 if not self.isalive():
850 850 # Some platforms, such as Irix, will claim that their processes are alive;
851 851 # then timeout on the select; and then finally admit that they are not alive.
852 852 self.flag_eof = True
853 853 raise EOF ('End of File (EOF) in read_nonblocking(). Very pokey platform.')
854 854 else:
855 855 raise TIMEOUT ('Timeout exceeded in read_nonblocking().')
856 856
857 857 if self.child_fd in r:
858 858 try:
859 859 s = os.read(self.child_fd, size)
860 860 except OSError as e: # Linux does this
861 861 self.flag_eof = True
862 862 raise EOF ('End Of File (EOF) in read_nonblocking(). Exception style platform.')
863 863 if s == b'': # BSD style
864 864 self.flag_eof = True
865 865 raise EOF ('End Of File (EOF) in read_nonblocking(). Empty string style platform.')
866 866
867 867 s2 = self._cast_buffer_type(s)
868 868 if self.logfile is not None:
869 869 self.logfile.write(s2)
870 870 self.logfile.flush()
871 871 if self.logfile_read is not None:
872 872 self.logfile_read.write(s2)
873 873 self.logfile_read.flush()
874 874
875 875 return s
876 876
877 877 raise ExceptionPexpect ('Reached an unexpected state in read_nonblocking().')
878 878
879 879 def read (self, size = -1): # File-like object.
880 880 """This reads at most "size" bytes from the file (less if the read hits
881 881 EOF before obtaining size bytes). If the size argument is negative or
882 882 omitted, read all data until EOF is reached. The bytes are returned as
883 883 a string object. An empty string is returned when EOF is encountered
884 884 immediately. """
885 885
886 886 if size == 0:
887 887 return self._empty_buffer
888 888 if size < 0:
889 889 self.expect (self.delimiter) # delimiter default is EOF
890 890 return self.before
891 891
892 892 # I could have done this more directly by not using expect(), but
893 893 # I deliberately decided to couple read() to expect() so that
894 894 # I would catch any bugs early and ensure consistant behavior.
895 895 # It's a little less efficient, but there is less for me to
896 896 # worry about if I have to later modify read() or expect().
897 897 # Note, it's OK if size==-1 in the regex. That just means it
898 898 # will never match anything in which case we stop only on EOF.
899 899 if self._buffer_type is bytes:
900 900 pat = (u'.{%d}' % size).encode('ascii')
901 901 else:
902 902 pat = u'.{%d}' % size
903 903 cre = re.compile(pat, re.DOTALL)
904 904 index = self.expect ([cre, self.delimiter]) # delimiter default is EOF
905 905 if index == 0:
906 906 return self.after ### self.before should be ''. Should I assert this?
907 907 return self.before
908 908
909 909 def readline(self, size = -1):
910 910 """This reads and returns one entire line. A trailing newline is kept
911 911 in the string, but may be absent when a file ends with an incomplete
912 912 line. Note: This readline() looks for a \\r\\n pair even on UNIX
913 913 because this is what the pseudo tty device returns. So contrary to what
914 914 you may expect you will receive the newline as \\r\\n. An empty string
915 915 is returned when EOF is hit immediately. Currently, the size argument is
916 916 mostly ignored, so this behavior is not standard for a file-like
917 917 object. If size is 0 then an empty string is returned. """
918 918
919 919 if size == 0:
920 920 return self._empty_buffer
921 921 index = self.expect ([self._pty_newline, self.delimiter]) # delimiter default is EOF
922 922 if index == 0:
923 923 return self.before + self._pty_newline
924 924 return self.before
925 925
926 926 def __iter__ (self): # File-like object.
927 927
928 928 """This is to support iterators over a file-like object.
929 929 """
930 930
931 931 return self
932 932
933 933 def __next__ (self): # File-like object.
934 934
935 935 """This is to support iterators over a file-like object.
936 936 """
937 937
938 938 result = self.readline()
939 939 if result == self._empty_buffer:
940 940 raise StopIteration
941 941 return result
942 942
943 943 if not PY3:
944 944 next = __next__ # File-like object.
945 945
946 946 def readlines (self, sizehint = -1): # File-like object.
947 947
948 948 """This reads until EOF using readline() and returns a list containing
949 949 the lines thus read. The optional "sizehint" argument is ignored. """
950 950
951 951 lines = []
952 952 while True:
953 953 line = self.readline()
954 954 if not line:
955 955 break
956 956 lines.append(line)
957 957 return lines
958 958
959 959 def write(self, s): # File-like object.
960 960
961 961 """This is similar to send() except that there is no return value.
962 962 """
963 963
964 964 self.send (s)
965 965
966 966 def writelines (self, sequence): # File-like object.
967 967
968 968 """This calls write() for each element in the sequence. The sequence
969 969 can be any iterable object producing strings, typically a list of
970 970 strings. This does not add line separators There is no return value.
971 971 """
972 972
973 973 for s in sequence:
974 974 self.write (s)
975 975
976 976 def send(self, s):
977 977
978 978 """This sends a string to the child process. This returns the number of
979 979 bytes written. If a log file was set then the data is also written to
980 980 the log. """
981 981
982 982 time.sleep(self.delaybeforesend)
983 983
984 984 s2 = self._cast_buffer_type(s)
985 985 if self.logfile is not None:
986 986 self.logfile.write(s2)
987 987 self.logfile.flush()
988 988 if self.logfile_send is not None:
989 989 self.logfile_send.write(s2)
990 990 self.logfile_send.flush()
991 991 c = os.write (self.child_fd, _cast_bytes(s, self.encoding))
992 992 return c
993 993
994 994 def sendline(self, s=''):
995 995
996 996 """This is like send(), but it adds a line feed (os.linesep). This
997 997 returns the number of bytes written. """
998 998
999 999 n = self.send (s)
1000 1000 n = n + self.send (os.linesep)
1001 1001 return n
1002 1002
1003 1003 def sendcontrol(self, char):
1004 1004
1005 1005 """This sends a control character to the child such as Ctrl-C or
1006 1006 Ctrl-D. For example, to send a Ctrl-G (ASCII 7)::
1007 1007
1008 1008 child.sendcontrol('g')
1009 1009
1010 1010 See also, sendintr() and sendeof().
1011 1011 """
1012 1012
1013 1013 char = char.lower()
1014 1014 a = ord(char)
1015 1015 if a>=97 and a<=122:
1016 1016 a = a - ord('a') + 1
1017 1017 return self.send (chr(a))
1018 1018 d = {'@':0, '`':0,
1019 1019 '[':27, '{':27,
1020 1020 '\\':28, '|':28,
1021 1021 ']':29, '}': 29,
1022 1022 '^':30, '~':30,
1023 1023 '_':31,
1024 1024 '?':127}
1025 1025 if char not in d:
1026 1026 return 0
1027 1027 return self.send (chr(d[char]))
1028 1028
1029 1029 def sendeof(self):
1030 1030
1031 1031 """This sends an EOF to the child. This sends a character which causes
1032 1032 the pending parent output buffer to be sent to the waiting child
1033 1033 program without waiting for end-of-line. If it is the first character
1034 1034 of the line, the read() in the user program returns 0, which signifies
1035 1035 end-of-file. This means to work as expected a sendeof() has to be
1036 1036 called at the beginning of a line. This method does not send a newline.
1037 1037 It is the responsibility of the caller to ensure the eof is sent at the
1038 1038 beginning of a line. """
1039 1039
1040 1040 ### Hmmm... how do I send an EOF?
1041 1041 ###C if ((m = write(pty, *buf, p - *buf)) < 0)
1042 1042 ###C return (errno == EWOULDBLOCK) ? n : -1;
1043 1043 #fd = sys.stdin.fileno()
1044 1044 #old = termios.tcgetattr(fd) # remember current state
1045 1045 #attr = termios.tcgetattr(fd)
1046 1046 #attr[3] = attr[3] | termios.ICANON # ICANON must be set to recognize EOF
1047 1047 #try: # use try/finally to ensure state gets restored
1048 1048 # termios.tcsetattr(fd, termios.TCSADRAIN, attr)
1049 1049 # if hasattr(termios, 'CEOF'):
1050 1050 # os.write (self.child_fd, '%c' % termios.CEOF)
1051 1051 # else:
1052 1052 # # Silly platform does not define CEOF so assume CTRL-D
1053 1053 # os.write (self.child_fd, '%c' % 4)
1054 1054 #finally: # restore state
1055 1055 # termios.tcsetattr(fd, termios.TCSADRAIN, old)
1056 1056 if hasattr(termios, 'VEOF'):
1057 1057 char = termios.tcgetattr(self.child_fd)[6][termios.VEOF]
1058 1058 else:
1059 1059 # platform does not define VEOF so assume CTRL-D
1060 1060 char = chr(4)
1061 1061 self.send(char)
1062 1062
1063 1063 def sendintr(self):
1064 1064
1065 1065 """This sends a SIGINT to the child. It does not require
1066 1066 the SIGINT to be the first character on a line. """
1067 1067
1068 1068 if hasattr(termios, 'VINTR'):
1069 1069 char = termios.tcgetattr(self.child_fd)[6][termios.VINTR]
1070 1070 else:
1071 1071 # platform does not define VINTR so assume CTRL-C
1072 1072 char = chr(3)
1073 1073 self.send (char)
1074 1074
1075 1075 def eof (self):
1076 1076
1077 1077 """This returns True if the EOF exception was ever raised.
1078 1078 """
1079 1079
1080 1080 return self.flag_eof
1081 1081
1082 1082 def terminate(self, force=False):
1083 1083
1084 1084 """This forces a child process to terminate. It starts nicely with
1085 1085 SIGHUP and SIGINT. If "force" is True then moves onto SIGKILL. This
1086 1086 returns True if the child was terminated. This returns False if the
1087 1087 child could not be terminated. """
1088 1088
1089 1089 if not self.isalive():
1090 1090 return True
1091 1091 try:
1092 1092 self.kill(signal.SIGHUP)
1093 1093 time.sleep(self.delayafterterminate)
1094 1094 if not self.isalive():
1095 1095 return True
1096 1096 self.kill(signal.SIGCONT)
1097 1097 time.sleep(self.delayafterterminate)
1098 1098 if not self.isalive():
1099 1099 return True
1100 1100 self.kill(signal.SIGINT)
1101 1101 time.sleep(self.delayafterterminate)
1102 1102 if not self.isalive():
1103 1103 return True
1104 1104 if force:
1105 1105 self.kill(signal.SIGKILL)
1106 1106 time.sleep(self.delayafterterminate)
1107 1107 if not self.isalive():
1108 1108 return True
1109 1109 else:
1110 1110 return False
1111 1111 return False
1112 1112 except OSError as e:
1113 1113 # I think there are kernel timing issues that sometimes cause
1114 1114 # this to happen. I think isalive() reports True, but the
1115 1115 # process is dead to the kernel.
1116 1116 # Make one last attempt to see if the kernel is up to date.
1117 1117 time.sleep(self.delayafterterminate)
1118 1118 if not self.isalive():
1119 1119 return True
1120 1120 else:
1121 1121 return False
1122 1122
1123 1123 def wait(self):
1124 1124
1125 1125 """This waits until the child exits. This is a blocking call. This will
1126 1126 not read any data from the child, so this will block forever if the
1127 1127 child has unread output and has terminated. In other words, the child
1128 1128 may have printed output then called exit(); but, technically, the child
1129 1129 is still alive until its output is read. """
1130 1130
1131 1131 if self.isalive():
1132 1132 pid, status = os.waitpid(self.pid, 0)
1133 1133 else:
1134 1134 raise ExceptionPexpect ('Cannot wait for dead child process.')
1135 1135 self.exitstatus = os.WEXITSTATUS(status)
1136 1136 if os.WIFEXITED (status):
1137 1137 self.status = status
1138 1138 self.exitstatus = os.WEXITSTATUS(status)
1139 1139 self.signalstatus = None
1140 1140 self.terminated = True
1141 1141 elif os.WIFSIGNALED (status):
1142 1142 self.status = status
1143 1143 self.exitstatus = None
1144 1144 self.signalstatus = os.WTERMSIG(status)
1145 1145 self.terminated = True
1146 1146 elif os.WIFSTOPPED (status):
1147 1147 raise ExceptionPexpect ('Wait was called for a child process that is stopped. This is not supported. Is some other process attempting job control with our child pid?')
1148 1148 return self.exitstatus
1149 1149
1150 1150 def isalive(self):
1151 1151
1152 1152 """This tests if the child process is running or not. This is
1153 1153 non-blocking. If the child was terminated then this will read the
1154 1154 exitstatus or signalstatus of the child. This returns True if the child
1155 1155 process appears to be running or False if not. It can take literally
1156 1156 SECONDS for Solaris to return the right status. """
1157 1157
1158 1158 if self.terminated:
1159 1159 return False
1160 1160
1161 1161 if self.flag_eof:
1162 1162 # This is for Linux, which requires the blocking form of waitpid to get
1163 1163 # status of a defunct process. This is super-lame. The flag_eof would have
1164 1164 # been set in read_nonblocking(), so this should be safe.
1165 1165 waitpid_options = 0
1166 1166 else:
1167 1167 waitpid_options = os.WNOHANG
1168 1168
1169 1169 try:
1170 1170 pid, status = os.waitpid(self.pid, waitpid_options)
1171 1171 except OSError as e: # No child processes
1172 1172 if e.errno == errno.ECHILD:
1173 1173 raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?')
1174 1174 else:
1175 1175 raise e
1176 1176
1177 1177 # I have to do this twice for Solaris. I can't even believe that I figured this out...
1178 1178 # If waitpid() returns 0 it means that no child process wishes to
1179 1179 # report, and the value of status is undefined.
1180 1180 if pid == 0:
1181 1181 try:
1182 1182 pid, status = os.waitpid(self.pid, waitpid_options) ### os.WNOHANG) # Solaris!
1183 1183 except OSError as e: # This should never happen...
1184 1184 if e[0] == errno.ECHILD:
1185 1185 raise ExceptionPexpect ('isalive() encountered condition that should never happen. There was no child process. Did someone else call waitpid() on our process?')
1186 1186 else:
1187 1187 raise e
1188 1188
1189 1189 # If pid is still 0 after two calls to waitpid() then
1190 1190 # the process really is alive. This seems to work on all platforms, except
1191 1191 # for Irix which seems to require a blocking call on waitpid or select, so I let read_nonblocking
1192 1192 # take care of this situation (unfortunately, this requires waiting through the timeout).
1193 1193 if pid == 0:
1194 1194 return True
1195 1195
1196 1196 if pid == 0:
1197 1197 return True
1198 1198
1199 1199 if os.WIFEXITED (status):
1200 1200 self.status = status
1201 1201 self.exitstatus = os.WEXITSTATUS(status)
1202 1202 self.signalstatus = None
1203 1203 self.terminated = True
1204 1204 elif os.WIFSIGNALED (status):
1205 1205 self.status = status
1206 1206 self.exitstatus = None
1207 1207 self.signalstatus = os.WTERMSIG(status)
1208 1208 self.terminated = True
1209 1209 elif os.WIFSTOPPED (status):
1210 1210 raise ExceptionPexpect ('isalive() encountered condition where child process is stopped. This is not supported. Is some other process attempting job control with our child pid?')
1211 1211 return False
1212 1212
1213 1213 def kill(self, sig):
1214 1214
1215 1215 """This sends the given signal to the child application. In keeping
1216 1216 with UNIX tradition it has a misleading name. It does not necessarily
1217 1217 kill the child unless you send the right signal. """
1218 1218
1219 1219 # Same as os.kill, but the pid is given for you.
1220 1220 if self.isalive():
1221 1221 os.kill(self.pid, sig)
1222 1222
1223 1223 def compile_pattern_list(self, patterns):
1224 1224
1225 1225 """This compiles a pattern-string or a list of pattern-strings.
1226 1226 Patterns must be a StringType, EOF, TIMEOUT, SRE_Pattern, or a list of
1227 1227 those. Patterns may also be None which results in an empty list (you
1228 1228 might do this if waiting for an EOF or TIMEOUT condition without
1229 1229 expecting any pattern).
1230 1230
1231 1231 This is used by expect() when calling expect_list(). Thus expect() is
1232 1232 nothing more than::
1233 1233
1234 1234 cpl = self.compile_pattern_list(pl)
1235 1235 return self.expect_list(cpl, timeout)
1236 1236
1237 1237 If you are using expect() within a loop it may be more
1238 1238 efficient to compile the patterns first and then call expect_list().
1239 1239 This avoid calls in a loop to compile_pattern_list()::
1240 1240
1241 1241 cpl = self.compile_pattern_list(my_pattern)
1242 1242 while some_condition:
1243 1243 ...
1244 1244 i = self.expect_list(clp, timeout)
1245 1245 ...
1246 1246 """
1247 1247
1248 1248 if patterns is None:
1249 1249 return []
1250 1250 if not isinstance(patterns, list):
1251 1251 patterns = [patterns]
1252 1252
1253 1253 compile_flags = re.DOTALL # Allow dot to match \n
1254 1254 if self.ignorecase:
1255 1255 compile_flags = compile_flags | re.IGNORECASE
1256 1256 compiled_pattern_list = []
1257 1257 for p in patterns:
1258 1258 if isinstance(p, (bytes, unicode)):
1259 1259 p = self._cast_buffer_type(p)
1260 1260 compiled_pattern_list.append(re.compile(p, compile_flags))
1261 1261 elif p is EOF:
1262 1262 compiled_pattern_list.append(EOF)
1263 1263 elif p is TIMEOUT:
1264 1264 compiled_pattern_list.append(TIMEOUT)
1265 1265 elif type(p) is re_type:
1266 1266 p = self._prepare_regex_pattern(p)
1267 1267 compiled_pattern_list.append(p)
1268 1268 else:
1269 1269 raise TypeError ('Argument must be one of StringTypes, EOF, TIMEOUT, SRE_Pattern, or a list of those type. %s' % str(type(p)))
1270 1270
1271 1271 return compiled_pattern_list
1272 1272
1273 1273 def _prepare_regex_pattern(self, p):
1274 1274 "Recompile unicode regexes as bytes regexes. Overridden in subclass."
1275 1275 if isinstance(p.pattern, unicode):
1276 1276 p = re.compile(p.pattern.encode('utf-8'), p.flags &~ re.UNICODE)
1277 1277 return p
1278 1278
1279 1279 def expect(self, pattern, timeout = -1, searchwindowsize=-1):
1280 1280
1281 1281 """This seeks through the stream until a pattern is matched. The
1282 1282 pattern is overloaded and may take several types. The pattern can be a
1283 1283 StringType, EOF, a compiled re, or a list of any of those types.
1284 1284 Strings will be compiled to re types. This returns the index into the
1285 1285 pattern list. If the pattern was not a list this returns index 0 on a
1286 1286 successful match. This may raise exceptions for EOF or TIMEOUT. To
1287 1287 avoid the EOF or TIMEOUT exceptions add EOF or TIMEOUT to the pattern
1288 1288 list. That will cause expect to match an EOF or TIMEOUT condition
1289 1289 instead of raising an exception.
1290 1290
1291 1291 If you pass a list of patterns and more than one matches, the first match
1292 1292 in the stream is chosen. If more than one pattern matches at that point,
1293 1293 the leftmost in the pattern list is chosen. For example::
1294 1294
1295 1295 # the input is 'foobar'
1296 1296 index = p.expect (['bar', 'foo', 'foobar'])
1297 1297 # returns 1 ('foo') even though 'foobar' is a "better" match
1298 1298
1299 1299 Please note, however, that buffering can affect this behavior, since
1300 1300 input arrives in unpredictable chunks. For example::
1301 1301
1302 1302 # the input is 'foobar'
1303 1303 index = p.expect (['foobar', 'foo'])
1304 1304 # returns 0 ('foobar') if all input is available at once,
1305 1305 # but returs 1 ('foo') if parts of the final 'bar' arrive late
1306 1306
1307 1307 After a match is found the instance attributes 'before', 'after' and
1308 1308 'match' will be set. You can see all the data read before the match in
1309 1309 'before'. You can see the data that was matched in 'after'. The
1310 1310 re.MatchObject used in the re match will be in 'match'. If an error
1311 1311 occurred then 'before' will be set to all the data read so far and
1312 1312 'after' and 'match' will be None.
1313 1313
1314 1314 If timeout is -1 then timeout will be set to the self.timeout value.
1315 1315
1316 1316 A list entry may be EOF or TIMEOUT instead of a string. This will
1317 1317 catch these exceptions and return the index of the list entry instead
1318 1318 of raising the exception. The attribute 'after' will be set to the
1319 1319 exception type. The attribute 'match' will be None. This allows you to
1320 1320 write code like this::
1321 1321
1322 1322 index = p.expect (['good', 'bad', pexpect.EOF, pexpect.TIMEOUT])
1323 1323 if index == 0:
1324 1324 do_something()
1325 1325 elif index == 1:
1326 1326 do_something_else()
1327 1327 elif index == 2:
1328 1328 do_some_other_thing()
1329 1329 elif index == 3:
1330 1330 do_something_completely_different()
1331 1331
1332 1332 instead of code like this::
1333 1333
1334 1334 try:
1335 1335 index = p.expect (['good', 'bad'])
1336 1336 if index == 0:
1337 1337 do_something()
1338 1338 elif index == 1:
1339 1339 do_something_else()
1340 1340 except EOF:
1341 1341 do_some_other_thing()
1342 1342 except TIMEOUT:
1343 1343 do_something_completely_different()
1344 1344
1345 1345 These two forms are equivalent. It all depends on what you want. You
1346 1346 can also just expect the EOF if you are waiting for all output of a
1347 1347 child to finish. For example::
1348 1348
1349 1349 p = pexpect.spawn('/bin/ls')
1350 1350 p.expect (pexpect.EOF)
1351 1351 print p.before
1352 1352
1353 1353 If you are trying to optimize for speed then see expect_list().
1354 1354 """
1355 1355
1356 1356 compiled_pattern_list = self.compile_pattern_list(pattern)
1357 1357 return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
1358 1358
1359 1359 def expect_list(self, pattern_list, timeout = -1, searchwindowsize = -1):
1360 1360
1361 1361 """This takes a list of compiled regular expressions and returns the
1362 1362 index into the pattern_list that matched the child output. The list may
1363 1363 also contain EOF or TIMEOUT (which are not compiled regular
1364 1364 expressions). This method is similar to the expect() method except that
1365 1365 expect_list() does not recompile the pattern list on every call. This
1366 1366 may help if you are trying to optimize for speed, otherwise just use
1367 1367 the expect() method. This is called by expect(). If timeout==-1 then
1368 1368 the self.timeout value is used. If searchwindowsize==-1 then the
1369 1369 self.searchwindowsize value is used. """
1370 1370
1371 1371 return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
1372 1372
1373 1373 def expect_exact(self, pattern_list, timeout = -1, searchwindowsize = -1):
1374 1374
1375 1375 """This is similar to expect(), but uses plain string matching instead
1376 1376 of compiled regular expressions in 'pattern_list'. The 'pattern_list'
1377 1377 may be a string; a list or other sequence of strings; or TIMEOUT and
1378 1378 EOF.
1379 1379
1380 1380 This call might be faster than expect() for two reasons: string
1381 1381 searching is faster than RE matching and it is possible to limit the
1382 1382 search to just the end of the input buffer.
1383 1383
1384 1384 This method is also useful when you don't want to have to worry about
1385 1385 escaping regular expression characters that you want to match."""
1386 1386
1387 1387 if isinstance(pattern_list, (bytes, unicode)) or pattern_list in (TIMEOUT, EOF):
1388 1388 pattern_list = [pattern_list]
1389 1389 return self.expect_loop(searcher_string(pattern_list), timeout, searchwindowsize)
1390 1390
1391 1391 def expect_loop(self, searcher, timeout = -1, searchwindowsize = -1):
1392 1392
1393 1393 """This is the common loop used inside expect. The 'searcher' should be
1394 1394 an instance of searcher_re or searcher_string, which describes how and what
1395 1395 to search for in the input.
1396 1396
1397 1397 See expect() for other arguments, return value and exceptions. """
1398 1398
1399 1399 self.searcher = searcher
1400 1400
1401 1401 if timeout == -1:
1402 1402 timeout = self.timeout
1403 1403 if timeout is not None:
1404 1404 end_time = time.time() + timeout
1405 1405 if searchwindowsize == -1:
1406 1406 searchwindowsize = self.searchwindowsize
1407 1407
1408 1408 try:
1409 1409 incoming = self.buffer
1410 1410 freshlen = len(incoming)
1411 1411 while True: # Keep reading until exception or return.
1412 1412 index = searcher.search(incoming, freshlen, searchwindowsize)
1413 1413 if index >= 0:
1414 1414 self.buffer = incoming[searcher.end : ]
1415 1415 self.before = incoming[ : searcher.start]
1416 1416 self.after = incoming[searcher.start : searcher.end]
1417 1417 self.match = searcher.match
1418 1418 self.match_index = index
1419 1419 return self.match_index
1420 1420 # No match at this point
1421 1421 if timeout is not None and timeout < 0:
1422 1422 raise TIMEOUT ('Timeout exceeded in expect_any().')
1423 1423 # Still have time left, so read more data
1424 1424 c = self.read_nonblocking (self.maxread, timeout)
1425 1425 freshlen = len(c)
1426 1426 time.sleep (0.0001)
1427 1427 incoming = incoming + c
1428 1428 if timeout is not None:
1429 1429 timeout = end_time - time.time()
1430 1430 except EOF as e:
1431 1431 self.buffer = self._empty_buffer
1432 1432 self.before = incoming
1433 1433 self.after = EOF
1434 1434 index = searcher.eof_index
1435 1435 if index >= 0:
1436 1436 self.match = EOF
1437 1437 self.match_index = index
1438 1438 return self.match_index
1439 1439 else:
1440 1440 self.match = None
1441 1441 self.match_index = None
1442 1442 raise EOF (str(e) + '\n' + str(self))
1443 1443 except TIMEOUT as e:
1444 1444 self.buffer = incoming
1445 1445 self.before = incoming
1446 1446 self.after = TIMEOUT
1447 1447 index = searcher.timeout_index
1448 1448 if index >= 0:
1449 1449 self.match = TIMEOUT
1450 1450 self.match_index = index
1451 1451 return self.match_index
1452 1452 else:
1453 1453 self.match = None
1454 1454 self.match_index = None
1455 1455 raise TIMEOUT (str(e) + '\n' + str(self))
1456 1456 except:
1457 1457 self.before = incoming
1458 1458 self.after = None
1459 1459 self.match = None
1460 1460 self.match_index = None
1461 1461 raise
1462 1462
1463 1463 def getwinsize(self):
1464 1464
1465 1465 """This returns the terminal window size of the child tty. The return
1466 1466 value is a tuple of (rows, cols). """
1467 1467
1468 1468 TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912L)
1469 1469 s = struct.pack('HHHH', 0, 0, 0, 0)
1470 1470 x = fcntl.ioctl(self.fileno(), TIOCGWINSZ, s)
1471 1471 return struct.unpack('HHHH', x)[0:2]
1472 1472
1473 1473 def setwinsize(self, r, c):
1474 1474
1475 1475 """This sets the terminal window size of the child tty. This will cause
1476 1476 a SIGWINCH signal to be sent to the child. This does not change the
1477 1477 physical window size. It changes the size reported to TTY-aware
1478 1478 applications like vi or curses -- applications that respond to the
1479 1479 SIGWINCH signal. """
1480 1480
1481 1481 # Check for buggy platforms. Some Python versions on some platforms
1482 1482 # (notably OSF1 Alpha and RedHat 7.1) truncate the value for
1483 1483 # termios.TIOCSWINSZ. It is not clear why this happens.
1484 1484 # These platforms don't seem to handle the signed int very well;
1485 1485 # yet other platforms like OpenBSD have a large negative value for
1486 1486 # TIOCSWINSZ and they don't have a truncate problem.
1487 1487 # Newer versions of Linux have totally different values for TIOCSWINSZ.
1488 1488 # Note that this fix is a hack.
1489 1489 TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561)
1490 1490 if TIOCSWINSZ == 2148037735L: # L is not required in Python >= 2.2.
1491 1491 TIOCSWINSZ = -2146929561 # Same bits, but with sign.
1492 1492 # Note, assume ws_xpixel and ws_ypixel are zero.
1493 1493 s = struct.pack('HHHH', r, c, 0, 0)
1494 1494 fcntl.ioctl(self.fileno(), TIOCSWINSZ, s)
1495 1495
1496 1496 def interact(self, escape_character = b'\x1d', input_filter = None, output_filter = None):
1497 1497
1498 1498 """This gives control of the child process to the interactive user (the
1499 1499 human at the keyboard). Keystrokes are sent to the child process, and
1500 1500 the stdout and stderr output of the child process is printed. This
1501 1501 simply echos the child stdout and child stderr to the real stdout and
1502 1502 it echos the real stdin to the child stdin. When the user types the
1503 1503 escape_character this method will stop. The default for
1504 1504 escape_character is ^]. This should not be confused with ASCII 27 --
1505 1505 the ESC character. ASCII 29 was chosen for historical merit because
1506 1506 this is the character used by 'telnet' as the escape character. The
1507 1507 escape_character will not be sent to the child process.
1508 1508
1509 1509 You may pass in optional input and output filter functions. These
1510 1510 functions should take a string and return a string. The output_filter
1511 1511 will be passed all the output from the child process. The input_filter
1512 1512 will be passed all the keyboard input from the user. The input_filter
1513 1513 is run BEFORE the check for the escape_character.
1514 1514
1515 1515 Note that if you change the window size of the parent the SIGWINCH
1516 1516 signal will not be passed through to the child. If you want the child
1517 1517 window size to change when the parent's window size changes then do
1518 1518 something like the following example::
1519 1519
1520 1520 import pexpect, struct, fcntl, termios, signal, sys
1521 1521 def sigwinch_passthrough (sig, data):
1522 1522 s = struct.pack("HHHH", 0, 0, 0, 0)
1523 1523 a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s))
1524 1524 global p
1525 1525 p.setwinsize(a[0],a[1])
1526 1526 p = pexpect.spawn('/bin/bash') # Note this is global and used in sigwinch_passthrough.
1527 1527 signal.signal(signal.SIGWINCH, sigwinch_passthrough)
1528 1528 p.interact()
1529 1529 """
1530 1530
1531 1531 # Flush the buffer.
1532 1532 if PY3: self.stdout.write(_cast_unicode(self.buffer, self.encoding))
1533 1533 else: self.stdout.write(self.buffer)
1534 1534 self.stdout.flush()
1535 1535 self.buffer = self._empty_buffer
1536 1536 mode = tty.tcgetattr(self.STDIN_FILENO)
1537 1537 tty.setraw(self.STDIN_FILENO)
1538 1538 try:
1539 1539 self.__interact_copy(escape_character, input_filter, output_filter)
1540 1540 finally:
1541 1541 tty.tcsetattr(self.STDIN_FILENO, tty.TCSAFLUSH, mode)
1542 1542
1543 1543 def __interact_writen(self, fd, data):
1544 1544
1545 1545 """This is used by the interact() method.
1546 1546 """
1547 1547
1548 1548 while data != b'' and self.isalive():
1549 1549 n = os.write(fd, data)
1550 1550 data = data[n:]
1551 1551
1552 1552 def __interact_read(self, fd):
1553 1553
1554 1554 """This is used by the interact() method.
1555 1555 """
1556 1556
1557 1557 return os.read(fd, 1000)
1558 1558
1559 1559 def __interact_copy(self, escape_character = None, input_filter = None, output_filter = None):
1560 1560
1561 1561 """This is used by the interact() method.
1562 1562 """
1563 1563
1564 1564 while self.isalive():
1565 1565 r,w,e = self.__select([self.child_fd, self.STDIN_FILENO], [], [])
1566 1566 if self.child_fd in r:
1567 1567 data = self.__interact_read(self.child_fd)
1568 1568 if output_filter: data = output_filter(data)
1569 1569 if self.logfile is not None:
1570 1570 self.logfile.write (data)
1571 1571 self.logfile.flush()
1572 1572 os.write(self.STDOUT_FILENO, data)
1573 1573 if self.STDIN_FILENO in r:
1574 1574 data = self.__interact_read(self.STDIN_FILENO)
1575 1575 if input_filter: data = input_filter(data)
1576 1576 i = data.rfind(escape_character)
1577 1577 if i != -1:
1578 1578 data = data[:i]
1579 1579 self.__interact_writen(self.child_fd, data)
1580 1580 break
1581 1581 self.__interact_writen(self.child_fd, data)
1582 1582
1583 1583 def __select (self, iwtd, owtd, ewtd, timeout=None):
1584 1584
1585 1585 """This is a wrapper around select.select() that ignores signals. If
1586 1586 select.select raises a select.error exception and errno is an EINTR
1587 1587 error then it is ignored. Mainly this is used to ignore sigwinch
1588 1588 (terminal resize). """
1589 1589
1590 1590 # if select() is interrupted by a signal (errno==EINTR) then
1591 1591 # we loop back and enter the select() again.
1592 1592 if timeout is not None:
1593 1593 end_time = time.time() + timeout
1594 1594 while True:
1595 1595 try:
1596 1596 return select.select (iwtd, owtd, ewtd, timeout)
1597 1597 except select.error as e:
1598 1598 if e.args[0] == errno.EINTR:
1599 1599 # if we loop back we have to subtract the amount of time we already waited.
1600 1600 if timeout is not None:
1601 1601 timeout = end_time - time.time()
1602 1602 if timeout < 0:
1603 1603 return ([],[],[])
1604 1604 else: # something else caused the select.error, so this really is an exception
1605 1605 raise
1606 1606
1607 1607 class spawn(spawnb):
1608 1608 """This is the main class interface for Pexpect. Use this class to start
1609 1609 and control child applications."""
1610 1610
1611 1611 _buffer_type = unicode
1612 1612 def _cast_buffer_type(self, s):
1613 1613 return _cast_unicode(s, self.encoding)
1614 1614 _empty_buffer = u''
1615 1615 _pty_newline = u'\r\n'
1616 1616
1617 1617 def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None,
1618 1618 logfile=None, cwd=None, env=None, encoding='utf-8'):
1619 1619 super(spawn, self).__init__(command, args, timeout=timeout, maxread=maxread,
1620 1620 searchwindowsize=searchwindowsize, logfile=logfile, cwd=cwd, env=env)
1621 1621 self.encoding = encoding
1622 1622
1623 1623 def _prepare_regex_pattern(self, p):
1624 1624 "Recompile bytes regexes as unicode regexes."
1625 1625 if isinstance(p.pattern, bytes):
1626 1626 p = re.compile(p.pattern.decode(self.encoding), p.flags)
1627 1627 return p
1628 1628
1629 1629 def read_nonblocking(self, size=1, timeout=-1):
1630 1630 return super(spawn, self).read_nonblocking(size=size, timeout=timeout)\
1631 1631 .decode(self.encoding)
1632 1632
1633 1633 read_nonblocking.__doc__ = spawnb.read_nonblocking.__doc__
1634 1634
1635 1635
1636 1636 ##############################################################################
1637 1637 # End of spawn class
1638 1638 ##############################################################################
1639 1639
1640 1640 class searcher_string (object):
1641 1641
1642 1642 """This is a plain string search helper for the spawn.expect_any() method.
1643 1643 This helper class is for speed. For more powerful regex patterns
1644 1644 see the helper class, searcher_re.
1645 1645
1646 1646 Attributes:
1647 1647
1648 1648 eof_index - index of EOF, or -1
1649 1649 timeout_index - index of TIMEOUT, or -1
1650 1650
1651 1651 After a successful match by the search() method the following attributes
1652 1652 are available:
1653 1653
1654 1654 start - index into the buffer, first byte of match
1655 1655 end - index into the buffer, first byte after match
1656 1656 match - the matching string itself
1657 1657
1658 1658 """
1659 1659
1660 1660 def __init__(self, strings):
1661 1661
1662 1662 """This creates an instance of searcher_string. This argument 'strings'
1663 1663 may be a list; a sequence of strings; or the EOF or TIMEOUT types. """
1664 1664
1665 1665 self.eof_index = -1
1666 1666 self.timeout_index = -1
1667 1667 self._strings = []
1668 1668 for n, s in enumerate(strings):
1669 1669 if s is EOF:
1670 1670 self.eof_index = n
1671 1671 continue
1672 1672 if s is TIMEOUT:
1673 1673 self.timeout_index = n
1674 1674 continue
1675 1675 self._strings.append((n, s))
1676 1676
1677 1677 def __str__(self):
1678 1678
1679 1679 """This returns a human-readable string that represents the state of
1680 1680 the object."""
1681 1681
1682 1682 ss = [ (ns[0],' %d: "%s"' % ns) for ns in self._strings ]
1683 1683 ss.append((-1,'searcher_string:'))
1684 1684 if self.eof_index >= 0:
1685 1685 ss.append ((self.eof_index,' %d: EOF' % self.eof_index))
1686 1686 if self.timeout_index >= 0:
1687 1687 ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
1688 1688 ss.sort()
1689 1689 return '\n'.join(a[1] for a in ss)
1690 1690
1691 1691 def search(self, buffer, freshlen, searchwindowsize=None):
1692 1692
1693 1693 """This searches 'buffer' for the first occurence of one of the search
1694 1694 strings. 'freshlen' must indicate the number of bytes at the end of
1695 1695 'buffer' which have not been searched before. It helps to avoid
1696 1696 searching the same, possibly big, buffer over and over again.
1697 1697
1698 1698 See class spawn for the 'searchwindowsize' argument.
1699 1699
1700 1700 If there is a match this returns the index of that string, and sets
1701 1701 'start', 'end' and 'match'. Otherwise, this returns -1. """
1702 1702
1703 1703 absurd_match = len(buffer)
1704 1704 first_match = absurd_match
1705 1705
1706 1706 # 'freshlen' helps a lot here. Further optimizations could
1707 1707 # possibly include:
1708 1708 #
1709 1709 # using something like the Boyer-Moore Fast String Searching
1710 1710 # Algorithm; pre-compiling the search through a list of
1711 1711 # strings into something that can scan the input once to
1712 1712 # search for all N strings; realize that if we search for
1713 1713 # ['bar', 'baz'] and the input is '...foo' we need not bother
1714 1714 # rescanning until we've read three more bytes.
1715 1715 #
1716 1716 # Sadly, I don't know enough about this interesting topic. /grahn
1717 1717
1718 1718 for index, s in self._strings:
1719 1719 if searchwindowsize is None:
1720 1720 # the match, if any, can only be in the fresh data,
1721 1721 # or at the very end of the old data
1722 1722 offset = -(freshlen+len(s))
1723 1723 else:
1724 1724 # better obey searchwindowsize
1725 1725 offset = -searchwindowsize
1726 1726 n = buffer.find(s, offset)
1727 1727 if n >= 0 and n < first_match:
1728 1728 first_match = n
1729 1729 best_index, best_match = index, s
1730 1730 if first_match == absurd_match:
1731 1731 return -1
1732 1732 self.match = best_match
1733 1733 self.start = first_match
1734 1734 self.end = self.start + len(self.match)
1735 1735 return best_index
1736 1736
1737 1737 class searcher_re (object):
1738 1738
1739 1739 """This is regular expression string search helper for the
1740 1740 spawn.expect_any() method. This helper class is for powerful
1741 1741 pattern matching. For speed, see the helper class, searcher_string.
1742 1742
1743 1743 Attributes:
1744 1744
1745 1745 eof_index - index of EOF, or -1
1746 1746 timeout_index - index of TIMEOUT, or -1
1747 1747
1748 1748 After a successful match by the search() method the following attributes
1749 1749 are available:
1750 1750
1751 1751 start - index into the buffer, first byte of match
1752 1752 end - index into the buffer, first byte after match
1753 1753 match - the re.match object returned by a succesful re.search
1754 1754
1755 1755 """
1756 1756
1757 1757 def __init__(self, patterns):
1758 1758
1759 1759 """This creates an instance that searches for 'patterns' Where
1760 1760 'patterns' may be a list or other sequence of compiled regular
1761 1761 expressions, or the EOF or TIMEOUT types."""
1762 1762
1763 1763 self.eof_index = -1
1764 1764 self.timeout_index = -1
1765 1765 self._searches = []
1766 1766 for n, s in enumerate(patterns):
1767 1767 if s is EOF:
1768 1768 self.eof_index = n
1769 1769 continue
1770 1770 if s is TIMEOUT:
1771 1771 self.timeout_index = n
1772 1772 continue
1773 1773 self._searches.append((n, s))
1774 1774
1775 1775 def __str__(self):
1776 1776
1777 1777 """This returns a human-readable string that represents the state of
1778 1778 the object."""
1779 1779
1780 1780 ss = [ (n,' %d: re.compile("%s")' % (n,str(s.pattern))) for n,s in self._searches]
1781 1781 ss.append((-1,'searcher_re:'))
1782 1782 if self.eof_index >= 0:
1783 1783 ss.append ((self.eof_index,' %d: EOF' % self.eof_index))
1784 1784 if self.timeout_index >= 0:
1785 1785 ss.append ((self.timeout_index,' %d: TIMEOUT' % self.timeout_index))
1786 1786 ss.sort()
1787 1787 return '\n'.join(a[1] for a in ss)
1788 1788
1789 1789 def search(self, buffer, freshlen, searchwindowsize=None):
1790 1790
1791 1791 """This searches 'buffer' for the first occurence of one of the regular
1792 1792 expressions. 'freshlen' must indicate the number of bytes at the end of
1793 1793 'buffer' which have not been searched before.
1794 1794
1795 1795 See class spawn for the 'searchwindowsize' argument.
1796 1796
1797 1797 If there is a match this returns the index of that string, and sets
1798 1798 'start', 'end' and 'match'. Otherwise, returns -1."""
1799 1799
1800 1800 absurd_match = len(buffer)
1801 1801 first_match = absurd_match
1802 1802 # 'freshlen' doesn't help here -- we cannot predict the
1803 1803 # length of a match, and the re module provides no help.
1804 1804 if searchwindowsize is None:
1805 1805 searchstart = 0
1806 1806 else:
1807 1807 searchstart = max(0, len(buffer)-searchwindowsize)
1808 1808 for index, s in self._searches:
1809 1809 match = s.search(buffer, searchstart)
1810 1810 if match is None:
1811 1811 continue
1812 1812 n = match.start()
1813 1813 if n < first_match:
1814 1814 first_match = n
1815 1815 the_match = match
1816 1816 best_index = index
1817 1817 if first_match == absurd_match:
1818 1818 return -1
1819 1819 self.start = first_match
1820 1820 self.match = the_match
1821 1821 self.end = self.match.end()
1822 1822 return best_index
1823 1823
1824 1824 def which (filename):
1825 1825
1826 1826 """This takes a given filename; tries to find it in the environment path;
1827 1827 then checks if it is executable. This returns the full path to the filename
1828 1828 if found and executable. Otherwise this returns None."""
1829 1829
1830 1830 # Special case where filename already contains a path.
1831 1831 if os.path.dirname(filename) != '':
1832 1832 if os.access (filename, os.X_OK):
1833 1833 return filename
1834 1834
1835 if not os.environ.has_key('PATH') or os.environ['PATH'] == '':
1835 if 'PATH' not in os.environ or os.environ['PATH'] == '':
1836 1836 p = os.defpath
1837 1837 else:
1838 1838 p = os.environ['PATH']
1839 1839
1840 1840 pathlist = p.split(os.pathsep)
1841 1841
1842 1842 for path in pathlist:
1843 1843 f = os.path.join(path, filename)
1844 1844 if os.access(f, os.X_OK):
1845 1845 return f
1846 1846 return None
1847 1847
1848 1848 def split_command_line(command_line):
1849 1849
1850 1850 """This splits a command line into a list of arguments. It splits arguments
1851 1851 on spaces, but handles embedded quotes, doublequotes, and escaped
1852 1852 characters. It's impossible to do this with a regular expression, so I
1853 1853 wrote a little state machine to parse the command line. """
1854 1854
1855 1855 arg_list = []
1856 1856 arg = ''
1857 1857
1858 1858 # Constants to name the states we can be in.
1859 1859 state_basic = 0
1860 1860 state_esc = 1
1861 1861 state_singlequote = 2
1862 1862 state_doublequote = 3
1863 1863 state_whitespace = 4 # The state of consuming whitespace between commands.
1864 1864 state = state_basic
1865 1865
1866 1866 for c in command_line:
1867 1867 if state == state_basic or state == state_whitespace:
1868 1868 if c == '\\': # Escape the next character
1869 1869 state = state_esc
1870 1870 elif c == r"'": # Handle single quote
1871 1871 state = state_singlequote
1872 1872 elif c == r'"': # Handle double quote
1873 1873 state = state_doublequote
1874 1874 elif c.isspace():
1875 1875 # Add arg to arg_list if we aren't in the middle of whitespace.
1876 1876 if state == state_whitespace:
1877 1877 None # Do nothing.
1878 1878 else:
1879 1879 arg_list.append(arg)
1880 1880 arg = ''
1881 1881 state = state_whitespace
1882 1882 else:
1883 1883 arg = arg + c
1884 1884 state = state_basic
1885 1885 elif state == state_esc:
1886 1886 arg = arg + c
1887 1887 state = state_basic
1888 1888 elif state == state_singlequote:
1889 1889 if c == r"'":
1890 1890 state = state_basic
1891 1891 else:
1892 1892 arg = arg + c
1893 1893 elif state == state_doublequote:
1894 1894 if c == r'"':
1895 1895 state = state_basic
1896 1896 else:
1897 1897 arg = arg + c
1898 1898
1899 1899 if arg != '':
1900 1900 arg_list.append(arg)
1901 1901 return arg_list
1902 1902
1903 1903 # vi:set sr et ts=4 sw=4 ft=python :
@@ -1,577 +1,577 b''
1 1 """ A FrontendWidget that emulates the interface of the console IPython and
2 2 supports the additional functionality provided by the IPython kernel.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Imports
7 7 #-----------------------------------------------------------------------------
8 8
9 9 # Standard library imports
10 10 from collections import namedtuple
11 11 import os.path
12 12 import re
13 13 from subprocess import Popen
14 14 import sys
15 15 import time
16 16 from textwrap import dedent
17 17
18 18 # System library imports
19 19 from IPython.external.qt import QtCore, QtGui
20 20
21 21 # Local imports
22 22 from IPython.core.inputsplitter import IPythonInputSplitter, \
23 23 transform_ipy_prompt
24 24 from IPython.utils.traitlets import Bool, Unicode
25 25 from frontend_widget import FrontendWidget
26 26 import styles
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Constants
30 30 #-----------------------------------------------------------------------------
31 31
32 32 # Default strings to build and display input and output prompts (and separators
33 33 # in between)
34 34 default_in_prompt = 'In [<span class="in-prompt-number">%i</span>]: '
35 35 default_out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
36 36 default_input_sep = '\n'
37 37 default_output_sep = ''
38 38 default_output_sep2 = ''
39 39
40 40 # Base path for most payload sources.
41 41 zmq_shell_source = 'IPython.zmq.zmqshell.ZMQInteractiveShell'
42 42
43 43 if sys.platform.startswith('win'):
44 44 default_editor = 'notepad'
45 45 else:
46 46 default_editor = ''
47 47
48 48 #-----------------------------------------------------------------------------
49 49 # IPythonWidget class
50 50 #-----------------------------------------------------------------------------
51 51
52 52 class IPythonWidget(FrontendWidget):
53 53 """ A FrontendWidget for an IPython kernel.
54 54 """
55 55
56 56 # If set, the 'custom_edit_requested(str, int)' signal will be emitted when
57 57 # an editor is needed for a file. This overrides 'editor' and 'editor_line'
58 58 # settings.
59 59 custom_edit = Bool(False)
60 60 custom_edit_requested = QtCore.Signal(object, object)
61 61
62 62 editor = Unicode(default_editor, config=True,
63 63 help="""
64 64 A command for invoking a system text editor. If the string contains a
65 65 {filename} format specifier, it will be used. Otherwise, the filename
66 66 will be appended to the end the command.
67 67 """)
68 68
69 69 editor_line = Unicode(config=True,
70 70 help="""
71 71 The editor command to use when a specific line number is requested. The
72 72 string should contain two format specifiers: {line} and {filename}. If
73 73 this parameter is not specified, the line number option to the %edit
74 74 magic will be ignored.
75 75 """)
76 76
77 77 style_sheet = Unicode(config=True,
78 78 help="""
79 79 A CSS stylesheet. The stylesheet can contain classes for:
80 80 1. Qt: QPlainTextEdit, QFrame, QWidget, etc
81 81 2. Pygments: .c, .k, .o, etc. (see PygmentsHighlighter)
82 82 3. IPython: .error, .in-prompt, .out-prompt, etc
83 83 """)
84 84
85 85 syntax_style = Unicode(config=True,
86 86 help="""
87 87 If not empty, use this Pygments style for syntax highlighting.
88 88 Otherwise, the style sheet is queried for Pygments style
89 89 information.
90 90 """)
91 91
92 92 # Prompts.
93 93 in_prompt = Unicode(default_in_prompt, config=True)
94 94 out_prompt = Unicode(default_out_prompt, config=True)
95 95 input_sep = Unicode(default_input_sep, config=True)
96 96 output_sep = Unicode(default_output_sep, config=True)
97 97 output_sep2 = Unicode(default_output_sep2, config=True)
98 98
99 99 # FrontendWidget protected class variables.
100 100 _input_splitter_class = IPythonInputSplitter
101 101 _transform_prompt = staticmethod(transform_ipy_prompt)
102 102
103 103 # IPythonWidget protected class variables.
104 104 _PromptBlock = namedtuple('_PromptBlock', ['block', 'length', 'number'])
105 105 _payload_source_edit = zmq_shell_source + '.edit_magic'
106 106 _payload_source_exit = zmq_shell_source + '.ask_exit'
107 107 _payload_source_next_input = zmq_shell_source + '.set_next_input'
108 108 _payload_source_page = 'IPython.zmq.page.page'
109 109 _retrying_history_request = False
110 110
111 111 #---------------------------------------------------------------------------
112 112 # 'object' interface
113 113 #---------------------------------------------------------------------------
114 114
115 115 def __init__(self, *args, **kw):
116 116 super(IPythonWidget, self).__init__(*args, **kw)
117 117
118 118 # IPythonWidget protected variables.
119 119 self._payload_handlers = {
120 120 self._payload_source_edit : self._handle_payload_edit,
121 121 self._payload_source_exit : self._handle_payload_exit,
122 122 self._payload_source_page : self._handle_payload_page,
123 123 self._payload_source_next_input : self._handle_payload_next_input }
124 124 self._previous_prompt_obj = None
125 125 self._keep_kernel_on_exit = None
126 126
127 127 # Initialize widget styling.
128 128 if self.style_sheet:
129 129 self._style_sheet_changed()
130 130 self._syntax_style_changed()
131 131 else:
132 132 self.set_default_style()
133 133
134 134 #---------------------------------------------------------------------------
135 135 # 'BaseFrontendMixin' abstract interface
136 136 #---------------------------------------------------------------------------
137 137
138 138 def _handle_complete_reply(self, rep):
139 139 """ Reimplemented to support IPython's improved completion machinery.
140 140 """
141 141 self.log.debug("complete: %s", rep.get('content', ''))
142 142 cursor = self._get_cursor()
143 143 info = self._request_info.get('complete')
144 144 if info and info.id == rep['parent_header']['msg_id'] and \
145 145 info.pos == cursor.position():
146 146 matches = rep['content']['matches']
147 147 text = rep['content']['matched_text']
148 148 offset = len(text)
149 149
150 150 # Clean up matches with period and path separators if the matched
151 151 # text has not been transformed. This is done by truncating all
152 152 # but the last component and then suitably decreasing the offset
153 153 # between the current cursor position and the start of completion.
154 154 if len(matches) > 1 and matches[0][:offset] == text:
155 155 parts = re.split(r'[./\\]', text)
156 156 sep_count = len(parts) - 1
157 157 if sep_count:
158 158 chop_length = sum(map(len, parts[:sep_count])) + sep_count
159 159 matches = [ match[chop_length:] for match in matches ]
160 160 offset -= chop_length
161 161
162 162 # Move the cursor to the start of the match and complete.
163 163 cursor.movePosition(QtGui.QTextCursor.Left, n=offset)
164 164 self._complete_with_items(cursor, matches)
165 165
166 166 def _handle_execute_reply(self, msg):
167 167 """ Reimplemented to support prompt requests.
168 168 """
169 169 msg_id = msg['parent_header'].get('msg_id')
170 170 info = self._request_info['execute'].get(msg_id)
171 171 if info and info.kind == 'prompt':
172 172 number = msg['content']['execution_count'] + 1
173 173 self._show_interpreter_prompt(number)
174 174 self._request_info['execute'].pop(msg_id)
175 175 else:
176 176 super(IPythonWidget, self)._handle_execute_reply(msg)
177 177
178 178 def _handle_history_reply(self, msg):
179 179 """ Implemented to handle history tail replies, which are only supported
180 180 by the IPython kernel.
181 181 """
182 182 content = msg['content']
183 183 if 'history' not in content:
184 184 self.log.error("History request failed: %r"%content)
185 185 if content.get('status', '') == 'aborted' and \
186 186 not self._retrying_history_request:
187 187 # a *different* action caused this request to be aborted, so
188 188 # we should try again.
189 189 self.log.error("Retrying aborted history request")
190 190 # prevent multiple retries of aborted requests:
191 191 self._retrying_history_request = True
192 192 # wait out the kernel's queue flush, which is currently timed at 0.1s
193 193 time.sleep(0.25)
194 194 self.kernel_manager.shell_channel.history(hist_access_type='tail',n=1000)
195 195 else:
196 196 self._retrying_history_request = False
197 197 return
198 198 # reset retry flag
199 199 self._retrying_history_request = False
200 200 history_items = content['history']
201 201 self.log.debug("Received history reply with %i entries", len(history_items))
202 202 items = []
203 203 last_cell = u""
204 204 for _, _, cell in history_items:
205 205 cell = cell.rstrip()
206 206 if cell != last_cell:
207 207 items.append(cell)
208 208 last_cell = cell
209 209 self._set_history(items)
210 210
211 211 def _handle_pyout(self, msg):
212 212 """ Reimplemented for IPython-style "display hook".
213 213 """
214 214 self.log.debug("pyout: %s", msg.get('content', ''))
215 215 if not self._hidden and self._is_from_this_session(msg):
216 216 content = msg['content']
217 217 prompt_number = content.get('execution_count', 0)
218 218 data = content['data']
219 if data.has_key('text/html'):
219 if 'text/html' in data:
220 220 self._append_plain_text(self.output_sep, True)
221 221 self._append_html(self._make_out_prompt(prompt_number), True)
222 222 html = data['text/html']
223 223 self._append_plain_text('\n', True)
224 224 self._append_html(html + self.output_sep2, True)
225 elif data.has_key('text/plain'):
225 elif 'text/plain' in data:
226 226 self._append_plain_text(self.output_sep, True)
227 227 self._append_html(self._make_out_prompt(prompt_number), True)
228 228 text = data['text/plain']
229 229 # If the repr is multiline, make sure we start on a new line,
230 230 # so that its lines are aligned.
231 231 if "\n" in text and not self.output_sep.endswith("\n"):
232 232 self._append_plain_text('\n', True)
233 233 self._append_plain_text(text + self.output_sep2, True)
234 234
235 235 def _handle_display_data(self, msg):
236 236 """ The base handler for the ``display_data`` message.
237 237 """
238 238 self.log.debug("display: %s", msg.get('content', ''))
239 239 # For now, we don't display data from other frontends, but we
240 240 # eventually will as this allows all frontends to monitor the display
241 241 # data. But we need to figure out how to handle this in the GUI.
242 242 if not self._hidden and self._is_from_this_session(msg):
243 243 source = msg['content']['source']
244 244 data = msg['content']['data']
245 245 metadata = msg['content']['metadata']
246 246 # In the regular IPythonWidget, we simply print the plain text
247 247 # representation.
248 if data.has_key('text/html'):
248 if 'text/html' in data:
249 249 html = data['text/html']
250 250 self._append_html(html, True)
251 elif data.has_key('text/plain'):
251 elif 'text/plain' in data:
252 252 text = data['text/plain']
253 253 self._append_plain_text(text, True)
254 254 # This newline seems to be needed for text and html output.
255 255 self._append_plain_text(u'\n', True)
256 256
257 257 def _started_channels(self):
258 258 """Reimplemented to make a history request and load %guiref."""
259 259 super(IPythonWidget, self)._started_channels()
260 260 self._load_guiref_magic()
261 261 self.kernel_manager.shell_channel.history(hist_access_type='tail',
262 262 n=1000)
263 263
264 264 def _started_kernel(self):
265 265 """Load %guiref when the kernel starts (if channels are also started).
266 266
267 267 Principally triggered by kernel restart.
268 268 """
269 269 if self.kernel_manager.shell_channel is not None:
270 270 self._load_guiref_magic()
271 271
272 272 def _load_guiref_magic(self):
273 273 """Load %guiref magic."""
274 274 self.kernel_manager.shell_channel.execute('\n'.join([
275 275 "from IPython.core import usage",
276 276 "get_ipython().register_magic_function(usage.page_guiref, 'line', 'guiref')",
277 277 ]), silent=True)
278 278
279 279 #---------------------------------------------------------------------------
280 280 # 'ConsoleWidget' public interface
281 281 #---------------------------------------------------------------------------
282 282
283 283 #---------------------------------------------------------------------------
284 284 # 'FrontendWidget' public interface
285 285 #---------------------------------------------------------------------------
286 286
287 287 def execute_file(self, path, hidden=False):
288 288 """ Reimplemented to use the 'run' magic.
289 289 """
290 290 # Use forward slashes on Windows to avoid escaping each separator.
291 291 if sys.platform == 'win32':
292 292 path = os.path.normpath(path).replace('\\', '/')
293 293
294 294 # Perhaps we should not be using %run directly, but while we
295 295 # are, it is necessary to quote or escape filenames containing spaces
296 296 # or quotes.
297 297
298 298 # In earlier code here, to minimize escaping, we sometimes quoted the
299 299 # filename with single quotes. But to do this, this code must be
300 300 # platform-aware, because run uses shlex rather than python string
301 301 # parsing, so that:
302 302 # * In Win: single quotes can be used in the filename without quoting,
303 303 # and we cannot use single quotes to quote the filename.
304 304 # * In *nix: we can escape double quotes in a double quoted filename,
305 305 # but can't escape single quotes in a single quoted filename.
306 306
307 307 # So to keep this code non-platform-specific and simple, we now only
308 308 # use double quotes to quote filenames, and escape when needed:
309 309 if ' ' in path or "'" in path or '"' in path:
310 310 path = '"%s"' % path.replace('"', '\\"')
311 311 self.execute('%%run %s' % path, hidden=hidden)
312 312
313 313 #---------------------------------------------------------------------------
314 314 # 'FrontendWidget' protected interface
315 315 #---------------------------------------------------------------------------
316 316
317 317 def _complete(self):
318 318 """ Reimplemented to support IPython's improved completion machinery.
319 319 """
320 320 # We let the kernel split the input line, so we *always* send an empty
321 321 # text field. Readline-based frontends do get a real text field which
322 322 # they can use.
323 323 text = ''
324 324
325 325 # Send the completion request to the kernel
326 326 msg_id = self.kernel_manager.shell_channel.complete(
327 327 text, # text
328 328 self._get_input_buffer_cursor_line(), # line
329 329 self._get_input_buffer_cursor_column(), # cursor_pos
330 330 self.input_buffer) # block
331 331 pos = self._get_cursor().position()
332 332 info = self._CompletionRequest(msg_id, pos)
333 333 self._request_info['complete'] = info
334 334
335 335 def _process_execute_error(self, msg):
336 336 """ Reimplemented for IPython-style traceback formatting.
337 337 """
338 338 content = msg['content']
339 339 traceback = '\n'.join(content['traceback']) + '\n'
340 340 if False:
341 341 # FIXME: For now, tracebacks come as plain text, so we can't use
342 342 # the html renderer yet. Once we refactor ultratb to produce
343 343 # properly styled tracebacks, this branch should be the default
344 344 traceback = traceback.replace(' ', '&nbsp;')
345 345 traceback = traceback.replace('\n', '<br/>')
346 346
347 347 ename = content['ename']
348 348 ename_styled = '<span class="error">%s</span>' % ename
349 349 traceback = traceback.replace(ename, ename_styled)
350 350
351 351 self._append_html(traceback)
352 352 else:
353 353 # This is the fallback for now, using plain text with ansi escapes
354 354 self._append_plain_text(traceback)
355 355
356 356 def _process_execute_payload(self, item):
357 357 """ Reimplemented to dispatch payloads to handler methods.
358 358 """
359 359 handler = self._payload_handlers.get(item['source'])
360 360 if handler is None:
361 361 # We have no handler for this type of payload, simply ignore it
362 362 return False
363 363 else:
364 364 handler(item)
365 365 return True
366 366
367 367 def _show_interpreter_prompt(self, number=None):
368 368 """ Reimplemented for IPython-style prompts.
369 369 """
370 370 # If a number was not specified, make a prompt number request.
371 371 if number is None:
372 372 msg_id = self.kernel_manager.shell_channel.execute('', silent=True)
373 373 info = self._ExecutionRequest(msg_id, 'prompt')
374 374 self._request_info['execute'][msg_id] = info
375 375 return
376 376
377 377 # Show a new prompt and save information about it so that it can be
378 378 # updated later if the prompt number turns out to be wrong.
379 379 self._prompt_sep = self.input_sep
380 380 self._show_prompt(self._make_in_prompt(number), html=True)
381 381 block = self._control.document().lastBlock()
382 382 length = len(self._prompt)
383 383 self._previous_prompt_obj = self._PromptBlock(block, length, number)
384 384
385 385 # Update continuation prompt to reflect (possibly) new prompt length.
386 386 self._set_continuation_prompt(
387 387 self._make_continuation_prompt(self._prompt), html=True)
388 388
389 389 def _show_interpreter_prompt_for_reply(self, msg):
390 390 """ Reimplemented for IPython-style prompts.
391 391 """
392 392 # Update the old prompt number if necessary.
393 393 content = msg['content']
394 394 # abort replies do not have any keys:
395 395 if content['status'] == 'aborted':
396 396 if self._previous_prompt_obj:
397 397 previous_prompt_number = self._previous_prompt_obj.number
398 398 else:
399 399 previous_prompt_number = 0
400 400 else:
401 401 previous_prompt_number = content['execution_count']
402 402 if self._previous_prompt_obj and \
403 403 self._previous_prompt_obj.number != previous_prompt_number:
404 404 block = self._previous_prompt_obj.block
405 405
406 406 # Make sure the prompt block has not been erased.
407 407 if block.isValid() and block.text():
408 408
409 409 # Remove the old prompt and insert a new prompt.
410 410 cursor = QtGui.QTextCursor(block)
411 411 cursor.movePosition(QtGui.QTextCursor.Right,
412 412 QtGui.QTextCursor.KeepAnchor,
413 413 self._previous_prompt_obj.length)
414 414 prompt = self._make_in_prompt(previous_prompt_number)
415 415 self._prompt = self._insert_html_fetching_plain_text(
416 416 cursor, prompt)
417 417
418 418 # When the HTML is inserted, Qt blows away the syntax
419 419 # highlighting for the line, so we need to rehighlight it.
420 420 self._highlighter.rehighlightBlock(cursor.block())
421 421
422 422 self._previous_prompt_obj = None
423 423
424 424 # Show a new prompt with the kernel's estimated prompt number.
425 425 self._show_interpreter_prompt(previous_prompt_number + 1)
426 426
427 427 #---------------------------------------------------------------------------
428 428 # 'IPythonWidget' interface
429 429 #---------------------------------------------------------------------------
430 430
431 431 def set_default_style(self, colors='lightbg'):
432 432 """ Sets the widget style to the class defaults.
433 433
434 434 Parameters:
435 435 -----------
436 436 colors : str, optional (default lightbg)
437 437 Whether to use the default IPython light background or dark
438 438 background or B&W style.
439 439 """
440 440 colors = colors.lower()
441 441 if colors=='lightbg':
442 442 self.style_sheet = styles.default_light_style_sheet
443 443 self.syntax_style = styles.default_light_syntax_style
444 444 elif colors=='linux':
445 445 self.style_sheet = styles.default_dark_style_sheet
446 446 self.syntax_style = styles.default_dark_syntax_style
447 447 elif colors=='nocolor':
448 448 self.style_sheet = styles.default_bw_style_sheet
449 449 self.syntax_style = styles.default_bw_syntax_style
450 450 else:
451 451 raise KeyError("No such color scheme: %s"%colors)
452 452
453 453 #---------------------------------------------------------------------------
454 454 # 'IPythonWidget' protected interface
455 455 #---------------------------------------------------------------------------
456 456
457 457 def _edit(self, filename, line=None):
458 458 """ Opens a Python script for editing.
459 459
460 460 Parameters:
461 461 -----------
462 462 filename : str
463 463 A path to a local system file.
464 464
465 465 line : int, optional
466 466 A line of interest in the file.
467 467 """
468 468 if self.custom_edit:
469 469 self.custom_edit_requested.emit(filename, line)
470 470 elif not self.editor:
471 471 self._append_plain_text('No default editor available.\n'
472 472 'Specify a GUI text editor in the `IPythonWidget.editor` '
473 473 'configurable to enable the %edit magic')
474 474 else:
475 475 try:
476 476 filename = '"%s"' % filename
477 477 if line and self.editor_line:
478 478 command = self.editor_line.format(filename=filename,
479 479 line=line)
480 480 else:
481 481 try:
482 482 command = self.editor.format()
483 483 except KeyError:
484 484 command = self.editor.format(filename=filename)
485 485 else:
486 486 command += ' ' + filename
487 487 except KeyError:
488 488 self._append_plain_text('Invalid editor command.\n')
489 489 else:
490 490 try:
491 491 Popen(command, shell=True)
492 492 except OSError:
493 493 msg = 'Opening editor with command "%s" failed.\n'
494 494 self._append_plain_text(msg % command)
495 495
496 496 def _make_in_prompt(self, number):
497 497 """ Given a prompt number, returns an HTML In prompt.
498 498 """
499 499 try:
500 500 body = self.in_prompt % number
501 501 except TypeError:
502 502 # allow in_prompt to leave out number, e.g. '>>> '
503 503 body = self.in_prompt
504 504 return '<span class="in-prompt">%s</span>' % body
505 505
506 506 def _make_continuation_prompt(self, prompt):
507 507 """ Given a plain text version of an In prompt, returns an HTML
508 508 continuation prompt.
509 509 """
510 510 end_chars = '...: '
511 511 space_count = len(prompt.lstrip('\n')) - len(end_chars)
512 512 body = '&nbsp;' * space_count + end_chars
513 513 return '<span class="in-prompt">%s</span>' % body
514 514
515 515 def _make_out_prompt(self, number):
516 516 """ Given a prompt number, returns an HTML Out prompt.
517 517 """
518 518 body = self.out_prompt % number
519 519 return '<span class="out-prompt">%s</span>' % body
520 520
521 521 #------ Payload handlers --------------------------------------------------
522 522
523 523 # Payload handlers with a generic interface: each takes the opaque payload
524 524 # dict, unpacks it and calls the underlying functions with the necessary
525 525 # arguments.
526 526
527 527 def _handle_payload_edit(self, item):
528 528 self._edit(item['filename'], item['line_number'])
529 529
530 530 def _handle_payload_exit(self, item):
531 531 self._keep_kernel_on_exit = item['keepkernel']
532 532 self.exit_requested.emit(self)
533 533
534 534 def _handle_payload_next_input(self, item):
535 535 self.input_buffer = dedent(item['text'].rstrip())
536 536
537 537 def _handle_payload_page(self, item):
538 538 # Since the plain text widget supports only a very small subset of HTML
539 539 # and we have no control over the HTML source, we only page HTML
540 540 # payloads in the rich text widget.
541 541 if item['html'] and self.kind == 'rich':
542 542 self._page(item['html'], html=True)
543 543 else:
544 544 self._page(item['text'], html=False)
545 545
546 546 #------ Trait change handlers --------------------------------------------
547 547
548 548 def _style_sheet_changed(self):
549 549 """ Set the style sheets of the underlying widgets.
550 550 """
551 551 self.setStyleSheet(self.style_sheet)
552 552 if self._control is not None:
553 553 self._control.document().setDefaultStyleSheet(self.style_sheet)
554 554 bg_color = self._control.palette().window().color()
555 555 self._ansi_processor.set_background_color(bg_color)
556 556
557 557 if self._page_control is not None:
558 558 self._page_control.document().setDefaultStyleSheet(self.style_sheet)
559 559
560 560
561 561
562 562 def _syntax_style_changed(self):
563 563 """ Set the style for the syntax highlighter.
564 564 """
565 565 if self._highlighter is None:
566 566 # ignore premature calls
567 567 return
568 568 if self.syntax_style:
569 569 self._highlighter.set_style(self.syntax_style)
570 570 else:
571 571 self._highlighter.set_style_sheet(self.style_sheet)
572 572
573 573 #------ Trait default initializers -----------------------------------------
574 574
575 575 def _banner_default(self):
576 576 from IPython.core.usage import default_gui_banner
577 577 return default_gui_banner
@@ -1,325 +1,325 b''
1 1 #-----------------------------------------------------------------------------
2 2 # Copyright (c) 2010, IPython Development Team.
3 3 #
4 4 # Distributed under the terms of the Modified BSD License.
5 5 #
6 6 # The full license is in the file COPYING.txt, distributed with this software.
7 7 #-----------------------------------------------------------------------------
8 8
9 9 # Standard libary imports.
10 10 from base64 import decodestring
11 11 import os
12 12 import re
13 13
14 14 # System libary imports.
15 15 from IPython.external.qt import QtCore, QtGui
16 16
17 17 # Local imports
18 18 from IPython.utils.traitlets import Bool
19 19 from IPython.frontend.qt.svg import save_svg, svg_to_clipboard, svg_to_image
20 20 from ipython_widget import IPythonWidget
21 21
22 22
23 23 class RichIPythonWidget(IPythonWidget):
24 24 """ An IPythonWidget that supports rich text, including lists, images, and
25 25 tables. Note that raw performance will be reduced compared to the plain
26 26 text version.
27 27 """
28 28
29 29 # RichIPythonWidget protected class variables.
30 30 _payload_source_plot = 'IPython.zmq.pylab.backend_payload.add_plot_payload'
31 31 _jpg_supported = Bool(False)
32 32
33 33 # Used to determine whether a given html export attempt has already
34 34 # displayed a warning about being unable to convert a png to svg.
35 35 _svg_warning_displayed = False
36 36
37 37 #---------------------------------------------------------------------------
38 38 # 'object' interface
39 39 #---------------------------------------------------------------------------
40 40
41 41 def __init__(self, *args, **kw):
42 42 """ Create a RichIPythonWidget.
43 43 """
44 44 kw['kind'] = 'rich'
45 45 super(RichIPythonWidget, self).__init__(*args, **kw)
46 46
47 47 # Configure the ConsoleWidget HTML exporter for our formats.
48 48 self._html_exporter.image_tag = self._get_image_tag
49 49
50 50 # Dictionary for resolving document resource names to SVG data.
51 51 self._name_to_svg_map = {}
52 52
53 53 # Do we support jpg ?
54 54 # it seems that sometime jpg support is a plugin of QT, so try to assume
55 55 # it is not always supported.
56 56 _supported_format = map(str, QtGui.QImageReader.supportedImageFormats())
57 57 self._jpg_supported = 'jpeg' in _supported_format
58 58
59 59
60 60 #---------------------------------------------------------------------------
61 61 # 'ConsoleWidget' public interface overides
62 62 #---------------------------------------------------------------------------
63 63
64 64 def export_html(self):
65 65 """ Shows a dialog to export HTML/XML in various formats.
66 66
67 67 Overridden in order to reset the _svg_warning_displayed flag prior
68 68 to the export running.
69 69 """
70 70 self._svg_warning_displayed = False
71 71 super(RichIPythonWidget, self).export_html()
72 72
73 73
74 74 #---------------------------------------------------------------------------
75 75 # 'ConsoleWidget' protected interface
76 76 #---------------------------------------------------------------------------
77 77
78 78 def _context_menu_make(self, pos):
79 79 """ Reimplemented to return a custom context menu for images.
80 80 """
81 81 format = self._control.cursorForPosition(pos).charFormat()
82 82 name = format.stringProperty(QtGui.QTextFormat.ImageName)
83 83 if name:
84 84 menu = QtGui.QMenu()
85 85
86 86 menu.addAction('Copy Image', lambda: self._copy_image(name))
87 87 menu.addAction('Save Image As...', lambda: self._save_image(name))
88 88 menu.addSeparator()
89 89
90 90 svg = self._name_to_svg_map.get(name, None)
91 91 if svg is not None:
92 92 menu.addSeparator()
93 93 menu.addAction('Copy SVG', lambda: svg_to_clipboard(svg))
94 94 menu.addAction('Save SVG As...',
95 95 lambda: save_svg(svg, self._control))
96 96 else:
97 97 menu = super(RichIPythonWidget, self)._context_menu_make(pos)
98 98 return menu
99 99
100 100 #---------------------------------------------------------------------------
101 101 # 'BaseFrontendMixin' abstract interface
102 102 #---------------------------------------------------------------------------
103 103 def _pre_image_append(self, msg, prompt_number):
104 104 """ Append the Out[] prompt and make the output nicer
105 105
106 106 Shared code for some the following if statement
107 107 """
108 108 self.log.debug("pyout: %s", msg.get('content', ''))
109 109 self._append_plain_text(self.output_sep, True)
110 110 self._append_html(self._make_out_prompt(prompt_number), True)
111 111 self._append_plain_text('\n', True)
112 112
113 113 def _handle_pyout(self, msg):
114 114 """ Overridden to handle rich data types, like SVG.
115 115 """
116 116 if not self._hidden and self._is_from_this_session(msg):
117 117 content = msg['content']
118 118 prompt_number = content.get('execution_count', 0)
119 119 data = content['data']
120 if data.has_key('image/svg+xml'):
120 if 'image/svg+xml' in data:
121 121 self._pre_image_append(msg, prompt_number)
122 122 self._append_svg(data['image/svg+xml'], True)
123 123 self._append_html(self.output_sep2, True)
124 elif data.has_key('image/png'):
124 elif 'image/png' in data:
125 125 self._pre_image_append(msg, prompt_number)
126 126 self._append_png(decodestring(data['image/png'].encode('ascii')), True)
127 127 self._append_html(self.output_sep2, True)
128 elif data.has_key('image/jpeg') and self._jpg_supported:
128 elif 'image/jpeg' in data and self._jpg_supported:
129 129 self._pre_image_append(msg, prompt_number)
130 130 self._append_jpg(decodestring(data['image/jpeg'].encode('ascii')), True)
131 131 self._append_html(self.output_sep2, True)
132 132 else:
133 133 # Default back to the plain text representation.
134 134 return super(RichIPythonWidget, self)._handle_pyout(msg)
135 135
136 136 def _handle_display_data(self, msg):
137 137 """ Overridden to handle rich data types, like SVG.
138 138 """
139 139 if not self._hidden and self._is_from_this_session(msg):
140 140 source = msg['content']['source']
141 141 data = msg['content']['data']
142 142 metadata = msg['content']['metadata']
143 143 # Try to use the svg or html representations.
144 144 # FIXME: Is this the right ordering of things to try?
145 if data.has_key('image/svg+xml'):
145 if 'image/svg+xml' in data:
146 146 self.log.debug("display: %s", msg.get('content', ''))
147 147 svg = data['image/svg+xml']
148 148 self._append_svg(svg, True)
149 elif data.has_key('image/png'):
149 elif 'image/png' in data:
150 150 self.log.debug("display: %s", msg.get('content', ''))
151 151 # PNG data is base64 encoded as it passes over the network
152 152 # in a JSON structure so we decode it.
153 153 png = decodestring(data['image/png'].encode('ascii'))
154 154 self._append_png(png, True)
155 elif data.has_key('image/jpeg') and self._jpg_supported:
155 elif 'image/jpeg' in data and self._jpg_supported:
156 156 self.log.debug("display: %s", msg.get('content', ''))
157 157 jpg = decodestring(data['image/jpeg'].encode('ascii'))
158 158 self._append_jpg(jpg, True)
159 159 else:
160 160 # Default back to the plain text representation.
161 161 return super(RichIPythonWidget, self)._handle_display_data(msg)
162 162
163 163 #---------------------------------------------------------------------------
164 164 # 'RichIPythonWidget' protected interface
165 165 #---------------------------------------------------------------------------
166 166
167 167 def _append_jpg(self, jpg, before_prompt=False):
168 168 """ Append raw JPG data to the widget."""
169 169 self._append_custom(self._insert_jpg, jpg, before_prompt)
170 170
171 171 def _append_png(self, png, before_prompt=False):
172 172 """ Append raw PNG data to the widget.
173 173 """
174 174 self._append_custom(self._insert_png, png, before_prompt)
175 175
176 176 def _append_svg(self, svg, before_prompt=False):
177 177 """ Append raw SVG data to the widget.
178 178 """
179 179 self._append_custom(self._insert_svg, svg, before_prompt)
180 180
181 181 def _add_image(self, image):
182 182 """ Adds the specified QImage to the document and returns a
183 183 QTextImageFormat that references it.
184 184 """
185 185 document = self._control.document()
186 186 name = str(image.cacheKey())
187 187 document.addResource(QtGui.QTextDocument.ImageResource,
188 188 QtCore.QUrl(name), image)
189 189 format = QtGui.QTextImageFormat()
190 190 format.setName(name)
191 191 return format
192 192
193 193 def _copy_image(self, name):
194 194 """ Copies the ImageResource with 'name' to the clipboard.
195 195 """
196 196 image = self._get_image(name)
197 197 QtGui.QApplication.clipboard().setImage(image)
198 198
199 199 def _get_image(self, name):
200 200 """ Returns the QImage stored as the ImageResource with 'name'.
201 201 """
202 202 document = self._control.document()
203 203 image = document.resource(QtGui.QTextDocument.ImageResource,
204 204 QtCore.QUrl(name))
205 205 return image
206 206
207 207 def _get_image_tag(self, match, path = None, format = "png"):
208 208 """ Return (X)HTML mark-up for the image-tag given by match.
209 209
210 210 Parameters
211 211 ----------
212 212 match : re.SRE_Match
213 213 A match to an HTML image tag as exported by Qt, with
214 214 match.group("Name") containing the matched image ID.
215 215
216 216 path : string|None, optional [default None]
217 217 If not None, specifies a path to which supporting files may be
218 218 written (e.g., for linked images). If None, all images are to be
219 219 included inline.
220 220
221 221 format : "png"|"svg"|"jpg", optional [default "png"]
222 222 Format for returned or referenced images.
223 223 """
224 224 if format in ("png","jpg"):
225 225 try:
226 226 image = self._get_image(match.group("name"))
227 227 except KeyError:
228 228 return "<b>Couldn't find image %s</b>" % match.group("name")
229 229
230 230 if path is not None:
231 231 if not os.path.exists(path):
232 232 os.mkdir(path)
233 233 relpath = os.path.basename(path)
234 234 if image.save("%s/qt_img%s.%s" % (path, match.group("name"), format),
235 235 "PNG"):
236 236 return '<img src="%s/qt_img%s.%s">' % (relpath,
237 237 match.group("name"),format)
238 238 else:
239 239 return "<b>Couldn't save image!</b>"
240 240 else:
241 241 ba = QtCore.QByteArray()
242 242 buffer_ = QtCore.QBuffer(ba)
243 243 buffer_.open(QtCore.QIODevice.WriteOnly)
244 244 image.save(buffer_, format.upper())
245 245 buffer_.close()
246 246 return '<img src="data:image/%s;base64,\n%s\n" />' % (
247 247 format,re.sub(r'(.{60})',r'\1\n',str(ba.toBase64())))
248 248
249 249 elif format == "svg":
250 250 try:
251 251 svg = str(self._name_to_svg_map[match.group("name")])
252 252 except KeyError:
253 253 if not self._svg_warning_displayed:
254 254 QtGui.QMessageBox.warning(self, 'Error converting PNG to SVG.',
255 255 'Cannot convert a PNG to SVG. To fix this, add this '
256 256 'to your ipython config:\n\n'
257 257 '\tc.InlineBackendConfig.figure_format = \'svg\'\n\n'
258 258 'And regenerate the figures.',
259 259 QtGui.QMessageBox.Ok)
260 260 self._svg_warning_displayed = True
261 261 return ("<b>Cannot convert a PNG to SVG.</b> "
262 262 "To fix this, add this to your config: "
263 263 "<span>c.InlineBackendConfig.figure_format = 'svg'</span> "
264 264 "and regenerate the figures.")
265 265
266 266 # Not currently checking path, because it's tricky to find a
267 267 # cross-browser way to embed external SVG images (e.g., via
268 268 # object or embed tags).
269 269
270 270 # Chop stand-alone header from matplotlib SVG
271 271 offset = svg.find("<svg")
272 272 assert(offset > -1)
273 273
274 274 return svg[offset:]
275 275
276 276 else:
277 277 return '<b>Unrecognized image format</b>'
278 278
279 279 def _insert_jpg(self, cursor, jpg):
280 280 """ Insert raw PNG data into the widget."""
281 281 self._insert_img(cursor, jpg, 'jpg')
282 282
283 283 def _insert_png(self, cursor, png):
284 284 """ Insert raw PNG data into the widget.
285 285 """
286 286 self._insert_img(cursor, png, 'png')
287 287
288 288 def _insert_img(self, cursor, img, fmt):
289 289 """ insert a raw image, jpg or png """
290 290 try:
291 291 image = QtGui.QImage()
292 292 image.loadFromData(img, fmt.upper())
293 293 except ValueError:
294 294 self._insert_plain_text(cursor, 'Received invalid %s data.'%fmt)
295 295 else:
296 296 format = self._add_image(image)
297 297 cursor.insertBlock()
298 298 cursor.insertImage(format)
299 299 cursor.insertBlock()
300 300
301 301 def _insert_svg(self, cursor, svg):
302 302 """ Insert raw SVG data into the widet.
303 303 """
304 304 try:
305 305 image = svg_to_image(svg)
306 306 except ValueError:
307 307 self._insert_plain_text(cursor, 'Received invalid SVG data.')
308 308 else:
309 309 format = self._add_image(image)
310 310 self._name_to_svg_map[format.name()] = svg
311 311 cursor.insertBlock()
312 312 cursor.insertImage(format)
313 313 cursor.insertBlock()
314 314
315 315 def _save_image(self, name, format='PNG'):
316 316 """ Shows a save dialog for the ImageResource with 'name'.
317 317 """
318 318 dialog = QtGui.QFileDialog(self._control, 'Save Image')
319 319 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
320 320 dialog.setDefaultSuffix(format.lower())
321 321 dialog.setNameFilter('%s file (*.%s)' % (format, format.lower()))
322 322 if dialog.exec_():
323 323 filename = dialog.selectedFiles()[0]
324 324 image = self._get_image(name)
325 325 image.save(filename, format)
@@ -1,146 +1,146 b''
1 1 # coding: utf-8
2 2 """
3 3 Support for creating GUI apps and starting event loops.
4 4
5 5 IPython's GUI integration allows interative plotting and GUI usage in IPython
6 6 session. IPython has two different types of GUI integration:
7 7
8 8 1. The terminal based IPython supports GUI event loops through Python's
9 9 PyOS_InputHook. PyOS_InputHook is a hook that Python calls periodically
10 10 whenever raw_input is waiting for a user to type code. We implement GUI
11 11 support in the terminal by setting PyOS_InputHook to a function that
12 12 iterates the event loop for a short while. It is important to note that
13 13 in this situation, the real GUI event loop is NOT run in the normal
14 14 manner, so you can't use the normal means to detect that it is running.
15 15 2. In the two process IPython kernel/frontend, the GUI event loop is run in
16 16 the kernel. In this case, the event loop is run in the normal manner by
17 17 calling the function or method of the GUI toolkit that starts the event
18 18 loop.
19 19
20 20 In addition to starting the GUI event loops in one of these two ways, IPython
21 21 will *always* create an appropriate GUI application object when GUi
22 22 integration is enabled.
23 23
24 24 If you want your GUI apps to run in IPython you need to do two things:
25 25
26 26 1. Test to see if there is already an existing main application object. If
27 27 there is, you should use it. If there is not an existing application object
28 28 you should create one.
29 29 2. Test to see if the GUI event loop is running. If it is, you should not
30 30 start it. If the event loop is not running you may start it.
31 31
32 32 This module contains functions for each toolkit that perform these things
33 33 in a consistent manner. Because of how PyOS_InputHook runs the event loop
34 34 you cannot detect if the event loop is running using the traditional calls
35 35 (such as ``wx.GetApp.IsMainLoopRunning()`` in wxPython). If PyOS_InputHook is
36 36 set These methods will return a false negative. That is, they will say the
37 37 event loop is not running, when is actually is. To work around this limitation
38 38 we proposed the following informal protocol:
39 39
40 40 * Whenever someone starts the event loop, they *must* set the ``_in_event_loop``
41 41 attribute of the main application object to ``True``. This should be done
42 42 regardless of how the event loop is actually run.
43 43 * Whenever someone stops the event loop, they *must* set the ``_in_event_loop``
44 44 attribute of the main application object to ``False``.
45 45 * If you want to see if the event loop is running, you *must* use ``hasattr``
46 46 to see if ``_in_event_loop`` attribute has been set. If it is set, you
47 47 *must* use its value. If it has not been set, you can query the toolkit
48 48 in the normal manner.
49 49 * If you want GUI support and no one else has created an application or
50 50 started the event loop you *must* do this. We don't want projects to
51 51 attempt to defer these things to someone else if they themselves need it.
52 52
53 53 The functions below implement this logic for each GUI toolkit. If you need
54 54 to create custom application subclasses, you will likely have to modify this
55 55 code for your own purposes. This code can be copied into your own project
56 56 so you don't have to depend on IPython.
57 57
58 58 """
59 59
60 60 #-----------------------------------------------------------------------------
61 61 # Copyright (C) 2008-2011 The IPython Development Team
62 62 #
63 63 # Distributed under the terms of the BSD License. The full license is in
64 64 # the file COPYING, distributed as part of this software.
65 65 #-----------------------------------------------------------------------------
66 66
67 67 #-----------------------------------------------------------------------------
68 68 # Imports
69 69 #-----------------------------------------------------------------------------
70 70
71 71 #-----------------------------------------------------------------------------
72 72 # wx
73 73 #-----------------------------------------------------------------------------
74 74
75 75 def get_app_wx(*args, **kwargs):
76 76 """Create a new wx app or return an exiting one."""
77 77 import wx
78 78 app = wx.GetApp()
79 79 if app is None:
80 if not kwargs.has_key('redirect'):
80 if 'redirect' not in kwargs:
81 81 kwargs['redirect'] = False
82 82 app = wx.PySimpleApp(*args, **kwargs)
83 83 return app
84 84
85 85 def is_event_loop_running_wx(app=None):
86 86 """Is the wx event loop running."""
87 87 if app is None:
88 88 app = get_app_wx()
89 89 if hasattr(app, '_in_event_loop'):
90 90 return app._in_event_loop
91 91 else:
92 92 return app.IsMainLoopRunning()
93 93
94 94 def start_event_loop_wx(app=None):
95 95 """Start the wx event loop in a consistent manner."""
96 96 if app is None:
97 97 app = get_app_wx()
98 98 if not is_event_loop_running_wx(app):
99 99 app._in_event_loop = True
100 100 app.MainLoop()
101 101 app._in_event_loop = False
102 102 else:
103 103 app._in_event_loop = True
104 104
105 105 #-----------------------------------------------------------------------------
106 106 # qt4
107 107 #-----------------------------------------------------------------------------
108 108
109 109 def get_app_qt4(*args, **kwargs):
110 110 """Create a new qt4 app or return an existing one."""
111 111 from IPython.external.qt_for_kernel import QtGui
112 112 app = QtGui.QApplication.instance()
113 113 if app is None:
114 114 if not args:
115 115 args = ([''],)
116 116 app = QtGui.QApplication(*args, **kwargs)
117 117 return app
118 118
119 119 def is_event_loop_running_qt4(app=None):
120 120 """Is the qt4 event loop running."""
121 121 if app is None:
122 122 app = get_app_qt4([''])
123 123 if hasattr(app, '_in_event_loop'):
124 124 return app._in_event_loop
125 125 else:
126 126 # Does qt4 provide a other way to detect this?
127 127 return False
128 128
129 129 def start_event_loop_qt4(app=None):
130 130 """Start the qt4 event loop in a consistent manner."""
131 131 if app is None:
132 132 app = get_app_qt4([''])
133 133 if not is_event_loop_running_qt4(app):
134 134 app._in_event_loop = True
135 135 app.exec_()
136 136 app._in_event_loop = False
137 137 else:
138 138 app._in_event_loop = True
139 139
140 140 #-----------------------------------------------------------------------------
141 141 # Tk
142 142 #-----------------------------------------------------------------------------
143 143
144 144 #-----------------------------------------------------------------------------
145 145 # gtk
146 146 #-----------------------------------------------------------------------------
@@ -1,529 +1,529 b''
1 1 # coding: utf-8
2 2 """
3 3 Inputhook management for GUI event loop integration.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
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 try:
18 18 import ctypes
19 19 except ImportError:
20 20 ctypes = None
21 21 import os
22 22 import sys
23 23 from distutils.version import LooseVersion as V
24 24
25 25 from IPython.utils.warn import warn
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Constants
29 29 #-----------------------------------------------------------------------------
30 30
31 31 # Constants for identifying the GUI toolkits.
32 32 GUI_WX = 'wx'
33 33 GUI_QT = 'qt'
34 34 GUI_QT4 = 'qt4'
35 35 GUI_GTK = 'gtk'
36 36 GUI_TK = 'tk'
37 37 GUI_OSX = 'osx'
38 38 GUI_GLUT = 'glut'
39 39 GUI_PYGLET = 'pyglet'
40 40 GUI_GTK3 = 'gtk3'
41 41 GUI_NONE = 'none' # i.e. disable
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Utilities
45 45 #-----------------------------------------------------------------------------
46 46
47 47 def _stdin_ready_posix():
48 48 """Return True if there's something to read on stdin (posix version)."""
49 49 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
50 50 return bool(infds)
51 51
52 52 def _stdin_ready_nt():
53 53 """Return True if there's something to read on stdin (nt version)."""
54 54 return msvcrt.kbhit()
55 55
56 56 def _stdin_ready_other():
57 57 """Return True, assuming there's something to read on stdin."""
58 58 return True #
59 59
60 60
61 61 def _ignore_CTRL_C_posix():
62 62 """Ignore CTRL+C (SIGINT)."""
63 63 signal.signal(signal.SIGINT, signal.SIG_IGN)
64 64
65 65 def _allow_CTRL_C_posix():
66 66 """Take CTRL+C into account (SIGINT)."""
67 67 signal.signal(signal.SIGINT, signal.default_int_handler)
68 68
69 69 def _ignore_CTRL_C_other():
70 70 """Ignore CTRL+C (not implemented)."""
71 71 pass
72 72
73 73 def _allow_CTRL_C_other():
74 74 """Take CTRL+C into account (not implemented)."""
75 75 pass
76 76
77 77 if os.name == 'posix':
78 78 import select
79 79 import signal
80 80 stdin_ready = _stdin_ready_posix
81 81 ignore_CTRL_C = _ignore_CTRL_C_posix
82 82 allow_CTRL_C = _allow_CTRL_C_posix
83 83 elif os.name == 'nt':
84 84 import msvcrt
85 85 stdin_ready = _stdin_ready_nt
86 86 ignore_CTRL_C = _ignore_CTRL_C_other
87 87 allow_CTRL_C = _allow_CTRL_C_other
88 88 else:
89 89 stdin_ready = _stdin_ready_other
90 90 ignore_CTRL_C = _ignore_CTRL_C_other
91 91 allow_CTRL_C = _allow_CTRL_C_other
92 92
93 93
94 94 #-----------------------------------------------------------------------------
95 95 # Main InputHookManager class
96 96 #-----------------------------------------------------------------------------
97 97
98 98
99 99 class InputHookManager(object):
100 100 """Manage PyOS_InputHook for different GUI toolkits.
101 101
102 102 This class installs various hooks under ``PyOSInputHook`` to handle
103 103 GUI event loop integration.
104 104 """
105 105
106 106 def __init__(self):
107 107 if ctypes is None:
108 108 warn("IPython GUI event loop requires ctypes, %gui will not be available\n")
109 109 return
110 110 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
111 111 self._apps = {}
112 112 self._reset()
113 113
114 114 def _reset(self):
115 115 self._callback_pyfunctype = None
116 116 self._callback = None
117 117 self._installed = False
118 118 self._current_gui = None
119 119
120 120 def get_pyos_inputhook(self):
121 121 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
122 122 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
123 123
124 124 def get_pyos_inputhook_as_func(self):
125 125 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
126 126 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
127 127
128 128 def set_inputhook(self, callback):
129 129 """Set PyOS_InputHook to callback and return the previous one."""
130 130 # On platforms with 'readline' support, it's all too likely to
131 131 # have a KeyboardInterrupt signal delivered *even before* an
132 132 # initial ``try:`` clause in the callback can be executed, so
133 133 # we need to disable CTRL+C in this situation.
134 134 ignore_CTRL_C()
135 135 self._callback = callback
136 136 self._callback_pyfunctype = self.PYFUNC(callback)
137 137 pyos_inputhook_ptr = self.get_pyos_inputhook()
138 138 original = self.get_pyos_inputhook_as_func()
139 139 pyos_inputhook_ptr.value = \
140 140 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
141 141 self._installed = True
142 142 return original
143 143
144 144 def clear_inputhook(self, app=None):
145 145 """Set PyOS_InputHook to NULL and return the previous one.
146 146
147 147 Parameters
148 148 ----------
149 149 app : optional, ignored
150 150 This parameter is allowed only so that clear_inputhook() can be
151 151 called with a similar interface as all the ``enable_*`` methods. But
152 152 the actual value of the parameter is ignored. This uniform interface
153 153 makes it easier to have user-level entry points in the main IPython
154 154 app like :meth:`enable_gui`."""
155 155 pyos_inputhook_ptr = self.get_pyos_inputhook()
156 156 original = self.get_pyos_inputhook_as_func()
157 157 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
158 158 allow_CTRL_C()
159 159 self._reset()
160 160 return original
161 161
162 162 def clear_app_refs(self, gui=None):
163 163 """Clear IPython's internal reference to an application instance.
164 164
165 165 Whenever we create an app for a user on qt4 or wx, we hold a
166 166 reference to the app. This is needed because in some cases bad things
167 167 can happen if a user doesn't hold a reference themselves. This
168 168 method is provided to clear the references we are holding.
169 169
170 170 Parameters
171 171 ----------
172 172 gui : None or str
173 173 If None, clear all app references. If ('wx', 'qt4') clear
174 174 the app for that toolkit. References are not held for gtk or tk
175 175 as those toolkits don't have the notion of an app.
176 176 """
177 177 if gui is None:
178 178 self._apps = {}
179 elif self._apps.has_key(gui):
179 elif gui in self._apps:
180 180 del self._apps[gui]
181 181
182 182 def enable_wx(self, app=None):
183 183 """Enable event loop integration with wxPython.
184 184
185 185 Parameters
186 186 ----------
187 187 app : WX Application, optional.
188 188 Running application to use. If not given, we probe WX for an
189 189 existing application object, and create a new one if none is found.
190 190
191 191 Notes
192 192 -----
193 193 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
194 194 the wxPython to integrate with terminal based applications like
195 195 IPython.
196 196
197 197 If ``app`` is not given we probe for an existing one, and return it if
198 198 found. If no existing app is found, we create an :class:`wx.App` as
199 199 follows::
200 200
201 201 import wx
202 202 app = wx.App(redirect=False, clearSigInt=False)
203 203 """
204 204 import wx
205 205
206 206 wx_version = V(wx.__version__).version
207 207
208 208 if wx_version < [2, 8]:
209 209 raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__)
210 210
211 211 from IPython.lib.inputhookwx import inputhook_wx
212 212 self.set_inputhook(inputhook_wx)
213 213 self._current_gui = GUI_WX
214 214 import wx
215 215 if app is None:
216 216 app = wx.GetApp()
217 217 if app is None:
218 218 app = wx.App(redirect=False, clearSigInt=False)
219 219 app._in_event_loop = True
220 220 self._apps[GUI_WX] = app
221 221 return app
222 222
223 223 def disable_wx(self):
224 224 """Disable event loop integration with wxPython.
225 225
226 226 This merely sets PyOS_InputHook to NULL.
227 227 """
228 if self._apps.has_key(GUI_WX):
228 if GUI_WX in self._apps:
229 229 self._apps[GUI_WX]._in_event_loop = False
230 230 self.clear_inputhook()
231 231
232 232 def enable_qt4(self, app=None):
233 233 """Enable event loop integration with PyQt4.
234 234
235 235 Parameters
236 236 ----------
237 237 app : Qt Application, optional.
238 238 Running application to use. If not given, we probe Qt for an
239 239 existing application object, and create a new one if none is found.
240 240
241 241 Notes
242 242 -----
243 243 This methods sets the PyOS_InputHook for PyQt4, which allows
244 244 the PyQt4 to integrate with terminal based applications like
245 245 IPython.
246 246
247 247 If ``app`` is not given we probe for an existing one, and return it if
248 248 found. If no existing app is found, we create an :class:`QApplication`
249 249 as follows::
250 250
251 251 from PyQt4 import QtCore
252 252 app = QtGui.QApplication(sys.argv)
253 253 """
254 254 from IPython.lib.inputhookqt4 import create_inputhook_qt4
255 255 app, inputhook_qt4 = create_inputhook_qt4(self, app)
256 256 self.set_inputhook(inputhook_qt4)
257 257
258 258 self._current_gui = GUI_QT4
259 259 app._in_event_loop = True
260 260 self._apps[GUI_QT4] = app
261 261 return app
262 262
263 263 def disable_qt4(self):
264 264 """Disable event loop integration with PyQt4.
265 265
266 266 This merely sets PyOS_InputHook to NULL.
267 267 """
268 if self._apps.has_key(GUI_QT4):
268 if GUI_QT4 in self._apps:
269 269 self._apps[GUI_QT4]._in_event_loop = False
270 270 self.clear_inputhook()
271 271
272 272 def enable_gtk(self, app=None):
273 273 """Enable event loop integration with PyGTK.
274 274
275 275 Parameters
276 276 ----------
277 277 app : ignored
278 278 Ignored, it's only a placeholder to keep the call signature of all
279 279 gui activation methods consistent, which simplifies the logic of
280 280 supporting magics.
281 281
282 282 Notes
283 283 -----
284 284 This methods sets the PyOS_InputHook for PyGTK, which allows
285 285 the PyGTK to integrate with terminal based applications like
286 286 IPython.
287 287 """
288 288 import gtk
289 289 try:
290 290 gtk.set_interactive(True)
291 291 self._current_gui = GUI_GTK
292 292 except AttributeError:
293 293 # For older versions of gtk, use our own ctypes version
294 294 from IPython.lib.inputhookgtk import inputhook_gtk
295 295 self.set_inputhook(inputhook_gtk)
296 296 self._current_gui = GUI_GTK
297 297
298 298 def disable_gtk(self):
299 299 """Disable event loop integration with PyGTK.
300 300
301 301 This merely sets PyOS_InputHook to NULL.
302 302 """
303 303 self.clear_inputhook()
304 304
305 305 def enable_tk(self, app=None):
306 306 """Enable event loop integration with Tk.
307 307
308 308 Parameters
309 309 ----------
310 310 app : toplevel :class:`Tkinter.Tk` widget, optional.
311 311 Running toplevel widget to use. If not given, we probe Tk for an
312 312 existing one, and create a new one if none is found.
313 313
314 314 Notes
315 315 -----
316 316 If you have already created a :class:`Tkinter.Tk` object, the only
317 317 thing done by this method is to register with the
318 318 :class:`InputHookManager`, since creating that object automatically
319 319 sets ``PyOS_InputHook``.
320 320 """
321 321 self._current_gui = GUI_TK
322 322 if app is None:
323 323 import Tkinter
324 324 app = Tkinter.Tk()
325 325 app.withdraw()
326 326 self._apps[GUI_TK] = app
327 327 return app
328 328
329 329 def disable_tk(self):
330 330 """Disable event loop integration with Tkinter.
331 331
332 332 This merely sets PyOS_InputHook to NULL.
333 333 """
334 334 self.clear_inputhook()
335 335
336 336
337 337 def enable_glut(self, app=None):
338 338 """ Enable event loop integration with GLUT.
339 339
340 340 Parameters
341 341 ----------
342 342
343 343 app : ignored
344 344 Ignored, it's only a placeholder to keep the call signature of all
345 345 gui activation methods consistent, which simplifies the logic of
346 346 supporting magics.
347 347
348 348 Notes
349 349 -----
350 350
351 351 This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to
352 352 integrate with terminal based applications like IPython. Due to GLUT
353 353 limitations, it is currently not possible to start the event loop
354 354 without first creating a window. You should thus not create another
355 355 window but use instead the created one. See 'gui-glut.py' in the
356 356 docs/examples/lib directory.
357 357
358 358 The default screen mode is set to:
359 359 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
360 360 """
361 361
362 362 import OpenGL.GLUT as glut
363 363 from IPython.lib.inputhookglut import glut_display_mode, \
364 364 glut_close, glut_display, \
365 365 glut_idle, inputhook_glut
366 366
367 if not self._apps.has_key( GUI_GLUT ):
367 if GUI_GLUT not in self._apps:
368 368 glut.glutInit( sys.argv )
369 369 glut.glutInitDisplayMode( glut_display_mode )
370 370 # This is specific to freeglut
371 371 if bool(glut.glutSetOption):
372 372 glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
373 373 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
374 374 glut.glutCreateWindow( sys.argv[0] )
375 375 glut.glutReshapeWindow( 1, 1 )
376 376 glut.glutHideWindow( )
377 377 glut.glutWMCloseFunc( glut_close )
378 378 glut.glutDisplayFunc( glut_display )
379 379 glut.glutIdleFunc( glut_idle )
380 380 else:
381 381 glut.glutWMCloseFunc( glut_close )
382 382 glut.glutDisplayFunc( glut_display )
383 383 glut.glutIdleFunc( glut_idle)
384 384 self.set_inputhook( inputhook_glut )
385 385 self._current_gui = GUI_GLUT
386 386 self._apps[GUI_GLUT] = True
387 387
388 388
389 389 def disable_glut(self):
390 390 """Disable event loop integration with glut.
391 391
392 392 This sets PyOS_InputHook to NULL and set the display function to a
393 393 dummy one and set the timer to a dummy timer that will be triggered
394 394 very far in the future.
395 395 """
396 396 import OpenGL.GLUT as glut
397 397 from glut_support import glutMainLoopEvent
398 398
399 399 glut.glutHideWindow() # This is an event to be processed below
400 400 glutMainLoopEvent()
401 401 self.clear_inputhook()
402 402
403 403 def enable_pyglet(self, app=None):
404 404 """Enable event loop integration with pyglet.
405 405
406 406 Parameters
407 407 ----------
408 408 app : ignored
409 409 Ignored, it's only a placeholder to keep the call signature of all
410 410 gui activation methods consistent, which simplifies the logic of
411 411 supporting magics.
412 412
413 413 Notes
414 414 -----
415 415 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
416 416 pyglet to integrate with terminal based applications like
417 417 IPython.
418 418
419 419 """
420 420 import pyglet
421 421 from IPython.lib.inputhookpyglet import inputhook_pyglet
422 422 self.set_inputhook(inputhook_pyglet)
423 423 self._current_gui = GUI_PYGLET
424 424 return app
425 425
426 426 def disable_pyglet(self):
427 427 """Disable event loop integration with pyglet.
428 428
429 429 This merely sets PyOS_InputHook to NULL.
430 430 """
431 431 self.clear_inputhook()
432 432
433 433 def enable_gtk3(self, app=None):
434 434 """Enable event loop integration with Gtk3 (gir bindings).
435 435
436 436 Parameters
437 437 ----------
438 438 app : ignored
439 439 Ignored, it's only a placeholder to keep the call signature of all
440 440 gui activation methods consistent, which simplifies the logic of
441 441 supporting magics.
442 442
443 443 Notes
444 444 -----
445 445 This methods sets the PyOS_InputHook for Gtk3, which allows
446 446 the Gtk3 to integrate with terminal based applications like
447 447 IPython.
448 448 """
449 449 from IPython.lib.inputhookgtk3 import inputhook_gtk3
450 450 self.set_inputhook(inputhook_gtk3)
451 451 self._current_gui = GUI_GTK
452 452
453 453 def disable_gtk3(self):
454 454 """Disable event loop integration with PyGTK.
455 455
456 456 This merely sets PyOS_InputHook to NULL.
457 457 """
458 458 self.clear_inputhook()
459 459
460 460 def current_gui(self):
461 461 """Return a string indicating the currently active GUI or None."""
462 462 return self._current_gui
463 463
464 464 inputhook_manager = InputHookManager()
465 465
466 466 enable_wx = inputhook_manager.enable_wx
467 467 disable_wx = inputhook_manager.disable_wx
468 468 enable_qt4 = inputhook_manager.enable_qt4
469 469 disable_qt4 = inputhook_manager.disable_qt4
470 470 enable_gtk = inputhook_manager.enable_gtk
471 471 disable_gtk = inputhook_manager.disable_gtk
472 472 enable_tk = inputhook_manager.enable_tk
473 473 disable_tk = inputhook_manager.disable_tk
474 474 enable_glut = inputhook_manager.enable_glut
475 475 disable_glut = inputhook_manager.disable_glut
476 476 enable_pyglet = inputhook_manager.enable_pyglet
477 477 disable_pyglet = inputhook_manager.disable_pyglet
478 478 enable_gtk3 = inputhook_manager.enable_gtk3
479 479 disable_gtk3 = inputhook_manager.disable_gtk3
480 480 clear_inputhook = inputhook_manager.clear_inputhook
481 481 set_inputhook = inputhook_manager.set_inputhook
482 482 current_gui = inputhook_manager.current_gui
483 483 clear_app_refs = inputhook_manager.clear_app_refs
484 484
485 485
486 486 # Convenience function to switch amongst them
487 487 def enable_gui(gui=None, app=None):
488 488 """Switch amongst GUI input hooks by name.
489 489
490 490 This is just a utility wrapper around the methods of the InputHookManager
491 491 object.
492 492
493 493 Parameters
494 494 ----------
495 495 gui : optional, string or None
496 496 If None (or 'none'), clears input hook, otherwise it must be one
497 497 of the recognized GUI names (see ``GUI_*`` constants in module).
498 498
499 499 app : optional, existing application object.
500 500 For toolkits that have the concept of a global app, you can supply an
501 501 existing one. If not given, the toolkit will be probed for one, and if
502 502 none is found, a new one will be created. Note that GTK does not have
503 503 this concept, and passing an app if `gui`=="GTK" will raise an error.
504 504
505 505 Returns
506 506 -------
507 507 The output of the underlying gui switch routine, typically the actual
508 508 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
509 509 one.
510 510 """
511 511 guis = {None: clear_inputhook,
512 512 GUI_NONE: clear_inputhook,
513 513 GUI_OSX: lambda app=False: None,
514 514 GUI_TK: enable_tk,
515 515 GUI_GTK: enable_gtk,
516 516 GUI_WX: enable_wx,
517 517 GUI_QT: enable_qt4, # qt3 not supported
518 518 GUI_QT4: enable_qt4,
519 519 GUI_GLUT: enable_glut,
520 520 GUI_PYGLET: enable_pyglet,
521 521 GUI_GTK3: enable_gtk3,
522 522 }
523 523 try:
524 524 gui_hook = guis[gui]
525 525 except KeyError:
526 526 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
527 527 raise ValueError(e)
528 528 return gui_hook(app)
529 529
@@ -1,220 +1,220 b''
1 1 """A Task logger that presents our DB interface,
2 2 but exists entirely in memory and implemented with dicts.
3 3
4 4 Authors:
5 5
6 6 * Min RK
7 7
8 8
9 9 TaskRecords are dicts of the form:
10 10 {
11 11 'msg_id' : str(uuid),
12 12 'client_uuid' : str(uuid),
13 13 'engine_uuid' : str(uuid) or None,
14 14 'header' : dict(header),
15 15 'content': dict(content),
16 16 'buffers': list(buffers),
17 17 'submitted': datetime,
18 18 'started': datetime or None,
19 19 'completed': datetime or None,
20 20 'resubmitted': datetime or None,
21 21 'result_header' : dict(header) or None,
22 22 'result_content' : dict(content) or None,
23 23 'result_buffers' : list(buffers) or None,
24 24 }
25 25 With this info, many of the special categories of tasks can be defined by query:
26 26
27 27 pending: completed is None
28 28 client's outstanding: client_uuid = uuid && completed is None
29 29 MIA: arrived is None (and completed is None)
30 30 etc.
31 31
32 32 EngineRecords are dicts of the form:
33 33 {
34 34 'eid' : int(id),
35 35 'uuid': str(uuid)
36 36 }
37 37 This may be extended, but is currently.
38 38
39 39 We support a subset of mongodb operators:
40 40 $lt,$gt,$lte,$gte,$ne,$in,$nin,$all,$mod,$exists
41 41 """
42 42 #-----------------------------------------------------------------------------
43 43 # Copyright (C) 2010-2011 The IPython Development Team
44 44 #
45 45 # Distributed under the terms of the BSD License. The full license is in
46 46 # the file COPYING, distributed as part of this software.
47 47 #-----------------------------------------------------------------------------
48 48
49 49 from copy import deepcopy as copy
50 50 from datetime import datetime
51 51
52 52 from IPython.config.configurable import LoggingConfigurable
53 53
54 54 from IPython.utils.traitlets import Dict, Unicode, Instance
55 55
56 56 filters = {
57 57 '$lt' : lambda a,b: a < b,
58 58 '$gt' : lambda a,b: b > a,
59 59 '$eq' : lambda a,b: a == b,
60 60 '$ne' : lambda a,b: a != b,
61 61 '$lte': lambda a,b: a <= b,
62 62 '$gte': lambda a,b: a >= b,
63 63 '$in' : lambda a,b: a in b,
64 64 '$nin': lambda a,b: a not in b,
65 65 '$all': lambda a,b: all([ a in bb for bb in b ]),
66 66 '$mod': lambda a,b: a%b[0] == b[1],
67 67 '$exists' : lambda a,b: (b and a is not None) or (a is None and not b)
68 68 }
69 69
70 70
71 71 class CompositeFilter(object):
72 72 """Composite filter for matching multiple properties."""
73 73
74 74 def __init__(self, dikt):
75 75 self.tests = []
76 76 self.values = []
77 77 for key, value in dikt.iteritems():
78 78 self.tests.append(filters[key])
79 79 self.values.append(value)
80 80
81 81 def __call__(self, value):
82 82 for test,check in zip(self.tests, self.values):
83 83 if not test(value, check):
84 84 return False
85 85 return True
86 86
87 87 class BaseDB(LoggingConfigurable):
88 88 """Empty Parent class so traitlets work on DB."""
89 89 # base configurable traits:
90 90 session = Unicode("")
91 91
92 92 class DictDB(BaseDB):
93 93 """Basic in-memory dict-based object for saving Task Records.
94 94
95 95 This is the first object to present the DB interface
96 96 for logging tasks out of memory.
97 97
98 98 The interface is based on MongoDB, so adding a MongoDB
99 99 backend should be straightforward.
100 100 """
101 101
102 102 _records = Dict()
103 103
104 104 def _match_one(self, rec, tests):
105 105 """Check if a specific record matches tests."""
106 106 for key,test in tests.iteritems():
107 107 if not test(rec.get(key, None)):
108 108 return False
109 109 return True
110 110
111 111 def _match(self, check):
112 112 """Find all the matches for a check dict."""
113 113 matches = []
114 114 tests = {}
115 115 for k,v in check.iteritems():
116 116 if isinstance(v, dict):
117 117 tests[k] = CompositeFilter(v)
118 118 else:
119 119 tests[k] = lambda o: o==v
120 120
121 121 for rec in self._records.itervalues():
122 122 if self._match_one(rec, tests):
123 123 matches.append(copy(rec))
124 124 return matches
125 125
126 126 def _extract_subdict(self, rec, keys):
127 127 """extract subdict of keys"""
128 128 d = {}
129 129 d['msg_id'] = rec['msg_id']
130 130 for key in keys:
131 131 d[key] = rec[key]
132 132 return copy(d)
133 133
134 134 def add_record(self, msg_id, rec):
135 135 """Add a new Task Record, by msg_id."""
136 if self._records.has_key(msg_id):
136 if msg_id in self._records:
137 137 raise KeyError("Already have msg_id %r"%(msg_id))
138 138 self._records[msg_id] = rec
139 139
140 140 def get_record(self, msg_id):
141 141 """Get a specific Task Record, by msg_id."""
142 142 if not msg_id in self._records:
143 143 raise KeyError("No such msg_id %r"%(msg_id))
144 144 return copy(self._records[msg_id])
145 145
146 146 def update_record(self, msg_id, rec):
147 147 """Update the data in an existing record."""
148 148 self._records[msg_id].update(rec)
149 149
150 150 def drop_matching_records(self, check):
151 151 """Remove a record from the DB."""
152 152 matches = self._match(check)
153 153 for m in matches:
154 154 del self._records[m['msg_id']]
155 155
156 156 def drop_record(self, msg_id):
157 157 """Remove a record from the DB."""
158 158 del self._records[msg_id]
159 159
160 160
161 161 def find_records(self, check, keys=None):
162 162 """Find records matching a query dict, optionally extracting subset of keys.
163 163
164 164 Returns dict keyed by msg_id of matching records.
165 165
166 166 Parameters
167 167 ----------
168 168
169 169 check: dict
170 170 mongodb-style query argument
171 171 keys: list of strs [optional]
172 172 if specified, the subset of keys to extract. msg_id will *always* be
173 173 included.
174 174 """
175 175 matches = self._match(check)
176 176 if keys:
177 177 return [ self._extract_subdict(rec, keys) for rec in matches ]
178 178 else:
179 179 return matches
180 180
181 181
182 182 def get_history(self):
183 183 """get all msg_ids, ordered by time submitted."""
184 184 msg_ids = self._records.keys()
185 185 return sorted(msg_ids, key=lambda m: self._records[m]['submitted'])
186 186
187 187 NODATA = KeyError("NoDB backend doesn't store any data. "
188 188 "Start the Controller with a DB backend to enable resubmission / result persistence."
189 189 )
190 190
191 191 class NoDB(DictDB):
192 192 """A blackhole db backend that actually stores no information.
193 193
194 194 Provides the full DB interface, but raises KeyErrors on any
195 195 method that tries to access the records. This can be used to
196 196 minimize the memory footprint of the Hub when its record-keeping
197 197 functionality is not required.
198 198 """
199 199
200 200 def add_record(self, msg_id, record):
201 201 pass
202 202
203 203 def get_record(self, msg_id):
204 204 raise NODATA
205 205
206 206 def update_record(self, msg_id, record):
207 207 pass
208 208
209 209 def drop_matching_records(self, check):
210 210 pass
211 211
212 212 def drop_record(self, msg_id):
213 213 pass
214 214
215 215 def find_records(self, check, keys=None):
216 216 raise NODATA
217 217
218 218 def get_history(self):
219 219 raise NODATA
220 220
@@ -1,358 +1,358 b''
1 1 """some generic utilities for dealing with classes, urls, and serialization
2 2
3 3 Authors:
4 4
5 5 * Min RK
6 6 """
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2010-2011 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
18 18 # Standard library imports.
19 19 import logging
20 20 import os
21 21 import re
22 22 import stat
23 23 import socket
24 24 import sys
25 25 from signal import signal, SIGINT, SIGABRT, SIGTERM
26 26 try:
27 27 from signal import SIGKILL
28 28 except ImportError:
29 29 SIGKILL=None
30 30
31 31 try:
32 32 import cPickle
33 33 pickle = cPickle
34 34 except:
35 35 cPickle = None
36 36 import pickle
37 37
38 38 # System library imports
39 39 import zmq
40 40 from zmq.log import handlers
41 41
42 42 from IPython.external.decorator import decorator
43 43
44 44 # IPython imports
45 45 from IPython.config.application import Application
46 46 from IPython.utils import py3compat
47 47 from IPython.utils.pickleutil import can, uncan, canSequence, uncanSequence
48 48 from IPython.utils.newserialized import serialize, unserialize
49 49 from IPython.zmq.log import EnginePUBHandler
50 50 from IPython.zmq.serialize import (
51 51 unserialize_object, serialize_object, pack_apply_message, unpack_apply_message
52 52 )
53 53
54 54 if py3compat.PY3:
55 55 buffer = memoryview
56 56
57 57 #-----------------------------------------------------------------------------
58 58 # Classes
59 59 #-----------------------------------------------------------------------------
60 60
61 61 class Namespace(dict):
62 62 """Subclass of dict for attribute access to keys."""
63 63
64 64 def __getattr__(self, key):
65 65 """getattr aliased to getitem"""
66 66 if key in self.iterkeys():
67 67 return self[key]
68 68 else:
69 69 raise NameError(key)
70 70
71 71 def __setattr__(self, key, value):
72 72 """setattr aliased to setitem, with strict"""
73 73 if hasattr(dict, key):
74 74 raise KeyError("Cannot override dict keys %r"%key)
75 75 self[key] = value
76 76
77 77
78 78 class ReverseDict(dict):
79 79 """simple double-keyed subset of dict methods."""
80 80
81 81 def __init__(self, *args, **kwargs):
82 82 dict.__init__(self, *args, **kwargs)
83 83 self._reverse = dict()
84 84 for key, value in self.iteritems():
85 85 self._reverse[value] = key
86 86
87 87 def __getitem__(self, key):
88 88 try:
89 89 return dict.__getitem__(self, key)
90 90 except KeyError:
91 91 return self._reverse[key]
92 92
93 93 def __setitem__(self, key, value):
94 94 if key in self._reverse:
95 95 raise KeyError("Can't have key %r on both sides!"%key)
96 96 dict.__setitem__(self, key, value)
97 97 self._reverse[value] = key
98 98
99 99 def pop(self, key):
100 100 value = dict.pop(self, key)
101 101 self._reverse.pop(value)
102 102 return value
103 103
104 104 def get(self, key, default=None):
105 105 try:
106 106 return self[key]
107 107 except KeyError:
108 108 return default
109 109
110 110 #-----------------------------------------------------------------------------
111 111 # Functions
112 112 #-----------------------------------------------------------------------------
113 113
114 114 @decorator
115 115 def log_errors(f, self, *args, **kwargs):
116 116 """decorator to log unhandled exceptions raised in a method.
117 117
118 118 For use wrapping on_recv callbacks, so that exceptions
119 119 do not cause the stream to be closed.
120 120 """
121 121 try:
122 122 return f(self, *args, **kwargs)
123 123 except Exception:
124 124 self.log.error("Uncaught exception in %r" % f, exc_info=True)
125 125
126 126
127 127 def is_url(url):
128 128 """boolean check for whether a string is a zmq url"""
129 129 if '://' not in url:
130 130 return False
131 131 proto, addr = url.split('://', 1)
132 132 if proto.lower() not in ['tcp','pgm','epgm','ipc','inproc']:
133 133 return False
134 134 return True
135 135
136 136 def validate_url(url):
137 137 """validate a url for zeromq"""
138 138 if not isinstance(url, basestring):
139 139 raise TypeError("url must be a string, not %r"%type(url))
140 140 url = url.lower()
141 141
142 142 proto_addr = url.split('://')
143 143 assert len(proto_addr) == 2, 'Invalid url: %r'%url
144 144 proto, addr = proto_addr
145 145 assert proto in ['tcp','pgm','epgm','ipc','inproc'], "Invalid protocol: %r"%proto
146 146
147 147 # domain pattern adapted from http://www.regexlib.com/REDetails.aspx?regexp_id=391
148 148 # author: Remi Sabourin
149 149 pat = re.compile(r'^([\w\d]([\w\d\-]{0,61}[\w\d])?\.)*[\w\d]([\w\d\-]{0,61}[\w\d])?$')
150 150
151 151 if proto == 'tcp':
152 152 lis = addr.split(':')
153 153 assert len(lis) == 2, 'Invalid url: %r'%url
154 154 addr,s_port = lis
155 155 try:
156 156 port = int(s_port)
157 157 except ValueError:
158 158 raise AssertionError("Invalid port %r in url: %r"%(port, url))
159 159
160 160 assert addr == '*' or pat.match(addr) is not None, 'Invalid url: %r'%url
161 161
162 162 else:
163 163 # only validate tcp urls currently
164 164 pass
165 165
166 166 return True
167 167
168 168
169 169 def validate_url_container(container):
170 170 """validate a potentially nested collection of urls."""
171 171 if isinstance(container, basestring):
172 172 url = container
173 173 return validate_url(url)
174 174 elif isinstance(container, dict):
175 175 container = container.itervalues()
176 176
177 177 for element in container:
178 178 validate_url_container(element)
179 179
180 180
181 181 def split_url(url):
182 182 """split a zmq url (tcp://ip:port) into ('tcp','ip','port')."""
183 183 proto_addr = url.split('://')
184 184 assert len(proto_addr) == 2, 'Invalid url: %r'%url
185 185 proto, addr = proto_addr
186 186 lis = addr.split(':')
187 187 assert len(lis) == 2, 'Invalid url: %r'%url
188 188 addr,s_port = lis
189 189 return proto,addr,s_port
190 190
191 191 def disambiguate_ip_address(ip, location=None):
192 192 """turn multi-ip interfaces '0.0.0.0' and '*' into connectable
193 193 ones, based on the location (default interpretation of location is localhost)."""
194 194 if ip in ('0.0.0.0', '*'):
195 195 try:
196 196 external_ips = socket.gethostbyname_ex(socket.gethostname())[2]
197 197 except (socket.gaierror, IndexError):
198 198 # couldn't identify this machine, assume localhost
199 199 external_ips = []
200 200 if location is None or location in external_ips or not external_ips:
201 201 # If location is unspecified or cannot be determined, assume local
202 202 ip='127.0.0.1'
203 203 elif location:
204 204 return location
205 205 return ip
206 206
207 207 def disambiguate_url(url, location=None):
208 208 """turn multi-ip interfaces '0.0.0.0' and '*' into connectable
209 209 ones, based on the location (default interpretation is localhost).
210 210
211 211 This is for zeromq urls, such as tcp://*:10101."""
212 212 try:
213 213 proto,ip,port = split_url(url)
214 214 except AssertionError:
215 215 # probably not tcp url; could be ipc, etc.
216 216 return url
217 217
218 218 ip = disambiguate_ip_address(ip,location)
219 219
220 220 return "%s://%s:%s"%(proto,ip,port)
221 221
222 222
223 223 #--------------------------------------------------------------------------
224 224 # helpers for implementing old MEC API via view.apply
225 225 #--------------------------------------------------------------------------
226 226
227 227 def interactive(f):
228 228 """decorator for making functions appear as interactively defined.
229 229 This results in the function being linked to the user_ns as globals()
230 230 instead of the module globals().
231 231 """
232 232 f.__module__ = '__main__'
233 233 return f
234 234
235 235 @interactive
236 236 def _push(**ns):
237 237 """helper method for implementing `client.push` via `client.apply`"""
238 238 globals().update(ns)
239 239
240 240 @interactive
241 241 def _pull(keys):
242 242 """helper method for implementing `client.pull` via `client.apply`"""
243 243 user_ns = globals()
244 244 if isinstance(keys, (list,tuple, set)):
245 245 for key in keys:
246 if not user_ns.has_key(key):
246 if key not in user_ns:
247 247 raise NameError("name '%s' is not defined"%key)
248 248 return map(user_ns.get, keys)
249 249 else:
250 if not user_ns.has_key(keys):
250 if keys not in user_ns:
251 251 raise NameError("name '%s' is not defined"%keys)
252 252 return user_ns.get(keys)
253 253
254 254 @interactive
255 255 def _execute(code):
256 256 """helper method for implementing `client.execute` via `client.apply`"""
257 257 exec code in globals()
258 258
259 259 #--------------------------------------------------------------------------
260 260 # extra process management utilities
261 261 #--------------------------------------------------------------------------
262 262
263 263 _random_ports = set()
264 264
265 265 def select_random_ports(n):
266 266 """Selects and return n random ports that are available."""
267 267 ports = []
268 268 for i in xrange(n):
269 269 sock = socket.socket()
270 270 sock.bind(('', 0))
271 271 while sock.getsockname()[1] in _random_ports:
272 272 sock.close()
273 273 sock = socket.socket()
274 274 sock.bind(('', 0))
275 275 ports.append(sock)
276 276 for i, sock in enumerate(ports):
277 277 port = sock.getsockname()[1]
278 278 sock.close()
279 279 ports[i] = port
280 280 _random_ports.add(port)
281 281 return ports
282 282
283 283 def signal_children(children):
284 284 """Relay interupt/term signals to children, for more solid process cleanup."""
285 285 def terminate_children(sig, frame):
286 286 log = Application.instance().log
287 287 log.critical("Got signal %i, terminating children..."%sig)
288 288 for child in children:
289 289 child.terminate()
290 290
291 291 sys.exit(sig != SIGINT)
292 292 # sys.exit(sig)
293 293 for sig in (SIGINT, SIGABRT, SIGTERM):
294 294 signal(sig, terminate_children)
295 295
296 296 def generate_exec_key(keyfile):
297 297 import uuid
298 298 newkey = str(uuid.uuid4())
299 299 with open(keyfile, 'w') as f:
300 300 # f.write('ipython-key ')
301 301 f.write(newkey+'\n')
302 302 # set user-only RW permissions (0600)
303 303 # this will have no effect on Windows
304 304 os.chmod(keyfile, stat.S_IRUSR|stat.S_IWUSR)
305 305
306 306
307 307 def integer_loglevel(loglevel):
308 308 try:
309 309 loglevel = int(loglevel)
310 310 except ValueError:
311 311 if isinstance(loglevel, str):
312 312 loglevel = getattr(logging, loglevel)
313 313 return loglevel
314 314
315 315 def connect_logger(logname, context, iface, root="ip", loglevel=logging.DEBUG):
316 316 logger = logging.getLogger(logname)
317 317 if any([isinstance(h, handlers.PUBHandler) for h in logger.handlers]):
318 318 # don't add a second PUBHandler
319 319 return
320 320 loglevel = integer_loglevel(loglevel)
321 321 lsock = context.socket(zmq.PUB)
322 322 lsock.connect(iface)
323 323 handler = handlers.PUBHandler(lsock)
324 324 handler.setLevel(loglevel)
325 325 handler.root_topic = root
326 326 logger.addHandler(handler)
327 327 logger.setLevel(loglevel)
328 328
329 329 def connect_engine_logger(context, iface, engine, loglevel=logging.DEBUG):
330 330 logger = logging.getLogger()
331 331 if any([isinstance(h, handlers.PUBHandler) for h in logger.handlers]):
332 332 # don't add a second PUBHandler
333 333 return
334 334 loglevel = integer_loglevel(loglevel)
335 335 lsock = context.socket(zmq.PUB)
336 336 lsock.connect(iface)
337 337 handler = EnginePUBHandler(engine, lsock)
338 338 handler.setLevel(loglevel)
339 339 logger.addHandler(handler)
340 340 logger.setLevel(loglevel)
341 341 return logger
342 342
343 343 def local_logger(logname, loglevel=logging.DEBUG):
344 344 loglevel = integer_loglevel(loglevel)
345 345 logger = logging.getLogger(logname)
346 346 if any([isinstance(h, logging.StreamHandler) for h in logger.handlers]):
347 347 # don't add a second StreamHandler
348 348 return
349 349 handler = logging.StreamHandler()
350 350 handler.setLevel(loglevel)
351 351 formatter = logging.Formatter("%(asctime)s.%(msecs).03d [%(name)s] %(message)s",
352 352 datefmt="%Y-%m-%d %H:%M:%S")
353 353 handler.setFormatter(formatter)
354 354
355 355 logger.addHandler(handler)
356 356 logger.setLevel(loglevel)
357 357 return logger
358 358
@@ -1,393 +1,393 b''
1 1 # encoding: utf-8
2 2 """A dict subclass that supports attribute style access.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez (original)
7 7 * Brian Granger (refactoring to a dict subclass)
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 from IPython.utils.data import list2dict2
22 22
23 23 __all__ = ['Struct']
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Code
27 27 #-----------------------------------------------------------------------------
28 28
29 29
30 30 class Struct(dict):
31 31 """A dict subclass with attribute style access.
32 32
33 33 This dict subclass has a a few extra features:
34 34
35 35 * Attribute style access.
36 36 * Protection of class members (like keys, items) when using attribute
37 37 style access.
38 38 * The ability to restrict assignment to only existing keys.
39 39 * Intelligent merging.
40 40 * Overloaded operators.
41 41 """
42 42 _allownew = True
43 43 def __init__(self, *args, **kw):
44 44 """Initialize with a dictionary, another Struct, or data.
45 45
46 46 Parameters
47 47 ----------
48 48 args : dict, Struct
49 49 Initialize with one dict or Struct
50 50 kw : dict
51 51 Initialize with key, value pairs.
52 52
53 53 Examples
54 54 --------
55 55
56 56 >>> s = Struct(a=10,b=30)
57 57 >>> s.a
58 58 10
59 59 >>> s.b
60 60 30
61 61 >>> s2 = Struct(s,c=30)
62 62 >>> sorted(s2.keys())
63 63 ['a', 'b', 'c']
64 64 """
65 65 object.__setattr__(self, '_allownew', True)
66 66 dict.__init__(self, *args, **kw)
67 67
68 68 def __setitem__(self, key, value):
69 69 """Set an item with check for allownew.
70 70
71 71 Examples
72 72 --------
73 73
74 74 >>> s = Struct()
75 75 >>> s['a'] = 10
76 76 >>> s.allow_new_attr(False)
77 77 >>> s['a'] = 10
78 78 >>> s['a']
79 79 10
80 80 >>> try:
81 81 ... s['b'] = 20
82 82 ... except KeyError:
83 83 ... print 'this is not allowed'
84 84 ...
85 85 this is not allowed
86 86 """
87 if not self._allownew and not self.has_key(key):
87 if not self._allownew and key not in self:
88 88 raise KeyError(
89 89 "can't create new attribute %s when allow_new_attr(False)" % key)
90 90 dict.__setitem__(self, key, value)
91 91
92 92 def __setattr__(self, key, value):
93 93 """Set an attr with protection of class members.
94 94
95 95 This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to
96 96 :exc:`AttributeError`.
97 97
98 98 Examples
99 99 --------
100 100
101 101 >>> s = Struct()
102 102 >>> s.a = 10
103 103 >>> s.a
104 104 10
105 105 >>> try:
106 106 ... s.get = 10
107 107 ... except AttributeError:
108 108 ... print "you can't set a class member"
109 109 ...
110 110 you can't set a class member
111 111 """
112 112 # If key is an str it might be a class member or instance var
113 113 if isinstance(key, str):
114 114 # I can't simply call hasattr here because it calls getattr, which
115 115 # calls self.__getattr__, which returns True for keys in
116 116 # self._data. But I only want keys in the class and in
117 117 # self.__dict__
118 118 if key in self.__dict__ or hasattr(Struct, key):
119 119 raise AttributeError(
120 120 'attr %s is a protected member of class Struct.' % key
121 121 )
122 122 try:
123 123 self.__setitem__(key, value)
124 124 except KeyError as e:
125 125 raise AttributeError(e)
126 126
127 127 def __getattr__(self, key):
128 128 """Get an attr by calling :meth:`dict.__getitem__`.
129 129
130 130 Like :meth:`__setattr__`, this method converts :exc:`KeyError` to
131 131 :exc:`AttributeError`.
132 132
133 133 Examples
134 134 --------
135 135
136 136 >>> s = Struct(a=10)
137 137 >>> s.a
138 138 10
139 139 >>> type(s.get)
140 140 <... 'builtin_function_or_method'>
141 141 >>> try:
142 142 ... s.b
143 143 ... except AttributeError:
144 144 ... print "I don't have that key"
145 145 ...
146 146 I don't have that key
147 147 """
148 148 try:
149 149 result = self[key]
150 150 except KeyError:
151 151 raise AttributeError(key)
152 152 else:
153 153 return result
154 154
155 155 def __iadd__(self, other):
156 156 """s += s2 is a shorthand for s.merge(s2).
157 157
158 158 Examples
159 159 --------
160 160
161 161 >>> s = Struct(a=10,b=30)
162 162 >>> s2 = Struct(a=20,c=40)
163 163 >>> s += s2
164 164 >>> sorted(s.keys())
165 165 ['a', 'b', 'c']
166 166 """
167 167 self.merge(other)
168 168 return self
169 169
170 170 def __add__(self,other):
171 171 """s + s2 -> New Struct made from s.merge(s2).
172 172
173 173 Examples
174 174 --------
175 175
176 176 >>> s1 = Struct(a=10,b=30)
177 177 >>> s2 = Struct(a=20,c=40)
178 178 >>> s = s1 + s2
179 179 >>> sorted(s.keys())
180 180 ['a', 'b', 'c']
181 181 """
182 182 sout = self.copy()
183 183 sout.merge(other)
184 184 return sout
185 185
186 186 def __sub__(self,other):
187 187 """s1 - s2 -> remove keys in s2 from s1.
188 188
189 189 Examples
190 190 --------
191 191
192 192 >>> s1 = Struct(a=10,b=30)
193 193 >>> s2 = Struct(a=40)
194 194 >>> s = s1 - s2
195 195 >>> s
196 196 {'b': 30}
197 197 """
198 198 sout = self.copy()
199 199 sout -= other
200 200 return sout
201 201
202 202 def __isub__(self,other):
203 203 """Inplace remove keys from self that are in other.
204 204
205 205 Examples
206 206 --------
207 207
208 208 >>> s1 = Struct(a=10,b=30)
209 209 >>> s2 = Struct(a=40)
210 210 >>> s1 -= s2
211 211 >>> s1
212 212 {'b': 30}
213 213 """
214 214 for k in other.keys():
215 if self.has_key(k):
215 if k in self:
216 216 del self[k]
217 217 return self
218 218
219 219 def __dict_invert(self, data):
220 220 """Helper function for merge.
221 221
222 222 Takes a dictionary whose values are lists and returns a dict with
223 223 the elements of each list as keys and the original keys as values.
224 224 """
225 225 outdict = {}
226 226 for k,lst in data.items():
227 227 if isinstance(lst, str):
228 228 lst = lst.split()
229 229 for entry in lst:
230 230 outdict[entry] = k
231 231 return outdict
232 232
233 233 def dict(self):
234 234 return self
235 235
236 236 def copy(self):
237 237 """Return a copy as a Struct.
238 238
239 239 Examples
240 240 --------
241 241
242 242 >>> s = Struct(a=10,b=30)
243 243 >>> s2 = s.copy()
244 244 >>> type(s2) is Struct
245 245 True
246 246 """
247 247 return Struct(dict.copy(self))
248 248
249 249 def hasattr(self, key):
250 250 """hasattr function available as a method.
251 251
252 252 Implemented like has_key.
253 253
254 254 Examples
255 255 --------
256 256
257 257 >>> s = Struct(a=10)
258 258 >>> s.hasattr('a')
259 259 True
260 260 >>> s.hasattr('b')
261 261 False
262 262 >>> s.hasattr('get')
263 263 False
264 264 """
265 return self.has_key(key)
265 return key in self
266 266
267 267 def allow_new_attr(self, allow = True):
268 268 """Set whether new attributes can be created in this Struct.
269 269
270 270 This can be used to catch typos by verifying that the attribute user
271 271 tries to change already exists in this Struct.
272 272 """
273 273 object.__setattr__(self, '_allownew', allow)
274 274
275 275 def merge(self, __loc_data__=None, __conflict_solve=None, **kw):
276 276 """Merge two Structs with customizable conflict resolution.
277 277
278 278 This is similar to :meth:`update`, but much more flexible. First, a
279 279 dict is made from data+key=value pairs. When merging this dict with
280 280 the Struct S, the optional dictionary 'conflict' is used to decide
281 281 what to do.
282 282
283 283 If conflict is not given, the default behavior is to preserve any keys
284 284 with their current value (the opposite of the :meth:`update` method's
285 285 behavior).
286 286
287 287 Parameters
288 288 ----------
289 289 __loc_data : dict, Struct
290 290 The data to merge into self
291 291 __conflict_solve : dict
292 292 The conflict policy dict. The keys are binary functions used to
293 293 resolve the conflict and the values are lists of strings naming
294 294 the keys the conflict resolution function applies to. Instead of
295 295 a list of strings a space separated string can be used, like
296 296 'a b c'.
297 297 kw : dict
298 298 Additional key, value pairs to merge in
299 299
300 300 Notes
301 301 -----
302 302
303 303 The `__conflict_solve` dict is a dictionary of binary functions which will be used to
304 304 solve key conflicts. Here is an example::
305 305
306 306 __conflict_solve = dict(
307 307 func1=['a','b','c'],
308 308 func2=['d','e']
309 309 )
310 310
311 311 In this case, the function :func:`func1` will be used to resolve
312 312 keys 'a', 'b' and 'c' and the function :func:`func2` will be used for
313 313 keys 'd' and 'e'. This could also be written as::
314 314
315 315 __conflict_solve = dict(func1='a b c',func2='d e')
316 316
317 317 These functions will be called for each key they apply to with the
318 318 form::
319 319
320 320 func1(self['a'], other['a'])
321 321
322 322 The return value is used as the final merged value.
323 323
324 324 As a convenience, merge() provides five (the most commonly needed)
325 325 pre-defined policies: preserve, update, add, add_flip and add_s. The
326 326 easiest explanation is their implementation::
327 327
328 328 preserve = lambda old,new: old
329 329 update = lambda old,new: new
330 330 add = lambda old,new: old + new
331 331 add_flip = lambda old,new: new + old # note change of order!
332 332 add_s = lambda old,new: old + ' ' + new # only for str!
333 333
334 334 You can use those four words (as strings) as keys instead
335 335 of defining them as functions, and the merge method will substitute
336 336 the appropriate functions for you.
337 337
338 338 For more complicated conflict resolution policies, you still need to
339 339 construct your own functions.
340 340
341 341 Examples
342 342 --------
343 343
344 344 This show the default policy:
345 345
346 346 >>> s = Struct(a=10,b=30)
347 347 >>> s2 = Struct(a=20,c=40)
348 348 >>> s.merge(s2)
349 349 >>> sorted(s.items())
350 350 [('a', 10), ('b', 30), ('c', 40)]
351 351
352 352 Now, show how to specify a conflict dict:
353 353
354 354 >>> s = Struct(a=10,b=30)
355 355 >>> s2 = Struct(a=20,b=40)
356 356 >>> conflict = {'update':'a','add':'b'}
357 357 >>> s.merge(s2,conflict)
358 358 >>> sorted(s.items())
359 359 [('a', 20), ('b', 70)]
360 360 """
361 361
362 362 data_dict = dict(__loc_data__,**kw)
363 363
364 364 # policies for conflict resolution: two argument functions which return
365 365 # the value that will go in the new struct
366 366 preserve = lambda old,new: old
367 367 update = lambda old,new: new
368 368 add = lambda old,new: old + new
369 369 add_flip = lambda old,new: new + old # note change of order!
370 370 add_s = lambda old,new: old + ' ' + new
371 371
372 372 # default policy is to keep current keys when there's a conflict
373 373 conflict_solve = list2dict2(self.keys(), default = preserve)
374 374
375 375 # the conflict_solve dictionary is given by the user 'inverted': we
376 376 # need a name-function mapping, it comes as a function -> names
377 377 # dict. Make a local copy (b/c we'll make changes), replace user
378 378 # strings for the three builtin policies and invert it.
379 379 if __conflict_solve:
380 380 inv_conflict_solve_user = __conflict_solve.copy()
381 381 for name, func in [('preserve',preserve), ('update',update),
382 382 ('add',add), ('add_flip',add_flip),
383 383 ('add_s',add_s)]:
384 384 if name in inv_conflict_solve_user.keys():
385 385 inv_conflict_solve_user[func] = inv_conflict_solve_user[name]
386 386 del inv_conflict_solve_user[name]
387 387 conflict_solve.update(self.__dict_invert(inv_conflict_solve_user))
388 388 for key in data_dict:
389 389 if key not in self:
390 390 self[key] = data_dict[key]
391 391 else:
392 392 self[key] = conflict_solve[key](self[key],data_dict[key])
393 393
@@ -1,1427 +1,1427 b''
1 1 # encoding: utf-8
2 2 """
3 3 A lightweight Traits like module.
4 4
5 5 This is designed to provide a lightweight, simple, pure Python version of
6 6 many of the capabilities of enthought.traits. This includes:
7 7
8 8 * Validation
9 9 * Type specification with defaults
10 10 * Static and dynamic notification
11 11 * Basic predefined types
12 12 * An API that is similar to enthought.traits
13 13
14 14 We don't support:
15 15
16 16 * Delegation
17 17 * Automatic GUI generation
18 18 * A full set of trait types. Most importantly, we don't provide container
19 19 traits (list, dict, tuple) that can trigger notifications if their
20 20 contents change.
21 21 * API compatibility with enthought.traits
22 22
23 23 There are also some important difference in our design:
24 24
25 25 * enthought.traits does not validate default values. We do.
26 26
27 27 We choose to create this module because we need these capabilities, but
28 28 we need them to be pure Python so they work in all Python implementations,
29 29 including Jython and IronPython.
30 30
31 31 Authors:
32 32
33 33 * Brian Granger
34 34 * Enthought, Inc. Some of the code in this file comes from enthought.traits
35 35 and is licensed under the BSD license. Also, many of the ideas also come
36 36 from enthought.traits even though our implementation is very different.
37 37 """
38 38
39 39 #-----------------------------------------------------------------------------
40 40 # Copyright (C) 2008-2011 The IPython Development Team
41 41 #
42 42 # Distributed under the terms of the BSD License. The full license is in
43 43 # the file COPYING, distributed as part of this software.
44 44 #-----------------------------------------------------------------------------
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Imports
48 48 #-----------------------------------------------------------------------------
49 49
50 50
51 51 import inspect
52 52 import re
53 53 import sys
54 54 import types
55 55 from types import FunctionType
56 56 try:
57 57 from types import ClassType, InstanceType
58 58 ClassTypes = (ClassType, type)
59 59 except:
60 60 ClassTypes = (type,)
61 61
62 62 from .importstring import import_item
63 63 from IPython.utils import py3compat
64 64
65 65 SequenceTypes = (list, tuple, set, frozenset)
66 66
67 67 #-----------------------------------------------------------------------------
68 68 # Basic classes
69 69 #-----------------------------------------------------------------------------
70 70
71 71
72 72 class NoDefaultSpecified ( object ): pass
73 73 NoDefaultSpecified = NoDefaultSpecified()
74 74
75 75
76 76 class Undefined ( object ): pass
77 77 Undefined = Undefined()
78 78
79 79 class TraitError(Exception):
80 80 pass
81 81
82 82 #-----------------------------------------------------------------------------
83 83 # Utilities
84 84 #-----------------------------------------------------------------------------
85 85
86 86
87 87 def class_of ( object ):
88 88 """ Returns a string containing the class name of an object with the
89 89 correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image',
90 90 'a PlotValue').
91 91 """
92 92 if isinstance( object, basestring ):
93 93 return add_article( object )
94 94
95 95 return add_article( object.__class__.__name__ )
96 96
97 97
98 98 def add_article ( name ):
99 99 """ Returns a string containing the correct indefinite article ('a' or 'an')
100 100 prefixed to the specified string.
101 101 """
102 102 if name[:1].lower() in 'aeiou':
103 103 return 'an ' + name
104 104
105 105 return 'a ' + name
106 106
107 107
108 108 def repr_type(obj):
109 109 """ Return a string representation of a value and its type for readable
110 110 error messages.
111 111 """
112 112 the_type = type(obj)
113 113 if (not py3compat.PY3) and the_type is InstanceType:
114 114 # Old-style class.
115 115 the_type = obj.__class__
116 116 msg = '%r %r' % (obj, the_type)
117 117 return msg
118 118
119 119
120 120 def parse_notifier_name(name):
121 121 """Convert the name argument to a list of names.
122 122
123 123 Examples
124 124 --------
125 125
126 126 >>> parse_notifier_name('a')
127 127 ['a']
128 128 >>> parse_notifier_name(['a','b'])
129 129 ['a', 'b']
130 130 >>> parse_notifier_name(None)
131 131 ['anytrait']
132 132 """
133 133 if isinstance(name, str):
134 134 return [name]
135 135 elif name is None:
136 136 return ['anytrait']
137 137 elif isinstance(name, (list, tuple)):
138 138 for n in name:
139 139 assert isinstance(n, str), "names must be strings"
140 140 return name
141 141
142 142
143 143 class _SimpleTest:
144 144 def __init__ ( self, value ): self.value = value
145 145 def __call__ ( self, test ):
146 146 return test == self.value
147 147 def __repr__(self):
148 148 return "<SimpleTest(%r)" % self.value
149 149 def __str__(self):
150 150 return self.__repr__()
151 151
152 152
153 153 def getmembers(object, predicate=None):
154 154 """A safe version of inspect.getmembers that handles missing attributes.
155 155
156 156 This is useful when there are descriptor based attributes that for
157 157 some reason raise AttributeError even though they exist. This happens
158 158 in zope.inteface with the __provides__ attribute.
159 159 """
160 160 results = []
161 161 for key in dir(object):
162 162 try:
163 163 value = getattr(object, key)
164 164 except AttributeError:
165 165 pass
166 166 else:
167 167 if not predicate or predicate(value):
168 168 results.append((key, value))
169 169 results.sort()
170 170 return results
171 171
172 172
173 173 #-----------------------------------------------------------------------------
174 174 # Base TraitType for all traits
175 175 #-----------------------------------------------------------------------------
176 176
177 177
178 178 class TraitType(object):
179 179 """A base class for all trait descriptors.
180 180
181 181 Notes
182 182 -----
183 183 Our implementation of traits is based on Python's descriptor
184 184 prototol. This class is the base class for all such descriptors. The
185 185 only magic we use is a custom metaclass for the main :class:`HasTraits`
186 186 class that does the following:
187 187
188 188 1. Sets the :attr:`name` attribute of every :class:`TraitType`
189 189 instance in the class dict to the name of the attribute.
190 190 2. Sets the :attr:`this_class` attribute of every :class:`TraitType`
191 191 instance in the class dict to the *class* that declared the trait.
192 192 This is used by the :class:`This` trait to allow subclasses to
193 193 accept superclasses for :class:`This` values.
194 194 """
195 195
196 196
197 197 metadata = {}
198 198 default_value = Undefined
199 199 info_text = 'any value'
200 200
201 201 def __init__(self, default_value=NoDefaultSpecified, **metadata):
202 202 """Create a TraitType.
203 203 """
204 204 if default_value is not NoDefaultSpecified:
205 205 self.default_value = default_value
206 206
207 207 if len(metadata) > 0:
208 208 if len(self.metadata) > 0:
209 209 self._metadata = self.metadata.copy()
210 210 self._metadata.update(metadata)
211 211 else:
212 212 self._metadata = metadata
213 213 else:
214 214 self._metadata = self.metadata
215 215
216 216 self.init()
217 217
218 218 def init(self):
219 219 pass
220 220
221 221 def get_default_value(self):
222 222 """Create a new instance of the default value."""
223 223 return self.default_value
224 224
225 225 def instance_init(self, obj):
226 226 """This is called by :meth:`HasTraits.__new__` to finish init'ing.
227 227
228 228 Some stages of initialization must be delayed until the parent
229 229 :class:`HasTraits` instance has been created. This method is
230 230 called in :meth:`HasTraits.__new__` after the instance has been
231 231 created.
232 232
233 233 This method trigger the creation and validation of default values
234 234 and also things like the resolution of str given class names in
235 235 :class:`Type` and :class`Instance`.
236 236
237 237 Parameters
238 238 ----------
239 239 obj : :class:`HasTraits` instance
240 240 The parent :class:`HasTraits` instance that has just been
241 241 created.
242 242 """
243 243 self.set_default_value(obj)
244 244
245 245 def set_default_value(self, obj):
246 246 """Set the default value on a per instance basis.
247 247
248 248 This method is called by :meth:`instance_init` to create and
249 249 validate the default value. The creation and validation of
250 250 default values must be delayed until the parent :class:`HasTraits`
251 251 class has been instantiated.
252 252 """
253 253 # Check for a deferred initializer defined in the same class as the
254 254 # trait declaration or above.
255 255 mro = type(obj).mro()
256 256 meth_name = '_%s_default' % self.name
257 257 for cls in mro[:mro.index(self.this_class)+1]:
258 258 if meth_name in cls.__dict__:
259 259 break
260 260 else:
261 261 # We didn't find one. Do static initialization.
262 262 dv = self.get_default_value()
263 263 newdv = self._validate(obj, dv)
264 264 obj._trait_values[self.name] = newdv
265 265 return
266 266 # Complete the dynamic initialization.
267 267 obj._trait_dyn_inits[self.name] = cls.__dict__[meth_name]
268 268
269 269 def __get__(self, obj, cls=None):
270 270 """Get the value of the trait by self.name for the instance.
271 271
272 272 Default values are instantiated when :meth:`HasTraits.__new__`
273 273 is called. Thus by the time this method gets called either the
274 274 default value or a user defined value (they called :meth:`__set__`)
275 275 is in the :class:`HasTraits` instance.
276 276 """
277 277 if obj is None:
278 278 return self
279 279 else:
280 280 try:
281 281 value = obj._trait_values[self.name]
282 282 except KeyError:
283 283 # Check for a dynamic initializer.
284 284 if self.name in obj._trait_dyn_inits:
285 285 value = obj._trait_dyn_inits[self.name](obj)
286 286 # FIXME: Do we really validate here?
287 287 value = self._validate(obj, value)
288 288 obj._trait_values[self.name] = value
289 289 return value
290 290 else:
291 291 raise TraitError('Unexpected error in TraitType: '
292 292 'both default value and dynamic initializer are '
293 293 'absent.')
294 294 except Exception:
295 295 # HasTraits should call set_default_value to populate
296 296 # this. So this should never be reached.
297 297 raise TraitError('Unexpected error in TraitType: '
298 298 'default value not set properly')
299 299 else:
300 300 return value
301 301
302 302 def __set__(self, obj, value):
303 303 new_value = self._validate(obj, value)
304 304 old_value = self.__get__(obj)
305 305 if old_value != new_value:
306 306 obj._trait_values[self.name] = new_value
307 307 obj._notify_trait(self.name, old_value, new_value)
308 308
309 309 def _validate(self, obj, value):
310 310 if hasattr(self, 'validate'):
311 311 return self.validate(obj, value)
312 312 elif hasattr(self, 'is_valid_for'):
313 313 valid = self.is_valid_for(value)
314 314 if valid:
315 315 return value
316 316 else:
317 317 raise TraitError('invalid value for type: %r' % value)
318 318 elif hasattr(self, 'value_for'):
319 319 return self.value_for(value)
320 320 else:
321 321 return value
322 322
323 323 def info(self):
324 324 return self.info_text
325 325
326 326 def error(self, obj, value):
327 327 if obj is not None:
328 328 e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
329 329 % (self.name, class_of(obj),
330 330 self.info(), repr_type(value))
331 331 else:
332 332 e = "The '%s' trait must be %s, but a value of %r was specified." \
333 333 % (self.name, self.info(), repr_type(value))
334 334 raise TraitError(e)
335 335
336 336 def get_metadata(self, key):
337 337 return getattr(self, '_metadata', {}).get(key, None)
338 338
339 339 def set_metadata(self, key, value):
340 340 getattr(self, '_metadata', {})[key] = value
341 341
342 342
343 343 #-----------------------------------------------------------------------------
344 344 # The HasTraits implementation
345 345 #-----------------------------------------------------------------------------
346 346
347 347
348 348 class MetaHasTraits(type):
349 349 """A metaclass for HasTraits.
350 350
351 351 This metaclass makes sure that any TraitType class attributes are
352 352 instantiated and sets their name attribute.
353 353 """
354 354
355 355 def __new__(mcls, name, bases, classdict):
356 356 """Create the HasTraits class.
357 357
358 358 This instantiates all TraitTypes in the class dict and sets their
359 359 :attr:`name` attribute.
360 360 """
361 361 # print "MetaHasTraitlets (mcls, name): ", mcls, name
362 362 # print "MetaHasTraitlets (bases): ", bases
363 363 # print "MetaHasTraitlets (classdict): ", classdict
364 364 for k,v in classdict.iteritems():
365 365 if isinstance(v, TraitType):
366 366 v.name = k
367 367 elif inspect.isclass(v):
368 368 if issubclass(v, TraitType):
369 369 vinst = v()
370 370 vinst.name = k
371 371 classdict[k] = vinst
372 372 return super(MetaHasTraits, mcls).__new__(mcls, name, bases, classdict)
373 373
374 374 def __init__(cls, name, bases, classdict):
375 375 """Finish initializing the HasTraits class.
376 376
377 377 This sets the :attr:`this_class` attribute of each TraitType in the
378 378 class dict to the newly created class ``cls``.
379 379 """
380 380 for k, v in classdict.iteritems():
381 381 if isinstance(v, TraitType):
382 382 v.this_class = cls
383 383 super(MetaHasTraits, cls).__init__(name, bases, classdict)
384 384
385 385 class HasTraits(object):
386 386
387 387 __metaclass__ = MetaHasTraits
388 388
389 389 def __new__(cls, **kw):
390 390 # This is needed because in Python 2.6 object.__new__ only accepts
391 391 # the cls argument.
392 392 new_meth = super(HasTraits, cls).__new__
393 393 if new_meth is object.__new__:
394 394 inst = new_meth(cls)
395 395 else:
396 396 inst = new_meth(cls, **kw)
397 397 inst._trait_values = {}
398 398 inst._trait_notifiers = {}
399 399 inst._trait_dyn_inits = {}
400 400 # Here we tell all the TraitType instances to set their default
401 401 # values on the instance.
402 402 for key in dir(cls):
403 403 # Some descriptors raise AttributeError like zope.interface's
404 404 # __provides__ attributes even though they exist. This causes
405 405 # AttributeErrors even though they are listed in dir(cls).
406 406 try:
407 407 value = getattr(cls, key)
408 408 except AttributeError:
409 409 pass
410 410 else:
411 411 if isinstance(value, TraitType):
412 412 value.instance_init(inst)
413 413
414 414 return inst
415 415
416 416 def __init__(self, **kw):
417 417 # Allow trait values to be set using keyword arguments.
418 418 # We need to use setattr for this to trigger validation and
419 419 # notifications.
420 420 for key, value in kw.iteritems():
421 421 setattr(self, key, value)
422 422
423 423 def _notify_trait(self, name, old_value, new_value):
424 424
425 425 # First dynamic ones
426 426 callables = self._trait_notifiers.get(name,[])
427 427 more_callables = self._trait_notifiers.get('anytrait',[])
428 428 callables.extend(more_callables)
429 429
430 430 # Now static ones
431 431 try:
432 432 cb = getattr(self, '_%s_changed' % name)
433 433 except:
434 434 pass
435 435 else:
436 436 callables.append(cb)
437 437
438 438 # Call them all now
439 439 for c in callables:
440 440 # Traits catches and logs errors here. I allow them to raise
441 441 if callable(c):
442 442 argspec = inspect.getargspec(c)
443 443 nargs = len(argspec[0])
444 444 # Bound methods have an additional 'self' argument
445 445 # I don't know how to treat unbound methods, but they
446 446 # can't really be used for callbacks.
447 447 if isinstance(c, types.MethodType):
448 448 offset = -1
449 449 else:
450 450 offset = 0
451 451 if nargs + offset == 0:
452 452 c()
453 453 elif nargs + offset == 1:
454 454 c(name)
455 455 elif nargs + offset == 2:
456 456 c(name, new_value)
457 457 elif nargs + offset == 3:
458 458 c(name, old_value, new_value)
459 459 else:
460 460 raise TraitError('a trait changed callback '
461 461 'must have 0-3 arguments.')
462 462 else:
463 463 raise TraitError('a trait changed callback '
464 464 'must be callable.')
465 465
466 466
467 467 def _add_notifiers(self, handler, name):
468 if not self._trait_notifiers.has_key(name):
468 if name not in self._trait_notifiers:
469 469 nlist = []
470 470 self._trait_notifiers[name] = nlist
471 471 else:
472 472 nlist = self._trait_notifiers[name]
473 473 if handler not in nlist:
474 474 nlist.append(handler)
475 475
476 476 def _remove_notifiers(self, handler, name):
477 if self._trait_notifiers.has_key(name):
477 if name in self._trait_notifiers:
478 478 nlist = self._trait_notifiers[name]
479 479 try:
480 480 index = nlist.index(handler)
481 481 except ValueError:
482 482 pass
483 483 else:
484 484 del nlist[index]
485 485
486 486 def on_trait_change(self, handler, name=None, remove=False):
487 487 """Setup a handler to be called when a trait changes.
488 488
489 489 This is used to setup dynamic notifications of trait changes.
490 490
491 491 Static handlers can be created by creating methods on a HasTraits
492 492 subclass with the naming convention '_[traitname]_changed'. Thus,
493 493 to create static handler for the trait 'a', create the method
494 494 _a_changed(self, name, old, new) (fewer arguments can be used, see
495 495 below).
496 496
497 497 Parameters
498 498 ----------
499 499 handler : callable
500 500 A callable that is called when a trait changes. Its
501 501 signature can be handler(), handler(name), handler(name, new)
502 502 or handler(name, old, new).
503 503 name : list, str, None
504 504 If None, the handler will apply to all traits. If a list
505 505 of str, handler will apply to all names in the list. If a
506 506 str, the handler will apply just to that name.
507 507 remove : bool
508 508 If False (the default), then install the handler. If True
509 509 then unintall it.
510 510 """
511 511 if remove:
512 512 names = parse_notifier_name(name)
513 513 for n in names:
514 514 self._remove_notifiers(handler, n)
515 515 else:
516 516 names = parse_notifier_name(name)
517 517 for n in names:
518 518 self._add_notifiers(handler, n)
519 519
520 520 @classmethod
521 521 def class_trait_names(cls, **metadata):
522 522 """Get a list of all the names of this classes traits.
523 523
524 524 This method is just like the :meth:`trait_names` method, but is unbound.
525 525 """
526 526 return cls.class_traits(**metadata).keys()
527 527
528 528 @classmethod
529 529 def class_traits(cls, **metadata):
530 530 """Get a list of all the traits of this class.
531 531
532 532 This method is just like the :meth:`traits` method, but is unbound.
533 533
534 534 The TraitTypes returned don't know anything about the values
535 535 that the various HasTrait's instances are holding.
536 536
537 537 This follows the same algorithm as traits does and does not allow
538 538 for any simple way of specifying merely that a metadata name
539 539 exists, but has any value. This is because get_metadata returns
540 540 None if a metadata key doesn't exist.
541 541 """
542 542 traits = dict([memb for memb in getmembers(cls) if \
543 543 isinstance(memb[1], TraitType)])
544 544
545 545 if len(metadata) == 0:
546 546 return traits
547 547
548 548 for meta_name, meta_eval in metadata.items():
549 549 if type(meta_eval) is not FunctionType:
550 550 metadata[meta_name] = _SimpleTest(meta_eval)
551 551
552 552 result = {}
553 553 for name, trait in traits.items():
554 554 for meta_name, meta_eval in metadata.items():
555 555 if not meta_eval(trait.get_metadata(meta_name)):
556 556 break
557 557 else:
558 558 result[name] = trait
559 559
560 560 return result
561 561
562 562 def trait_names(self, **metadata):
563 563 """Get a list of all the names of this classes traits."""
564 564 return self.traits(**metadata).keys()
565 565
566 566 def traits(self, **metadata):
567 567 """Get a list of all the traits of this class.
568 568
569 569 The TraitTypes returned don't know anything about the values
570 570 that the various HasTrait's instances are holding.
571 571
572 572 This follows the same algorithm as traits does and does not allow
573 573 for any simple way of specifying merely that a metadata name
574 574 exists, but has any value. This is because get_metadata returns
575 575 None if a metadata key doesn't exist.
576 576 """
577 577 traits = dict([memb for memb in getmembers(self.__class__) if \
578 578 isinstance(memb[1], TraitType)])
579 579
580 580 if len(metadata) == 0:
581 581 return traits
582 582
583 583 for meta_name, meta_eval in metadata.items():
584 584 if type(meta_eval) is not FunctionType:
585 585 metadata[meta_name] = _SimpleTest(meta_eval)
586 586
587 587 result = {}
588 588 for name, trait in traits.items():
589 589 for meta_name, meta_eval in metadata.items():
590 590 if not meta_eval(trait.get_metadata(meta_name)):
591 591 break
592 592 else:
593 593 result[name] = trait
594 594
595 595 return result
596 596
597 597 def trait_metadata(self, traitname, key):
598 598 """Get metadata values for trait by key."""
599 599 try:
600 600 trait = getattr(self.__class__, traitname)
601 601 except AttributeError:
602 602 raise TraitError("Class %s does not have a trait named %s" %
603 603 (self.__class__.__name__, traitname))
604 604 else:
605 605 return trait.get_metadata(key)
606 606
607 607 #-----------------------------------------------------------------------------
608 608 # Actual TraitTypes implementations/subclasses
609 609 #-----------------------------------------------------------------------------
610 610
611 611 #-----------------------------------------------------------------------------
612 612 # TraitTypes subclasses for handling classes and instances of classes
613 613 #-----------------------------------------------------------------------------
614 614
615 615
616 616 class ClassBasedTraitType(TraitType):
617 617 """A trait with error reporting for Type, Instance and This."""
618 618
619 619 def error(self, obj, value):
620 620 kind = type(value)
621 621 if (not py3compat.PY3) and kind is InstanceType:
622 622 msg = 'class %s' % value.__class__.__name__
623 623 else:
624 624 msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) )
625 625
626 626 if obj is not None:
627 627 e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
628 628 % (self.name, class_of(obj),
629 629 self.info(), msg)
630 630 else:
631 631 e = "The '%s' trait must be %s, but a value of %r was specified." \
632 632 % (self.name, self.info(), msg)
633 633
634 634 raise TraitError(e)
635 635
636 636
637 637 class Type(ClassBasedTraitType):
638 638 """A trait whose value must be a subclass of a specified class."""
639 639
640 640 def __init__ (self, default_value=None, klass=None, allow_none=True, **metadata ):
641 641 """Construct a Type trait
642 642
643 643 A Type trait specifies that its values must be subclasses of
644 644 a particular class.
645 645
646 646 If only ``default_value`` is given, it is used for the ``klass`` as
647 647 well.
648 648
649 649 Parameters
650 650 ----------
651 651 default_value : class, str or None
652 652 The default value must be a subclass of klass. If an str,
653 653 the str must be a fully specified class name, like 'foo.bar.Bah'.
654 654 The string is resolved into real class, when the parent
655 655 :class:`HasTraits` class is instantiated.
656 656 klass : class, str, None
657 657 Values of this trait must be a subclass of klass. The klass
658 658 may be specified in a string like: 'foo.bar.MyClass'.
659 659 The string is resolved into real class, when the parent
660 660 :class:`HasTraits` class is instantiated.
661 661 allow_none : boolean
662 662 Indicates whether None is allowed as an assignable value. Even if
663 663 ``False``, the default value may be ``None``.
664 664 """
665 665 if default_value is None:
666 666 if klass is None:
667 667 klass = object
668 668 elif klass is None:
669 669 klass = default_value
670 670
671 671 if not (inspect.isclass(klass) or isinstance(klass, basestring)):
672 672 raise TraitError("A Type trait must specify a class.")
673 673
674 674 self.klass = klass
675 675 self._allow_none = allow_none
676 676
677 677 super(Type, self).__init__(default_value, **metadata)
678 678
679 679 def validate(self, obj, value):
680 680 """Validates that the value is a valid object instance."""
681 681 try:
682 682 if issubclass(value, self.klass):
683 683 return value
684 684 except:
685 685 if (value is None) and (self._allow_none):
686 686 return value
687 687
688 688 self.error(obj, value)
689 689
690 690 def info(self):
691 691 """ Returns a description of the trait."""
692 692 if isinstance(self.klass, basestring):
693 693 klass = self.klass
694 694 else:
695 695 klass = self.klass.__name__
696 696 result = 'a subclass of ' + klass
697 697 if self._allow_none:
698 698 return result + ' or None'
699 699 return result
700 700
701 701 def instance_init(self, obj):
702 702 self._resolve_classes()
703 703 super(Type, self).instance_init(obj)
704 704
705 705 def _resolve_classes(self):
706 706 if isinstance(self.klass, basestring):
707 707 self.klass = import_item(self.klass)
708 708 if isinstance(self.default_value, basestring):
709 709 self.default_value = import_item(self.default_value)
710 710
711 711 def get_default_value(self):
712 712 return self.default_value
713 713
714 714
715 715 class DefaultValueGenerator(object):
716 716 """A class for generating new default value instances."""
717 717
718 718 def __init__(self, *args, **kw):
719 719 self.args = args
720 720 self.kw = kw
721 721
722 722 def generate(self, klass):
723 723 return klass(*self.args, **self.kw)
724 724
725 725
726 726 class Instance(ClassBasedTraitType):
727 727 """A trait whose value must be an instance of a specified class.
728 728
729 729 The value can also be an instance of a subclass of the specified class.
730 730 """
731 731
732 732 def __init__(self, klass=None, args=None, kw=None,
733 733 allow_none=True, **metadata ):
734 734 """Construct an Instance trait.
735 735
736 736 This trait allows values that are instances of a particular
737 737 class or its sublclasses. Our implementation is quite different
738 738 from that of enthough.traits as we don't allow instances to be used
739 739 for klass and we handle the ``args`` and ``kw`` arguments differently.
740 740
741 741 Parameters
742 742 ----------
743 743 klass : class, str
744 744 The class that forms the basis for the trait. Class names
745 745 can also be specified as strings, like 'foo.bar.Bar'.
746 746 args : tuple
747 747 Positional arguments for generating the default value.
748 748 kw : dict
749 749 Keyword arguments for generating the default value.
750 750 allow_none : bool
751 751 Indicates whether None is allowed as a value.
752 752
753 753 Default Value
754 754 -------------
755 755 If both ``args`` and ``kw`` are None, then the default value is None.
756 756 If ``args`` is a tuple and ``kw`` is a dict, then the default is
757 757 created as ``klass(*args, **kw)``. If either ``args`` or ``kw`` is
758 758 not (but not both), None is replace by ``()`` or ``{}``.
759 759 """
760 760
761 761 self._allow_none = allow_none
762 762
763 763 if (klass is None) or (not (inspect.isclass(klass) or isinstance(klass, basestring))):
764 764 raise TraitError('The klass argument must be a class'
765 765 ' you gave: %r' % klass)
766 766 self.klass = klass
767 767
768 768 # self.klass is a class, so handle default_value
769 769 if args is None and kw is None:
770 770 default_value = None
771 771 else:
772 772 if args is None:
773 773 # kw is not None
774 774 args = ()
775 775 elif kw is None:
776 776 # args is not None
777 777 kw = {}
778 778
779 779 if not isinstance(kw, dict):
780 780 raise TraitError("The 'kw' argument must be a dict or None.")
781 781 if not isinstance(args, tuple):
782 782 raise TraitError("The 'args' argument must be a tuple or None.")
783 783
784 784 default_value = DefaultValueGenerator(*args, **kw)
785 785
786 786 super(Instance, self).__init__(default_value, **metadata)
787 787
788 788 def validate(self, obj, value):
789 789 if value is None:
790 790 if self._allow_none:
791 791 return value
792 792 self.error(obj, value)
793 793
794 794 if isinstance(value, self.klass):
795 795 return value
796 796 else:
797 797 self.error(obj, value)
798 798
799 799 def info(self):
800 800 if isinstance(self.klass, basestring):
801 801 klass = self.klass
802 802 else:
803 803 klass = self.klass.__name__
804 804 result = class_of(klass)
805 805 if self._allow_none:
806 806 return result + ' or None'
807 807
808 808 return result
809 809
810 810 def instance_init(self, obj):
811 811 self._resolve_classes()
812 812 super(Instance, self).instance_init(obj)
813 813
814 814 def _resolve_classes(self):
815 815 if isinstance(self.klass, basestring):
816 816 self.klass = import_item(self.klass)
817 817
818 818 def get_default_value(self):
819 819 """Instantiate a default value instance.
820 820
821 821 This is called when the containing HasTraits classes'
822 822 :meth:`__new__` method is called to ensure that a unique instance
823 823 is created for each HasTraits instance.
824 824 """
825 825 dv = self.default_value
826 826 if isinstance(dv, DefaultValueGenerator):
827 827 return dv.generate(self.klass)
828 828 else:
829 829 return dv
830 830
831 831
832 832 class This(ClassBasedTraitType):
833 833 """A trait for instances of the class containing this trait.
834 834
835 835 Because how how and when class bodies are executed, the ``This``
836 836 trait can only have a default value of None. This, and because we
837 837 always validate default values, ``allow_none`` is *always* true.
838 838 """
839 839
840 840 info_text = 'an instance of the same type as the receiver or None'
841 841
842 842 def __init__(self, **metadata):
843 843 super(This, self).__init__(None, **metadata)
844 844
845 845 def validate(self, obj, value):
846 846 # What if value is a superclass of obj.__class__? This is
847 847 # complicated if it was the superclass that defined the This
848 848 # trait.
849 849 if isinstance(value, self.this_class) or (value is None):
850 850 return value
851 851 else:
852 852 self.error(obj, value)
853 853
854 854
855 855 #-----------------------------------------------------------------------------
856 856 # Basic TraitTypes implementations/subclasses
857 857 #-----------------------------------------------------------------------------
858 858
859 859
860 860 class Any(TraitType):
861 861 default_value = None
862 862 info_text = 'any value'
863 863
864 864
865 865 class Int(TraitType):
866 866 """An int trait."""
867 867
868 868 default_value = 0
869 869 info_text = 'an int'
870 870
871 871 def validate(self, obj, value):
872 872 if isinstance(value, int):
873 873 return value
874 874 self.error(obj, value)
875 875
876 876 class CInt(Int):
877 877 """A casting version of the int trait."""
878 878
879 879 def validate(self, obj, value):
880 880 try:
881 881 return int(value)
882 882 except:
883 883 self.error(obj, value)
884 884
885 885 if py3compat.PY3:
886 886 Long, CLong = Int, CInt
887 887 Integer = Int
888 888 else:
889 889 class Long(TraitType):
890 890 """A long integer trait."""
891 891
892 892 default_value = 0L
893 893 info_text = 'a long'
894 894
895 895 def validate(self, obj, value):
896 896 if isinstance(value, long):
897 897 return value
898 898 if isinstance(value, int):
899 899 return long(value)
900 900 self.error(obj, value)
901 901
902 902
903 903 class CLong(Long):
904 904 """A casting version of the long integer trait."""
905 905
906 906 def validate(self, obj, value):
907 907 try:
908 908 return long(value)
909 909 except:
910 910 self.error(obj, value)
911 911
912 912 class Integer(TraitType):
913 913 """An integer trait.
914 914
915 915 Longs that are unnecessary (<= sys.maxint) are cast to ints."""
916 916
917 917 default_value = 0
918 918 info_text = 'an integer'
919 919
920 920 def validate(self, obj, value):
921 921 if isinstance(value, int):
922 922 return value
923 923 elif isinstance(value, long):
924 924 # downcast longs that fit in int:
925 925 # note that int(n > sys.maxint) returns a long, so
926 926 # we don't need a condition on this cast
927 927 return int(value)
928 928 self.error(obj, value)
929 929
930 930
931 931 class Float(TraitType):
932 932 """A float trait."""
933 933
934 934 default_value = 0.0
935 935 info_text = 'a float'
936 936
937 937 def validate(self, obj, value):
938 938 if isinstance(value, float):
939 939 return value
940 940 if isinstance(value, int):
941 941 return float(value)
942 942 self.error(obj, value)
943 943
944 944
945 945 class CFloat(Float):
946 946 """A casting version of the float trait."""
947 947
948 948 def validate(self, obj, value):
949 949 try:
950 950 return float(value)
951 951 except:
952 952 self.error(obj, value)
953 953
954 954 class Complex(TraitType):
955 955 """A trait for complex numbers."""
956 956
957 957 default_value = 0.0 + 0.0j
958 958 info_text = 'a complex number'
959 959
960 960 def validate(self, obj, value):
961 961 if isinstance(value, complex):
962 962 return value
963 963 if isinstance(value, (float, int)):
964 964 return complex(value)
965 965 self.error(obj, value)
966 966
967 967
968 968 class CComplex(Complex):
969 969 """A casting version of the complex number trait."""
970 970
971 971 def validate (self, obj, value):
972 972 try:
973 973 return complex(value)
974 974 except:
975 975 self.error(obj, value)
976 976
977 977 # We should always be explicit about whether we're using bytes or unicode, both
978 978 # for Python 3 conversion and for reliable unicode behaviour on Python 2. So
979 979 # we don't have a Str type.
980 980 class Bytes(TraitType):
981 981 """A trait for byte strings."""
982 982
983 983 default_value = b''
984 984 info_text = 'a string'
985 985
986 986 def validate(self, obj, value):
987 987 if isinstance(value, bytes):
988 988 return value
989 989 self.error(obj, value)
990 990
991 991
992 992 class CBytes(Bytes):
993 993 """A casting version of the byte string trait."""
994 994
995 995 def validate(self, obj, value):
996 996 try:
997 997 return bytes(value)
998 998 except:
999 999 self.error(obj, value)
1000 1000
1001 1001
1002 1002 class Unicode(TraitType):
1003 1003 """A trait for unicode strings."""
1004 1004
1005 1005 default_value = u''
1006 1006 info_text = 'a unicode string'
1007 1007
1008 1008 def validate(self, obj, value):
1009 1009 if isinstance(value, unicode):
1010 1010 return value
1011 1011 if isinstance(value, bytes):
1012 1012 return unicode(value)
1013 1013 self.error(obj, value)
1014 1014
1015 1015
1016 1016 class CUnicode(Unicode):
1017 1017 """A casting version of the unicode trait."""
1018 1018
1019 1019 def validate(self, obj, value):
1020 1020 try:
1021 1021 return unicode(value)
1022 1022 except:
1023 1023 self.error(obj, value)
1024 1024
1025 1025
1026 1026 class ObjectName(TraitType):
1027 1027 """A string holding a valid object name in this version of Python.
1028 1028
1029 1029 This does not check that the name exists in any scope."""
1030 1030 info_text = "a valid object identifier in Python"
1031 1031
1032 1032 if py3compat.PY3:
1033 1033 # Python 3:
1034 1034 coerce_str = staticmethod(lambda _,s: s)
1035 1035
1036 1036 else:
1037 1037 # Python 2:
1038 1038 def coerce_str(self, obj, value):
1039 1039 "In Python 2, coerce ascii-only unicode to str"
1040 1040 if isinstance(value, unicode):
1041 1041 try:
1042 1042 return str(value)
1043 1043 except UnicodeEncodeError:
1044 1044 self.error(obj, value)
1045 1045 return value
1046 1046
1047 1047 def validate(self, obj, value):
1048 1048 value = self.coerce_str(obj, value)
1049 1049
1050 1050 if isinstance(value, str) and py3compat.isidentifier(value):
1051 1051 return value
1052 1052 self.error(obj, value)
1053 1053
1054 1054 class DottedObjectName(ObjectName):
1055 1055 """A string holding a valid dotted object name in Python, such as A.b3._c"""
1056 1056 def validate(self, obj, value):
1057 1057 value = self.coerce_str(obj, value)
1058 1058
1059 1059 if isinstance(value, str) and py3compat.isidentifier(value, dotted=True):
1060 1060 return value
1061 1061 self.error(obj, value)
1062 1062
1063 1063
1064 1064 class Bool(TraitType):
1065 1065 """A boolean (True, False) trait."""
1066 1066
1067 1067 default_value = False
1068 1068 info_text = 'a boolean'
1069 1069
1070 1070 def validate(self, obj, value):
1071 1071 if isinstance(value, bool):
1072 1072 return value
1073 1073 self.error(obj, value)
1074 1074
1075 1075
1076 1076 class CBool(Bool):
1077 1077 """A casting version of the boolean trait."""
1078 1078
1079 1079 def validate(self, obj, value):
1080 1080 try:
1081 1081 return bool(value)
1082 1082 except:
1083 1083 self.error(obj, value)
1084 1084
1085 1085
1086 1086 class Enum(TraitType):
1087 1087 """An enum that whose value must be in a given sequence."""
1088 1088
1089 1089 def __init__(self, values, default_value=None, allow_none=True, **metadata):
1090 1090 self.values = values
1091 1091 self._allow_none = allow_none
1092 1092 super(Enum, self).__init__(default_value, **metadata)
1093 1093
1094 1094 def validate(self, obj, value):
1095 1095 if value is None:
1096 1096 if self._allow_none:
1097 1097 return value
1098 1098
1099 1099 if value in self.values:
1100 1100 return value
1101 1101 self.error(obj, value)
1102 1102
1103 1103 def info(self):
1104 1104 """ Returns a description of the trait."""
1105 1105 result = 'any of ' + repr(self.values)
1106 1106 if self._allow_none:
1107 1107 return result + ' or None'
1108 1108 return result
1109 1109
1110 1110 class CaselessStrEnum(Enum):
1111 1111 """An enum of strings that are caseless in validate."""
1112 1112
1113 1113 def validate(self, obj, value):
1114 1114 if value is None:
1115 1115 if self._allow_none:
1116 1116 return value
1117 1117
1118 1118 if not isinstance(value, basestring):
1119 1119 self.error(obj, value)
1120 1120
1121 1121 for v in self.values:
1122 1122 if v.lower() == value.lower():
1123 1123 return v
1124 1124 self.error(obj, value)
1125 1125
1126 1126 class Container(Instance):
1127 1127 """An instance of a container (list, set, etc.)
1128 1128
1129 1129 To be subclassed by overriding klass.
1130 1130 """
1131 1131 klass = None
1132 1132 _valid_defaults = SequenceTypes
1133 1133 _trait = None
1134 1134
1135 1135 def __init__(self, trait=None, default_value=None, allow_none=True,
1136 1136 **metadata):
1137 1137 """Create a container trait type from a list, set, or tuple.
1138 1138
1139 1139 The default value is created by doing ``List(default_value)``,
1140 1140 which creates a copy of the ``default_value``.
1141 1141
1142 1142 ``trait`` can be specified, which restricts the type of elements
1143 1143 in the container to that TraitType.
1144 1144
1145 1145 If only one arg is given and it is not a Trait, it is taken as
1146 1146 ``default_value``:
1147 1147
1148 1148 ``c = List([1,2,3])``
1149 1149
1150 1150 Parameters
1151 1151 ----------
1152 1152
1153 1153 trait : TraitType [ optional ]
1154 1154 the type for restricting the contents of the Container. If unspecified,
1155 1155 types are not checked.
1156 1156
1157 1157 default_value : SequenceType [ optional ]
1158 1158 The default value for the Trait. Must be list/tuple/set, and
1159 1159 will be cast to the container type.
1160 1160
1161 1161 allow_none : Bool [ default True ]
1162 1162 Whether to allow the value to be None
1163 1163
1164 1164 **metadata : any
1165 1165 further keys for extensions to the Trait (e.g. config)
1166 1166
1167 1167 """
1168 1168 istrait = lambda t: isinstance(t, type) and issubclass(t, TraitType)
1169 1169
1170 1170 # allow List([values]):
1171 1171 if default_value is None and not istrait(trait):
1172 1172 default_value = trait
1173 1173 trait = None
1174 1174
1175 1175 if default_value is None:
1176 1176 args = ()
1177 1177 elif isinstance(default_value, self._valid_defaults):
1178 1178 args = (default_value,)
1179 1179 else:
1180 1180 raise TypeError('default value of %s was %s' %(self.__class__.__name__, default_value))
1181 1181
1182 1182 if istrait(trait):
1183 1183 self._trait = trait()
1184 1184 self._trait.name = 'element'
1185 1185 elif trait is not None:
1186 1186 raise TypeError("`trait` must be a Trait or None, got %s"%repr_type(trait))
1187 1187
1188 1188 super(Container,self).__init__(klass=self.klass, args=args,
1189 1189 allow_none=allow_none, **metadata)
1190 1190
1191 1191 def element_error(self, obj, element, validator):
1192 1192 e = "Element of the '%s' trait of %s instance must be %s, but a value of %s was specified." \
1193 1193 % (self.name, class_of(obj), validator.info(), repr_type(element))
1194 1194 raise TraitError(e)
1195 1195
1196 1196 def validate(self, obj, value):
1197 1197 value = super(Container, self).validate(obj, value)
1198 1198 if value is None:
1199 1199 return value
1200 1200
1201 1201 value = self.validate_elements(obj, value)
1202 1202
1203 1203 return value
1204 1204
1205 1205 def validate_elements(self, obj, value):
1206 1206 validated = []
1207 1207 if self._trait is None or isinstance(self._trait, Any):
1208 1208 return value
1209 1209 for v in value:
1210 1210 try:
1211 1211 v = self._trait.validate(obj, v)
1212 1212 except TraitError:
1213 1213 self.element_error(obj, v, self._trait)
1214 1214 else:
1215 1215 validated.append(v)
1216 1216 return self.klass(validated)
1217 1217
1218 1218
1219 1219 class List(Container):
1220 1220 """An instance of a Python list."""
1221 1221 klass = list
1222 1222
1223 1223 def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxint,
1224 1224 allow_none=True, **metadata):
1225 1225 """Create a List trait type from a list, set, or tuple.
1226 1226
1227 1227 The default value is created by doing ``List(default_value)``,
1228 1228 which creates a copy of the ``default_value``.
1229 1229
1230 1230 ``trait`` can be specified, which restricts the type of elements
1231 1231 in the container to that TraitType.
1232 1232
1233 1233 If only one arg is given and it is not a Trait, it is taken as
1234 1234 ``default_value``:
1235 1235
1236 1236 ``c = List([1,2,3])``
1237 1237
1238 1238 Parameters
1239 1239 ----------
1240 1240
1241 1241 trait : TraitType [ optional ]
1242 1242 the type for restricting the contents of the Container. If unspecified,
1243 1243 types are not checked.
1244 1244
1245 1245 default_value : SequenceType [ optional ]
1246 1246 The default value for the Trait. Must be list/tuple/set, and
1247 1247 will be cast to the container type.
1248 1248
1249 1249 minlen : Int [ default 0 ]
1250 1250 The minimum length of the input list
1251 1251
1252 1252 maxlen : Int [ default sys.maxint ]
1253 1253 The maximum length of the input list
1254 1254
1255 1255 allow_none : Bool [ default True ]
1256 1256 Whether to allow the value to be None
1257 1257
1258 1258 **metadata : any
1259 1259 further keys for extensions to the Trait (e.g. config)
1260 1260
1261 1261 """
1262 1262 self._minlen = minlen
1263 1263 self._maxlen = maxlen
1264 1264 super(List, self).__init__(trait=trait, default_value=default_value,
1265 1265 allow_none=allow_none, **metadata)
1266 1266
1267 1267 def length_error(self, obj, value):
1268 1268 e = "The '%s' trait of %s instance must be of length %i <= L <= %i, but a value of %s was specified." \
1269 1269 % (self.name, class_of(obj), self._minlen, self._maxlen, value)
1270 1270 raise TraitError(e)
1271 1271
1272 1272 def validate_elements(self, obj, value):
1273 1273 length = len(value)
1274 1274 if length < self._minlen or length > self._maxlen:
1275 1275 self.length_error(obj, value)
1276 1276
1277 1277 return super(List, self).validate_elements(obj, value)
1278 1278
1279 1279
1280 1280 class Set(Container):
1281 1281 """An instance of a Python set."""
1282 1282 klass = set
1283 1283
1284 1284 class Tuple(Container):
1285 1285 """An instance of a Python tuple."""
1286 1286 klass = tuple
1287 1287
1288 1288 def __init__(self, *traits, **metadata):
1289 1289 """Tuple(*traits, default_value=None, allow_none=True, **medatata)
1290 1290
1291 1291 Create a tuple from a list, set, or tuple.
1292 1292
1293 1293 Create a fixed-type tuple with Traits:
1294 1294
1295 1295 ``t = Tuple(Int, Str, CStr)``
1296 1296
1297 1297 would be length 3, with Int,Str,CStr for each element.
1298 1298
1299 1299 If only one arg is given and it is not a Trait, it is taken as
1300 1300 default_value:
1301 1301
1302 1302 ``t = Tuple((1,2,3))``
1303 1303
1304 1304 Otherwise, ``default_value`` *must* be specified by keyword.
1305 1305
1306 1306 Parameters
1307 1307 ----------
1308 1308
1309 1309 *traits : TraitTypes [ optional ]
1310 1310 the tsype for restricting the contents of the Tuple. If unspecified,
1311 1311 types are not checked. If specified, then each positional argument
1312 1312 corresponds to an element of the tuple. Tuples defined with traits
1313 1313 are of fixed length.
1314 1314
1315 1315 default_value : SequenceType [ optional ]
1316 1316 The default value for the Tuple. Must be list/tuple/set, and
1317 1317 will be cast to a tuple. If `traits` are specified, the
1318 1318 `default_value` must conform to the shape and type they specify.
1319 1319
1320 1320 allow_none : Bool [ default True ]
1321 1321 Whether to allow the value to be None
1322 1322
1323 1323 **metadata : any
1324 1324 further keys for extensions to the Trait (e.g. config)
1325 1325
1326 1326 """
1327 1327 default_value = metadata.pop('default_value', None)
1328 1328 allow_none = metadata.pop('allow_none', True)
1329 1329
1330 1330 istrait = lambda t: isinstance(t, type) and issubclass(t, TraitType)
1331 1331
1332 1332 # allow Tuple((values,)):
1333 1333 if len(traits) == 1 and default_value is None and not istrait(traits[0]):
1334 1334 default_value = traits[0]
1335 1335 traits = ()
1336 1336
1337 1337 if default_value is None:
1338 1338 args = ()
1339 1339 elif isinstance(default_value, self._valid_defaults):
1340 1340 args = (default_value,)
1341 1341 else:
1342 1342 raise TypeError('default value of %s was %s' %(self.__class__.__name__, default_value))
1343 1343
1344 1344 self._traits = []
1345 1345 for trait in traits:
1346 1346 t = trait()
1347 1347 t.name = 'element'
1348 1348 self._traits.append(t)
1349 1349
1350 1350 if self._traits and default_value is None:
1351 1351 # don't allow default to be an empty container if length is specified
1352 1352 args = None
1353 1353 super(Container,self).__init__(klass=self.klass, args=args,
1354 1354 allow_none=allow_none, **metadata)
1355 1355
1356 1356 def validate_elements(self, obj, value):
1357 1357 if not self._traits:
1358 1358 # nothing to validate
1359 1359 return value
1360 1360 if len(value) != len(self._traits):
1361 1361 e = "The '%s' trait of %s instance requires %i elements, but a value of %s was specified." \
1362 1362 % (self.name, class_of(obj), len(self._traits), repr_type(value))
1363 1363 raise TraitError(e)
1364 1364
1365 1365 validated = []
1366 1366 for t,v in zip(self._traits, value):
1367 1367 try:
1368 1368 v = t.validate(obj, v)
1369 1369 except TraitError:
1370 1370 self.element_error(obj, v, t)
1371 1371 else:
1372 1372 validated.append(v)
1373 1373 return tuple(validated)
1374 1374
1375 1375
1376 1376 class Dict(Instance):
1377 1377 """An instance of a Python dict."""
1378 1378
1379 1379 def __init__(self, default_value=None, allow_none=True, **metadata):
1380 1380 """Create a dict trait type from a dict.
1381 1381
1382 1382 The default value is created by doing ``dict(default_value)``,
1383 1383 which creates a copy of the ``default_value``.
1384 1384 """
1385 1385 if default_value is None:
1386 1386 args = ((),)
1387 1387 elif isinstance(default_value, dict):
1388 1388 args = (default_value,)
1389 1389 elif isinstance(default_value, SequenceTypes):
1390 1390 args = (default_value,)
1391 1391 else:
1392 1392 raise TypeError('default value of Dict was %s' % default_value)
1393 1393
1394 1394 super(Dict,self).__init__(klass=dict, args=args,
1395 1395 allow_none=allow_none, **metadata)
1396 1396
1397 1397 class TCPAddress(TraitType):
1398 1398 """A trait for an (ip, port) tuple.
1399 1399
1400 1400 This allows for both IPv4 IP addresses as well as hostnames.
1401 1401 """
1402 1402
1403 1403 default_value = ('127.0.0.1', 0)
1404 1404 info_text = 'an (ip, port) tuple'
1405 1405
1406 1406 def validate(self, obj, value):
1407 1407 if isinstance(value, tuple):
1408 1408 if len(value) == 2:
1409 1409 if isinstance(value[0], basestring) and isinstance(value[1], int):
1410 1410 port = value[1]
1411 1411 if port >= 0 and port <= 65535:
1412 1412 return value
1413 1413 self.error(obj, value)
1414 1414
1415 1415 class CRegExp(TraitType):
1416 1416 """A casting compiled regular expression trait.
1417 1417
1418 1418 Accepts both strings and compiled regular expressions. The resulting
1419 1419 attribute will be a compiled regular expression."""
1420 1420
1421 1421 info_text = 'a regular expression'
1422 1422
1423 1423 def validate(self, obj, value):
1424 1424 try:
1425 1425 return re.compile(value)
1426 1426 except:
1427 1427 self.error(obj, value)
General Comments 0
You need to be logged in to leave comments. Login now