##// END OF EJS Templates
main branch resync
laurent.dufrechou@gmail.com -
r1824:34b4cf01 merge
parent child Browse files
Show More

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

This diff has been collapsed as it changes many lines, (1867 lines changed) Show them Hide them
@@ -0,0 +1,1867 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright � 2006 Steven J. Bethard <steven.bethard@gmail.com>.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted under the terms of the 3-clause BSD
7 # license. No warranty expressed or implied.
8 # For details, see the accompanying file LICENSE.txt.
9
10 """Command-line parsing library
11
12 This module is an optparse-inspired command-line parsing library that:
13
14 * handles both optional and positional arguments
15 * produces highly informative usage messages
16 * supports parsers that dispatch to sub-parsers
17
18 The following is a simple usage example that sums integers from the
19 command-line and writes the result to a file:
20
21 parser = argparse.ArgumentParser(
22 description='sum the integers at the command line')
23 parser.add_argument(
24 'integers', metavar='int', nargs='+', type=int,
25 help='an integer to be summed')
26 parser.add_argument(
27 '--log', default=sys.stdout, type=argparse.FileType('w'),
28 help='the file where the sum should be written')
29 args = parser.parse_args()
30 args.log.write('%s' % sum(args.integers))
31 args.log.close()
32
33 The module contains the following public classes:
34
35 ArgumentParser -- The main entry point for command-line parsing. As the
36 example above shows, the add_argument() method is used to populate
37 the parser with actions for optional and positional arguments. Then
38 the parse_args() method is invoked to convert the args at the
39 command-line into an object with attributes.
40
41 ArgumentError -- The exception raised by ArgumentParser objects when
42 there are errors with the parser's actions. Errors raised while
43 parsing the command-line are caught by ArgumentParser and emitted
44 as command-line messages.
45
46 FileType -- A factory for defining types of files to be created. As the
47 example above shows, instances of FileType are typically passed as
48 the type= argument of add_argument() calls.
49
50 Action -- The base class for parser actions. Typically actions are
51 selected by passing strings like 'store_true' or 'append_const' to
52 the action= argument of add_argument(). However, for greater
53 customization of ArgumentParser actions, subclasses of Action may
54 be defined and passed as the action= argument.
55
56 HelpFormatter, RawDescriptionHelpFormatter -- Formatter classes which
57 may be passed as the formatter_class= argument to the
58 ArgumentParser constructor. HelpFormatter is the default, while
59 RawDescriptionHelpFormatter tells the parser not to perform any
60 line-wrapping on description text.
61
62 All other classes in this module are considered implementation details.
63 (Also note that HelpFormatter and RawDescriptionHelpFormatter are only
64 considered public as object names -- the API of the formatter objects is
65 still considered an implementation detail.)
66 """
67
68 __version__ = '0.8.0'
69
70 import os as _os
71 import re as _re
72 import sys as _sys
73 import textwrap as _textwrap
74
75 from gettext import gettext as _
76
77 SUPPRESS = '==SUPPRESS=='
78
79 OPTIONAL = '?'
80 ZERO_OR_MORE = '*'
81 ONE_OR_MORE = '+'
82 PARSER = '==PARSER=='
83
84 # =============================
85 # Utility functions and classes
86 # =============================
87
88 class _AttributeHolder(object):
89 """Abstract base class that provides __repr__.
90
91 The __repr__ method returns a string in the format:
92 ClassName(attr=name, attr=name, ...)
93 The attributes are determined either by a class-level attribute,
94 '_kwarg_names', or by inspecting the instance __dict__.
95 """
96
97 def __repr__(self):
98 type_name = type(self).__name__
99 arg_strings = []
100 for arg in self._get_args():
101 arg_strings.append(repr(arg))
102 for name, value in self._get_kwargs():
103 arg_strings.append('%s=%r' % (name, value))
104 return '%s(%s)' % (type_name, ', '.join(arg_strings))
105
106 def _get_kwargs(self):
107 return sorted(self.__dict__.items())
108
109 def _get_args(self):
110 return []
111
112 def _ensure_value(namespace, name, value):
113 if getattr(namespace, name, None) is None:
114 setattr(namespace, name, value)
115 return getattr(namespace, name)
116
117
118
119 # ===============
120 # Formatting Help
121 # ===============
122
123 class HelpFormatter(object):
124
125 def __init__(self,
126 prog,
127 indent_increment=2,
128 max_help_position=24,
129 width=None):
130
131 # default setting for width
132 if width is None:
133 try:
134 width = int(_os.environ['COLUMNS'])
135 except (KeyError, ValueError):
136 width = 80
137 width -= 2
138
139 self._prog = prog
140 self._indent_increment = indent_increment
141 self._max_help_position = max_help_position
142 self._width = width
143
144 self._current_indent = 0
145 self._level = 0
146 self._action_max_length = 0
147
148 self._root_section = self._Section(self, None)
149 self._current_section = self._root_section
150
151 self._whitespace_matcher = _re.compile(r'\s+')
152 self._long_break_matcher = _re.compile(r'\n\n\n+')
153
154 # ===============================
155 # Section and indentation methods
156 # ===============================
157
158 def _indent(self):
159 self._current_indent += self._indent_increment
160 self._level += 1
161
162 def _dedent(self):
163 self._current_indent -= self._indent_increment
164 assert self._current_indent >= 0, 'Indent decreased below 0.'
165 self._level -= 1
166
167 class _Section(object):
168 def __init__(self, formatter, parent, heading=None):
169 self.formatter = formatter
170 self.parent = parent
171 self.heading = heading
172 self.items = []
173
174 def format_help(self):
175 # format the indented section
176 if self.parent is not None:
177 self.formatter._indent()
178 join = self.formatter._join_parts
179 for func, args in self.items:
180 func(*args)
181 item_help = join(func(*args) for func, args in self.items)
182 if self.parent is not None:
183 self.formatter._dedent()
184
185 # return nothing if the section was empty
186 if not item_help:
187 return ''
188
189 # add the heading if the section was non-empty
190 if self.heading is not SUPPRESS and self.heading is not None:
191 current_indent = self.formatter._current_indent
192 heading = '%*s%s:\n' % (current_indent, '', self.heading)
193 else:
194 heading = ''
195
196 # join the section-initial newline, the heading and the help
197 return join(['\n', heading, item_help, '\n'])
198
199 def _add_item(self, func, args):
200 self._current_section.items.append((func, args))
201
202 # ========================
203 # Message building methods
204 # ========================
205
206 def start_section(self, heading):
207 self._indent()
208 section = self._Section(self, self._current_section, heading)
209 self._add_item(section.format_help, [])
210 self._current_section = section
211
212 def end_section(self):
213 self._current_section = self._current_section.parent
214 self._dedent()
215
216 def add_text(self, text):
217 if text is not SUPPRESS and text is not None:
218 self._add_item(self._format_text, [text])
219
220 def add_usage(self, usage, optionals, positionals, prefix=None):
221 if usage is not SUPPRESS:
222 args = usage, optionals, positionals, prefix
223 self._add_item(self._format_usage, args)
224
225 def add_argument(self, action):
226 if action.help is not SUPPRESS:
227
228 # find all invocations
229 get_invocation = self._format_action_invocation
230 invocations = [get_invocation(action)]
231 for subaction in self._iter_indented_subactions(action):
232 invocations.append(get_invocation(subaction))
233
234 # update the maximum item length
235 invocation_length = max(len(s) for s in invocations)
236 action_length = invocation_length + self._current_indent
237 self._action_max_length = max(self._action_max_length,
238 action_length)
239
240 # add the item to the list
241 self._add_item(self._format_action, [action])
242
243 def add_arguments(self, actions):
244 for action in actions:
245 self.add_argument(action)
246
247 # =======================
248 # Help-formatting methods
249 # =======================
250
251 def format_help(self):
252 help = self._root_section.format_help() % dict(prog=self._prog)
253 if help:
254 help = self._long_break_matcher.sub('\n\n', help)
255 help = help.strip('\n') + '\n'
256 return help
257
258 def _join_parts(self, part_strings):
259 return ''.join(part
260 for part in part_strings
261 if part and part is not SUPPRESS)
262
263 def _format_usage(self, usage, optionals, positionals, prefix):
264 if prefix is None:
265 prefix = _('usage: ')
266
267 # if no optionals or positionals are available, usage is just prog
268 if usage is None and not optionals and not positionals:
269 usage = '%(prog)s'
270
271 # if optionals and positionals are available, calculate usage
272 elif usage is None:
273 usage = '%(prog)s' % dict(prog=self._prog)
274
275 # determine width of "usage: PROG" and width of text
276 prefix_width = len(prefix) + len(usage) + 1
277 prefix_indent = self._current_indent + prefix_width
278 text_width = self._width - self._current_indent
279
280 # put them on one line if they're short enough
281 format = self._format_actions_usage
282 action_usage = format(optionals + positionals)
283 if prefix_width + len(action_usage) + 1 < text_width:
284 usage = '%s %s' % (usage, action_usage)
285
286 # if they're long, wrap optionals and positionals individually
287 else:
288 optional_usage = format(optionals)
289 positional_usage = format(positionals)
290 indent = ' ' * prefix_indent
291
292 # usage is made of PROG, optionals and positionals
293 parts = [usage, ' ']
294
295 # options always get added right after PROG
296 if optional_usage:
297 parts.append(_textwrap.fill(
298 optional_usage, text_width,
299 initial_indent=indent,
300 subsequent_indent=indent).lstrip())
301
302 # if there were options, put arguments on the next line
303 # otherwise, start them right after PROG
304 if positional_usage:
305 part = _textwrap.fill(
306 positional_usage, text_width,
307 initial_indent=indent,
308 subsequent_indent=indent).lstrip()
309 if optional_usage:
310 part = '\n' + indent + part
311 parts.append(part)
312 usage = ''.join(parts)
313
314 # prefix with 'usage:'
315 return '%s%s\n\n' % (prefix, usage)
316
317 def _format_actions_usage(self, actions):
318 parts = []
319 for action in actions:
320 if action.help is SUPPRESS:
321 continue
322
323 # produce all arg strings
324 if not action.option_strings:
325 parts.append(self._format_args(action, action.dest))
326
327 # produce the first way to invoke the option in brackets
328 else:
329 option_string = action.option_strings[0]
330
331 # if the Optional doesn't take a value, format is:
332 # -s or --long
333 if action.nargs == 0:
334 part = '%s' % option_string
335
336 # if the Optional takes a value, format is:
337 # -s ARGS or --long ARGS
338 else:
339 default = action.dest.upper()
340 args_string = self._format_args(action, default)
341 part = '%s %s' % (option_string, args_string)
342
343 # make it look optional if it's not required
344 if not action.required:
345 part = '[%s]' % part
346 parts.append(part)
347
348 return ' '.join(parts)
349
350 def _format_text(self, text):
351 text_width = self._width - self._current_indent
352 indent = ' ' * self._current_indent
353 return self._fill_text(text, text_width, indent) + '\n\n'
354
355 def _format_action(self, action):
356 # determine the required width and the entry label
357 help_position = min(self._action_max_length + 2,
358 self._max_help_position)
359 help_width = self._width - help_position
360 action_width = help_position - self._current_indent - 2
361 action_header = self._format_action_invocation(action)
362
363 # ho nelp; start on same line and add a final newline
364 if not action.help:
365 tup = self._current_indent, '', action_header
366 action_header = '%*s%s\n' % tup
367
368 # short action name; start on the same line and pad two spaces
369 elif len(action_header) <= action_width:
370 tup = self._current_indent, '', action_width, action_header
371 action_header = '%*s%-*s ' % tup
372 indent_first = 0
373
374 # long action name; start on the next line
375 else:
376 tup = self._current_indent, '', action_header
377 action_header = '%*s%s\n' % tup
378 indent_first = help_position
379
380 # collect the pieces of the action help
381 parts = [action_header]
382
383 # if there was help for the action, add lines of help text
384 if action.help:
385 help_text = self._expand_help(action)
386 help_lines = self._split_lines(help_text, help_width)
387 parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
388 for line in help_lines[1:]:
389 parts.append('%*s%s\n' % (help_position, '', line))
390
391 # or add a newline if the description doesn't end with one
392 elif not action_header.endswith('\n'):
393 parts.append('\n')
394
395 # if there are any sub-actions, add their help as well
396 for subaction in self._iter_indented_subactions(action):
397 parts.append(self._format_action(subaction))
398
399 # return a single string
400 return self._join_parts(parts)
401
402 def _format_action_invocation(self, action):
403 if not action.option_strings:
404 return self._format_metavar(action, action.dest)
405
406 else:
407 parts = []
408
409 # if the Optional doesn't take a value, format is:
410 # -s, --long
411 if action.nargs == 0:
412 parts.extend(action.option_strings)
413
414 # if the Optional takes a value, format is:
415 # -s ARGS, --long ARGS
416 else:
417 default = action.dest.upper()
418 args_string = self._format_args(action, default)
419 for option_string in action.option_strings:
420 parts.append('%s %s' % (option_string, args_string))
421
422 return ', '.join(parts)
423
424 def _format_metavar(self, action, default_metavar):
425 if action.metavar is not None:
426 name = action.metavar
427 elif action.choices is not None:
428 choice_strs = (str(choice) for choice in action.choices)
429 name = '{%s}' % ','.join(choice_strs)
430 else:
431 name = default_metavar
432 return name
433
434 def _format_args(self, action, default_metavar):
435 name = self._format_metavar(action, default_metavar)
436 if action.nargs is None:
437 result = name
438 elif action.nargs == OPTIONAL:
439 result = '[%s]' % name
440 elif action.nargs == ZERO_OR_MORE:
441 result = '[%s [%s ...]]' % (name, name)
442 elif action.nargs == ONE_OR_MORE:
443 result = '%s [%s ...]' % (name, name)
444 elif action.nargs is PARSER:
445 result = '%s ...' % name
446 else:
447 result = ' '.join([name] * action.nargs)
448 return result
449
450 def _expand_help(self, action):
451 params = dict(vars(action), prog=self._prog)
452 for name, value in params.items():
453 if value is SUPPRESS:
454 del params[name]
455 if params.get('choices') is not None:
456 choices_str = ', '.join(str(c) for c in params['choices'])
457 params['choices'] = choices_str
458 return action.help % params
459
460 def _iter_indented_subactions(self, action):
461 try:
462 get_subactions = action._get_subactions
463 except AttributeError:
464 pass
465 else:
466 self._indent()
467 for subaction in get_subactions():
468 yield subaction
469 self._dedent()
470
471 def _split_lines(self, text, width):
472 text = self._whitespace_matcher.sub(' ', text).strip()
473 return _textwrap.wrap(text, width)
474
475 def _fill_text(self, text, width, indent):
476 text = self._whitespace_matcher.sub(' ', text).strip()
477 return _textwrap.fill(text, width, initial_indent=indent,
478 subsequent_indent=indent)
479
480 class RawDescriptionHelpFormatter(HelpFormatter):
481
482 def _fill_text(self, text, width, indent):
483 return ''.join(indent + line for line in text.splitlines(True))
484
485 class RawTextHelpFormatter(RawDescriptionHelpFormatter):
486
487 def _split_lines(self, text, width):
488 return text.splitlines()
489
490 # =====================
491 # Options and Arguments
492 # =====================
493
494 class ArgumentError(Exception):
495 """ArgumentError(message, argument)
496
497 Raised whenever there was an error creating or using an argument
498 (optional or positional).
499
500 The string value of this exception is the message, augmented with
501 information about the argument that caused it.
502 """
503
504 def __init__(self, argument, message):
505 if argument.option_strings:
506 self.argument_name = '/'.join(argument.option_strings)
507 elif argument.metavar not in (None, SUPPRESS):
508 self.argument_name = argument.metavar
509 elif argument.dest not in (None, SUPPRESS):
510 self.argument_name = argument.dest
511 else:
512 self.argument_name = None
513 self.message = message
514
515 def __str__(self):
516 if self.argument_name is None:
517 format = '%(message)s'
518 else:
519 format = 'argument %(argument_name)s: %(message)s'
520 return format % dict(message=self.message,
521 argument_name=self.argument_name)
522
523 # ==============
524 # Action classes
525 # ==============
526
527 class Action(_AttributeHolder):
528 """Action(*strings, **options)
529
530 Action objects hold the information necessary to convert a
531 set of command-line arguments (possibly including an initial option
532 string) into the desired Python object(s).
533
534 Keyword Arguments:
535
536 option_strings -- A list of command-line option strings which
537 should be associated with this action.
538
539 dest -- The name of the attribute to hold the created object(s)
540
541 nargs -- The number of command-line arguments that should be consumed.
542 By default, one argument will be consumed and a single value will
543 be produced. Other values include:
544 * N (an integer) consumes N arguments (and produces a list)
545 * '?' consumes zero or one arguments
546 * '*' consumes zero or more arguments (and produces a list)
547 * '+' consumes one or more arguments (and produces a list)
548 Note that the difference between the default and nargs=1 is that
549 with the default, a single value will be produced, while with
550 nargs=1, a list containing a single value will be produced.
551
552 const -- The value to be produced if the option is specified and the
553 option uses an action that takes no values.
554
555 default -- The value to be produced if the option is not specified.
556
557 type -- The type which the command-line arguments should be converted
558 to, should be one of 'string', 'int', 'float', 'complex' or a
559 callable object that accepts a single string argument. If None,
560 'string' is assumed.
561
562 choices -- A container of values that should be allowed. If not None,
563 after a command-line argument has been converted to the appropriate
564 type, an exception will be raised if it is not a member of this
565 collection.
566
567 required -- True if the action must always be specified at the command
568 line. This is only meaningful for optional command-line arguments.
569
570 help -- The help string describing the argument.
571
572 metavar -- The name to be used for the option's argument with the help
573 string. If None, the 'dest' value will be used as the name.
574 """
575
576
577 def __init__(self,
578 option_strings,
579 dest,
580 nargs=None,
581 const=None,
582 default=None,
583 type=None,
584 choices=None,
585 required=False,
586 help=None,
587 metavar=None):
588 self.option_strings = option_strings
589 self.dest = dest
590 self.nargs = nargs
591 self.const = const
592 self.default = default
593 self.type = type
594 self.choices = choices
595 self.required = required
596 self.help = help
597 self.metavar = metavar
598
599 def _get_kwargs(self):
600 names = [
601 'option_strings',
602 'dest',
603 'nargs',
604 'const',
605 'default',
606 'type',
607 'choices',
608 'help',
609 'metavar'
610 ]
611 return [(name, getattr(self, name)) for name in names]
612
613 def __call__(self, parser, namespace, values, option_string=None):
614 raise NotImplementedError(_('.__call__() not defined'))
615
616 class _StoreAction(Action):
617 def __init__(self,
618 option_strings,
619 dest,
620 nargs=None,
621 const=None,
622 default=None,
623 type=None,
624 choices=None,
625 required=False,
626 help=None,
627 metavar=None):
628 if nargs == 0:
629 raise ValueError('nargs must be > 0')
630 if const is not None and nargs != OPTIONAL:
631 raise ValueError('nargs must be %r to supply const' % OPTIONAL)
632 super(_StoreAction, self).__init__(
633 option_strings=option_strings,
634 dest=dest,
635 nargs=nargs,
636 const=const,
637 default=default,
638 type=type,
639 choices=choices,
640 required=required,
641 help=help,
642 metavar=metavar)
643
644 def __call__(self, parser, namespace, values, option_string=None):
645 setattr(namespace, self.dest, values)
646
647 class _StoreConstAction(Action):
648 def __init__(self,
649 option_strings,
650 dest,
651 const,
652 default=None,
653 required=False,
654 help=None,
655 metavar=None):
656 super(_StoreConstAction, self).__init__(
657 option_strings=option_strings,
658 dest=dest,
659 nargs=0,
660 const=const,
661 default=default,
662 required=required,
663 help=help)
664
665 def __call__(self, parser, namespace, values, option_string=None):
666 setattr(namespace, self.dest, self.const)
667
668 class _StoreTrueAction(_StoreConstAction):
669 def __init__(self,
670 option_strings,
671 dest,
672 default=False,
673 required=False,
674 help=None):
675 super(_StoreTrueAction, self).__init__(
676 option_strings=option_strings,
677 dest=dest,
678 const=True,
679 default=default,
680 required=required,
681 help=help)
682
683 class _StoreFalseAction(_StoreConstAction):
684 def __init__(self,
685 option_strings,
686 dest,
687 default=True,
688 required=False,
689 help=None):
690 super(_StoreFalseAction, self).__init__(
691 option_strings=option_strings,
692 dest=dest,
693 const=False,
694 default=default,
695 required=required,
696 help=help)
697
698 class _AppendAction(Action):
699 def __init__(self,
700 option_strings,
701 dest,
702 nargs=None,
703 const=None,
704 default=None,
705 type=None,
706 choices=None,
707 required=False,
708 help=None,
709 metavar=None):
710 if nargs == 0:
711 raise ValueError('nargs must be > 0')
712 if const is not None and nargs != OPTIONAL:
713 raise ValueError('nargs must be %r to supply const' % OPTIONAL)
714 super(_AppendAction, self).__init__(
715 option_strings=option_strings,
716 dest=dest,
717 nargs=nargs,
718 const=const,
719 default=default,
720 type=type,
721 choices=choices,
722 required=required,
723 help=help,
724 metavar=metavar)
725
726 def __call__(self, parser, namespace, values, option_string=None):
727 _ensure_value(namespace, self.dest, []).append(values)
728
729 class _AppendConstAction(Action):
730 def __init__(self,
731 option_strings,
732 dest,
733 const,
734 default=None,
735 required=False,
736 help=None,
737 metavar=None):
738 super(_AppendConstAction, self).__init__(
739 option_strings=option_strings,
740 dest=dest,
741 nargs=0,
742 const=const,
743 default=default,
744 required=required,
745 help=help,
746 metavar=metavar)
747
748 def __call__(self, parser, namespace, values, option_string=None):
749 _ensure_value(namespace, self.dest, []).append(self.const)
750
751 class _CountAction(Action):
752 def __init__(self,
753 option_strings,
754 dest,
755 default=None,
756 required=False,
757 help=None):
758 super(_CountAction, self).__init__(
759 option_strings=option_strings,
760 dest=dest,
761 nargs=0,
762 default=default,
763 required=required,
764 help=help)
765
766 def __call__(self, parser, namespace, values, option_string=None):
767 new_count = _ensure_value(namespace, self.dest, 0) + 1
768 setattr(namespace, self.dest, new_count)
769
770 class _HelpAction(Action):
771 def __init__(self,
772 option_strings,
773 dest=SUPPRESS,
774 default=SUPPRESS,
775 help=None):
776 super(_HelpAction, self).__init__(
777 option_strings=option_strings,
778 dest=dest,
779 default=default,
780 nargs=0,
781 help=help)
782
783 def __call__(self, parser, namespace, values, option_string=None):
784 parser.print_help()
785 parser.exit()
786
787 class _VersionAction(Action):
788 def __init__(self,
789 option_strings,
790 dest=SUPPRESS,
791 default=SUPPRESS,
792 help=None):
793 super(_VersionAction, self).__init__(
794 option_strings=option_strings,
795 dest=dest,
796 default=default,
797 nargs=0,
798 help=help)
799
800 def __call__(self, parser, namespace, values, option_string=None):
801 parser.print_version()
802 parser.exit()
803
804 class _SubParsersAction(Action):
805
806 class _ChoicesPseudoAction(Action):
807 def __init__(self, name, help):
808 sup = super(_SubParsersAction._ChoicesPseudoAction, self)
809 sup.__init__(option_strings=[], dest=name, help=help)
810
811
812 def __init__(self,
813 option_strings,
814 prog,
815 parser_class,
816 dest=SUPPRESS,
817 help=None,
818 metavar=None):
819
820 self._prog_prefix = prog
821 self._parser_class = parser_class
822 self._name_parser_map = {}
823 self._choices_actions = []
824
825 super(_SubParsersAction, self).__init__(
826 option_strings=option_strings,
827 dest=dest,
828 nargs=PARSER,
829 choices=self._name_parser_map,
830 help=help,
831 metavar=metavar)
832
833 def add_parser(self, name, **kwargs):
834 # set prog from the existing prefix
835 if kwargs.get('prog') is None:
836 kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
837
838 # create a pseudo-action to hold the choice help
839 if 'help' in kwargs:
840 help = kwargs.pop('help')
841 choice_action = self._ChoicesPseudoAction(name, help)
842 self._choices_actions.append(choice_action)
843
844 # create the parser and add it to the map
845 parser = self._parser_class(**kwargs)
846 self._name_parser_map[name] = parser
847 return parser
848
849 def _get_subactions(self):
850 return self._choices_actions
851
852 def __call__(self, parser, namespace, values, option_string=None):
853 parser_name = values[0]
854 arg_strings = values[1:]
855
856 # set the parser name if requested
857 if self.dest is not SUPPRESS:
858 setattr(namespace, self.dest, parser_name)
859
860 # select the parser
861 try:
862 parser = self._name_parser_map[parser_name]
863 except KeyError:
864 tup = parser_name, ', '.join(self._name_parser_map)
865 msg = _('unknown parser %r (choices: %s)' % tup)
866 raise ArgumentError(self, msg)
867
868 # parse all the remaining options into the namespace
869 parser.parse_args(arg_strings, namespace)
870
871
872 # ==============
873 # Type classes
874 # ==============
875
876 class FileType(object):
877 """Factory for creating file object types
878
879 Instances of FileType are typically passed as type= arguments to the
880 ArgumentParser add_argument() method.
881
882 Keyword Arguments:
883 mode -- A string indicating how the file is to be opened. Accepts the
884 same values as the builtin open() function.
885 bufsize -- The file's desired buffer size. Accepts the same values as
886 the builtin open() function.
887 """
888 def __init__(self, mode='r', bufsize=None):
889 self._mode = mode
890 self._bufsize = bufsize
891
892 def __call__(self, string):
893 # the special argument "-" means sys.std{in,out}
894 if string == '-':
895 if self._mode == 'r':
896 return _sys.stdin
897 elif self._mode == 'w':
898 return _sys.stdout
899 else:
900 msg = _('argument "-" with mode %r' % self._mode)
901 raise ValueError(msg)
902
903 # all other arguments are used as file names
904 if self._bufsize:
905 return open(string, self._mode, self._bufsize)
906 else:
907 return open(string, self._mode)
908
909
910 # ===========================
911 # Optional and Positional Parsing
912 # ===========================
913
914 class Namespace(_AttributeHolder):
915
916 def __init__(self, **kwargs):
917 for name, value in kwargs.iteritems():
918 setattr(self, name, value)
919
920 def __eq__(self, other):
921 return vars(self) == vars(other)
922
923 def __ne__(self, other):
924 return not (self == other)
925
926
927 class _ActionsContainer(object):
928 def __init__(self,
929 description,
930 prefix_chars,
931 argument_default,
932 conflict_handler):
933 super(_ActionsContainer, self).__init__()
934
935 self.description = description
936 self.argument_default = argument_default
937 self.prefix_chars = prefix_chars
938 self.conflict_handler = conflict_handler
939
940 # set up registries
941 self._registries = {}
942
943 # register actions
944 self.register('action', None, _StoreAction)
945 self.register('action', 'store', _StoreAction)
946 self.register('action', 'store_const', _StoreConstAction)
947 self.register('action', 'store_true', _StoreTrueAction)
948 self.register('action', 'store_false', _StoreFalseAction)
949 self.register('action', 'append', _AppendAction)
950 self.register('action', 'append_const', _AppendConstAction)
951 self.register('action', 'count', _CountAction)
952 self.register('action', 'help', _HelpAction)
953 self.register('action', 'version', _VersionAction)
954 self.register('action', 'parsers', _SubParsersAction)
955
956 # raise an exception if the conflict handler is invalid
957 self._get_handler()
958
959 # action storage
960 self._optional_actions_list = []
961 self._positional_actions_list = []
962 self._positional_actions_full_list = []
963 self._option_strings = {}
964
965 # defaults storage
966 self._defaults = {}
967
968 # ====================
969 # Registration methods
970 # ====================
971
972 def register(self, registry_name, value, object):
973 registry = self._registries.setdefault(registry_name, {})
974 registry[value] = object
975
976 def _registry_get(self, registry_name, value, default=None):
977 return self._registries[registry_name].get(value, default)
978
979 # ==================================
980 # Namespace default settings methods
981 # ==================================
982
983 def set_defaults(self, **kwargs):
984 self._defaults.update(kwargs)
985
986 # if these defaults match any existing arguments, replace
987 # the previous default on the object with the new one
988 for action_list in [self._option_strings.values(),
989 self._positional_actions_full_list]:
990 for action in action_list:
991 if action.dest in kwargs:
992 action.default = kwargs[action.dest]
993
994 # =======================
995 # Adding argument actions
996 # =======================
997
998 def add_argument(self, *args, **kwargs):
999 """
1000 add_argument(dest, ..., name=value, ...)
1001 add_argument(option_string, option_string, ..., name=value, ...)
1002 """
1003
1004 # if no positional args are supplied or only one is supplied and
1005 # it doesn't look like an option string, parse a positional
1006 # argument
1007 chars = self.prefix_chars
1008 if not args or len(args) == 1 and args[0][0] not in chars:
1009 kwargs = self._get_positional_kwargs(*args, **kwargs)
1010
1011 # otherwise, we're adding an optional argument
1012 else:
1013 kwargs = self._get_optional_kwargs(*args, **kwargs)
1014
1015 # if no default was supplied, use the parser-level default
1016 if 'default' not in kwargs:
1017 dest = kwargs['dest']
1018 if dest in self._defaults:
1019 kwargs['default'] = self._defaults[dest]
1020 elif self.argument_default is not None:
1021 kwargs['default'] = self.argument_default
1022
1023 # create the action object, and add it to the parser
1024 action_class = self._pop_action_class(kwargs)
1025 action = action_class(**kwargs)
1026 return self._add_action(action)
1027
1028 def _add_action(self, action):
1029 # resolve any conflicts
1030 self._check_conflict(action)
1031
1032 # add to optional or positional list
1033 if action.option_strings:
1034 self._optional_actions_list.append(action)
1035 else:
1036 self._positional_actions_list.append(action)
1037 self._positional_actions_full_list.append(action)
1038 action.container = self
1039
1040 # index the action by any option strings it has
1041 for option_string in action.option_strings:
1042 self._option_strings[option_string] = action
1043
1044 # return the created action
1045 return action
1046
1047 def _add_container_actions(self, container):
1048 for action in container._optional_actions_list:
1049 self._add_action(action)
1050 for action in container._positional_actions_list:
1051 self._add_action(action)
1052
1053 def _get_positional_kwargs(self, dest, **kwargs):
1054 # make sure required is not specified
1055 if 'required' in kwargs:
1056 msg = _("'required' is an invalid argument for positionals")
1057 raise TypeError(msg)
1058
1059 # return the keyword arguments with no option strings
1060 return dict(kwargs, dest=dest, option_strings=[])
1061
1062 def _get_optional_kwargs(self, *args, **kwargs):
1063 # determine short and long option strings
1064 option_strings = []
1065 long_option_strings = []
1066 for option_string in args:
1067 # error on one-or-fewer-character option strings
1068 if len(option_string) < 2:
1069 msg = _('invalid option string %r: '
1070 'must be at least two characters long')
1071 raise ValueError(msg % option_string)
1072
1073 # error on strings that don't start with an appropriate prefix
1074 if not option_string[0] in self.prefix_chars:
1075 msg = _('invalid option string %r: '
1076 'must start with a character %r')
1077 tup = option_string, self.prefix_chars
1078 raise ValueError(msg % tup)
1079
1080 # error on strings that are all prefix characters
1081 if not (set(option_string) - set(self.prefix_chars)):
1082 msg = _('invalid option string %r: '
1083 'must contain characters other than %r')
1084 tup = option_string, self.prefix_chars
1085 raise ValueError(msg % tup)
1086
1087 # strings starting with two prefix characters are long options
1088 option_strings.append(option_string)
1089 if option_string[0] in self.prefix_chars:
1090 if option_string[1] in self.prefix_chars:
1091 long_option_strings.append(option_string)
1092
1093 # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
1094 dest = kwargs.pop('dest', None)
1095 if dest is None:
1096 if long_option_strings:
1097 dest_option_string = long_option_strings[0]
1098 else:
1099 dest_option_string = option_strings[0]
1100 dest = dest_option_string.lstrip(self.prefix_chars)
1101 dest = dest.replace('-', '_')
1102
1103 # return the updated keyword arguments
1104 return dict(kwargs, dest=dest, option_strings=option_strings)
1105
1106 def _pop_action_class(self, kwargs, default=None):
1107 action = kwargs.pop('action', default)
1108 return self._registry_get('action', action, action)
1109
1110 def _get_handler(self):
1111 # determine function from conflict handler string
1112 handler_func_name = '_handle_conflict_%s' % self.conflict_handler
1113 try:
1114 return getattr(self, handler_func_name)
1115 except AttributeError:
1116 msg = _('invalid conflict_resolution value: %r')
1117 raise ValueError(msg % self.conflict_handler)
1118
1119 def _check_conflict(self, action):
1120
1121 # find all options that conflict with this option
1122 confl_optionals = []
1123 for option_string in action.option_strings:
1124 if option_string in self._option_strings:
1125 confl_optional = self._option_strings[option_string]
1126 confl_optionals.append((option_string, confl_optional))
1127
1128 # resolve any conflicts
1129 if confl_optionals:
1130 conflict_handler = self._get_handler()
1131 conflict_handler(action, confl_optionals)
1132
1133 def _handle_conflict_error(self, action, conflicting_actions):
1134 message = _('conflicting option string(s): %s')
1135 conflict_string = ', '.join(option_string
1136 for option_string, action
1137 in conflicting_actions)
1138 raise ArgumentError(action, message % conflict_string)
1139
1140 def _handle_conflict_resolve(self, action, conflicting_actions):
1141
1142 # remove all conflicting options
1143 for option_string, action in conflicting_actions:
1144
1145 # remove the conflicting option
1146 action.option_strings.remove(option_string)
1147 self._option_strings.pop(option_string, None)
1148
1149 # if the option now has no option string, remove it from the
1150 # container holding it
1151 if not action.option_strings:
1152 action.container._optional_actions_list.remove(action)
1153
1154
1155 class _ArgumentGroup(_ActionsContainer):
1156
1157 def __init__(self, container, title=None, description=None, **kwargs):
1158 # add any missing keyword arguments by checking the container
1159 update = kwargs.setdefault
1160 update('conflict_handler', container.conflict_handler)
1161 update('prefix_chars', container.prefix_chars)
1162 update('argument_default', container.argument_default)
1163 super_init = super(_ArgumentGroup, self).__init__
1164 super_init(description=description, **kwargs)
1165
1166 self.title = title
1167 self._registries = container._registries
1168 self._positional_actions_full_list = container._positional_actions_full_list
1169 self._option_strings = container._option_strings
1170 self._defaults = container._defaults
1171
1172
1173 class ArgumentParser(_AttributeHolder, _ActionsContainer):
1174
1175 def __init__(self,
1176 prog=None,
1177 usage=None,
1178 description=None,
1179 epilog=None,
1180 version=None,
1181 parents=[],
1182 formatter_class=HelpFormatter,
1183 prefix_chars='-',
1184 argument_default=None,
1185 conflict_handler='error',
1186 add_help=True):
1187
1188 superinit = super(ArgumentParser, self).__init__
1189 superinit(description=description,
1190 prefix_chars=prefix_chars,
1191 argument_default=argument_default,
1192 conflict_handler=conflict_handler)
1193
1194 # default setting for prog
1195 if prog is None:
1196 prog = _os.path.basename(_sys.argv[0])
1197
1198 self.prog = prog
1199 self.usage = usage
1200 self.epilog = epilog
1201 self.version = version
1202 self.formatter_class = formatter_class
1203 self.add_help = add_help
1204
1205 self._argument_group_class = _ArgumentGroup
1206 self._has_subparsers = False
1207 self._argument_groups = []
1208
1209 # register types
1210 def identity(string):
1211 return string
1212 self.register('type', None, identity)
1213
1214 # add help and version arguments if necessary
1215 # (using explicit default to override global argument_default)
1216 if self.add_help:
1217 self.add_argument(
1218 '-h', '--help', action='help', default=SUPPRESS,
1219 help=_('show this help message and exit'))
1220 if self.version:
1221 self.add_argument(
1222 '-v', '--version', action='version', default=SUPPRESS,
1223 help=_("show program's version number and exit"))
1224
1225 # add parent arguments and defaults
1226 for parent in parents:
1227 self._add_container_actions(parent)
1228 try:
1229 defaults = parent._defaults
1230 except AttributeError:
1231 pass
1232 else:
1233 self._defaults.update(defaults)
1234
1235 # determines whether an "option" looks like a negative number
1236 self._negative_number_matcher = _re.compile(r'^-\d+|-\d*.\d+$')
1237
1238
1239 # =======================
1240 # Pretty __repr__ methods
1241 # =======================
1242
1243 def _get_kwargs(self):
1244 names = [
1245 'prog',
1246 'usage',
1247 'description',
1248 'version',
1249 'formatter_class',
1250 'conflict_handler',
1251 'add_help',
1252 ]
1253 return [(name, getattr(self, name)) for name in names]
1254
1255 # ==================================
1256 # Optional/Positional adding methods
1257 # ==================================
1258
1259 def add_argument_group(self, *args, **kwargs):
1260 group = self._argument_group_class(self, *args, **kwargs)
1261 self._argument_groups.append(group)
1262 return group
1263
1264 def add_subparsers(self, **kwargs):
1265 if self._has_subparsers:
1266 self.error(_('cannot have multiple subparser arguments'))
1267
1268 # add the parser class to the arguments if it's not present
1269 kwargs.setdefault('parser_class', type(self))
1270
1271 # prog defaults to the usage message of this parser, skipping
1272 # optional arguments and with no "usage:" prefix
1273 if kwargs.get('prog') is None:
1274 formatter = self._get_formatter()
1275 formatter.add_usage(self.usage, [],
1276 self._get_positional_actions(), '')
1277 kwargs['prog'] = formatter.format_help().strip()
1278
1279 # create the parsers action and add it to the positionals list
1280 parsers_class = self._pop_action_class(kwargs, 'parsers')
1281 action = parsers_class(option_strings=[], **kwargs)
1282 self._positional_actions_list.append(action)
1283 self._positional_actions_full_list.append(action)
1284 self._has_subparsers = True
1285
1286 # return the created parsers action
1287 return action
1288
1289 def _add_container_actions(self, container):
1290 super(ArgumentParser, self)._add_container_actions(container)
1291 try:
1292 groups = container._argument_groups
1293 except AttributeError:
1294 pass
1295 else:
1296 for group in groups:
1297 new_group = self.add_argument_group(
1298 title=group.title,
1299 description=group.description,
1300 conflict_handler=group.conflict_handler)
1301 new_group._add_container_actions(group)
1302
1303 def _get_optional_actions(self):
1304 actions = []
1305 actions.extend(self._optional_actions_list)
1306 for argument_group in self._argument_groups:
1307 actions.extend(argument_group._optional_actions_list)
1308 return actions
1309
1310 def _get_positional_actions(self):
1311 return list(self._positional_actions_full_list)
1312
1313
1314 # =====================================
1315 # Command line argument parsing methods
1316 # =====================================
1317
1318 def parse_args(self, args=None, namespace=None):
1319 # args default to the system args
1320 if args is None:
1321 args = _sys.argv[1:]
1322
1323 # default Namespace built from parser defaults
1324 if namespace is None:
1325 namespace = Namespace()
1326
1327 # add any action defaults that aren't present
1328 optional_actions = self._get_optional_actions()
1329 positional_actions = self._get_positional_actions()
1330 for action in optional_actions + positional_actions:
1331 if action.dest is not SUPPRESS:
1332 if not hasattr(namespace, action.dest):
1333 if action.default is not SUPPRESS:
1334 default = action.default
1335 if isinstance(action.default, basestring):
1336 default = self._get_value(action, default)
1337 setattr(namespace, action.dest, default)
1338
1339 # add any parser defaults that aren't present
1340 for dest, value in self._defaults.iteritems():
1341 if not hasattr(namespace, dest):
1342 setattr(namespace, dest, value)
1343
1344 # parse the arguments and exit if there are any errors
1345 try:
1346 result = self._parse_args(args, namespace)
1347 except ArgumentError, err:
1348 self.error(str(err))
1349
1350 # make sure all required optionals are present
1351 for action in self._get_optional_actions():
1352 if action.required:
1353 if getattr(result, action.dest, None) is None:
1354 opt_strs = '/'.join(action.option_strings)
1355 msg = _('option %s is required' % opt_strs)
1356 self.error(msg)
1357
1358 # return the parsed arguments
1359 return result
1360
1361 def _parse_args(self, arg_strings, namespace):
1362
1363 # find all option indices, and determine the arg_string_pattern
1364 # which has an 'O' if there is an option at an index,
1365 # an 'A' if there is an argument, or a '-' if there is a '--'
1366 option_string_indices = {}
1367 arg_string_pattern_parts = []
1368 arg_strings_iter = iter(arg_strings)
1369 for i, arg_string in enumerate(arg_strings_iter):
1370
1371 # all args after -- are non-options
1372 if arg_string == '--':
1373 arg_string_pattern_parts.append('-')
1374 for arg_string in arg_strings_iter:
1375 arg_string_pattern_parts.append('A')
1376
1377 # otherwise, add the arg to the arg strings
1378 # and note the index if it was an option
1379 else:
1380 option_tuple = self._parse_optional(arg_string)
1381 if option_tuple is None:
1382 pattern = 'A'
1383 else:
1384 option_string_indices[i] = option_tuple
1385 pattern = 'O'
1386 arg_string_pattern_parts.append(pattern)
1387
1388 # join the pieces together to form the pattern
1389 arg_strings_pattern = ''.join(arg_string_pattern_parts)
1390
1391 # converts arg strings to the appropriate and then takes the action
1392 def take_action(action, argument_strings, option_string=None):
1393 argument_values = self._get_values(action, argument_strings)
1394 # take the action if we didn't receive a SUPPRESS value
1395 # (e.g. from a default)
1396 if argument_values is not SUPPRESS:
1397 action(self, namespace, argument_values, option_string)
1398
1399 # function to convert arg_strings into an optional action
1400 def consume_optional(start_index):
1401
1402 # determine the optional action and parse any explicit
1403 # argument out of the option string
1404 option_tuple = option_string_indices[start_index]
1405 action, option_string, explicit_arg = option_tuple
1406
1407 # loop because single-dash options can be chained
1408 # (e.g. -xyz is the same as -x -y -z if no args are required)
1409 match_argument = self._match_argument
1410 action_tuples = []
1411 while True:
1412
1413 # if we found no optional action, raise an error
1414 if action is None:
1415 self.error(_('no such option: %s') % option_string)
1416
1417 # if there is an explicit argument, try to match the
1418 # optional's string arguments to only this
1419 if explicit_arg is not None:
1420 arg_count = match_argument(action, 'A')
1421
1422 # if the action is a single-dash option and takes no
1423 # arguments, try to parse more single-dash options out
1424 # of the tail of the option string
1425 chars = self.prefix_chars
1426 if arg_count == 0 and option_string[1] not in chars:
1427 action_tuples.append((action, [], option_string))
1428 parse_optional = self._parse_optional
1429 for char in self.prefix_chars:
1430 option_string = char + explicit_arg
1431 option_tuple = parse_optional(option_string)
1432 if option_tuple[0] is not None:
1433 break
1434 else:
1435 msg = _('ignored explicit argument %r')
1436 raise ArgumentError(action, msg % explicit_arg)
1437
1438 # set the action, etc. for the next loop iteration
1439 action, option_string, explicit_arg = option_tuple
1440
1441 # if the action expect exactly one argument, we've
1442 # successfully matched the option; exit the loop
1443 elif arg_count == 1:
1444 stop = start_index + 1
1445 args = [explicit_arg]
1446 action_tuples.append((action, args, option_string))
1447 break
1448
1449 # error if a double-dash option did not use the
1450 # explicit argument
1451 else:
1452 msg = _('ignored explicit argument %r')
1453 raise ArgumentError(action, msg % explicit_arg)
1454
1455 # if there is no explicit argument, try to match the
1456 # optional's string arguments with the following strings
1457 # if successful, exit the loop
1458 else:
1459 start = start_index + 1
1460 selected_patterns = arg_strings_pattern[start:]
1461 arg_count = match_argument(action, selected_patterns)
1462 stop = start + arg_count
1463 args = arg_strings[start:stop]
1464 action_tuples.append((action, args, option_string))
1465 break
1466
1467 # add the Optional to the list and return the index at which
1468 # the Optional's string args stopped
1469 assert action_tuples
1470 for action, args, option_string in action_tuples:
1471 take_action(action, args, option_string)
1472 return stop
1473
1474 # the list of Positionals left to be parsed; this is modified
1475 # by consume_positionals()
1476 positionals = self._get_positional_actions()
1477
1478 # function to convert arg_strings into positional actions
1479 def consume_positionals(start_index):
1480 # match as many Positionals as possible
1481 match_partial = self._match_arguments_partial
1482 selected_pattern = arg_strings_pattern[start_index:]
1483 arg_counts = match_partial(positionals, selected_pattern)
1484
1485 # slice off the appropriate arg strings for each Positional
1486 # and add the Positional and its args to the list
1487 for action, arg_count in zip(positionals, arg_counts):
1488 args = arg_strings[start_index: start_index + arg_count]
1489 start_index += arg_count
1490 take_action(action, args)
1491
1492 # slice off the Positionals that we just parsed and return the
1493 # index at which the Positionals' string args stopped
1494 positionals[:] = positionals[len(arg_counts):]
1495 return start_index
1496
1497 # consume Positionals and Optionals alternately, until we have
1498 # passed the last option string
1499 start_index = 0
1500 if option_string_indices:
1501 max_option_string_index = max(option_string_indices)
1502 else:
1503 max_option_string_index = -1
1504 while start_index <= max_option_string_index:
1505
1506 # consume any Positionals preceding the next option
1507 next_option_string_index = min(
1508 index
1509 for index in option_string_indices
1510 if index >= start_index)
1511 if start_index != next_option_string_index:
1512 positionals_end_index = consume_positionals(start_index)
1513
1514 # only try to parse the next optional if we didn't consume
1515 # the option string during the positionals parsing
1516 if positionals_end_index > start_index:
1517 start_index = positionals_end_index
1518 continue
1519 else:
1520 start_index = positionals_end_index
1521
1522 # if we consumed all the positionals we could and we're not
1523 # at the index of an option string, there were unparseable
1524 # arguments
1525 if start_index not in option_string_indices:
1526 msg = _('extra arguments found: %s')
1527 extras = arg_strings[start_index:next_option_string_index]
1528 self.error(msg % ' '.join(extras))
1529
1530 # consume the next optional and any arguments for it
1531 start_index = consume_optional(start_index)
1532
1533 # consume any positionals following the last Optional
1534 stop_index = consume_positionals(start_index)
1535
1536 # if we didn't consume all the argument strings, there were too
1537 # many supplied
1538 if stop_index != len(arg_strings):
1539 extras = arg_strings[stop_index:]
1540 self.error(_('extra arguments found: %s') % ' '.join(extras))
1541
1542 # if we didn't use all the Positional objects, there were too few
1543 # arg strings supplied.
1544 if positionals:
1545 self.error(_('too few arguments'))
1546
1547 # return the updated namespace
1548 return namespace
1549
1550 def _match_argument(self, action, arg_strings_pattern):
1551 # match the pattern for this action to the arg strings
1552 nargs_pattern = self._get_nargs_pattern(action)
1553 match = _re.match(nargs_pattern, arg_strings_pattern)
1554
1555 # raise an exception if we weren't able to find a match
1556 if match is None:
1557 nargs_errors = {
1558 None:_('expected one argument'),
1559 OPTIONAL:_('expected at most one argument'),
1560 ONE_OR_MORE:_('expected at least one argument')
1561 }
1562 default = _('expected %s argument(s)') % action.nargs
1563 msg = nargs_errors.get(action.nargs, default)
1564 raise ArgumentError(action, msg)
1565
1566 # return the number of arguments matched
1567 return len(match.group(1))
1568
1569 def _match_arguments_partial(self, actions, arg_strings_pattern):
1570 # progressively shorten the actions list by slicing off the
1571 # final actions until we find a match
1572 result = []
1573 for i in xrange(len(actions), 0, -1):
1574 actions_slice = actions[:i]
1575 pattern = ''.join(self._get_nargs_pattern(action)
1576 for action in actions_slice)
1577 match = _re.match(pattern, arg_strings_pattern)
1578 if match is not None:
1579 result.extend(len(string) for string in match.groups())
1580 break
1581
1582 # return the list of arg string counts
1583 return result
1584
1585 def _parse_optional(self, arg_string):
1586 # if it doesn't start with a prefix, it was meant to be positional
1587 if not arg_string[0] in self.prefix_chars:
1588 return None
1589
1590 # if it's just dashes, it was meant to be positional
1591 if not arg_string.strip('-'):
1592 return None
1593
1594 # if the option string is present in the parser, return the action
1595 if arg_string in self._option_strings:
1596 action = self._option_strings[arg_string]
1597 return action, arg_string, None
1598
1599 # search through all possible prefixes of the option string
1600 # and all actions in the parser for possible interpretations
1601 option_tuples = []
1602 prefix_tuples = self._get_option_prefix_tuples(arg_string)
1603 for option_string in self._option_strings:
1604 for option_prefix, explicit_arg in prefix_tuples:
1605 if option_string.startswith(option_prefix):
1606 action = self._option_strings[option_string]
1607 tup = action, option_string, explicit_arg
1608 option_tuples.append(tup)
1609 break
1610
1611 # if multiple actions match, the option string was ambiguous
1612 if len(option_tuples) > 1:
1613 options = ', '.join(opt_str for _, opt_str, _ in option_tuples)
1614 tup = arg_string, options
1615 self.error(_('ambiguous option: %s could match %s') % tup)
1616
1617 # if exactly one action matched, this segmentation is good,
1618 # so return the parsed action
1619 elif len(option_tuples) == 1:
1620 option_tuple, = option_tuples
1621 return option_tuple
1622
1623 # if it was not found as an option, but it looks like a negative
1624 # number, it was meant to be positional
1625 if self._negative_number_matcher.match(arg_string):
1626 return None
1627
1628 # it was meant to be an optional but there is no such option
1629 # in this parser (though it might be a valid option in a subparser)
1630 return None, arg_string, None
1631
1632 def _get_option_prefix_tuples(self, option_string):
1633 result = []
1634
1635 # option strings starting with two prefix characters are only
1636 # split at the '='
1637 chars = self.prefix_chars
1638 if option_string[0] in chars and option_string[1] in chars:
1639 if '=' in option_string:
1640 option_prefix, explicit_arg = option_string.split('=', 1)
1641 else:
1642 option_prefix = option_string
1643 explicit_arg = None
1644 tup = option_prefix, explicit_arg
1645 result.append(tup)
1646
1647 # option strings starting with a single prefix character are
1648 # split at all indices
1649 else:
1650 for first_index, char in enumerate(option_string):
1651 if char not in self.prefix_chars:
1652 break
1653 for i in xrange(len(option_string), first_index, -1):
1654 tup = option_string[:i], option_string[i:] or None
1655 result.append(tup)
1656
1657 # return the collected prefix tuples
1658 return result
1659
1660 def _get_nargs_pattern(self, action):
1661 # in all examples below, we have to allow for '--' args
1662 # which are represented as '-' in the pattern
1663 nargs = action.nargs
1664
1665 # the default (None) is assumed to be a single argument
1666 if nargs is None:
1667 nargs_pattern = '(-*A-*)'
1668
1669 # allow zero or one arguments
1670 elif nargs == OPTIONAL:
1671 nargs_pattern = '(-*A?-*)'
1672
1673 # allow zero or more arguments
1674 elif nargs == ZERO_OR_MORE:
1675 nargs_pattern = '(-*[A-]*)'
1676
1677 # allow one or more arguments
1678 elif nargs == ONE_OR_MORE:
1679 nargs_pattern = '(-*A[A-]*)'
1680
1681 # allow one argument followed by any number of options or arguments
1682 elif nargs is PARSER:
1683 nargs_pattern = '(-*A[-AO]*)'
1684
1685 # all others should be integers
1686 else:
1687 nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
1688
1689 # if this is an optional action, -- is not allowed
1690 if action.option_strings:
1691 nargs_pattern = nargs_pattern.replace('-*', '')
1692 nargs_pattern = nargs_pattern.replace('-', '')
1693
1694 # return the pattern
1695 return nargs_pattern
1696
1697 # ========================
1698 # Value conversion methods
1699 # ========================
1700
1701 def _get_values(self, action, arg_strings):
1702 # for everything but PARSER args, strip out '--'
1703 if action.nargs is not PARSER:
1704 arg_strings = [s for s in arg_strings if s != '--']
1705
1706 # optional argument produces a default when not present
1707 if not arg_strings and action.nargs == OPTIONAL:
1708 if action.option_strings:
1709 value = action.const
1710 else:
1711 value = action.default
1712 if isinstance(value, basestring):
1713 value = self._get_value(action, value)
1714 self._check_value(action, value)
1715
1716 # when nargs='*' on a positional, if there were no command-line
1717 # args, use the default if it is anything other than None
1718 elif (not arg_strings and action.nargs == ZERO_OR_MORE and
1719 not action.option_strings):
1720 if action.default is not None:
1721 value = action.default
1722 else:
1723 value = arg_strings
1724 self._check_value(action, value)
1725
1726 # single argument or optional argument produces a single value
1727 elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
1728 arg_string, = arg_strings
1729 value = self._get_value(action, arg_string)
1730 self._check_value(action, value)
1731
1732 # PARSER arguments convert all values, but check only the first
1733 elif action.nargs is PARSER:
1734 value = list(self._get_value(action, v) for v in arg_strings)
1735 self._check_value(action, value[0])
1736
1737 # all other types of nargs produce a list
1738 else:
1739 value = list(self._get_value(action, v) for v in arg_strings)
1740 for v in value:
1741 self._check_value(action, v)
1742
1743 # return the converted value
1744 return value
1745
1746 def _get_value(self, action, arg_string):
1747 type_func = self._registry_get('type', action.type, action.type)
1748 if not callable(type_func):
1749 msg = _('%r is not callable')
1750 raise ArgumentError(action, msg % type_func)
1751
1752 # convert the value to the appropriate type
1753 try:
1754 result = type_func(arg_string)
1755
1756 # TypeErrors or ValueErrors indicate errors
1757 except (TypeError, ValueError):
1758 name = getattr(action.type, '__name__', repr(action.type))
1759 msg = _('invalid %s value: %r')
1760 raise ArgumentError(action, msg % (name, arg_string))
1761
1762 # return the converted value
1763 return result
1764
1765 def _check_value(self, action, value):
1766 # converted value must be one of the choices (if specified)
1767 if action.choices is not None and value not in action.choices:
1768 tup = value, ', '.join(map(repr, action.choices))
1769 msg = _('invalid choice: %r (choose from %s)') % tup
1770 raise ArgumentError(action, msg)
1771
1772
1773
1774 # =======================
1775 # Help-formatting methods
1776 # =======================
1777
1778 def format_usage(self):
1779 formatter = self._get_formatter()
1780 formatter.add_usage(self.usage,
1781 self._get_optional_actions(),
1782 self._get_positional_actions())
1783 return formatter.format_help()
1784
1785 def format_help(self):
1786 formatter = self._get_formatter()
1787
1788 # usage
1789 formatter.add_usage(self.usage,
1790 self._get_optional_actions(),
1791 self._get_positional_actions())
1792
1793 # description
1794 formatter.add_text(self.description)
1795
1796 # positionals
1797 formatter.start_section(_('positional arguments'))
1798 formatter.add_arguments(self._positional_actions_list)
1799 formatter.end_section()
1800
1801 # optionals
1802 formatter.start_section(_('optional arguments'))
1803 formatter.add_arguments(self._optional_actions_list)
1804 formatter.end_section()
1805
1806 # user-defined groups
1807 for argument_group in self._argument_groups:
1808 formatter.start_section(argument_group.title)
1809 formatter.add_text(argument_group.description)
1810 formatter.add_arguments(argument_group._positional_actions_list)
1811 formatter.add_arguments(argument_group._optional_actions_list)
1812 formatter.end_section()
1813
1814 # epilog
1815 formatter.add_text(self.epilog)
1816
1817 # determine help from format above
1818 return formatter.format_help()
1819
1820 def format_version(self):
1821 formatter = self._get_formatter()
1822 formatter.add_text(self.version)
1823 return formatter.format_help()
1824
1825 def _get_formatter(self):
1826 return self.formatter_class(prog=self.prog)
1827
1828 # =====================
1829 # Help-printing methods
1830 # =====================
1831
1832 def print_usage(self, file=None):
1833 self._print_message(self.format_usage(), file)
1834
1835 def print_help(self, file=None):
1836 self._print_message(self.format_help(), file)
1837
1838 def print_version(self, file=None):
1839 self._print_message(self.format_version(), file)
1840
1841 def _print_message(self, message, file=None):
1842 if message:
1843 if file is None:
1844 file = _sys.stderr
1845 file.write(message)
1846
1847
1848 # ===============
1849 # Exiting methods
1850 # ===============
1851
1852 def exit(self, status=0, message=None):
1853 if message:
1854 _sys.stderr.write(message)
1855 _sys.exit(status)
1856
1857 def error(self, message):
1858 """error(message: string)
1859
1860 Prints a usage message incorporating the message to stderr and
1861 exits.
1862
1863 If you override this in a subclass, it should not return -- it
1864 should either exit or raise an exception.
1865 """
1866 self.print_usage(_sys.stderr)
1867 self.exit(2, _('%s: error: %s\n') % (self.prog, message))
@@ -0,0 +1,155 b''
1 # encoding: utf-8
2
3 """This file contains unittests for the frontendbase module."""
4
5 __docformat__ = "restructuredtext en"
6
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
13
14 #---------------------------------------------------------------------------
15 # Imports
16 #---------------------------------------------------------------------------
17
18 import unittest
19
20 try:
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend import frontendbase
23 from IPython.kernel.engineservice import EngineService
24 except ImportError:
25 import nose
26 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
27
28 from IPython.testing.decorators import skip
29
30 class FrontEndCallbackChecker(AsyncFrontEndBase):
31 """FrontEndBase subclass for checking callbacks"""
32 def __init__(self, engine=None, history=None):
33 super(FrontEndCallbackChecker, self).__init__(engine=engine,
34 history=history)
35 self.updateCalled = False
36 self.renderResultCalled = False
37 self.renderErrorCalled = False
38
39 def update_cell_prompt(self, result, blockID=None):
40 self.updateCalled = True
41 return result
42
43 def render_result(self, result):
44 self.renderResultCalled = True
45 return result
46
47
48 def render_error(self, failure):
49 self.renderErrorCalled = True
50 return failure
51
52
53
54
55 class TestAsyncFrontendBase(unittest.TestCase):
56 def setUp(self):
57 """Setup the EngineService and FrontEndBase"""
58
59 self.fb = FrontEndCallbackChecker(engine=EngineService())
60
61 def test_implements_IFrontEnd(self):
62 assert(frontendbase.IFrontEnd.implementedBy(
63 AsyncFrontEndBase))
64
65 def test_is_complete_returns_False_for_incomplete_block(self):
66 """"""
67
68 block = """def test(a):"""
69
70 assert(self.fb.is_complete(block) == False)
71
72 def test_is_complete_returns_True_for_complete_block(self):
73 """"""
74
75 block = """def test(a): pass"""
76
77 assert(self.fb.is_complete(block))
78
79 block = """a=3"""
80
81 assert(self.fb.is_complete(block))
82
83 def test_blockID_added_to_result(self):
84 block = """3+3"""
85
86 d = self.fb.execute(block, blockID='TEST_ID')
87
88 d.addCallback(self.checkBlockID, expected='TEST_ID')
89
90 def test_blockID_added_to_failure(self):
91 block = "raise Exception()"
92
93 d = self.fb.execute(block,blockID='TEST_ID')
94 d.addErrback(self.checkFailureID, expected='TEST_ID')
95
96 def checkBlockID(self, result, expected=""):
97 assert(result['blockID'] == expected)
98
99
100 def checkFailureID(self, failure, expected=""):
101 assert(failure.blockID == expected)
102
103
104 def test_callbacks_added_to_execute(self):
105 """test that
106 update_cell_prompt
107 render_result
108
109 are added to execute request
110 """
111
112 d = self.fb.execute("10+10")
113 d.addCallback(self.checkCallbacks)
114
115 def checkCallbacks(self, result):
116 assert(self.fb.updateCalled)
117 assert(self.fb.renderResultCalled)
118
119 @skip("This test fails and lead to an unhandled error in a Deferred.")
120 def test_error_callback_added_to_execute(self):
121 """test that render_error called on execution error"""
122
123 d = self.fb.execute("raise Exception()")
124 d.addCallback(self.checkRenderError)
125
126 def checkRenderError(self, result):
127 assert(self.fb.renderErrorCalled)
128
129 def test_history_returns_expected_block(self):
130 """Make sure history browsing doesn't fail"""
131
132 blocks = ["a=1","a=2","a=3"]
133 for b in blocks:
134 d = self.fb.execute(b)
135
136 # d is now the deferred for the last executed block
137 d.addCallback(self.historyTests, blocks)
138
139
140 def historyTests(self, result, blocks):
141 """historyTests"""
142
143 assert(len(blocks) >= 3)
144 assert(self.fb.get_history_previous("") == blocks[-2])
145 assert(self.fb.get_history_previous("") == blocks[-3])
146 assert(self.fb.get_history_next() == blocks[-2])
147
148
149 def test_history_returns_none_at_startup(self):
150 """test_history_returns_none_at_startup"""
151
152 assert(self.fb.get_history_previous("")==None)
153 assert(self.fb.get_history_next()==None)
154
155
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,170 +1,182 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for coloring text in ANSI terminals.
3 3
4 4 $Id: ColorANSI.py 2167 2007-03-21 06:57:50Z fperez $"""
5 5
6 6 #*****************************************************************************
7 7 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
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 from IPython import Release
14 14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 15 __license__ = Release.license
16 16
17 17 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
18 18
19 19 import os
20 20
21 21 from IPython.ipstruct import Struct
22 22
23 23 def make_color_table(in_class):
24 24 """Build a set of color attributes in a class.
25 25
26 26 Helper function for building the *TermColors classes."""
27 27
28 28 color_templates = (
29 # Dark colors
29 30 ("Black" , "0;30"),
30 31 ("Red" , "0;31"),
31 32 ("Green" , "0;32"),
32 33 ("Brown" , "0;33"),
33 34 ("Blue" , "0;34"),
34 35 ("Purple" , "0;35"),
35 36 ("Cyan" , "0;36"),
36 37 ("LightGray" , "0;37"),
38 # Light colors
37 39 ("DarkGray" , "1;30"),
38 40 ("LightRed" , "1;31"),
39 41 ("LightGreen" , "1;32"),
40 42 ("Yellow" , "1;33"),
41 43 ("LightBlue" , "1;34"),
42 44 ("LightPurple" , "1;35"),
43 45 ("LightCyan" , "1;36"),
44 ("White" , "1;37"), )
46 ("White" , "1;37"),
47 # Blinking colors. Probably should not be used in anything serious.
48 ("BlinkBlack" , "5;30"),
49 ("BlinkRed" , "5;31"),
50 ("BlinkGreen" , "5;32"),
51 ("BlinkYellow" , "5;33"),
52 ("BlinkBlue" , "5;34"),
53 ("BlinkPurple" , "5;35"),
54 ("BlinkCyan" , "5;36"),
55 ("BlinkLightGray", "5;37"),
56 )
45 57
46 58 for name,value in color_templates:
47 59 setattr(in_class,name,in_class._base % value)
48 60
49 61 class TermColors:
50 62 """Color escape sequences.
51 63
52 64 This class defines the escape sequences for all the standard (ANSI?)
53 65 colors in terminals. Also defines a NoColor escape which is just the null
54 66 string, suitable for defining 'dummy' color schemes in terminals which get
55 67 confused by color escapes.
56 68
57 69 This class should be used as a mixin for building color schemes."""
58 70
59 71 NoColor = '' # for color schemes in color-less terminals.
60 72 Normal = '\033[0m' # Reset normal coloring
61 73 _base = '\033[%sm' # Template for all other colors
62 74
63 75 # Build the actual color table as a set of class attributes:
64 76 make_color_table(TermColors)
65 77
66 78 class InputTermColors:
67 79 """Color escape sequences for input prompts.
68 80
69 81 This class is similar to TermColors, but the escapes are wrapped in \001
70 82 and \002 so that readline can properly know the length of each line and
71 83 can wrap lines accordingly. Use this class for any colored text which
72 84 needs to be used in input prompts, such as in calls to raw_input().
73 85
74 86 This class defines the escape sequences for all the standard (ANSI?)
75 87 colors in terminals. Also defines a NoColor escape which is just the null
76 88 string, suitable for defining 'dummy' color schemes in terminals which get
77 89 confused by color escapes.
78 90
79 91 This class should be used as a mixin for building color schemes."""
80 92
81 93 NoColor = '' # for color schemes in color-less terminals.
82 94
83 95 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
84 96 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
85 97 Normal = '\033[0m' # Reset normal coloring
86 98 _base = '\033[%sm' # Template for all other colors
87 99 else:
88 100 Normal = '\001\033[0m\002' # Reset normal coloring
89 101 _base = '\001\033[%sm\002' # Template for all other colors
90 102
91 103 # Build the actual color table as a set of class attributes:
92 104 make_color_table(InputTermColors)
93 105
94 106 class ColorScheme:
95 107 """Generic color scheme class. Just a name and a Struct."""
96 108 def __init__(self,__scheme_name_,colordict=None,**colormap):
97 109 self.name = __scheme_name_
98 110 if colordict is None:
99 111 self.colors = Struct(**colormap)
100 112 else:
101 113 self.colors = Struct(colordict)
102 114
103 115 def copy(self,name=None):
104 116 """Return a full copy of the object, optionally renaming it."""
105 117 if name is None:
106 118 name = self.name
107 119 return ColorScheme(name,self.colors.__dict__)
108 120
109 121 class ColorSchemeTable(dict):
110 122 """General class to handle tables of color schemes.
111 123
112 124 It's basically a dict of color schemes with a couple of shorthand
113 125 attributes and some convenient methods.
114 126
115 127 active_scheme_name -> obvious
116 128 active_colors -> actual color table of the active scheme"""
117 129
118 130 def __init__(self,scheme_list=None,default_scheme=''):
119 131 """Create a table of color schemes.
120 132
121 133 The table can be created empty and manually filled or it can be
122 134 created with a list of valid color schemes AND the specification for
123 135 the default active scheme.
124 136 """
125 137
126 138 # create object attributes to be set later
127 139 self.active_scheme_name = ''
128 140 self.active_colors = None
129 141
130 142 if scheme_list:
131 143 if default_scheme == '':
132 144 raise ValueError,'you must specify the default color scheme'
133 145 for scheme in scheme_list:
134 146 self.add_scheme(scheme)
135 147 self.set_active_scheme(default_scheme)
136 148
137 149 def copy(self):
138 150 """Return full copy of object"""
139 151 return ColorSchemeTable(self.values(),self.active_scheme_name)
140 152
141 153 def add_scheme(self,new_scheme):
142 154 """Add a new color scheme to the table."""
143 155 if not isinstance(new_scheme,ColorScheme):
144 156 raise ValueError,'ColorSchemeTable only accepts ColorScheme instances'
145 157 self[new_scheme.name] = new_scheme
146 158
147 159 def set_active_scheme(self,scheme,case_sensitive=0):
148 160 """Set the currently active scheme.
149 161
150 162 Names are by default compared in a case-insensitive way, but this can
151 163 be changed by setting the parameter case_sensitive to true."""
152 164
153 165 scheme_names = self.keys()
154 166 if case_sensitive:
155 167 valid_schemes = scheme_names
156 168 scheme_test = scheme
157 169 else:
158 170 valid_schemes = [s.lower() for s in scheme_names]
159 171 scheme_test = scheme.lower()
160 172 try:
161 173 scheme_idx = valid_schemes.index(scheme_test)
162 174 except ValueError:
163 175 raise ValueError,'Unrecognized color scheme: ' + scheme + \
164 176 '\nValid schemes: '+str(scheme_names).replace("'', ",'')
165 177 else:
166 178 active = scheme_names[scheme_idx]
167 179 self.active_scheme_name = active
168 180 self.active_colors = self[active].colors
169 181 # Now allow using '' as an index for the current active scheme
170 182 self[''] = self[active]
@@ -1,394 +1,400 b''
1 1
2 2 """ Implementations for various useful completers
3 3
4 4 See Extensions/ipy_stock_completers.py on examples of how to enable a completer,
5 5 but the basic idea is to do:
6 6
7 7 ip.set_hook('complete_command', svn_completer, str_key = 'svn')
8 8
9 9 """
10 10 import IPython.ipapi
11 11 import glob,os,shlex,sys
12 12 import inspect
13 13 from time import time
14 14 from zipimport import zipimporter
15 15 ip = IPython.ipapi.get()
16 16
17 17 try:
18 18 set
19 19 except:
20 20 from sets import Set as set
21 21
22 22 TIMEOUT_STORAGE = 3 #Time in seconds after which the rootmodules will be stored
23 23 TIMEOUT_GIVEUP = 20 #Time in seconds after which we give up
24 24
25 25 def quick_completer(cmd, completions):
26 26 """ Easily create a trivial completer for a command.
27 27
28 28 Takes either a list of completions, or all completions in string
29 29 (that will be split on whitespace)
30 30
31 31 Example::
32 32
33 33 [d:\ipython]|1> import ipy_completers
34 34 [d:\ipython]|2> ipy_completers.quick_completer('foo', ['bar','baz'])
35 35 [d:\ipython]|3> foo b<TAB>
36 36 bar baz
37 37 [d:\ipython]|3> foo ba
38 38 """
39 39 if isinstance(completions, basestring):
40 40
41 41 completions = completions.split()
42 42 def do_complete(self,event):
43 43 return completions
44 44
45 45 ip.set_hook('complete_command',do_complete, str_key = cmd)
46 46
47 47 def getRootModules():
48 48 """
49 49 Returns a list containing the names of all the modules available in the
50 50 folders of the pythonpath.
51 51 """
52 52 modules = []
53 53 if ip.db.has_key('rootmodules'):
54 54 return ip.db['rootmodules']
55 55 t = time()
56 56 store = False
57 57 for path in sys.path:
58 58 modules += moduleList(path)
59 59 if time() - t >= TIMEOUT_STORAGE and not store:
60 60 store = True
61 61 print "\nCaching the list of root modules, please wait!"
62 62 print "(This will only be done once - type '%rehashx' to " + \
63 63 "reset cache!)"
64 64 print
65 65 if time() - t > TIMEOUT_GIVEUP:
66 66 print "This is taking too long, we give up."
67 67 print
68 68 ip.db['rootmodules'] = []
69 69 return []
70 70
71 71 modules += sys.builtin_module_names
72 72
73 73 modules = list(set(modules))
74 74 if '__init__' in modules:
75 75 modules.remove('__init__')
76 76 modules = list(set(modules))
77 77 if store:
78 78 ip.db['rootmodules'] = modules
79 79 return modules
80 80
81 81 def moduleList(path):
82 82 """
83 83 Return the list containing the names of the modules available in the given
84 84 folder.
85 85 """
86 86
87 87 if os.path.isdir(path):
88 88 folder_list = os.listdir(path)
89 89 elif path.endswith('.egg'):
90 90 try:
91 91 folder_list = [f for f in zipimporter(path)._files]
92 92 except:
93 93 folder_list = []
94 94 else:
95 95 folder_list = []
96 96 #folder_list = glob.glob(os.path.join(path,'*'))
97 97 folder_list = [p for p in folder_list \
98 98 if os.path.exists(os.path.join(path, p,'__init__.py'))\
99 99 or p[-3:] in ('.py','.so')\
100 100 or p[-4:] in ('.pyc','.pyo','.pyd')]
101 101
102 102 folder_list = [os.path.basename(p).split('.')[0] for p in folder_list]
103 103 return folder_list
104 104
105 105 def moduleCompletion(line):
106 106 """
107 107 Returns a list containing the completion possibilities for an import line.
108 108 The line looks like this :
109 109 'import xml.d'
110 110 'from xml.dom import'
111 111 """
112 112 def tryImport(mod, only_modules=False):
113 113 def isImportable(module, attr):
114 114 if only_modules:
115 115 return inspect.ismodule(getattr(module, attr))
116 116 else:
117 117 return not(attr[:2] == '__' and attr[-2:] == '__')
118 118 try:
119 119 m = __import__(mod)
120 120 except:
121 121 return []
122 122 mods = mod.split('.')
123 123 for module in mods[1:]:
124 124 m = getattr(m,module)
125 125 if (not hasattr(m, '__file__')) or (not only_modules) or\
126 126 (hasattr(m, '__file__') and '__init__' in m.__file__):
127 127 completion_list = [attr for attr in dir(m) if isImportable(m, attr)]
128 128 completion_list.extend(getattr(m,'__all__',[]))
129 129 if hasattr(m, '__file__') and '__init__' in m.__file__:
130 130 completion_list.extend(moduleList(os.path.dirname(m.__file__)))
131 131 completion_list = list(set(completion_list))
132 132 if '__init__' in completion_list:
133 133 completion_list.remove('__init__')
134 134 return completion_list
135 135
136 136 words = line.split(' ')
137 137 if len(words) == 3 and words[0] == 'from':
138 138 return ['import ']
139 139 if len(words) < 3 and (words[0] in ['import','from']) :
140 140 if len(words) == 1:
141 141 return getRootModules()
142 142 mod = words[1].split('.')
143 143 if len(mod) < 2:
144 144 return getRootModules()
145 145 completion_list = tryImport('.'.join(mod[:-1]), True)
146 146 completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
147 147 return completion_list
148 148 if len(words) >= 3 and words[0] == 'from':
149 149 mod = words[1]
150 150 return tryImport(mod)
151 151
152 152 def vcs_completer(commands, event):
153 153 """ utility to make writing typical version control app completers easier
154 154
155 155 VCS command line apps typically have the format:
156 156
157 157 [sudo ]PROGNAME [help] [command] file file...
158 158
159 159 """
160 160
161 161
162 162 cmd_param = event.line.split()
163 163 if event.line.endswith(' '):
164 164 cmd_param.append('')
165 165
166 166 if cmd_param[0] == 'sudo':
167 167 cmd_param = cmd_param[1:]
168 168
169 169 if len(cmd_param) == 2 or 'help' in cmd_param:
170 170 return commands.split()
171 171
172 172 return ip.IP.Completer.file_matches(event.symbol)
173 173
174 174
175 175 pkg_cache = None
176 176
177 177 def module_completer(self,event):
178 178 """ Give completions after user has typed 'import ...' or 'from ...'"""
179 179
180 180 # This works in all versions of python. While 2.5 has
181 181 # pkgutil.walk_packages(), that particular routine is fairly dangerous,
182 182 # since it imports *EVERYTHING* on sys.path. That is: a) very slow b) full
183 183 # of possibly problematic side effects.
184 184 # This search the folders in the sys.path for available modules.
185 185
186 186 return moduleCompletion(event.line)
187 187
188 188
189 189 svn_commands = """\
190 190 add blame praise annotate ann cat checkout co cleanup commit ci copy
191 191 cp delete del remove rm diff di export help ? h import info list ls
192 192 lock log merge mkdir move mv rename ren propdel pdel pd propedit pedit
193 193 pe propget pget pg proplist plist pl propset pset ps resolved revert
194 194 status stat st switch sw unlock update
195 195 """
196 196
197 197 def svn_completer(self,event):
198 198 return vcs_completer(svn_commands, event)
199 199
200 200
201 201 hg_commands = """
202 202 add addremove annotate archive backout branch branches bundle cat
203 203 clone commit copy diff export grep heads help identify import incoming
204 204 init locate log manifest merge outgoing parents paths pull push
205 205 qapplied qclone qcommit qdelete qdiff qfold qguard qheader qimport
206 206 qinit qnew qnext qpop qprev qpush qrefresh qrename qrestore qsave
207 207 qselect qseries qtop qunapplied recover remove rename revert rollback
208 208 root serve showconfig status strip tag tags tip unbundle update verify
209 209 version
210 210 """
211 211
212 212 def hg_completer(self,event):
213 213 """ Completer for mercurial commands """
214 214
215 215 return vcs_completer(hg_commands, event)
216 216
217 217
218 218
219 219 __bzr_commands = None
220 220
221 221 def bzr_commands():
222 222 global __bzr_commands
223 223 if __bzr_commands is not None:
224 224 return __bzr_commands
225 225 out = os.popen('bzr help commands')
226 226 __bzr_commands = [l.split()[0] for l in out]
227 227 return __bzr_commands
228 228
229 229 def bzr_completer(self,event):
230 230 """ Completer for bazaar commands """
231 231 cmd_param = event.line.split()
232 232 if event.line.endswith(' '):
233 233 cmd_param.append('')
234 234
235 235 if len(cmd_param) > 2:
236 236 cmd = cmd_param[1]
237 237 param = cmd_param[-1]
238 238 output_file = (param == '--output=')
239 239 if cmd == 'help':
240 240 return bzr_commands()
241 241 elif cmd in ['bundle-revisions','conflicts',
242 242 'deleted','nick','register-branch',
243 243 'serve','unbind','upgrade','version',
244 244 'whoami'] and not output_file:
245 245 return []
246 246 else:
247 247 # the rest are probably file names
248 248 return ip.IP.Completer.file_matches(event.symbol)
249 249
250 250 return bzr_commands()
251 251
252 252
253 253 def shlex_split(x):
254 254 """Helper function to split lines into segments."""
255 255 #shlex.split raise exception if syntax error in sh syntax
256 256 #for example if no closing " is found. This function keeps dropping
257 257 #the last character of the line until shlex.split does not raise
258 258 #exception. Adds end of the line to the result of shlex.split
259 259 #example: %run "c:/python -> ['%run','"c:/python']
260 260 endofline=[]
261 261 while x!="":
262 262 try:
263 263 comps=shlex.split(x)
264 264 if len(endofline)>=1:
265 265 comps.append("".join(endofline))
266 266 return comps
267 267 except ValueError:
268 268 endofline=[x[-1:]]+endofline
269 269 x=x[:-1]
270 270 return ["".join(endofline)]
271 271
272 272 def runlistpy(self, event):
273 273 comps = shlex_split(event.line)
274 274 relpath = (len(comps) > 1 and comps[-1] or '').strip("'\"")
275 275
276 276 #print "\nev=",event # dbg
277 277 #print "rp=",relpath # dbg
278 278 #print 'comps=',comps # dbg
279 279
280 280 lglob = glob.glob
281 281 isdir = os.path.isdir
282 282 if relpath.startswith('~'):
283 283 relpath = os.path.expanduser(relpath)
284 284 dirs = [f.replace('\\','/') + "/" for f in lglob(relpath+'*')
285 285 if isdir(f)]
286 286
287 287 # Find if the user has already typed the first filename, after which we
288 288 # should complete on all files, since after the first one other files may
289 289 # be arguments to the input script.
290 290 #filter(
291 291 if filter(lambda f: f.endswith('.py') or f.endswith('.ipy') or
292 292 f.endswith('.pyw'),comps):
293 293 pys = [f.replace('\\','/') for f in lglob('*')]
294 294 else:
295 295 pys = [f.replace('\\','/')
296 296 for f in lglob(relpath+'*.py') + lglob(relpath+'*.ipy') +
297 297 lglob(relpath + '*.pyw')]
298 298 return dirs + pys
299 299
300 300
301 301 greedy_cd_completer = False
302 302
303 303 def cd_completer(self, event):
304 304 relpath = event.symbol
305 305 #print event # dbg
306 306 if '-b' in event.line:
307 307 # return only bookmark completions
308 308 bkms = self.db.get('bookmarks',{})
309 309 return bkms.keys()
310 310
311 311
312 312 if event.symbol == '-':
313 313 width_dh = str(len(str(len(ip.user_ns['_dh']) + 1)))
314 314 # jump in directory history by number
315 315 fmt = '-%0' + width_dh +'d [%s]'
316 316 ents = [ fmt % (i,s) for i,s in enumerate(ip.user_ns['_dh'])]
317 317 if len(ents) > 1:
318 318 return ents
319 319 return []
320 320
321 321 if event.symbol.startswith('--'):
322 322 return ["--" + os.path.basename(d) for d in ip.user_ns['_dh']]
323 323
324 324 if relpath.startswith('~'):
325 325 relpath = os.path.expanduser(relpath).replace('\\','/')
326 326 found = []
327 327 for d in [f.replace('\\','/') + '/' for f in glob.glob(relpath+'*')
328 328 if os.path.isdir(f)]:
329 329 if ' ' in d:
330 330 # we don't want to deal with any of that, complex code
331 331 # for this is elsewhere
332 332 raise IPython.ipapi.TryNext
333 333 found.append( d )
334 334
335 335 if not found:
336 336 if os.path.isdir(relpath):
337 337 return [relpath]
338 # if no completions so far, try bookmarks
339 bks = self.db.get('bookmarks',{}).keys()
340 bkmatches = [s for s in bks if s.startswith(event.symbol)]
341 if bkmatches:
342 return bkmatches
343
338 344 raise IPython.ipapi.TryNext
339 345
340 346
341 347 def single_dir_expand(matches):
342 348 "Recursively expand match lists containing a single dir."
343 349
344 350 if len(matches) == 1 and os.path.isdir(matches[0]):
345 351 # Takes care of links to directories also. Use '/'
346 352 # explicitly, even under Windows, so that name completions
347 353 # don't end up escaped.
348 354 d = matches[0]
349 355 if d[-1] in ['/','\\']:
350 356 d = d[:-1]
351 357
352 358 subdirs = [p for p in os.listdir(d) if os.path.isdir( d + '/' + p) and not p.startswith('.')]
353 359 if subdirs:
354 360 matches = [ (d + '/' + p) for p in subdirs ]
355 361 return single_dir_expand(matches)
356 362 else:
357 363 return matches
358 364 else:
359 365 return matches
360 366
361 367 if greedy_cd_completer:
362 368 return single_dir_expand(found)
363 369 else:
364 370 return found
365 371
366 372 def apt_get_packages(prefix):
367 373 out = os.popen('apt-cache pkgnames')
368 374 for p in out:
369 375 if p.startswith(prefix):
370 376 yield p.rstrip()
371 377
372 378
373 379 apt_commands = """\
374 380 update upgrade install remove purge source build-dep dist-upgrade
375 381 dselect-upgrade clean autoclean check"""
376 382
377 383 def apt_completer(self, event):
378 384 """ Completer for apt-get (uses apt-cache internally)
379 385
380 386 """
381 387
382 388
383 389 cmd_param = event.line.split()
384 390 if event.line.endswith(' '):
385 391 cmd_param.append('')
386 392
387 393 if cmd_param[0] == 'sudo':
388 394 cmd_param = cmd_param[1:]
389 395
390 396 if len(cmd_param) == 2 or 'help' in cmd_param:
391 397 return apt_commands.split()
392 398
393 399 return list(apt_get_packages(event.symbol))
394 400
@@ -1,84 +1,88 b''
1 1 """ 'editor' hooks for common editors that work well with ipython
2 2
3 3 They should honor the line number argument, at least.
4 4
5 5 Contributions are *very* welcome.
6 6 """
7 7
8 8 import IPython.ipapi
9 9 ip = IPython.ipapi.get()
10 10
11 11 from IPython.Itpl import itplns
12 12 import os
13 13
14 14 def install_editor(run_template, wait = False):
15 15 """ Gets a template in format "myeditor bah bah $file bah bah $line"
16 16
17 17 $file will be replaced by file name, $line by line number (or 0).
18 18 Installs the editor that is called by IPython, instead of the default
19 19 notepad or vi.
20 20
21 21 If wait is true, wait until the user presses enter before returning,
22 22 to facilitate non-blocking editors that exit immediately after
23 23 the call.
24 24 """
25 25
26 26 def call_editor(self, file, line=0):
27 27 if line is None:
28 28 line = 0
29 29 cmd = itplns(run_template, locals())
30 30 print ">",cmd
31 os.system(cmd)
31 if os.system(cmd) != 0:
32 raise IPython.ipapi.TryNext()
32 33 if wait:
33 34 raw_input("Press Enter when done editing:")
34 35
35 36 ip.set_hook('editor',call_editor)
36 37
37 38
38 39 # in these, exe is always the path/name of the executable. Useful
39 40 # if you don't have the editor directory in your path
40 41
41 42 def komodo(exe = 'komodo'):
42 43 """ Activestate Komodo [Edit] """
43 44 install_editor(exe + ' -l $line "$file"', wait = True)
44 45
45 46 def scite(exe = "scite"):
46 47 """ SciTE or Sc1 """
47 48 install_editor(exe + ' "$file" -goto:$line')
48 49
49 50 def notepadplusplus(exe = 'notepad++'):
50 51 """ Notepad++ http://notepad-plus.sourceforge.net """
51 52 install_editor(exe + ' -n$line "$file"')
52 53
53 54 def jed(exe = 'jed'):
54 55 """ JED, the lightweight emacsish editor """
55 56 install_editor(exe + ' +$line "$file"')
56 57
57 58 def idle(exe = None):
58 59 """ Idle, the editor bundled with python
59 60
60 61 Should be pretty smart about finding the executable.
61 62 """
62 63 if exe is None:
63 64 import idlelib
64 65 p = os.path.dirname(idlelib.__file__)
65 66 exe = p + '/idle.py'
66 67 install_editor(exe + ' "$file"')
67
68
69 def mate(exe = 'mate'):
70 """ TextMate, the missing editor"""
71 install_editor(exe + ' -w -l $line "$file"')
68 72
69 73 # these are untested, report any problems
70 74
71 75 def emacs(exe = 'emacs'):
72 76 install_editor(exe + ' +$line "$file"')
73 77
74 78 def gnuclient(exe= 'gnuclient'):
75 79 install_editor(exe + ' -nw +$line "$file"')
76 80
77 81 def crimson_editor(exe = 'cedt.exe'):
78 82 install_editor(exe + ' /L:$line "$file"')
79 83
80 84 def kate(exe = 'kate'):
81 85 install_editor(exe + ' -u -l $line "$file"')
82 86
83 87
84 88 No newline at end of file
@@ -1,258 +1,270 b''
1 1 """Shell mode for IPython.
2 2
3 3 Start ipython in shell mode by invoking "ipython -p sh"
4 4
5 5 (the old version, "ipython -p pysh" still works but this is the more "modern"
6 6 shell mode and is recommended for users who don't care about pysh-mode
7 7 compatibility)
8 8 """
9 9
10 10 from IPython import ipapi
11 import os,textwrap
11 import os,re,textwrap
12 12
13 13 # The import below effectively obsoletes your old-style ipythonrc[.ini],
14 14 # so consider yourself warned!
15 15
16 16 import ipy_defaults
17 17
18 18 def main():
19 19 ip = ipapi.get()
20 20 o = ip.options
21 21 # autocall to "full" mode (smart mode is default, I like full mode)
22 22
23 23 o.autocall = 2
24 24
25 25 # Jason Orendorff's path class is handy to have in user namespace
26 26 # if you are doing shell-like stuff
27 27 try:
28 28 ip.ex("from IPython.external.path import path" )
29 29 except ImportError:
30 30 pass
31 31
32 32 # beefed up %env is handy in shell mode
33 33 import envpersist
34 34
35 35 # To see where mycmd resides (in path/aliases), do %which mycmd
36 36 import ipy_which
37 37
38 38 # tab completers for hg, svn, ...
39 39 import ipy_app_completers
40 40
41 41 # To make executables foo and bar in mybin usable without PATH change, do:
42 42 # %rehashdir c:/mybin
43 43 # %store foo
44 44 # %store bar
45 45 import ipy_rehashdir
46 46
47 47 # does not work without subprocess module!
48 48 #import ipy_signals
49 49
50 50 ip.ex('import os')
51 51 ip.ex("def up(): os.chdir('..')")
52 52 ip.user_ns['LA'] = LastArgFinder()
53 # Nice prompt
54 53
55 o.prompt_in1= r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
54 # You can assign to _prompt_title variable
55 # to provide some extra information for prompt
56 # (e.g. the current mode, host/username...)
57
58 ip.user_ns['_prompt_title'] = ''
59
60 # Nice prompt
61 o.prompt_in1= r'\C_Green${_prompt_title}\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
56 62 o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> '
57 63 o.prompt_out= '<\#> '
58 64
59 65 from IPython import Release
60 66
61 67 import sys
62 68 # Non-chatty banner
63 69 o.banner = "IPython %s [on Py %s]\n" % (Release.version,sys.version.split(None,1)[0])
64 70
65 71
66 72 ip.IP.default_option('cd','-q')
67 73 ip.IP.default_option('macro', '-r')
68 74 # If you only rarely want to execute the things you %edit...
69 75 #ip.IP.default_option('edit','-x')
70 76
71 77
72 78 o.prompts_pad_left="1"
73 79 # Remove all blank lines in between prompts, like a normal shell.
74 80 o.separate_in="0"
75 81 o.separate_out="0"
76 82 o.separate_out2="0"
77 83
78 84 # now alias all syscommands
79 85
80 86 db = ip.db
81 87
82 88 syscmds = db.get("syscmdlist",[] )
83 89 if not syscmds:
84 90 print textwrap.dedent("""
85 91 System command list not initialized, probably the first run...
86 92 running %rehashx to refresh the command list. Run %rehashx
87 93 again to refresh command list (after installing new software etc.)
88 94 """)
89 95 ip.magic('rehashx')
90 96 syscmds = db.get("syscmdlist")
91 97
92 98 # lowcase aliases on win32 only
93 99 if os.name == 'posix':
94 100 mapper = lambda s:s
95 101 else:
96 102 def mapper(s): return s.lower()
97 103
98 104 for cmd in syscmds:
99 105 # print "sys",cmd #dbg
100 106 noext, ext = os.path.splitext(cmd)
101 key = mapper(noext)
107 if ext.lower() == '.exe':
108 cmd = noext
109
110 key = mapper(cmd)
102 111 if key not in ip.IP.alias_table:
103 ip.defalias(key, cmd)
112 # Dots will be removed from alias names, since ipython
113 # assumes names with dots to be python code
114
115 ip.defalias(key.replace('.',''), cmd)
104 116
105 117 # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more
106 118 ip.load("IPython.external.mglob")
107 119
108 120 # win32 is crippled w/o cygwin, try to help it a little bit
109 121 if sys.platform == 'win32':
110 122 if 'cygwin' in os.environ['PATH'].lower():
111 123 # use the colors of cygwin ls (recommended)
112 124 ip.defalias('d', 'ls -F --color=auto')
113 125 else:
114 126 # get icp, imv, imkdir, igrep, irm,...
115 127 ip.load('ipy_fsops')
116 128
117 129 # and the next best thing to real 'ls -F'
118 130 ip.defalias('d','dir /w /og /on')
119 131
120 ip.set_hook('input_prefilter', dotslash_prefilter_f)
132 ip.set_hook('input_prefilter', slash_prefilter_f)
121 133 extend_shell_behavior(ip)
122 134
123 135 class LastArgFinder:
124 136 """ Allow $LA to work as "last argument of previous command", like $! in bash
125 137
126 138 To call this in normal IPython code, do LA()
127 139 """
128 140 def __call__(self, hist_idx = None):
129 141 ip = ipapi.get()
130 142 if hist_idx is None:
131 143 return str(self)
132 144 return ip.IP.input_hist_raw[hist_idx].strip().split()[-1]
133 145 def __str__(self):
134 146 ip = ipapi.get()
135 147 for cmd in reversed(ip.IP.input_hist_raw):
136 148 parts = cmd.strip().split()
137 149 if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']:
138 150 continue
139 151 return parts[-1]
140 152 return ""
141 153
142 def dotslash_prefilter_f(self,line):
143 """ ./foo now runs foo as system command
154 def slash_prefilter_f(self,line):
155 """ ./foo, ~/foo and /bin/foo now run foo as system command
144 156
145 Removes the need for doing !./foo
157 Removes the need for doing !./foo, !~/foo or !/bin/foo
146 158 """
147 159 import IPython.genutils
148 if line.startswith("./"):
160 if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line):
149 161 return "_ip.system(" + IPython.genutils.make_quoted_expr(line)+")"
150 162 raise ipapi.TryNext
151 163
152 164 # XXX You do not need to understand the next function!
153 165 # This should probably be moved out of profile
154 166
155 167 def extend_shell_behavior(ip):
156 168
157 169 # Instead of making signature a global variable tie it to IPSHELL.
158 170 # In future if it is required to distinguish between different
159 171 # shells we can assign a signature per shell basis
160 172 ip.IP.__sig__ = 0xa005
161 173 # mark the IPSHELL with this signature
162 174 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
163 175
164 176 from IPython.Itpl import ItplNS
165 177 from IPython.genutils import shell
166 178 # utility to expand user variables via Itpl
167 179 # xxx do something sensible with depth?
168 180 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
169 181 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
170 182
171 183 def get_locals():
172 184 """ Substituting a variable through Itpl deep inside the IPSHELL stack
173 185 requires the knowledge of all the variables in scope upto the last
174 186 IPSHELL frame. This routine simply merges all the local variables
175 187 on the IPSHELL stack without worrying about their scope rules
176 188 """
177 189 import sys
178 190 # note lambda expression constitues a function call
179 191 # hence fno should be incremented by one
180 192 getsig = lambda fno: sys._getframe(fno+1).f_globals \
181 193 ['__builtins__'].__dict__['__sig__']
182 194 getlvars = lambda fno: sys._getframe(fno+1).f_locals
183 195 # trackback until we enter the IPSHELL
184 196 frame_no = 1
185 197 sig = ip.IP.__sig__
186 198 fsig = ~sig
187 199 while fsig != sig :
188 200 try:
189 201 fsig = getsig(frame_no)
190 202 except (AttributeError, KeyError):
191 203 frame_no += 1
192 204 except ValueError:
193 205 # stack is depleted
194 206 # call did not originate from IPSHELL
195 207 return {}
196 208 first_frame = frame_no
197 209 # walk further back until we exit from IPSHELL or deplete stack
198 210 try:
199 211 while(sig == getsig(frame_no+1)):
200 212 frame_no += 1
201 213 except (AttributeError, KeyError, ValueError):
202 214 pass
203 215 # merge the locals from top down hence overriding
204 216 # any re-definitions of variables, functions etc.
205 217 lvars = {}
206 218 for fno in range(frame_no, first_frame-1, -1):
207 219 lvars.update(getlvars(fno))
208 220 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
209 221 return lvars
210 222
211 223 def _runlines(lines):
212 224 """Run a string of one or more lines of source.
213 225
214 226 This method is capable of running a string containing multiple source
215 227 lines, as if they had been entered at the IPython prompt. Since it
216 228 exposes IPython's processing machinery, the given strings can contain
217 229 magic calls (%magic), special shell access (!cmd), etc."""
218 230
219 231 # We must start with a clean buffer, in case this is run from an
220 232 # interactive IPython session (via a magic, for example).
221 233 ip.IP.resetbuffer()
222 234 lines = lines.split('\n')
223 235 more = 0
224 236 command = ''
225 237 for line in lines:
226 238 # skip blank lines so we don't mess up the prompt counter, but do
227 239 # NOT skip even a blank line if we are in a code block (more is
228 240 # true)
229 241 # if command is not empty trim the line
230 242 if command != '' :
231 243 line = line.strip()
232 244 # add the broken line to the command
233 245 if line and line[-1] == '\\' :
234 246 command += line[0:-1] + ' '
235 247 more = True
236 248 continue
237 249 else :
238 250 # add the last (current) line to the command
239 251 command += line
240 252 if command or more:
241 253 # push to raw history, so hist line numbers stay in sync
242 254 ip.IP.input_hist_raw.append("# " + command + "\n")
243 255
244 256 more = ip.IP.push(ip.IP.prefilter(command,more))
245 257 command = ''
246 258 # IPython's runsource returns None if there was an error
247 259 # compiling the code. This allows us to stop processing right
248 260 # away, so the user gets the error message at the right place.
249 261 if more is None:
250 262 break
251 263 # final newline in case the input didn't have it, so that the code
252 264 # actually does get executed
253 265 if more:
254 266 ip.IP.push('\n')
255 267
256 268 ip.IP.runlines = _runlines
257 269
258 270 main()
1 NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file chmod 100755 => 100644
@@ -1,3377 +1,3405 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Magic functions for InteractiveShell.
3 3
4 4 $Id: Magic.py 2996 2008-01-30 06:31:39Z fperez $"""
5 5
6 6 #*****************************************************************************
7 7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
8 8 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
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 # Modules and globals
16 16
17 17 from IPython import Release
18 18 __author__ = '%s <%s>\n%s <%s>' % \
19 19 ( Release.authors['Janko'] + Release.authors['Fernando'] )
20 20 __license__ = Release.license
21 21
22 22 # Python standard modules
23 23 import __builtin__
24 24 import bdb
25 25 import inspect
26 26 import os
27 27 import pdb
28 28 import pydoc
29 29 import sys
30 30 import re
31 31 import tempfile
32 32 import time
33 33 import cPickle as pickle
34 34 import textwrap
35 35 from cStringIO import StringIO
36 36 from getopt import getopt,GetoptError
37 37 from pprint import pprint, pformat
38 38 from sets import Set
39 39
40 40 # cProfile was added in Python2.5
41 41 try:
42 42 import cProfile as profile
43 43 import pstats
44 44 except ImportError:
45 45 # profile isn't bundled by default in Debian for license reasons
46 46 try:
47 47 import profile,pstats
48 48 except ImportError:
49 49 profile = pstats = None
50 50
51 51 # Homebrewed
52 52 import IPython
53 53 from IPython import Debugger, OInspect, wildcard
54 54 from IPython.FakeModule import FakeModule
55 55 from IPython.Itpl import Itpl, itpl, printpl,itplns
56 56 from IPython.PyColorize import Parser
57 57 from IPython.ipstruct import Struct
58 58 from IPython.macro import Macro
59 59 from IPython.genutils import *
60 60 from IPython import platutils
61 61 import IPython.generics
62 62 import IPython.ipapi
63 63 from IPython.ipapi import UsageError
64 64 from IPython.testing import decorators as testdec
65 65
66 66 #***************************************************************************
67 67 # Utility functions
68 68 def on_off(tag):
69 69 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
70 70 return ['OFF','ON'][tag]
71 71
72 72 class Bunch: pass
73 73
74 74 def compress_dhist(dh):
75 75 head, tail = dh[:-10], dh[-10:]
76 76
77 77 newhead = []
78 78 done = Set()
79 79 for h in head:
80 80 if h in done:
81 81 continue
82 82 newhead.append(h)
83 83 done.add(h)
84 84
85 85 return newhead + tail
86 86
87 87
88 88 #***************************************************************************
89 89 # Main class implementing Magic functionality
90 90 class Magic:
91 91 """Magic functions for InteractiveShell.
92 92
93 93 Shell functions which can be reached as %function_name. All magic
94 94 functions should accept a string, which they can parse for their own
95 95 needs. This can make some functions easier to type, eg `%cd ../`
96 96 vs. `%cd("../")`
97 97
98 98 ALL definitions MUST begin with the prefix magic_. The user won't need it
99 99 at the command line, but it is is needed in the definition. """
100 100
101 101 # class globals
102 102 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
103 103 'Automagic is ON, % prefix NOT needed for magic functions.']
104 104
105 105 #......................................................................
106 106 # some utility functions
107 107
108 108 def __init__(self,shell):
109 109
110 110 self.options_table = {}
111 111 if profile is None:
112 112 self.magic_prun = self.profile_missing_notice
113 113 self.shell = shell
114 114
115 115 # namespace for holding state we may need
116 116 self._magic_state = Bunch()
117 117
118 118 def profile_missing_notice(self, *args, **kwargs):
119 119 error("""\
120 120 The profile module could not be found. It has been removed from the standard
121 121 python packages because of its non-free license. To use profiling, install the
122 122 python-profiler package from non-free.""")
123 123
124 124 def default_option(self,fn,optstr):
125 125 """Make an entry in the options_table for fn, with value optstr"""
126 126
127 127 if fn not in self.lsmagic():
128 128 error("%s is not a magic function" % fn)
129 129 self.options_table[fn] = optstr
130 130
131 131 def lsmagic(self):
132 132 """Return a list of currently available magic functions.
133 133
134 134 Gives a list of the bare names after mangling (['ls','cd', ...], not
135 135 ['magic_ls','magic_cd',...]"""
136 136
137 137 # FIXME. This needs a cleanup, in the way the magics list is built.
138 138
139 139 # magics in class definition
140 140 class_magic = lambda fn: fn.startswith('magic_') and \
141 141 callable(Magic.__dict__[fn])
142 142 # in instance namespace (run-time user additions)
143 143 inst_magic = lambda fn: fn.startswith('magic_') and \
144 144 callable(self.__dict__[fn])
145 145 # and bound magics by user (so they can access self):
146 146 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
147 147 callable(self.__class__.__dict__[fn])
148 148 magics = filter(class_magic,Magic.__dict__.keys()) + \
149 149 filter(inst_magic,self.__dict__.keys()) + \
150 150 filter(inst_bound_magic,self.__class__.__dict__.keys())
151 151 out = []
152 152 for fn in Set(magics):
153 153 out.append(fn.replace('magic_','',1))
154 154 out.sort()
155 155 return out
156 156
157 157 def extract_input_slices(self,slices,raw=False):
158 158 """Return as a string a set of input history slices.
159 159
160 160 Inputs:
161 161
162 162 - slices: the set of slices is given as a list of strings (like
163 163 ['1','4:8','9'], since this function is for use by magic functions
164 164 which get their arguments as strings.
165 165
166 166 Optional inputs:
167 167
168 168 - raw(False): by default, the processed input is used. If this is
169 169 true, the raw input history is used instead.
170 170
171 171 Note that slices can be called with two notations:
172 172
173 173 N:M -> standard python form, means including items N...(M-1).
174 174
175 175 N-M -> include items N..M (closed endpoint)."""
176 176
177 177 if raw:
178 178 hist = self.shell.input_hist_raw
179 179 else:
180 180 hist = self.shell.input_hist
181 181
182 182 cmds = []
183 183 for chunk in slices:
184 184 if ':' in chunk:
185 185 ini,fin = map(int,chunk.split(':'))
186 186 elif '-' in chunk:
187 187 ini,fin = map(int,chunk.split('-'))
188 188 fin += 1
189 189 else:
190 190 ini = int(chunk)
191 191 fin = ini+1
192 192 cmds.append(hist[ini:fin])
193 193 return cmds
194 194
195 195 def _ofind(self, oname, namespaces=None):
196 196 """Find an object in the available namespaces.
197 197
198 198 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
199 199
200 200 Has special code to detect magic functions.
201 201 """
202 202
203 203 oname = oname.strip()
204 204
205 205 alias_ns = None
206 206 if namespaces is None:
207 207 # Namespaces to search in:
208 208 # Put them in a list. The order is important so that we
209 209 # find things in the same order that Python finds them.
210 210 namespaces = [ ('Interactive', self.shell.user_ns),
211 211 ('IPython internal', self.shell.internal_ns),
212 212 ('Python builtin', __builtin__.__dict__),
213 213 ('Alias', self.shell.alias_table),
214 214 ]
215 215 alias_ns = self.shell.alias_table
216 216
217 217 # initialize results to 'null'
218 218 found = 0; obj = None; ospace = None; ds = None;
219 219 ismagic = 0; isalias = 0; parent = None
220 220
221 221 # Look for the given name by splitting it in parts. If the head is
222 222 # found, then we look for all the remaining parts as members, and only
223 223 # declare success if we can find them all.
224 224 oname_parts = oname.split('.')
225 225 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
226 226 for nsname,ns in namespaces:
227 227 try:
228 228 obj = ns[oname_head]
229 229 except KeyError:
230 230 continue
231 231 else:
232 232 #print 'oname_rest:', oname_rest # dbg
233 233 for part in oname_rest:
234 234 try:
235 235 parent = obj
236 236 obj = getattr(obj,part)
237 237 except:
238 238 # Blanket except b/c some badly implemented objects
239 239 # allow __getattr__ to raise exceptions other than
240 240 # AttributeError, which then crashes IPython.
241 241 break
242 242 else:
243 243 # If we finish the for loop (no break), we got all members
244 244 found = 1
245 245 ospace = nsname
246 246 if ns == alias_ns:
247 247 isalias = 1
248 248 break # namespace loop
249 249
250 250 # Try to see if it's magic
251 251 if not found:
252 252 if oname.startswith(self.shell.ESC_MAGIC):
253 253 oname = oname[1:]
254 254 obj = getattr(self,'magic_'+oname,None)
255 255 if obj is not None:
256 256 found = 1
257 257 ospace = 'IPython internal'
258 258 ismagic = 1
259 259
260 260 # Last try: special-case some literals like '', [], {}, etc:
261 261 if not found and oname_head in ["''",'""','[]','{}','()']:
262 262 obj = eval(oname_head)
263 263 found = 1
264 264 ospace = 'Interactive'
265 265
266 266 return {'found':found, 'obj':obj, 'namespace':ospace,
267 267 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
268 268
269 269 def arg_err(self,func):
270 270 """Print docstring if incorrect arguments were passed"""
271 271 print 'Error in arguments:'
272 272 print OInspect.getdoc(func)
273 273
274 274 def format_latex(self,strng):
275 275 """Format a string for latex inclusion."""
276 276
277 277 # Characters that need to be escaped for latex:
278 278 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
279 279 # Magic command names as headers:
280 280 cmd_name_re = re.compile(r'^(%s.*?):' % self.shell.ESC_MAGIC,
281 281 re.MULTILINE)
282 282 # Magic commands
283 283 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % self.shell.ESC_MAGIC,
284 284 re.MULTILINE)
285 285 # Paragraph continue
286 286 par_re = re.compile(r'\\$',re.MULTILINE)
287 287
288 288 # The "\n" symbol
289 289 newline_re = re.compile(r'\\n')
290 290
291 291 # Now build the string for output:
292 292 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
293 293 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
294 294 strng)
295 295 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
296 296 strng = par_re.sub(r'\\\\',strng)
297 297 strng = escape_re.sub(r'\\\1',strng)
298 298 strng = newline_re.sub(r'\\textbackslash{}n',strng)
299 299 return strng
300 300
301 301 def format_screen(self,strng):
302 302 """Format a string for screen printing.
303 303
304 304 This removes some latex-type format codes."""
305 305 # Paragraph continue
306 306 par_re = re.compile(r'\\$',re.MULTILINE)
307 307 strng = par_re.sub('',strng)
308 308 return strng
309 309
310 310 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
311 311 """Parse options passed to an argument string.
312 312
313 313 The interface is similar to that of getopt(), but it returns back a
314 314 Struct with the options as keys and the stripped argument string still
315 315 as a string.
316 316
317 317 arg_str is quoted as a true sys.argv vector by using shlex.split.
318 318 This allows us to easily expand variables, glob files, quote
319 319 arguments, etc.
320 320
321 321 Options:
322 322 -mode: default 'string'. If given as 'list', the argument string is
323 323 returned as a list (split on whitespace) instead of a string.
324 324
325 325 -list_all: put all option values in lists. Normally only options
326 326 appearing more than once are put in a list.
327 327
328 328 -posix (True): whether to split the input line in POSIX mode or not,
329 329 as per the conventions outlined in the shlex module from the
330 330 standard library."""
331 331
332 332 # inject default options at the beginning of the input line
333 333 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
334 334 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
335 335
336 336 mode = kw.get('mode','string')
337 337 if mode not in ['string','list']:
338 338 raise ValueError,'incorrect mode given: %s' % mode
339 339 # Get options
340 340 list_all = kw.get('list_all',0)
341 341 posix = kw.get('posix',True)
342 342
343 343 # Check if we have more than one argument to warrant extra processing:
344 344 odict = {} # Dictionary with options
345 345 args = arg_str.split()
346 346 if len(args) >= 1:
347 347 # If the list of inputs only has 0 or 1 thing in it, there's no
348 348 # need to look for options
349 349 argv = arg_split(arg_str,posix)
350 350 # Do regular option processing
351 351 try:
352 352 opts,args = getopt(argv,opt_str,*long_opts)
353 353 except GetoptError,e:
354 354 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
355 355 " ".join(long_opts)))
356 356 for o,a in opts:
357 357 if o.startswith('--'):
358 358 o = o[2:]
359 359 else:
360 360 o = o[1:]
361 361 try:
362 362 odict[o].append(a)
363 363 except AttributeError:
364 364 odict[o] = [odict[o],a]
365 365 except KeyError:
366 366 if list_all:
367 367 odict[o] = [a]
368 368 else:
369 369 odict[o] = a
370 370
371 371 # Prepare opts,args for return
372 372 opts = Struct(odict)
373 373 if mode == 'string':
374 374 args = ' '.join(args)
375 375
376 376 return opts,args
377 377
378 378 #......................................................................
379 379 # And now the actual magic functions
380 380
381 381 # Functions for IPython shell work (vars,funcs, config, etc)
382 382 def magic_lsmagic(self, parameter_s = ''):
383 383 """List currently available magic functions."""
384 384 mesc = self.shell.ESC_MAGIC
385 385 print 'Available magic functions:\n'+mesc+\
386 386 (' '+mesc).join(self.lsmagic())
387 387 print '\n' + Magic.auto_status[self.shell.rc.automagic]
388 388 return None
389 389
390 390 def magic_magic(self, parameter_s = ''):
391 391 """Print information about the magic function system.
392 392
393 393 Supported formats: -latex, -brief, -rest
394 394 """
395 395
396 396 mode = ''
397 397 try:
398 398 if parameter_s.split()[0] == '-latex':
399 399 mode = 'latex'
400 400 if parameter_s.split()[0] == '-brief':
401 401 mode = 'brief'
402 402 if parameter_s.split()[0] == '-rest':
403 403 mode = 'rest'
404 404 rest_docs = []
405 405 except:
406 406 pass
407 407
408 408 magic_docs = []
409 409 for fname in self.lsmagic():
410 410 mname = 'magic_' + fname
411 411 for space in (Magic,self,self.__class__):
412 412 try:
413 413 fn = space.__dict__[mname]
414 414 except KeyError:
415 415 pass
416 416 else:
417 417 break
418 418 if mode == 'brief':
419 419 # only first line
420 420 if fn.__doc__:
421 421 fndoc = fn.__doc__.split('\n',1)[0]
422 422 else:
423 423 fndoc = 'No documentation'
424 424 else:
425 fndoc = fn.__doc__.rstrip()
425 if fn.__doc__:
426 fndoc = fn.__doc__.rstrip()
427 else:
428 fndoc = 'No documentation'
429
426 430
427 431 if mode == 'rest':
428 432 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(self.shell.ESC_MAGIC,
429 433 fname,fndoc))
430 434
431 435 else:
432 436 magic_docs.append('%s%s:\n\t%s\n' %(self.shell.ESC_MAGIC,
433 437 fname,fndoc))
434 438
435 439 magic_docs = ''.join(magic_docs)
436 440
437 441 if mode == 'rest':
438 442 return "".join(rest_docs)
439 443
440 444 if mode == 'latex':
441 445 print self.format_latex(magic_docs)
442 446 return
443 447 else:
444 448 magic_docs = self.format_screen(magic_docs)
445 449 if mode == 'brief':
446 450 return magic_docs
447 451
448 452 outmsg = """
449 453 IPython's 'magic' functions
450 454 ===========================
451 455
452 456 The magic function system provides a series of functions which allow you to
453 457 control the behavior of IPython itself, plus a lot of system-type
454 458 features. All these functions are prefixed with a % character, but parameters
455 459 are given without parentheses or quotes.
456 460
457 461 NOTE: If you have 'automagic' enabled (via the command line option or with the
458 462 %automagic function), you don't need to type in the % explicitly. By default,
459 463 IPython ships with automagic on, so you should only rarely need the % escape.
460 464
461 465 Example: typing '%cd mydir' (without the quotes) changes you working directory
462 466 to 'mydir', if it exists.
463 467
464 468 You can define your own magic functions to extend the system. See the supplied
465 469 ipythonrc and example-magic.py files for details (in your ipython
466 470 configuration directory, typically $HOME/.ipython/).
467 471
468 472 You can also define your own aliased names for magic functions. In your
469 473 ipythonrc file, placing a line like:
470 474
471 475 execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
472 476
473 477 will define %pf as a new name for %profile.
474 478
475 479 You can also call magics in code using the ipmagic() function, which IPython
476 480 automatically adds to the builtin namespace. Type 'ipmagic?' for details.
477 481
478 482 For a list of the available magic functions, use %lsmagic. For a description
479 483 of any of them, type %magic_name?, e.g. '%cd?'.
480 484
481 485 Currently the magic system has the following functions:\n"""
482 486
483 487 mesc = self.shell.ESC_MAGIC
484 488 outmsg = ("%s\n%s\n\nSummary of magic functions (from %slsmagic):"
485 489 "\n\n%s%s\n\n%s" % (outmsg,
486 490 magic_docs,mesc,mesc,
487 491 (' '+mesc).join(self.lsmagic()),
488 492 Magic.auto_status[self.shell.rc.automagic] ) )
489 493
490 494 page(outmsg,screen_lines=self.shell.rc.screen_length)
491 495
492 496
493 497 def magic_autoindent(self, parameter_s = ''):
494 498 """Toggle autoindent on/off (if available)."""
495 499
496 500 self.shell.set_autoindent()
497 501 print "Automatic indentation is:",['OFF','ON'][self.shell.autoindent]
498 502
499 503
500 504 def magic_automagic(self, parameter_s = ''):
501 505 """Make magic functions callable without having to type the initial %.
502 506
503 507 Without argumentsl toggles on/off (when off, you must call it as
504 508 %automagic, of course). With arguments it sets the value, and you can
505 509 use any of (case insensitive):
506 510
507 511 - on,1,True: to activate
508 512
509 513 - off,0,False: to deactivate.
510 514
511 515 Note that magic functions have lowest priority, so if there's a
512 516 variable whose name collides with that of a magic fn, automagic won't
513 517 work for that function (you get the variable instead). However, if you
514 518 delete the variable (del var), the previously shadowed magic function
515 519 becomes visible to automagic again."""
516 520
517 521 rc = self.shell.rc
518 522 arg = parameter_s.lower()
519 523 if parameter_s in ('on','1','true'):
520 524 rc.automagic = True
521 525 elif parameter_s in ('off','0','false'):
522 526 rc.automagic = False
523 527 else:
524 528 rc.automagic = not rc.automagic
525 529 print '\n' + Magic.auto_status[rc.automagic]
526 530
527 531 @testdec.skip_doctest
528 532 def magic_autocall(self, parameter_s = ''):
529 533 """Make functions callable without having to type parentheses.
530 534
531 535 Usage:
532 536
533 537 %autocall [mode]
534 538
535 539 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
536 540 value is toggled on and off (remembering the previous state).
537 541
538 542 In more detail, these values mean:
539 543
540 544 0 -> fully disabled
541 545
542 546 1 -> active, but do not apply if there are no arguments on the line.
543 547
544 548 In this mode, you get:
545 549
546 550 In [1]: callable
547 551 Out[1]: <built-in function callable>
548 552
549 553 In [2]: callable 'hello'
550 554 ------> callable('hello')
551 555 Out[2]: False
552 556
553 557 2 -> Active always. Even if no arguments are present, the callable
554 558 object is called:
555 559
556 560 In [2]: float
557 561 ------> float()
558 562 Out[2]: 0.0
559 563
560 564 Note that even with autocall off, you can still use '/' at the start of
561 565 a line to treat the first argument on the command line as a function
562 566 and add parentheses to it:
563 567
564 568 In [8]: /str 43
565 569 ------> str(43)
566 570 Out[8]: '43'
567 571
568 572 # all-random (note for auto-testing)
569 573 """
570 574
571 575 rc = self.shell.rc
572 576
573 577 if parameter_s:
574 578 arg = int(parameter_s)
575 579 else:
576 580 arg = 'toggle'
577 581
578 582 if not arg in (0,1,2,'toggle'):
579 583 error('Valid modes: (0->Off, 1->Smart, 2->Full')
580 584 return
581 585
582 586 if arg in (0,1,2):
583 587 rc.autocall = arg
584 588 else: # toggle
585 589 if rc.autocall:
586 590 self._magic_state.autocall_save = rc.autocall
587 591 rc.autocall = 0
588 592 else:
589 593 try:
590 594 rc.autocall = self._magic_state.autocall_save
591 595 except AttributeError:
592 596 rc.autocall = self._magic_state.autocall_save = 1
593 597
594 598 print "Automatic calling is:",['OFF','Smart','Full'][rc.autocall]
595 599
596 600 def magic_system_verbose(self, parameter_s = ''):
597 601 """Set verbose printing of system calls.
598 602
599 603 If called without an argument, act as a toggle"""
600 604
601 605 if parameter_s:
602 606 val = bool(eval(parameter_s))
603 607 else:
604 608 val = None
605 609
606 610 self.shell.rc_set_toggle('system_verbose',val)
607 611 print "System verbose printing is:",\
608 612 ['OFF','ON'][self.shell.rc.system_verbose]
609 613
610 614
611 615 def magic_page(self, parameter_s=''):
612 616 """Pretty print the object and display it through a pager.
613 617
614 618 %page [options] OBJECT
615 619
616 620 If no object is given, use _ (last output).
617 621
618 622 Options:
619 623
620 624 -r: page str(object), don't pretty-print it."""
621 625
622 626 # After a function contributed by Olivier Aubert, slightly modified.
623 627
624 628 # Process options/args
625 629 opts,args = self.parse_options(parameter_s,'r')
626 630 raw = 'r' in opts
627 631
628 632 oname = args and args or '_'
629 633 info = self._ofind(oname)
630 634 if info['found']:
631 635 txt = (raw and str or pformat)( info['obj'] )
632 636 page(txt)
633 637 else:
634 638 print 'Object `%s` not found' % oname
635 639
636 640 def magic_profile(self, parameter_s=''):
637 641 """Print your currently active IPyhton profile."""
638 642 if self.shell.rc.profile:
639 643 printpl('Current IPython profile: $self.shell.rc.profile.')
640 644 else:
641 645 print 'No profile active.'
642 646
643 647 def magic_pinfo(self, parameter_s='', namespaces=None):
644 648 """Provide detailed information about an object.
645 649
646 650 '%pinfo object' is just a synonym for object? or ?object."""
647 651
648 652 #print 'pinfo par: <%s>' % parameter_s # dbg
649 653
650 654
651 655 # detail_level: 0 -> obj? , 1 -> obj??
652 656 detail_level = 0
653 657 # We need to detect if we got called as 'pinfo pinfo foo', which can
654 658 # happen if the user types 'pinfo foo?' at the cmd line.
655 659 pinfo,qmark1,oname,qmark2 = \
656 660 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
657 661 if pinfo or qmark1 or qmark2:
658 662 detail_level = 1
659 663 if "*" in oname:
660 664 self.magic_psearch(oname)
661 665 else:
662 666 self._inspect('pinfo', oname, detail_level=detail_level,
663 667 namespaces=namespaces)
664 668
665 669 def magic_pdef(self, parameter_s='', namespaces=None):
666 670 """Print the definition header for any callable object.
667 671
668 672 If the object is a class, print the constructor information."""
669 673 self._inspect('pdef',parameter_s, namespaces)
670 674
671 675 def magic_pdoc(self, parameter_s='', namespaces=None):
672 676 """Print the docstring for an object.
673 677
674 678 If the given object is a class, it will print both the class and the
675 679 constructor docstrings."""
676 680 self._inspect('pdoc',parameter_s, namespaces)
677 681
678 682 def magic_psource(self, parameter_s='', namespaces=None):
679 683 """Print (or run through pager) the source code for an object."""
680 684 self._inspect('psource',parameter_s, namespaces)
681 685
682 686 def magic_pfile(self, parameter_s=''):
683 687 """Print (or run through pager) the file where an object is defined.
684 688
685 689 The file opens at the line where the object definition begins. IPython
686 690 will honor the environment variable PAGER if set, and otherwise will
687 691 do its best to print the file in a convenient form.
688 692
689 693 If the given argument is not an object currently defined, IPython will
690 694 try to interpret it as a filename (automatically adding a .py extension
691 695 if needed). You can thus use %pfile as a syntax highlighting code
692 696 viewer."""
693 697
694 698 # first interpret argument as an object name
695 699 out = self._inspect('pfile',parameter_s)
696 700 # if not, try the input as a filename
697 701 if out == 'not found':
698 702 try:
699 703 filename = get_py_filename(parameter_s)
700 704 except IOError,msg:
701 705 print msg
702 706 return
703 707 page(self.shell.inspector.format(file(filename).read()))
704 708
705 709 def _inspect(self,meth,oname,namespaces=None,**kw):
706 710 """Generic interface to the inspector system.
707 711
708 712 This function is meant to be called by pdef, pdoc & friends."""
709 713
710 714 #oname = oname.strip()
711 715 #print '1- oname: <%r>' % oname # dbg
712 716 try:
713 717 oname = oname.strip().encode('ascii')
714 718 #print '2- oname: <%r>' % oname # dbg
715 719 except UnicodeEncodeError:
716 720 print 'Python identifiers can only contain ascii characters.'
717 721 return 'not found'
718 722
719 723 info = Struct(self._ofind(oname, namespaces))
720 724
721 725 if info.found:
722 726 try:
723 727 IPython.generics.inspect_object(info.obj)
724 728 return
725 729 except IPython.ipapi.TryNext:
726 730 pass
727 731 # Get the docstring of the class property if it exists.
728 732 path = oname.split('.')
729 733 root = '.'.join(path[:-1])
730 734 if info.parent is not None:
731 735 try:
732 736 target = getattr(info.parent, '__class__')
733 737 # The object belongs to a class instance.
734 738 try:
735 739 target = getattr(target, path[-1])
736 740 # The class defines the object.
737 741 if isinstance(target, property):
738 742 oname = root + '.__class__.' + path[-1]
739 743 info = Struct(self._ofind(oname))
740 744 except AttributeError: pass
741 745 except AttributeError: pass
742 746
743 747 pmethod = getattr(self.shell.inspector,meth)
744 748 formatter = info.ismagic and self.format_screen or None
745 749 if meth == 'pdoc':
746 750 pmethod(info.obj,oname,formatter)
747 751 elif meth == 'pinfo':
748 752 pmethod(info.obj,oname,formatter,info,**kw)
749 753 else:
750 754 pmethod(info.obj,oname)
751 755 else:
752 756 print 'Object `%s` not found.' % oname
753 757 return 'not found' # so callers can take other action
754 758
755 759 def magic_psearch(self, parameter_s=''):
756 760 """Search for object in namespaces by wildcard.
757 761
758 762 %psearch [options] PATTERN [OBJECT TYPE]
759 763
760 764 Note: ? can be used as a synonym for %psearch, at the beginning or at
761 765 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
762 766 rest of the command line must be unchanged (options come first), so
763 767 for example the following forms are equivalent
764 768
765 769 %psearch -i a* function
766 770 -i a* function?
767 771 ?-i a* function
768 772
769 773 Arguments:
770 774
771 775 PATTERN
772 776
773 777 where PATTERN is a string containing * as a wildcard similar to its
774 778 use in a shell. The pattern is matched in all namespaces on the
775 779 search path. By default objects starting with a single _ are not
776 780 matched, many IPython generated objects have a single
777 781 underscore. The default is case insensitive matching. Matching is
778 782 also done on the attributes of objects and not only on the objects
779 783 in a module.
780 784
781 785 [OBJECT TYPE]
782 786
783 787 Is the name of a python type from the types module. The name is
784 788 given in lowercase without the ending type, ex. StringType is
785 789 written string. By adding a type here only objects matching the
786 790 given type are matched. Using all here makes the pattern match all
787 791 types (this is the default).
788 792
789 793 Options:
790 794
791 795 -a: makes the pattern match even objects whose names start with a
792 796 single underscore. These names are normally ommitted from the
793 797 search.
794 798
795 799 -i/-c: make the pattern case insensitive/sensitive. If neither of
796 800 these options is given, the default is read from your ipythonrc
797 801 file. The option name which sets this value is
798 802 'wildcards_case_sensitive'. If this option is not specified in your
799 803 ipythonrc file, IPython's internal default is to do a case sensitive
800 804 search.
801 805
802 806 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
803 807 specifiy can be searched in any of the following namespaces:
804 808 'builtin', 'user', 'user_global','internal', 'alias', where
805 809 'builtin' and 'user' are the search defaults. Note that you should
806 810 not use quotes when specifying namespaces.
807 811
808 812 'Builtin' contains the python module builtin, 'user' contains all
809 813 user data, 'alias' only contain the shell aliases and no python
810 814 objects, 'internal' contains objects used by IPython. The
811 815 'user_global' namespace is only used by embedded IPython instances,
812 816 and it contains module-level globals. You can add namespaces to the
813 817 search with -s or exclude them with -e (these options can be given
814 818 more than once).
815 819
816 820 Examples:
817 821
818 822 %psearch a* -> objects beginning with an a
819 823 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
820 824 %psearch a* function -> all functions beginning with an a
821 825 %psearch re.e* -> objects beginning with an e in module re
822 826 %psearch r*.e* -> objects that start with e in modules starting in r
823 827 %psearch r*.* string -> all strings in modules beginning with r
824 828
825 829 Case sensitve search:
826 830
827 831 %psearch -c a* list all object beginning with lower case a
828 832
829 833 Show objects beginning with a single _:
830 834
831 835 %psearch -a _* list objects beginning with a single underscore"""
832 836 try:
833 837 parameter_s = parameter_s.encode('ascii')
834 838 except UnicodeEncodeError:
835 839 print 'Python identifiers can only contain ascii characters.'
836 840 return
837 841
838 842 # default namespaces to be searched
839 843 def_search = ['user','builtin']
840 844
841 845 # Process options/args
842 846 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
843 847 opt = opts.get
844 848 shell = self.shell
845 849 psearch = shell.inspector.psearch
846 850
847 851 # select case options
848 852 if opts.has_key('i'):
849 853 ignore_case = True
850 854 elif opts.has_key('c'):
851 855 ignore_case = False
852 856 else:
853 857 ignore_case = not shell.rc.wildcards_case_sensitive
854 858
855 859 # Build list of namespaces to search from user options
856 860 def_search.extend(opt('s',[]))
857 861 ns_exclude = ns_exclude=opt('e',[])
858 862 ns_search = [nm for nm in def_search if nm not in ns_exclude]
859 863
860 864 # Call the actual search
861 865 try:
862 866 psearch(args,shell.ns_table,ns_search,
863 867 show_all=opt('a'),ignore_case=ignore_case)
864 868 except:
865 869 shell.showtraceback()
866 870
867 871 def magic_who_ls(self, parameter_s=''):
868 872 """Return a sorted list of all interactive variables.
869 873
870 874 If arguments are given, only variables of types matching these
871 875 arguments are returned."""
872 876
873 877 user_ns = self.shell.user_ns
874 878 internal_ns = self.shell.internal_ns
875 879 user_config_ns = self.shell.user_config_ns
876 880 out = []
877 881 typelist = parameter_s.split()
878 882
879 883 for i in user_ns:
880 884 if not (i.startswith('_') or i.startswith('_i')) \
881 885 and not (i in internal_ns or i in user_config_ns):
882 886 if typelist:
883 887 if type(user_ns[i]).__name__ in typelist:
884 888 out.append(i)
885 889 else:
886 890 out.append(i)
887 891 out.sort()
888 892 return out
889 893
890 894 def magic_who(self, parameter_s=''):
891 895 """Print all interactive variables, with some minimal formatting.
892 896
893 897 If any arguments are given, only variables whose type matches one of
894 898 these are printed. For example:
895 899
896 900 %who function str
897 901
898 902 will only list functions and strings, excluding all other types of
899 903 variables. To find the proper type names, simply use type(var) at a
900 904 command line to see how python prints type names. For example:
901 905
902 906 In [1]: type('hello')\\
903 907 Out[1]: <type 'str'>
904 908
905 909 indicates that the type name for strings is 'str'.
906 910
907 911 %who always excludes executed names loaded through your configuration
908 912 file and things which are internal to IPython.
909 913
910 914 This is deliberate, as typically you may load many modules and the
911 915 purpose of %who is to show you only what you've manually defined."""
912 916
913 917 varlist = self.magic_who_ls(parameter_s)
914 918 if not varlist:
915 919 if parameter_s:
916 920 print 'No variables match your requested type.'
917 921 else:
918 922 print 'Interactive namespace is empty.'
919 923 return
920 924
921 925 # if we have variables, move on...
922 926 count = 0
923 927 for i in varlist:
924 928 print i+'\t',
925 929 count += 1
926 930 if count > 8:
927 931 count = 0
928 932 print
929 933 print
930 934
931 935 def magic_whos(self, parameter_s=''):
932 936 """Like %who, but gives some extra information about each variable.
933 937
934 938 The same type filtering of %who can be applied here.
935 939
936 940 For all variables, the type is printed. Additionally it prints:
937 941
938 942 - For {},[],(): their length.
939 943
940 944 - For numpy and Numeric arrays, a summary with shape, number of
941 945 elements, typecode and size in memory.
942 946
943 947 - Everything else: a string representation, snipping their middle if
944 948 too long."""
945 949
946 950 varnames = self.magic_who_ls(parameter_s)
947 951 if not varnames:
948 952 if parameter_s:
949 953 print 'No variables match your requested type.'
950 954 else:
951 955 print 'Interactive namespace is empty.'
952 956 return
953 957
954 958 # if we have variables, move on...
955 959
956 960 # for these types, show len() instead of data:
957 961 seq_types = [types.DictType,types.ListType,types.TupleType]
958 962
959 963 # for numpy/Numeric arrays, display summary info
960 964 try:
961 965 import numpy
962 966 except ImportError:
963 967 ndarray_type = None
964 968 else:
965 969 ndarray_type = numpy.ndarray.__name__
966 970 try:
967 971 import Numeric
968 972 except ImportError:
969 973 array_type = None
970 974 else:
971 975 array_type = Numeric.ArrayType.__name__
972 976
973 977 # Find all variable names and types so we can figure out column sizes
974 978 def get_vars(i):
975 979 return self.shell.user_ns[i]
976 980
977 981 # some types are well known and can be shorter
978 982 abbrevs = {'IPython.macro.Macro' : 'Macro'}
979 983 def type_name(v):
980 984 tn = type(v).__name__
981 985 return abbrevs.get(tn,tn)
982 986
983 987 varlist = map(get_vars,varnames)
984 988
985 989 typelist = []
986 990 for vv in varlist:
987 991 tt = type_name(vv)
988 992
989 993 if tt=='instance':
990 994 typelist.append( abbrevs.get(str(vv.__class__),
991 995 str(vv.__class__)))
992 996 else:
993 997 typelist.append(tt)
994 998
995 999 # column labels and # of spaces as separator
996 1000 varlabel = 'Variable'
997 1001 typelabel = 'Type'
998 1002 datalabel = 'Data/Info'
999 1003 colsep = 3
1000 1004 # variable format strings
1001 1005 vformat = "$vname.ljust(varwidth)$vtype.ljust(typewidth)"
1002 1006 vfmt_short = '$vstr[:25]<...>$vstr[-25:]'
1003 1007 aformat = "%s: %s elems, type `%s`, %s bytes"
1004 1008 # find the size of the columns to format the output nicely
1005 1009 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
1006 1010 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
1007 1011 # table header
1008 1012 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
1009 1013 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
1010 1014 # and the table itself
1011 1015 kb = 1024
1012 1016 Mb = 1048576 # kb**2
1013 1017 for vname,var,vtype in zip(varnames,varlist,typelist):
1014 1018 print itpl(vformat),
1015 1019 if vtype in seq_types:
1016 1020 print len(var)
1017 1021 elif vtype in [array_type,ndarray_type]:
1018 1022 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
1019 1023 if vtype==ndarray_type:
1020 1024 # numpy
1021 1025 vsize = var.size
1022 1026 vbytes = vsize*var.itemsize
1023 1027 vdtype = var.dtype
1024 1028 else:
1025 1029 # Numeric
1026 1030 vsize = Numeric.size(var)
1027 1031 vbytes = vsize*var.itemsize()
1028 1032 vdtype = var.typecode()
1029 1033
1030 1034 if vbytes < 100000:
1031 1035 print aformat % (vshape,vsize,vdtype,vbytes)
1032 1036 else:
1033 1037 print aformat % (vshape,vsize,vdtype,vbytes),
1034 1038 if vbytes < Mb:
1035 1039 print '(%s kb)' % (vbytes/kb,)
1036 1040 else:
1037 1041 print '(%s Mb)' % (vbytes/Mb,)
1038 1042 else:
1039 1043 try:
1040 1044 vstr = str(var)
1041 1045 except UnicodeEncodeError:
1042 1046 vstr = unicode(var).encode(sys.getdefaultencoding(),
1043 1047 'backslashreplace')
1044 1048 vstr = vstr.replace('\n','\\n')
1045 1049 if len(vstr) < 50:
1046 1050 print vstr
1047 1051 else:
1048 1052 printpl(vfmt_short)
1049 1053
1050 1054 def magic_reset(self, parameter_s=''):
1051 1055 """Resets the namespace by removing all names defined by the user.
1052 1056
1053 1057 Input/Output history are left around in case you need them."""
1054 1058
1055 1059 ans = self.shell.ask_yes_no(
1056 1060 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ")
1057 1061 if not ans:
1058 1062 print 'Nothing done.'
1059 1063 return
1060 1064 user_ns = self.shell.user_ns
1061 1065 for i in self.magic_who_ls():
1062 1066 del(user_ns[i])
1063 1067
1064 1068 # Also flush the private list of module references kept for script
1065 1069 # execution protection
1066 1070 self.shell._user_main_modules[:] = []
1067 1071
1068 1072 def magic_logstart(self,parameter_s=''):
1069 1073 """Start logging anywhere in a session.
1070 1074
1071 1075 %logstart [-o|-r|-t] [log_name [log_mode]]
1072 1076
1073 1077 If no name is given, it defaults to a file named 'ipython_log.py' in your
1074 1078 current directory, in 'rotate' mode (see below).
1075 1079
1076 1080 '%logstart name' saves to file 'name' in 'backup' mode. It saves your
1077 1081 history up to that point and then continues logging.
1078 1082
1079 1083 %logstart takes a second optional parameter: logging mode. This can be one
1080 1084 of (note that the modes are given unquoted):\\
1081 1085 append: well, that says it.\\
1082 1086 backup: rename (if exists) to name~ and start name.\\
1083 1087 global: single logfile in your home dir, appended to.\\
1084 1088 over : overwrite existing log.\\
1085 1089 rotate: create rotating logs name.1~, name.2~, etc.
1086 1090
1087 1091 Options:
1088 1092
1089 1093 -o: log also IPython's output. In this mode, all commands which
1090 1094 generate an Out[NN] prompt are recorded to the logfile, right after
1091 1095 their corresponding input line. The output lines are always
1092 1096 prepended with a '#[Out]# ' marker, so that the log remains valid
1093 1097 Python code.
1094 1098
1095 1099 Since this marker is always the same, filtering only the output from
1096 1100 a log is very easy, using for example a simple awk call:
1097 1101
1098 1102 awk -F'#\\[Out\\]# ' '{if($2) {print $2}}' ipython_log.py
1099 1103
1100 1104 -r: log 'raw' input. Normally, IPython's logs contain the processed
1101 1105 input, so that user lines are logged in their final form, converted
1102 1106 into valid Python. For example, %Exit is logged as
1103 1107 '_ip.magic("Exit"). If the -r flag is given, all input is logged
1104 1108 exactly as typed, with no transformations applied.
1105 1109
1106 1110 -t: put timestamps before each input line logged (these are put in
1107 1111 comments)."""
1108 1112
1109 1113 opts,par = self.parse_options(parameter_s,'ort')
1110 1114 log_output = 'o' in opts
1111 1115 log_raw_input = 'r' in opts
1112 1116 timestamp = 't' in opts
1113 1117
1114 1118 rc = self.shell.rc
1115 1119 logger = self.shell.logger
1116 1120
1117 1121 # if no args are given, the defaults set in the logger constructor by
1118 1122 # ipytohn remain valid
1119 1123 if par:
1120 1124 try:
1121 1125 logfname,logmode = par.split()
1122 1126 except:
1123 1127 logfname = par
1124 1128 logmode = 'backup'
1125 1129 else:
1126 1130 logfname = logger.logfname
1127 1131 logmode = logger.logmode
1128 1132 # put logfname into rc struct as if it had been called on the command
1129 1133 # line, so it ends up saved in the log header Save it in case we need
1130 1134 # to restore it...
1131 1135 old_logfile = rc.opts.get('logfile','')
1132 1136 if logfname:
1133 1137 logfname = os.path.expanduser(logfname)
1134 1138 rc.opts.logfile = logfname
1135 1139 loghead = self.shell.loghead_tpl % (rc.opts,rc.args)
1136 1140 try:
1137 1141 started = logger.logstart(logfname,loghead,logmode,
1138 1142 log_output,timestamp,log_raw_input)
1139 1143 except:
1140 1144 rc.opts.logfile = old_logfile
1141 1145 warn("Couldn't start log: %s" % sys.exc_info()[1])
1142 1146 else:
1143 1147 # log input history up to this point, optionally interleaving
1144 1148 # output if requested
1145 1149
1146 1150 if timestamp:
1147 1151 # disable timestamping for the previous history, since we've
1148 1152 # lost those already (no time machine here).
1149 1153 logger.timestamp = False
1150 1154
1151 1155 if log_raw_input:
1152 1156 input_hist = self.shell.input_hist_raw
1153 1157 else:
1154 1158 input_hist = self.shell.input_hist
1155 1159
1156 1160 if log_output:
1157 1161 log_write = logger.log_write
1158 1162 output_hist = self.shell.output_hist
1159 1163 for n in range(1,len(input_hist)-1):
1160 1164 log_write(input_hist[n].rstrip())
1161 1165 if n in output_hist:
1162 1166 log_write(repr(output_hist[n]),'output')
1163 1167 else:
1164 1168 logger.log_write(input_hist[1:])
1165 1169 if timestamp:
1166 1170 # re-enable timestamping
1167 1171 logger.timestamp = True
1168 1172
1169 1173 print ('Activating auto-logging. '
1170 1174 'Current session state plus future input saved.')
1171 1175 logger.logstate()
1172 1176
1173 1177 def magic_logstop(self,parameter_s=''):
1174 1178 """Fully stop logging and close log file.
1175 1179
1176 1180 In order to start logging again, a new %logstart call needs to be made,
1177 1181 possibly (though not necessarily) with a new filename, mode and other
1178 1182 options."""
1179 1183 self.logger.logstop()
1180 1184
1181 1185 def magic_logoff(self,parameter_s=''):
1182 1186 """Temporarily stop logging.
1183 1187
1184 1188 You must have previously started logging."""
1185 1189 self.shell.logger.switch_log(0)
1186 1190
1187 1191 def magic_logon(self,parameter_s=''):
1188 1192 """Restart logging.
1189 1193
1190 1194 This function is for restarting logging which you've temporarily
1191 1195 stopped with %logoff. For starting logging for the first time, you
1192 1196 must use the %logstart function, which allows you to specify an
1193 1197 optional log filename."""
1194 1198
1195 1199 self.shell.logger.switch_log(1)
1196 1200
1197 1201 def magic_logstate(self,parameter_s=''):
1198 1202 """Print the status of the logging system."""
1199 1203
1200 1204 self.shell.logger.logstate()
1201 1205
1202 1206 def magic_pdb(self, parameter_s=''):
1203 1207 """Control the automatic calling of the pdb interactive debugger.
1204 1208
1205 1209 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
1206 1210 argument it works as a toggle.
1207 1211
1208 1212 When an exception is triggered, IPython can optionally call the
1209 1213 interactive pdb debugger after the traceback printout. %pdb toggles
1210 1214 this feature on and off.
1211 1215
1212 1216 The initial state of this feature is set in your ipythonrc
1213 1217 configuration file (the variable is called 'pdb').
1214 1218
1215 1219 If you want to just activate the debugger AFTER an exception has fired,
1216 1220 without having to type '%pdb on' and rerunning your code, you can use
1217 1221 the %debug magic."""
1218 1222
1219 1223 par = parameter_s.strip().lower()
1220 1224
1221 1225 if par:
1222 1226 try:
1223 1227 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
1224 1228 except KeyError:
1225 1229 print ('Incorrect argument. Use on/1, off/0, '
1226 1230 'or nothing for a toggle.')
1227 1231 return
1228 1232 else:
1229 1233 # toggle
1230 1234 new_pdb = not self.shell.call_pdb
1231 1235
1232 1236 # set on the shell
1233 1237 self.shell.call_pdb = new_pdb
1234 1238 print 'Automatic pdb calling has been turned',on_off(new_pdb)
1235 1239
1236 1240 def magic_debug(self, parameter_s=''):
1237 1241 """Activate the interactive debugger in post-mortem mode.
1238 1242
1239 1243 If an exception has just occurred, this lets you inspect its stack
1240 1244 frames interactively. Note that this will always work only on the last
1241 1245 traceback that occurred, so you must call this quickly after an
1242 1246 exception that you wish to inspect has fired, because if another one
1243 1247 occurs, it clobbers the previous one.
1244 1248
1245 1249 If you want IPython to automatically do this on every exception, see
1246 1250 the %pdb magic for more details.
1247 1251 """
1248 1252
1249 1253 self.shell.debugger(force=True)
1250 1254
1251 1255 @testdec.skip_doctest
1252 1256 def magic_prun(self, parameter_s ='',user_mode=1,
1253 1257 opts=None,arg_lst=None,prog_ns=None):
1254 1258
1255 1259 """Run a statement through the python code profiler.
1256 1260
1257 1261 Usage:
1258 1262 %prun [options] statement
1259 1263
1260 1264 The given statement (which doesn't require quote marks) is run via the
1261 1265 python profiler in a manner similar to the profile.run() function.
1262 1266 Namespaces are internally managed to work correctly; profile.run
1263 1267 cannot be used in IPython because it makes certain assumptions about
1264 1268 namespaces which do not hold under IPython.
1265 1269
1266 1270 Options:
1267 1271
1268 1272 -l <limit>: you can place restrictions on what or how much of the
1269 1273 profile gets printed. The limit value can be:
1270 1274
1271 1275 * A string: only information for function names containing this string
1272 1276 is printed.
1273 1277
1274 1278 * An integer: only these many lines are printed.
1275 1279
1276 1280 * A float (between 0 and 1): this fraction of the report is printed
1277 1281 (for example, use a limit of 0.4 to see the topmost 40% only).
1278 1282
1279 1283 You can combine several limits with repeated use of the option. For
1280 1284 example, '-l __init__ -l 5' will print only the topmost 5 lines of
1281 1285 information about class constructors.
1282 1286
1283 1287 -r: return the pstats.Stats object generated by the profiling. This
1284 1288 object has all the information about the profile in it, and you can
1285 1289 later use it for further analysis or in other functions.
1286 1290
1287 1291 -s <key>: sort profile by given key. You can provide more than one key
1288 1292 by using the option several times: '-s key1 -s key2 -s key3...'. The
1289 1293 default sorting key is 'time'.
1290 1294
1291 1295 The following is copied verbatim from the profile documentation
1292 1296 referenced below:
1293 1297
1294 1298 When more than one key is provided, additional keys are used as
1295 1299 secondary criteria when the there is equality in all keys selected
1296 1300 before them.
1297 1301
1298 1302 Abbreviations can be used for any key names, as long as the
1299 1303 abbreviation is unambiguous. The following are the keys currently
1300 1304 defined:
1301 1305
1302 1306 Valid Arg Meaning
1303 1307 "calls" call count
1304 1308 "cumulative" cumulative time
1305 1309 "file" file name
1306 1310 "module" file name
1307 1311 "pcalls" primitive call count
1308 1312 "line" line number
1309 1313 "name" function name
1310 1314 "nfl" name/file/line
1311 1315 "stdname" standard name
1312 1316 "time" internal time
1313 1317
1314 1318 Note that all sorts on statistics are in descending order (placing
1315 1319 most time consuming items first), where as name, file, and line number
1316 1320 searches are in ascending order (i.e., alphabetical). The subtle
1317 1321 distinction between "nfl" and "stdname" is that the standard name is a
1318 1322 sort of the name as printed, which means that the embedded line
1319 1323 numbers get compared in an odd way. For example, lines 3, 20, and 40
1320 1324 would (if the file names were the same) appear in the string order
1321 1325 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
1322 1326 line numbers. In fact, sort_stats("nfl") is the same as
1323 1327 sort_stats("name", "file", "line").
1324 1328
1325 1329 -T <filename>: save profile results as shown on screen to a text
1326 1330 file. The profile is still shown on screen.
1327 1331
1328 1332 -D <filename>: save (via dump_stats) profile statistics to given
1329 1333 filename. This data is in a format understod by the pstats module, and
1330 1334 is generated by a call to the dump_stats() method of profile
1331 1335 objects. The profile is still shown on screen.
1332 1336
1333 1337 If you want to run complete programs under the profiler's control, use
1334 1338 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
1335 1339 contains profiler specific options as described here.
1336 1340
1337 1341 You can read the complete documentation for the profile module with::
1338 1342
1339 1343 In [1]: import profile; profile.help()
1340 1344 """
1341 1345
1342 1346 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
1343 1347 # protect user quote marks
1344 1348 parameter_s = parameter_s.replace('"',r'\"').replace("'",r"\'")
1345 1349
1346 1350 if user_mode: # regular user call
1347 1351 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:',
1348 1352 list_all=1)
1349 1353 namespace = self.shell.user_ns
1350 1354 else: # called to run a program by %run -p
1351 1355 try:
1352 1356 filename = get_py_filename(arg_lst[0])
1353 1357 except IOError,msg:
1354 1358 error(msg)
1355 1359 return
1356 1360
1357 1361 arg_str = 'execfile(filename,prog_ns)'
1358 1362 namespace = locals()
1359 1363
1360 1364 opts.merge(opts_def)
1361 1365
1362 1366 prof = profile.Profile()
1363 1367 try:
1364 1368 prof = prof.runctx(arg_str,namespace,namespace)
1365 1369 sys_exit = ''
1366 1370 except SystemExit:
1367 1371 sys_exit = """*** SystemExit exception caught in code being profiled."""
1368 1372
1369 1373 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
1370 1374
1371 1375 lims = opts.l
1372 1376 if lims:
1373 1377 lims = [] # rebuild lims with ints/floats/strings
1374 1378 for lim in opts.l:
1375 1379 try:
1376 1380 lims.append(int(lim))
1377 1381 except ValueError:
1378 1382 try:
1379 1383 lims.append(float(lim))
1380 1384 except ValueError:
1381 1385 lims.append(lim)
1382 1386
1383 1387 # Trap output.
1384 1388 stdout_trap = StringIO()
1385 1389
1386 1390 if hasattr(stats,'stream'):
1387 1391 # In newer versions of python, the stats object has a 'stream'
1388 1392 # attribute to write into.
1389 1393 stats.stream = stdout_trap
1390 1394 stats.print_stats(*lims)
1391 1395 else:
1392 1396 # For older versions, we manually redirect stdout during printing
1393 1397 sys_stdout = sys.stdout
1394 1398 try:
1395 1399 sys.stdout = stdout_trap
1396 1400 stats.print_stats(*lims)
1397 1401 finally:
1398 1402 sys.stdout = sys_stdout
1399 1403
1400 1404 output = stdout_trap.getvalue()
1401 1405 output = output.rstrip()
1402 1406
1403 1407 page(output,screen_lines=self.shell.rc.screen_length)
1404 1408 print sys_exit,
1405 1409
1406 1410 dump_file = opts.D[0]
1407 1411 text_file = opts.T[0]
1408 1412 if dump_file:
1409 1413 prof.dump_stats(dump_file)
1410 1414 print '\n*** Profile stats marshalled to file',\
1411 1415 `dump_file`+'.',sys_exit
1412 1416 if text_file:
1413 1417 pfile = file(text_file,'w')
1414 1418 pfile.write(output)
1415 1419 pfile.close()
1416 1420 print '\n*** Profile printout saved to text file',\
1417 1421 `text_file`+'.',sys_exit
1418 1422
1419 1423 if opts.has_key('r'):
1420 1424 return stats
1421 1425 else:
1422 1426 return None
1423 1427
1424 1428 @testdec.skip_doctest
1425 1429 def magic_run(self, parameter_s ='',runner=None):
1426 1430 """Run the named file inside IPython as a program.
1427 1431
1428 1432 Usage:\\
1429 1433 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
1430 1434
1431 1435 Parameters after the filename are passed as command-line arguments to
1432 1436 the program (put in sys.argv). Then, control returns to IPython's
1433 1437 prompt.
1434 1438
1435 1439 This is similar to running at a system prompt:\\
1436 1440 $ python file args\\
1437 1441 but with the advantage of giving you IPython's tracebacks, and of
1438 1442 loading all variables into your interactive namespace for further use
1439 1443 (unless -p is used, see below).
1440 1444
1441 1445 The file is executed in a namespace initially consisting only of
1442 1446 __name__=='__main__' and sys.argv constructed as indicated. It thus
1443 1447 sees its environment as if it were being run as a stand-alone program
1444 1448 (except for sharing global objects such as previously imported
1445 1449 modules). But after execution, the IPython interactive namespace gets
1446 1450 updated with all variables defined in the program (except for __name__
1447 1451 and sys.argv). This allows for very convenient loading of code for
1448 1452 interactive work, while giving each program a 'clean sheet' to run in.
1449 1453
1450 1454 Options:
1451 1455
1452 1456 -n: __name__ is NOT set to '__main__', but to the running file's name
1453 1457 without extension (as python does under import). This allows running
1454 1458 scripts and reloading the definitions in them without calling code
1455 1459 protected by an ' if __name__ == "__main__" ' clause.
1456 1460
1457 1461 -i: run the file in IPython's namespace instead of an empty one. This
1458 1462 is useful if you are experimenting with code written in a text editor
1459 1463 which depends on variables defined interactively.
1460 1464
1461 1465 -e: ignore sys.exit() calls or SystemExit exceptions in the script
1462 1466 being run. This is particularly useful if IPython is being used to
1463 1467 run unittests, which always exit with a sys.exit() call. In such
1464 1468 cases you are interested in the output of the test results, not in
1465 1469 seeing a traceback of the unittest module.
1466 1470
1467 1471 -t: print timing information at the end of the run. IPython will give
1468 1472 you an estimated CPU time consumption for your script, which under
1469 1473 Unix uses the resource module to avoid the wraparound problems of
1470 1474 time.clock(). Under Unix, an estimate of time spent on system tasks
1471 1475 is also given (for Windows platforms this is reported as 0.0).
1472 1476
1473 1477 If -t is given, an additional -N<N> option can be given, where <N>
1474 1478 must be an integer indicating how many times you want the script to
1475 1479 run. The final timing report will include total and per run results.
1476 1480
1477 1481 For example (testing the script uniq_stable.py):
1478 1482
1479 1483 In [1]: run -t uniq_stable
1480 1484
1481 1485 IPython CPU timings (estimated):\\
1482 1486 User : 0.19597 s.\\
1483 1487 System: 0.0 s.\\
1484 1488
1485 1489 In [2]: run -t -N5 uniq_stable
1486 1490
1487 1491 IPython CPU timings (estimated):\\
1488 1492 Total runs performed: 5\\
1489 1493 Times : Total Per run\\
1490 1494 User : 0.910862 s, 0.1821724 s.\\
1491 1495 System: 0.0 s, 0.0 s.
1492 1496
1493 1497 -d: run your program under the control of pdb, the Python debugger.
1494 1498 This allows you to execute your program step by step, watch variables,
1495 1499 etc. Internally, what IPython does is similar to calling:
1496 1500
1497 1501 pdb.run('execfile("YOURFILENAME")')
1498 1502
1499 1503 with a breakpoint set on line 1 of your file. You can change the line
1500 1504 number for this automatic breakpoint to be <N> by using the -bN option
1501 1505 (where N must be an integer). For example:
1502 1506
1503 1507 %run -d -b40 myscript
1504 1508
1505 1509 will set the first breakpoint at line 40 in myscript.py. Note that
1506 1510 the first breakpoint must be set on a line which actually does
1507 1511 something (not a comment or docstring) for it to stop execution.
1508 1512
1509 1513 When the pdb debugger starts, you will see a (Pdb) prompt. You must
1510 1514 first enter 'c' (without qoutes) to start execution up to the first
1511 1515 breakpoint.
1512 1516
1513 1517 Entering 'help' gives information about the use of the debugger. You
1514 1518 can easily see pdb's full documentation with "import pdb;pdb.help()"
1515 1519 at a prompt.
1516 1520
1517 1521 -p: run program under the control of the Python profiler module (which
1518 1522 prints a detailed report of execution times, function calls, etc).
1519 1523
1520 1524 You can pass other options after -p which affect the behavior of the
1521 1525 profiler itself. See the docs for %prun for details.
1522 1526
1523 1527 In this mode, the program's variables do NOT propagate back to the
1524 1528 IPython interactive namespace (because they remain in the namespace
1525 1529 where the profiler executes them).
1526 1530
1527 1531 Internally this triggers a call to %prun, see its documentation for
1528 1532 details on the options available specifically for profiling.
1529 1533
1530 1534 There is one special usage for which the text above doesn't apply:
1531 1535 if the filename ends with .ipy, the file is run as ipython script,
1532 1536 just as if the commands were written on IPython prompt.
1533 1537 """
1534 1538
1535 1539 # get arguments and set sys.argv for program to be run.
1536 1540 opts,arg_lst = self.parse_options(parameter_s,'nidtN:b:pD:l:rs:T:e',
1537 1541 mode='list',list_all=1)
1538 1542
1539 1543 try:
1540 1544 filename = get_py_filename(arg_lst[0])
1541 1545 except IndexError:
1542 1546 warn('you must provide at least a filename.')
1543 1547 print '\n%run:\n',OInspect.getdoc(self.magic_run)
1544 1548 return
1545 1549 except IOError,msg:
1546 1550 error(msg)
1547 1551 return
1548 1552
1549 1553 if filename.lower().endswith('.ipy'):
1550 1554 self.api.runlines(open(filename).read())
1551 1555 return
1552 1556
1553 1557 # Control the response to exit() calls made by the script being run
1554 1558 exit_ignore = opts.has_key('e')
1555 1559
1556 1560 # Make sure that the running script gets a proper sys.argv as if it
1557 1561 # were run from a system shell.
1558 1562 save_argv = sys.argv # save it for later restoring
1559 1563 sys.argv = [filename]+ arg_lst[1:] # put in the proper filename
1560 1564
1561 1565 if opts.has_key('i'):
1562 1566 # Run in user's interactive namespace
1563 1567 prog_ns = self.shell.user_ns
1564 1568 __name__save = self.shell.user_ns['__name__']
1565 1569 prog_ns['__name__'] = '__main__'
1566 1570 main_mod = FakeModule(prog_ns)
1567 1571 else:
1568 1572 # Run in a fresh, empty namespace
1569 1573 if opts.has_key('n'):
1570 1574 name = os.path.splitext(os.path.basename(filename))[0]
1571 1575 else:
1572 1576 name = '__main__'
1573 1577 main_mod = FakeModule()
1574 1578 prog_ns = main_mod.__dict__
1575 1579 prog_ns['__name__'] = name
1576 1580 # The shell MUST hold a reference to main_mod so after %run exits,
1577 1581 # the python deletion mechanism doesn't zero it out (leaving
1578 1582 # dangling references)
1579 1583 self.shell._user_main_modules.append(main_mod)
1580 1584
1581 1585 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
1582 1586 # set the __file__ global in the script's namespace
1583 1587 prog_ns['__file__'] = filename
1584 1588
1585 1589 # pickle fix. See iplib for an explanation. But we need to make sure
1586 1590 # that, if we overwrite __main__, we replace it at the end
1587 1591 main_mod_name = prog_ns['__name__']
1588 1592
1589 1593 if main_mod_name == '__main__':
1590 1594 restore_main = sys.modules['__main__']
1591 1595 else:
1592 1596 restore_main = False
1593 1597
1594 1598 # This needs to be undone at the end to prevent holding references to
1595 1599 # every single object ever created.
1596 1600 sys.modules[main_mod_name] = main_mod
1597 1601
1598 1602 stats = None
1599 1603 try:
1600 1604 self.shell.savehist()
1601 1605
1602 1606 if opts.has_key('p'):
1603 1607 stats = self.magic_prun('',0,opts,arg_lst,prog_ns)
1604 1608 else:
1605 1609 if opts.has_key('d'):
1606 1610 deb = Debugger.Pdb(self.shell.rc.colors)
1607 1611 # reset Breakpoint state, which is moronically kept
1608 1612 # in a class
1609 1613 bdb.Breakpoint.next = 1
1610 1614 bdb.Breakpoint.bplist = {}
1611 1615 bdb.Breakpoint.bpbynumber = [None]
1612 1616 # Set an initial breakpoint to stop execution
1613 1617 maxtries = 10
1614 1618 bp = int(opts.get('b',[1])[0])
1615 1619 checkline = deb.checkline(filename,bp)
1616 1620 if not checkline:
1617 1621 for bp in range(bp+1,bp+maxtries+1):
1618 1622 if deb.checkline(filename,bp):
1619 1623 break
1620 1624 else:
1621 1625 msg = ("\nI failed to find a valid line to set "
1622 1626 "a breakpoint\n"
1623 1627 "after trying up to line: %s.\n"
1624 1628 "Please set a valid breakpoint manually "
1625 1629 "with the -b option." % bp)
1626 1630 error(msg)
1627 1631 return
1628 1632 # if we find a good linenumber, set the breakpoint
1629 1633 deb.do_break('%s:%s' % (filename,bp))
1630 1634 # Start file run
1631 1635 print "NOTE: Enter 'c' at the",
1632 1636 print "%s prompt to start your script." % deb.prompt
1633 1637 try:
1634 1638 deb.run('execfile("%s")' % filename,prog_ns)
1635 1639
1636 1640 except:
1637 1641 etype, value, tb = sys.exc_info()
1638 1642 # Skip three frames in the traceback: the %run one,
1639 1643 # one inside bdb.py, and the command-line typed by the
1640 1644 # user (run by exec in pdb itself).
1641 1645 self.shell.InteractiveTB(etype,value,tb,tb_offset=3)
1642 1646 else:
1643 1647 if runner is None:
1644 1648 runner = self.shell.safe_execfile
1645 1649 if opts.has_key('t'):
1646 1650 # timed execution
1647 1651 try:
1648 1652 nruns = int(opts['N'][0])
1649 1653 if nruns < 1:
1650 1654 error('Number of runs must be >=1')
1651 1655 return
1652 1656 except (KeyError):
1653 1657 nruns = 1
1654 1658 if nruns == 1:
1655 1659 t0 = clock2()
1656 1660 runner(filename,prog_ns,prog_ns,
1657 1661 exit_ignore=exit_ignore)
1658 1662 t1 = clock2()
1659 1663 t_usr = t1[0]-t0[0]
1660 1664 t_sys = t1[1]-t1[1]
1661 1665 print "\nIPython CPU timings (estimated):"
1662 1666 print " User : %10s s." % t_usr
1663 1667 print " System: %10s s." % t_sys
1664 1668 else:
1665 1669 runs = range(nruns)
1666 1670 t0 = clock2()
1667 1671 for nr in runs:
1668 1672 runner(filename,prog_ns,prog_ns,
1669 1673 exit_ignore=exit_ignore)
1670 1674 t1 = clock2()
1671 1675 t_usr = t1[0]-t0[0]
1672 1676 t_sys = t1[1]-t1[1]
1673 1677 print "\nIPython CPU timings (estimated):"
1674 1678 print "Total runs performed:",nruns
1675 1679 print " Times : %10s %10s" % ('Total','Per run')
1676 1680 print " User : %10s s, %10s s." % (t_usr,t_usr/nruns)
1677 1681 print " System: %10s s, %10s s." % (t_sys,t_sys/nruns)
1678 1682
1679 1683 else:
1680 1684 # regular execution
1681 1685 runner(filename,prog_ns,prog_ns,exit_ignore=exit_ignore)
1682 1686 if opts.has_key('i'):
1683 1687 self.shell.user_ns['__name__'] = __name__save
1684 1688 else:
1685 1689 # update IPython interactive namespace
1686 1690 del prog_ns['__name__']
1687 1691 self.shell.user_ns.update(prog_ns)
1688 1692 finally:
1689 1693 # Ensure key global structures are restored
1690 1694 sys.argv = save_argv
1691 1695 if restore_main:
1692 1696 sys.modules['__main__'] = restore_main
1693 1697 else:
1694 1698 # Remove from sys.modules the reference to main_mod we'd
1695 1699 # added. Otherwise it will trap references to objects
1696 1700 # contained therein.
1697 1701 del sys.modules[main_mod_name]
1698 1702 self.shell.reloadhist()
1699 1703
1700 1704 return stats
1701 1705
1702 1706 def magic_runlog(self, parameter_s =''):
1703 1707 """Run files as logs.
1704 1708
1705 1709 Usage:\\
1706 1710 %runlog file1 file2 ...
1707 1711
1708 1712 Run the named files (treating them as log files) in sequence inside
1709 1713 the interpreter, and return to the prompt. This is much slower than
1710 1714 %run because each line is executed in a try/except block, but it
1711 1715 allows running files with syntax errors in them.
1712 1716
1713 1717 Normally IPython will guess when a file is one of its own logfiles, so
1714 1718 you can typically use %run even for logs. This shorthand allows you to
1715 1719 force any file to be treated as a log file."""
1716 1720
1717 1721 for f in parameter_s.split():
1718 1722 self.shell.safe_execfile(f,self.shell.user_ns,
1719 1723 self.shell.user_ns,islog=1)
1720 1724
1721 1725 @testdec.skip_doctest
1722 1726 def magic_timeit(self, parameter_s =''):
1723 1727 """Time execution of a Python statement or expression
1724 1728
1725 1729 Usage:\\
1726 1730 %timeit [-n<N> -r<R> [-t|-c]] statement
1727 1731
1728 1732 Time execution of a Python statement or expression using the timeit
1729 1733 module.
1730 1734
1731 1735 Options:
1732 1736 -n<N>: execute the given statement <N> times in a loop. If this value
1733 1737 is not given, a fitting value is chosen.
1734 1738
1735 1739 -r<R>: repeat the loop iteration <R> times and take the best result.
1736 1740 Default: 3
1737 1741
1738 1742 -t: use time.time to measure the time, which is the default on Unix.
1739 1743 This function measures wall time.
1740 1744
1741 1745 -c: use time.clock to measure the time, which is the default on
1742 1746 Windows and measures wall time. On Unix, resource.getrusage is used
1743 1747 instead and returns the CPU user time.
1744 1748
1745 1749 -p<P>: use a precision of <P> digits to display the timing result.
1746 1750 Default: 3
1747 1751
1748 1752
1749 1753 Examples:
1750 1754
1751 1755 In [1]: %timeit pass
1752 1756 10000000 loops, best of 3: 53.3 ns per loop
1753 1757
1754 1758 In [2]: u = None
1755 1759
1756 1760 In [3]: %timeit u is None
1757 1761 10000000 loops, best of 3: 184 ns per loop
1758 1762
1759 1763 In [4]: %timeit -r 4 u == None
1760 1764 1000000 loops, best of 4: 242 ns per loop
1761 1765
1762 1766 In [5]: import time
1763 1767
1764 1768 In [6]: %timeit -n1 time.sleep(2)
1765 1769 1 loops, best of 3: 2 s per loop
1766 1770
1767 1771
1768 1772 The times reported by %timeit will be slightly higher than those
1769 1773 reported by the timeit.py script when variables are accessed. This is
1770 1774 due to the fact that %timeit executes the statement in the namespace
1771 1775 of the shell, compared with timeit.py, which uses a single setup
1772 1776 statement to import function or create variables. Generally, the bias
1773 1777 does not matter as long as results from timeit.py are not mixed with
1774 1778 those from %timeit."""
1775 1779
1776 1780 import timeit
1777 1781 import math
1778 1782
1779 1783 units = [u"s", u"ms", u"\xb5s", u"ns"]
1780 1784 scaling = [1, 1e3, 1e6, 1e9]
1781 1785
1782 1786 opts, stmt = self.parse_options(parameter_s,'n:r:tcp:',
1783 1787 posix=False)
1784 1788 if stmt == "":
1785 1789 return
1786 1790 timefunc = timeit.default_timer
1787 1791 number = int(getattr(opts, "n", 0))
1788 1792 repeat = int(getattr(opts, "r", timeit.default_repeat))
1789 1793 precision = int(getattr(opts, "p", 3))
1790 1794 if hasattr(opts, "t"):
1791 1795 timefunc = time.time
1792 1796 if hasattr(opts, "c"):
1793 1797 timefunc = clock
1794 1798
1795 1799 timer = timeit.Timer(timer=timefunc)
1796 1800 # this code has tight coupling to the inner workings of timeit.Timer,
1797 1801 # but is there a better way to achieve that the code stmt has access
1798 1802 # to the shell namespace?
1799 1803
1800 1804 src = timeit.template % {'stmt': timeit.reindent(stmt, 8),
1801 1805 'setup': "pass"}
1802 1806 # Track compilation time so it can be reported if too long
1803 1807 # Minimum time above which compilation time will be reported
1804 1808 tc_min = 0.1
1805 1809
1806 1810 t0 = clock()
1807 1811 code = compile(src, "<magic-timeit>", "exec")
1808 1812 tc = clock()-t0
1809 1813
1810 1814 ns = {}
1811 1815 exec code in self.shell.user_ns, ns
1812 1816 timer.inner = ns["inner"]
1813 1817
1814 1818 if number == 0:
1815 1819 # determine number so that 0.2 <= total time < 2.0
1816 1820 number = 1
1817 1821 for i in range(1, 10):
1818 1822 number *= 10
1819 1823 if timer.timeit(number) >= 0.2:
1820 1824 break
1821 1825
1822 1826 best = min(timer.repeat(repeat, number)) / number
1823 1827
1824 1828 if best > 0.0:
1825 1829 order = min(-int(math.floor(math.log10(best)) // 3), 3)
1826 1830 else:
1827 1831 order = 3
1828 1832 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
1829 1833 precision,
1830 1834 best * scaling[order],
1831 1835 units[order])
1832 1836 if tc > tc_min:
1833 1837 print "Compiler time: %.2f s" % tc
1834 1838
1835 1839 @testdec.skip_doctest
1836 1840 def magic_time(self,parameter_s = ''):
1837 1841 """Time execution of a Python statement or expression.
1838 1842
1839 1843 The CPU and wall clock times are printed, and the value of the
1840 1844 expression (if any) is returned. Note that under Win32, system time
1841 1845 is always reported as 0, since it can not be measured.
1842 1846
1843 1847 This function provides very basic timing functionality. In Python
1844 1848 2.3, the timeit module offers more control and sophistication, so this
1845 1849 could be rewritten to use it (patches welcome).
1846 1850
1847 1851 Some examples:
1848 1852
1849 1853 In [1]: time 2**128
1850 1854 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1851 1855 Wall time: 0.00
1852 1856 Out[1]: 340282366920938463463374607431768211456L
1853 1857
1854 1858 In [2]: n = 1000000
1855 1859
1856 1860 In [3]: time sum(range(n))
1857 1861 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1858 1862 Wall time: 1.37
1859 1863 Out[3]: 499999500000L
1860 1864
1861 1865 In [4]: time print 'hello world'
1862 1866 hello world
1863 1867 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1864 1868 Wall time: 0.00
1865 1869
1866 1870 Note that the time needed by Python to compile the given expression
1867 1871 will be reported if it is more than 0.1s. In this example, the
1868 1872 actual exponentiation is done by Python at compilation time, so while
1869 1873 the expression can take a noticeable amount of time to compute, that
1870 1874 time is purely due to the compilation:
1871 1875
1872 1876 In [5]: time 3**9999;
1873 1877 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1874 1878 Wall time: 0.00 s
1875 1879
1876 1880 In [6]: time 3**999999;
1877 1881 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1878 1882 Wall time: 0.00 s
1879 1883 Compiler : 0.78 s
1880 1884 """
1881 1885
1882 1886 # fail immediately if the given expression can't be compiled
1883 1887
1884 1888 expr = self.shell.prefilter(parameter_s,False)
1885 1889
1886 1890 # Minimum time above which compilation time will be reported
1887 1891 tc_min = 0.1
1888 1892
1889 1893 try:
1890 1894 mode = 'eval'
1891 1895 t0 = clock()
1892 1896 code = compile(expr,'<timed eval>',mode)
1893 1897 tc = clock()-t0
1894 1898 except SyntaxError:
1895 1899 mode = 'exec'
1896 1900 t0 = clock()
1897 1901 code = compile(expr,'<timed exec>',mode)
1898 1902 tc = clock()-t0
1899 1903 # skew measurement as little as possible
1900 1904 glob = self.shell.user_ns
1901 1905 clk = clock2
1902 1906 wtime = time.time
1903 1907 # time execution
1904 1908 wall_st = wtime()
1905 1909 if mode=='eval':
1906 1910 st = clk()
1907 1911 out = eval(code,glob)
1908 1912 end = clk()
1909 1913 else:
1910 1914 st = clk()
1911 1915 exec code in glob
1912 1916 end = clk()
1913 1917 out = None
1914 1918 wall_end = wtime()
1915 1919 # Compute actual times and report
1916 1920 wall_time = wall_end-wall_st
1917 1921 cpu_user = end[0]-st[0]
1918 1922 cpu_sys = end[1]-st[1]
1919 1923 cpu_tot = cpu_user+cpu_sys
1920 1924 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
1921 1925 (cpu_user,cpu_sys,cpu_tot)
1922 1926 print "Wall time: %.2f s" % wall_time
1923 1927 if tc > tc_min:
1924 1928 print "Compiler : %.2f s" % tc
1925 1929 return out
1926 1930
1927 1931 @testdec.skip_doctest
1928 1932 def magic_macro(self,parameter_s = ''):
1929 1933 """Define a set of input lines as a macro for future re-execution.
1930 1934
1931 1935 Usage:\\
1932 1936 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1933 1937
1934 1938 Options:
1935 1939
1936 1940 -r: use 'raw' input. By default, the 'processed' history is used,
1937 1941 so that magics are loaded in their transformed version to valid
1938 1942 Python. If this option is given, the raw input as typed as the
1939 1943 command line is used instead.
1940 1944
1941 1945 This will define a global variable called `name` which is a string
1942 1946 made of joining the slices and lines you specify (n1,n2,... numbers
1943 1947 above) from your input history into a single string. This variable
1944 1948 acts like an automatic function which re-executes those lines as if
1945 1949 you had typed them. You just type 'name' at the prompt and the code
1946 1950 executes.
1947 1951
1948 1952 The notation for indicating number ranges is: n1-n2 means 'use line
1949 1953 numbers n1,...n2' (the endpoint is included). That is, '5-7' means
1950 1954 using the lines numbered 5,6 and 7.
1951 1955
1952 1956 Note: as a 'hidden' feature, you can also use traditional python slice
1953 1957 notation, where N:M means numbers N through M-1.
1954 1958
1955 1959 For example, if your history contains (%hist prints it):
1956 1960
1957 1961 44: x=1
1958 1962 45: y=3
1959 1963 46: z=x+y
1960 1964 47: print x
1961 1965 48: a=5
1962 1966 49: print 'x',x,'y',y
1963 1967
1964 1968 you can create a macro with lines 44 through 47 (included) and line 49
1965 1969 called my_macro with:
1966 1970
1967 1971 In [55]: %macro my_macro 44-47 49
1968 1972
1969 1973 Now, typing `my_macro` (without quotes) will re-execute all this code
1970 1974 in one pass.
1971 1975
1972 1976 You don't need to give the line-numbers in order, and any given line
1973 1977 number can appear multiple times. You can assemble macros with any
1974 1978 lines from your input history in any order.
1975 1979
1976 1980 The macro is a simple object which holds its value in an attribute,
1977 1981 but IPython's display system checks for macros and executes them as
1978 1982 code instead of printing them when you type their name.
1979 1983
1980 1984 You can view a macro's contents by explicitly printing it with:
1981 1985
1982 1986 'print macro_name'.
1983 1987
1984 1988 For one-off cases which DON'T contain magic function calls in them you
1985 1989 can obtain similar results by explicitly executing slices from your
1986 1990 input history with:
1987 1991
1988 1992 In [60]: exec In[44:48]+In[49]"""
1989 1993
1990 1994 opts,args = self.parse_options(parameter_s,'r',mode='list')
1991 1995 if not args:
1992 1996 macs = [k for k,v in self.shell.user_ns.items() if isinstance(v, Macro)]
1993 1997 macs.sort()
1994 1998 return macs
1995 1999 if len(args) == 1:
1996 2000 raise UsageError(
1997 2001 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1998 2002 name,ranges = args[0], args[1:]
1999 2003
2000 2004 #print 'rng',ranges # dbg
2001 2005 lines = self.extract_input_slices(ranges,opts.has_key('r'))
2002 2006 macro = Macro(lines)
2003 2007 self.shell.user_ns.update({name:macro})
2004 2008 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2005 2009 print 'Macro contents:'
2006 2010 print macro,
2007 2011
2008 2012 def magic_save(self,parameter_s = ''):
2009 2013 """Save a set of lines to a given filename.
2010 2014
2011 2015 Usage:\\
2012 2016 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
2013 2017
2014 2018 Options:
2015 2019
2016 2020 -r: use 'raw' input. By default, the 'processed' history is used,
2017 2021 so that magics are loaded in their transformed version to valid
2018 2022 Python. If this option is given, the raw input as typed as the
2019 2023 command line is used instead.
2020 2024
2021 2025 This function uses the same syntax as %macro for line extraction, but
2022 2026 instead of creating a macro it saves the resulting string to the
2023 2027 filename you specify.
2024 2028
2025 2029 It adds a '.py' extension to the file if you don't do so yourself, and
2026 2030 it asks for confirmation before overwriting existing files."""
2027 2031
2028 2032 opts,args = self.parse_options(parameter_s,'r',mode='list')
2029 2033 fname,ranges = args[0], args[1:]
2030 2034 if not fname.endswith('.py'):
2031 2035 fname += '.py'
2032 2036 if os.path.isfile(fname):
2033 2037 ans = raw_input('File `%s` exists. Overwrite (y/[N])? ' % fname)
2034 2038 if ans.lower() not in ['y','yes']:
2035 2039 print 'Operation cancelled.'
2036 2040 return
2037 2041 cmds = ''.join(self.extract_input_slices(ranges,opts.has_key('r')))
2038 2042 f = file(fname,'w')
2039 2043 f.write(cmds)
2040 2044 f.close()
2041 2045 print 'The following commands were written to file `%s`:' % fname
2042 2046 print cmds
2043 2047
2044 2048 def _edit_macro(self,mname,macro):
2045 2049 """open an editor with the macro data in a file"""
2046 2050 filename = self.shell.mktempfile(macro.value)
2047 2051 self.shell.hooks.editor(filename)
2048 2052
2049 2053 # and make a new macro object, to replace the old one
2050 2054 mfile = open(filename)
2051 2055 mvalue = mfile.read()
2052 2056 mfile.close()
2053 2057 self.shell.user_ns[mname] = Macro(mvalue)
2054 2058
2055 2059 def magic_ed(self,parameter_s=''):
2056 2060 """Alias to %edit."""
2057 2061 return self.magic_edit(parameter_s)
2058 2062
2059 2063 @testdec.skip_doctest
2060 2064 def magic_edit(self,parameter_s='',last_call=['','']):
2061 2065 """Bring up an editor and execute the resulting code.
2062 2066
2063 2067 Usage:
2064 2068 %edit [options] [args]
2065 2069
2066 2070 %edit runs IPython's editor hook. The default version of this hook is
2067 2071 set to call the __IPYTHON__.rc.editor command. This is read from your
2068 2072 environment variable $EDITOR. If this isn't found, it will default to
2069 2073 vi under Linux/Unix and to notepad under Windows. See the end of this
2070 2074 docstring for how to change the editor hook.
2071 2075
2072 2076 You can also set the value of this editor via the command line option
2073 2077 '-editor' or in your ipythonrc file. This is useful if you wish to use
2074 2078 specifically for IPython an editor different from your typical default
2075 2079 (and for Windows users who typically don't set environment variables).
2076 2080
2077 2081 This command allows you to conveniently edit multi-line code right in
2078 2082 your IPython session.
2079 2083
2080 2084 If called without arguments, %edit opens up an empty editor with a
2081 2085 temporary file and will execute the contents of this file when you
2082 2086 close it (don't forget to save it!).
2083 2087
2084 2088
2085 2089 Options:
2086 2090
2087 2091 -n <number>: open the editor at a specified line number. By default,
2088 2092 the IPython editor hook uses the unix syntax 'editor +N filename', but
2089 2093 you can configure this by providing your own modified hook if your
2090 2094 favorite editor supports line-number specifications with a different
2091 2095 syntax.
2092 2096
2093 2097 -p: this will call the editor with the same data as the previous time
2094 2098 it was used, regardless of how long ago (in your current session) it
2095 2099 was.
2096 2100
2097 2101 -r: use 'raw' input. This option only applies to input taken from the
2098 2102 user's history. By default, the 'processed' history is used, so that
2099 2103 magics are loaded in their transformed version to valid Python. If
2100 2104 this option is given, the raw input as typed as the command line is
2101 2105 used instead. When you exit the editor, it will be executed by
2102 2106 IPython's own processor.
2103 2107
2104 2108 -x: do not execute the edited code immediately upon exit. This is
2105 2109 mainly useful if you are editing programs which need to be called with
2106 2110 command line arguments, which you can then do using %run.
2107 2111
2108 2112
2109 2113 Arguments:
2110 2114
2111 2115 If arguments are given, the following possibilites exist:
2112 2116
2113 2117 - The arguments are numbers or pairs of colon-separated numbers (like
2114 2118 1 4:8 9). These are interpreted as lines of previous input to be
2115 2119 loaded into the editor. The syntax is the same of the %macro command.
2116 2120
2117 2121 - If the argument doesn't start with a number, it is evaluated as a
2118 2122 variable and its contents loaded into the editor. You can thus edit
2119 2123 any string which contains python code (including the result of
2120 2124 previous edits).
2121 2125
2122 2126 - If the argument is the name of an object (other than a string),
2123 2127 IPython will try to locate the file where it was defined and open the
2124 2128 editor at the point where it is defined. You can use `%edit function`
2125 2129 to load an editor exactly at the point where 'function' is defined,
2126 2130 edit it and have the file be executed automatically.
2127 2131
2128 2132 If the object is a macro (see %macro for details), this opens up your
2129 2133 specified editor with a temporary file containing the macro's data.
2130 2134 Upon exit, the macro is reloaded with the contents of the file.
2131 2135
2132 2136 Note: opening at an exact line is only supported under Unix, and some
2133 2137 editors (like kedit and gedit up to Gnome 2.8) do not understand the
2134 2138 '+NUMBER' parameter necessary for this feature. Good editors like
2135 2139 (X)Emacs, vi, jed, pico and joe all do.
2136 2140
2137 2141 - If the argument is not found as a variable, IPython will look for a
2138 2142 file with that name (adding .py if necessary) and load it into the
2139 2143 editor. It will execute its contents with execfile() when you exit,
2140 2144 loading any code in the file into your interactive namespace.
2141 2145
2142 2146 After executing your code, %edit will return as output the code you
2143 2147 typed in the editor (except when it was an existing file). This way
2144 2148 you can reload the code in further invocations of %edit as a variable,
2145 2149 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
2146 2150 the output.
2147 2151
2148 2152 Note that %edit is also available through the alias %ed.
2149 2153
2150 2154 This is an example of creating a simple function inside the editor and
2151 2155 then modifying it. First, start up the editor:
2152 2156
2153 2157 In [1]: ed
2154 2158 Editing... done. Executing edited code...
2155 2159 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
2156 2160
2157 2161 We can then call the function foo():
2158 2162
2159 2163 In [2]: foo()
2160 2164 foo() was defined in an editing session
2161 2165
2162 2166 Now we edit foo. IPython automatically loads the editor with the
2163 2167 (temporary) file where foo() was previously defined:
2164 2168
2165 2169 In [3]: ed foo
2166 2170 Editing... done. Executing edited code...
2167 2171
2168 2172 And if we call foo() again we get the modified version:
2169 2173
2170 2174 In [4]: foo()
2171 2175 foo() has now been changed!
2172 2176
2173 2177 Here is an example of how to edit a code snippet successive
2174 2178 times. First we call the editor:
2175 2179
2176 2180 In [5]: ed
2177 2181 Editing... done. Executing edited code...
2178 2182 hello
2179 2183 Out[5]: "print 'hello'n"
2180 2184
2181 2185 Now we call it again with the previous output (stored in _):
2182 2186
2183 2187 In [6]: ed _
2184 2188 Editing... done. Executing edited code...
2185 2189 hello world
2186 2190 Out[6]: "print 'hello world'n"
2187 2191
2188 2192 Now we call it with the output #8 (stored in _8, also as Out[8]):
2189 2193
2190 2194 In [7]: ed _8
2191 2195 Editing... done. Executing edited code...
2192 2196 hello again
2193 2197 Out[7]: "print 'hello again'n"
2194 2198
2195 2199
2196 2200 Changing the default editor hook:
2197 2201
2198 2202 If you wish to write your own editor hook, you can put it in a
2199 2203 configuration file which you load at startup time. The default hook
2200 2204 is defined in the IPython.hooks module, and you can use that as a
2201 2205 starting example for further modifications. That file also has
2202 2206 general instructions on how to set a new hook for use once you've
2203 2207 defined it."""
2204 2208
2205 2209 # FIXME: This function has become a convoluted mess. It needs a
2206 2210 # ground-up rewrite with clean, simple logic.
2207 2211
2208 2212 def make_filename(arg):
2209 2213 "Make a filename from the given args"
2210 2214 try:
2211 2215 filename = get_py_filename(arg)
2212 2216 except IOError:
2213 2217 if args.endswith('.py'):
2214 2218 filename = arg
2215 2219 else:
2216 2220 filename = None
2217 2221 return filename
2218 2222
2219 2223 # custom exceptions
2220 2224 class DataIsObject(Exception): pass
2221 2225
2222 2226 opts,args = self.parse_options(parameter_s,'prxn:')
2223 2227 # Set a few locals from the options for convenience:
2224 2228 opts_p = opts.has_key('p')
2225 2229 opts_r = opts.has_key('r')
2226 2230
2227 2231 # Default line number value
2228 2232 lineno = opts.get('n',None)
2229 2233
2230 2234 if opts_p:
2231 2235 args = '_%s' % last_call[0]
2232 2236 if not self.shell.user_ns.has_key(args):
2233 2237 args = last_call[1]
2234 2238
2235 2239 # use last_call to remember the state of the previous call, but don't
2236 2240 # let it be clobbered by successive '-p' calls.
2237 2241 try:
2238 2242 last_call[0] = self.shell.outputcache.prompt_count
2239 2243 if not opts_p:
2240 2244 last_call[1] = parameter_s
2241 2245 except:
2242 2246 pass
2243 2247
2244 2248 # by default this is done with temp files, except when the given
2245 2249 # arg is a filename
2246 2250 use_temp = 1
2247 2251
2248 2252 if re.match(r'\d',args):
2249 2253 # Mode where user specifies ranges of lines, like in %macro.
2250 2254 # This means that you can't edit files whose names begin with
2251 2255 # numbers this way. Tough.
2252 2256 ranges = args.split()
2253 2257 data = ''.join(self.extract_input_slices(ranges,opts_r))
2254 2258 elif args.endswith('.py'):
2255 2259 filename = make_filename(args)
2256 2260 data = ''
2257 2261 use_temp = 0
2258 2262 elif args:
2259 2263 try:
2260 2264 # Load the parameter given as a variable. If not a string,
2261 2265 # process it as an object instead (below)
2262 2266
2263 2267 #print '*** args',args,'type',type(args) # dbg
2264 2268 data = eval(args,self.shell.user_ns)
2265 2269 if not type(data) in StringTypes:
2266 2270 raise DataIsObject
2267 2271
2268 2272 except (NameError,SyntaxError):
2269 2273 # given argument is not a variable, try as a filename
2270 2274 filename = make_filename(args)
2271 2275 if filename is None:
2272 2276 warn("Argument given (%s) can't be found as a variable "
2273 2277 "or as a filename." % args)
2274 2278 return
2275 2279
2276 2280 data = ''
2277 2281 use_temp = 0
2278 2282 except DataIsObject:
2279 2283
2280 2284 # macros have a special edit function
2281 2285 if isinstance(data,Macro):
2282 2286 self._edit_macro(args,data)
2283 2287 return
2284 2288
2285 2289 # For objects, try to edit the file where they are defined
2286 2290 try:
2287 2291 filename = inspect.getabsfile(data)
2288 2292 if 'fakemodule' in filename.lower() and inspect.isclass(data):
2289 2293 # class created by %edit? Try to find source
2290 2294 # by looking for method definitions instead, the
2291 2295 # __module__ in those classes is FakeModule.
2292 2296 attrs = [getattr(data, aname) for aname in dir(data)]
2293 2297 for attr in attrs:
2294 2298 if not inspect.ismethod(attr):
2295 2299 continue
2296 2300 filename = inspect.getabsfile(attr)
2297 2301 if filename and 'fakemodule' not in filename.lower():
2298 2302 # change the attribute to be the edit target instead
2299 2303 data = attr
2300 2304 break
2301 2305
2302 2306 datafile = 1
2303 2307 except TypeError:
2304 2308 filename = make_filename(args)
2305 2309 datafile = 1
2306 2310 warn('Could not find file where `%s` is defined.\n'
2307 2311 'Opening a file named `%s`' % (args,filename))
2308 2312 # Now, make sure we can actually read the source (if it was in
2309 2313 # a temp file it's gone by now).
2310 2314 if datafile:
2311 2315 try:
2312 2316 if lineno is None:
2313 2317 lineno = inspect.getsourcelines(data)[1]
2314 2318 except IOError:
2315 2319 filename = make_filename(args)
2316 2320 if filename is None:
2317 2321 warn('The file `%s` where `%s` was defined cannot '
2318 2322 'be read.' % (filename,data))
2319 2323 return
2320 2324 use_temp = 0
2321 2325 else:
2322 2326 data = ''
2323 2327
2324 2328 if use_temp:
2325 2329 filename = self.shell.mktempfile(data)
2326 2330 print 'IPython will make a temporary file named:',filename
2327 2331
2328 2332 # do actual editing here
2329 2333 print 'Editing...',
2330 2334 sys.stdout.flush()
2331 self.shell.hooks.editor(filename,lineno)
2335 try:
2336 self.shell.hooks.editor(filename,lineno)
2337 except IPython.ipapi.TryNext:
2338 warn('Could not open editor')
2339 return
2340
2341 # XXX TODO: should this be generalized for all string vars?
2342 # For now, this is special-cased to blocks created by cpaste
2343 if args.strip() == 'pasted_block':
2344 self.shell.user_ns['pasted_block'] = file_read(filename)
2345
2332 2346 if opts.has_key('x'): # -x prevents actual execution
2333 2347 print
2334 2348 else:
2335 2349 print 'done. Executing edited code...'
2336 2350 if opts_r:
2337 2351 self.shell.runlines(file_read(filename))
2338 2352 else:
2339 2353 self.shell.safe_execfile(filename,self.shell.user_ns,
2340 2354 self.shell.user_ns)
2355
2356
2341 2357 if use_temp:
2342 2358 try:
2343 2359 return open(filename).read()
2344 2360 except IOError,msg:
2345 2361 if msg.filename == filename:
2346 2362 warn('File not found. Did you forget to save?')
2347 2363 return
2348 2364 else:
2349 2365 self.shell.showtraceback()
2350 2366
2351 2367 def magic_xmode(self,parameter_s = ''):
2352 2368 """Switch modes for the exception handlers.
2353 2369
2354 2370 Valid modes: Plain, Context and Verbose.
2355 2371
2356 2372 If called without arguments, acts as a toggle."""
2357 2373
2358 2374 def xmode_switch_err(name):
2359 2375 warn('Error changing %s exception modes.\n%s' %
2360 2376 (name,sys.exc_info()[1]))
2361 2377
2362 2378 shell = self.shell
2363 2379 new_mode = parameter_s.strip().capitalize()
2364 2380 try:
2365 2381 shell.InteractiveTB.set_mode(mode=new_mode)
2366 2382 print 'Exception reporting mode:',shell.InteractiveTB.mode
2367 2383 except:
2368 2384 xmode_switch_err('user')
2369 2385
2370 2386 # threaded shells use a special handler in sys.excepthook
2371 2387 if shell.isthreaded:
2372 2388 try:
2373 2389 shell.sys_excepthook.set_mode(mode=new_mode)
2374 2390 except:
2375 2391 xmode_switch_err('threaded')
2376 2392
2377 2393 def magic_colors(self,parameter_s = ''):
2378 2394 """Switch color scheme for prompts, info system and exception handlers.
2379 2395
2380 2396 Currently implemented schemes: NoColor, Linux, LightBG.
2381 2397
2382 2398 Color scheme names are not case-sensitive."""
2383 2399
2384 2400 def color_switch_err(name):
2385 2401 warn('Error changing %s color schemes.\n%s' %
2386 2402 (name,sys.exc_info()[1]))
2387 2403
2388 2404
2389 2405 new_scheme = parameter_s.strip()
2390 2406 if not new_scheme:
2391 2407 raise UsageError(
2392 2408 "%colors: you must specify a color scheme. See '%colors?'")
2393 2409 return
2394 2410 # local shortcut
2395 2411 shell = self.shell
2396 2412
2397 2413 import IPython.rlineimpl as readline
2398 2414
2399 2415 if not readline.have_readline and sys.platform == "win32":
2400 2416 msg = """\
2401 2417 Proper color support under MS Windows requires the pyreadline library.
2402 2418 You can find it at:
2403 2419 http://ipython.scipy.org/moin/PyReadline/Intro
2404 2420 Gary's readline needs the ctypes module, from:
2405 2421 http://starship.python.net/crew/theller/ctypes
2406 2422 (Note that ctypes is already part of Python versions 2.5 and newer).
2407 2423
2408 2424 Defaulting color scheme to 'NoColor'"""
2409 2425 new_scheme = 'NoColor'
2410 2426 warn(msg)
2411 2427
2412 2428 # readline option is 0
2413 2429 if not shell.has_readline:
2414 2430 new_scheme = 'NoColor'
2415 2431
2416 2432 # Set prompt colors
2417 2433 try:
2418 2434 shell.outputcache.set_colors(new_scheme)
2419 2435 except:
2420 2436 color_switch_err('prompt')
2421 2437 else:
2422 2438 shell.rc.colors = \
2423 2439 shell.outputcache.color_table.active_scheme_name
2424 2440 # Set exception colors
2425 2441 try:
2426 2442 shell.InteractiveTB.set_colors(scheme = new_scheme)
2427 2443 shell.SyntaxTB.set_colors(scheme = new_scheme)
2428 2444 except:
2429 2445 color_switch_err('exception')
2430 2446
2431 2447 # threaded shells use a verbose traceback in sys.excepthook
2432 2448 if shell.isthreaded:
2433 2449 try:
2434 2450 shell.sys_excepthook.set_colors(scheme=new_scheme)
2435 2451 except:
2436 2452 color_switch_err('system exception handler')
2437 2453
2438 2454 # Set info (for 'object?') colors
2439 2455 if shell.rc.color_info:
2440 2456 try:
2441 2457 shell.inspector.set_active_scheme(new_scheme)
2442 2458 except:
2443 2459 color_switch_err('object inspector')
2444 2460 else:
2445 2461 shell.inspector.set_active_scheme('NoColor')
2446 2462
2447 2463 def magic_color_info(self,parameter_s = ''):
2448 2464 """Toggle color_info.
2449 2465
2450 2466 The color_info configuration parameter controls whether colors are
2451 2467 used for displaying object details (by things like %psource, %pfile or
2452 2468 the '?' system). This function toggles this value with each call.
2453 2469
2454 2470 Note that unless you have a fairly recent pager (less works better
2455 2471 than more) in your system, using colored object information displays
2456 2472 will not work properly. Test it and see."""
2457 2473
2458 2474 self.shell.rc.color_info = 1 - self.shell.rc.color_info
2459 2475 self.magic_colors(self.shell.rc.colors)
2460 2476 print 'Object introspection functions have now coloring:',
2461 2477 print ['OFF','ON'][self.shell.rc.color_info]
2462 2478
2463 2479 def magic_Pprint(self, parameter_s=''):
2464 2480 """Toggle pretty printing on/off."""
2465 2481
2466 2482 self.shell.rc.pprint = 1 - self.shell.rc.pprint
2467 2483 print 'Pretty printing has been turned', \
2468 2484 ['OFF','ON'][self.shell.rc.pprint]
2469 2485
2470 2486 def magic_exit(self, parameter_s=''):
2471 2487 """Exit IPython, confirming if configured to do so.
2472 2488
2473 2489 You can configure whether IPython asks for confirmation upon exit by
2474 2490 setting the confirm_exit flag in the ipythonrc file."""
2475 2491
2476 2492 self.shell.exit()
2477 2493
2478 2494 def magic_quit(self, parameter_s=''):
2479 2495 """Exit IPython, confirming if configured to do so (like %exit)"""
2480 2496
2481 2497 self.shell.exit()
2482 2498
2483 2499 def magic_Exit(self, parameter_s=''):
2484 2500 """Exit IPython without confirmation."""
2485 2501
2486 2502 self.shell.ask_exit()
2487 2503
2488 2504 #......................................................................
2489 2505 # Functions to implement unix shell-type things
2490 2506
2491 2507 @testdec.skip_doctest
2492 2508 def magic_alias(self, parameter_s = ''):
2493 2509 """Define an alias for a system command.
2494 2510
2495 2511 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
2496 2512
2497 2513 Then, typing 'alias_name params' will execute the system command 'cmd
2498 2514 params' (from your underlying operating system).
2499 2515
2500 2516 Aliases have lower precedence than magic functions and Python normal
2501 2517 variables, so if 'foo' is both a Python variable and an alias, the
2502 2518 alias can not be executed until 'del foo' removes the Python variable.
2503 2519
2504 2520 You can use the %l specifier in an alias definition to represent the
2505 2521 whole line when the alias is called. For example:
2506 2522
2507 2523 In [2]: alias all echo "Input in brackets: <%l>"
2508 2524 In [3]: all hello world
2509 2525 Input in brackets: <hello world>
2510 2526
2511 2527 You can also define aliases with parameters using %s specifiers (one
2512 2528 per parameter):
2513 2529
2514 2530 In [1]: alias parts echo first %s second %s
2515 2531 In [2]: %parts A B
2516 2532 first A second B
2517 2533 In [3]: %parts A
2518 2534 Incorrect number of arguments: 2 expected.
2519 2535 parts is an alias to: 'echo first %s second %s'
2520 2536
2521 2537 Note that %l and %s are mutually exclusive. You can only use one or
2522 2538 the other in your aliases.
2523 2539
2524 2540 Aliases expand Python variables just like system calls using ! or !!
2525 2541 do: all expressions prefixed with '$' get expanded. For details of
2526 2542 the semantic rules, see PEP-215:
2527 2543 http://www.python.org/peps/pep-0215.html. This is the library used by
2528 2544 IPython for variable expansion. If you want to access a true shell
2529 2545 variable, an extra $ is necessary to prevent its expansion by IPython:
2530 2546
2531 2547 In [6]: alias show echo
2532 2548 In [7]: PATH='A Python string'
2533 2549 In [8]: show $PATH
2534 2550 A Python string
2535 2551 In [9]: show $$PATH
2536 2552 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
2537 2553
2538 2554 You can use the alias facility to acess all of $PATH. See the %rehash
2539 2555 and %rehashx functions, which automatically create aliases for the
2540 2556 contents of your $PATH.
2541 2557
2542 2558 If called with no parameters, %alias prints the current alias table."""
2543 2559
2544 2560 par = parameter_s.strip()
2545 2561 if not par:
2546 2562 stored = self.db.get('stored_aliases', {} )
2547 2563 atab = self.shell.alias_table
2548 2564 aliases = atab.keys()
2549 2565 aliases.sort()
2550 2566 res = []
2551 2567 showlast = []
2552 2568 for alias in aliases:
2553 2569 special = False
2554 2570 try:
2555 2571 tgt = atab[alias][1]
2556 2572 except (TypeError, AttributeError):
2557 2573 # unsubscriptable? probably a callable
2558 2574 tgt = atab[alias]
2559 2575 special = True
2560 2576 # 'interesting' aliases
2561 2577 if (alias in stored or
2562 2578 special or
2563 2579 alias.lower() != os.path.splitext(tgt)[0].lower() or
2564 2580 ' ' in tgt):
2565 2581 showlast.append((alias, tgt))
2566 2582 else:
2567 2583 res.append((alias, tgt ))
2568 2584
2569 2585 # show most interesting aliases last
2570 2586 res.extend(showlast)
2571 2587 print "Total number of aliases:",len(aliases)
2572 2588 return res
2573 2589 try:
2574 2590 alias,cmd = par.split(None,1)
2575 2591 except:
2576 2592 print OInspect.getdoc(self.magic_alias)
2577 2593 else:
2578 2594 nargs = cmd.count('%s')
2579 2595 if nargs>0 and cmd.find('%l')>=0:
2580 2596 error('The %s and %l specifiers are mutually exclusive '
2581 2597 'in alias definitions.')
2582 2598 else: # all looks OK
2583 2599 self.shell.alias_table[alias] = (nargs,cmd)
2584 2600 self.shell.alias_table_validate(verbose=0)
2585 2601 # end magic_alias
2586 2602
2587 2603 def magic_unalias(self, parameter_s = ''):
2588 2604 """Remove an alias"""
2589 2605
2590 2606 aname = parameter_s.strip()
2591 2607 if aname in self.shell.alias_table:
2592 2608 del self.shell.alias_table[aname]
2593 2609 stored = self.db.get('stored_aliases', {} )
2594 2610 if aname in stored:
2595 2611 print "Removing %stored alias",aname
2596 2612 del stored[aname]
2597 2613 self.db['stored_aliases'] = stored
2598 2614
2599 2615
2600 2616 def magic_rehashx(self, parameter_s = ''):
2601 2617 """Update the alias table with all executable files in $PATH.
2602 2618
2603 2619 This version explicitly checks that every entry in $PATH is a file
2604 2620 with execute access (os.X_OK), so it is much slower than %rehash.
2605 2621
2606 2622 Under Windows, it checks executability as a match agains a
2607 2623 '|'-separated string of extensions, stored in the IPython config
2608 2624 variable win_exec_ext. This defaults to 'exe|com|bat'.
2609 2625
2610 2626 This function also resets the root module cache of module completer,
2611 2627 used on slow filesystems.
2612 2628 """
2613 2629
2614 2630
2615 2631 ip = self.api
2616 2632
2617 2633 # for the benefit of module completer in ipy_completers.py
2618 2634 del ip.db['rootmodules']
2619 2635
2620 2636 path = [os.path.abspath(os.path.expanduser(p)) for p in
2621 2637 os.environ.get('PATH','').split(os.pathsep)]
2622 2638 path = filter(os.path.isdir,path)
2623 2639
2624 2640 alias_table = self.shell.alias_table
2625 2641 syscmdlist = []
2626 2642 if os.name == 'posix':
2627 2643 isexec = lambda fname:os.path.isfile(fname) and \
2628 2644 os.access(fname,os.X_OK)
2629 2645 else:
2630 2646
2631 2647 try:
2632 2648 winext = os.environ['pathext'].replace(';','|').replace('.','')
2633 2649 except KeyError:
2634 2650 winext = 'exe|com|bat|py'
2635 2651 if 'py' not in winext:
2636 2652 winext += '|py'
2637 2653 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
2638 2654 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
2639 2655 savedir = os.getcwd()
2640 2656 try:
2641 2657 # write the whole loop for posix/Windows so we don't have an if in
2642 2658 # the innermost part
2643 2659 if os.name == 'posix':
2644 2660 for pdir in path:
2645 2661 os.chdir(pdir)
2646 2662 for ff in os.listdir(pdir):
2647 2663 if isexec(ff) and ff not in self.shell.no_alias:
2648 2664 # each entry in the alias table must be (N,name),
2649 2665 # where N is the number of positional arguments of the
2650 # alias.
2651 alias_table[ff] = (0,ff)
2666 # alias.
2667 # Dots will be removed from alias names, since ipython
2668 # assumes names with dots to be python code
2669 alias_table[ff.replace('.','')] = (0,ff)
2652 2670 syscmdlist.append(ff)
2653 2671 else:
2654 2672 for pdir in path:
2655 2673 os.chdir(pdir)
2656 2674 for ff in os.listdir(pdir):
2657 2675 base, ext = os.path.splitext(ff)
2658 2676 if isexec(ff) and base.lower() not in self.shell.no_alias:
2659 2677 if ext.lower() == '.exe':
2660 2678 ff = base
2661 alias_table[base.lower()] = (0,ff)
2679 alias_table[base.lower().replace('.','')] = (0,ff)
2662 2680 syscmdlist.append(ff)
2663 2681 # Make sure the alias table doesn't contain keywords or builtins
2664 2682 self.shell.alias_table_validate()
2665 2683 # Call again init_auto_alias() so we get 'rm -i' and other
2666 2684 # modified aliases since %rehashx will probably clobber them
2667 2685
2668 2686 # no, we don't want them. if %rehashx clobbers them, good,
2669 2687 # we'll probably get better versions
2670 2688 # self.shell.init_auto_alias()
2671 2689 db = ip.db
2672 2690 db['syscmdlist'] = syscmdlist
2673 2691 finally:
2674 2692 os.chdir(savedir)
2675 2693
2676 2694 def magic_pwd(self, parameter_s = ''):
2677 2695 """Return the current working directory path."""
2678 2696 return os.getcwd()
2679 2697
2680 2698 def magic_cd(self, parameter_s=''):
2681 2699 """Change the current working directory.
2682 2700
2683 2701 This command automatically maintains an internal list of directories
2684 2702 you visit during your IPython session, in the variable _dh. The
2685 2703 command %dhist shows this history nicely formatted. You can also
2686 2704 do 'cd -<tab>' to see directory history conveniently.
2687 2705
2688 2706 Usage:
2689 2707
2690 2708 cd 'dir': changes to directory 'dir'.
2691 2709
2692 2710 cd -: changes to the last visited directory.
2693 2711
2694 2712 cd -<n>: changes to the n-th directory in the directory history.
2695 2713
2696 2714 cd --foo: change to directory that matches 'foo' in history
2697 2715
2698 2716 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
2699 2717 (note: cd <bookmark_name> is enough if there is no
2700 2718 directory <bookmark_name>, but a bookmark with the name exists.)
2701 2719 'cd -b <tab>' allows you to tab-complete bookmark names.
2702 2720
2703 2721 Options:
2704 2722
2705 2723 -q: quiet. Do not print the working directory after the cd command is
2706 2724 executed. By default IPython's cd command does print this directory,
2707 2725 since the default prompts do not display path information.
2708 2726
2709 2727 Note that !cd doesn't work for this purpose because the shell where
2710 2728 !command runs is immediately discarded after executing 'command'."""
2711 2729
2712 2730 parameter_s = parameter_s.strip()
2713 2731 #bkms = self.shell.persist.get("bookmarks",{})
2714 2732
2715 2733 oldcwd = os.getcwd()
2716 2734 numcd = re.match(r'(-)(\d+)$',parameter_s)
2717 2735 # jump in directory history by number
2718 2736 if numcd:
2719 2737 nn = int(numcd.group(2))
2720 2738 try:
2721 2739 ps = self.shell.user_ns['_dh'][nn]
2722 2740 except IndexError:
2723 2741 print 'The requested directory does not exist in history.'
2724 2742 return
2725 2743 else:
2726 2744 opts = {}
2727 2745 elif parameter_s.startswith('--'):
2728 2746 ps = None
2729 2747 fallback = None
2730 2748 pat = parameter_s[2:]
2731 2749 dh = self.shell.user_ns['_dh']
2732 2750 # first search only by basename (last component)
2733 2751 for ent in reversed(dh):
2734 2752 if pat in os.path.basename(ent) and os.path.isdir(ent):
2735 2753 ps = ent
2736 2754 break
2737 2755
2738 2756 if fallback is None and pat in ent and os.path.isdir(ent):
2739 2757 fallback = ent
2740 2758
2741 2759 # if we have no last part match, pick the first full path match
2742 2760 if ps is None:
2743 2761 ps = fallback
2744 2762
2745 2763 if ps is None:
2746 2764 print "No matching entry in directory history"
2747 2765 return
2748 2766 else:
2749 2767 opts = {}
2750 2768
2751 2769
2752 2770 else:
2753 2771 #turn all non-space-escaping backslashes to slashes,
2754 2772 # for c:\windows\directory\names\
2755 2773 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
2756 2774 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
2757 2775 # jump to previous
2758 2776 if ps == '-':
2759 2777 try:
2760 2778 ps = self.shell.user_ns['_dh'][-2]
2761 2779 except IndexError:
2762 2780 raise UsageError('%cd -: No previous directory to change to.')
2763 2781 # jump to bookmark if needed
2764 2782 else:
2765 2783 if not os.path.isdir(ps) or opts.has_key('b'):
2766 2784 bkms = self.db.get('bookmarks', {})
2767 2785
2768 2786 if bkms.has_key(ps):
2769 2787 target = bkms[ps]
2770 2788 print '(bookmark:%s) -> %s' % (ps,target)
2771 2789 ps = target
2772 2790 else:
2773 2791 if opts.has_key('b'):
2774 2792 raise UsageError("Bookmark '%s' not found. "
2775 2793 "Use '%%bookmark -l' to see your bookmarks." % ps)
2776 2794
2777 2795 # at this point ps should point to the target dir
2778 2796 if ps:
2779 2797 try:
2780 2798 os.chdir(os.path.expanduser(ps))
2781 2799 if self.shell.rc.term_title:
2782 2800 #print 'set term title:',self.shell.rc.term_title # dbg
2783 2801 platutils.set_term_title('IPy ' + abbrev_cwd())
2784 2802 except OSError:
2785 2803 print sys.exc_info()[1]
2786 2804 else:
2787 2805 cwd = os.getcwd()
2788 2806 dhist = self.shell.user_ns['_dh']
2789 2807 if oldcwd != cwd:
2790 2808 dhist.append(cwd)
2791 2809 self.db['dhist'] = compress_dhist(dhist)[-100:]
2792 2810
2793 2811 else:
2794 2812 os.chdir(self.shell.home_dir)
2795 2813 if self.shell.rc.term_title:
2796 2814 platutils.set_term_title("IPy ~")
2797 2815 cwd = os.getcwd()
2798 2816 dhist = self.shell.user_ns['_dh']
2799 2817
2800 2818 if oldcwd != cwd:
2801 2819 dhist.append(cwd)
2802 2820 self.db['dhist'] = compress_dhist(dhist)[-100:]
2803 2821 if not 'q' in opts and self.shell.user_ns['_dh']:
2804 2822 print self.shell.user_ns['_dh'][-1]
2805 2823
2806 2824
2807 2825 def magic_env(self, parameter_s=''):
2808 2826 """List environment variables."""
2809 2827
2810 2828 return os.environ.data
2811 2829
2812 2830 def magic_pushd(self, parameter_s=''):
2813 2831 """Place the current dir on stack and change directory.
2814 2832
2815 2833 Usage:\\
2816 2834 %pushd ['dirname']
2817 2835 """
2818 2836
2819 2837 dir_s = self.shell.dir_stack
2820 2838 tgt = os.path.expanduser(parameter_s)
2821 2839 cwd = os.getcwd().replace(self.home_dir,'~')
2822 2840 if tgt:
2823 2841 self.magic_cd(parameter_s)
2824 2842 dir_s.insert(0,cwd)
2825 2843 return self.magic_dirs()
2826 2844
2827 2845 def magic_popd(self, parameter_s=''):
2828 2846 """Change to directory popped off the top of the stack.
2829 2847 """
2830 2848 if not self.shell.dir_stack:
2831 2849 raise UsageError("%popd on empty stack")
2832 2850 top = self.shell.dir_stack.pop(0)
2833 2851 self.magic_cd(top)
2834 2852 print "popd ->",top
2835 2853
2836 2854 def magic_dirs(self, parameter_s=''):
2837 2855 """Return the current directory stack."""
2838 2856
2839 2857 return self.shell.dir_stack
2840 2858
2841 2859 def magic_dhist(self, parameter_s=''):
2842 2860 """Print your history of visited directories.
2843 2861
2844 2862 %dhist -> print full history\\
2845 2863 %dhist n -> print last n entries only\\
2846 2864 %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\
2847 2865
2848 2866 This history is automatically maintained by the %cd command, and
2849 2867 always available as the global list variable _dh. You can use %cd -<n>
2850 2868 to go to directory number <n>.
2851 2869
2852 2870 Note that most of time, you should view directory history by entering
2853 2871 cd -<TAB>.
2854 2872
2855 2873 """
2856 2874
2857 2875 dh = self.shell.user_ns['_dh']
2858 2876 if parameter_s:
2859 2877 try:
2860 2878 args = map(int,parameter_s.split())
2861 2879 except:
2862 2880 self.arg_err(Magic.magic_dhist)
2863 2881 return
2864 2882 if len(args) == 1:
2865 2883 ini,fin = max(len(dh)-(args[0]),0),len(dh)
2866 2884 elif len(args) == 2:
2867 2885 ini,fin = args
2868 2886 else:
2869 2887 self.arg_err(Magic.magic_dhist)
2870 2888 return
2871 2889 else:
2872 2890 ini,fin = 0,len(dh)
2873 2891 nlprint(dh,
2874 2892 header = 'Directory history (kept in _dh)',
2875 2893 start=ini,stop=fin)
2876 2894
2877 2895 @testdec.skip_doctest
2878 2896 def magic_sc(self, parameter_s=''):
2879 2897 """Shell capture - execute a shell command and capture its output.
2880 2898
2881 2899 DEPRECATED. Suboptimal, retained for backwards compatibility.
2882 2900
2883 2901 You should use the form 'var = !command' instead. Example:
2884 2902
2885 2903 "%sc -l myfiles = ls ~" should now be written as
2886 2904
2887 2905 "myfiles = !ls ~"
2888 2906
2889 2907 myfiles.s, myfiles.l and myfiles.n still apply as documented
2890 2908 below.
2891 2909
2892 2910 --
2893 2911 %sc [options] varname=command
2894 2912
2895 2913 IPython will run the given command using commands.getoutput(), and
2896 2914 will then update the user's interactive namespace with a variable
2897 2915 called varname, containing the value of the call. Your command can
2898 2916 contain shell wildcards, pipes, etc.
2899 2917
2900 2918 The '=' sign in the syntax is mandatory, and the variable name you
2901 2919 supply must follow Python's standard conventions for valid names.
2902 2920
2903 2921 (A special format without variable name exists for internal use)
2904 2922
2905 2923 Options:
2906 2924
2907 2925 -l: list output. Split the output on newlines into a list before
2908 2926 assigning it to the given variable. By default the output is stored
2909 2927 as a single string.
2910 2928
2911 2929 -v: verbose. Print the contents of the variable.
2912 2930
2913 2931 In most cases you should not need to split as a list, because the
2914 2932 returned value is a special type of string which can automatically
2915 2933 provide its contents either as a list (split on newlines) or as a
2916 2934 space-separated string. These are convenient, respectively, either
2917 2935 for sequential processing or to be passed to a shell command.
2918 2936
2919 2937 For example:
2920 2938
2921 2939 # all-random
2922 2940
2923 2941 # Capture into variable a
2924 2942 In [1]: sc a=ls *py
2925 2943
2926 2944 # a is a string with embedded newlines
2927 2945 In [2]: a
2928 2946 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
2929 2947
2930 2948 # which can be seen as a list:
2931 2949 In [3]: a.l
2932 2950 Out[3]: ['setup.py', 'win32_manual_post_install.py']
2933 2951
2934 2952 # or as a whitespace-separated string:
2935 2953 In [4]: a.s
2936 2954 Out[4]: 'setup.py win32_manual_post_install.py'
2937 2955
2938 2956 # a.s is useful to pass as a single command line:
2939 2957 In [5]: !wc -l $a.s
2940 2958 146 setup.py
2941 2959 130 win32_manual_post_install.py
2942 2960 276 total
2943 2961
2944 2962 # while the list form is useful to loop over:
2945 2963 In [6]: for f in a.l:
2946 2964 ...: !wc -l $f
2947 2965 ...:
2948 2966 146 setup.py
2949 2967 130 win32_manual_post_install.py
2950 2968
2951 2969 Similiarly, the lists returned by the -l option are also special, in
2952 2970 the sense that you can equally invoke the .s attribute on them to
2953 2971 automatically get a whitespace-separated string from their contents:
2954 2972
2955 2973 In [7]: sc -l b=ls *py
2956 2974
2957 2975 In [8]: b
2958 2976 Out[8]: ['setup.py', 'win32_manual_post_install.py']
2959 2977
2960 2978 In [9]: b.s
2961 2979 Out[9]: 'setup.py win32_manual_post_install.py'
2962 2980
2963 2981 In summary, both the lists and strings used for ouptut capture have
2964 2982 the following special attributes:
2965 2983
2966 2984 .l (or .list) : value as list.
2967 2985 .n (or .nlstr): value as newline-separated string.
2968 2986 .s (or .spstr): value as space-separated string.
2969 2987 """
2970 2988
2971 2989 opts,args = self.parse_options(parameter_s,'lv')
2972 2990 # Try to get a variable name and command to run
2973 2991 try:
2974 2992 # the variable name must be obtained from the parse_options
2975 2993 # output, which uses shlex.split to strip options out.
2976 2994 var,_ = args.split('=',1)
2977 2995 var = var.strip()
2978 2996 # But the the command has to be extracted from the original input
2979 2997 # parameter_s, not on what parse_options returns, to avoid the
2980 2998 # quote stripping which shlex.split performs on it.
2981 2999 _,cmd = parameter_s.split('=',1)
2982 3000 except ValueError:
2983 3001 var,cmd = '',''
2984 3002 # If all looks ok, proceed
2985 3003 out,err = self.shell.getoutputerror(cmd)
2986 3004 if err:
2987 3005 print >> Term.cerr,err
2988 3006 if opts.has_key('l'):
2989 3007 out = SList(out.split('\n'))
2990 3008 else:
2991 3009 out = LSString(out)
2992 3010 if opts.has_key('v'):
2993 3011 print '%s ==\n%s' % (var,pformat(out))
2994 3012 if var:
2995 3013 self.shell.user_ns.update({var:out})
2996 3014 else:
2997 3015 return out
2998 3016
2999 3017 def magic_sx(self, parameter_s=''):
3000 3018 """Shell execute - run a shell command and capture its output.
3001 3019
3002 3020 %sx command
3003 3021
3004 3022 IPython will run the given command using commands.getoutput(), and
3005 3023 return the result formatted as a list (split on '\\n'). Since the
3006 3024 output is _returned_, it will be stored in ipython's regular output
3007 3025 cache Out[N] and in the '_N' automatic variables.
3008 3026
3009 3027 Notes:
3010 3028
3011 3029 1) If an input line begins with '!!', then %sx is automatically
3012 3030 invoked. That is, while:
3013 3031 !ls
3014 3032 causes ipython to simply issue system('ls'), typing
3015 3033 !!ls
3016 3034 is a shorthand equivalent to:
3017 3035 %sx ls
3018 3036
3019 3037 2) %sx differs from %sc in that %sx automatically splits into a list,
3020 3038 like '%sc -l'. The reason for this is to make it as easy as possible
3021 3039 to process line-oriented shell output via further python commands.
3022 3040 %sc is meant to provide much finer control, but requires more
3023 3041 typing.
3024 3042
3025 3043 3) Just like %sc -l, this is a list with special attributes:
3026 3044
3027 3045 .l (or .list) : value as list.
3028 3046 .n (or .nlstr): value as newline-separated string.
3029 3047 .s (or .spstr): value as whitespace-separated string.
3030 3048
3031 3049 This is very useful when trying to use such lists as arguments to
3032 3050 system commands."""
3033 3051
3034 3052 if parameter_s:
3035 3053 out,err = self.shell.getoutputerror(parameter_s)
3036 3054 if err:
3037 3055 print >> Term.cerr,err
3038 3056 return SList(out.split('\n'))
3039 3057
3040 3058 def magic_bg(self, parameter_s=''):
3041 3059 """Run a job in the background, in a separate thread.
3042 3060
3043 3061 For example,
3044 3062
3045 3063 %bg myfunc(x,y,z=1)
3046 3064
3047 3065 will execute 'myfunc(x,y,z=1)' in a background thread. As soon as the
3048 3066 execution starts, a message will be printed indicating the job
3049 3067 number. If your job number is 5, you can use
3050 3068
3051 3069 myvar = jobs.result(5) or myvar = jobs[5].result
3052 3070
3053 3071 to assign this result to variable 'myvar'.
3054 3072
3055 3073 IPython has a job manager, accessible via the 'jobs' object. You can
3056 3074 type jobs? to get more information about it, and use jobs.<TAB> to see
3057 3075 its attributes. All attributes not starting with an underscore are
3058 3076 meant for public use.
3059 3077
3060 3078 In particular, look at the jobs.new() method, which is used to create
3061 3079 new jobs. This magic %bg function is just a convenience wrapper
3062 3080 around jobs.new(), for expression-based jobs. If you want to create a
3063 3081 new job with an explicit function object and arguments, you must call
3064 3082 jobs.new() directly.
3065 3083
3066 3084 The jobs.new docstring also describes in detail several important
3067 3085 caveats associated with a thread-based model for background job
3068 3086 execution. Type jobs.new? for details.
3069 3087
3070 3088 You can check the status of all jobs with jobs.status().
3071 3089
3072 3090 The jobs variable is set by IPython into the Python builtin namespace.
3073 3091 If you ever declare a variable named 'jobs', you will shadow this
3074 3092 name. You can either delete your global jobs variable to regain
3075 3093 access to the job manager, or make a new name and assign it manually
3076 3094 to the manager (stored in IPython's namespace). For example, to
3077 3095 assign the job manager to the Jobs name, use:
3078 3096
3079 3097 Jobs = __builtins__.jobs"""
3080 3098
3081 3099 self.shell.jobs.new(parameter_s,self.shell.user_ns)
3082 3100
3083 3101 def magic_r(self, parameter_s=''):
3084 3102 """Repeat previous input.
3085 3103
3086 3104 Note: Consider using the more powerfull %rep instead!
3087 3105
3088 3106 If given an argument, repeats the previous command which starts with
3089 3107 the same string, otherwise it just repeats the previous input.
3090 3108
3091 3109 Shell escaped commands (with ! as first character) are not recognized
3092 3110 by this system, only pure python code and magic commands.
3093 3111 """
3094 3112
3095 3113 start = parameter_s.strip()
3096 3114 esc_magic = self.shell.ESC_MAGIC
3097 3115 # Identify magic commands even if automagic is on (which means
3098 3116 # the in-memory version is different from that typed by the user).
3099 3117 if self.shell.rc.automagic:
3100 3118 start_magic = esc_magic+start
3101 3119 else:
3102 3120 start_magic = start
3103 3121 # Look through the input history in reverse
3104 3122 for n in range(len(self.shell.input_hist)-2,0,-1):
3105 3123 input = self.shell.input_hist[n]
3106 3124 # skip plain 'r' lines so we don't recurse to infinity
3107 3125 if input != '_ip.magic("r")\n' and \
3108 3126 (input.startswith(start) or input.startswith(start_magic)):
3109 3127 #print 'match',`input` # dbg
3110 3128 print 'Executing:',input,
3111 3129 self.shell.runlines(input)
3112 3130 return
3113 3131 print 'No previous input matching `%s` found.' % start
3114 3132
3115 3133
3116 3134 def magic_bookmark(self, parameter_s=''):
3117 3135 """Manage IPython's bookmark system.
3118 3136
3119 3137 %bookmark <name> - set bookmark to current dir
3120 3138 %bookmark <name> <dir> - set bookmark to <dir>
3121 3139 %bookmark -l - list all bookmarks
3122 3140 %bookmark -d <name> - remove bookmark
3123 3141 %bookmark -r - remove all bookmarks
3124 3142
3125 3143 You can later on access a bookmarked folder with:
3126 3144 %cd -b <name>
3127 3145 or simply '%cd <name>' if there is no directory called <name> AND
3128 3146 there is such a bookmark defined.
3129 3147
3130 3148 Your bookmarks persist through IPython sessions, but they are
3131 3149 associated with each profile."""
3132 3150
3133 3151 opts,args = self.parse_options(parameter_s,'drl',mode='list')
3134 3152 if len(args) > 2:
3135 3153 raise UsageError("%bookmark: too many arguments")
3136 3154
3137 3155 bkms = self.db.get('bookmarks',{})
3138 3156
3139 3157 if opts.has_key('d'):
3140 3158 try:
3141 3159 todel = args[0]
3142 3160 except IndexError:
3143 3161 raise UsageError(
3144 3162 "%bookmark -d: must provide a bookmark to delete")
3145 3163 else:
3146 3164 try:
3147 3165 del bkms[todel]
3148 3166 except KeyError:
3149 3167 raise UsageError(
3150 3168 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
3151 3169
3152 3170 elif opts.has_key('r'):
3153 3171 bkms = {}
3154 3172 elif opts.has_key('l'):
3155 3173 bks = bkms.keys()
3156 3174 bks.sort()
3157 3175 if bks:
3158 3176 size = max(map(len,bks))
3159 3177 else:
3160 3178 size = 0
3161 3179 fmt = '%-'+str(size)+'s -> %s'
3162 3180 print 'Current bookmarks:'
3163 3181 for bk in bks:
3164 3182 print fmt % (bk,bkms[bk])
3165 3183 else:
3166 3184 if not args:
3167 3185 raise UsageError("%bookmark: You must specify the bookmark name")
3168 3186 elif len(args)==1:
3169 3187 bkms[args[0]] = os.getcwd()
3170 3188 elif len(args)==2:
3171 3189 bkms[args[0]] = args[1]
3172 3190 self.db['bookmarks'] = bkms
3173 3191
3174 3192 def magic_pycat(self, parameter_s=''):
3175 3193 """Show a syntax-highlighted file through a pager.
3176 3194
3177 3195 This magic is similar to the cat utility, but it will assume the file
3178 3196 to be Python source and will show it with syntax highlighting. """
3179 3197
3180 3198 try:
3181 3199 filename = get_py_filename(parameter_s)
3182 3200 cont = file_read(filename)
3183 3201 except IOError:
3184 3202 try:
3185 3203 cont = eval(parameter_s,self.user_ns)
3186 3204 except NameError:
3187 3205 cont = None
3188 3206 if cont is None:
3189 3207 print "Error: no such file or variable"
3190 3208 return
3191 3209
3192 3210 page(self.shell.pycolorize(cont),
3193 3211 screen_lines=self.shell.rc.screen_length)
3194 3212
3195 3213 def magic_cpaste(self, parameter_s=''):
3196 3214 """Allows you to paste & execute a pre-formatted code block from clipboard.
3197 3215
3198 3216 You must terminate the block with '--' (two minus-signs) alone on the
3199 3217 line. You can also provide your own sentinel with '%paste -s %%' ('%%'
3200 3218 is the new sentinel for this operation)
3201 3219
3202 3220 The block is dedented prior to execution to enable execution of method
3203 3221 definitions. '>' and '+' characters at the beginning of a line are
3204 3222 ignored, to allow pasting directly from e-mails, diff files and
3205 3223 doctests (the '...' continuation prompt is also stripped). The
3206 3224 executed block is also assigned to variable named 'pasted_block' for
3207 3225 later editing with '%edit pasted_block'.
3208 3226
3209 3227 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
3210 3228 This assigns the pasted block to variable 'foo' as string, without
3211 3229 dedenting or executing it (preceding >>> and + is still stripped)
3212 3230
3231 '%cpaste -r' re-executes the block previously entered by cpaste.
3232
3213 3233 Do not be alarmed by garbled output on Windows (it's a readline bug).
3214 3234 Just press enter and type -- (and press enter again) and the block
3215 3235 will be what was just pasted.
3216 3236
3217 3237 IPython statements (magics, shell escapes) are not supported (yet).
3218 3238 """
3219 opts,args = self.parse_options(parameter_s,'s:',mode='string')
3239 opts,args = self.parse_options(parameter_s,'rs:',mode='string')
3220 3240 par = args.strip()
3241 if opts.has_key('r'):
3242 b = self.user_ns.get('pasted_block', None)
3243 if b is None:
3244 raise UsageError('No previous pasted block available')
3245 print "Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))
3246 exec b in self.user_ns
3247 return
3248
3221 3249 sentinel = opts.get('s','--')
3222 3250
3223 3251 # Regular expressions that declare text we strip from the input:
3224 3252 strip_re = [r'^\s*In \[\d+\]:', # IPython input prompt
3225 3253 r'^\s*(\s?>)+', # Python input prompt
3226 3254 r'^\s*\.{3,}', # Continuation prompts
3227 3255 r'^\++',
3228 3256 ]
3229 3257
3230 3258 strip_from_start = map(re.compile,strip_re)
3231 3259
3232 3260 from IPython import iplib
3233 3261 lines = []
3234 3262 print "Pasting code; enter '%s' alone on the line to stop." % sentinel
3235 3263 while 1:
3236 3264 l = iplib.raw_input_original(':')
3237 3265 if l ==sentinel:
3238 3266 break
3239 3267
3240 3268 for pat in strip_from_start:
3241 3269 l = pat.sub('',l)
3242 3270 lines.append(l)
3243 3271
3244 3272 block = "\n".join(lines) + '\n'
3245 3273 #print "block:\n",block
3246 3274 if not par:
3247 3275 b = textwrap.dedent(block)
3248 exec b in self.user_ns
3249 3276 self.user_ns['pasted_block'] = b
3277 exec b in self.user_ns
3250 3278 else:
3251 3279 self.user_ns[par] = SList(block.splitlines())
3252 3280 print "Block assigned to '%s'" % par
3253 3281
3254 3282 def magic_quickref(self,arg):
3255 3283 """ Show a quick reference sheet """
3256 3284 import IPython.usage
3257 3285 qr = IPython.usage.quick_reference + self.magic_magic('-brief')
3258 3286
3259 3287 page(qr)
3260 3288
3261 3289 def magic_upgrade(self,arg):
3262 3290 """ Upgrade your IPython installation
3263 3291
3264 3292 This will copy the config files that don't yet exist in your
3265 3293 ipython dir from the system config dir. Use this after upgrading
3266 3294 IPython if you don't wish to delete your .ipython dir.
3267 3295
3268 3296 Call with -nolegacy to get rid of ipythonrc* files (recommended for
3269 3297 new users)
3270 3298
3271 3299 """
3272 3300 ip = self.getapi()
3273 3301 ipinstallation = path(IPython.__file__).dirname()
3274 3302 upgrade_script = '%s "%s"' % (sys.executable,ipinstallation / 'upgrade_dir.py')
3275 3303 src_config = ipinstallation / 'UserConfig'
3276 3304 userdir = path(ip.options.ipythondir)
3277 3305 cmd = '%s "%s" "%s"' % (upgrade_script, src_config, userdir)
3278 3306 print ">",cmd
3279 3307 shell(cmd)
3280 3308 if arg == '-nolegacy':
3281 3309 legacy = userdir.files('ipythonrc*')
3282 3310 print "Nuking legacy files:",legacy
3283 3311
3284 3312 [p.remove() for p in legacy]
3285 3313 suffix = (sys.platform == 'win32' and '.ini' or '')
3286 3314 (userdir / ('ipythonrc' + suffix)).write_text('# Empty, see ipy_user_conf.py\n')
3287 3315
3288 3316
3289 3317 def magic_doctest_mode(self,parameter_s=''):
3290 3318 """Toggle doctest mode on and off.
3291 3319
3292 3320 This mode allows you to toggle the prompt behavior between normal
3293 3321 IPython prompts and ones that are as similar to the default IPython
3294 3322 interpreter as possible.
3295 3323
3296 3324 It also supports the pasting of code snippets that have leading '>>>'
3297 3325 and '...' prompts in them. This means that you can paste doctests from
3298 3326 files or docstrings (even if they have leading whitespace), and the
3299 3327 code will execute correctly. You can then use '%history -tn' to see
3300 3328 the translated history without line numbers; this will give you the
3301 3329 input after removal of all the leading prompts and whitespace, which
3302 3330 can be pasted back into an editor.
3303 3331
3304 3332 With these features, you can switch into this mode easily whenever you
3305 3333 need to do testing and changes to doctests, without having to leave
3306 3334 your existing IPython session.
3307 3335 """
3308 3336
3309 3337 # XXX - Fix this to have cleaner activate/deactivate calls.
3310 3338 from IPython.Extensions import InterpreterPasteInput as ipaste
3311 3339 from IPython.ipstruct import Struct
3312 3340
3313 3341 # Shorthands
3314 3342 shell = self.shell
3315 3343 oc = shell.outputcache
3316 3344 rc = shell.rc
3317 3345 meta = shell.meta
3318 3346 # dstore is a data store kept in the instance metadata bag to track any
3319 3347 # changes we make, so we can undo them later.
3320 3348 dstore = meta.setdefault('doctest_mode',Struct())
3321 3349 save_dstore = dstore.setdefault
3322 3350
3323 3351 # save a few values we'll need to recover later
3324 3352 mode = save_dstore('mode',False)
3325 3353 save_dstore('rc_pprint',rc.pprint)
3326 3354 save_dstore('xmode',shell.InteractiveTB.mode)
3327 3355 save_dstore('rc_separate_out',rc.separate_out)
3328 3356 save_dstore('rc_separate_out2',rc.separate_out2)
3329 3357 save_dstore('rc_prompts_pad_left',rc.prompts_pad_left)
3330 3358 save_dstore('rc_separate_in',rc.separate_in)
3331 3359
3332 3360 if mode == False:
3333 3361 # turn on
3334 3362 ipaste.activate_prefilter()
3335 3363
3336 3364 oc.prompt1.p_template = '>>> '
3337 3365 oc.prompt2.p_template = '... '
3338 3366 oc.prompt_out.p_template = ''
3339 3367
3340 3368 # Prompt separators like plain python
3341 3369 oc.input_sep = oc.prompt1.sep = ''
3342 3370 oc.output_sep = ''
3343 3371 oc.output_sep2 = ''
3344 3372
3345 3373 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3346 3374 oc.prompt_out.pad_left = False
3347 3375
3348 3376 rc.pprint = False
3349 3377
3350 3378 shell.magic_xmode('Plain')
3351 3379
3352 3380 else:
3353 3381 # turn off
3354 3382 ipaste.deactivate_prefilter()
3355 3383
3356 3384 oc.prompt1.p_template = rc.prompt_in1
3357 3385 oc.prompt2.p_template = rc.prompt_in2
3358 3386 oc.prompt_out.p_template = rc.prompt_out
3359 3387
3360 3388 oc.input_sep = oc.prompt1.sep = dstore.rc_separate_in
3361 3389
3362 3390 oc.output_sep = dstore.rc_separate_out
3363 3391 oc.output_sep2 = dstore.rc_separate_out2
3364 3392
3365 3393 oc.prompt1.pad_left = oc.prompt2.pad_left = \
3366 3394 oc.prompt_out.pad_left = dstore.rc_prompts_pad_left
3367 3395
3368 3396 rc.pprint = dstore.rc_pprint
3369 3397
3370 3398 shell.magic_xmode(dstore.xmode)
3371 3399
3372 3400 # Store new mode and inform
3373 3401 dstore.mode = bool(1-int(mode))
3374 3402 print 'Doctest mode is:',
3375 3403 print ['OFF','ON'][dstore.mode]
3376 3404
3377 3405 # end Magic
1 NO CONTENT: modified file chmod 100755 => 100644
@@ -1,99 +1,121 b''
1 1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project.
3
4 $Id: Release.py 3002 2008-02-01 07:17:00Z fperez $"""
2 """Release data for the IPython project."""
5 3
6 4 #*****************************************************************************
7 5 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
8 6 #
9 7 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
10 8 # <n8gray@caltech.edu>
11 9 #
12 10 # Distributed under the terms of the BSD License. The full license is in
13 11 # the file COPYING, distributed as part of this software.
14 12 #*****************************************************************************
15 13
16 14 # Name of the package for release purposes. This is the name which labels
17 15 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
18 16 name = 'ipython'
19 17
20 18 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
21 19 # the new substring. We have to avoid using either dashes or underscores,
22 20 # because bdist_rpm does not accept dashes (an RPM) convention, and
23 21 # bdist_deb does not accept underscores (a Debian convention).
24 22
25 23 development = False # change this to False to do a release
26 version_base = '0.9.beta'
24 version_base = '0.9.1'
27 25 branch = 'ipython'
28 revision = '1099'
26 revision = '1143'
29 27
30 28 if development:
31 29 if branch == 'ipython':
32 30 version = '%s.bzr.r%s' % (version_base, revision)
33 31 else:
34 32 version = '%s.bzr.r%s.%s' % (version_base, revision, branch)
35 33 else:
36 34 version = version_base
37 35
38 36
39 description = "Tools for interactive development in Python."
37 description = "An interactive computing environment for Python"
40 38
41 39 long_description = \
42 40 """
43 IPython provides a replacement for the interactive Python interpreter with
44 extra functionality.
41 The goal of IPython is to create a comprehensive environment for
42 interactive and exploratory computing. To support this goal, IPython
43 has two main components:
44
45 * An enhanced interactive Python shell.
46
47 * An architecture for interactive parallel computing.
48
49 The enhanced interactive Python shell has the following main features:
50
51 * Comprehensive object introspection.
52
53 * Input history, persistent across sessions.
45 54
46 Main features:
55 * Caching of output results during a session with automatically generated
56 references.
47 57
48 * Comprehensive object introspection.
58 * Readline based name completion.
49 59
50 * Input history, persistent across sessions.
60 * Extensible system of 'magic' commands for controlling the environment and
61 performing many tasks related either to IPython or the operating system.
51 62
52 * Caching of output results during a session with automatically generated
53 references.
63 * Configuration system with easy switching between different setups (simpler
64 than changing $PYTHONSTARTUP environment variables every time).
54 65
55 * Readline based name completion.
66 * Session logging and reloading.
56 67
57 * Extensible system of 'magic' commands for controlling the environment and
58 performing many tasks related either to IPython or the operating system.
68 * Extensible syntax processing for special purpose situations.
59 69
60 * Configuration system with easy switching between different setups (simpler
61 than changing $PYTHONSTARTUP environment variables every time).
70 * Access to the system shell with user-extensible alias system.
62 71
63 * Session logging and reloading.
72 * Easily embeddable in other Python programs and wxPython GUIs.
64 73
65 * Extensible syntax processing for special purpose situations.
74 * Integrated access to the pdb debugger and the Python profiler.
66 75
67 * Access to the system shell with user-extensible alias system.
76 The parallel computing architecture has the following main features:
68 77
69 * Easily embeddable in other Python programs.
78 * Quickly parallelize Python code from an interactive Python/IPython session.
70 79
71 * Integrated access to the pdb debugger and the Python profiler.
80 * A flexible and dynamic process model that be deployed on anything from
81 multicore workstations to supercomputers.
72 82
73 The latest development version is always available at the IPython subversion
74 repository_.
83 * An architecture that supports many different styles of parallelism, from
84 message passing to task farming.
75 85
76 .. _repository: http://ipython.scipy.org/svn/ipython/ipython/trunk#egg=ipython-dev
77 """
86 * Both blocking and fully asynchronous interfaces.
87
88 * High level APIs that enable many things to be parallelized in a few lines
89 of code.
90
91 * Share live parallel jobs with other users securely.
92
93 * Dynamically load balanced task farming system.
94
95 * Robust error handling in parallel code.
96
97 The latest development version is always available from IPython's `Launchpad
98 site <http://launchpad.net/ipython>`_.
99 """
78 100
79 101 license = 'BSD'
80 102
81 103 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
82 104 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
83 105 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
84 106 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
85 107 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
86 108 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com')
87 109 }
88 110
89 111 author = 'The IPython Development Team'
90 112
91 113 author_email = 'ipython-dev@scipy.org'
92 114
93 115 url = 'http://ipython.scipy.org'
94 116
95 117 download_url = 'http://ipython.scipy.org/dist'
96 118
97 119 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
98 120
99 121 keywords = ['Interactive','Interpreter','Shell','Parallel','Distributed']
@@ -1,1236 +1,1249 b''
1 1 # -*- coding: utf-8 -*-
2 2 """IPython Shell classes.
3 3
4 4 All the matplotlib support code was co-developed with John Hunter,
5 5 matplotlib's author.
6 6
7 7 $Id: Shell.py 3024 2008-02-07 15:34:42Z darren.dale $"""
8 8
9 9 #*****************************************************************************
10 10 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
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 from IPython import Release
17 17 __author__ = '%s <%s>' % Release.authors['Fernando']
18 18 __license__ = Release.license
19 19
20 20 # Code begins
21 21 # Stdlib imports
22 22 import __builtin__
23 23 import __main__
24 24 import Queue
25 25 import inspect
26 26 import os
27 27 import sys
28 28 import thread
29 29 import threading
30 30 import time
31 31
32 32 from signal import signal, SIGINT
33 33
34 34 try:
35 35 import ctypes
36 36 HAS_CTYPES = True
37 37 except ImportError:
38 38 HAS_CTYPES = False
39 39
40 40 # IPython imports
41 41 import IPython
42 42 from IPython import ultraTB, ipapi
43 from IPython.Magic import Magic
43 44 from IPython.genutils import Term,warn,error,flag_calls, ask_yes_no
44 45 from IPython.iplib import InteractiveShell
45 46 from IPython.ipmaker import make_IPython
46 from IPython.Magic import Magic
47 47 from IPython.ipstruct import Struct
48 from IPython.testing import decorators as testdec
48 49
49 50 # Globals
50 51 # global flag to pass around information about Ctrl-C without exceptions
51 52 KBINT = False
52 53
53 54 # global flag to turn on/off Tk support.
54 55 USE_TK = False
55 56
56 57 # ID for the main thread, used for cross-thread exceptions
57 58 MAIN_THREAD_ID = thread.get_ident()
58 59
59 60 # Tag when runcode() is active, for exception handling
60 61 CODE_RUN = None
61 62
62 63 # Default timeout for waiting for multithreaded shells (in seconds)
63 64 GUI_TIMEOUT = 10
64 65
65 66 #-----------------------------------------------------------------------------
66 67 # This class is trivial now, but I want to have it in to publish a clean
67 68 # interface. Later when the internals are reorganized, code that uses this
68 69 # shouldn't have to change.
69 70
70 71 class IPShell:
71 72 """Create an IPython instance."""
72 73
73 74 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
74 75 debug=1,shell_class=InteractiveShell):
75 76 self.IP = make_IPython(argv,user_ns=user_ns,
76 77 user_global_ns=user_global_ns,
77 78 debug=debug,shell_class=shell_class)
78 79
79 80 def mainloop(self,sys_exit=0,banner=None):
80 81 self.IP.mainloop(banner)
81 82 if sys_exit:
82 83 sys.exit()
83 84
84 85 #-----------------------------------------------------------------------------
85 86 def kill_embedded(self,parameter_s=''):
86 87 """%kill_embedded : deactivate for good the current embedded IPython.
87 88
88 89 This function (after asking for confirmation) sets an internal flag so that
89 90 an embedded IPython will never activate again. This is useful to
90 91 permanently disable a shell that is being called inside a loop: once you've
91 92 figured out what you needed from it, you may then kill it and the program
92 93 will then continue to run without the interactive shell interfering again.
93 94 """
94 95
95 96 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
96 97 "(y/n)? [y/N] ",'n')
97 98 if kill:
98 99 self.shell.embedded_active = False
99 100 print "This embedded IPython will not reactivate anymore once you exit."
100 101
101 102 class IPShellEmbed:
102 103 """Allow embedding an IPython shell into a running program.
103 104
104 105 Instances of this class are callable, with the __call__ method being an
105 106 alias to the embed() method of an InteractiveShell instance.
106 107
107 108 Usage (see also the example-embed.py file for a running example):
108 109
109 110 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
110 111
111 112 - argv: list containing valid command-line options for IPython, as they
112 113 would appear in sys.argv[1:].
113 114
114 115 For example, the following command-line options:
115 116
116 117 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
117 118
118 119 would be passed in the argv list as:
119 120
120 121 ['-prompt_in1','Input <\\#>','-colors','LightBG']
121 122
122 123 - banner: string which gets printed every time the interpreter starts.
123 124
124 125 - exit_msg: string which gets printed every time the interpreter exits.
125 126
126 127 - rc_override: a dict or Struct of configuration options such as those
127 128 used by IPython. These options are read from your ~/.ipython/ipythonrc
128 129 file when the Shell object is created. Passing an explicit rc_override
129 130 dict with any options you want allows you to override those values at
130 131 creation time without having to modify the file. This way you can create
131 132 embeddable instances configured in any way you want without editing any
132 133 global files (thus keeping your interactive IPython configuration
133 134 unchanged).
134 135
135 136 Then the ipshell instance can be called anywhere inside your code:
136 137
137 138 ipshell(header='') -> Opens up an IPython shell.
138 139
139 140 - header: string printed by the IPython shell upon startup. This can let
140 141 you know where in your code you are when dropping into the shell. Note
141 142 that 'banner' gets prepended to all calls, so header is used for
142 143 location-specific information.
143 144
144 145 For more details, see the __call__ method below.
145 146
146 147 When the IPython shell is exited with Ctrl-D, normal program execution
147 148 resumes.
148 149
149 150 This functionality was inspired by a posting on comp.lang.python by cmkl
150 151 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
151 152 by the IDL stop/continue commands."""
152 153
153 154 def __init__(self,argv=None,banner='',exit_msg=None,rc_override=None,
154 155 user_ns=None):
155 156 """Note that argv here is a string, NOT a list."""
156 157 self.set_banner(banner)
157 158 self.set_exit_msg(exit_msg)
158 159 self.set_dummy_mode(0)
159 160
160 161 # sys.displayhook is a global, we need to save the user's original
161 162 # Don't rely on __displayhook__, as the user may have changed that.
162 163 self.sys_displayhook_ori = sys.displayhook
163 164
164 165 # save readline completer status
165 166 try:
166 167 #print 'Save completer',sys.ipcompleter # dbg
167 168 self.sys_ipcompleter_ori = sys.ipcompleter
168 169 except:
169 170 pass # not nested with IPython
170 171
171 172 self.IP = make_IPython(argv,rc_override=rc_override,
172 173 embedded=True,
173 174 user_ns=user_ns)
174 175
175 176 ip = ipapi.IPApi(self.IP)
176 177 ip.expose_magic("kill_embedded",kill_embedded)
177 178
178 179 # copy our own displayhook also
179 180 self.sys_displayhook_embed = sys.displayhook
180 181 # and leave the system's display hook clean
181 182 sys.displayhook = self.sys_displayhook_ori
182 183 # don't use the ipython crash handler so that user exceptions aren't
183 184 # trapped
184 185 sys.excepthook = ultraTB.FormattedTB(color_scheme = self.IP.rc.colors,
185 186 mode = self.IP.rc.xmode,
186 187 call_pdb = self.IP.rc.pdb)
187 188 self.restore_system_completer()
188 189
189 190 def restore_system_completer(self):
190 191 """Restores the readline completer which was in place.
191 192
192 193 This allows embedded IPython within IPython not to disrupt the
193 194 parent's completion.
194 195 """
195 196
196 197 try:
197 198 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
198 199 sys.ipcompleter = self.sys_ipcompleter_ori
199 200 except:
200 201 pass
201 202
202 203 def __call__(self,header='',local_ns=None,global_ns=None,dummy=None):
203 204 """Activate the interactive interpreter.
204 205
205 206 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
206 207 the interpreter shell with the given local and global namespaces, and
207 208 optionally print a header string at startup.
208 209
209 210 The shell can be globally activated/deactivated using the
210 211 set/get_dummy_mode methods. This allows you to turn off a shell used
211 212 for debugging globally.
212 213
213 214 However, *each* time you call the shell you can override the current
214 215 state of dummy_mode with the optional keyword parameter 'dummy'. For
215 216 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
216 217 can still have a specific call work by making it as IPShell(dummy=0).
217 218
218 219 The optional keyword parameter dummy controls whether the call
219 220 actually does anything. """
220 221
221 222 # If the user has turned it off, go away
222 223 if not self.IP.embedded_active:
223 224 return
224 225
225 226 # Normal exits from interactive mode set this flag, so the shell can't
226 227 # re-enter (it checks this variable at the start of interactive mode).
227 228 self.IP.exit_now = False
228 229
229 230 # Allow the dummy parameter to override the global __dummy_mode
230 231 if dummy or (dummy != 0 and self.__dummy_mode):
231 232 return
232 233
233 234 # Set global subsystems (display,completions) to our values
234 235 sys.displayhook = self.sys_displayhook_embed
235 236 if self.IP.has_readline:
236 237 self.IP.set_completer()
237 238
238 239 if self.banner and header:
239 240 format = '%s\n%s\n'
240 241 else:
241 242 format = '%s%s\n'
242 243 banner = format % (self.banner,header)
243 244
244 245 # Call the embedding code with a stack depth of 1 so it can skip over
245 246 # our call and get the original caller's namespaces.
246 247 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
247 248
248 249 if self.exit_msg:
249 250 print self.exit_msg
250 251
251 252 # Restore global systems (display, completion)
252 253 sys.displayhook = self.sys_displayhook_ori
253 254 self.restore_system_completer()
254 255
255 256 def set_dummy_mode(self,dummy):
256 257 """Sets the embeddable shell's dummy mode parameter.
257 258
258 259 set_dummy_mode(dummy): dummy = 0 or 1.
259 260
260 261 This parameter is persistent and makes calls to the embeddable shell
261 262 silently return without performing any action. This allows you to
262 263 globally activate or deactivate a shell you're using with a single call.
263 264
264 265 If you need to manually"""
265 266
266 267 if dummy not in [0,1,False,True]:
267 268 raise ValueError,'dummy parameter must be boolean'
268 269 self.__dummy_mode = dummy
269 270
270 271 def get_dummy_mode(self):
271 272 """Return the current value of the dummy mode parameter.
272 273 """
273 274 return self.__dummy_mode
274 275
275 276 def set_banner(self,banner):
276 277 """Sets the global banner.
277 278
278 279 This banner gets prepended to every header printed when the shell
279 280 instance is called."""
280 281
281 282 self.banner = banner
282 283
283 284 def set_exit_msg(self,exit_msg):
284 285 """Sets the global exit_msg.
285 286
286 287 This exit message gets printed upon exiting every time the embedded
287 288 shell is called. It is None by default. """
288 289
289 290 self.exit_msg = exit_msg
290 291
291 292 #-----------------------------------------------------------------------------
292 293 if HAS_CTYPES:
293 294 # Add async exception support. Trick taken from:
294 295 # http://sebulba.wikispaces.com/recipe+thread2
295 296 def _async_raise(tid, exctype):
296 297 """raises the exception, performs cleanup if needed"""
297 298 if not inspect.isclass(exctype):
298 299 raise TypeError("Only types can be raised (not instances)")
299 300 res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
300 301 ctypes.py_object(exctype))
301 302 if res == 0:
302 303 raise ValueError("invalid thread id")
303 304 elif res != 1:
304 305 # """if it returns a number greater than one, you're in trouble,
305 306 # and you should call it again with exc=NULL to revert the effect"""
306 307 ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
307 308 raise SystemError("PyThreadState_SetAsyncExc failed")
308 309
309 310 def sigint_handler (signum,stack_frame):
310 311 """Sigint handler for threaded apps.
311 312
312 313 This is a horrible hack to pass information about SIGINT _without_
313 314 using exceptions, since I haven't been able to properly manage
314 315 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
315 316 done (or at least that's my understanding from a c.l.py thread where
316 317 this was discussed)."""
317 318
318 319 global KBINT
319 320
320 321 if CODE_RUN:
321 322 _async_raise(MAIN_THREAD_ID,KeyboardInterrupt)
322 323 else:
323 324 KBINT = True
324 325 print '\nKeyboardInterrupt - Press <Enter> to continue.',
325 326 Term.cout.flush()
326 327
327 328 else:
328 329 def sigint_handler (signum,stack_frame):
329 330 """Sigint handler for threaded apps.
330 331
331 332 This is a horrible hack to pass information about SIGINT _without_
332 333 using exceptions, since I haven't been able to properly manage
333 334 cross-thread exceptions in GTK/WX. In fact, I don't think it can be
334 335 done (or at least that's my understanding from a c.l.py thread where
335 336 this was discussed)."""
336 337
337 338 global KBINT
338 339
339 340 print '\nKeyboardInterrupt - Press <Enter> to continue.',
340 341 Term.cout.flush()
341 342 # Set global flag so that runsource can know that Ctrl-C was hit
342 343 KBINT = True
343 344
344 345
345 346 class MTInteractiveShell(InteractiveShell):
346 347 """Simple multi-threaded shell."""
347 348
348 349 # Threading strategy taken from:
349 350 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
350 351 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
351 352 # from the pygtk mailing list, to avoid lockups with system calls.
352 353
353 354 # class attribute to indicate whether the class supports threads or not.
354 355 # Subclasses with thread support should override this as needed.
355 356 isthreaded = True
356 357
357 358 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
358 359 user_ns=None,user_global_ns=None,banner2='',
359 360 gui_timeout=GUI_TIMEOUT,**kw):
360 361 """Similar to the normal InteractiveShell, but with threading control"""
361 362
362 363 InteractiveShell.__init__(self,name,usage,rc,user_ns,
363 364 user_global_ns,banner2)
364 365
365 366 # Timeout we wait for GUI thread
366 367 self.gui_timeout = gui_timeout
367 368
368 369 # A queue to hold the code to be executed.
369 370 self.code_queue = Queue.Queue()
370 371
371 372 # Stuff to do at closing time
372 373 self._kill = None
373 374 on_kill = kw.get('on_kill', [])
374 375 # Check that all things to kill are callable:
375 376 for t in on_kill:
376 377 if not callable(t):
377 378 raise TypeError,'on_kill must be a list of callables'
378 379 self.on_kill = on_kill
379 380 # thread identity of the "worker thread" (that may execute code directly)
380 381 self.worker_ident = None
381 382
382 383 def runsource(self, source, filename="<input>", symbol="single"):
383 384 """Compile and run some source in the interpreter.
384 385
385 386 Modified version of code.py's runsource(), to handle threading issues.
386 387 See the original for full docstring details."""
387
388
388 389 global KBINT
389 390
390 391 # If Ctrl-C was typed, we reset the flag and return right away
391 392 if KBINT:
392 393 KBINT = False
393 394 return False
394 395
395 396 if self._kill:
396 397 # can't queue new code if we are being killed
397 398 return True
398 399
399 400 try:
400 401 code = self.compile(source, filename, symbol)
401 402 except (OverflowError, SyntaxError, ValueError):
402 403 # Case 1
403 404 self.showsyntaxerror(filename)
404 405 return False
405 406
406 407 if code is None:
407 408 # Case 2
408 409 return True
409 410
410 411 # shortcut - if we are in worker thread, or the worker thread is not
411 412 # running, execute directly (to allow recursion and prevent deadlock if
412 413 # code is run early in IPython construction)
413 414
414 415 if (self.worker_ident is None
415 416 or self.worker_ident == thread.get_ident() ):
416 417 InteractiveShell.runcode(self,code)
417 return
418 return False
418 419
419 420 # Case 3
420 421 # Store code in queue, so the execution thread can handle it.
421 422
422 423 completed_ev, received_ev = threading.Event(), threading.Event()
423 424
424 425 self.code_queue.put((code,completed_ev, received_ev))
425 426 # first make sure the message was received, with timeout
426 427 received_ev.wait(self.gui_timeout)
427 428 if not received_ev.isSet():
428 429 # the mainloop is dead, start executing code directly
429 430 print "Warning: Timeout for mainloop thread exceeded"
430 431 print "switching to nonthreaded mode (until mainloop wakes up again)"
431 432 self.worker_ident = None
432 433 else:
433 434 completed_ev.wait()
434 435 return False
435 436
436 437 def runcode(self):
437 438 """Execute a code object.
438 439
439 440 Multithreaded wrapper around IPython's runcode()."""
440 441
441 442 global CODE_RUN
442 443
443 444 # we are in worker thread, stash out the id for runsource()
444 445 self.worker_ident = thread.get_ident()
445 446
446 447 if self._kill:
447 448 print >>Term.cout, 'Closing threads...',
448 449 Term.cout.flush()
449 450 for tokill in self.on_kill:
450 451 tokill()
451 452 print >>Term.cout, 'Done.'
452 453 # allow kill() to return
453 454 self._kill.set()
454 455 return True
455 456
456 457 # Install sigint handler. We do it every time to ensure that if user
457 458 # code modifies it, we restore our own handling.
458 459 try:
459 460 signal(SIGINT,sigint_handler)
460 461 except SystemError:
461 462 # This happens under Windows, which seems to have all sorts
462 463 # of problems with signal handling. Oh well...
463 464 pass
464 465
465 466 # Flush queue of pending code by calling the run methood of the parent
466 467 # class with all items which may be in the queue.
467 468 code_to_run = None
468 469 while 1:
469 470 try:
470 471 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
471 472 except Queue.Empty:
472 473 break
473 474 received_ev.set()
474 475
475 476 # Exceptions need to be raised differently depending on which
476 477 # thread is active. This convoluted try/except is only there to
477 478 # protect against asynchronous exceptions, to ensure that a KBINT
478 479 # at the wrong time doesn't deadlock everything. The global
479 480 # CODE_TO_RUN is set to true/false as close as possible to the
480 481 # runcode() call, so that the KBINT handler is correctly informed.
481 482 try:
482 483 try:
483 484 CODE_RUN = True
484 485 InteractiveShell.runcode(self,code_to_run)
485 486 except KeyboardInterrupt:
486 487 print "Keyboard interrupted in mainloop"
487 488 while not self.code_queue.empty():
488 489 code, ev1,ev2 = self.code_queue.get_nowait()
489 490 ev1.set()
490 491 ev2.set()
491 492 break
492 493 finally:
493 494 CODE_RUN = False
494 495 # allow runsource() return from wait
495 496 completed_ev.set()
496 497
497 498
498 499 # This MUST return true for gtk threading to work
499 500 return True
500 501
501 502 def kill(self):
502 503 """Kill the thread, returning when it has been shut down."""
503 504 self._kill = threading.Event()
504 505 self._kill.wait()
505 506
506 507 class MatplotlibShellBase:
507 508 """Mixin class to provide the necessary modifications to regular IPython
508 509 shell classes for matplotlib support.
509 510
510 511 Given Python's MRO, this should be used as the FIRST class in the
511 512 inheritance hierarchy, so that it overrides the relevant methods."""
512 513
513 514 def _matplotlib_config(self,name,user_ns,user_global_ns=None):
514 515 """Return items needed to setup the user's shell with matplotlib"""
515 516
516 517 # Initialize matplotlib to interactive mode always
517 518 import matplotlib
518 519 from matplotlib import backends
519 520 matplotlib.interactive(True)
520 521
521 522 def use(arg):
522 523 """IPython wrapper for matplotlib's backend switcher.
523 524
524 525 In interactive use, we can not allow switching to a different
525 526 interactive backend, since thread conflicts will most likely crash
526 527 the python interpreter. This routine does a safety check first,
527 528 and refuses to perform a dangerous switch. It still allows
528 529 switching to non-interactive backends."""
529 530
530 531 if arg in backends.interactive_bk and arg != self.mpl_backend:
531 532 m=('invalid matplotlib backend switch.\n'
532 533 'This script attempted to switch to the interactive '
533 534 'backend: `%s`\n'
534 535 'Your current choice of interactive backend is: `%s`\n\n'
535 536 'Switching interactive matplotlib backends at runtime\n'
536 537 'would crash the python interpreter, '
537 538 'and IPython has blocked it.\n\n'
538 539 'You need to either change your choice of matplotlib backend\n'
539 540 'by editing your .matplotlibrc file, or run this script as a \n'
540 541 'standalone file from the command line, not using IPython.\n' %
541 542 (arg,self.mpl_backend) )
542 543 raise RuntimeError, m
543 544 else:
544 545 self.mpl_use(arg)
545 546 self.mpl_use._called = True
546 547
547 548 self.matplotlib = matplotlib
548 549 self.mpl_backend = matplotlib.rcParams['backend']
549 550
550 551 # we also need to block switching of interactive backends by use()
551 552 self.mpl_use = matplotlib.use
552 553 self.mpl_use._called = False
553 554 # overwrite the original matplotlib.use with our wrapper
554 555 matplotlib.use = use
555 556
556 557 # This must be imported last in the matplotlib series, after
557 558 # backend/interactivity choices have been made
558 559 import matplotlib.pylab as pylab
559 560 self.pylab = pylab
560 561
561 562 self.pylab.show._needmain = False
562 563 # We need to detect at runtime whether show() is called by the user.
563 564 # For this, we wrap it into a decorator which adds a 'called' flag.
564 565 self.pylab.draw_if_interactive = flag_calls(self.pylab.draw_if_interactive)
565 566
566 567 # Build a user namespace initialized with matplotlib/matlab features.
567 568 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
568 569 user_global_ns)
569 570
570 571 # Import numpy as np/pyplot as plt are conventions we're trying to
571 572 # somewhat standardize on. Making them available to users by default
572 573 # will greatly help this.
573 574 exec ("import numpy\n"
574 575 "import numpy as np\n"
575 576 "import matplotlib\n"
576 577 "import matplotlib.pylab as pylab\n"
577 578 "try:\n"
578 579 " import matplotlib.pyplot as plt\n"
579 580 "except ImportError:\n"
580 581 " pass\n"
581 582 ) in user_ns
582 583
583 584 # Build matplotlib info banner
584 585 b="""
585 586 Welcome to pylab, a matplotlib-based Python environment.
586 587 For more information, type 'help(pylab)'.
587 588 """
588 589 return user_ns,user_global_ns,b
589 590
590 591 def mplot_exec(self,fname,*where,**kw):
591 592 """Execute a matplotlib script.
592 593
593 594 This is a call to execfile(), but wrapped in safeties to properly
594 595 handle interactive rendering and backend switching."""
595 596
596 597 #print '*** Matplotlib runner ***' # dbg
597 598 # turn off rendering until end of script
598 599 isInteractive = self.matplotlib.rcParams['interactive']
599 600 self.matplotlib.interactive(False)
600 601 self.safe_execfile(fname,*where,**kw)
601 602 self.matplotlib.interactive(isInteractive)
602 603 # make rendering call now, if the user tried to do it
603 604 if self.pylab.draw_if_interactive.called:
604 605 self.pylab.draw()
605 606 self.pylab.draw_if_interactive.called = False
606 607
607 608 # if a backend switch was performed, reverse it now
608 609 if self.mpl_use._called:
609 610 self.matplotlib.rcParams['backend'] = self.mpl_backend
610
611
612 @testdec.skip_doctest
611 613 def magic_run(self,parameter_s=''):
612 614 Magic.magic_run(self,parameter_s,runner=self.mplot_exec)
613 615
614 616 # Fix the docstring so users see the original as well
615 617 magic_run.__doc__ = "%s\n%s" % (Magic.magic_run.__doc__,
616 618 "\n *** Modified %run for Matplotlib,"
617 619 " with proper interactive handling ***")
618 620
619 621 # Now we provide 2 versions of a matplotlib-aware IPython base shells, single
620 622 # and multithreaded. Note that these are meant for internal use, the IPShell*
621 623 # classes below are the ones meant for public consumption.
622 624
623 625 class MatplotlibShell(MatplotlibShellBase,InteractiveShell):
624 626 """Single-threaded shell with matplotlib support."""
625 627
626 628 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
627 629 user_ns=None,user_global_ns=None,**kw):
628 630 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
629 631 InteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
630 632 banner2=b2,**kw)
631 633
632 634 class MatplotlibMTShell(MatplotlibShellBase,MTInteractiveShell):
633 635 """Multi-threaded shell with matplotlib support."""
634 636
635 637 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
636 638 user_ns=None,user_global_ns=None, **kw):
637 639 user_ns,user_global_ns,b2 = self._matplotlib_config(name,user_ns,user_global_ns)
638 640 MTInteractiveShell.__init__(self,name,usage,rc,user_ns,user_global_ns,
639 641 banner2=b2,**kw)
640 642
641 643 #-----------------------------------------------------------------------------
642 644 # Utility functions for the different GUI enabled IPShell* classes.
643 645
644 646 def get_tk():
645 647 """Tries to import Tkinter and returns a withdrawn Tkinter root
646 648 window. If Tkinter is already imported or not available, this
647 649 returns None. This function calls `hijack_tk` underneath.
648 650 """
649 651 if not USE_TK or sys.modules.has_key('Tkinter'):
650 652 return None
651 653 else:
652 654 try:
653 655 import Tkinter
654 656 except ImportError:
655 657 return None
656 658 else:
657 659 hijack_tk()
658 660 r = Tkinter.Tk()
659 661 r.withdraw()
660 662 return r
661 663
662 664 def hijack_tk():
663 665 """Modifies Tkinter's mainloop with a dummy so when a module calls
664 666 mainloop, it does not block.
665 667
666 668 """
667 669 def misc_mainloop(self, n=0):
668 670 pass
669 671 def tkinter_mainloop(n=0):
670 672 pass
671 673
672 674 import Tkinter
673 675 Tkinter.Misc.mainloop = misc_mainloop
674 676 Tkinter.mainloop = tkinter_mainloop
675 677
676 678 def update_tk(tk):
677 679 """Updates the Tkinter event loop. This is typically called from
678 680 the respective WX or GTK mainloops.
679 681 """
680 682 if tk:
681 683 tk.update()
682 684
683 685 def hijack_wx():
684 686 """Modifies wxPython's MainLoop with a dummy so user code does not
685 687 block IPython. The hijacked mainloop function is returned.
686 688 """
687 689 def dummy_mainloop(*args, **kw):
688 690 pass
689 691
690 692 try:
691 693 import wx
692 694 except ImportError:
693 695 # For very old versions of WX
694 696 import wxPython as wx
695 697
696 698 ver = wx.__version__
697 699 orig_mainloop = None
698 700 if ver[:3] >= '2.5':
699 701 import wx
700 702 if hasattr(wx, '_core_'): core = getattr(wx, '_core_')
701 703 elif hasattr(wx, '_core'): core = getattr(wx, '_core')
702 704 else: raise AttributeError('Could not find wx core module')
703 705 orig_mainloop = core.PyApp_MainLoop
704 706 core.PyApp_MainLoop = dummy_mainloop
705 707 elif ver[:3] == '2.4':
706 708 orig_mainloop = wx.wxc.wxPyApp_MainLoop
707 709 wx.wxc.wxPyApp_MainLoop = dummy_mainloop
708 710 else:
709 711 warn("Unable to find either wxPython version 2.4 or >= 2.5.")
710 712 return orig_mainloop
711 713
712 714 def hijack_gtk():
713 715 """Modifies pyGTK's mainloop with a dummy so user code does not
714 716 block IPython. This function returns the original `gtk.mainloop`
715 717 function that has been hijacked.
716 718 """
717 719 def dummy_mainloop(*args, **kw):
718 720 pass
719 721 import gtk
720 722 if gtk.pygtk_version >= (2,4,0): orig_mainloop = gtk.main
721 723 else: orig_mainloop = gtk.mainloop
722 724 gtk.mainloop = dummy_mainloop
723 725 gtk.main = dummy_mainloop
724 726 return orig_mainloop
725 727
726 728 def hijack_qt():
727 729 """Modifies PyQt's mainloop with a dummy so user code does not
728 730 block IPython. This function returns the original
729 731 `qt.qApp.exec_loop` function that has been hijacked.
730 732 """
731 733 def dummy_mainloop(*args, **kw):
732 734 pass
733 735 import qt
734 736 orig_mainloop = qt.qApp.exec_loop
735 737 qt.qApp.exec_loop = dummy_mainloop
736 738 qt.QApplication.exec_loop = dummy_mainloop
737 739 return orig_mainloop
738 740
739 741 def hijack_qt4():
740 742 """Modifies PyQt4's mainloop with a dummy so user code does not
741 743 block IPython. This function returns the original
742 744 `QtGui.qApp.exec_` function that has been hijacked.
743 745 """
744 746 def dummy_mainloop(*args, **kw):
745 747 pass
746 748 from PyQt4 import QtGui, QtCore
747 749 orig_mainloop = QtGui.qApp.exec_
748 750 QtGui.qApp.exec_ = dummy_mainloop
749 751 QtGui.QApplication.exec_ = dummy_mainloop
750 752 QtCore.QCoreApplication.exec_ = dummy_mainloop
751 753 return orig_mainloop
752 754
753 755 #-----------------------------------------------------------------------------
754 756 # The IPShell* classes below are the ones meant to be run by external code as
755 757 # IPython instances. Note that unless a specific threading strategy is
756 758 # desired, the factory function start() below should be used instead (it
757 759 # selects the proper threaded class).
758 760
759 761 class IPThread(threading.Thread):
760 762 def run(self):
761 763 self.IP.mainloop(self._banner)
762 764 self.IP.kill()
763 765
764 766 class IPShellGTK(IPThread):
765 767 """Run a gtk mainloop() in a separate thread.
766 768
767 769 Python commands can be passed to the thread where they will be executed.
768 770 This is implemented by periodically checking for passed code using a
769 771 GTK timeout callback."""
770 772
771 773 TIMEOUT = 100 # Millisecond interval between timeouts.
772 774
773 775 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
774 776 debug=1,shell_class=MTInteractiveShell):
775 777
776 778 import gtk
779 # Check for set_interactive, coming up in new pygtk.
780 # Disable it so that this code works, but notify
781 # the user that he has a better option as well.
782 # XXX TODO better support when set_interactive is released
783 try:
784 gtk.set_interactive(False)
785 print "Your PyGtk has set_interactive(), so you can use the"
786 print "more stable single-threaded Gtk mode."
787 print "See https://bugs.launchpad.net/ipython/+bug/270856"
788 except AttributeError:
789 pass
777 790
778 791 self.gtk = gtk
779 792 self.gtk_mainloop = hijack_gtk()
780 793
781 794 # Allows us to use both Tk and GTK.
782 795 self.tk = get_tk()
783 796
784 797 if gtk.pygtk_version >= (2,4,0): mainquit = self.gtk.main_quit
785 798 else: mainquit = self.gtk.mainquit
786 799
787 800 self.IP = make_IPython(argv,user_ns=user_ns,
788 801 user_global_ns=user_global_ns,
789 802 debug=debug,
790 803 shell_class=shell_class,
791 804 on_kill=[mainquit])
792 805
793 806 # HACK: slot for banner in self; it will be passed to the mainloop
794 807 # method only and .run() needs it. The actual value will be set by
795 808 # .mainloop().
796 809 self._banner = None
797 810
798 811 threading.Thread.__init__(self)
799 812
800 813 def mainloop(self,sys_exit=0,banner=None):
801 814
802 815 self._banner = banner
803 816
804 817 if self.gtk.pygtk_version >= (2,4,0):
805 818 import gobject
806 819 gobject.idle_add(self.on_timer)
807 820 else:
808 821 self.gtk.idle_add(self.on_timer)
809 822
810 823 if sys.platform != 'win32':
811 824 try:
812 825 if self.gtk.gtk_version[0] >= 2:
813 826 self.gtk.gdk.threads_init()
814 827 except AttributeError:
815 828 pass
816 829 except RuntimeError:
817 830 error('Your pyGTK likely has not been compiled with '
818 831 'threading support.\n'
819 832 'The exception printout is below.\n'
820 833 'You can either rebuild pyGTK with threads, or '
821 834 'try using \n'
822 835 'matplotlib with a different backend (like Tk or WX).\n'
823 836 'Note that matplotlib will most likely not work in its '
824 837 'current state!')
825 838 self.IP.InteractiveTB()
826 839
827 840 self.start()
828 841 self.gtk.gdk.threads_enter()
829 842 self.gtk_mainloop()
830 843 self.gtk.gdk.threads_leave()
831 844 self.join()
832 845
833 846 def on_timer(self):
834 847 """Called when GTK is idle.
835 848
836 849 Must return True always, otherwise GTK stops calling it"""
837 850
838 851 update_tk(self.tk)
839 852 self.IP.runcode()
840 853 time.sleep(0.01)
841 854 return True
842 855
843 856
844 857 class IPShellWX(IPThread):
845 858 """Run a wx mainloop() in a separate thread.
846 859
847 860 Python commands can be passed to the thread where they will be executed.
848 861 This is implemented by periodically checking for passed code using a
849 862 GTK timeout callback."""
850 863
851 864 TIMEOUT = 100 # Millisecond interval between timeouts.
852 865
853 866 def __init__(self,argv=None,user_ns=None,user_global_ns=None,
854 867 debug=1,shell_class=MTInteractiveShell):
855 868
856 869 self.IP = make_IPython(argv,user_ns=user_ns,
857 870 user_global_ns=user_global_ns,
858 871 debug=debug,
859 872 shell_class=shell_class,
860 873 on_kill=[self.wxexit])
861 874
862 875 wantedwxversion=self.IP.rc.wxversion
863 876 if wantedwxversion!="0":
864 877 try:
865 878 import wxversion
866 879 except ImportError:
867 880 error('The wxversion module is needed for WX version selection')
868 881 else:
869 882 try:
870 883 wxversion.select(wantedwxversion)
871 884 except:
872 885 self.IP.InteractiveTB()
873 886 error('Requested wxPython version %s could not be loaded' %
874 887 wantedwxversion)
875 888
876 889 import wx
877 890
878 891 threading.Thread.__init__(self)
879 892 self.wx = wx
880 893 self.wx_mainloop = hijack_wx()
881 894
882 895 # Allows us to use both Tk and GTK.
883 896 self.tk = get_tk()
884 897
885 898 # HACK: slot for banner in self; it will be passed to the mainloop
886 899 # method only and .run() needs it. The actual value will be set by
887 900 # .mainloop().
888 901 self._banner = None
889 902
890 903 self.app = None
891 904
892 905 def wxexit(self, *args):
893 906 if self.app is not None:
894 907 self.app.agent.timer.Stop()
895 908 self.app.ExitMainLoop()
896 909
897 910 def mainloop(self,sys_exit=0,banner=None):
898 911
899 912 self._banner = banner
900 913
901 914 self.start()
902 915
903 916 class TimerAgent(self.wx.MiniFrame):
904 917 wx = self.wx
905 918 IP = self.IP
906 919 tk = self.tk
907 920 def __init__(self, parent, interval):
908 921 style = self.wx.DEFAULT_FRAME_STYLE | self.wx.TINY_CAPTION_HORIZ
909 922 self.wx.MiniFrame.__init__(self, parent, -1, ' ', pos=(200, 200),
910 923 size=(100, 100),style=style)
911 924 self.Show(False)
912 925 self.interval = interval
913 926 self.timerId = self.wx.NewId()
914 927
915 928 def StartWork(self):
916 929 self.timer = self.wx.Timer(self, self.timerId)
917 930 self.wx.EVT_TIMER(self, self.timerId, self.OnTimer)
918 931 self.timer.Start(self.interval)
919 932
920 933 def OnTimer(self, event):
921 934 update_tk(self.tk)
922 935 self.IP.runcode()
923 936
924 937 class App(self.wx.App):
925 938 wx = self.wx
926 939 TIMEOUT = self.TIMEOUT
927 940 def OnInit(self):
928 941 'Create the main window and insert the custom frame'
929 942 self.agent = TimerAgent(None, self.TIMEOUT)
930 943 self.agent.Show(False)
931 944 self.agent.StartWork()
932 945 return True
933 946
934 947 self.app = App(redirect=False)
935 948 self.wx_mainloop(self.app)
936 949 self.join()
937 950
938 951
939 952 class IPShellQt(IPThread):
940 953 """Run a Qt event loop in a separate thread.
941 954
942 955 Python commands can be passed to the thread where they will be executed.
943 956 This is implemented by periodically checking for passed code using a
944 957 Qt timer / slot."""
945 958
946 959 TIMEOUT = 100 # Millisecond interval between timeouts.
947 960
948 961 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
949 962 debug=0, shell_class=MTInteractiveShell):
950 963
951 964 import qt
952 965
953 966 self.exec_loop = hijack_qt()
954 967
955 968 # Allows us to use both Tk and QT.
956 969 self.tk = get_tk()
957 970
958 971 self.IP = make_IPython(argv,
959 972 user_ns=user_ns,
960 973 user_global_ns=user_global_ns,
961 974 debug=debug,
962 975 shell_class=shell_class,
963 976 on_kill=[qt.qApp.exit])
964 977
965 978 # HACK: slot for banner in self; it will be passed to the mainloop
966 979 # method only and .run() needs it. The actual value will be set by
967 980 # .mainloop().
968 981 self._banner = None
969 982
970 983 threading.Thread.__init__(self)
971 984
972 985 def mainloop(self, sys_exit=0, banner=None):
973 986
974 987 import qt
975 988
976 989 self._banner = banner
977 990
978 991 if qt.QApplication.startingUp():
979 992 a = qt.QApplication(sys.argv)
980 993
981 994 self.timer = qt.QTimer()
982 995 qt.QObject.connect(self.timer,
983 996 qt.SIGNAL('timeout()'),
984 997 self.on_timer)
985 998
986 999 self.start()
987 1000 self.timer.start(self.TIMEOUT, True)
988 1001 while True:
989 1002 if self.IP._kill: break
990 1003 self.exec_loop()
991 1004 self.join()
992 1005
993 1006 def on_timer(self):
994 1007 update_tk(self.tk)
995 1008 result = self.IP.runcode()
996 1009 self.timer.start(self.TIMEOUT, True)
997 1010 return result
998 1011
999 1012
1000 1013 class IPShellQt4(IPThread):
1001 1014 """Run a Qt event loop in a separate thread.
1002 1015
1003 1016 Python commands can be passed to the thread where they will be executed.
1004 1017 This is implemented by periodically checking for passed code using a
1005 1018 Qt timer / slot."""
1006 1019
1007 1020 TIMEOUT = 100 # Millisecond interval between timeouts.
1008 1021
1009 1022 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
1010 1023 debug=0, shell_class=MTInteractiveShell):
1011 1024
1012 1025 from PyQt4 import QtCore, QtGui
1013 1026
1014 1027 try:
1015 1028 # present in PyQt4-4.2.1 or later
1016 1029 QtCore.pyqtRemoveInputHook()
1017 1030 except AttributeError:
1018 1031 pass
1019 1032
1020 1033 if QtCore.PYQT_VERSION_STR == '4.3':
1021 1034 warn('''PyQt4 version 4.3 detected.
1022 1035 If you experience repeated threading warnings, please update PyQt4.
1023 1036 ''')
1024 1037
1025 1038 self.exec_ = hijack_qt4()
1026 1039
1027 1040 # Allows us to use both Tk and QT.
1028 1041 self.tk = get_tk()
1029 1042
1030 1043 self.IP = make_IPython(argv,
1031 1044 user_ns=user_ns,
1032 1045 user_global_ns=user_global_ns,
1033 1046 debug=debug,
1034 1047 shell_class=shell_class,
1035 1048 on_kill=[QtGui.qApp.exit])
1036 1049
1037 1050 # HACK: slot for banner in self; it will be passed to the mainloop
1038 1051 # method only and .run() needs it. The actual value will be set by
1039 1052 # .mainloop().
1040 1053 self._banner = None
1041 1054
1042 1055 threading.Thread.__init__(self)
1043 1056
1044 1057 def mainloop(self, sys_exit=0, banner=None):
1045 1058
1046 1059 from PyQt4 import QtCore, QtGui
1047 1060
1048 1061 self._banner = banner
1049 1062
1050 1063 if QtGui.QApplication.startingUp():
1051 1064 a = QtGui.QApplication(sys.argv)
1052 1065
1053 1066 self.timer = QtCore.QTimer()
1054 1067 QtCore.QObject.connect(self.timer,
1055 1068 QtCore.SIGNAL('timeout()'),
1056 1069 self.on_timer)
1057 1070
1058 1071 self.start()
1059 1072 self.timer.start(self.TIMEOUT)
1060 1073 while True:
1061 1074 if self.IP._kill: break
1062 1075 self.exec_()
1063 1076 self.join()
1064 1077
1065 1078 def on_timer(self):
1066 1079 update_tk(self.tk)
1067 1080 result = self.IP.runcode()
1068 1081 self.timer.start(self.TIMEOUT)
1069 1082 return result
1070 1083
1071 1084
1072 1085 # A set of matplotlib public IPython shell classes, for single-threaded (Tk*
1073 1086 # and FLTK*) and multithreaded (GTK*, WX* and Qt*) backends to use.
1074 1087 def _load_pylab(user_ns):
1075 1088 """Allow users to disable pulling all of pylab into the top-level
1076 1089 namespace.
1077 1090
1078 1091 This little utility must be called AFTER the actual ipython instance is
1079 1092 running, since only then will the options file have been fully parsed."""
1080 1093
1081 1094 ip = IPython.ipapi.get()
1082 1095 if ip.options.pylab_import_all:
1083 1096 ip.ex("from matplotlib.pylab import *")
1084 1097 ip.IP.user_config_ns.update(ip.user_ns)
1085 1098
1086 1099
1087 1100 class IPShellMatplotlib(IPShell):
1088 1101 """Subclass IPShell with MatplotlibShell as the internal shell.
1089 1102
1090 1103 Single-threaded class, meant for the Tk* and FLTK* backends.
1091 1104
1092 1105 Having this on a separate class simplifies the external driver code."""
1093 1106
1094 1107 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1095 1108 IPShell.__init__(self,argv,user_ns,user_global_ns,debug,
1096 1109 shell_class=MatplotlibShell)
1097 1110 _load_pylab(self.IP.user_ns)
1098 1111
1099 1112 class IPShellMatplotlibGTK(IPShellGTK):
1100 1113 """Subclass IPShellGTK with MatplotlibMTShell as the internal shell.
1101 1114
1102 1115 Multi-threaded class, meant for the GTK* backends."""
1103 1116
1104 1117 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1105 1118 IPShellGTK.__init__(self,argv,user_ns,user_global_ns,debug,
1106 1119 shell_class=MatplotlibMTShell)
1107 1120 _load_pylab(self.IP.user_ns)
1108 1121
1109 1122 class IPShellMatplotlibWX(IPShellWX):
1110 1123 """Subclass IPShellWX with MatplotlibMTShell as the internal shell.
1111 1124
1112 1125 Multi-threaded class, meant for the WX* backends."""
1113 1126
1114 1127 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1115 1128 IPShellWX.__init__(self,argv,user_ns,user_global_ns,debug,
1116 1129 shell_class=MatplotlibMTShell)
1117 1130 _load_pylab(self.IP.user_ns)
1118 1131
1119 1132 class IPShellMatplotlibQt(IPShellQt):
1120 1133 """Subclass IPShellQt with MatplotlibMTShell as the internal shell.
1121 1134
1122 1135 Multi-threaded class, meant for the Qt* backends."""
1123 1136
1124 1137 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1125 1138 IPShellQt.__init__(self,argv,user_ns,user_global_ns,debug,
1126 1139 shell_class=MatplotlibMTShell)
1127 1140 _load_pylab(self.IP.user_ns)
1128 1141
1129 1142 class IPShellMatplotlibQt4(IPShellQt4):
1130 1143 """Subclass IPShellQt4 with MatplotlibMTShell as the internal shell.
1131 1144
1132 1145 Multi-threaded class, meant for the Qt4* backends."""
1133 1146
1134 1147 def __init__(self,argv=None,user_ns=None,user_global_ns=None,debug=1):
1135 1148 IPShellQt4.__init__(self,argv,user_ns,user_global_ns,debug,
1136 1149 shell_class=MatplotlibMTShell)
1137 1150 _load_pylab(self.IP.user_ns)
1138 1151
1139 1152 #-----------------------------------------------------------------------------
1140 1153 # Factory functions to actually start the proper thread-aware shell
1141 1154
1142 1155 def _select_shell(argv):
1143 1156 """Select a shell from the given argv vector.
1144 1157
1145 1158 This function implements the threading selection policy, allowing runtime
1146 1159 control of the threading mode, both for general users and for matplotlib.
1147 1160
1148 1161 Return:
1149 1162 Shell class to be instantiated for runtime operation.
1150 1163 """
1151 1164
1152 1165 global USE_TK
1153 1166
1154 1167 mpl_shell = {'gthread' : IPShellMatplotlibGTK,
1155 1168 'wthread' : IPShellMatplotlibWX,
1156 1169 'qthread' : IPShellMatplotlibQt,
1157 1170 'q4thread' : IPShellMatplotlibQt4,
1158 1171 'tkthread' : IPShellMatplotlib, # Tk is built-in
1159 1172 }
1160 1173
1161 1174 th_shell = {'gthread' : IPShellGTK,
1162 1175 'wthread' : IPShellWX,
1163 1176 'qthread' : IPShellQt,
1164 1177 'q4thread' : IPShellQt4,
1165 1178 'tkthread' : IPShell, # Tk is built-in
1166 1179 }
1167 1180
1168 1181 backends = {'gthread' : 'GTKAgg',
1169 1182 'wthread' : 'WXAgg',
1170 1183 'qthread' : 'QtAgg',
1171 1184 'q4thread' :'Qt4Agg',
1172 1185 'tkthread' :'TkAgg',
1173 1186 }
1174 1187
1175 1188 all_opts = set(['tk','pylab','gthread','qthread','q4thread','wthread',
1176 1189 'tkthread'])
1177 1190 user_opts = set([s.replace('-','') for s in argv[:3]])
1178 1191 special_opts = user_opts & all_opts
1179 1192
1180 1193 if 'tk' in special_opts:
1181 1194 USE_TK = True
1182 1195 special_opts.remove('tk')
1183 1196
1184 1197 if 'pylab' in special_opts:
1185 1198
1186 1199 try:
1187 1200 import matplotlib
1188 1201 except ImportError:
1189 1202 error('matplotlib could NOT be imported! Starting normal IPython.')
1190 1203 return IPShell
1191 1204
1192 1205 special_opts.remove('pylab')
1193 1206 # If there's any option left, it means the user wants to force the
1194 1207 # threading backend, else it's auto-selected from the rc file
1195 1208 if special_opts:
1196 1209 th_mode = special_opts.pop()
1197 1210 matplotlib.rcParams['backend'] = backends[th_mode]
1198 1211 else:
1199 1212 backend = matplotlib.rcParams['backend']
1200 1213 if backend.startswith('GTK'):
1201 1214 th_mode = 'gthread'
1202 1215 elif backend.startswith('WX'):
1203 1216 th_mode = 'wthread'
1204 1217 elif backend.startswith('Qt4'):
1205 1218 th_mode = 'q4thread'
1206 1219 elif backend.startswith('Qt'):
1207 1220 th_mode = 'qthread'
1208 1221 else:
1209 1222 # Any other backend, use plain Tk
1210 1223 th_mode = 'tkthread'
1211 1224
1212 1225 return mpl_shell[th_mode]
1213 1226 else:
1214 1227 # No pylab requested, just plain threads
1215 1228 try:
1216 1229 th_mode = special_opts.pop()
1217 1230 except KeyError:
1218 1231 th_mode = 'tkthread'
1219 1232 return th_shell[th_mode]
1220 1233
1221 1234
1222 1235 # This is the one which should be called by external code.
1223 1236 def start(user_ns = None):
1224 1237 """Return a running shell instance, dealing with threading options.
1225 1238
1226 1239 This is a factory function which will instantiate the proper IPython shell
1227 1240 based on the user's threading choice. Such a selector is needed because
1228 1241 different GUI toolkits require different thread handling details."""
1229 1242
1230 1243 shell = _select_shell(sys.argv)
1231 1244 return shell(user_ns = user_ns)
1232 1245
1233 1246 # Some aliases for backwards compatibility
1234 1247 IPythonShell = IPShell
1235 1248 IPythonShellEmbed = IPShellEmbed
1236 1249 #************************ End of file <Shell.py> ***************************
@@ -1,43 +1,45 b''
1 1 # -*- Mode: Shell-Script -*- Not really, but shows comments correctly
2 2 #***************************************************************************
3 3 #
4 4 # Configuration file for ipython -- ipythonrc format
5 5 #
6 6 # The format of this file is one of 'key value' lines.
7 7 # Lines containing only whitespace at the beginning and then a # are ignored
8 8 # as comments. But comments can NOT be put on lines with data.
9 9 #***************************************************************************
10 10
11 11 # If this file is found in the user's ~/.ipython directory as
12 12 # ipythonrc-physics, it can be loaded by calling passing the '-profile
13 13 # physics' (or '-p physics') option to IPython.
14 14
15 15 # This profile loads modules useful for doing interactive calculations with
16 16 # physical quantities (with units). It relies on modules from Konrad Hinsen's
17 17 # ScientificPython (http://dirac.cnrs-orleans.fr/ScientificPython/)
18 18
19 19 # First load basic user configuration
20 20 include ipythonrc
21 21
22 22 # import ...
23 23 # Module with alternate input syntax for PhysicalQuantity objects.
24 24 import_mod IPython.Extensions.PhysicalQInput
25 25
26 26 # from ... import *
27 27 # math CANNOT be imported after PhysicalQInteractive. It will override the
28 28 # functions defined there.
29 29 import_all math IPython.Extensions.PhysicalQInteractive
30 30
31 31 # from ... import ...
32 32 import_some
33 33
34 34 # code
35 35 execute q = PhysicalQuantityInteractive
36 36 execute g = PhysicalQuantityInteractive('9.8 m/s**2')
37 37 ececute rad = pi/180.
38 38 execute print '*** q is an alias for PhysicalQuantityInteractive'
39 39 execute print '*** g = 9.8 m/s^2 has been defined'
40 40 execute print '*** rad = pi/180 has been defined'
41 execute import ipy_constants as C
42 execute print '*** C is the physical constants module'
41 43
42 44 # Files to execute
43 45 execfile
@@ -1,637 +1,640 b''
1 1 """Word completion for IPython.
2 2
3 3 This module is a fork of the rlcompleter module in the Python standard
4 4 library. The original enhancements made to rlcompleter have been sent
5 5 upstream and were accepted as of Python 2.3, but we need a lot more
6 6 functionality specific to IPython, so this module will continue to live as an
7 7 IPython-specific utility.
8 8
9 9 ---------------------------------------------------------------------------
10 10 Original rlcompleter documentation:
11 11
12 12 This requires the latest extension to the readline module (the
13 13 completes keywords, built-ins and globals in __main__; when completing
14 14 NAME.NAME..., it evaluates (!) the expression up to the last dot and
15 15 completes its attributes.
16 16
17 17 It's very cool to do "import string" type "string.", hit the
18 18 completion key (twice), and see the list of names defined by the
19 19 string module!
20 20
21 21 Tip: to use the tab key as the completion key, call
22 22
23 23 readline.parse_and_bind("tab: complete")
24 24
25 25 Notes:
26 26
27 27 - Exceptions raised by the completer function are *ignored* (and
28 28 generally cause the completion to fail). This is a feature -- since
29 29 readline sets the tty device in raw (or cbreak) mode, printing a
30 30 traceback wouldn't work well without some complicated hoopla to save,
31 31 reset and restore the tty state.
32 32
33 33 - The evaluation of the NAME.NAME... form may cause arbitrary
34 34 application defined code to be executed if an object with a
35 35 __getattr__ hook is found. Since it is the responsibility of the
36 36 application (or the user) to enable this feature, I consider this an
37 37 acceptable risk. More complicated expressions (e.g. function calls or
38 38 indexing operations) are *not* evaluated.
39 39
40 40 - GNU readline is also used by the built-in functions input() and
41 41 raw_input(), and thus these also benefit/suffer from the completer
42 42 features. Clearly an interactive application can benefit by
43 43 specifying its own completer function and using raw_input() for all
44 44 its input.
45 45
46 46 - When the original stdin is not a tty device, GNU readline is never
47 47 used, and this module (and the readline module) are silently inactive.
48 48
49 49 """
50 50
51 51 #*****************************************************************************
52 52 #
53 53 # Since this file is essentially a minimally modified copy of the rlcompleter
54 54 # module which is part of the standard Python distribution, I assume that the
55 55 # proper procedure is to maintain its copyright as belonging to the Python
56 56 # Software Foundation (in addition to my own, for all new code).
57 57 #
58 58 # Copyright (C) 2001 Python Software Foundation, www.python.org
59 59 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
60 60 #
61 61 # Distributed under the terms of the BSD License. The full license is in
62 62 # the file COPYING, distributed as part of this software.
63 63 #
64 64 #*****************************************************************************
65 65
66 66 import __builtin__
67 67 import __main__
68 68 import glob
69 69 import keyword
70 70 import os
71 71 import re
72 72 import shlex
73 73 import sys
74 74 import IPython.rlineimpl as readline
75 75 import itertools
76 76 from IPython.ipstruct import Struct
77 77 from IPython import ipapi
78 78 from IPython import generics
79 79 import types
80 80
81 81 # Python 2.4 offers sets as a builtin
82 82 try:
83 83 set()
84 84 except NameError:
85 85 from sets import Set as set
86 86
87 87 from IPython.genutils import debugx, dir2
88 88
89 89 __all__ = ['Completer','IPCompleter']
90 90
91 91 class Completer:
92 92 def __init__(self,namespace=None,global_namespace=None):
93 93 """Create a new completer for the command line.
94 94
95 95 Completer([namespace,global_namespace]) -> completer instance.
96 96
97 97 If unspecified, the default namespace where completions are performed
98 98 is __main__ (technically, __main__.__dict__). Namespaces should be
99 99 given as dictionaries.
100 100
101 101 An optional second namespace can be given. This allows the completer
102 102 to handle cases where both the local and global scopes need to be
103 103 distinguished.
104 104
105 105 Completer instances should be used as the completion mechanism of
106 106 readline via the set_completer() call:
107 107
108 108 readline.set_completer(Completer(my_namespace).complete)
109 109 """
110 110
111 111 # Don't bind to namespace quite yet, but flag whether the user wants a
112 112 # specific namespace or to use __main__.__dict__. This will allow us
113 113 # to bind to __main__.__dict__ at completion time, not now.
114 114 if namespace is None:
115 115 self.use_main_ns = 1
116 116 else:
117 117 self.use_main_ns = 0
118 118 self.namespace = namespace
119 119
120 120 # The global namespace, if given, can be bound directly
121 121 if global_namespace is None:
122 122 self.global_namespace = {}
123 123 else:
124 124 self.global_namespace = global_namespace
125 125
126 126 def complete(self, text, state):
127 127 """Return the next possible completion for 'text'.
128 128
129 129 This is called successively with state == 0, 1, 2, ... until it
130 130 returns None. The completion should begin with 'text'.
131 131
132 132 """
133 133 if self.use_main_ns:
134 134 self.namespace = __main__.__dict__
135 135
136 136 if state == 0:
137 137 if "." in text:
138 138 self.matches = self.attr_matches(text)
139 139 else:
140 140 self.matches = self.global_matches(text)
141 141 try:
142 142 return self.matches[state]
143 143 except IndexError:
144 144 return None
145 145
146 146 def global_matches(self, text):
147 147 """Compute matches when text is a simple name.
148 148
149 149 Return a list of all keywords, built-in functions and names currently
150 150 defined in self.namespace or self.global_namespace that match.
151 151
152 152 """
153 153 matches = []
154 154 match_append = matches.append
155 155 n = len(text)
156 156 for lst in [keyword.kwlist,
157 157 __builtin__.__dict__.keys(),
158 158 self.namespace.keys(),
159 159 self.global_namespace.keys()]:
160 160 for word in lst:
161 161 if word[:n] == text and word != "__builtins__":
162 162 match_append(word)
163 163 return matches
164 164
165 165 def attr_matches(self, text):
166 166 """Compute matches when text contains a dot.
167 167
168 168 Assuming the text is of the form NAME.NAME....[NAME], and is
169 169 evaluatable in self.namespace or self.global_namespace, it will be
170 170 evaluated and its attributes (as revealed by dir()) are used as
171 171 possible completions. (For class instances, class members are are
172 172 also considered.)
173 173
174 174 WARNING: this can still invoke arbitrary C code, if an object
175 175 with a __getattr__ hook is evaluated.
176 176
177 177 """
178 178 import re
179 179
180 180 # Another option, seems to work great. Catches things like ''.<tab>
181 181 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
182 182
183 183 if not m:
184 184 return []
185 185
186 186 expr, attr = m.group(1, 3)
187 187 try:
188 188 obj = eval(expr, self.namespace)
189 189 except:
190 190 try:
191 191 obj = eval(expr, self.global_namespace)
192 192 except:
193 193 return []
194 194
195 195 words = dir2(obj)
196 196
197 197 try:
198 198 words = generics.complete_object(obj, words)
199 199 except ipapi.TryNext:
200 200 pass
201 201 # Build match list to return
202 202 n = len(attr)
203 203 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
204 204 return res
205 205
206 206 class IPCompleter(Completer):
207 207 """Extension of the completer class with IPython-specific features"""
208 208
209 209 def __init__(self,shell,namespace=None,global_namespace=None,
210 210 omit__names=0,alias_table=None):
211 211 """IPCompleter() -> completer
212 212
213 213 Return a completer object suitable for use by the readline library
214 214 via readline.set_completer().
215 215
216 216 Inputs:
217 217
218 218 - shell: a pointer to the ipython shell itself. This is needed
219 219 because this completer knows about magic functions, and those can
220 220 only be accessed via the ipython instance.
221 221
222 222 - namespace: an optional dict where completions are performed.
223 223
224 224 - global_namespace: secondary optional dict for completions, to
225 225 handle cases (such as IPython embedded inside functions) where
226 226 both Python scopes are visible.
227 227
228 228 - The optional omit__names parameter sets the completer to omit the
229 229 'magic' names (__magicname__) for python objects unless the text
230 230 to be completed explicitly starts with one or more underscores.
231 231
232 232 - If alias_table is supplied, it should be a dictionary of aliases
233 233 to complete. """
234 234
235 235 Completer.__init__(self,namespace,global_namespace)
236 236 self.magic_prefix = shell.name+'.magic_'
237 237 self.magic_escape = shell.ESC_MAGIC
238 238 self.readline = readline
239 239 delims = self.readline.get_completer_delims()
240 240 delims = delims.replace(self.magic_escape,'')
241 241 self.readline.set_completer_delims(delims)
242 242 self.get_line_buffer = self.readline.get_line_buffer
243 243 self.get_endidx = self.readline.get_endidx
244 244 self.omit__names = omit__names
245 245 self.merge_completions = shell.rc.readline_merge_completions
246 246 if alias_table is None:
247 247 alias_table = {}
248 248 self.alias_table = alias_table
249 249 # Regexp to split filenames with spaces in them
250 250 self.space_name_re = re.compile(r'([^\\] )')
251 251 # Hold a local ref. to glob.glob for speed
252 252 self.glob = glob.glob
253 253
254 254 # Determine if we are running on 'dumb' terminals, like (X)Emacs
255 255 # buffers, to avoid completion problems.
256 256 term = os.environ.get('TERM','xterm')
257 257 self.dumb_terminal = term in ['dumb','emacs']
258 258
259 259 # Special handling of backslashes needed in win32 platforms
260 260 if sys.platform == "win32":
261 261 self.clean_glob = self._clean_glob_win32
262 262 else:
263 263 self.clean_glob = self._clean_glob
264 264 self.matchers = [self.python_matches,
265 265 self.file_matches,
266 266 self.alias_matches,
267 267 self.python_func_kw_matches]
268 268
269 269
270 270 # Code contributed by Alex Schmolck, for ipython/emacs integration
271 271 def all_completions(self, text):
272 272 """Return all possible completions for the benefit of emacs."""
273 273
274 274 completions = []
275 275 comp_append = completions.append
276 276 try:
277 277 for i in xrange(sys.maxint):
278 278 res = self.complete(text, i)
279 279
280 280 if not res: break
281 281
282 282 comp_append(res)
283 283 #XXX workaround for ``notDefined.<tab>``
284 284 except NameError:
285 285 pass
286 286 return completions
287 287 # /end Alex Schmolck code.
288 288
289 289 def _clean_glob(self,text):
290 290 return self.glob("%s*" % text)
291 291
292 292 def _clean_glob_win32(self,text):
293 293 return [f.replace("\\","/")
294 294 for f in self.glob("%s*" % text)]
295 295
296 296 def file_matches(self, text):
297 297 """Match filenames, expanding ~USER type strings.
298 298
299 299 Most of the seemingly convoluted logic in this completer is an
300 300 attempt to handle filenames with spaces in them. And yet it's not
301 301 quite perfect, because Python's readline doesn't expose all of the
302 302 GNU readline details needed for this to be done correctly.
303 303
304 304 For a filename with a space in it, the printed completions will be
305 305 only the parts after what's already been typed (instead of the
306 306 full completions, as is normally done). I don't think with the
307 307 current (as of Python 2.3) Python readline it's possible to do
308 308 better."""
309 309
310 310 #print 'Completer->file_matches: <%s>' % text # dbg
311 311
312 312 # chars that require escaping with backslash - i.e. chars
313 313 # that readline treats incorrectly as delimiters, but we
314 314 # don't want to treat as delimiters in filename matching
315 315 # when escaped with backslash
316 316
317 protectables = ' '
317 if sys.platform == 'win32':
318 protectables = ' '
319 else:
320 protectables = ' ()'
318 321
319 322 if text.startswith('!'):
320 323 text = text[1:]
321 324 text_prefix = '!'
322 325 else:
323 326 text_prefix = ''
324 327
325 328 def protect_filename(s):
326 329 return "".join([(ch in protectables and '\\' + ch or ch)
327 330 for ch in s])
328 331
329 332 def single_dir_expand(matches):
330 333 "Recursively expand match lists containing a single dir."
331 334
332 335 if len(matches) == 1 and os.path.isdir(matches[0]):
333 336 # Takes care of links to directories also. Use '/'
334 337 # explicitly, even under Windows, so that name completions
335 338 # don't end up escaped.
336 339 d = matches[0]
337 340 if d[-1] in ['/','\\']:
338 341 d = d[:-1]
339 342
340 343 subdirs = os.listdir(d)
341 344 if subdirs:
342 345 matches = [ (d + '/' + p) for p in subdirs]
343 346 return single_dir_expand(matches)
344 347 else:
345 348 return matches
346 349 else:
347 350 return matches
348 351
349 352 lbuf = self.lbuf
350 353 open_quotes = 0 # track strings with open quotes
351 354 try:
352 355 lsplit = shlex.split(lbuf)[-1]
353 356 except ValueError:
354 357 # typically an unmatched ", or backslash without escaped char.
355 358 if lbuf.count('"')==1:
356 359 open_quotes = 1
357 360 lsplit = lbuf.split('"')[-1]
358 361 elif lbuf.count("'")==1:
359 362 open_quotes = 1
360 363 lsplit = lbuf.split("'")[-1]
361 364 else:
362 365 return []
363 366 except IndexError:
364 367 # tab pressed on empty line
365 368 lsplit = ""
366 369
367 370 if lsplit != protect_filename(lsplit):
368 371 # if protectables are found, do matching on the whole escaped
369 372 # name
370 373 has_protectables = 1
371 374 text0,text = text,lsplit
372 375 else:
373 376 has_protectables = 0
374 377 text = os.path.expanduser(text)
375 378
376 379 if text == "":
377 380 return [text_prefix + protect_filename(f) for f in self.glob("*")]
378 381
379 382 m0 = self.clean_glob(text.replace('\\',''))
380 383 if has_protectables:
381 384 # If we had protectables, we need to revert our changes to the
382 385 # beginning of filename so that we don't double-write the part
383 386 # of the filename we have so far
384 387 len_lsplit = len(lsplit)
385 388 matches = [text_prefix + text0 +
386 389 protect_filename(f[len_lsplit:]) for f in m0]
387 390 else:
388 391 if open_quotes:
389 392 # if we have a string with an open quote, we don't need to
390 393 # protect the names at all (and we _shouldn't_, as it
391 394 # would cause bugs when the filesystem call is made).
392 395 matches = m0
393 396 else:
394 397 matches = [text_prefix +
395 398 protect_filename(f) for f in m0]
396 399
397 400 #print 'mm',matches # dbg
398 401 return single_dir_expand(matches)
399 402
400 403 def alias_matches(self, text):
401 404 """Match internal system aliases"""
402 405 #print 'Completer->alias_matches:',text,'lb',self.lbuf # dbg
403 406
404 407 # if we are not in the first 'item', alias matching
405 408 # doesn't make sense - unless we are starting with 'sudo' command.
406 409 if ' ' in self.lbuf.lstrip() and not self.lbuf.lstrip().startswith('sudo'):
407 410 return []
408 411 text = os.path.expanduser(text)
409 412 aliases = self.alias_table.keys()
410 413 if text == "":
411 414 return aliases
412 415 else:
413 416 return [alias for alias in aliases if alias.startswith(text)]
414 417
415 418 def python_matches(self,text):
416 419 """Match attributes or global python names"""
417 420
418 421 #print 'Completer->python_matches, txt=<%s>' % text # dbg
419 422 if "." in text:
420 423 try:
421 424 matches = self.attr_matches(text)
422 425 if text.endswith('.') and self.omit__names:
423 426 if self.omit__names == 1:
424 427 # true if txt is _not_ a __ name, false otherwise:
425 428 no__name = (lambda txt:
426 429 re.match(r'.*\.__.*?__',txt) is None)
427 430 else:
428 431 # true if txt is _not_ a _ name, false otherwise:
429 432 no__name = (lambda txt:
430 433 re.match(r'.*\._.*?',txt) is None)
431 434 matches = filter(no__name, matches)
432 435 except NameError:
433 436 # catches <undefined attributes>.<tab>
434 437 matches = []
435 438 else:
436 439 matches = self.global_matches(text)
437 440 # this is so completion finds magics when automagic is on:
438 441 if (matches == [] and
439 442 not text.startswith(os.sep) and
440 443 not ' ' in self.lbuf):
441 444 matches = self.attr_matches(self.magic_prefix+text)
442 445 return matches
443 446
444 447 def _default_arguments(self, obj):
445 448 """Return the list of default arguments of obj if it is callable,
446 449 or empty list otherwise."""
447 450
448 451 if not (inspect.isfunction(obj) or inspect.ismethod(obj)):
449 452 # for classes, check for __init__,__new__
450 453 if inspect.isclass(obj):
451 454 obj = (getattr(obj,'__init__',None) or
452 455 getattr(obj,'__new__',None))
453 456 # for all others, check if they are __call__able
454 457 elif hasattr(obj, '__call__'):
455 458 obj = obj.__call__
456 459 # XXX: is there a way to handle the builtins ?
457 460 try:
458 461 args,_,_1,defaults = inspect.getargspec(obj)
459 462 if defaults:
460 463 return args[-len(defaults):]
461 464 except TypeError: pass
462 465 return []
463 466
464 467 def python_func_kw_matches(self,text):
465 468 """Match named parameters (kwargs) of the last open function"""
466 469
467 470 if "." in text: # a parameter cannot be dotted
468 471 return []
469 472 try: regexp = self.__funcParamsRegex
470 473 except AttributeError:
471 474 regexp = self.__funcParamsRegex = re.compile(r'''
472 475 '.*?' | # single quoted strings or
473 476 ".*?" | # double quoted strings or
474 477 \w+ | # identifier
475 478 \S # other characters
476 479 ''', re.VERBOSE | re.DOTALL)
477 480 # 1. find the nearest identifier that comes before an unclosed
478 481 # parenthesis e.g. for "foo (1+bar(x), pa", the candidate is "foo"
479 482 tokens = regexp.findall(self.get_line_buffer())
480 483 tokens.reverse()
481 484 iterTokens = iter(tokens); openPar = 0
482 485 for token in iterTokens:
483 486 if token == ')':
484 487 openPar -= 1
485 488 elif token == '(':
486 489 openPar += 1
487 490 if openPar > 0:
488 491 # found the last unclosed parenthesis
489 492 break
490 493 else:
491 494 return []
492 495 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
493 496 ids = []
494 497 isId = re.compile(r'\w+$').match
495 498 while True:
496 499 try:
497 500 ids.append(iterTokens.next())
498 501 if not isId(ids[-1]):
499 502 ids.pop(); break
500 503 if not iterTokens.next() == '.':
501 504 break
502 505 except StopIteration:
503 506 break
504 507 # lookup the candidate callable matches either using global_matches
505 508 # or attr_matches for dotted names
506 509 if len(ids) == 1:
507 510 callableMatches = self.global_matches(ids[0])
508 511 else:
509 512 callableMatches = self.attr_matches('.'.join(ids[::-1]))
510 513 argMatches = []
511 514 for callableMatch in callableMatches:
512 515 try: namedArgs = self._default_arguments(eval(callableMatch,
513 516 self.namespace))
514 517 except: continue
515 518 for namedArg in namedArgs:
516 519 if namedArg.startswith(text):
517 520 argMatches.append("%s=" %namedArg)
518 521 return argMatches
519 522
520 523 def dispatch_custom_completer(self,text):
521 524 #print "Custom! '%s' %s" % (text, self.custom_completers) # dbg
522 525 line = self.full_lbuf
523 526 if not line.strip():
524 527 return None
525 528
526 529 event = Struct()
527 530 event.line = line
528 531 event.symbol = text
529 532 cmd = line.split(None,1)[0]
530 533 event.command = cmd
531 534 #print "\ncustom:{%s]\n" % event # dbg
532 535
533 536 # for foo etc, try also to find completer for %foo
534 537 if not cmd.startswith(self.magic_escape):
535 538 try_magic = self.custom_completers.s_matches(
536 539 self.magic_escape + cmd)
537 540 else:
538 541 try_magic = []
539 542
540 543
541 544 for c in itertools.chain(
542 545 self.custom_completers.s_matches(cmd),
543 546 try_magic,
544 547 self.custom_completers.flat_matches(self.lbuf)):
545 548 #print "try",c # dbg
546 549 try:
547 550 res = c(event)
548 551 # first, try case sensitive match
549 552 withcase = [r for r in res if r.startswith(text)]
550 553 if withcase:
551 554 return withcase
552 555 # if none, then case insensitive ones are ok too
553 556 return [r for r in res if r.lower().startswith(text.lower())]
554 557 except ipapi.TryNext:
555 558 pass
556 559
557 560 return None
558 561
559 562 def complete(self, text, state,line_buffer=None):
560 563 """Return the next possible completion for 'text'.
561 564
562 565 This is called successively with state == 0, 1, 2, ... until it
563 566 returns None. The completion should begin with 'text'.
564 567
565 568 :Keywords:
566 569 - line_buffer: string
567 570 If not given, the completer attempts to obtain the current line buffer
568 571 via readline. This keyword allows clients which are requesting for
569 572 text completions in non-readline contexts to inform the completer of
570 573 the entire text.
571 574 """
572 575
573 576 #print '\n*** COMPLETE: <%s> (%s)' % (text,state) # dbg
574 577
575 578 # if there is only a tab on a line with only whitespace, instead
576 579 # of the mostly useless 'do you want to see all million
577 580 # completions' message, just do the right thing and give the user
578 581 # his tab! Incidentally, this enables pasting of tabbed text from
579 582 # an editor (as long as autoindent is off).
580 583
581 584 # It should be noted that at least pyreadline still shows
582 585 # file completions - is there a way around it?
583 586
584 587 # don't apply this on 'dumb' terminals, such as emacs buffers, so we
585 588 # don't interfere with their own tab-completion mechanism.
586 589 if line_buffer is None:
587 590 self.full_lbuf = self.get_line_buffer()
588 591 else:
589 592 self.full_lbuf = line_buffer
590 593
591 594 if not (self.dumb_terminal or self.full_lbuf.strip()):
592 595 self.readline.insert_text('\t')
593 596 return None
594 597
595 598 magic_escape = self.magic_escape
596 599 magic_prefix = self.magic_prefix
597 600
598 601 self.lbuf = self.full_lbuf[:self.get_endidx()]
599 602
600 603 try:
601 604 if text.startswith(magic_escape):
602 605 text = text.replace(magic_escape,magic_prefix)
603 606 elif text.startswith('~'):
604 607 text = os.path.expanduser(text)
605 608 if state == 0:
606 609 custom_res = self.dispatch_custom_completer(text)
607 610 if custom_res is not None:
608 611 # did custom completers produce something?
609 612 self.matches = custom_res
610 613 else:
611 614 # Extend the list of completions with the results of each
612 615 # matcher, so we return results to the user from all
613 616 # namespaces.
614 617 if self.merge_completions:
615 618 self.matches = []
616 619 for matcher in self.matchers:
617 620 self.matches.extend(matcher(text))
618 621 else:
619 622 for matcher in self.matchers:
620 623 self.matches = matcher(text)
621 624 if self.matches:
622 625 break
623 626 def uniq(alist):
624 627 set = {}
625 628 return [set.setdefault(e,e) for e in alist if e not in set]
626 629 self.matches = uniq(self.matches)
627 630 try:
628 631 ret = self.matches[state].replace(magic_prefix,magic_escape)
629 632 return ret
630 633 except IndexError:
631 634 return None
632 635 except:
633 636 #from IPython.ultraTB import AutoFormattedTB; # dbg
634 637 #tb=AutoFormattedTB('Verbose');tb() #dbg
635 638
636 639 # If completion fails, don't annoy the user.
637 640 return None
@@ -1,104 +1,102 b''
1 1 # encoding: utf-8
2 2
3 3 """This is the official entry point to IPython's configuration system. """
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #-------------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-------------------------------------------------------------------------------
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Imports
16 16 #-------------------------------------------------------------------------------
17 17
18 18 import os
19 from IPython.config.cutils import get_home_dir, get_ipython_dir
19 from os.path import join as pjoin
20
21 from IPython.genutils import get_home_dir, get_ipython_dir
20 22 from IPython.external.configobj import ConfigObj
21 23
22 # Traitlets config imports
23 from IPython.config import traitlets
24 from IPython.config.config import *
25 from traitlets import *
26 24
27 25 class ConfigObjManager(object):
28 26
29 27 def __init__(self, configObj, filename):
30 28 self.current = configObj
31 29 self.current.indent_type = ' '
32 30 self.filename = filename
33 31 # self.write_default_config_file()
34 32
35 33 def get_config_obj(self):
36 34 return self.current
37 35
38 36 def update_config_obj(self, newConfig):
39 37 self.current.merge(newConfig)
40 38
41 39 def update_config_obj_from_file(self, filename):
42 40 newConfig = ConfigObj(filename, file_error=False)
43 41 self.current.merge(newConfig)
44 42
45 43 def update_config_obj_from_default_file(self, ipythondir=None):
46 44 fname = self.resolve_file_path(self.filename, ipythondir)
47 45 self.update_config_obj_from_file(fname)
48 46
49 47 def write_config_obj_to_file(self, filename):
50 48 f = open(filename, 'w')
51 49 self.current.write(f)
52 50 f.close()
53 51
54 52 def write_default_config_file(self):
55 53 ipdir = get_ipython_dir()
56 fname = ipdir + '/' + self.filename
54 fname = pjoin(ipdir, self.filename)
57 55 if not os.path.isfile(fname):
58 56 print "Writing the configuration file to: " + fname
59 57 self.write_config_obj_to_file(fname)
60 58
61 59 def _import(self, key):
62 60 package = '.'.join(key.split('.')[0:-1])
63 61 obj = key.split('.')[-1]
64 62 execString = 'from %s import %s' % (package, obj)
65 63 exec execString
66 64 exec 'temp = %s' % obj
67 65 return temp
68 66
69 67 def resolve_file_path(self, filename, ipythondir = None):
70 68 """Resolve filenames into absolute paths.
71 69
72 70 This function looks in the following directories in order:
73 71
74 72 1. In the current working directory or by absolute path with ~ expanded
75 73 2. In ipythondir if that is set
76 74 3. In the IPYTHONDIR environment variable if it exists
77 75 4. In the ~/.ipython directory
78 76
79 77 Note: The IPYTHONDIR is also used by the trunk version of IPython so
80 78 changing it will also affect it was well.
81 79 """
82 80
83 81 # In cwd or by absolute path with ~ expanded
84 82 trythis = os.path.expanduser(filename)
85 83 if os.path.isfile(trythis):
86 84 return trythis
87 85
88 86 # In ipythondir if it is set
89 87 if ipythondir is not None:
90 trythis = ipythondir + '/' + filename
88 trythis = pjoin(ipythondir, filename)
91 89 if os.path.isfile(trythis):
92 90 return trythis
93 91
94 trythis = get_ipython_dir() + '/' + filename
92 trythis = pjoin(get_ipython_dir(), filename)
95 93 if os.path.isfile(trythis):
96 94 return trythis
97 95
98 96 return None
99 97
100 98
101 99
102 100
103 101
104 102
@@ -1,99 +1,34 b''
1 1 # encoding: utf-8
2 2
3 3 """Configuration-related utilities for all IPython."""
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #-------------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-------------------------------------------------------------------------------
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Imports
16 16 #-------------------------------------------------------------------------------
17 17
18 18 import os
19 19 import sys
20 20
21 21 #---------------------------------------------------------------------------
22 22 # Normal code begins
23 23 #---------------------------------------------------------------------------
24 24
25 class HomeDirError(Exception):
26 pass
27
28 def get_home_dir():
29 """Return the closest possible equivalent to a 'home' directory.
30
31 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
32
33 Currently only Posix and NT are implemented, a HomeDirError exception is
34 raised for all other OSes. """
35
36 isdir = os.path.isdir
37 env = os.environ
38 try:
39 homedir = env['HOME']
40 if not isdir(homedir):
41 # in case a user stuck some string which does NOT resolve to a
42 # valid path, it's as good as if we hadn't foud it
43 raise KeyError
44 return homedir
45 except KeyError:
46 if os.name == 'posix':
47 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
48 elif os.name == 'nt':
49 # For some strange reason, win9x returns 'nt' for os.name.
50 try:
51 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
52 if not isdir(homedir):
53 homedir = os.path.join(env['USERPROFILE'])
54 if not isdir(homedir):
55 raise HomeDirError
56 return homedir
57 except:
58 try:
59 # Use the registry to get the 'My Documents' folder.
60 import _winreg as wreg
61 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
62 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
63 homedir = wreg.QueryValueEx(key,'Personal')[0]
64 key.Close()
65 if not isdir(homedir):
66 e = ('Invalid "Personal" folder registry key '
67 'typically "My Documents".\n'
68 'Value: %s\n'
69 'This is not a valid directory on your system.' %
70 homedir)
71 raise HomeDirError(e)
72 return homedir
73 except HomeDirError:
74 raise
75 except:
76 return 'C:\\'
77 elif os.name == 'dos':
78 # Desperate, may do absurd things in classic MacOS. May work under DOS.
79 return 'C:\\'
80 else:
81 raise HomeDirError,'support for your operating system not implemented.'
82
83 def get_ipython_dir():
84 ipdir_def = '.ipython'
85 home_dir = get_home_dir()
86 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
87 os.path.join(home_dir,ipdir_def)))
88 return ipdir
89
90 25 def import_item(key):
91 26 """
92 27 Import and return bar given the string foo.bar.
93 28 """
94 29 package = '.'.join(key.split('.')[0:-1])
95 30 obj = key.split('.')[-1]
96 31 execString = 'from %s import %s' % (package, obj)
97 32 exec execString
98 33 exec 'temp = %s' % obj
99 34 return temp
@@ -1,526 +1,526 b''
1 1 """Module for interactive demos using IPython.
2 2
3 3 This module implements a few classes for running Python scripts interactively
4 4 in IPython for demonstrations. With very simple markup (a few tags in
5 5 comments), you can control points where the script stops executing and returns
6 6 control to IPython.
7 7
8 8
9 9 Provided classes
10 10 ================
11 11
12 12 The classes are (see their docstrings for further details):
13 13
14 14 - Demo: pure python demos
15 15
16 16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 17 typed interactively (so magics work, as well as any other special syntax you
18 18 may have added via input prefilters).
19 19
20 20 - LineDemo: single-line version of the Demo class. These demos are executed
21 21 one line at a time, and require no markup.
22 22
23 23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 24 executed a line at a time, but processed via IPython).
25 25
26 26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 27 declares an empty marquee and a pre_cmd that clears the screen before each
28 28 block (see Subclassing below).
29 29
30 30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 31 classes.
32 32
33 33
34 34 Subclassing
35 35 ===========
36 36
37 37 The classes here all include a few methods meant to make customization by
38 38 subclassing more convenient. Their docstrings below have some more details:
39 39
40 40 - marquee(): generates a marquee to provide visible on-screen markers at each
41 41 block start and end.
42 42
43 43 - pre_cmd(): run right before the execution of each block.
44 44
45 45 - post_cmd(): run right after the execution of each block. If the block
46 46 raises an exception, this is NOT called.
47 47
48 48
49 49 Operation
50 50 =========
51 51
52 52 The file is run in its own empty namespace (though you can pass it a string of
53 53 arguments as if in a command line environment, and it will see those as
54 54 sys.argv). But at each stop, the global IPython namespace is updated with the
55 55 current internal demo namespace, so you can work interactively with the data
56 56 accumulated so far.
57 57
58 58 By default, each block of code is printed (with syntax highlighting) before
59 59 executing it and you have to confirm execution. This is intended to show the
60 60 code to an audience first so you can discuss it, and only proceed with
61 61 execution once you agree. There are a few tags which allow you to modify this
62 62 behavior.
63 63
64 64 The supported tags are:
65 65
66 66 # <demo> stop
67 67
68 68 Defines block boundaries, the points where IPython stops execution of the
69 69 file and returns to the interactive prompt.
70 70
71 71 You can optionally mark the stop tag with extra dashes before and after the
72 72 word 'stop', to help visually distinguish the blocks in a text editor:
73 73
74 74 # <demo> --- stop ---
75 75
76 76
77 77 # <demo> silent
78 78
79 79 Make a block execute silently (and hence automatically). Typically used in
80 80 cases where you have some boilerplate or initialization code which you need
81 81 executed but do not want to be seen in the demo.
82 82
83 83 # <demo> auto
84 84
85 85 Make a block execute automatically, but still being printed. Useful for
86 86 simple code which does not warrant discussion, since it avoids the extra
87 87 manual confirmation.
88 88
89 89 # <demo> auto_all
90 90
91 91 This tag can _only_ be in the first block, and if given it overrides the
92 92 individual auto tags to make the whole demo fully automatic (no block asks
93 93 for confirmation). It can also be given at creation time (or the attribute
94 94 set later) to override what's in the file.
95 95
96 96 While _any_ python file can be run as a Demo instance, if there are no stop
97 97 tags the whole file will run in a single block (no different that calling
98 98 first %pycat and then %run). The minimal markup to make this useful is to
99 99 place a set of stop tags; the other tags are only there to let you fine-tune
100 100 the execution.
101 101
102 102 This is probably best explained with the simple example file below. You can
103 103 copy this into a file named ex_demo.py, and try running it via:
104 104
105 105 from IPython.demo import Demo
106 106 d = Demo('ex_demo.py')
107 107 d() <--- Call the d object (omit the parens if you have autocall set to 2).
108 108
109 109 Each time you call the demo object, it runs the next block. The demo object
110 110 has a few useful methods for navigation, like again(), edit(), jump(), seek()
111 111 and back(). It can be reset for a new run via reset() or reloaded from disk
112 112 (in case you've edited the source) via reload(). See their docstrings below.
113 113
114 114
115 115 Example
116 116 =======
117 117
118 118 The following is a very simple example of a valid demo file.
119 119
120 120 #################### EXAMPLE DEMO <ex_demo.py> ###############################
121 121 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
122 122
123 123 print 'Hello, welcome to an interactive IPython demo.'
124 124
125 125 # The mark below defines a block boundary, which is a point where IPython will
126 126 # stop execution and return to the interactive prompt. The dashes are actually
127 127 # optional and used only as a visual aid to clearly separate blocks while
128 128 editing the demo code.
129 129 # <demo> stop
130 130
131 131 x = 1
132 132 y = 2
133 133
134 134 # <demo> stop
135 135
136 136 # the mark below makes this block as silent
137 137 # <demo> silent
138 138
139 139 print 'This is a silent block, which gets executed but not printed.'
140 140
141 141 # <demo> stop
142 142 # <demo> auto
143 143 print 'This is an automatic block.'
144 144 print 'It is executed without asking for confirmation, but printed.'
145 145 z = x+y
146 146
147 147 print 'z=',x
148 148
149 149 # <demo> stop
150 150 # This is just another normal block.
151 151 print 'z is now:', z
152 152
153 153 print 'bye!'
154 154 ################### END EXAMPLE DEMO <ex_demo.py> ############################
155 155 """
156 156
157 157 #*****************************************************************************
158 158 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
159 159 #
160 160 # Distributed under the terms of the BSD License. The full license is in
161 161 # the file COPYING, distributed as part of this software.
162 162 #
163 163 #*****************************************************************************
164 164
165 165 import exceptions
166 166 import os
167 167 import re
168 168 import shlex
169 169 import sys
170 170
171 171 from IPython.PyColorize import Parser
172 172 from IPython.genutils import marquee, file_read, file_readlines
173 173
174 174 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
175 175
176 176 class DemoError(exceptions.Exception): pass
177 177
178 178 def re_mark(mark):
179 179 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
180 180
181 181 class Demo(object):
182 182
183 re_stop = re_mark('-?\s?stop\s?-?')
183 re_stop = re_mark('-*\s?stop\s?-*')
184 184 re_silent = re_mark('silent')
185 185 re_auto = re_mark('auto')
186 186 re_auto_all = re_mark('auto_all')
187 187
188 188 def __init__(self,fname,arg_str='',auto_all=None):
189 189 """Make a new demo object. To run the demo, simply call the object.
190 190
191 191 See the module docstring for full details and an example (you can use
192 192 IPython.Demo? in IPython to see it).
193 193
194 194 Inputs:
195 195
196 196 - fname = filename.
197 197
198 198 Optional inputs:
199 199
200 200 - arg_str(''): a string of arguments, internally converted to a list
201 201 just like sys.argv, so the demo script can see a similar
202 202 environment.
203 203
204 204 - auto_all(None): global flag to run all blocks automatically without
205 205 confirmation. This attribute overrides the block-level tags and
206 206 applies to the whole demo. It is an attribute of the object, and
207 207 can be changed at runtime simply by reassigning it to a boolean
208 208 value.
209 209 """
210 210
211 211 self.fname = fname
212 212 self.sys_argv = [fname] + shlex.split(arg_str)
213 213 self.auto_all = auto_all
214 214
215 215 # get a few things from ipython. While it's a bit ugly design-wise,
216 216 # it ensures that things like color scheme and the like are always in
217 217 # sync with the ipython mode being used. This class is only meant to
218 218 # be used inside ipython anyways, so it's OK.
219 219 self.ip_ns = __IPYTHON__.user_ns
220 220 self.ip_colorize = __IPYTHON__.pycolorize
221 221 self.ip_showtb = __IPYTHON__.showtraceback
222 222 self.ip_runlines = __IPYTHON__.runlines
223 223 self.shell = __IPYTHON__
224 224
225 225 # load user data and initialize data structures
226 226 self.reload()
227 227
228 228 def reload(self):
229 229 """Reload source from disk and initialize state."""
230 230 # read data and parse into blocks
231 231 self.src = file_read(self.fname)
232 232 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
233 233 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
234 234 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
235 235
236 236 # if auto_all is not given (def. None), we read it from the file
237 237 if self.auto_all is None:
238 238 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
239 239 else:
240 240 self.auto_all = bool(self.auto_all)
241 241
242 242 # Clean the sources from all markup so it doesn't get displayed when
243 243 # running the demo
244 244 src_blocks = []
245 245 auto_strip = lambda s: self.re_auto.sub('',s)
246 246 for i,b in enumerate(src_b):
247 247 if self._auto[i]:
248 248 src_blocks.append(auto_strip(b))
249 249 else:
250 250 src_blocks.append(b)
251 251 # remove the auto_all marker
252 252 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
253 253
254 254 self.nblocks = len(src_blocks)
255 255 self.src_blocks = src_blocks
256 256
257 257 # also build syntax-highlighted source
258 258 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
259 259
260 260 # ensure clean namespace and seek offset
261 261 self.reset()
262 262
263 263 def reset(self):
264 264 """Reset the namespace and seek pointer to restart the demo"""
265 265 self.user_ns = {}
266 266 self.finished = False
267 267 self.block_index = 0
268 268
269 269 def _validate_index(self,index):
270 270 if index<0 or index>=self.nblocks:
271 271 raise ValueError('invalid block index %s' % index)
272 272
273 273 def _get_index(self,index):
274 274 """Get the current block index, validating and checking status.
275 275
276 276 Returns None if the demo is finished"""
277 277
278 278 if index is None:
279 279 if self.finished:
280 280 print 'Demo finished. Use reset() if you want to rerun it.'
281 281 return None
282 282 index = self.block_index
283 283 else:
284 284 self._validate_index(index)
285 285 return index
286 286
287 287 def seek(self,index):
288 288 """Move the current seek pointer to the given block.
289 289
290 290 You can use negative indices to seek from the end, with identical
291 291 semantics to those of Python lists."""
292 292 if index<0:
293 293 index = self.nblocks + index
294 294 self._validate_index(index)
295 295 self.block_index = index
296 296 self.finished = False
297 297
298 298 def back(self,num=1):
299 299 """Move the seek pointer back num blocks (default is 1)."""
300 300 self.seek(self.block_index-num)
301 301
302 302 def jump(self,num=1):
303 303 """Jump a given number of blocks relative to the current one.
304 304
305 305 The offset can be positive or negative, defaults to 1."""
306 306 self.seek(self.block_index+num)
307 307
308 308 def again(self):
309 309 """Move the seek pointer back one block and re-execute."""
310 310 self.back(1)
311 311 self()
312 312
313 313 def edit(self,index=None):
314 314 """Edit a block.
315 315
316 316 If no number is given, use the last block executed.
317 317
318 318 This edits the in-memory copy of the demo, it does NOT modify the
319 319 original source file. If you want to do that, simply open the file in
320 320 an editor and use reload() when you make changes to the file. This
321 321 method is meant to let you change a block during a demonstration for
322 322 explanatory purposes, without damaging your original script."""
323 323
324 324 index = self._get_index(index)
325 325 if index is None:
326 326 return
327 327 # decrease the index by one (unless we're at the very beginning), so
328 328 # that the default demo.edit() call opens up the sblock we've last run
329 329 if index>0:
330 330 index -= 1
331 331
332 332 filename = self.shell.mktempfile(self.src_blocks[index])
333 333 self.shell.hooks.editor(filename,1)
334 334 new_block = file_read(filename)
335 335 # update the source and colored block
336 336 self.src_blocks[index] = new_block
337 337 self.src_blocks_colored[index] = self.ip_colorize(new_block)
338 338 self.block_index = index
339 339 # call to run with the newly edited index
340 340 self()
341 341
342 342 def show(self,index=None):
343 343 """Show a single block on screen"""
344 344
345 345 index = self._get_index(index)
346 346 if index is None:
347 347 return
348 348
349 349 print self.marquee('<%s> block # %s (%s remaining)' %
350 350 (self.fname,index,self.nblocks-index-1))
351 351 sys.stdout.write(self.src_blocks_colored[index])
352 352 sys.stdout.flush()
353 353
354 354 def show_all(self):
355 355 """Show entire demo on screen, block by block"""
356 356
357 357 fname = self.fname
358 358 nblocks = self.nblocks
359 359 silent = self._silent
360 360 marquee = self.marquee
361 361 for index,block in enumerate(self.src_blocks_colored):
362 362 if silent[index]:
363 363 print marquee('<%s> SILENT block # %s (%s remaining)' %
364 364 (fname,index,nblocks-index-1))
365 365 else:
366 366 print marquee('<%s> block # %s (%s remaining)' %
367 367 (fname,index,nblocks-index-1))
368 368 print block,
369 369 sys.stdout.flush()
370 370
371 371 def runlines(self,source):
372 372 """Execute a string with one or more lines of code"""
373 373
374 374 exec source in self.user_ns
375 375
376 376 def __call__(self,index=None):
377 377 """run a block of the demo.
378 378
379 379 If index is given, it should be an integer >=1 and <= nblocks. This
380 380 means that the calling convention is one off from typical Python
381 381 lists. The reason for the inconsistency is that the demo always
382 382 prints 'Block n/N, and N is the total, so it would be very odd to use
383 383 zero-indexing here."""
384 384
385 385 index = self._get_index(index)
386 386 if index is None:
387 387 return
388 388 try:
389 389 marquee = self.marquee
390 390 next_block = self.src_blocks[index]
391 391 self.block_index += 1
392 392 if self._silent[index]:
393 393 print marquee('Executing silent block # %s (%s remaining)' %
394 394 (index,self.nblocks-index-1))
395 395 else:
396 396 self.pre_cmd()
397 397 self.show(index)
398 398 if self.auto_all or self._auto[index]:
399 399 print marquee('output:')
400 400 else:
401 401 print marquee('Press <q> to quit, <Enter> to execute...'),
402 402 ans = raw_input().strip()
403 403 if ans:
404 404 print marquee('Block NOT executed')
405 405 return
406 406 try:
407 407 save_argv = sys.argv
408 408 sys.argv = self.sys_argv
409 409 self.runlines(next_block)
410 410 self.post_cmd()
411 411 finally:
412 412 sys.argv = save_argv
413 413
414 414 except:
415 415 self.ip_showtb(filename=self.fname)
416 416 else:
417 417 self.ip_ns.update(self.user_ns)
418 418
419 419 if self.block_index == self.nblocks:
420 420 mq1 = self.marquee('END OF DEMO')
421 421 if mq1:
422 422 # avoid spurious prints if empty marquees are used
423 423 print
424 424 print mq1
425 425 print self.marquee('Use reset() if you want to rerun it.')
426 426 self.finished = True
427 427
428 428 # These methods are meant to be overridden by subclasses who may wish to
429 429 # customize the behavior of of their demos.
430 430 def marquee(self,txt='',width=78,mark='*'):
431 431 """Return the input string centered in a 'marquee'."""
432 432 return marquee(txt,width,mark)
433 433
434 434 def pre_cmd(self):
435 435 """Method called before executing each block."""
436 436 pass
437 437
438 438 def post_cmd(self):
439 439 """Method called after executing each block."""
440 440 pass
441 441
442 442
443 443 class IPythonDemo(Demo):
444 444 """Class for interactive demos with IPython's input processing applied.
445 445
446 446 This subclasses Demo, but instead of executing each block by the Python
447 447 interpreter (via exec), it actually calls IPython on it, so that any input
448 448 filters which may be in place are applied to the input block.
449 449
450 450 If you have an interactive environment which exposes special input
451 451 processing, you can use this class instead to write demo scripts which
452 452 operate exactly as if you had typed them interactively. The default Demo
453 453 class requires the input to be valid, pure Python code.
454 454 """
455 455
456 456 def runlines(self,source):
457 457 """Execute a string with one or more lines of code"""
458 458
459 459 self.shell.runlines(source)
460 460
461 461 class LineDemo(Demo):
462 462 """Demo where each line is executed as a separate block.
463 463
464 464 The input script should be valid Python code.
465 465
466 466 This class doesn't require any markup at all, and it's meant for simple
467 467 scripts (with no nesting or any kind of indentation) which consist of
468 468 multiple lines of input to be executed, one at a time, as if they had been
469 469 typed in the interactive prompt."""
470 470
471 471 def reload(self):
472 472 """Reload source from disk and initialize state."""
473 473 # read data and parse into blocks
474 474 src_b = [l for l in file_readlines(self.fname) if l.strip()]
475 475 nblocks = len(src_b)
476 476 self.src = os.linesep.join(file_readlines(self.fname))
477 477 self._silent = [False]*nblocks
478 478 self._auto = [True]*nblocks
479 479 self.auto_all = True
480 480 self.nblocks = nblocks
481 481 self.src_blocks = src_b
482 482
483 483 # also build syntax-highlighted source
484 484 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
485 485
486 486 # ensure clean namespace and seek offset
487 487 self.reset()
488 488
489 489
490 490 class IPythonLineDemo(IPythonDemo,LineDemo):
491 491 """Variant of the LineDemo class whose input is processed by IPython."""
492 492 pass
493 493
494 494
495 495 class ClearMixin(object):
496 496 """Use this mixin to make Demo classes with less visual clutter.
497 497
498 498 Demos using this mixin will clear the screen before every block and use
499 499 blank marquees.
500 500
501 501 Note that in order for the methods defined here to actually override those
502 502 of the classes it's mixed with, it must go /first/ in the inheritance
503 503 tree. For example:
504 504
505 505 class ClearIPDemo(ClearMixin,IPythonDemo): pass
506 506
507 507 will provide an IPythonDemo class with the mixin's features.
508 508 """
509 509
510 510 def marquee(self,txt='',width=78,mark='*'):
511 511 """Blank marquee that returns '' no matter what the input."""
512 512 return ''
513 513
514 514 def pre_cmd(self):
515 515 """Method called before executing each block.
516 516
517 517 This one simply clears the screen."""
518 518 os.system('clear')
519 519
520 520
521 521 class ClearDemo(ClearMixin,Demo):
522 522 pass
523 523
524 524
525 525 class ClearIPDemo(ClearMixin,IPythonDemo):
526 526 pass
@@ -1,168 +1,179 b''
1 1 # Addapted from killableprocess.py.
2 2 #______________________________________________________________________________
3 3 #
4 4 # killableprocess - subprocesses which can be reliably killed
5 5 #
6 6 # Parts of this module are copied from the subprocess.py file contained
7 7 # in the Python distribution.
8 8 #
9 9 # Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
10 10 #
11 11 # Additions and modifications written by Benjamin Smedberg
12 12 # <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
13 13 # <http://www.mozilla.org/>
14 14 #
15 15 # By obtaining, using, and/or copying this software and/or its
16 16 # associated documentation, you agree that you have read, understood,
17 17 # and will comply with the following terms and conditions:
18 18 #
19 19 # Permission to use, copy, modify, and distribute this software and
20 20 # its associated documentation for any purpose and without fee is
21 21 # hereby granted, provided that the above copyright notice appears in
22 22 # all copies, and that both that copyright notice and this permission
23 23 # notice appear in supporting documentation, and that the name of the
24 24 # author not be used in advertising or publicity pertaining to
25 25 # distribution of the software without specific, written prior
26 26 # permission.
27 27 #
28 28 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
29 29 # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
30 30 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
31 31 # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
32 32 # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
33 33 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
34 34 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 35
36 36 r"""killableprocess - Subprocesses which can be reliably killed
37 37
38 38 This module is a subclass of the builtin "subprocess" module. It allows
39 39 processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method.
40 40
41 41 It also adds a timeout argument to Wait() for a limited period of time before
42 42 forcefully killing the process.
43 43
44 44 Note: On Windows, this module requires Windows 2000 or higher (no support for
45 45 Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with
46 46 Python 2.5+ or available from http://python.net/crew/theller/ctypes/
47 47 """
48 48
49 49 import subprocess
50 50 from subprocess import PIPE
51 51 import sys
52 52 import os
53 import time
54 53 import types
55 54
56 55 try:
57 56 from subprocess import CalledProcessError
58 57 except ImportError:
59 58 # Python 2.4 doesn't implement CalledProcessError
60 59 class CalledProcessError(Exception):
61 60 """This exception is raised when a process run by check_call() returns
62 61 a non-zero exit status. The exit status will be stored in the
63 62 returncode attribute."""
64 63 def __init__(self, returncode, cmd):
65 64 self.returncode = returncode
66 65 self.cmd = cmd
67 66 def __str__(self):
68 67 return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
69 68
70 69 mswindows = (sys.platform == "win32")
71 70
71 skip = False
72
72 73 if mswindows:
73 import winprocess
74 import platform
75 if platform.uname()[3] == '' or platform.uname()[3] > '6.0.6000':
76 # Killable process does not work under vista when starting for
77 # something else than cmd.
78 skip = True
79 else:
80 import winprocess
74 81 else:
75 82 import signal
76 83
77 84 if not mswindows:
78 85 def DoNothing(*args):
79 86 pass
80 87
81 class Popen(subprocess.Popen):
88
89 if skip:
90 Popen = subprocess.Popen
91 else:
92 class Popen(subprocess.Popen):
82 93 if not mswindows:
83 94 # Override __init__ to set a preexec_fn
84 95 def __init__(self, *args, **kwargs):
85 96 if len(args) >= 7:
86 97 raise Exception("Arguments preexec_fn and after must be passed by keyword.")
87 98
88 99 real_preexec_fn = kwargs.pop("preexec_fn", None)
89 100 def setpgid_preexec_fn():
90 101 os.setpgid(0, 0)
91 102 if real_preexec_fn:
92 103 apply(real_preexec_fn)
93 104
94 105 kwargs['preexec_fn'] = setpgid_preexec_fn
95 106
96 107 subprocess.Popen.__init__(self, *args, **kwargs)
97 108
98 109 if mswindows:
99 110 def _execute_child(self, args, executable, preexec_fn, close_fds,
100 111 cwd, env, universal_newlines, startupinfo,
101 112 creationflags, shell,
102 113 p2cread, p2cwrite,
103 114 c2pread, c2pwrite,
104 115 errread, errwrite):
105 116 if not isinstance(args, types.StringTypes):
106 117 args = subprocess.list2cmdline(args)
107 118
108 119 if startupinfo is None:
109 120 startupinfo = winprocess.STARTUPINFO()
110 121
111 122 if None not in (p2cread, c2pwrite, errwrite):
112 123 startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
113 124
114 125 startupinfo.hStdInput = int(p2cread)
115 126 startupinfo.hStdOutput = int(c2pwrite)
116 127 startupinfo.hStdError = int(errwrite)
117 128 if shell:
118 129 startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW
119 130 startupinfo.wShowWindow = winprocess.SW_HIDE
120 131 comspec = os.environ.get("COMSPEC", "cmd.exe")
121 132 args = comspec + " /c " + args
122 133
123 134 # We create a new job for this process, so that we can kill
124 135 # the process and any sub-processes
125 136 self._job = winprocess.CreateJobObject()
126 137
127 138 creationflags |= winprocess.CREATE_SUSPENDED
128 139 creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT
129 140
130 141 hp, ht, pid, tid = winprocess.CreateProcess(
131 142 executable, args,
132 143 None, None, # No special security
133 144 1, # Must inherit handles!
134 145 creationflags,
135 146 winprocess.EnvironmentBlock(env),
136 147 cwd, startupinfo)
137 148
138 149 self._child_created = True
139 150 self._handle = hp
140 151 self._thread = ht
141 152 self.pid = pid
142 153
143 154 winprocess.AssignProcessToJobObject(self._job, hp)
144 155 winprocess.ResumeThread(ht)
145 156
146 157 if p2cread is not None:
147 158 p2cread.Close()
148 159 if c2pwrite is not None:
149 160 c2pwrite.Close()
150 161 if errwrite is not None:
151 162 errwrite.Close()
152 163
153 164 def kill(self, group=True):
154 165 """Kill the process. If group=True, all sub-processes will also be killed."""
155 166 if mswindows:
156 167 if group:
157 168 winprocess.TerminateJobObject(self._job, 127)
158 169 else:
159 170 winprocess.TerminateProcess(self._handle, 127)
160 171 self.returncode = 127
161 172 else:
162 173 if group:
163 174 os.killpg(self.pid, signal.SIGKILL)
164 175 else:
165 176 os.kill(self.pid, signal.SIGKILL)
166 177 self.returncode = -9
167 178
168 179
@@ -1,74 +1,74 b''
1 1 # encoding: utf-8
2 2 """
3 3 Object for encapsulating process execution by using callbacks for stdout,
4 4 stderr and stdin.
5 5 """
6 6 __docformat__ = "restructuredtext en"
7 7
8 8 #-------------------------------------------------------------------------------
9 9 # Copyright (C) 2008 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-------------------------------------------------------------------------------
14 14
15 15 #-------------------------------------------------------------------------------
16 16 # Imports
17 17 #-------------------------------------------------------------------------------
18 18 from killableprocess import Popen, PIPE
19 19 from threading import Thread
20 20 from time import sleep
21 21 import os
22 22
23 23 class PipedProcess(Thread):
24 24 """ Class that encapsulates process execution by using callbacks for
25 25 stdout, stderr and stdin, and providing a reliable way of
26 26 killing it.
27 27 """
28 28
29 29 def __init__(self, command_string, out_callback,
30 30 end_callback=None,):
31 31 """ command_string: the command line executed to start the
32 32 process.
33 33
34 34 out_callback: the python callable called on stdout/stderr.
35 35
36 36 end_callback: an optional callable called when the process
37 37 finishes.
38 38
39 39 These callbacks are called from a different thread as the
40 40 thread from which is started.
41 41 """
42 42 self.command_string = command_string
43 43 self.out_callback = out_callback
44 44 self.end_callback = end_callback
45 45 Thread.__init__(self)
46 46
47 47
48 48 def run(self):
49 49 """ Start the process and hook up the callbacks.
50 50 """
51 51 env = os.environ
52 52 env['TERM'] = 'xterm'
53 process = Popen((self.command_string + ' 2>&1', ), shell=True,
53 process = Popen(self.command_string + ' 2>&1', shell=True,
54 54 env=env,
55 55 universal_newlines=True,
56 56 stdout=PIPE, stdin=PIPE, )
57 57 self.process = process
58 58 while True:
59 59 out_char = process.stdout.read(1)
60 60 if out_char == '':
61 61 if process.poll() is not None:
62 62 # The process has finished
63 63 break
64 64 else:
65 65 # The process is not giving any interesting
66 66 # output. No use polling it immediatly.
67 67 sleep(0.1)
68 68 else:
69 69 self.out_callback(out_char)
70 70
71 71 if self.end_callback is not None:
72 72 self.end_callback()
73 73
74 74
@@ -1,92 +1,76 b''
1 1 """
2 2 Base front end class for all async frontends.
3 3 """
4 4 __docformat__ = "restructuredtext en"
5 5
6 6 #-------------------------------------------------------------------------------
7 7 # Copyright (C) 2008 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 #-------------------------------------------------------------------------------
15 15 # Imports
16 16 #-------------------------------------------------------------------------------
17 import uuid
17 from IPython.external import guid
18 18
19 try:
20 from zope.interface import Interface, Attribute, implements, classProvides
21 except ImportError, e:
22 e.message = """%s
23 ________________________________________________________________________________
24 zope.interface is required to run asynchronous frontends.""" % e.message
25 e.args = (e.message, ) + e.args[1:]
26 19
27 from frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory
28
29 from IPython.kernel.engineservice import IEngineCore
20 from zope.interface import Interface, Attribute, implements, classProvides
21 from twisted.python.failure import Failure
22 from IPython.frontend.frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory
30 23 from IPython.kernel.core.history import FrontEndHistory
31
32 try:
33 from twisted.python.failure import Failure
34 except ImportError, e:
35 e.message = """%s
36 ________________________________________________________________________________
37 twisted is required to run asynchronous frontends.""" % e.message
38 e.args = (e.message, ) + e.args[1:]
39
40
24 from IPython.kernel.engineservice import IEngineCore
41 25
42 26
43 27 class AsyncFrontEndBase(FrontEndBase):
44 28 """
45 29 Overrides FrontEndBase to wrap execute in a deferred result.
46 30 All callbacks are made as callbacks on the deferred result.
47 31 """
48 32
49 33 implements(IFrontEnd)
50 34 classProvides(IFrontEndFactory)
51 35
52 36 def __init__(self, engine=None, history=None):
53 37 assert(engine==None or IEngineCore.providedBy(engine))
54 38 self.engine = IEngineCore(engine)
55 39 if history is None:
56 40 self.history = FrontEndHistory(input_cache=[''])
57 41 else:
58 42 self.history = history
59 43
60 44
61 45 def execute(self, block, blockID=None):
62 46 """Execute the block and return the deferred result.
63 47
64 48 Parameters:
65 49 block : {str, AST}
66 50 blockID : any
67 51 Caller may provide an ID to identify this block.
68 52 result['blockID'] := blockID
69 53
70 54 Result:
71 55 Deferred result of self.interpreter.execute
72 56 """
73 57
74 58 if(not self.is_complete(block)):
75 59 return Failure(Exception("Block is not compilable"))
76 60
77 61 if(blockID == None):
78 blockID = uuid.uuid4() #random UUID
62 blockID = guid.generate()
79 63
80 64 d = self.engine.execute(block)
81 65 d.addCallback(self._add_history, block=block)
82 66 d.addCallbacks(self._add_block_id_for_result,
83 67 errback=self._add_block_id_for_failure,
84 68 callbackArgs=(blockID,),
85 69 errbackArgs=(blockID,))
86 70 d.addBoth(self.update_cell_prompt, blockID=blockID)
87 71 d.addCallbacks(self.render_result,
88 72 errback=self.render_error)
89 73
90 74 return d
91 75
92 76
@@ -1,560 +1,560 b''
1 1 # encoding: utf-8
2 2 # -*- test-case-name: IPython.frontend.cocoa.tests.test_cocoa_frontend -*-
3 3
4 4 """PyObjC classes to provide a Cocoa frontend to the
5 5 IPython.kernel.engineservice.IEngineBase.
6 6
7 7 To add an IPython interpreter to a cocoa app, instantiate an
8 8 IPythonCocoaController in a XIB and connect its textView outlet to an
9 9 NSTextView instance in your UI. That's it.
10 10
11 11 Author: Barry Wark
12 12 """
13 13
14 14 __docformat__ = "restructuredtext en"
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Copyright (C) 2008 The IPython Development Team
18 18 #
19 19 # Distributed under the terms of the BSD License. The full license is in
20 20 # the file COPYING, distributed as part of this software.
21 21 #-----------------------------------------------------------------------------
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Imports
25 25 #-----------------------------------------------------------------------------
26 26
27 27 import sys
28 28 import objc
29 import uuid
29 from IPython.external import guid
30 30
31 31 from Foundation import NSObject, NSMutableArray, NSMutableDictionary,\
32 32 NSLog, NSNotificationCenter, NSMakeRange,\
33 33 NSLocalizedString, NSIntersectionRange,\
34 34 NSString, NSAutoreleasePool
35 35
36 36 from AppKit import NSApplicationWillTerminateNotification, NSBeep,\
37 37 NSTextView, NSRulerView, NSVerticalRuler
38 38
39 39 from pprint import saferepr
40 40
41 41 import IPython
42 42 from IPython.kernel.engineservice import ThreadedEngineService
43 43 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
44 44
45 45 from twisted.internet.threads import blockingCallFromThread
46 46 from twisted.python.failure import Failure
47 47
48 48 #-----------------------------------------------------------------------------
49 49 # Classes to implement the Cocoa frontend
50 50 #-----------------------------------------------------------------------------
51 51
52 52 # TODO:
53 53 # 1. use MultiEngineClient and out-of-process engine rather than
54 54 # ThreadedEngineService?
55 55 # 2. integrate Xgrid launching of engines
56 56
57 57 class AutoreleasePoolWrappedThreadedEngineService(ThreadedEngineService):
58 58 """Wrap all blocks in an NSAutoreleasePool"""
59 59
60 60 def wrapped_execute(self, msg, lines):
61 61 """wrapped_execute"""
62 62 try:
63 63 p = NSAutoreleasePool.alloc().init()
64 64 result = super(AutoreleasePoolWrappedThreadedEngineService,
65 65 self).wrapped_execute(msg, lines)
66 66 finally:
67 67 p.drain()
68 68
69 69 return result
70 70
71 71
72 72
73 73 class Cell(NSObject):
74 74 """
75 75 Representation of the prompts, input and output of a cell in the
76 76 frontend
77 77 """
78 78
79 79 blockNumber = objc.ivar().unsigned_long()
80 80 blockID = objc.ivar()
81 81 inputBlock = objc.ivar()
82 82 output = objc.ivar()
83 83
84 84
85 85
86 86 class CellBlock(object):
87 87 """
88 88 Storage for information about text ranges relating to a single cell
89 89 """
90 90
91 91
92 92 def __init__(self, inputPromptRange, inputRange=None, outputPromptRange=None,
93 93 outputRange=None):
94 94 super(CellBlock, self).__init__()
95 95 self.inputPromptRange = inputPromptRange
96 96 self.inputRange = inputRange
97 97 self.outputPromptRange = outputPromptRange
98 98 self.outputRange = outputRange
99 99
100 100 def update_ranges_for_insertion(self, text, textRange):
101 101 """Update ranges for text insertion at textRange"""
102 102
103 103 for r in [self.inputPromptRange,self.inputRange,
104 104 self.outputPromptRange, self.outputRange]:
105 105 if(r == None):
106 106 continue
107 107 intersection = NSIntersectionRange(r,textRange)
108 108 if(intersection.length == 0): #ranges don't intersect
109 109 if r.location >= textRange.location:
110 110 r.location += len(text)
111 111 else: #ranges intersect
112 112 if(r.location > textRange.location):
113 113 offset = len(text) - intersection.length
114 114 r.length -= offset
115 115 r.location += offset
116 116 elif(r.location == textRange.location):
117 117 r.length += len(text) - intersection.length
118 118 else:
119 119 r.length -= intersection.length
120 120
121 121
122 122 def update_ranges_for_deletion(self, textRange):
123 123 """Update ranges for text deletion at textRange"""
124 124
125 125 for r in [self.inputPromptRange,self.inputRange,
126 126 self.outputPromptRange, self.outputRange]:
127 127 if(r==None):
128 128 continue
129 129 intersection = NSIntersectionRange(r, textRange)
130 130 if(intersection.length == 0): #ranges don't intersect
131 131 if r.location >= textRange.location:
132 132 r.location -= textRange.length
133 133 else: #ranges intersect
134 134 if(r.location > textRange.location):
135 135 offset = intersection.length
136 136 r.length -= offset
137 137 r.location += offset
138 138 elif(r.location == textRange.location):
139 139 r.length += intersection.length
140 140 else:
141 141 r.length -= intersection.length
142 142
143 143 def __repr__(self):
144 144 return 'CellBlock('+ str((self.inputPromptRange,
145 145 self.inputRange,
146 146 self.outputPromptRange,
147 147 self.outputRange)) + ')'
148 148
149 149
150 150
151 151
152 152 class IPythonCocoaController(NSObject, AsyncFrontEndBase):
153 153 userNS = objc.ivar() #mirror of engine.user_ns (key=>str(value))
154 154 waitingForEngine = objc.ivar().bool()
155 155 textView = objc.IBOutlet()
156 156
157 157 def init(self):
158 158 self = super(IPythonCocoaController, self).init()
159 159 AsyncFrontEndBase.__init__(self,
160 160 engine=AutoreleasePoolWrappedThreadedEngineService())
161 161 if(self != None):
162 162 self._common_init()
163 163
164 164 return self
165 165
166 166 def _common_init(self):
167 167 """_common_init"""
168 168
169 169 self.userNS = NSMutableDictionary.dictionary()
170 170 self.waitingForEngine = False
171 171
172 172 self.lines = {}
173 173 self.tabSpaces = 4
174 174 self.tabUsesSpaces = True
175 175 self.currentBlockID = self.next_block_ID()
176 176 self.blockRanges = {} # blockID=>CellBlock
177 177
178 178
179 179 def awakeFromNib(self):
180 180 """awakeFromNib"""
181 181
182 182 self._common_init()
183 183
184 184 # Start the IPython engine
185 185 self.engine.startService()
186 186 NSLog('IPython engine started')
187 187
188 188 # Register for app termination
189 189 nc = NSNotificationCenter.defaultCenter()
190 190 nc.addObserver_selector_name_object_(
191 191 self,
192 192 'appWillTerminate:',
193 193 NSApplicationWillTerminateNotification,
194 194 None)
195 195
196 196 self.textView.setDelegate_(self)
197 197 self.textView.enclosingScrollView().setHasVerticalRuler_(True)
198 198 r = NSRulerView.alloc().initWithScrollView_orientation_(
199 199 self.textView.enclosingScrollView(),
200 200 NSVerticalRuler)
201 201 self.verticalRulerView = r
202 202 self.verticalRulerView.setClientView_(self.textView)
203 203 self._start_cli_banner()
204 204 self.start_new_block()
205 205
206 206
207 207 def appWillTerminate_(self, notification):
208 208 """appWillTerminate"""
209 209
210 210 self.engine.stopService()
211 211
212 212
213 213 def complete(self, token):
214 214 """Complete token in engine's user_ns
215 215
216 216 Parameters
217 217 ----------
218 218 token : string
219 219
220 220 Result
221 221 ------
222 222 Deferred result of
223 223 IPython.kernel.engineservice.IEngineBase.complete
224 224 """
225 225
226 226 return self.engine.complete(token)
227 227
228 228
229 229 def execute(self, block, blockID=None):
230 230 self.waitingForEngine = True
231 231 self.willChangeValueForKey_('commandHistory')
232 232 d = super(IPythonCocoaController, self).execute(block,
233 233 blockID)
234 234 d.addBoth(self._engine_done)
235 235 d.addCallback(self._update_user_ns)
236 236
237 237 return d
238 238
239 239
240 240 def push_(self, namespace):
241 241 """Push dictionary of key=>values to python namespace"""
242 242
243 243 self.waitingForEngine = True
244 244 self.willChangeValueForKey_('commandHistory')
245 245 d = self.engine.push(namespace)
246 246 d.addBoth(self._engine_done)
247 247 d.addCallback(self._update_user_ns)
248 248
249 249
250 250 def pull_(self, keys):
251 251 """Pull keys from python namespace"""
252 252
253 253 self.waitingForEngine = True
254 254 result = blockingCallFromThread(self.engine.pull, keys)
255 255 self.waitingForEngine = False
256 256
257 257 @objc.signature('v@:@I')
258 258 def executeFileAtPath_encoding_(self, path, encoding):
259 259 """Execute file at path in an empty namespace. Update the engine
260 260 user_ns with the resulting locals."""
261 261
262 262 lines,err = NSString.stringWithContentsOfFile_encoding_error_(
263 263 path,
264 264 encoding,
265 265 None)
266 266 self.engine.execute(lines)
267 267
268 268
269 269 def _engine_done(self, x):
270 270 self.waitingForEngine = False
271 271 self.didChangeValueForKey_('commandHistory')
272 272 return x
273 273
274 274 def _update_user_ns(self, result):
275 275 """Update self.userNS from self.engine's namespace"""
276 276 d = self.engine.keys()
277 277 d.addCallback(self._get_engine_namespace_values_for_keys)
278 278
279 279 return result
280 280
281 281
282 282 def _get_engine_namespace_values_for_keys(self, keys):
283 283 d = self.engine.pull(keys)
284 284 d.addCallback(self._store_engine_namespace_values, keys=keys)
285 285
286 286
287 287 def _store_engine_namespace_values(self, values, keys=[]):
288 288 assert(len(values) == len(keys))
289 289 self.willChangeValueForKey_('userNS')
290 290 for (k,v) in zip(keys,values):
291 291 self.userNS[k] = saferepr(v)
292 292 self.didChangeValueForKey_('userNS')
293 293
294 294
295 295 def update_cell_prompt(self, result, blockID=None):
296 296 print self.blockRanges
297 297 if(isinstance(result, Failure)):
298 298 prompt = self.input_prompt()
299 299
300 300 else:
301 301 prompt = self.input_prompt(number=result['number'])
302 302
303 303 r = self.blockRanges[blockID].inputPromptRange
304 304 self.insert_text(prompt,
305 305 textRange=r,
306 306 scrollToVisible=False
307 307 )
308 308
309 309 return result
310 310
311 311
312 312 def render_result(self, result):
313 313 blockID = result['blockID']
314 314 inputRange = self.blockRanges[blockID].inputRange
315 315 del self.blockRanges[blockID]
316 316
317 317 #print inputRange,self.current_block_range()
318 318 self.insert_text('\n' +
319 319 self.output_prompt(number=result['number']) +
320 320 result.get('display',{}).get('pprint','') +
321 321 '\n\n',
322 322 textRange=NSMakeRange(inputRange.location+inputRange.length,
323 323 0))
324 324 return result
325 325
326 326
327 327 def render_error(self, failure):
328 328 print failure
329 329 blockID = failure.blockID
330 330 inputRange = self.blockRanges[blockID].inputRange
331 331 self.insert_text('\n' +
332 332 self.output_prompt() +
333 333 '\n' +
334 334 failure.getErrorMessage() +
335 335 '\n\n',
336 336 textRange=NSMakeRange(inputRange.location +
337 337 inputRange.length,
338 338 0))
339 339 self.start_new_block()
340 340 return failure
341 341
342 342
343 343 def _start_cli_banner(self):
344 344 """Print banner"""
345 345
346 346 banner = """IPython1 %s -- An enhanced Interactive Python.""" % \
347 347 IPython.__version__
348 348
349 349 self.insert_text(banner + '\n\n')
350 350
351 351
352 352 def start_new_block(self):
353 353 """"""
354 354
355 355 self.currentBlockID = self.next_block_ID()
356 356 self.blockRanges[self.currentBlockID] = self.new_cell_block()
357 357 self.insert_text(self.input_prompt(),
358 358 textRange=self.current_block_range().inputPromptRange)
359 359
360 360
361 361
362 362 def next_block_ID(self):
363 363
364 return uuid.uuid4()
364 return guid.generate()
365 365
366 366 def new_cell_block(self):
367 367 """A new CellBlock at the end of self.textView.textStorage()"""
368 368
369 369 return CellBlock(NSMakeRange(self.textView.textStorage().length(),
370 370 0), #len(self.input_prompt())),
371 371 NSMakeRange(self.textView.textStorage().length(),# + len(self.input_prompt()),
372 372 0))
373 373
374 374
375 375 def current_block_range(self):
376 376 return self.blockRanges.get(self.currentBlockID,
377 377 self.new_cell_block())
378 378
379 379 def current_block(self):
380 380 """The current block's text"""
381 381
382 382 return self.text_for_range(self.current_block_range().inputRange)
383 383
384 384 def text_for_range(self, textRange):
385 385 """text_for_range"""
386 386
387 387 ts = self.textView.textStorage()
388 388 return ts.string().substringWithRange_(textRange)
389 389
390 390 def current_line(self):
391 391 block = self.text_for_range(self.current_block_range().inputRange)
392 392 block = block.split('\n')
393 393 return block[-1]
394 394
395 395
396 396 def insert_text(self, string=None, textRange=None, scrollToVisible=True):
397 397 """Insert text into textView at textRange, updating blockRanges
398 398 as necessary
399 399 """
400 400 if(textRange == None):
401 401 #range for end of text
402 402 textRange = NSMakeRange(self.textView.textStorage().length(), 0)
403 403
404 404
405 405 self.textView.replaceCharactersInRange_withString_(
406 406 textRange, string)
407 407
408 408 for r in self.blockRanges.itervalues():
409 409 r.update_ranges_for_insertion(string, textRange)
410 410
411 411 self.textView.setSelectedRange_(textRange)
412 412 if(scrollToVisible):
413 413 self.textView.scrollRangeToVisible_(textRange)
414 414
415 415
416 416
417 417 def replace_current_block_with_string(self, textView, string):
418 418 textView.replaceCharactersInRange_withString_(
419 419 self.current_block_range().inputRange,
420 420 string)
421 421 self.current_block_range().inputRange.length = len(string)
422 422 r = NSMakeRange(textView.textStorage().length(), 0)
423 423 textView.scrollRangeToVisible_(r)
424 424 textView.setSelectedRange_(r)
425 425
426 426
427 427 def current_indent_string(self):
428 428 """returns string for indent or None if no indent"""
429 429
430 430 return self._indent_for_block(self.current_block())
431 431
432 432
433 433 def _indent_for_block(self, block):
434 434 lines = block.split('\n')
435 435 if(len(lines) > 1):
436 436 currentIndent = len(lines[-1]) - len(lines[-1].lstrip())
437 437 if(currentIndent == 0):
438 438 currentIndent = self.tabSpaces
439 439
440 440 if(self.tabUsesSpaces):
441 441 result = ' ' * currentIndent
442 442 else:
443 443 result = '\t' * (currentIndent/self.tabSpaces)
444 444 else:
445 445 result = None
446 446
447 447 return result
448 448
449 449
450 450 # NSTextView delegate methods...
451 451 def textView_doCommandBySelector_(self, textView, selector):
452 452 assert(textView == self.textView)
453 453 NSLog("textView_doCommandBySelector_: "+selector)
454 454
455 455
456 456 if(selector == 'insertNewline:'):
457 457 indent = self.current_indent_string()
458 458 if(indent):
459 459 line = indent + self.current_line()
460 460 else:
461 461 line = self.current_line()
462 462
463 463 if(self.is_complete(self.current_block())):
464 464 self.execute(self.current_block(),
465 465 blockID=self.currentBlockID)
466 466 self.start_new_block()
467 467
468 468 return True
469 469
470 470 return False
471 471
472 472 elif(selector == 'moveUp:'):
473 473 prevBlock = self.get_history_previous(self.current_block())
474 474 if(prevBlock != None):
475 475 self.replace_current_block_with_string(textView, prevBlock)
476 476 else:
477 477 NSBeep()
478 478 return True
479 479
480 480 elif(selector == 'moveDown:'):
481 481 nextBlock = self.get_history_next()
482 482 if(nextBlock != None):
483 483 self.replace_current_block_with_string(textView, nextBlock)
484 484 else:
485 485 NSBeep()
486 486 return True
487 487
488 488 elif(selector == 'moveToBeginningOfParagraph:'):
489 489 textView.setSelectedRange_(NSMakeRange(
490 490 self.current_block_range().inputRange.location,
491 491 0))
492 492 return True
493 493 elif(selector == 'moveToEndOfParagraph:'):
494 494 textView.setSelectedRange_(NSMakeRange(
495 495 self.current_block_range().inputRange.location + \
496 496 self.current_block_range().inputRange.length, 0))
497 497 return True
498 498 elif(selector == 'deleteToEndOfParagraph:'):
499 499 if(textView.selectedRange().location <= \
500 500 self.current_block_range().location):
501 501 raise NotImplemented()
502 502
503 503 return False # don't actually handle the delete
504 504
505 505 elif(selector == 'insertTab:'):
506 506 if(len(self.current_line().strip()) == 0): #only white space
507 507 return False
508 508 else:
509 509 self.textView.complete_(self)
510 510 return True
511 511
512 512 elif(selector == 'deleteBackward:'):
513 513 #if we're at the beginning of the current block, ignore
514 514 if(textView.selectedRange().location == \
515 515 self.current_block_range().inputRange.location):
516 516 return True
517 517 else:
518 518 for r in self.blockRanges.itervalues():
519 519 deleteRange = textView.selectedRange
520 520 if(deleteRange.length == 0):
521 521 deleteRange.location -= 1
522 522 deleteRange.length = 1
523 523 r.update_ranges_for_deletion(deleteRange)
524 524 return False
525 525 return False
526 526
527 527
528 528 def textView_shouldChangeTextInRanges_replacementStrings_(self,
529 529 textView, ranges, replacementStrings):
530 530 """
531 531 Delegate method for NSTextView.
532 532
533 533 Refuse change text in ranges not at end, but make those changes at
534 534 end.
535 535 """
536 536
537 537 assert(len(ranges) == len(replacementStrings))
538 538 allow = True
539 539 for r,s in zip(ranges, replacementStrings):
540 540 r = r.rangeValue()
541 541 if(textView.textStorage().length() > 0 and
542 542 r.location < self.current_block_range().inputRange.location):
543 543 self.insert_text(s)
544 544 allow = False
545 545
546 546 return allow
547 547
548 548 def textView_completions_forPartialWordRange_indexOfSelectedItem_(self,
549 549 textView, words, charRange, index):
550 550 try:
551 551 ts = textView.textStorage()
552 552 token = ts.string().substringWithRange_(charRange)
553 553 completions = blockingCallFromThread(self.complete, token)
554 554 except:
555 555 completions = objc.nil
556 556 NSBeep()
557 557
558 558 return (completions,0)
559 559
560 560
@@ -1,91 +1,94 b''
1 1 # encoding: utf-8
2 2 """This file contains unittests for the
3 3 IPython.frontend.cocoa.cocoa_frontend module.
4 4 """
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #---------------------------------------------------------------------------
8 8 # Copyright (C) 2005 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 from IPython.kernel.core.interpreter import Interpreter
18 import IPython.kernel.engineservice as es
19 from IPython.testing.util import DeferredTestCase
20 from twisted.internet.defer import succeed
21 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
22
23 from Foundation import NSMakeRect
24 from AppKit import NSTextView, NSScrollView
17
18 try:
19 from IPython.kernel.core.interpreter import Interpreter
20 import IPython.kernel.engineservice as es
21 from IPython.testing.util import DeferredTestCase
22 from twisted.internet.defer import succeed
23 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
24 from Foundation import NSMakeRect
25 from AppKit import NSTextView, NSScrollView
26 except ImportError:
27 import nose
28 raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC")
25 29
26 30 class TestIPythonCocoaControler(DeferredTestCase):
27 31 """Tests for IPythonCocoaController"""
28
32
29 33 def setUp(self):
30 34 self.controller = IPythonCocoaController.alloc().init()
31 35 self.engine = es.EngineService()
32 36 self.engine.startService()
33
34
37
35 38 def tearDown(self):
36 39 self.controller = None
37 40 self.engine.stopService()
38
41
39 42 def testControllerExecutesCode(self):
40 43 code ="""5+5"""
41 44 expected = Interpreter().execute(code)
42 45 del expected['number']
43 46 def removeNumberAndID(result):
44 47 del result['number']
45 48 del result['id']
46 49 return result
47 50 self.assertDeferredEquals(
48 51 self.controller.execute(code).addCallback(removeNumberAndID),
49 52 expected)
50
53
51 54 def testControllerMirrorsUserNSWithValuesAsStrings(self):
52 55 code = """userns1=1;userns2=2"""
53 56 def testControllerUserNS(result):
54 57 self.assertEquals(self.controller.userNS['userns1'], 1)
55 58 self.assertEquals(self.controller.userNS['userns2'], 2)
56
59
57 60 self.controller.execute(code).addCallback(testControllerUserNS)
58
59
61
62
60 63 def testControllerInstantiatesIEngine(self):
61 64 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
62
65
63 66 def testControllerCompletesToken(self):
64 67 code = """longNameVariable=10"""
65 68 def testCompletes(result):
66 69 self.assert_("longNameVariable" in result)
67
70
68 71 def testCompleteToken(result):
69 72 self.controller.complete("longNa").addCallback(testCompletes)
70
73
71 74 self.controller.execute(code).addCallback(testCompletes)
72
73
75
76
74 77 def testCurrentIndent(self):
75 78 """test that current_indent_string returns current indent or None.
76 79 Uses _indent_for_block for direct unit testing.
77 80 """
78
81
79 82 self.controller.tabUsesSpaces = True
80 83 self.assert_(self.controller._indent_for_block("""a=3""") == None)
81 84 self.assert_(self.controller._indent_for_block("") == None)
82 85 block = """def test():\n a=3"""
83 86 self.assert_(self.controller._indent_for_block(block) == \
84 87 ' ' * self.controller.tabSpaces)
85
88
86 89 block = """if(True):\n%sif(False):\n%spass""" % \
87 90 (' '*self.controller.tabSpaces,
88 91 2*' '*self.controller.tabSpaces)
89 92 self.assert_(self.controller._indent_for_block(block) == \
90 93 2*(' '*self.controller.tabSpaces))
91
94
@@ -1,359 +1,343 b''
1 1 # encoding: utf-8
2 2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
3 3 """
4 4 frontendbase provides an interface and base class for GUI frontends for
5 5 IPython.kernel/IPython.kernel.core.
6 6
7 7 Frontend implementations will likely want to subclass FrontEndBase.
8 8
9 9 Author: Barry Wark
10 10 """
11 11 __docformat__ = "restructuredtext en"
12 12
13 13 #-------------------------------------------------------------------------------
14 14 # Copyright (C) 2008 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-------------------------------------------------------------------------------
19 19
20 20 #-------------------------------------------------------------------------------
21 21 # Imports
22 22 #-------------------------------------------------------------------------------
23 23 import string
24 import uuid
25 import _ast
24 import codeop
25 from IPython.external import guid
26 26
27 from zopeinterface import Interface, Attribute, implements, classProvides
28 27
28 from IPython.frontend.zopeinterface import (
29 Interface,
30 Attribute,
31 )
29 32 from IPython.kernel.core.history import FrontEndHistory
30 33 from IPython.kernel.core.util import Bunch
31 from IPython.kernel.engineservice import IEngineCore
32 34
33 35 ##############################################################################
34 36 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
35 37 # not
36 38
37 39 rc = Bunch()
38 40 rc.prompt_in1 = r'In [$number]: '
39 41 rc.prompt_in2 = r'...'
40 42 rc.prompt_out = r'Out [$number]: '
41 43
42 44 ##############################################################################
43 45 # Interface definitions
44 46 ##############################################################################
45 47
46 48 class IFrontEndFactory(Interface):
47 49 """Factory interface for frontends."""
48 50
49 51 def __call__(engine=None, history=None):
50 52 """
51 53 Parameters:
52 54 interpreter : IPython.kernel.engineservice.IEngineCore
53 55 """
54 56
55 57 pass
56 58
57 59
58 60 class IFrontEnd(Interface):
59 61 """Interface for frontends. All methods return t.i.d.Deferred"""
60 62
61 63 Attribute("input_prompt_template", "string.Template instance\
62 64 substituteable with execute result.")
63 65 Attribute("output_prompt_template", "string.Template instance\
64 66 substituteable with execute result.")
65 67 Attribute("continuation_prompt_template", "string.Template instance\
66 68 substituteable with execute result.")
67 69
68 70 def update_cell_prompt(result, blockID=None):
69 71 """Subclass may override to update the input prompt for a block.
70 72
71 73 In asynchronous frontends, this method will be called as a
72 74 twisted.internet.defer.Deferred's callback/errback.
73 75 Implementations should thus return result when finished.
74 76
75 77 Result is a result dict in case of success, and a
76 78 twisted.python.util.failure.Failure in case of an error
77 79 """
78 80
79 81 pass
80 82
81 83 def render_result(result):
82 84 """Render the result of an execute call. Implementors may choose the
83 85 method of rendering.
84 86 For example, a notebook-style frontend might render a Chaco plot
85 87 inline.
86 88
87 89 Parameters:
88 90 result : dict (result of IEngineBase.execute )
89 91 blockID = result['blockID']
90 92
91 93 Result:
92 94 Output of frontend rendering
93 95 """
94 96
95 97 pass
96 98
97 99 def render_error(failure):
98 100 """Subclasses must override to render the failure.
99 101
100 102 In asynchronous frontend, since this method will be called as a
101 103 twisted.internet.defer.Deferred's callback. Implementations
102 104 should thus return result when finished.
103 105
104 106 blockID = failure.blockID
105 107 """
106 108
107 109 pass
108 110
109 111 def input_prompt(number=''):
110 112 """Returns the input prompt by subsituting into
111 113 self.input_prompt_template
112 114 """
113 115 pass
114 116
115 117 def output_prompt(number=''):
116 118 """Returns the output prompt by subsituting into
117 119 self.output_prompt_template
118 120 """
119 121
120 122 pass
121 123
122 124 def continuation_prompt():
123 125 """Returns the continuation prompt by subsituting into
124 126 self.continuation_prompt_template
125 127 """
126 128
127 129 pass
128 130
129 131 def is_complete(block):
130 132 """Returns True if block is complete, False otherwise."""
131 133
132 134 pass
133 135
134 def compile_ast(block):
135 """Compiles block to an _ast.AST"""
136
137 pass
138
136
139 137 def get_history_previous(current_block):
140 138 """Returns the block previous in the history. Saves currentBlock if
141 139 the history_cursor is currently at the end of the input history"""
142 140 pass
143 141
144 142 def get_history_next():
145 143 """Returns the next block in the history."""
146 144
147 145 pass
148 146
149 147 def complete(self, line):
150 148 """Returns the list of possible completions, and the completed
151 149 line.
152 150
153 151 The input argument is the full line to be completed. This method
154 152 returns both the line completed as much as possible, and the list
155 153 of further possible completions (full words).
156 154 """
157 155 pass
158 156
159 157
160 158 ##############################################################################
161 159 # Base class for all the frontends.
162 160 ##############################################################################
163 161
164 162 class FrontEndBase(object):
165 163 """
166 164 FrontEndBase manages the state tasks for a CLI frontend:
167 165 - Input and output history management
168 166 - Input/continuation and output prompt generation
169 167
170 168 Some issues (due to possibly unavailable engine):
171 169 - How do we get the current cell number for the engine?
172 170 - How do we handle completions?
173 171 """
174 172
175 173 history_cursor = 0
176 174
177 175 input_prompt_template = string.Template(rc.prompt_in1)
178 176 output_prompt_template = string.Template(rc.prompt_out)
179 177 continuation_prompt_template = string.Template(rc.prompt_in2)
180 178
181 179 def __init__(self, shell=None, history=None):
182 180 self.shell = shell
183 181 if history is None:
184 182 self.history = FrontEndHistory(input_cache=[''])
185 183 else:
186 184 self.history = history
187 185
188 186
189 187 def input_prompt(self, number=''):
190 188 """Returns the current input prompt
191 189
192 190 It would be great to use ipython1.core.prompts.Prompt1 here
193 191 """
194 192 return self.input_prompt_template.safe_substitute({'number':number})
195 193
196 194
197 195 def continuation_prompt(self):
198 196 """Returns the current continuation prompt"""
199 197
200 198 return self.continuation_prompt_template.safe_substitute()
201 199
202 200 def output_prompt(self, number=''):
203 201 """Returns the output prompt for result"""
204 202
205 203 return self.output_prompt_template.safe_substitute({'number':number})
206 204
207 205
208 206 def is_complete(self, block):
209 207 """Determine if block is complete.
210 208
211 209 Parameters
212 210 block : string
213 211
214 212 Result
215 213 True if block can be sent to the engine without compile errors.
216 214 False otherwise.
217 215 """
218 216
219 217 try:
220 ast = self.compile_ast(block)
218 is_complete = codeop.compile_command(block.rstrip() + '\n\n',
219 "<string>", "exec")
221 220 except:
222 221 return False
223 222
224 223 lines = block.split('\n')
225 return (len(lines)==1 or str(lines[-1])=='')
226
227
228 def compile_ast(self, block):
229 """Compile block to an AST
230
231 Parameters:
232 block : str
233
234 Result:
235 AST
236
237 Throws:
238 Exception if block cannot be compiled
239 """
240
241 return compile(block, "<string>", "exec", _ast.PyCF_ONLY_AST)
224 return ((is_complete is not None)
225 and (len(lines)==1 or str(lines[-1])==''))
242 226
243 227
244 228 def execute(self, block, blockID=None):
245 229 """Execute the block and return the result.
246 230
247 231 Parameters:
248 232 block : {str, AST}
249 233 blockID : any
250 234 Caller may provide an ID to identify this block.
251 235 result['blockID'] := blockID
252 236
253 237 Result:
254 238 Deferred result of self.interpreter.execute
255 239 """
256 240
257 241 if(not self.is_complete(block)):
258 242 raise Exception("Block is not compilable")
259 243
260 244 if(blockID == None):
261 blockID = uuid.uuid4() #random UUID
245 blockID = guid.generate()
262 246
263 247 try:
264 248 result = self.shell.execute(block)
265 249 except Exception,e:
266 250 e = self._add_block_id_for_failure(e, blockID=blockID)
267 251 e = self.update_cell_prompt(e, blockID=blockID)
268 252 e = self.render_error(e)
269 253 else:
270 254 result = self._add_block_id_for_result(result, blockID=blockID)
271 255 result = self.update_cell_prompt(result, blockID=blockID)
272 256 result = self.render_result(result)
273 257
274 258 return result
275 259
276 260
277 261 def _add_block_id_for_result(self, result, blockID):
278 262 """Add the blockID to result or failure. Unfortunatley, we have to
279 263 treat failures differently than result dicts.
280 264 """
281 265
282 266 result['blockID'] = blockID
283 267
284 268 return result
285 269
286 270 def _add_block_id_for_failure(self, failure, blockID):
287 271 """_add_block_id_for_failure"""
288 272 failure.blockID = blockID
289 273 return failure
290 274
291 275
292 276 def _add_history(self, result, block=None):
293 277 """Add block to the history"""
294 278
295 279 assert(block != None)
296 280 self.history.add_items([block])
297 281 self.history_cursor += 1
298 282
299 283 return result
300 284
301 285
302 286 def get_history_previous(self, current_block):
303 287 """ Returns previous history string and decrement history cursor.
304 288 """
305 289 command = self.history.get_history_item(self.history_cursor - 1)
306 290
307 291 if command is not None:
308 292 if(self.history_cursor+1 == len(self.history.input_cache)):
309 293 self.history.input_cache[self.history_cursor] = current_block
310 294 self.history_cursor -= 1
311 295 return command
312 296
313 297
314 298 def get_history_next(self):
315 299 """ Returns next history string and increment history cursor.
316 300 """
317 301 command = self.history.get_history_item(self.history_cursor+1)
318 302
319 303 if command is not None:
320 304 self.history_cursor += 1
321 305 return command
322 306
323 307 ###
324 308 # Subclasses probably want to override these methods...
325 309 ###
326 310
327 311 def update_cell_prompt(self, result, blockID=None):
328 312 """Subclass may override to update the input prompt for a block.
329 313
330 314 This method only really makes sens in asyncrhonous frontend.
331 315 Since this method will be called as a
332 316 twisted.internet.defer.Deferred's callback, implementations should
333 317 return result when finished.
334 318 """
335 319
336 320 raise NotImplementedError
337 321
338 322
339 323 def render_result(self, result):
340 324 """Subclasses must override to render result.
341 325
342 326 In asynchronous frontends, this method will be called as a
343 327 twisted.internet.defer.Deferred's callback. Implementations
344 328 should thus return result when finished.
345 329 """
346 330
347 331 raise NotImplementedError
348 332
349 333
350 334 def render_error(self, failure):
351 335 """Subclasses must override to render the failure.
352 336
353 337 In asynchronous frontends, this method will be called as a
354 338 twisted.internet.defer.Deferred's callback. Implementations
355 339 should thus return result when finished.
356 340 """
357 341
358 342 raise NotImplementedError
359 343
@@ -1,294 +1,333 b''
1 1 """
2 2 Base front end class for all line-oriented frontends, rather than
3 3 block-oriented.
4 4
5 5 Currently this focuses on synchronous frontends.
6 6 """
7 7 __docformat__ = "restructuredtext en"
8 8
9 9 #-------------------------------------------------------------------------------
10 10 # Copyright (C) 2008 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-------------------------------------------------------------------------------
15 15
16 16 #-------------------------------------------------------------------------------
17 17 # Imports
18 18 #-------------------------------------------------------------------------------
19 19 import re
20 20
21 21 import IPython
22 22 import sys
23 import codeop
24 import traceback
23 25
24 26 from frontendbase import FrontEndBase
25 27 from IPython.kernel.core.interpreter import Interpreter
26 28
27 29 def common_prefix(strings):
28 30 """ Given a list of strings, return the common prefix between all
29 31 these strings.
30 32 """
31 33 ref = strings[0]
32 34 prefix = ''
33 35 for size in range(len(ref)):
34 36 test_prefix = ref[:size+1]
35 37 for string in strings[1:]:
36 38 if not string.startswith(test_prefix):
37 39 return prefix
38 40 prefix = test_prefix
39 41
40 42 return prefix
41 43
42 44 #-------------------------------------------------------------------------------
43 45 # Base class for the line-oriented front ends
44 46 #-------------------------------------------------------------------------------
45 47 class LineFrontEndBase(FrontEndBase):
46 48 """ Concrete implementation of the FrontEndBase class. This is meant
47 49 to be the base class behind all the frontend that are line-oriented,
48 50 rather than block-oriented.
49 51 """
50 52
51 53 # We need to keep the prompt number, to be able to increment
52 54 # it when there is an exception.
53 55 prompt_number = 1
54 56
55 57 # We keep a reference to the last result: it helps testing and
56 58 # programatic control of the frontend.
57 59 last_result = dict(number=0)
58 60
59 61 # The input buffer being edited
60 62 input_buffer = ''
61 63
62 64 # Set to true for debug output
63 65 debug = False
64 66
65 67 # A banner to print at startup
66 68 banner = None
67 69
68 70 #--------------------------------------------------------------------------
69 71 # FrontEndBase interface
70 72 #--------------------------------------------------------------------------
71 73
72 74 def __init__(self, shell=None, history=None, banner=None, *args, **kwargs):
73 75 if shell is None:
74 76 shell = Interpreter()
75 77 FrontEndBase.__init__(self, shell=shell, history=history)
76 78
77 79 if banner is not None:
78 80 self.banner = banner
81
82 def start(self):
83 """ Put the frontend in a state where it is ready for user
84 interaction.
85 """
79 86 if self.banner is not None:
80 87 self.write(self.banner, refresh=False)
81 88
82 89 self.new_prompt(self.input_prompt_template.substitute(number=1))
83 90
84 91
85 92 def complete(self, line):
86 93 """Complete line in engine's user_ns
87 94
88 95 Parameters
89 96 ----------
90 97 line : string
91 98
92 99 Result
93 100 ------
94 101 The replacement for the line and the list of possible completions.
95 102 """
96 103 completions = self.shell.complete(line)
97 104 complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
98 105 if completions:
99 106 prefix = common_prefix(completions)
100 107 residual = complete_sep.split(line)[:-1]
101 108 line = line[:-len(residual)] + prefix
102 109 return line, completions
103 110
104 111
105 112 def render_result(self, result):
106 113 """ Frontend-specific rendering of the result of a calculation
107 114 that has been sent to an engine.
108 115 """
109 116 if 'stdout' in result and result['stdout']:
110 117 self.write('\n' + result['stdout'])
111 118 if 'display' in result and result['display']:
112 119 self.write("%s%s\n" % (
113 120 self.output_prompt_template.substitute(
114 121 number=result['number']),
115 122 result['display']['pprint']
116 123 ) )
117 124
118 125
119 126 def render_error(self, failure):
120 127 """ Frontend-specific rendering of error.
121 128 """
122 129 self.write('\n\n'+str(failure)+'\n\n')
123 130 return failure
124 131
125 132
126 133 def is_complete(self, string):
127 134 """ Check if a string forms a complete, executable set of
128 135 commands.
129 136
130 137 For the line-oriented frontend, multi-line code is not executed
131 138 as soon as it is complete: the users has to enter two line
132 139 returns.
133 140 """
134 141 if string in ('', '\n'):
135 142 # Prefiltering, eg through ipython0, may return an empty
136 143 # string although some operations have been accomplished. We
137 144 # thus want to consider an empty string as a complete
138 145 # statement.
139 146 return True
140 147 elif ( len(self.input_buffer.split('\n'))>2
141 148 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
142 149 return False
143 150 else:
144 # Add line returns here, to make sure that the statement is
145 # complete.
146 return FrontEndBase.is_complete(self, string.rstrip() + '\n\n')
151 self.capture_output()
152 try:
153 # Add line returns here, to make sure that the statement is
154 # complete.
155 is_complete = codeop.compile_command(string.rstrip() + '\n\n',
156 "<string>", "exec")
157 self.release_output()
158 except Exception, e:
159 # XXX: Hack: return True so that the
160 # code gets executed and the error captured.
161 is_complete = True
162 return is_complete
147 163
148 164
149 165 def write(self, string, refresh=True):
150 166 """ Write some characters to the display.
151 167
152 168 Subclass should overide this method.
153 169
154 170 The refresh keyword argument is used in frontends with an
155 171 event loop, to choose whether the write should trigget an UI
156 172 refresh, and thus be syncrhonous, or not.
157 173 """
158 174 print >>sys.__stderr__, string
159 175
160 176
161 177 def execute(self, python_string, raw_string=None):
162 178 """ Stores the raw_string in the history, and sends the
163 179 python string to the interpreter.
164 180 """
165 181 if raw_string is None:
166 182 raw_string = python_string
167 183 # Create a false result, in case there is an exception
168 184 self.last_result = dict(number=self.prompt_number)
185
186 ## try:
187 ## self.history.input_cache[-1] = raw_string.rstrip()
188 ## result = self.shell.execute(python_string)
189 ## self.last_result = result
190 ## self.render_result(result)
191 ## except:
192 ## self.show_traceback()
193 ## finally:
194 ## self.after_execute()
195
169 196 try:
170 self.history.input_cache[-1] = raw_string.rstrip()
171 result = self.shell.execute(python_string)
172 self.last_result = result
173 self.render_result(result)
174 except:
175 self.show_traceback()
197 try:
198 self.history.input_cache[-1] = raw_string.rstrip()
199 result = self.shell.execute(python_string)
200 self.last_result = result
201 self.render_result(result)
202 except:
203 self.show_traceback()
176 204 finally:
177 205 self.after_execute()
178 206
207
179 208 #--------------------------------------------------------------------------
180 209 # LineFrontEndBase interface
181 210 #--------------------------------------------------------------------------
182 211
183 212 def prefilter_input(self, string):
184 """ Priflter the input to turn it in valid python.
213 """ Prefilter the input to turn it in valid python.
185 214 """
186 215 string = string.replace('\r\n', '\n')
187 216 string = string.replace('\t', 4*' ')
188 217 # Clean the trailing whitespace
189 218 string = '\n'.join(l.rstrip() for l in string.split('\n'))
190 219 return string
191 220
192 221
193 222 def after_execute(self):
194 223 """ All the operations required after an execution to put the
195 224 terminal back in a shape where it is usable.
196 225 """
197 226 self.prompt_number += 1
198 227 self.new_prompt(self.input_prompt_template.substitute(
199 228 number=(self.last_result['number'] + 1)))
200 229 # Start a new empty history entry
201 230 self._add_history(None, '')
202 231 self.history_cursor = len(self.history.input_cache) - 1
203 232
204 233
205 234 def complete_current_input(self):
206 235 """ Do code completion on current line.
207 236 """
208 237 if self.debug:
209 238 print >>sys.__stdout__, "complete_current_input",
210 239 line = self.input_buffer
211 240 new_line, completions = self.complete(line)
212 241 if len(completions)>1:
213 self.write_completion(completions)
214 self.input_buffer = new_line
242 self.write_completion(completions, new_line=new_line)
243 elif not line == new_line:
244 self.input_buffer = new_line
215 245 if self.debug:
246 print >>sys.__stdout__, 'line', line
247 print >>sys.__stdout__, 'new_line', new_line
216 248 print >>sys.__stdout__, completions
217 249
218 250
219 251 def get_line_width(self):
220 252 """ Return the width of the line in characters.
221 253 """
222 254 return 80
223 255
224 256
225 def write_completion(self, possibilities):
257 def write_completion(self, possibilities, new_line=None):
226 258 """ Write the list of possible completions.
259
260 new_line is the completed input line that should be displayed
261 after the completion are writen. If None, the input_buffer
262 before the completion is used.
227 263 """
228 current_buffer = self.input_buffer
264 if new_line is None:
265 new_line = self.input_buffer
229 266
230 267 self.write('\n')
231 268 max_len = len(max(possibilities, key=len)) + 1
232 269
233 270 # Now we check how much symbol we can put on a line...
234 271 chars_per_line = self.get_line_width()
235 272 symbols_per_line = max(1, chars_per_line/max_len)
236 273
237 274 pos = 1
238 275 buf = []
239 276 for symbol in possibilities:
240 277 if pos < symbols_per_line:
241 278 buf.append(symbol.ljust(max_len))
242 279 pos += 1
243 280 else:
244 281 buf.append(symbol.rstrip() + '\n')
245 282 pos = 1
246 283 self.write(''.join(buf))
247 284 self.new_prompt(self.input_prompt_template.substitute(
248 285 number=self.last_result['number'] + 1))
249 self.input_buffer = current_buffer
286 self.input_buffer = new_line
250 287
251 288
252 289 def new_prompt(self, prompt):
253 290 """ Prints a prompt and starts a new editing buffer.
254 291
255 292 Subclasses should use this method to make sure that the
256 293 terminal is put in a state favorable for a new line
257 294 input.
258 295 """
259 296 self.input_buffer = ''
260 297 self.write(prompt)
261 298
262 299
263 300 #--------------------------------------------------------------------------
264 301 # Private API
265 302 #--------------------------------------------------------------------------
266 303
267 304 def _on_enter(self):
268 305 """ Called when the return key is pressed in a line editing
269 306 buffer.
270 307 """
271 308 current_buffer = self.input_buffer
272 309 cleaned_buffer = self.prefilter_input(current_buffer)
273 310 if self.is_complete(cleaned_buffer):
274 311 self.execute(cleaned_buffer, raw_string=current_buffer)
275 312 else:
276 313 self.input_buffer += self._get_indent_string(
277 314 current_buffer[:-1])
315 if len(current_buffer.split('\n')) == 2:
316 self.input_buffer += '\t\t'
278 317 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
279 318 self.input_buffer += '\t'
280 319
281 320
282 321 def _get_indent_string(self, string):
283 322 """ Return the string of whitespace that prefixes a line. Used to
284 323 add the right amount of indendation when creating a new line.
285 324 """
286 325 string = string.replace('\t', ' '*4)
287 326 string = string.split('\n')[-1]
288 327 indent_chars = len(string) - len(string.lstrip())
289 328 indent_string = '\t'*(indent_chars // 4) + \
290 329 ' '*(indent_chars % 4)
291 330
292 331 return indent_string
293 332
294 333
@@ -1,223 +1,246 b''
1 1 """
2 2 Frontend class that uses IPython0 to prefilter the inputs.
3 3
4 4 Using the IPython0 mechanism gives us access to the magics.
5 5
6 6 This is a transitory class, used here to do the transition between
7 7 ipython0 and ipython1. This class is meant to be short-lived as more
8 8 functionnality is abstracted out of ipython0 in reusable functions and
9 9 is added on the interpreter. This class can be a used to guide this
10 10 refactoring.
11 11 """
12 12 __docformat__ = "restructuredtext en"
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Copyright (C) 2008 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-------------------------------------------------------------------------------
20 20
21 21 #-------------------------------------------------------------------------------
22 22 # Imports
23 23 #-------------------------------------------------------------------------------
24 24 import sys
25 25
26 26 from linefrontendbase import LineFrontEndBase, common_prefix
27 from frontendbase import FrontEndBase
27 28
28 29 from IPython.ipmaker import make_IPython
29 30 from IPython.ipapi import IPApi
30 31 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
31 32
32 33 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
33 34
34 35 from IPython.genutils import Term
35 36 import pydoc
36 37 import os
38 import sys
37 39
38 40
39 41 def mk_system_call(system_call_function, command):
40 42 """ given a os.system replacement, and a leading string command,
41 43 returns a function that will execute the command with the given
42 44 argument string.
43 45 """
44 46 def my_system_call(args):
45 47 system_call_function("%s %s" % (command, args))
46 48 return my_system_call
47 49
48 50 #-------------------------------------------------------------------------------
49 51 # Frontend class using ipython0 to do the prefiltering.
50 52 #-------------------------------------------------------------------------------
51 53 class PrefilterFrontEnd(LineFrontEndBase):
52 54 """ Class that uses ipython0 to do prefilter the input, do the
53 55 completion and the magics.
54 56
55 57 The core trick is to use an ipython0 instance to prefilter the
56 58 input, and share the namespace between the interpreter instance used
57 59 to execute the statements and the ipython0 used for code
58 60 completion...
59 61 """
62
63 debug = False
60 64
61 65 def __init__(self, ipython0=None, *args, **kwargs):
62 66 """ Parameters:
63 67 -----------
64 68
65 69 ipython0: an optional ipython0 instance to use for command
66 70 prefiltering and completion.
67 71 """
72 LineFrontEndBase.__init__(self, *args, **kwargs)
73 self.shell.output_trap = RedirectorOutputTrap(
74 out_callback=self.write,
75 err_callback=self.write,
76 )
77 self.shell.traceback_trap = SyncTracebackTrap(
78 formatters=self.shell.traceback_trap.formatters,
79 )
80
81 # Start the ipython0 instance:
68 82 self.save_output_hooks()
69 83 if ipython0 is None:
70 84 # Instanciate an IPython0 interpreter to be able to use the
71 85 # prefiltering.
72 86 # XXX: argv=[] is a bit bold.
73 ipython0 = make_IPython(argv=[])
87 ipython0 = make_IPython(argv=[],
88 user_ns=self.shell.user_ns,
89 user_global_ns=self.shell.user_global_ns)
74 90 self.ipython0 = ipython0
75 91 # Set the pager:
76 92 self.ipython0.set_hook('show_in_pager',
77 93 lambda s, string: self.write("\n" + string))
78 94 self.ipython0.write = self.write
79 95 self._ip = _ip = IPApi(self.ipython0)
80 96 # Make sure the raw system call doesn't get called, as we don't
81 97 # have a stdin accessible.
82 98 self._ip.system = self.system_call
83 99 # XXX: Muck around with magics so that they work better
84 100 # in our environment
85 101 self.ipython0.magic_ls = mk_system_call(self.system_call,
86 102 'ls -CF')
87 103 # And now clean up the mess created by ipython0
88 104 self.release_output()
105
106
89 107 if not 'banner' in kwargs and self.banner is None:
90 kwargs['banner'] = self.ipython0.BANNER + """
108 self.banner = self.ipython0.BANNER + """
91 109 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
92 110
93 LineFrontEndBase.__init__(self, *args, **kwargs)
94 # XXX: Hack: mix the two namespaces
95 self.shell.user_ns.update(self.ipython0.user_ns)
96 self.ipython0.user_ns = self.shell.user_ns
97 self.shell.user_global_ns.update(self.ipython0.user_global_ns)
98 self.ipython0.user_global_ns = self.shell.user_global_ns
99
100 self.shell.output_trap = RedirectorOutputTrap(
101 out_callback=self.write,
102 err_callback=self.write,
103 )
104 self.shell.traceback_trap = SyncTracebackTrap(
105 formatters=self.shell.traceback_trap.formatters,
106 )
111 self.start()
107 112
108 113 #--------------------------------------------------------------------------
109 114 # FrontEndBase interface
110 115 #--------------------------------------------------------------------------
111 116
112 117 def show_traceback(self):
113 118 """ Use ipython0 to capture the last traceback and display it.
114 119 """
115 120 self.capture_output()
116 self.ipython0.showtraceback()
121 self.ipython0.showtraceback(tb_offset=-1)
117 122 self.release_output()
118 123
119 124
120 125 def execute(self, python_string, raw_string=None):
121 126 if self.debug:
122 127 print 'Executing Python code:', repr(python_string)
123 128 self.capture_output()
124 129 LineFrontEndBase.execute(self, python_string,
125 130 raw_string=raw_string)
126 131 self.release_output()
127 132
128 133
129 134 def save_output_hooks(self):
130 135 """ Store all the output hooks we can think of, to be able to
131 136 restore them.
132 137
133 138 We need to do this early, as starting the ipython0 instance will
134 139 screw ouput hooks.
135 140 """
136 141 self.__old_cout_write = Term.cout.write
137 142 self.__old_cerr_write = Term.cerr.write
138 143 self.__old_stdout = sys.stdout
139 144 self.__old_stderr= sys.stderr
140 145 self.__old_help_output = pydoc.help.output
141 146 self.__old_display_hook = sys.displayhook
142 147
143 148
144 149 def capture_output(self):
145 150 """ Capture all the output mechanisms we can think of.
146 151 """
147 152 self.save_output_hooks()
148 153 Term.cout.write = self.write
149 154 Term.cerr.write = self.write
150 155 sys.stdout = Term.cout
151 156 sys.stderr = Term.cerr
152 157 pydoc.help.output = self.shell.output_trap.out
153 158
154 159
155 160 def release_output(self):
156 161 """ Release all the different captures we have made.
157 162 """
158 163 Term.cout.write = self.__old_cout_write
159 164 Term.cerr.write = self.__old_cerr_write
160 165 sys.stdout = self.__old_stdout
161 166 sys.stderr = self.__old_stderr
162 167 pydoc.help.output = self.__old_help_output
163 168 sys.displayhook = self.__old_display_hook
164 169
165 170
166 171 def complete(self, line):
172 # FIXME: This should be factored out in the linefrontendbase
173 # method.
167 174 word = line.split('\n')[-1].split(' ')[-1]
168 175 completions = self.ipython0.complete(word)
169 176 # FIXME: The proper sort should be done in the complete method.
170 177 key = lambda x: x.replace('_', '')
171 178 completions.sort(key=key)
172 179 if completions:
173 180 prefix = common_prefix(completions)
174 181 line = line[:-len(word)] + prefix
175 182 return line, completions
176 183
177 184
178 185 #--------------------------------------------------------------------------
179 186 # LineFrontEndBase interface
180 187 #--------------------------------------------------------------------------
181 188
182 189 def prefilter_input(self, input_string):
183 190 """ Using IPython0 to prefilter the commands to turn them
184 191 in executable statements that are valid Python strings.
185 192 """
186 193 input_string = LineFrontEndBase.prefilter_input(self, input_string)
187 194 filtered_lines = []
188 195 # The IPython0 prefilters sometime produce output. We need to
189 196 # capture it.
190 197 self.capture_output()
191 198 self.last_result = dict(number=self.prompt_number)
199
200 ## try:
201 ## for line in input_string.split('\n'):
202 ## filtered_lines.append(
203 ## self.ipython0.prefilter(line, False).rstrip())
204 ## except:
205 ## # XXX: probably not the right thing to do.
206 ## self.ipython0.showsyntaxerror()
207 ## self.after_execute()
208 ## finally:
209 ## self.release_output()
210
211
192 212 try:
193 for line in input_string.split('\n'):
194 filtered_lines.append(
195 self.ipython0.prefilter(line, False).rstrip())
196 except:
197 # XXX: probably not the right thing to do.
198 self.ipython0.showsyntaxerror()
199 self.after_execute()
213 try:
214 for line in input_string.split('\n'):
215 filtered_lines.append(
216 self.ipython0.prefilter(line, False).rstrip())
217 except:
218 # XXX: probably not the right thing to do.
219 self.ipython0.showsyntaxerror()
220 self.after_execute()
200 221 finally:
201 222 self.release_output()
202 223
224
225
203 226 # Clean up the trailing whitespace, to avoid indentation errors
204 227 filtered_string = '\n'.join(filtered_lines)
205 228 return filtered_string
206 229
207 230
208 231 #--------------------------------------------------------------------------
209 232 # PrefilterFrontEnd interface
210 233 #--------------------------------------------------------------------------
211 234
212 235 def system_call(self, command_string):
213 236 """ Allows for frontend to define their own system call, to be
214 237 able capture output and redirect input.
215 238 """
216 239 return os.system(command_string)
217 240
218 241
219 242 def do_exit(self):
220 243 """ Exit the shell, cleanup and save the history.
221 244 """
222 245 self.ipython0.atexit_operations()
223 246
@@ -1,152 +1,32 b''
1 1 # encoding: utf-8
2
3 """This file contains unittests for the frontendbase module."""
2 """
3 Test the basic functionality of frontendbase.
4 """
4 5
5 6 __docformat__ = "restructuredtext en"
6 7
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
13
14 #---------------------------------------------------------------------------
15 # Imports
16 #---------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
17 14
18 import unittest
19 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
20 from IPython.frontend import frontendbase
21 from IPython.kernel.engineservice import EngineService
15 from IPython.frontend.frontendbase import FrontEndBase
22 16
23 class FrontEndCallbackChecker(AsyncFrontEndBase):
24 """FrontEndBase subclass for checking callbacks"""
25 def __init__(self, engine=None, history=None):
26 super(FrontEndCallbackChecker, self).__init__(engine=engine,
27 history=history)
28 self.updateCalled = False
29 self.renderResultCalled = False
30 self.renderErrorCalled = False
31
32 def update_cell_prompt(self, result, blockID=None):
33 self.updateCalled = True
34 return result
35
36 def render_result(self, result):
37 self.renderResultCalled = True
38 return result
39
40
41 def render_error(self, failure):
42 self.renderErrorCalled = True
43 return failure
44
17 def test_iscomplete():
18 """ Check that is_complete works.
19 """
20 f = FrontEndBase()
21 assert f.is_complete('(a + a)')
22 assert not f.is_complete('(a + a')
23 assert f.is_complete('1')
24 assert not f.is_complete('1 + ')
25 assert not f.is_complete('1 + \n\n')
26 assert f.is_complete('if True:\n print 1\n')
27 assert not f.is_complete('if True:\n print 1')
28 assert f.is_complete('def f():\n print 1\n')
45 29
30 if __name__ == '__main__':
31 test_iscomplete()
46 32
47
48 class TestAsyncFrontendBase(unittest.TestCase):
49 def setUp(self):
50 """Setup the EngineService and FrontEndBase"""
51
52 self.fb = FrontEndCallbackChecker(engine=EngineService())
53
54
55 def test_implements_IFrontEnd(self):
56 assert(frontendbase.IFrontEnd.implementedBy(
57 AsyncFrontEndBase))
58
59
60 def test_is_complete_returns_False_for_incomplete_block(self):
61 """"""
62
63 block = """def test(a):"""
64
65 assert(self.fb.is_complete(block) == False)
66
67 def test_is_complete_returns_True_for_complete_block(self):
68 """"""
69
70 block = """def test(a): pass"""
71
72 assert(self.fb.is_complete(block))
73
74 block = """a=3"""
75
76 assert(self.fb.is_complete(block))
77
78
79 def test_blockID_added_to_result(self):
80 block = """3+3"""
81
82 d = self.fb.execute(block, blockID='TEST_ID')
83
84 d.addCallback(self.checkBlockID, expected='TEST_ID')
85
86 def test_blockID_added_to_failure(self):
87 block = "raise Exception()"
88
89 d = self.fb.execute(block,blockID='TEST_ID')
90 d.addErrback(self.checkFailureID, expected='TEST_ID')
91
92 def checkBlockID(self, result, expected=""):
93 assert(result['blockID'] == expected)
94
95
96 def checkFailureID(self, failure, expected=""):
97 assert(failure.blockID == expected)
98
99
100 def test_callbacks_added_to_execute(self):
101 """test that
102 update_cell_prompt
103 render_result
104
105 are added to execute request
106 """
107
108 d = self.fb.execute("10+10")
109 d.addCallback(self.checkCallbacks)
110
111
112 def checkCallbacks(self, result):
113 assert(self.fb.updateCalled)
114 assert(self.fb.renderResultCalled)
115
116
117 def test_error_callback_added_to_execute(self):
118 """test that render_error called on execution error"""
119
120 d = self.fb.execute("raise Exception()")
121 d.addCallback(self.checkRenderError)
122
123 def checkRenderError(self, result):
124 assert(self.fb.renderErrorCalled)
125
126 def test_history_returns_expected_block(self):
127 """Make sure history browsing doesn't fail"""
128
129 blocks = ["a=1","a=2","a=3"]
130 for b in blocks:
131 d = self.fb.execute(b)
132
133 # d is now the deferred for the last executed block
134 d.addCallback(self.historyTests, blocks)
135
136
137 def historyTests(self, result, blocks):
138 """historyTests"""
139
140 assert(len(blocks) >= 3)
141 assert(self.fb.get_history_previous("") == blocks[-2])
142 assert(self.fb.get_history_previous("") == blocks[-3])
143 assert(self.fb.get_history_next() == blocks[-2])
144
145
146 def test_history_returns_none_at_startup(self):
147 """test_history_returns_none_at_startup"""
148
149 assert(self.fb.get_history_previous("")==None)
150 assert(self.fb.get_history_next()==None)
151
152
@@ -1,63 +1,67 b''
1 1 # encoding: utf-8
2 2 """
3 3 Test process execution and IO redirection.
4 4 """
5 5
6 6 __docformat__ = "restructuredtext en"
7 7
8 8 #-------------------------------------------------------------------------------
9 9 # Copyright (C) 2008 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is
12 12 # in the file COPYING, distributed as part of this software.
13 13 #-------------------------------------------------------------------------------
14 14
15 15 from cStringIO import StringIO
16 16 from time import sleep
17 17 import sys
18 18
19 19 from IPython.frontend._process import PipedProcess
20 from IPython.testing import decorators as testdec
21
20 22
21 23 def test_capture_out():
22 24 """ A simple test to see if we can execute a process and get the output.
23 25 """
24 26 s = StringIO()
25 27 p = PipedProcess('echo 1', out_callback=s.write, )
26 28 p.start()
27 29 p.join()
28 assert s.getvalue() == '1\n'
30 result = s.getvalue().rstrip()
31 assert result == '1'
29 32
30 33
31 34 def test_io():
32 35 """ Checks that we can send characters on stdin to the process.
33 36 """
34 37 s = StringIO()
35 38 p = PipedProcess(sys.executable + ' -c "a = raw_input(); print a"',
36 39 out_callback=s.write, )
37 40 p.start()
38 41 test_string = '12345\n'
39 42 while not hasattr(p, 'process'):
40 43 sleep(0.1)
41 44 p.process.stdin.write(test_string)
42 45 p.join()
43 assert s.getvalue() == test_string
46 result = s.getvalue()
47 assert result == test_string
44 48
45 49
46 50 def test_kill():
47 51 """ Check that we can kill a process, and its subprocess.
48 52 """
49 53 s = StringIO()
50 54 p = PipedProcess(sys.executable + ' -c "a = raw_input();"',
51 55 out_callback=s.write, )
52 56 p.start()
53 57 while not hasattr(p, 'process'):
54 58 sleep(0.1)
55 59 p.process.kill()
56 60 assert p.process.poll() is not None
57 61
58 62
59 63 if __name__ == '__main__':
60 64 test_capture_out()
61 65 test_io()
62 66 test_kill()
63 67
@@ -1,428 +1,436 b''
1 1 # encoding: utf-8
2 2 """
3 3 A Wx widget to act as a console and input commands.
4 4
5 5 This widget deals with prompts and provides an edit buffer
6 6 restricted to after the last prompt.
7 7 """
8 8
9 9 __docformat__ = "restructuredtext en"
10 10
11 11 #-------------------------------------------------------------------------------
12 12 # Copyright (C) 2008 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is
15 15 # in 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 wx
23 23 import wx.stc as stc
24 24
25 25 from wx.py import editwindow
26 import time
26 27 import sys
27 28 LINESEP = '\n'
28 29 if sys.platform == 'win32':
29 30 LINESEP = '\n\r'
30 31
31 32 import re
32 33
33 34 # FIXME: Need to provide an API for non user-generated display on the
34 35 # screen: this should not be editable by the user.
35 36
36 37 _DEFAULT_SIZE = 10
37 38 if sys.platform == 'darwin':
38 _DEFAULT_STYLE = 12
39 _DEFAULT_SIZE = 12
39 40
40 41 _DEFAULT_STYLE = {
41 42 'stdout' : 'fore:#0000FF',
42 43 'stderr' : 'fore:#007f00',
43 44 'trace' : 'fore:#FF0000',
44 45
45 46 'default' : 'size:%d' % _DEFAULT_SIZE,
46 47 'bracegood' : 'fore:#00AA00,back:#000000,bold',
47 48 'bracebad' : 'fore:#FF0000,back:#000000,bold',
48 49
49 50 # properties for the various Python lexer styles
50 51 'comment' : 'fore:#007F00',
51 52 'number' : 'fore:#007F7F',
52 53 'string' : 'fore:#7F007F,italic',
53 54 'char' : 'fore:#7F007F,italic',
54 55 'keyword' : 'fore:#00007F,bold',
55 56 'triple' : 'fore:#7F0000',
56 57 'tripledouble' : 'fore:#7F0000',
57 58 'class' : 'fore:#0000FF,bold,underline',
58 59 'def' : 'fore:#007F7F,bold',
59 60 'operator' : 'bold'
60 61 }
61 62
62 63 # new style numbers
63 64 _STDOUT_STYLE = 15
64 65 _STDERR_STYLE = 16
65 66 _TRACE_STYLE = 17
66 67
67 68
68 69 # system colors
69 70 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
70 71
71 72 #-------------------------------------------------------------------------------
72 73 # The console widget class
73 74 #-------------------------------------------------------------------------------
74 75 class ConsoleWidget(editwindow.EditWindow):
75 76 """ Specialized styled text control view for console-like workflow.
76 77
77 78 This widget is mainly interested in dealing with the prompt and
78 79 keeping the cursor inside the editing line.
79 80 """
80 81
81 82 # This is where the title captured from the ANSI escape sequences are
82 83 # stored.
83 84 title = 'Console'
84 85
85 86 # The buffer being edited.
86 87 def _set_input_buffer(self, string):
87 88 self.SetSelection(self.current_prompt_pos, self.GetLength())
88 89 self.ReplaceSelection(string)
89 90 self.GotoPos(self.GetLength())
90 91
91 92 def _get_input_buffer(self):
92 93 """ Returns the text in current edit buffer.
93 94 """
94 95 input_buffer = self.GetTextRange(self.current_prompt_pos,
95 96 self.GetLength())
96 97 input_buffer = input_buffer.replace(LINESEP, '\n')
97 98 return input_buffer
98 99
99 100 input_buffer = property(_get_input_buffer, _set_input_buffer)
100 101
101 102 style = _DEFAULT_STYLE.copy()
102 103
103 104 # Translation table from ANSI escape sequences to color. Override
104 105 # this to specify your colors.
105 106 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
106 107 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
107 108 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
108 109 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
109 110 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
110 111 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
111 112 '1;34': [12, 'LIGHT BLUE'], '1;35':
112 113 [13, 'MEDIUM VIOLET RED'],
113 114 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
114 115
115 116 # The color of the carret (call _apply_style() after setting)
116 117 carret_color = 'BLACK'
117 118
119 # Store the last time a refresh was done
120 _last_refresh_time = 0
121
118 122 #--------------------------------------------------------------------------
119 123 # Public API
120 124 #--------------------------------------------------------------------------
121 125
122 126 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
123 size=wx.DefaultSize, style=0, ):
127 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
124 128 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
125 129 self._configure_scintilla()
126 130
127 131 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
128 132 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
129 133
130 134
131 135 def write(self, text, refresh=True):
132 136 """ Write given text to buffer, while translating the ansi escape
133 137 sequences.
134 138 """
135 139 # XXX: do not put print statements to sys.stdout/sys.stderr in
136 140 # this method, the print statements will call this method, as
137 141 # you will end up with an infinit loop
138 142 title = self.title_pat.split(text)
139 143 if len(title)>1:
140 144 self.title = title[-2]
141 145
142 146 text = self.title_pat.sub('', text)
143 147 segments = self.color_pat.split(text)
144 148 segment = segments.pop(0)
145 149 self.GotoPos(self.GetLength())
146 150 self.StartStyling(self.GetLength(), 0xFF)
147 151 try:
148 152 self.AppendText(segment)
149 153 except UnicodeDecodeError:
150 154 # XXX: Do I really want to skip the exception?
151 155 pass
152 156
153 157 if segments:
154 158 for ansi_tag, text in zip(segments[::2], segments[1::2]):
155 159 self.StartStyling(self.GetLength(), 0xFF)
156 160 try:
157 161 self.AppendText(text)
158 162 except UnicodeDecodeError:
159 163 # XXX: Do I really want to skip the exception?
160 164 pass
161 165
162 166 if ansi_tag not in self.ANSI_STYLES:
163 167 style = 0
164 168 else:
165 169 style = self.ANSI_STYLES[ansi_tag][0]
166 170
167 171 self.SetStyling(len(text), style)
168 172
169 173 self.GotoPos(self.GetLength())
170 174 if refresh:
171 # Maybe this is faster than wx.Yield()
172 self.ProcessEvent(wx.PaintEvent())
173 #wx.Yield()
175 current_time = time.time()
176 if current_time - self._last_refresh_time > 0.03:
177 if sys.platform == 'win32':
178 wx.SafeYield()
179 else:
180 wx.Yield()
181 # self.ProcessEvent(wx.PaintEvent())
182 self._last_refresh_time = current_time
174 183
175 184
176 185 def new_prompt(self, prompt):
177 186 """ Prints a prompt at start of line, and move the start of the
178 187 current block there.
179 188
180 189 The prompt can be given with ascii escape sequences.
181 190 """
182 191 self.write(prompt, refresh=False)
183 192 # now we update our cursor giving end of prompt
184 193 self.current_prompt_pos = self.GetLength()
185 194 self.current_prompt_line = self.GetCurrentLine()
186 wx.Yield()
187 195 self.EnsureCaretVisible()
188 196
189 197
190 198 def scroll_to_bottom(self):
191 199 maxrange = self.GetScrollRange(wx.VERTICAL)
192 200 self.ScrollLines(maxrange)
193 201
194 202
195 203 def pop_completion(self, possibilities, offset=0):
196 204 """ Pops up an autocompletion menu. Offset is the offset
197 205 in characters of the position at which the menu should
198 206 appear, relativ to the cursor.
199 207 """
200 208 self.AutoCompSetIgnoreCase(False)
201 209 self.AutoCompSetAutoHide(False)
202 210 self.AutoCompSetMaxHeight(len(possibilities))
203 211 self.AutoCompShow(offset, " ".join(possibilities))
204 212
205 213
206 214 def get_line_width(self):
207 215 """ Return the width of the line in characters.
208 216 """
209 217 return self.GetSize()[0]/self.GetCharWidth()
210 218
211 219 #--------------------------------------------------------------------------
212 220 # EditWindow API
213 221 #--------------------------------------------------------------------------
214 222
215 223 def OnUpdateUI(self, event):
216 224 """ Override the OnUpdateUI of the EditWindow class, to prevent
217 225 syntax highlighting both for faster redraw, and for more
218 226 consistent look and feel.
219 227 """
220 228
221 229 #--------------------------------------------------------------------------
222 230 # Private API
223 231 #--------------------------------------------------------------------------
224 232
225 233 def _apply_style(self):
226 234 """ Applies the colors for the different text elements and the
227 235 carret.
228 236 """
229 237 self.SetCaretForeground(self.carret_color)
230 238
231 239 #self.StyleClearAll()
232 240 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
233 241 "fore:#FF0000,back:#0000FF,bold")
234 242 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
235 243 "fore:#000000,back:#FF0000,bold")
236 244
237 245 for style in self.ANSI_STYLES.values():
238 246 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
239 247
240 248
241 249 def _configure_scintilla(self):
242 250 self.SetEOLMode(stc.STC_EOL_LF)
243 251
244 252 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
245 253 # the widget
246 254 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
247 255 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
248 256 # Also allow Ctrl Shift "=" for poor non US keyboard users.
249 257 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
250 258 stc.STC_CMD_ZOOMIN)
251 259
252 260 # Keys: we need to clear some of the keys the that don't play
253 261 # well with a console.
254 262 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
255 263 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
256 264 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
257 265 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
258 266
259 267 self.SetEOLMode(stc.STC_EOL_CRLF)
260 268 self.SetWrapMode(stc.STC_WRAP_CHAR)
261 269 self.SetWrapMode(stc.STC_WRAP_WORD)
262 270 self.SetBufferedDraw(True)
263 271 self.SetUseAntiAliasing(True)
264 272 self.SetLayoutCache(stc.STC_CACHE_PAGE)
265 273 self.SetUndoCollection(False)
266 274 self.SetUseTabs(True)
267 275 self.SetIndent(4)
268 276 self.SetTabWidth(4)
269 277
270 278 # we don't want scintilla's autocompletion to choose
271 279 # automaticaly out of a single choice list, as we pop it up
272 280 # automaticaly
273 281 self.AutoCompSetChooseSingle(False)
274 282 self.AutoCompSetMaxHeight(10)
275 283 # XXX: this doesn't seem to have an effect.
276 284 self.AutoCompSetFillUps('\n')
277 285
278 286 self.SetMargins(3, 3) #text is moved away from border with 3px
279 287 # Suppressing Scintilla margins
280 288 self.SetMarginWidth(0, 0)
281 289 self.SetMarginWidth(1, 0)
282 290 self.SetMarginWidth(2, 0)
283 291
284 292 self._apply_style()
285 293
286 294 # Xterm escape sequences
287 295 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
288 296 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
289 297
290 298 #self.SetEdgeMode(stc.STC_EDGE_LINE)
291 299 #self.SetEdgeColumn(80)
292 300
293 301 # styles
294 302 p = self.style
295 303 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
296 304 self.StyleClearAll()
297 305 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
298 306 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
299 307 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
300 308
301 309 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
302 310 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
303 311 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
304 312 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
305 313 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
306 314 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
307 315 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
308 316 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
309 317 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
310 318 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
311 319 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
312 320 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
313 321 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
314 322 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
315 323
316 324 def _on_key_down(self, event, skip=True):
317 325 """ Key press callback used for correcting behavior for
318 326 console-like interfaces: the cursor is constraint to be after
319 327 the last prompt.
320 328
321 329 Return True if event as been catched.
322 330 """
323 331 catched = True
324 332 # Intercept some specific keys.
325 333 if event.KeyCode == ord('L') and event.ControlDown() :
326 334 self.scroll_to_bottom()
327 335 elif event.KeyCode == ord('K') and event.ControlDown() :
328 336 self.input_buffer = ''
329 337 elif event.KeyCode == ord('A') and event.ControlDown() :
330 338 self.GotoPos(self.GetLength())
331 339 self.SetSelectionStart(self.current_prompt_pos)
332 340 self.SetSelectionEnd(self.GetCurrentPos())
333 341 catched = True
334 342 elif event.KeyCode == ord('E') and event.ControlDown() :
335 343 self.GotoPos(self.GetLength())
336 344 catched = True
337 345 elif event.KeyCode == wx.WXK_PAGEUP:
338 346 self.ScrollPages(-1)
339 347 elif event.KeyCode == wx.WXK_PAGEDOWN:
340 348 self.ScrollPages(1)
341 349 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
342 350 self.ScrollLines(-1)
343 351 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
344 352 self.ScrollLines(1)
345 353 else:
346 354 catched = False
347 355
348 356 if self.AutoCompActive():
349 357 event.Skip()
350 358 else:
351 359 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
352 360 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
353 361 catched = True
354 362 self.CallTipCancel()
355 363 self.write('\n', refresh=False)
356 364 # Under windows scintilla seems to be doing funny stuff to the
357 365 # line returns here, but the getter for input_buffer filters
358 366 # this out.
359 367 if sys.platform == 'win32':
360 368 self.input_buffer = self.input_buffer
361 369 self._on_enter()
362 370
363 371 elif event.KeyCode == wx.WXK_HOME:
364 372 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
365 373 self.GotoPos(self.current_prompt_pos)
366 374 catched = True
367 375
368 376 elif event.Modifiers == wx.MOD_SHIFT:
369 377 # FIXME: This behavior is not ideal: if the selection
370 378 # is already started, it will jump.
371 379 self.SetSelectionStart(self.current_prompt_pos)
372 380 self.SetSelectionEnd(self.GetCurrentPos())
373 381 catched = True
374 382
375 383 elif event.KeyCode == wx.WXK_UP:
376 384 if self.GetCurrentLine() > self.current_prompt_line:
377 385 if self.GetCurrentLine() == self.current_prompt_line + 1 \
378 386 and self.GetColumn(self.GetCurrentPos()) < \
379 387 self.GetColumn(self.current_prompt_pos):
380 388 self.GotoPos(self.current_prompt_pos)
381 389 else:
382 390 event.Skip()
383 391 catched = True
384 392
385 393 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
386 394 if self.GetCurrentPos() > self.current_prompt_pos:
387 395 event.Skip()
388 396 catched = True
389 397
390 398 if skip and not catched:
391 399 # Put the cursor back in the edit region
392 400 if self.GetCurrentPos() < self.current_prompt_pos:
393 401 self.GotoPos(self.current_prompt_pos)
394 402 else:
395 403 event.Skip()
396 404
397 405 return catched
398 406
399 407
400 408 def _on_key_up(self, event, skip=True):
401 409 """ If cursor is outside the editing region, put it back.
402 410 """
403 411 event.Skip()
404 412 if self.GetCurrentPos() < self.current_prompt_pos:
405 413 self.GotoPos(self.current_prompt_pos)
406 414
407 415
408 416
409 417 if __name__ == '__main__':
410 418 # Some simple code to test the console widget.
411 419 class MainWindow(wx.Frame):
412 420 def __init__(self, parent, id, title):
413 421 wx.Frame.__init__(self, parent, id, title, size=(300,250))
414 422 self._sizer = wx.BoxSizer(wx.VERTICAL)
415 423 self.console_widget = ConsoleWidget(self)
416 424 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
417 425 self.SetSizer(self._sizer)
418 426 self.SetAutoLayout(1)
419 427 self.Show(True)
420 428
421 429 app = wx.PySimpleApp()
422 430 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
423 431 w.SetSize((780, 460))
424 432 w.Show()
425 433
426 434 app.MainLoop()
427 435
428 436
@@ -1,510 +1,526 b''
1 1 # encoding: utf-8 -*- test-case-name:
2 2 # FIXME: Need to add tests.
3 3 # ipython1.frontend.wx.tests.test_wx_frontend -*-
4 4
5 5 """Classes to provide a Wx frontend to the
6 6 IPython.kernel.core.interpreter.
7 7
8 8 This class inherits from ConsoleWidget, that provides a console-like
9 9 widget to provide a text-rendering widget suitable for a terminal.
10 10 """
11 11
12 12 __docformat__ = "restructuredtext en"
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Copyright (C) 2008 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-------------------------------------------------------------------------------
20 20
21 21 #-------------------------------------------------------------------------------
22 22 # Imports
23 23 #-------------------------------------------------------------------------------
24 24
25 25 # Major library imports
26 26 import re
27 27 import __builtin__
28 28 from time import sleep
29 29 import sys
30 30 from threading import Lock
31 31 import string
32 32
33 33 import wx
34 34 from wx import stc
35 35
36 36 # Ipython-specific imports.
37 37 from IPython.frontend._process import PipedProcess
38 38 from console_widget import ConsoleWidget
39 39 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
40 40
41 41 #-------------------------------------------------------------------------------
42 42 # Constants
43 43 #-------------------------------------------------------------------------------
44 44
45 45 _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green
46 46 _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow
47 47 _ERROR_BG = '#FFF1F1' # Nice red
48 48
49 49 _COMPLETE_BUFFER_MARKER = 31
50 50 _ERROR_MARKER = 30
51 51 _INPUT_MARKER = 29
52 52
53 53 prompt_in1 = \
54 54 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
55 55
56 56 prompt_out = \
57 57 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
58 58
59 59 #-------------------------------------------------------------------------------
60 60 # Classes to implement the Wx frontend
61 61 #-------------------------------------------------------------------------------
62 62 class WxController(ConsoleWidget, PrefilterFrontEnd):
63 63 """Classes to provide a Wx frontend to the
64 64 IPython.kernel.core.interpreter.
65 65
66 66 This class inherits from ConsoleWidget, that provides a console-like
67 67 widget to provide a text-rendering widget suitable for a terminal.
68 68 """
69 69
70 70 output_prompt_template = string.Template(prompt_out)
71 71
72 72 input_prompt_template = string.Template(prompt_in1)
73 73
74 74 # Print debug info on what is happening to the console.
75 75 debug = False
76 76
77 77 # The title of the terminal, as captured through the ANSI escape
78 78 # sequences.
79 79 def _set_title(self, title):
80 80 return self.Parent.SetTitle(title)
81 81
82 82 def _get_title(self):
83 83 return self.Parent.GetTitle()
84 84
85 85 title = property(_get_title, _set_title)
86 86
87 87
88 88 # The buffer being edited.
89 89 # We are duplicating the definition here because of multiple
90 90 # inheritence
91 91 def _set_input_buffer(self, string):
92 92 ConsoleWidget._set_input_buffer(self, string)
93 93 self._colorize_input_buffer()
94 94
95 95 def _get_input_buffer(self):
96 96 """ Returns the text in current edit buffer.
97 97 """
98 98 return ConsoleWidget._get_input_buffer(self)
99 99
100 100 input_buffer = property(_get_input_buffer, _set_input_buffer)
101 101
102 102
103 103 #--------------------------------------------------------------------------
104 104 # Private Attributes
105 105 #--------------------------------------------------------------------------
106 106
107 107 # A flag governing the behavior of the input. Can be:
108 108 #
109 109 # 'readline' for readline-like behavior with a prompt
110 110 # and an edit buffer.
111 111 # 'raw_input' similar to readline, but triggered by a raw-input
112 112 # call. Can be used by subclasses to act differently.
113 113 # 'subprocess' for sending the raw input directly to a
114 114 # subprocess.
115 115 # 'buffering' for buffering of the input, that will be used
116 116 # when the input state switches back to another state.
117 117 _input_state = 'readline'
118 118
119 119 # Attribute to store reference to the pipes of a subprocess, if we
120 120 # are running any.
121 121 _running_process = False
122 122
123 123 # A queue for writing fast streams to the screen without flooding the
124 124 # event loop
125 125 _out_buffer = []
126 126
127 127 # A lock to lock the _out_buffer to make sure we don't empty it
128 128 # while it is being swapped
129 129 _out_buffer_lock = Lock()
130 130
131 # The different line markers used to higlight the prompts.
131 132 _markers = dict()
132 133
133 134 #--------------------------------------------------------------------------
134 135 # Public API
135 136 #--------------------------------------------------------------------------
136 137
137 138 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
138 size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
139 size=wx.DefaultSize,
140 style=wx.CLIP_CHILDREN|wx.WANTS_CHARS,
139 141 *args, **kwds):
140 142 """ Create Shell instance.
141 143 """
142 144 ConsoleWidget.__init__(self, parent, id, pos, size, style)
143 145 PrefilterFrontEnd.__init__(self, **kwds)
146
147 # Stick in our own raw_input:
148 self.ipython0.raw_input = self.raw_input
144 149
145 150 # Marker for complete buffer.
146 151 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
147 152 background=_COMPLETE_BUFFER_BG)
148 153 # Marker for current input buffer.
149 154 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
150 155 background=_INPUT_BUFFER_BG)
151 156 # Marker for tracebacks.
152 157 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
153 158 background=_ERROR_BG)
154 159
155 160 # A time for flushing the write buffer
156 161 BUFFER_FLUSH_TIMER_ID = 100
157 162 self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID)
158 163 wx.EVT_TIMER(self, BUFFER_FLUSH_TIMER_ID, self._buffer_flush)
159 164
160 165 if 'debug' in kwds:
161 166 self.debug = kwds['debug']
162 167 kwds.pop('debug')
163 168
164 169 # Inject self in namespace, for debug
165 170 if self.debug:
166 171 self.shell.user_ns['self'] = self
172 # Inject our own raw_input in namespace
173 self.shell.user_ns['raw_input'] = self.raw_input
167 174
168 175
169 def raw_input(self, prompt):
176 def raw_input(self, prompt=''):
170 177 """ A replacement from python's raw_input.
171 178 """
172 179 self.new_prompt(prompt)
173 180 self._input_state = 'raw_input'
174 181 if hasattr(self, '_cursor'):
175 182 del self._cursor
176 183 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
177 self.waiting = True
178 184 self.__old_on_enter = self._on_enter
185 event_loop = wx.EventLoop()
179 186 def my_on_enter():
180 self.waiting = False
187 event_loop.Exit()
181 188 self._on_enter = my_on_enter
182 # XXX: Busy waiting, ugly.
183 while self.waiting:
184 wx.Yield()
185 sleep(0.1)
189 # XXX: Running a separate event_loop. Ugly.
190 event_loop.Run()
186 191 self._on_enter = self.__old_on_enter
187 192 self._input_state = 'buffering'
188 193 self._cursor = wx.BusyCursor()
189 194 return self.input_buffer.rstrip('\n')
190 195
191 196
192 197 def system_call(self, command_string):
193 198 self._input_state = 'subprocess'
199 event_loop = wx.EventLoop()
200 def _end_system_call():
201 self._input_state = 'buffering'
202 self._running_process = False
203 event_loop.Exit()
204
194 205 self._running_process = PipedProcess(command_string,
195 206 out_callback=self.buffered_write,
196 end_callback = self._end_system_call)
207 end_callback = _end_system_call)
197 208 self._running_process.start()
198 # XXX: another one of these polling loops to have a blocking
199 # call
200 wx.Yield()
201 while self._running_process:
202 wx.Yield()
203 sleep(0.1)
209 # XXX: Running a separate event_loop. Ugly.
210 event_loop.Run()
204 211 # Be sure to flush the buffer.
205 212 self._buffer_flush(event=None)
206 213
207 214
208 215 def do_calltip(self):
209 216 """ Analyse current and displays useful calltip for it.
210 217 """
211 218 if self.debug:
212 219 print >>sys.__stdout__, "do_calltip"
213 220 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
214 221 symbol = self.input_buffer
215 222 symbol_string = separators.split(symbol)[-1]
216 223 base_symbol_string = symbol_string.split('.')[0]
217 224 if base_symbol_string in self.shell.user_ns:
218 225 symbol = self.shell.user_ns[base_symbol_string]
219 226 elif base_symbol_string in self.shell.user_global_ns:
220 227 symbol = self.shell.user_global_ns[base_symbol_string]
221 228 elif base_symbol_string in __builtin__.__dict__:
222 229 symbol = __builtin__.__dict__[base_symbol_string]
223 230 else:
224 231 return False
225 232 try:
226 233 for name in symbol_string.split('.')[1:] + ['__doc__']:
227 234 symbol = getattr(symbol, name)
228 235 self.AutoCompCancel()
229 wx.Yield()
230 self.CallTipShow(self.GetCurrentPos(), symbol)
236 # Check that the symbol can indeed be converted to a string:
237 symbol += ''
238 wx.CallAfter(self.CallTipShow, self.GetCurrentPos(), symbol)
231 239 except:
232 240 # The retrieve symbol couldn't be converted to a string
233 241 pass
234 242
235 243
236 244 def _popup_completion(self, create=False):
237 245 """ Updates the popup completion menu if it exists. If create is
238 246 true, open the menu.
239 247 """
240 248 if self.debug:
241 print >>sys.__stdout__, "_popup_completion",
249 print >>sys.__stdout__, "_popup_completion"
242 250 line = self.input_buffer
243 if (self.AutoCompActive() and not line[-1] == '.') \
251 if (self.AutoCompActive() and line and not line[-1] == '.') \
244 252 or create==True:
245 253 suggestion, completions = self.complete(line)
246 254 offset=0
247 255 if completions:
248 256 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ,:]')
249 257 residual = complete_sep.split(line)[-1]
250 258 offset = len(residual)
251 259 self.pop_completion(completions, offset=offset)
252 260 if self.debug:
253 261 print >>sys.__stdout__, completions
254 262
255 263
256 264 def buffered_write(self, text):
257 265 """ A write method for streams, that caches the stream in order
258 266 to avoid flooding the event loop.
259 267
260 268 This can be called outside of the main loop, in separate
261 269 threads.
262 270 """
263 271 self._out_buffer_lock.acquire()
264 272 self._out_buffer.append(text)
265 273 self._out_buffer_lock.release()
266 274 if not self._buffer_flush_timer.IsRunning():
267 275 wx.CallAfter(self._buffer_flush_timer.Start,
268 276 milliseconds=100, oneShot=True)
269 277
270 278
271 279 #--------------------------------------------------------------------------
272 280 # LineFrontEnd interface
273 281 #--------------------------------------------------------------------------
274 282
275 283 def execute(self, python_string, raw_string=None):
276 284 self._input_state = 'buffering'
277 285 self.CallTipCancel()
278 286 self._cursor = wx.BusyCursor()
279 287 if raw_string is None:
280 288 raw_string = python_string
281 289 end_line = self.current_prompt_line \
282 290 + max(1, len(raw_string.split('\n'))-1)
283 291 for i in range(self.current_prompt_line, end_line):
284 292 if i in self._markers:
285 293 self.MarkerDeleteHandle(self._markers[i])
286 294 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
287 # Update the display:
288 wx.Yield()
289 self.GotoPos(self.GetLength())
290 PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string)
295 # Use a callafter to update the display robustly under windows
296 def callback():
297 self.GotoPos(self.GetLength())
298 PrefilterFrontEnd.execute(self, python_string,
299 raw_string=raw_string)
300 wx.CallAfter(callback)
291 301
292 302 def save_output_hooks(self):
293 303 self.__old_raw_input = __builtin__.raw_input
294 304 PrefilterFrontEnd.save_output_hooks(self)
295 305
296 306 def capture_output(self):
297 __builtin__.raw_input = self.raw_input
298 307 self.SetLexer(stc.STC_LEX_NULL)
299 308 PrefilterFrontEnd.capture_output(self)
309 __builtin__.raw_input = self.raw_input
300 310
301 311
302 312 def release_output(self):
303 313 __builtin__.raw_input = self.__old_raw_input
304 314 PrefilterFrontEnd.release_output(self)
305 315 self.SetLexer(stc.STC_LEX_PYTHON)
306 316
307 317
308 318 def after_execute(self):
309 319 PrefilterFrontEnd.after_execute(self)
310 320 # Clear the wait cursor
311 321 if hasattr(self, '_cursor'):
312 322 del self._cursor
313 323 self.SetCursor(wx.StockCursor(wx.CURSOR_CHAR))
314 324
315 325
316 326 def show_traceback(self):
317 327 start_line = self.GetCurrentLine()
318 328 PrefilterFrontEnd.show_traceback(self)
319 wx.Yield()
329 self.ProcessEvent(wx.PaintEvent())
330 #wx.Yield()
320 331 for i in range(start_line, self.GetCurrentLine()):
321 332 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
322 333
323 334
324 335 #--------------------------------------------------------------------------
336 # FrontEndBase interface
337 #--------------------------------------------------------------------------
338
339 def render_error(self, e):
340 start_line = self.GetCurrentLine()
341 self.write('\n' + e + '\n')
342 for i in range(start_line, self.GetCurrentLine()):
343 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
344
345
346 #--------------------------------------------------------------------------
325 347 # ConsoleWidget interface
326 348 #--------------------------------------------------------------------------
327 349
328 350 def new_prompt(self, prompt):
329 351 """ Display a new prompt, and start a new input buffer.
330 352 """
331 353 self._input_state = 'readline'
332 354 ConsoleWidget.new_prompt(self, prompt)
333 355 i = self.current_prompt_line
334 356 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
335 357
336 358
337 359 def write(self, *args, **kwargs):
338 360 # Avoid multiple inheritence, be explicit about which
339 361 # parent method class gets called
340 362 ConsoleWidget.write(self, *args, **kwargs)
341 363
342 364
343 365 def _on_key_down(self, event, skip=True):
344 366 """ Capture the character events, let the parent
345 367 widget handle them, and put our logic afterward.
346 368 """
347 369 # FIXME: This method needs to be broken down in smaller ones.
348 370 current_line_number = self.GetCurrentLine()
349 371 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
350 372 # Capture Control-C
351 373 if self._input_state == 'subprocess':
352 374 if self.debug:
353 375 print >>sys.__stderr__, 'Killing running process'
354 self._running_process.process.kill()
376 if hasattr(self._running_process, 'process'):
377 self._running_process.process.kill()
355 378 elif self._input_state == 'buffering':
356 379 if self.debug:
357 380 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
358 381 raise KeyboardInterrupt
359 382 # XXX: We need to make really sure we
360 383 # get back to a prompt.
361 384 elif self._input_state == 'subprocess' and (
362 385 ( event.KeyCode<256 and
363 386 not event.ControlDown() )
364 387 or
365 388 ( event.KeyCode in (ord('d'), ord('D')) and
366 389 event.ControlDown())):
367 390 # We are running a process, we redirect keys.
368 391 ConsoleWidget._on_key_down(self, event, skip=skip)
369 392 char = chr(event.KeyCode)
370 393 # Deal with some inconsistency in wx keycodes:
371 394 if char == '\r':
372 395 char = '\n'
373 396 elif not event.ShiftDown():
374 397 char = char.lower()
375 398 if event.ControlDown() and event.KeyCode in (ord('d'), ord('D')):
376 399 char = '\04'
377 400 self._running_process.process.stdin.write(char)
378 401 self._running_process.process.stdin.flush()
379 elif event.KeyCode in (ord('('), 57):
402 elif event.KeyCode in (ord('('), 57, 53):
380 403 # Calltips
381 404 event.Skip()
382 405 self.do_calltip()
383 406 elif self.AutoCompActive() and not event.KeyCode == ord('\t'):
384 407 event.Skip()
385 408 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
386 409 wx.CallAfter(self._popup_completion, create=True)
387 410 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
388 411 wx.WXK_RIGHT, wx.WXK_ESCAPE):
389 412 wx.CallAfter(self._popup_completion)
390 413 else:
391 414 # Up history
392 415 if event.KeyCode == wx.WXK_UP and (
393 416 ( current_line_number == self.current_prompt_line and
394 417 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
395 418 or event.ControlDown() ):
396 419 new_buffer = self.get_history_previous(
397 420 self.input_buffer)
398 421 if new_buffer is not None:
399 422 self.input_buffer = new_buffer
400 423 if self.GetCurrentLine() > self.current_prompt_line:
401 424 # Go to first line, for seemless history up.
402 425 self.GotoPos(self.current_prompt_pos)
403 426 # Down history
404 427 elif event.KeyCode == wx.WXK_DOWN and (
405 428 ( current_line_number == self.LineCount -1 and
406 429 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
407 430 or event.ControlDown() ):
408 431 new_buffer = self.get_history_next()
409 432 if new_buffer is not None:
410 433 self.input_buffer = new_buffer
411 434 # Tab-completion
412 435 elif event.KeyCode == ord('\t'):
413 last_line = self.input_buffer.split('\n')[-1]
414 if not re.match(r'^\s*$', last_line):
436 current_line, current_line_number = self.CurLine
437 if not re.match(r'^\s*$', current_line):
415 438 self.complete_current_input()
416 439 if self.AutoCompActive():
417 440 wx.CallAfter(self._popup_completion, create=True)
418 441 else:
419 442 event.Skip()
420 443 else:
421 444 ConsoleWidget._on_key_down(self, event, skip=skip)
422 445
423 446
424 447 def _on_key_up(self, event, skip=True):
425 448 """ Called when any key is released.
426 449 """
427 450 if event.KeyCode in (59, ord('.')):
428 451 # Intercepting '.'
429 452 event.Skip()
430 self._popup_completion(create=True)
453 wx.CallAfter(self._popup_completion, create=True)
431 454 else:
432 455 ConsoleWidget._on_key_up(self, event, skip=skip)
433 456
434 457
435 458 def _on_enter(self):
436 459 """ Called on return key down, in readline input_state.
437 460 """
438 461 if self.debug:
439 462 print >>sys.__stdout__, repr(self.input_buffer)
440 463 PrefilterFrontEnd._on_enter(self)
441 464
442 465
443 466 #--------------------------------------------------------------------------
444 467 # EditWindow API
445 468 #--------------------------------------------------------------------------
446 469
447 470 def OnUpdateUI(self, event):
448 471 """ Override the OnUpdateUI of the EditWindow class, to prevent
449 472 syntax highlighting both for faster redraw, and for more
450 473 consistent look and feel.
451 474 """
452 475 if not self._input_state == 'readline':
453 476 ConsoleWidget.OnUpdateUI(self, event)
454 477
455 478 #--------------------------------------------------------------------------
456 479 # Private API
457 480 #--------------------------------------------------------------------------
458 481
459 def _end_system_call(self):
460 """ Called at the end of a system call.
461 """
462 self._input_state = 'buffering'
463 self._running_process = False
464
465
466 482 def _buffer_flush(self, event):
467 483 """ Called by the timer to flush the write buffer.
468 484
469 485 This is always called in the mainloop, by the wx timer.
470 486 """
471 487 self._out_buffer_lock.acquire()
472 488 _out_buffer = self._out_buffer
473 489 self._out_buffer = []
474 490 self._out_buffer_lock.release()
475 491 self.write(''.join(_out_buffer), refresh=False)
476 492
477 493
478 494 def _colorize_input_buffer(self):
479 495 """ Keep the input buffer lines at a bright color.
480 496 """
481 497 if not self._input_state in ('readline', 'raw_input'):
482 498 return
483 499 end_line = self.GetCurrentLine()
484 500 if not sys.platform == 'win32':
485 501 end_line += 1
486 502 for i in range(self.current_prompt_line, end_line):
487 503 if i in self._markers:
488 504 self.MarkerDeleteHandle(self._markers[i])
489 505 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
490 506
491 507
492 508 if __name__ == '__main__':
493 509 class MainWindow(wx.Frame):
494 510 def __init__(self, parent, id, title):
495 511 wx.Frame.__init__(self, parent, id, title, size=(300,250))
496 512 self._sizer = wx.BoxSizer(wx.VERTICAL)
497 513 self.shell = WxController(self)
498 514 self._sizer.Add(self.shell, 1, wx.EXPAND)
499 515 self.SetSizer(self._sizer)
500 516 self.SetAutoLayout(1)
501 517 self.Show(True)
502 518
503 519 app = wx.PySimpleApp()
504 520 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
505 521 frame.shell.SetFocus()
506 522 frame.SetSize((680, 460))
507 523 self = frame.shell
508 524
509 525 app.MainLoop()
510 526
@@ -1,34 +1,27 b''
1 1 # encoding: utf-8
2 2 # -*- test-case-name: IPython.frontend.tests.test_frontendbase -*-
3 3 """
4 4 zope.interface mock. If zope is installed, this module provides a zope
5 5 interface classes, if not it provides mocks for them.
6 6
7 7 Classes provided:
8 8 Interface, Attribute, implements, classProvides
9 9 """
10 10 __docformat__ = "restructuredtext en"
11 11
12 12 #-------------------------------------------------------------------------------
13 13 # Copyright (C) 2008 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-------------------------------------------------------------------------------
18 18
19 #-------------------------------------------------------------------------------
20 # Imports
21 #-------------------------------------------------------------------------------
22 import string
23 import uuid
24 import _ast
25
26 19 try:
27 20 from zope.interface import Interface, Attribute, implements, classProvides
28 21 except ImportError:
29 22 #zope.interface is not available
30 23 Interface = object
31 24 def Attribute(name, doc): pass
32 25 def implements(interface): pass
33 26 def classProvides(interface): pass
34 27
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file chmod 100755 => 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file chmod 100755 => 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file chmod 100755 => 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file chmod 100755 => 100644
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from IPython/config/config.py to sandbox/config.py
1 NO CONTENT: file renamed from IPython/config/tests/sample_config.py to sandbox/sample_config.py
1 NO CONTENT: file renamed from IPython/config/tests/test_config.py to sandbox/test_config.py
1 NO CONTENT: file renamed from IPython/config/traitlets.py to sandbox/traitlets.py
1 NO CONTENT: modified file chmod 100644 => 100755, file renamed from scripts/wxIpython to scripts/ipython-wx
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (660 lines changed) Show them Hide them
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now