##// END OF EJS Templates
Improvements in the code that breaks up user input.
Thomas Kluyver -
Show More
@@ -1,263 +1,263 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 System command aliases.
3 System command aliases.
4
4
5 Authors:
5 Authors:
6
6
7 * Fernando Perez
7 * Fernando Perez
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2010 The IPython Development Team
12 # Copyright (C) 2008-2010 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License.
14 # Distributed under the terms of the BSD License.
15 #
15 #
16 # The full license is in the file COPYING.txt, distributed with this software.
16 # The full license is in the file COPYING.txt, distributed with this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import __builtin__
23 import __builtin__
24 import keyword
24 import keyword
25 import os
25 import os
26 import re
26 import re
27 import sys
27 import sys
28
28
29 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
30 from IPython.core.splitinput import split_user_input
30 from IPython.core.splitinput import split_user_input
31
31
32 from IPython.utils.traitlets import List, Instance
32 from IPython.utils.traitlets import List, Instance
33 from IPython.utils.autoattr import auto_attr
33 from IPython.utils.autoattr import auto_attr
34 from IPython.utils.warn import warn, error
34 from IPython.utils.warn import warn, error
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Utilities
37 # Utilities
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 # This is used as the pattern for calls to split_user_input.
40 # This is used as the pattern for calls to split_user_input.
41 shell_line_split = re.compile(r'^(\s*)(\S*\s*)(.*$)')
41 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
42
42
43 def default_aliases():
43 def default_aliases():
44 """Return list of shell aliases to auto-define.
44 """Return list of shell aliases to auto-define.
45 """
45 """
46 # Note: the aliases defined here should be safe to use on a kernel
46 # Note: the aliases defined here should be safe to use on a kernel
47 # regardless of what frontend it is attached to. Frontends that use a
47 # regardless of what frontend it is attached to. Frontends that use a
48 # kernel in-process can define additional aliases that will only work in
48 # kernel in-process can define additional aliases that will only work in
49 # their case. For example, things like 'less' or 'clear' that manipulate
49 # their case. For example, things like 'less' or 'clear' that manipulate
50 # the terminal should NOT be declared here, as they will only work if the
50 # the terminal should NOT be declared here, as they will only work if the
51 # kernel is running inside a true terminal, and not over the network.
51 # kernel is running inside a true terminal, and not over the network.
52
52
53 if os.name == 'posix':
53 if os.name == 'posix':
54 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
54 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
55 ('mv', 'mv -i'), ('rm', 'rm -i'), ('cp', 'cp -i'),
55 ('mv', 'mv -i'), ('rm', 'rm -i'), ('cp', 'cp -i'),
56 ('cat', 'cat'),
56 ('cat', 'cat'),
57 ]
57 ]
58 # Useful set of ls aliases. The GNU and BSD options are a little
58 # Useful set of ls aliases. The GNU and BSD options are a little
59 # different, so we make aliases that provide as similar as possible
59 # different, so we make aliases that provide as similar as possible
60 # behavior in ipython, by passing the right flags for each platform
60 # behavior in ipython, by passing the right flags for each platform
61 if sys.platform.startswith('linux'):
61 if sys.platform.startswith('linux'):
62 ls_aliases = [('ls', 'ls -F --color'),
62 ls_aliases = [('ls', 'ls -F --color'),
63 # long ls
63 # long ls
64 ('ll', 'ls -F -o --color'),
64 ('ll', 'ls -F -o --color'),
65 # ls normal files only
65 # ls normal files only
66 ('lf', 'ls -F -o --color %l | grep ^-'),
66 ('lf', 'ls -F -o --color %l | grep ^-'),
67 # ls symbolic links
67 # ls symbolic links
68 ('lk', 'ls -F -o --color %l | grep ^l'),
68 ('lk', 'ls -F -o --color %l | grep ^l'),
69 # directories or links to directories,
69 # directories or links to directories,
70 ('ldir', 'ls -F -o --color %l | grep /$'),
70 ('ldir', 'ls -F -o --color %l | grep /$'),
71 # things which are executable
71 # things which are executable
72 ('lx', 'ls -F -o --color %l | grep ^-..x'),
72 ('lx', 'ls -F -o --color %l | grep ^-..x'),
73 ]
73 ]
74 else:
74 else:
75 # BSD, OSX, etc.
75 # BSD, OSX, etc.
76 ls_aliases = [('ls', 'ls -F'),
76 ls_aliases = [('ls', 'ls -F'),
77 # long ls
77 # long ls
78 ('ll', 'ls -F -l'),
78 ('ll', 'ls -F -l'),
79 # ls normal files only
79 # ls normal files only
80 ('lf', 'ls -F -l %l | grep ^-'),
80 ('lf', 'ls -F -l %l | grep ^-'),
81 # ls symbolic links
81 # ls symbolic links
82 ('lk', 'ls -F -l %l | grep ^l'),
82 ('lk', 'ls -F -l %l | grep ^l'),
83 # directories or links to directories,
83 # directories or links to directories,
84 ('ldir', 'ls -F -l %l | grep /$'),
84 ('ldir', 'ls -F -l %l | grep /$'),
85 # things which are executable
85 # things which are executable
86 ('lx', 'ls -F -l %l | grep ^-..x'),
86 ('lx', 'ls -F -l %l | grep ^-..x'),
87 ]
87 ]
88 default_aliases = default_aliases + ls_aliases
88 default_aliases = default_aliases + ls_aliases
89 elif os.name in ['nt', 'dos']:
89 elif os.name in ['nt', 'dos']:
90 default_aliases = [('ls', 'dir /on'),
90 default_aliases = [('ls', 'dir /on'),
91 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
91 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
92 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
92 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
93 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
93 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
94 ]
94 ]
95 else:
95 else:
96 default_aliases = []
96 default_aliases = []
97
97
98 return default_aliases
98 return default_aliases
99
99
100
100
101 class AliasError(Exception):
101 class AliasError(Exception):
102 pass
102 pass
103
103
104
104
105 class InvalidAliasError(AliasError):
105 class InvalidAliasError(AliasError):
106 pass
106 pass
107
107
108 #-----------------------------------------------------------------------------
108 #-----------------------------------------------------------------------------
109 # Main AliasManager class
109 # Main AliasManager class
110 #-----------------------------------------------------------------------------
110 #-----------------------------------------------------------------------------
111
111
112 class AliasManager(Configurable):
112 class AliasManager(Configurable):
113
113
114 default_aliases = List(default_aliases(), config=True)
114 default_aliases = List(default_aliases(), config=True)
115 user_aliases = List(default_value=[], config=True)
115 user_aliases = List(default_value=[], config=True)
116 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
116 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
117
117
118 def __init__(self, shell=None, config=None):
118 def __init__(self, shell=None, config=None):
119 super(AliasManager, self).__init__(shell=shell, config=config)
119 super(AliasManager, self).__init__(shell=shell, config=config)
120 self.alias_table = {}
120 self.alias_table = {}
121 self.exclude_aliases()
121 self.exclude_aliases()
122 self.init_aliases()
122 self.init_aliases()
123
123
124 def __contains__(self, name):
124 def __contains__(self, name):
125 return name in self.alias_table
125 return name in self.alias_table
126
126
127 @property
127 @property
128 def aliases(self):
128 def aliases(self):
129 return [(item[0], item[1][1]) for item in self.alias_table.iteritems()]
129 return [(item[0], item[1][1]) for item in self.alias_table.iteritems()]
130
130
131 def exclude_aliases(self):
131 def exclude_aliases(self):
132 # set of things NOT to alias (keywords, builtins and some magics)
132 # set of things NOT to alias (keywords, builtins and some magics)
133 no_alias = set(['cd','popd','pushd','dhist','alias','unalias'])
133 no_alias = set(['cd','popd','pushd','dhist','alias','unalias'])
134 no_alias.update(set(keyword.kwlist))
134 no_alias.update(set(keyword.kwlist))
135 no_alias.update(set(__builtin__.__dict__.keys()))
135 no_alias.update(set(__builtin__.__dict__.keys()))
136 self.no_alias = no_alias
136 self.no_alias = no_alias
137
137
138 def init_aliases(self):
138 def init_aliases(self):
139 # Load default aliases
139 # Load default aliases
140 for name, cmd in self.default_aliases:
140 for name, cmd in self.default_aliases:
141 self.soft_define_alias(name, cmd)
141 self.soft_define_alias(name, cmd)
142
142
143 # Load user aliases
143 # Load user aliases
144 for name, cmd in self.user_aliases:
144 for name, cmd in self.user_aliases:
145 self.soft_define_alias(name, cmd)
145 self.soft_define_alias(name, cmd)
146
146
147 def clear_aliases(self):
147 def clear_aliases(self):
148 self.alias_table.clear()
148 self.alias_table.clear()
149
149
150 def soft_define_alias(self, name, cmd):
150 def soft_define_alias(self, name, cmd):
151 """Define an alias, but don't raise on an AliasError."""
151 """Define an alias, but don't raise on an AliasError."""
152 try:
152 try:
153 self.define_alias(name, cmd)
153 self.define_alias(name, cmd)
154 except AliasError, e:
154 except AliasError, e:
155 error("Invalid alias: %s" % e)
155 error("Invalid alias: %s" % e)
156
156
157 def define_alias(self, name, cmd):
157 def define_alias(self, name, cmd):
158 """Define a new alias after validating it.
158 """Define a new alias after validating it.
159
159
160 This will raise an :exc:`AliasError` if there are validation
160 This will raise an :exc:`AliasError` if there are validation
161 problems.
161 problems.
162 """
162 """
163 nargs = self.validate_alias(name, cmd)
163 nargs = self.validate_alias(name, cmd)
164 self.alias_table[name] = (nargs, cmd)
164 self.alias_table[name] = (nargs, cmd)
165
165
166 def undefine_alias(self, name):
166 def undefine_alias(self, name):
167 if self.alias_table.has_key(name):
167 if self.alias_table.has_key(name):
168 del self.alias_table[name]
168 del self.alias_table[name]
169
169
170 def validate_alias(self, name, cmd):
170 def validate_alias(self, name, cmd):
171 """Validate an alias and return the its number of arguments."""
171 """Validate an alias and return the its number of arguments."""
172 if name in self.no_alias:
172 if name in self.no_alias:
173 raise InvalidAliasError("The name %s can't be aliased "
173 raise InvalidAliasError("The name %s can't be aliased "
174 "because it is a keyword or builtin." % name)
174 "because it is a keyword or builtin." % name)
175 if not (isinstance(cmd, basestring)):
175 if not (isinstance(cmd, basestring)):
176 raise InvalidAliasError("An alias command must be a string, "
176 raise InvalidAliasError("An alias command must be a string, "
177 "got: %r" % name)
177 "got: %r" % name)
178 nargs = cmd.count('%s')
178 nargs = cmd.count('%s')
179 if nargs>0 and cmd.find('%l')>=0:
179 if nargs>0 and cmd.find('%l')>=0:
180 raise InvalidAliasError('The %s and %l specifiers are mutually '
180 raise InvalidAliasError('The %s and %l specifiers are mutually '
181 'exclusive in alias definitions.')
181 'exclusive in alias definitions.')
182 return nargs
182 return nargs
183
183
184 def call_alias(self, alias, rest=''):
184 def call_alias(self, alias, rest=''):
185 """Call an alias given its name and the rest of the line."""
185 """Call an alias given its name and the rest of the line."""
186 cmd = self.transform_alias(alias, rest)
186 cmd = self.transform_alias(alias, rest)
187 try:
187 try:
188 self.shell.system(cmd)
188 self.shell.system(cmd)
189 except:
189 except:
190 self.shell.showtraceback()
190 self.shell.showtraceback()
191
191
192 def transform_alias(self, alias,rest=''):
192 def transform_alias(self, alias,rest=''):
193 """Transform alias to system command string."""
193 """Transform alias to system command string."""
194 nargs, cmd = self.alias_table[alias]
194 nargs, cmd = self.alias_table[alias]
195
195
196 if ' ' in cmd and os.path.isfile(cmd):
196 if ' ' in cmd and os.path.isfile(cmd):
197 cmd = '"%s"' % cmd
197 cmd = '"%s"' % cmd
198
198
199 # Expand the %l special to be the user's input line
199 # Expand the %l special to be the user's input line
200 if cmd.find('%l') >= 0:
200 if cmd.find('%l') >= 0:
201 cmd = cmd.replace('%l', rest)
201 cmd = cmd.replace('%l', rest)
202 rest = ''
202 rest = ''
203 if nargs==0:
203 if nargs==0:
204 # Simple, argument-less aliases
204 # Simple, argument-less aliases
205 cmd = '%s %s' % (cmd, rest)
205 cmd = '%s %s' % (cmd, rest)
206 else:
206 else:
207 # Handle aliases with positional arguments
207 # Handle aliases with positional arguments
208 args = rest.split(None, nargs)
208 args = rest.split(None, nargs)
209 if len(args) < nargs:
209 if len(args) < nargs:
210 raise AliasError('Alias <%s> requires %s arguments, %s given.' %
210 raise AliasError('Alias <%s> requires %s arguments, %s given.' %
211 (alias, nargs, len(args)))
211 (alias, nargs, len(args)))
212 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
212 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
213 return cmd
213 return cmd
214
214
215 def expand_alias(self, line):
215 def expand_alias(self, line):
216 """ Expand an alias in the command line
216 """ Expand an alias in the command line
217
217
218 Returns the provided command line, possibly with the first word
218 Returns the provided command line, possibly with the first word
219 (command) translated according to alias expansion rules.
219 (command) translated according to alias expansion rules.
220
220
221 [ipython]|16> _ip.expand_aliases("np myfile.txt")
221 [ipython]|16> _ip.expand_aliases("np myfile.txt")
222 <16> 'q:/opt/np/notepad++.exe myfile.txt'
222 <16> 'q:/opt/np/notepad++.exe myfile.txt'
223 """
223 """
224
224
225 pre,fn,rest = split_user_input(line)
225 pre,_,fn,rest = split_user_input(line)
226 res = pre + self.expand_aliases(fn, rest)
226 res = pre + self.expand_aliases(fn, rest)
227 return res
227 return res
228
228
229 def expand_aliases(self, fn, rest):
229 def expand_aliases(self, fn, rest):
230 """Expand multiple levels of aliases:
230 """Expand multiple levels of aliases:
231
231
232 if:
232 if:
233
233
234 alias foo bar /tmp
234 alias foo bar /tmp
235 alias baz foo
235 alias baz foo
236
236
237 then:
237 then:
238
238
239 baz huhhahhei -> bar /tmp huhhahhei
239 baz huhhahhei -> bar /tmp huhhahhei
240 """
240 """
241 line = fn + " " + rest
241 line = fn + " " + rest
242
242
243 done = set()
243 done = set()
244 while 1:
244 while 1:
245 pre,fn,rest = split_user_input(line, shell_line_split)
245 pre,_,fn,rest = split_user_input(line, shell_line_split)
246 if fn in self.alias_table:
246 if fn in self.alias_table:
247 if fn in done:
247 if fn in done:
248 warn("Cyclic alias definition, repeated '%s'" % fn)
248 warn("Cyclic alias definition, repeated '%s'" % fn)
249 return ""
249 return ""
250 done.add(fn)
250 done.add(fn)
251
251
252 l2 = self.transform_alias(fn, rest)
252 l2 = self.transform_alias(fn, rest)
253 if l2 == line:
253 if l2 == line:
254 break
254 break
255 # ls -> ls -F should not recurse forever
255 # ls -> ls -F should not recurse forever
256 if l2.split(None,1)[0] == line.split(None,1)[0]:
256 if l2.split(None,1)[0] == line.split(None,1)[0]:
257 line = l2
257 line = l2
258 break
258 break
259 line=l2
259 line=l2
260 else:
260 else:
261 break
261 break
262
262
263 return line
263 return line
@@ -1,769 +1,773 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 __all__ = ['Inspector','InspectColors']
17 __all__ = ['Inspector','InspectColors']
18
18
19 # stdlib modules
19 # stdlib modules
20 import __builtin__
20 import __builtin__
21 import inspect
21 import inspect
22 import linecache
22 import linecache
23 import os
23 import os
24 import sys
24 import sys
25 import types
25 import types
26 from collections import namedtuple
26 from collections import namedtuple
27 from itertools import izip_longest
27 try:
28 from itertools import izip_longest
29 except ImportError:
30 from itertools import zip_longest as izip_longest
28
31
29 # IPython's own
32 # IPython's own
30 from IPython.core import page
33 from IPython.core import page
31 from IPython.utils import PyColorize
34 from IPython.utils import PyColorize
32 from IPython.utils import io
35 from IPython.utils import io
36 from IPython.utils import py3compat
33 from IPython.utils.text import indent
37 from IPython.utils.text import indent
34 from IPython.utils.wildcard import list_namespace
38 from IPython.utils.wildcard import list_namespace
35 from IPython.utils.coloransi import *
39 from IPython.utils.coloransi import *
36
40
37 #****************************************************************************
41 #****************************************************************************
38 # Builtin color schemes
42 # Builtin color schemes
39
43
40 Colors = TermColors # just a shorthand
44 Colors = TermColors # just a shorthand
41
45
42 # Build a few color schemes
46 # Build a few color schemes
43 NoColor = ColorScheme(
47 NoColor = ColorScheme(
44 'NoColor',{
48 'NoColor',{
45 'header' : Colors.NoColor,
49 'header' : Colors.NoColor,
46 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
50 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
47 } )
51 } )
48
52
49 LinuxColors = ColorScheme(
53 LinuxColors = ColorScheme(
50 'Linux',{
54 'Linux',{
51 'header' : Colors.LightRed,
55 'header' : Colors.LightRed,
52 'normal' : Colors.Normal # color off (usu. Colors.Normal)
56 'normal' : Colors.Normal # color off (usu. Colors.Normal)
53 } )
57 } )
54
58
55 LightBGColors = ColorScheme(
59 LightBGColors = ColorScheme(
56 'LightBG',{
60 'LightBG',{
57 'header' : Colors.Red,
61 'header' : Colors.Red,
58 'normal' : Colors.Normal # color off (usu. Colors.Normal)
62 'normal' : Colors.Normal # color off (usu. Colors.Normal)
59 } )
63 } )
60
64
61 # Build table of color schemes (needed by the parser)
65 # Build table of color schemes (needed by the parser)
62 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
66 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
63 'Linux')
67 'Linux')
64
68
65 #****************************************************************************
69 #****************************************************************************
66 # Auxiliary functions and objects
70 # Auxiliary functions and objects
67
71
68 # See the messaging spec for the definition of all these fields. This list
72 # See the messaging spec for the definition of all these fields. This list
69 # effectively defines the order of display
73 # effectively defines the order of display
70 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
74 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
71 'length', 'file', 'definition', 'docstring', 'source',
75 'length', 'file', 'definition', 'docstring', 'source',
72 'init_definition', 'class_docstring', 'init_docstring',
76 'init_definition', 'class_docstring', 'init_docstring',
73 'call_def', 'call_docstring',
77 'call_def', 'call_docstring',
74 # These won't be printed but will be used to determine how to
78 # These won't be printed but will be used to determine how to
75 # format the object
79 # format the object
76 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
80 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
77 ]
81 ]
78
82
79
83
80 def object_info(**kw):
84 def object_info(**kw):
81 """Make an object info dict with all fields present."""
85 """Make an object info dict with all fields present."""
82 infodict = dict(izip_longest(info_fields, [None]))
86 infodict = dict(izip_longest(info_fields, [None]))
83 infodict.update(kw)
87 infodict.update(kw)
84 return infodict
88 return infodict
85
89
86
90
87 def getdoc(obj):
91 def getdoc(obj):
88 """Stable wrapper around inspect.getdoc.
92 """Stable wrapper around inspect.getdoc.
89
93
90 This can't crash because of attribute problems.
94 This can't crash because of attribute problems.
91
95
92 It also attempts to call a getdoc() method on the given object. This
96 It also attempts to call a getdoc() method on the given object. This
93 allows objects which provide their docstrings via non-standard mechanisms
97 allows objects which provide their docstrings via non-standard mechanisms
94 (like Pyro proxies) to still be inspected by ipython's ? system."""
98 (like Pyro proxies) to still be inspected by ipython's ? system."""
95
99
96 ds = None # default return value
100 ds = None # default return value
97 try:
101 try:
98 ds = inspect.getdoc(obj)
102 ds = inspect.getdoc(obj)
99 except:
103 except:
100 # Harden against an inspect failure, which can occur with
104 # Harden against an inspect failure, which can occur with
101 # SWIG-wrapped extensions.
105 # SWIG-wrapped extensions.
102 pass
106 pass
103 # Allow objects to offer customized documentation via a getdoc method:
107 # Allow objects to offer customized documentation via a getdoc method:
104 try:
108 try:
105 ds2 = obj.getdoc()
109 ds2 = obj.getdoc()
106 except:
110 except:
107 pass
111 pass
108 else:
112 else:
109 # if we get extra info, we add it to the normal docstring.
113 # if we get extra info, we add it to the normal docstring.
110 if ds is None:
114 if ds is None:
111 ds = ds2
115 ds = ds2
112 else:
116 else:
113 ds = '%s\n%s' % (ds,ds2)
117 ds = '%s\n%s' % (ds,ds2)
114 return ds
118 return ds
115
119
116
120
117 def getsource(obj,is_binary=False):
121 def getsource(obj,is_binary=False):
118 """Wrapper around inspect.getsource.
122 """Wrapper around inspect.getsource.
119
123
120 This can be modified by other projects to provide customized source
124 This can be modified by other projects to provide customized source
121 extraction.
125 extraction.
122
126
123 Inputs:
127 Inputs:
124
128
125 - obj: an object whose source code we will attempt to extract.
129 - obj: an object whose source code we will attempt to extract.
126
130
127 Optional inputs:
131 Optional inputs:
128
132
129 - is_binary: whether the object is known to come from a binary source.
133 - is_binary: whether the object is known to come from a binary source.
130 This implementation will skip returning any output for binary objects, but
134 This implementation will skip returning any output for binary objects, but
131 custom extractors may know how to meaningfully process them."""
135 custom extractors may know how to meaningfully process them."""
132
136
133 if is_binary:
137 if is_binary:
134 return None
138 return None
135 else:
139 else:
136 # get source if obj was decorated with @decorator
140 # get source if obj was decorated with @decorator
137 if hasattr(obj,"__wrapped__"):
141 if hasattr(obj,"__wrapped__"):
138 obj = obj.__wrapped__
142 obj = obj.__wrapped__
139 try:
143 try:
140 src = inspect.getsource(obj)
144 src = inspect.getsource(obj)
141 except TypeError:
145 except TypeError:
142 if hasattr(obj,'__class__'):
146 if hasattr(obj,'__class__'):
143 src = inspect.getsource(obj.__class__)
147 src = inspect.getsource(obj.__class__)
144 return src
148 return src
145
149
146 def getargspec(obj):
150 def getargspec(obj):
147 """Get the names and default values of a function's arguments.
151 """Get the names and default values of a function's arguments.
148
152
149 A tuple of four things is returned: (args, varargs, varkw, defaults).
153 A tuple of four things is returned: (args, varargs, varkw, defaults).
150 'args' is a list of the argument names (it may contain nested lists).
154 'args' is a list of the argument names (it may contain nested lists).
151 'varargs' and 'varkw' are the names of the * and ** arguments or None.
155 'varargs' and 'varkw' are the names of the * and ** arguments or None.
152 'defaults' is an n-tuple of the default values of the last n arguments.
156 'defaults' is an n-tuple of the default values of the last n arguments.
153
157
154 Modified version of inspect.getargspec from the Python Standard
158 Modified version of inspect.getargspec from the Python Standard
155 Library."""
159 Library."""
156
160
157 if inspect.isfunction(obj):
161 if inspect.isfunction(obj):
158 func_obj = obj
162 func_obj = obj
159 elif inspect.ismethod(obj):
163 elif inspect.ismethod(obj):
160 func_obj = obj.im_func
164 func_obj = obj.im_func
161 elif hasattr(obj, '__call__'):
165 elif hasattr(obj, '__call__'):
162 func_obj = obj.__call__
166 func_obj = obj.__call__
163 else:
167 else:
164 raise TypeError('arg is not a Python function')
168 raise TypeError('arg is not a Python function')
165 args, varargs, varkw = inspect.getargs(func_obj.func_code)
169 args, varargs, varkw = inspect.getargs(func_obj.func_code)
166 return args, varargs, varkw, func_obj.func_defaults
170 return args, varargs, varkw, func_obj.func_defaults
167
171
168
172
169 def format_argspec(argspec):
173 def format_argspec(argspec):
170 """Format argspect, convenience wrapper around inspect's.
174 """Format argspect, convenience wrapper around inspect's.
171
175
172 This takes a dict instead of ordered arguments and calls
176 This takes a dict instead of ordered arguments and calls
173 inspect.format_argspec with the arguments in the necessary order.
177 inspect.format_argspec with the arguments in the necessary order.
174 """
178 """
175 return inspect.formatargspec(argspec['args'], argspec['varargs'],
179 return inspect.formatargspec(argspec['args'], argspec['varargs'],
176 argspec['varkw'], argspec['defaults'])
180 argspec['varkw'], argspec['defaults'])
177
181
178
182
179 def call_tip(oinfo, format_call=True):
183 def call_tip(oinfo, format_call=True):
180 """Extract call tip data from an oinfo dict.
184 """Extract call tip data from an oinfo dict.
181
185
182 Parameters
186 Parameters
183 ----------
187 ----------
184 oinfo : dict
188 oinfo : dict
185
189
186 format_call : bool, optional
190 format_call : bool, optional
187 If True, the call line is formatted and returned as a string. If not, a
191 If True, the call line is formatted and returned as a string. If not, a
188 tuple of (name, argspec) is returned.
192 tuple of (name, argspec) is returned.
189
193
190 Returns
194 Returns
191 -------
195 -------
192 call_info : None, str or (str, dict) tuple.
196 call_info : None, str or (str, dict) tuple.
193 When format_call is True, the whole call information is formattted as a
197 When format_call is True, the whole call information is formattted as a
194 single string. Otherwise, the object's name and its argspec dict are
198 single string. Otherwise, the object's name and its argspec dict are
195 returned. If no call information is available, None is returned.
199 returned. If no call information is available, None is returned.
196
200
197 docstring : str or None
201 docstring : str or None
198 The most relevant docstring for calling purposes is returned, if
202 The most relevant docstring for calling purposes is returned, if
199 available. The priority is: call docstring for callable instances, then
203 available. The priority is: call docstring for callable instances, then
200 constructor docstring for classes, then main object's docstring otherwise
204 constructor docstring for classes, then main object's docstring otherwise
201 (regular functions).
205 (regular functions).
202 """
206 """
203 # Get call definition
207 # Get call definition
204 argspec = oinfo.get('argspec')
208 argspec = oinfo.get('argspec')
205 if argspec is None:
209 if argspec is None:
206 call_line = None
210 call_line = None
207 else:
211 else:
208 # Callable objects will have 'self' as their first argument, prune
212 # Callable objects will have 'self' as their first argument, prune
209 # it out if it's there for clarity (since users do *not* pass an
213 # it out if it's there for clarity (since users do *not* pass an
210 # extra first argument explicitly).
214 # extra first argument explicitly).
211 try:
215 try:
212 has_self = argspec['args'][0] == 'self'
216 has_self = argspec['args'][0] == 'self'
213 except (KeyError, IndexError):
217 except (KeyError, IndexError):
214 pass
218 pass
215 else:
219 else:
216 if has_self:
220 if has_self:
217 argspec['args'] = argspec['args'][1:]
221 argspec['args'] = argspec['args'][1:]
218
222
219 call_line = oinfo['name']+format_argspec(argspec)
223 call_line = oinfo['name']+format_argspec(argspec)
220
224
221 # Now get docstring.
225 # Now get docstring.
222 # The priority is: call docstring, constructor docstring, main one.
226 # The priority is: call docstring, constructor docstring, main one.
223 doc = oinfo.get('call_docstring')
227 doc = oinfo.get('call_docstring')
224 if doc is None:
228 if doc is None:
225 doc = oinfo.get('init_docstring')
229 doc = oinfo.get('init_docstring')
226 if doc is None:
230 if doc is None:
227 doc = oinfo.get('docstring','')
231 doc = oinfo.get('docstring','')
228
232
229 return call_line, doc
233 return call_line, doc
230
234
231
235
232 class Inspector:
236 class Inspector:
233 def __init__(self, color_table=InspectColors,
237 def __init__(self, color_table=InspectColors,
234 code_color_table=PyColorize.ANSICodeColors,
238 code_color_table=PyColorize.ANSICodeColors,
235 scheme='NoColor',
239 scheme='NoColor',
236 str_detail_level=0):
240 str_detail_level=0):
237 self.color_table = color_table
241 self.color_table = color_table
238 self.parser = PyColorize.Parser(code_color_table,out='str')
242 self.parser = PyColorize.Parser(code_color_table,out='str')
239 self.format = self.parser.format
243 self.format = self.parser.format
240 self.str_detail_level = str_detail_level
244 self.str_detail_level = str_detail_level
241 self.set_active_scheme(scheme)
245 self.set_active_scheme(scheme)
242
246
243 def _getdef(self,obj,oname=''):
247 def _getdef(self,obj,oname=''):
244 """Return the definition header for any callable object.
248 """Return the definition header for any callable object.
245
249
246 If any exception is generated, None is returned instead and the
250 If any exception is generated, None is returned instead and the
247 exception is suppressed."""
251 exception is suppressed."""
248
252
249 try:
253 try:
250 # We need a plain string here, NOT unicode!
254 # We need a plain string here, NOT unicode!
251 hdef = oname + inspect.formatargspec(*getargspec(obj))
255 hdef = oname + inspect.formatargspec(*getargspec(obj))
252 return hdef.encode('ascii')
256 return py3compat.unicode_to_str(hdef.encode('ascii'))
253 except:
257 except:
254 return None
258 return None
255
259
256 def __head(self,h):
260 def __head(self,h):
257 """Return a header string with proper colors."""
261 """Return a header string with proper colors."""
258 return '%s%s%s' % (self.color_table.active_colors.header,h,
262 return '%s%s%s' % (self.color_table.active_colors.header,h,
259 self.color_table.active_colors.normal)
263 self.color_table.active_colors.normal)
260
264
261 def set_active_scheme(self,scheme):
265 def set_active_scheme(self,scheme):
262 self.color_table.set_active_scheme(scheme)
266 self.color_table.set_active_scheme(scheme)
263 self.parser.color_table.set_active_scheme(scheme)
267 self.parser.color_table.set_active_scheme(scheme)
264
268
265 def noinfo(self,msg,oname):
269 def noinfo(self,msg,oname):
266 """Generic message when no information is found."""
270 """Generic message when no information is found."""
267 print 'No %s found' % msg,
271 print 'No %s found' % msg,
268 if oname:
272 if oname:
269 print 'for %s' % oname
273 print 'for %s' % oname
270 else:
274 else:
271 print
275 print
272
276
273 def pdef(self,obj,oname=''):
277 def pdef(self,obj,oname=''):
274 """Print the definition header for any callable object.
278 """Print the definition header for any callable object.
275
279
276 If the object is a class, print the constructor information."""
280 If the object is a class, print the constructor information."""
277
281
278 if not callable(obj):
282 if not callable(obj):
279 print 'Object is not callable.'
283 print 'Object is not callable.'
280 return
284 return
281
285
282 header = ''
286 header = ''
283
287
284 if inspect.isclass(obj):
288 if inspect.isclass(obj):
285 header = self.__head('Class constructor information:\n')
289 header = self.__head('Class constructor information:\n')
286 obj = obj.__init__
290 obj = obj.__init__
287 elif type(obj) is types.InstanceType:
291 elif type(obj) is types.InstanceType:
288 obj = obj.__call__
292 obj = obj.__call__
289
293
290 output = self._getdef(obj,oname)
294 output = self._getdef(obj,oname)
291 if output is None:
295 if output is None:
292 self.noinfo('definition header',oname)
296 self.noinfo('definition header',oname)
293 else:
297 else:
294 print >>io.stdout, header,self.format(output),
298 print >>io.stdout, header,self.format(output),
295
299
296 def pdoc(self,obj,oname='',formatter = None):
300 def pdoc(self,obj,oname='',formatter = None):
297 """Print the docstring for any object.
301 """Print the docstring for any object.
298
302
299 Optional:
303 Optional:
300 -formatter: a function to run the docstring through for specially
304 -formatter: a function to run the docstring through for specially
301 formatted docstrings.
305 formatted docstrings.
302
306
303 Examples
307 Examples
304 --------
308 --------
305
309
306 In [1]: class NoInit:
310 In [1]: class NoInit:
307 ...: pass
311 ...: pass
308
312
309 In [2]: class NoDoc:
313 In [2]: class NoDoc:
310 ...: def __init__(self):
314 ...: def __init__(self):
311 ...: pass
315 ...: pass
312
316
313 In [3]: %pdoc NoDoc
317 In [3]: %pdoc NoDoc
314 No documentation found for NoDoc
318 No documentation found for NoDoc
315
319
316 In [4]: %pdoc NoInit
320 In [4]: %pdoc NoInit
317 No documentation found for NoInit
321 No documentation found for NoInit
318
322
319 In [5]: obj = NoInit()
323 In [5]: obj = NoInit()
320
324
321 In [6]: %pdoc obj
325 In [6]: %pdoc obj
322 No documentation found for obj
326 No documentation found for obj
323
327
324 In [5]: obj2 = NoDoc()
328 In [5]: obj2 = NoDoc()
325
329
326 In [6]: %pdoc obj2
330 In [6]: %pdoc obj2
327 No documentation found for obj2
331 No documentation found for obj2
328 """
332 """
329
333
330 head = self.__head # For convenience
334 head = self.__head # For convenience
331 lines = []
335 lines = []
332 ds = getdoc(obj)
336 ds = getdoc(obj)
333 if formatter:
337 if formatter:
334 ds = formatter(ds)
338 ds = formatter(ds)
335 if ds:
339 if ds:
336 lines.append(head("Class Docstring:"))
340 lines.append(head("Class Docstring:"))
337 lines.append(indent(ds))
341 lines.append(indent(ds))
338 if inspect.isclass(obj) and hasattr(obj, '__init__'):
342 if inspect.isclass(obj) and hasattr(obj, '__init__'):
339 init_ds = getdoc(obj.__init__)
343 init_ds = getdoc(obj.__init__)
340 if init_ds is not None:
344 if init_ds is not None:
341 lines.append(head("Constructor Docstring:"))
345 lines.append(head("Constructor Docstring:"))
342 lines.append(indent(init_ds))
346 lines.append(indent(init_ds))
343 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
347 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
344 and hasattr(obj,'__call__'):
348 and hasattr(obj,'__call__'):
345 call_ds = getdoc(obj.__call__)
349 call_ds = getdoc(obj.__call__)
346 if call_ds:
350 if call_ds:
347 lines.append(head("Calling Docstring:"))
351 lines.append(head("Calling Docstring:"))
348 lines.append(indent(call_ds))
352 lines.append(indent(call_ds))
349
353
350 if not lines:
354 if not lines:
351 self.noinfo('documentation',oname)
355 self.noinfo('documentation',oname)
352 else:
356 else:
353 page.page('\n'.join(lines))
357 page.page('\n'.join(lines))
354
358
355 def psource(self,obj,oname=''):
359 def psource(self,obj,oname=''):
356 """Print the source code for an object."""
360 """Print the source code for an object."""
357
361
358 # Flush the source cache because inspect can return out-of-date source
362 # Flush the source cache because inspect can return out-of-date source
359 linecache.checkcache()
363 linecache.checkcache()
360 try:
364 try:
361 src = getsource(obj)
365 src = getsource(obj)
362 except:
366 except:
363 self.noinfo('source',oname)
367 self.noinfo('source',oname)
364 else:
368 else:
365 page.page(self.format(src))
369 page.page(self.format(py3compat.unicode_to_str(src)))
366
370
367 def pfile(self,obj,oname=''):
371 def pfile(self,obj,oname=''):
368 """Show the whole file where an object was defined."""
372 """Show the whole file where an object was defined."""
369
373
370 try:
374 try:
371 try:
375 try:
372 lineno = inspect.getsourcelines(obj)[1]
376 lineno = inspect.getsourcelines(obj)[1]
373 except TypeError:
377 except TypeError:
374 # For instances, try the class object like getsource() does
378 # For instances, try the class object like getsource() does
375 if hasattr(obj,'__class__'):
379 if hasattr(obj,'__class__'):
376 lineno = inspect.getsourcelines(obj.__class__)[1]
380 lineno = inspect.getsourcelines(obj.__class__)[1]
377 # Adjust the inspected object so getabsfile() below works
381 # Adjust the inspected object so getabsfile() below works
378 obj = obj.__class__
382 obj = obj.__class__
379 except:
383 except:
380 self.noinfo('file',oname)
384 self.noinfo('file',oname)
381 return
385 return
382
386
383 # We only reach this point if object was successfully queried
387 # We only reach this point if object was successfully queried
384
388
385 # run contents of file through pager starting at line
389 # run contents of file through pager starting at line
386 # where the object is defined
390 # where the object is defined
387 ofile = inspect.getabsfile(obj)
391 ofile = inspect.getabsfile(obj)
388
392
389 if ofile.endswith(('.so', '.dll', '.pyd')):
393 if ofile.endswith(('.so', '.dll', '.pyd')):
390 print 'File %r is binary, not printing.' % ofile
394 print 'File %r is binary, not printing.' % ofile
391 elif not os.path.isfile(ofile):
395 elif not os.path.isfile(ofile):
392 print 'File %r does not exist, not printing.' % ofile
396 print 'File %r does not exist, not printing.' % ofile
393 else:
397 else:
394 # Print only text files, not extension binaries. Note that
398 # Print only text files, not extension binaries. Note that
395 # getsourcelines returns lineno with 1-offset and page() uses
399 # getsourcelines returns lineno with 1-offset and page() uses
396 # 0-offset, so we must adjust.
400 # 0-offset, so we must adjust.
397 page.page(self.format(open(ofile).read()),lineno-1)
401 page.page(self.format(open(ofile).read()),lineno-1)
398
402
399 def _format_fields(self, fields, title_width=12):
403 def _format_fields(self, fields, title_width=12):
400 """Formats a list of fields for display.
404 """Formats a list of fields for display.
401
405
402 Parameters
406 Parameters
403 ----------
407 ----------
404 fields : list
408 fields : list
405 A list of 2-tuples: (field_title, field_content)
409 A list of 2-tuples: (field_title, field_content)
406 title_width : int
410 title_width : int
407 How many characters to pad titles to. Default 12.
411 How many characters to pad titles to. Default 12.
408 """
412 """
409 out = []
413 out = []
410 header = self.__head
414 header = self.__head
411 for title, content in fields:
415 for title, content in fields:
412 if len(content.splitlines()) > 1:
416 if len(content.splitlines()) > 1:
413 title = header(title + ":") + "\n"
417 title = header(title + ":") + "\n"
414 else:
418 else:
415 title = header((title+":").ljust(title_width))
419 title = header((title+":").ljust(title_width))
416 out.append(title + content)
420 out.append(title + content)
417 return "\n".join(out)
421 return "\n".join(out)
418
422
419 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
423 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
420 pinfo_fields1 = [("Type", "type_name"),
424 pinfo_fields1 = [("Type", "type_name"),
421 ("Base Class", "base_class"),
425 ("Base Class", "base_class"),
422 ("String Form", "string_form"),
426 ("String Form", "string_form"),
423 ("Namespace", "namespace"),
427 ("Namespace", "namespace"),
424 ("Length", "length"),
428 ("Length", "length"),
425 ("File", "file"),
429 ("File", "file"),
426 ("Definition", "definition")]
430 ("Definition", "definition")]
427
431
428 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
432 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
429 ("Constructor Docstring","init_docstring"),
433 ("Constructor Docstring","init_docstring"),
430 ("Call def", "call_def"),
434 ("Call def", "call_def"),
431 ("Call docstring", "call_docstring")]
435 ("Call docstring", "call_docstring")]
432
436
433 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
437 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
434 """Show detailed information about an object.
438 """Show detailed information about an object.
435
439
436 Optional arguments:
440 Optional arguments:
437
441
438 - oname: name of the variable pointing to the object.
442 - oname: name of the variable pointing to the object.
439
443
440 - formatter: special formatter for docstrings (see pdoc)
444 - formatter: special formatter for docstrings (see pdoc)
441
445
442 - info: a structure with some information fields which may have been
446 - info: a structure with some information fields which may have been
443 precomputed already.
447 precomputed already.
444
448
445 - detail_level: if set to 1, more information is given.
449 - detail_level: if set to 1, more information is given.
446 """
450 """
447 info = self.info(obj, oname=oname, formatter=formatter,
451 info = self.info(obj, oname=oname, formatter=formatter,
448 info=info, detail_level=detail_level)
452 info=info, detail_level=detail_level)
449 displayfields = []
453 displayfields = []
450 for title, key in self.pinfo_fields1:
454 for title, key in self.pinfo_fields1:
451 field = info[key]
455 field = info[key]
452 if field is not None:
456 if field is not None:
453 displayfields.append((title, field.rstrip()))
457 displayfields.append((title, field.rstrip()))
454
458
455 # Source or docstring, depending on detail level and whether
459 # Source or docstring, depending on detail level and whether
456 # source found.
460 # source found.
457 if detail_level > 0 and info['source'] is not None:
461 if detail_level > 0 and info['source'] is not None:
458 displayfields.append(("Source", info['source']))
462 displayfields.append(("Source", info['source']))
459 elif info['docstring'] is not None:
463 elif info['docstring'] is not None:
460 displayfields.append(("Docstring", info["docstring"]))
464 displayfields.append(("Docstring", info["docstring"]))
461
465
462 # Constructor info for classes
466 # Constructor info for classes
463 if info['isclass']:
467 if info['isclass']:
464 if info['init_definition'] or info['init_docstring']:
468 if info['init_definition'] or info['init_docstring']:
465 displayfields.append(("Constructor information", ""))
469 displayfields.append(("Constructor information", ""))
466 if info['init_definition'] is not None:
470 if info['init_definition'] is not None:
467 displayfields.append((" Definition",
471 displayfields.append((" Definition",
468 info['init_definition'].rstrip()))
472 info['init_definition'].rstrip()))
469 if info['init_docstring'] is not None:
473 if info['init_docstring'] is not None:
470 displayfields.append((" Docstring",
474 displayfields.append((" Docstring",
471 indent(info['init_docstring'])))
475 indent(info['init_docstring'])))
472
476
473 # Info for objects:
477 # Info for objects:
474 else:
478 else:
475 for title, key in self.pinfo_fields_obj:
479 for title, key in self.pinfo_fields_obj:
476 field = info[key]
480 field = info[key]
477 if field is not None:
481 if field is not None:
478 displayfields.append((title, field.rstrip()))
482 displayfields.append((title, field.rstrip()))
479
483
480 # Finally send to printer/pager:
484 # Finally send to printer/pager:
481 if displayfields:
485 if displayfields:
482 page.page(self._format_fields(displayfields))
486 page.page(self._format_fields(displayfields))
483
487
484 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
488 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
485 """Compute a dict with detailed information about an object.
489 """Compute a dict with detailed information about an object.
486
490
487 Optional arguments:
491 Optional arguments:
488
492
489 - oname: name of the variable pointing to the object.
493 - oname: name of the variable pointing to the object.
490
494
491 - formatter: special formatter for docstrings (see pdoc)
495 - formatter: special formatter for docstrings (see pdoc)
492
496
493 - info: a structure with some information fields which may have been
497 - info: a structure with some information fields which may have been
494 precomputed already.
498 precomputed already.
495
499
496 - detail_level: if set to 1, more information is given.
500 - detail_level: if set to 1, more information is given.
497 """
501 """
498
502
499 obj_type = type(obj)
503 obj_type = type(obj)
500
504
501 header = self.__head
505 header = self.__head
502 if info is None:
506 if info is None:
503 ismagic = 0
507 ismagic = 0
504 isalias = 0
508 isalias = 0
505 ospace = ''
509 ospace = ''
506 else:
510 else:
507 ismagic = info.ismagic
511 ismagic = info.ismagic
508 isalias = info.isalias
512 isalias = info.isalias
509 ospace = info.namespace
513 ospace = info.namespace
510
514
511 # Get docstring, special-casing aliases:
515 # Get docstring, special-casing aliases:
512 if isalias:
516 if isalias:
513 if not callable(obj):
517 if not callable(obj):
514 try:
518 try:
515 ds = "Alias to the system command:\n %s" % obj[1]
519 ds = "Alias to the system command:\n %s" % obj[1]
516 except:
520 except:
517 ds = "Alias: " + str(obj)
521 ds = "Alias: " + str(obj)
518 else:
522 else:
519 ds = "Alias to " + str(obj)
523 ds = "Alias to " + str(obj)
520 if obj.__doc__:
524 if obj.__doc__:
521 ds += "\nDocstring:\n" + obj.__doc__
525 ds += "\nDocstring:\n" + obj.__doc__
522 else:
526 else:
523 ds = getdoc(obj)
527 ds = getdoc(obj)
524 if ds is None:
528 if ds is None:
525 ds = '<no docstring>'
529 ds = '<no docstring>'
526 if formatter is not None:
530 if formatter is not None:
527 ds = formatter(ds)
531 ds = formatter(ds)
528
532
529 # store output in a dict, we initialize it here and fill it as we go
533 # store output in a dict, we initialize it here and fill it as we go
530 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
534 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
531
535
532 string_max = 200 # max size of strings to show (snipped if longer)
536 string_max = 200 # max size of strings to show (snipped if longer)
533 shalf = int((string_max -5)/2)
537 shalf = int((string_max -5)/2)
534
538
535 if ismagic:
539 if ismagic:
536 obj_type_name = 'Magic function'
540 obj_type_name = 'Magic function'
537 elif isalias:
541 elif isalias:
538 obj_type_name = 'System alias'
542 obj_type_name = 'System alias'
539 else:
543 else:
540 obj_type_name = obj_type.__name__
544 obj_type_name = obj_type.__name__
541 out['type_name'] = obj_type_name
545 out['type_name'] = obj_type_name
542
546
543 try:
547 try:
544 bclass = obj.__class__
548 bclass = obj.__class__
545 out['base_class'] = str(bclass)
549 out['base_class'] = str(bclass)
546 except: pass
550 except: pass
547
551
548 # String form, but snip if too long in ? form (full in ??)
552 # String form, but snip if too long in ? form (full in ??)
549 if detail_level >= self.str_detail_level:
553 if detail_level >= self.str_detail_level:
550 try:
554 try:
551 ostr = str(obj)
555 ostr = str(obj)
552 str_head = 'string_form'
556 str_head = 'string_form'
553 if not detail_level and len(ostr)>string_max:
557 if not detail_level and len(ostr)>string_max:
554 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
558 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
555 ostr = ("\n" + " " * len(str_head.expandtabs())).\
559 ostr = ("\n" + " " * len(str_head.expandtabs())).\
556 join(q.strip() for q in ostr.split("\n"))
560 join(q.strip() for q in ostr.split("\n"))
557 out[str_head] = ostr
561 out[str_head] = ostr
558 except:
562 except:
559 pass
563 pass
560
564
561 if ospace:
565 if ospace:
562 out['namespace'] = ospace
566 out['namespace'] = ospace
563
567
564 # Length (for strings and lists)
568 # Length (for strings and lists)
565 try:
569 try:
566 out['length'] = str(len(obj))
570 out['length'] = str(len(obj))
567 except: pass
571 except: pass
568
572
569 # Filename where object was defined
573 # Filename where object was defined
570 binary_file = False
574 binary_file = False
571 try:
575 try:
572 try:
576 try:
573 fname = inspect.getabsfile(obj)
577 fname = inspect.getabsfile(obj)
574 except TypeError:
578 except TypeError:
575 # For an instance, the file that matters is where its class was
579 # For an instance, the file that matters is where its class was
576 # declared.
580 # declared.
577 if hasattr(obj,'__class__'):
581 if hasattr(obj,'__class__'):
578 fname = inspect.getabsfile(obj.__class__)
582 fname = inspect.getabsfile(obj.__class__)
579 if fname.endswith('<string>'):
583 if fname.endswith('<string>'):
580 fname = 'Dynamically generated function. No source code available.'
584 fname = 'Dynamically generated function. No source code available.'
581 if fname.endswith(('.so', '.dll', '.pyd')):
585 if fname.endswith(('.so', '.dll', '.pyd')):
582 binary_file = True
586 binary_file = True
583 out['file'] = fname
587 out['file'] = fname
584 except:
588 except:
585 # if anything goes wrong, we don't want to show source, so it's as
589 # if anything goes wrong, we don't want to show source, so it's as
586 # if the file was binary
590 # if the file was binary
587 binary_file = True
591 binary_file = True
588
592
589 # reconstruct the function definition and print it:
593 # reconstruct the function definition and print it:
590 defln = self._getdef(obj, oname)
594 defln = self._getdef(obj, oname)
591 if defln:
595 if defln:
592 out['definition'] = self.format(defln)
596 out['definition'] = self.format(defln)
593
597
594 # Docstrings only in detail 0 mode, since source contains them (we
598 # Docstrings only in detail 0 mode, since source contains them (we
595 # avoid repetitions). If source fails, we add them back, see below.
599 # avoid repetitions). If source fails, we add them back, see below.
596 if ds and detail_level == 0:
600 if ds and detail_level == 0:
597 out['docstring'] = ds
601 out['docstring'] = ds
598
602
599 # Original source code for any callable
603 # Original source code for any callable
600 if detail_level:
604 if detail_level:
601 # Flush the source cache because inspect can return out-of-date
605 # Flush the source cache because inspect can return out-of-date
602 # source
606 # source
603 linecache.checkcache()
607 linecache.checkcache()
604 source = None
608 source = None
605 try:
609 try:
606 try:
610 try:
607 src = getsource(obj,binary_file)
611 src = getsource(obj,binary_file)
608 except TypeError:
612 except TypeError:
609 if hasattr(obj,'__class__'):
613 if hasattr(obj,'__class__'):
610 src = getsource(obj.__class__,binary_file)
614 src = getsource(obj.__class__,binary_file)
611 if src is not None:
615 if src is not None:
612 source = self.format(src)
616 source = self.format(src)
613 out['source'] = source.rstrip()
617 out['source'] = source.rstrip()
614 except Exception:
618 except Exception:
615 pass
619 pass
616
620
617 if ds and source is None:
621 if ds and source is None:
618 out['docstring'] = ds
622 out['docstring'] = ds
619
623
620
624
621 # Constructor docstring for classes
625 # Constructor docstring for classes
622 if inspect.isclass(obj):
626 if inspect.isclass(obj):
623 out['isclass'] = True
627 out['isclass'] = True
624 # reconstruct the function definition and print it:
628 # reconstruct the function definition and print it:
625 try:
629 try:
626 obj_init = obj.__init__
630 obj_init = obj.__init__
627 except AttributeError:
631 except AttributeError:
628 init_def = init_ds = None
632 init_def = init_ds = None
629 else:
633 else:
630 init_def = self._getdef(obj_init,oname)
634 init_def = self._getdef(obj_init,oname)
631 init_ds = getdoc(obj_init)
635 init_ds = getdoc(obj_init)
632 # Skip Python's auto-generated docstrings
636 # Skip Python's auto-generated docstrings
633 if init_ds and \
637 if init_ds and \
634 init_ds.startswith('x.__init__(...) initializes'):
638 init_ds.startswith('x.__init__(...) initializes'):
635 init_ds = None
639 init_ds = None
636
640
637 if init_def or init_ds:
641 if init_def or init_ds:
638 if init_def:
642 if init_def:
639 out['init_definition'] = self.format(init_def)
643 out['init_definition'] = self.format(init_def)
640 if init_ds:
644 if init_ds:
641 out['init_docstring'] = init_ds
645 out['init_docstring'] = init_ds
642
646
643 # and class docstring for instances:
647 # and class docstring for instances:
644 else:
648 else:
645 # First, check whether the instance docstring is identical to the
649 # First, check whether the instance docstring is identical to the
646 # class one, and print it separately if they don't coincide. In
650 # class one, and print it separately if they don't coincide. In
647 # most cases they will, but it's nice to print all the info for
651 # most cases they will, but it's nice to print all the info for
648 # objects which use instance-customized docstrings.
652 # objects which use instance-customized docstrings.
649 if ds:
653 if ds:
650 try:
654 try:
651 cls = getattr(obj,'__class__')
655 cls = getattr(obj,'__class__')
652 except:
656 except:
653 class_ds = None
657 class_ds = None
654 else:
658 else:
655 class_ds = getdoc(cls)
659 class_ds = getdoc(cls)
656 # Skip Python's auto-generated docstrings
660 # Skip Python's auto-generated docstrings
657 if class_ds and \
661 if class_ds and \
658 (class_ds.startswith('function(code, globals[,') or \
662 (class_ds.startswith('function(code, globals[,') or \
659 class_ds.startswith('instancemethod(function, instance,') or \
663 class_ds.startswith('instancemethod(function, instance,') or \
660 class_ds.startswith('module(name[,') ):
664 class_ds.startswith('module(name[,') ):
661 class_ds = None
665 class_ds = None
662 if class_ds and ds != class_ds:
666 if class_ds and ds != class_ds:
663 out['class_docstring'] = class_ds
667 out['class_docstring'] = class_ds
664
668
665 # Next, try to show constructor docstrings
669 # Next, try to show constructor docstrings
666 try:
670 try:
667 init_ds = getdoc(obj.__init__)
671 init_ds = getdoc(obj.__init__)
668 # Skip Python's auto-generated docstrings
672 # Skip Python's auto-generated docstrings
669 if init_ds and \
673 if init_ds and \
670 init_ds.startswith('x.__init__(...) initializes'):
674 init_ds.startswith('x.__init__(...) initializes'):
671 init_ds = None
675 init_ds = None
672 except AttributeError:
676 except AttributeError:
673 init_ds = None
677 init_ds = None
674 if init_ds:
678 if init_ds:
675 out['init_docstring'] = init_ds
679 out['init_docstring'] = init_ds
676
680
677 # Call form docstring for callable instances
681 # Call form docstring for callable instances
678 if hasattr(obj, '__call__'):
682 if hasattr(obj, '__call__'):
679 call_def = self._getdef(obj.__call__, oname)
683 call_def = self._getdef(obj.__call__, oname)
680 if call_def is not None:
684 if call_def is not None:
681 out['call_def'] = self.format(call_def)
685 out['call_def'] = self.format(call_def)
682 call_ds = getdoc(obj.__call__)
686 call_ds = getdoc(obj.__call__)
683 # Skip Python's auto-generated docstrings
687 # Skip Python's auto-generated docstrings
684 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
688 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
685 call_ds = None
689 call_ds = None
686 if call_ds:
690 if call_ds:
687 out['call_docstring'] = call_ds
691 out['call_docstring'] = call_ds
688
692
689 # Compute the object's argspec as a callable. The key is to decide
693 # Compute the object's argspec as a callable. The key is to decide
690 # whether to pull it from the object itself, from its __init__ or
694 # whether to pull it from the object itself, from its __init__ or
691 # from its __call__ method.
695 # from its __call__ method.
692
696
693 if inspect.isclass(obj):
697 if inspect.isclass(obj):
694 # Old-style classes need not have an __init__
698 # Old-style classes need not have an __init__
695 callable_obj = getattr(obj, "__init__", None)
699 callable_obj = getattr(obj, "__init__", None)
696 elif callable(obj):
700 elif callable(obj):
697 callable_obj = obj
701 callable_obj = obj
698 else:
702 else:
699 callable_obj = None
703 callable_obj = None
700
704
701 if callable_obj:
705 if callable_obj:
702 try:
706 try:
703 args, varargs, varkw, defaults = getargspec(callable_obj)
707 args, varargs, varkw, defaults = getargspec(callable_obj)
704 except (TypeError, AttributeError):
708 except (TypeError, AttributeError):
705 # For extensions/builtins we can't retrieve the argspec
709 # For extensions/builtins we can't retrieve the argspec
706 pass
710 pass
707 else:
711 else:
708 out['argspec'] = dict(args=args, varargs=varargs,
712 out['argspec'] = dict(args=args, varargs=varargs,
709 varkw=varkw, defaults=defaults)
713 varkw=varkw, defaults=defaults)
710
714
711 return object_info(**out)
715 return object_info(**out)
712
716
713
717
714 def psearch(self,pattern,ns_table,ns_search=[],
718 def psearch(self,pattern,ns_table,ns_search=[],
715 ignore_case=False,show_all=False):
719 ignore_case=False,show_all=False):
716 """Search namespaces with wildcards for objects.
720 """Search namespaces with wildcards for objects.
717
721
718 Arguments:
722 Arguments:
719
723
720 - pattern: string containing shell-like wildcards to use in namespace
724 - pattern: string containing shell-like wildcards to use in namespace
721 searches and optionally a type specification to narrow the search to
725 searches and optionally a type specification to narrow the search to
722 objects of that type.
726 objects of that type.
723
727
724 - ns_table: dict of name->namespaces for search.
728 - ns_table: dict of name->namespaces for search.
725
729
726 Optional arguments:
730 Optional arguments:
727
731
728 - ns_search: list of namespace names to include in search.
732 - ns_search: list of namespace names to include in search.
729
733
730 - ignore_case(False): make the search case-insensitive.
734 - ignore_case(False): make the search case-insensitive.
731
735
732 - show_all(False): show all names, including those starting with
736 - show_all(False): show all names, including those starting with
733 underscores.
737 underscores.
734 """
738 """
735 #print 'ps pattern:<%r>' % pattern # dbg
739 #print 'ps pattern:<%r>' % pattern # dbg
736
740
737 # defaults
741 # defaults
738 type_pattern = 'all'
742 type_pattern = 'all'
739 filter = ''
743 filter = ''
740
744
741 cmds = pattern.split()
745 cmds = pattern.split()
742 len_cmds = len(cmds)
746 len_cmds = len(cmds)
743 if len_cmds == 1:
747 if len_cmds == 1:
744 # Only filter pattern given
748 # Only filter pattern given
745 filter = cmds[0]
749 filter = cmds[0]
746 elif len_cmds == 2:
750 elif len_cmds == 2:
747 # Both filter and type specified
751 # Both filter and type specified
748 filter,type_pattern = cmds
752 filter,type_pattern = cmds
749 else:
753 else:
750 raise ValueError('invalid argument string for psearch: <%s>' %
754 raise ValueError('invalid argument string for psearch: <%s>' %
751 pattern)
755 pattern)
752
756
753 # filter search namespaces
757 # filter search namespaces
754 for name in ns_search:
758 for name in ns_search:
755 if name not in ns_table:
759 if name not in ns_table:
756 raise ValueError('invalid namespace <%s>. Valid names: %s' %
760 raise ValueError('invalid namespace <%s>. Valid names: %s' %
757 (name,ns_table.keys()))
761 (name,ns_table.keys()))
758
762
759 #print 'type_pattern:',type_pattern # dbg
763 #print 'type_pattern:',type_pattern # dbg
760 search_result = []
764 search_result = []
761 for ns_name in ns_search:
765 for ns_name in ns_search:
762 ns = ns_table[ns_name]
766 ns = ns_table[ns_name]
763 tmp_res = list(list_namespace(ns,type_pattern,filter,
767 tmp_res = list(list_namespace(ns,type_pattern,filter,
764 ignore_case=ignore_case,
768 ignore_case=ignore_case,
765 show_all=show_all))
769 show_all=show_all))
766 search_result.extend(tmp_res)
770 search_result.extend(tmp_res)
767 search_result.sort()
771 search_result.sort()
768
772
769 page.page('\n'.join(search_result))
773 page.page('\n'.join(search_result))
@@ -1,1012 +1,1015 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Prefiltering components.
3 Prefiltering components.
4
4
5 Prefilters transform user input before it is exec'd by Python. These
5 Prefilters transform user input before it is exec'd by Python. These
6 transforms are used to implement additional syntax such as !ls and %magic.
6 transforms are used to implement additional syntax such as !ls and %magic.
7
7
8 Authors:
8 Authors:
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Dan Milstein
12 * Dan Milstein
13 * Ville Vainio
13 * Ville Vainio
14 """
14 """
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Copyright (C) 2008-2009 The IPython Development Team
17 # Copyright (C) 2008-2009 The IPython Development Team
18 #
18 #
19 # Distributed under the terms of the BSD License. The full license is in
19 # Distributed under the terms of the BSD License. The full license is in
20 # the file COPYING, distributed as part of this software.
20 # the file COPYING, distributed as part of this software.
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Imports
24 # Imports
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 import __builtin__
27 import __builtin__
28 import codeop
28 import codeop
29 import re
29 import re
30
30
31 from IPython.core.alias import AliasManager
31 from IPython.core.alias import AliasManager
32 from IPython.core.autocall import IPyAutocall
32 from IPython.core.autocall import IPyAutocall
33 from IPython.config.configurable import Configurable
33 from IPython.config.configurable import Configurable
34 from IPython.core.macro import Macro
34 from IPython.core.macro import Macro
35 from IPython.core.splitinput import split_user_input
35 from IPython.core.splitinput import split_user_input
36 from IPython.core import page
36 from IPython.core import page
37
37
38 from IPython.utils.traitlets import List, Int, Any, Unicode, CBool, Bool, Instance
38 from IPython.utils.traitlets import List, Int, Any, Unicode, CBool, Bool, Instance
39 from IPython.utils.text import make_quoted_expr
39 from IPython.utils.text import make_quoted_expr
40 from IPython.utils.autoattr import auto_attr
40 from IPython.utils.autoattr import auto_attr
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Global utilities, errors and constants
43 # Global utilities, errors and constants
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 # Warning, these cannot be changed unless various regular expressions
46 # Warning, these cannot be changed unless various regular expressions
47 # are updated in a number of places. Not great, but at least we told you.
47 # are updated in a number of places. Not great, but at least we told you.
48 ESC_SHELL = '!'
48 ESC_SHELL = '!'
49 ESC_SH_CAP = '!!'
49 ESC_SH_CAP = '!!'
50 ESC_HELP = '?'
50 ESC_HELP = '?'
51 ESC_MAGIC = '%'
51 ESC_MAGIC = '%'
52 ESC_QUOTE = ','
52 ESC_QUOTE = ','
53 ESC_QUOTE2 = ';'
53 ESC_QUOTE2 = ';'
54 ESC_PAREN = '/'
54 ESC_PAREN = '/'
55
55
56
56
57 class PrefilterError(Exception):
57 class PrefilterError(Exception):
58 pass
58 pass
59
59
60
60
61 # RegExp to identify potential function names
61 # RegExp to identify potential function names
62 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
62 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
63
63
64 # RegExp to exclude strings with this start from autocalling. In
64 # RegExp to exclude strings with this start from autocalling. In
65 # particular, all binary operators should be excluded, so that if foo is
65 # particular, all binary operators should be excluded, so that if foo is
66 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
66 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
67 # characters '!=()' don't need to be checked for, as the checkPythonChars
67 # characters '!=()' don't need to be checked for, as the checkPythonChars
68 # routine explicitely does so, to catch direct calls and rebindings of
68 # routine explicitely does so, to catch direct calls and rebindings of
69 # existing names.
69 # existing names.
70
70
71 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
71 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
72 # it affects the rest of the group in square brackets.
72 # it affects the rest of the group in square brackets.
73 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
73 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
74 r'|^is |^not |^in |^and |^or ')
74 r'|^is |^not |^in |^and |^or ')
75
75
76 # try to catch also methods for stuff in lists/tuples/dicts: off
76 # try to catch also methods for stuff in lists/tuples/dicts: off
77 # (experimental). For this to work, the line_split regexp would need
77 # (experimental). For this to work, the line_split regexp would need
78 # to be modified so it wouldn't break things at '['. That line is
78 # to be modified so it wouldn't break things at '['. That line is
79 # nasty enough that I shouldn't change it until I can test it _well_.
79 # nasty enough that I shouldn't change it until I can test it _well_.
80 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
80 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
81
81
82
82
83 # Handler Check Utilities
83 # Handler Check Utilities
84 def is_shadowed(identifier, ip):
84 def is_shadowed(identifier, ip):
85 """Is the given identifier defined in one of the namespaces which shadow
85 """Is the given identifier defined in one of the namespaces which shadow
86 the alias and magic namespaces? Note that an identifier is different
86 the alias and magic namespaces? Note that an identifier is different
87 than ifun, because it can not contain a '.' character."""
87 than ifun, because it can not contain a '.' character."""
88 # This is much safer than calling ofind, which can change state
88 # This is much safer than calling ofind, which can change state
89 return (identifier in ip.user_ns \
89 return (identifier in ip.user_ns \
90 or identifier in ip.internal_ns \
90 or identifier in ip.internal_ns \
91 or identifier in ip.ns_table['builtin'])
91 or identifier in ip.ns_table['builtin'])
92
92
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # The LineInfo class used throughout
95 # The LineInfo class used throughout
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97
97
98
98
99 class LineInfo(object):
99 class LineInfo(object):
100 """A single line of input and associated info.
100 """A single line of input and associated info.
101
101
102 Includes the following as properties:
102 Includes the following as properties:
103
103
104 line
104 line
105 The original, raw line
105 The original, raw line
106
106
107 continue_prompt
107 continue_prompt
108 Is this line a continuation in a sequence of multiline input?
108 Is this line a continuation in a sequence of multiline input?
109
109
110 pre
110 pre
111 The initial esc character or whitespace.
111 The initial esc character or whitespace.
112
112
113 pre_char
113 pre_char
114 The escape character(s) in pre or the empty string if there isn't one.
114 The escape character(s) in pre or the empty string if there isn't one.
115 Note that '!!' is a possible value for pre_char. Otherwise it will
115 Note that '!!' is a possible value for pre_char. Otherwise it will
116 always be a single character.
116 always be a single character.
117
117
118 pre_whitespace
118 pre_whitespace
119 The leading whitespace from pre if it exists. If there is a pre_char,
119 The leading whitespace from pre if it exists. If there is a pre_char,
120 this is just ''.
120 this is just ''.
121
121
122 ifun
122 ifun
123 The 'function part', which is basically the maximal initial sequence
123 The 'function part', which is basically the maximal initial sequence
124 of valid python identifiers and the '.' character. This is what is
124 of valid python identifiers and the '.' character. This is what is
125 checked for alias and magic transformations, used for auto-calling,
125 checked for alias and magic transformations, used for auto-calling,
126 etc.
126 etc.
127
127
128 the_rest
128 the_rest
129 Everything else on the line.
129 Everything else on the line.
130 """
130 """
131 def __init__(self, line, continue_prompt):
131 def __init__(self, line, continue_prompt):
132 self.line = line
132 self.line = line
133 self.continue_prompt = continue_prompt
133 self.continue_prompt = continue_prompt
134 self.pre, self.ifun, self.the_rest = split_user_input(line)
134 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
135
135
136 self.pre_char = self.pre.strip()
136 self.pre_char = self.pre.strip()
137 if self.pre_char:
137 if self.pre_char:
138 self.pre_whitespace = '' # No whitespace allowd before esc chars
138 self.pre_whitespace = '' # No whitespace allowd before esc chars
139 else:
139 else:
140 self.pre_whitespace = self.pre
140 self.pre_whitespace = self.pre
141
141
142 self._oinfo = None
142 self._oinfo = None
143
143
144 def ofind(self, ip):
144 def ofind(self, ip):
145 """Do a full, attribute-walking lookup of the ifun in the various
145 """Do a full, attribute-walking lookup of the ifun in the various
146 namespaces for the given IPython InteractiveShell instance.
146 namespaces for the given IPython InteractiveShell instance.
147
147
148 Return a dict with keys: found,obj,ospace,ismagic
148 Return a dict with keys: found,obj,ospace,ismagic
149
149
150 Note: can cause state changes because of calling getattr, but should
150 Note: can cause state changes because of calling getattr, but should
151 only be run if autocall is on and if the line hasn't matched any
151 only be run if autocall is on and if the line hasn't matched any
152 other, less dangerous handlers.
152 other, less dangerous handlers.
153
153
154 Does cache the results of the call, so can be called multiple times
154 Does cache the results of the call, so can be called multiple times
155 without worrying about *further* damaging state.
155 without worrying about *further* damaging state.
156 """
156 """
157 if not self._oinfo:
157 if not self._oinfo:
158 # ip.shell._ofind is actually on the Magic class!
158 # ip.shell._ofind is actually on the Magic class!
159 self._oinfo = ip.shell._ofind(self.ifun)
159 self._oinfo = ip.shell._ofind(self.ifun)
160 return self._oinfo
160 return self._oinfo
161
161
162 def __str__(self):
162 def __str__(self):
163 return "Lineinfo [%s|%s|%s]" %(self.pre, self.ifun, self.the_rest)
163 return "Lineinfo [%s|%s|%s]" %(self.pre, self.ifun, self.the_rest)
164
164
165
165
166 #-----------------------------------------------------------------------------
166 #-----------------------------------------------------------------------------
167 # Main Prefilter manager
167 # Main Prefilter manager
168 #-----------------------------------------------------------------------------
168 #-----------------------------------------------------------------------------
169
169
170
170
171 class PrefilterManager(Configurable):
171 class PrefilterManager(Configurable):
172 """Main prefilter component.
172 """Main prefilter component.
173
173
174 The IPython prefilter is run on all user input before it is run. The
174 The IPython prefilter is run on all user input before it is run. The
175 prefilter consumes lines of input and produces transformed lines of
175 prefilter consumes lines of input and produces transformed lines of
176 input.
176 input.
177
177
178 The iplementation consists of two phases:
178 The iplementation consists of two phases:
179
179
180 1. Transformers
180 1. Transformers
181 2. Checkers and handlers
181 2. Checkers and handlers
182
182
183 Over time, we plan on deprecating the checkers and handlers and doing
183 Over time, we plan on deprecating the checkers and handlers and doing
184 everything in the transformers.
184 everything in the transformers.
185
185
186 The transformers are instances of :class:`PrefilterTransformer` and have
186 The transformers are instances of :class:`PrefilterTransformer` and have
187 a single method :meth:`transform` that takes a line and returns a
187 a single method :meth:`transform` that takes a line and returns a
188 transformed line. The transformation can be accomplished using any
188 transformed line. The transformation can be accomplished using any
189 tool, but our current ones use regular expressions for speed. We also
189 tool, but our current ones use regular expressions for speed. We also
190 ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers.
190 ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers.
191
191
192 After all the transformers have been run, the line is fed to the checkers,
192 After all the transformers have been run, the line is fed to the checkers,
193 which are instances of :class:`PrefilterChecker`. The line is passed to
193 which are instances of :class:`PrefilterChecker`. The line is passed to
194 the :meth:`check` method, which either returns `None` or a
194 the :meth:`check` method, which either returns `None` or a
195 :class:`PrefilterHandler` instance. If `None` is returned, the other
195 :class:`PrefilterHandler` instance. If `None` is returned, the other
196 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
196 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
197 the line is passed to the :meth:`handle` method of the returned
197 the line is passed to the :meth:`handle` method of the returned
198 handler and no further checkers are tried.
198 handler and no further checkers are tried.
199
199
200 Both transformers and checkers have a `priority` attribute, that determines
200 Both transformers and checkers have a `priority` attribute, that determines
201 the order in which they are called. Smaller priorities are tried first.
201 the order in which they are called. Smaller priorities are tried first.
202
202
203 Both transformers and checkers also have `enabled` attribute, which is
203 Both transformers and checkers also have `enabled` attribute, which is
204 a boolean that determines if the instance is used.
204 a boolean that determines if the instance is used.
205
205
206 Users or developers can change the priority or enabled attribute of
206 Users or developers can change the priority or enabled attribute of
207 transformers or checkers, but they must call the :meth:`sort_checkers`
207 transformers or checkers, but they must call the :meth:`sort_checkers`
208 or :meth:`sort_transformers` method after changing the priority.
208 or :meth:`sort_transformers` method after changing the priority.
209 """
209 """
210
210
211 multi_line_specials = CBool(True, config=True)
211 multi_line_specials = CBool(True, config=True)
212 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
212 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
213
213
214 def __init__(self, shell=None, config=None):
214 def __init__(self, shell=None, config=None):
215 super(PrefilterManager, self).__init__(shell=shell, config=config)
215 super(PrefilterManager, self).__init__(shell=shell, config=config)
216 self.shell = shell
216 self.shell = shell
217 self.init_transformers()
217 self.init_transformers()
218 self.init_handlers()
218 self.init_handlers()
219 self.init_checkers()
219 self.init_checkers()
220
220
221 #-------------------------------------------------------------------------
221 #-------------------------------------------------------------------------
222 # API for managing transformers
222 # API for managing transformers
223 #-------------------------------------------------------------------------
223 #-------------------------------------------------------------------------
224
224
225 def init_transformers(self):
225 def init_transformers(self):
226 """Create the default transformers."""
226 """Create the default transformers."""
227 self._transformers = []
227 self._transformers = []
228 for transformer_cls in _default_transformers:
228 for transformer_cls in _default_transformers:
229 transformer_cls(
229 transformer_cls(
230 shell=self.shell, prefilter_manager=self, config=self.config
230 shell=self.shell, prefilter_manager=self, config=self.config
231 )
231 )
232
232
233 def sort_transformers(self):
233 def sort_transformers(self):
234 """Sort the transformers by priority.
234 """Sort the transformers by priority.
235
235
236 This must be called after the priority of a transformer is changed.
236 This must be called after the priority of a transformer is changed.
237 The :meth:`register_transformer` method calls this automatically.
237 The :meth:`register_transformer` method calls this automatically.
238 """
238 """
239 self._transformers.sort(key=lambda x: x.priority)
239 self._transformers.sort(key=lambda x: x.priority)
240
240
241 @property
241 @property
242 def transformers(self):
242 def transformers(self):
243 """Return a list of checkers, sorted by priority."""
243 """Return a list of checkers, sorted by priority."""
244 return self._transformers
244 return self._transformers
245
245
246 def register_transformer(self, transformer):
246 def register_transformer(self, transformer):
247 """Register a transformer instance."""
247 """Register a transformer instance."""
248 if transformer not in self._transformers:
248 if transformer not in self._transformers:
249 self._transformers.append(transformer)
249 self._transformers.append(transformer)
250 self.sort_transformers()
250 self.sort_transformers()
251
251
252 def unregister_transformer(self, transformer):
252 def unregister_transformer(self, transformer):
253 """Unregister a transformer instance."""
253 """Unregister a transformer instance."""
254 if transformer in self._transformers:
254 if transformer in self._transformers:
255 self._transformers.remove(transformer)
255 self._transformers.remove(transformer)
256
256
257 #-------------------------------------------------------------------------
257 #-------------------------------------------------------------------------
258 # API for managing checkers
258 # API for managing checkers
259 #-------------------------------------------------------------------------
259 #-------------------------------------------------------------------------
260
260
261 def init_checkers(self):
261 def init_checkers(self):
262 """Create the default checkers."""
262 """Create the default checkers."""
263 self._checkers = []
263 self._checkers = []
264 for checker in _default_checkers:
264 for checker in _default_checkers:
265 checker(
265 checker(
266 shell=self.shell, prefilter_manager=self, config=self.config
266 shell=self.shell, prefilter_manager=self, config=self.config
267 )
267 )
268
268
269 def sort_checkers(self):
269 def sort_checkers(self):
270 """Sort the checkers by priority.
270 """Sort the checkers by priority.
271
271
272 This must be called after the priority of a checker is changed.
272 This must be called after the priority of a checker is changed.
273 The :meth:`register_checker` method calls this automatically.
273 The :meth:`register_checker` method calls this automatically.
274 """
274 """
275 self._checkers.sort(key=lambda x: x.priority)
275 self._checkers.sort(key=lambda x: x.priority)
276
276
277 @property
277 @property
278 def checkers(self):
278 def checkers(self):
279 """Return a list of checkers, sorted by priority."""
279 """Return a list of checkers, sorted by priority."""
280 return self._checkers
280 return self._checkers
281
281
282 def register_checker(self, checker):
282 def register_checker(self, checker):
283 """Register a checker instance."""
283 """Register a checker instance."""
284 if checker not in self._checkers:
284 if checker not in self._checkers:
285 self._checkers.append(checker)
285 self._checkers.append(checker)
286 self.sort_checkers()
286 self.sort_checkers()
287
287
288 def unregister_checker(self, checker):
288 def unregister_checker(self, checker):
289 """Unregister a checker instance."""
289 """Unregister a checker instance."""
290 if checker in self._checkers:
290 if checker in self._checkers:
291 self._checkers.remove(checker)
291 self._checkers.remove(checker)
292
292
293 #-------------------------------------------------------------------------
293 #-------------------------------------------------------------------------
294 # API for managing checkers
294 # API for managing checkers
295 #-------------------------------------------------------------------------
295 #-------------------------------------------------------------------------
296
296
297 def init_handlers(self):
297 def init_handlers(self):
298 """Create the default handlers."""
298 """Create the default handlers."""
299 self._handlers = {}
299 self._handlers = {}
300 self._esc_handlers = {}
300 self._esc_handlers = {}
301 for handler in _default_handlers:
301 for handler in _default_handlers:
302 handler(
302 handler(
303 shell=self.shell, prefilter_manager=self, config=self.config
303 shell=self.shell, prefilter_manager=self, config=self.config
304 )
304 )
305
305
306 @property
306 @property
307 def handlers(self):
307 def handlers(self):
308 """Return a dict of all the handlers."""
308 """Return a dict of all the handlers."""
309 return self._handlers
309 return self._handlers
310
310
311 def register_handler(self, name, handler, esc_strings):
311 def register_handler(self, name, handler, esc_strings):
312 """Register a handler instance by name with esc_strings."""
312 """Register a handler instance by name with esc_strings."""
313 self._handlers[name] = handler
313 self._handlers[name] = handler
314 for esc_str in esc_strings:
314 for esc_str in esc_strings:
315 self._esc_handlers[esc_str] = handler
315 self._esc_handlers[esc_str] = handler
316
316
317 def unregister_handler(self, name, handler, esc_strings):
317 def unregister_handler(self, name, handler, esc_strings):
318 """Unregister a handler instance by name with esc_strings."""
318 """Unregister a handler instance by name with esc_strings."""
319 try:
319 try:
320 del self._handlers[name]
320 del self._handlers[name]
321 except KeyError:
321 except KeyError:
322 pass
322 pass
323 for esc_str in esc_strings:
323 for esc_str in esc_strings:
324 h = self._esc_handlers.get(esc_str)
324 h = self._esc_handlers.get(esc_str)
325 if h is handler:
325 if h is handler:
326 del self._esc_handlers[esc_str]
326 del self._esc_handlers[esc_str]
327
327
328 def get_handler_by_name(self, name):
328 def get_handler_by_name(self, name):
329 """Get a handler by its name."""
329 """Get a handler by its name."""
330 return self._handlers.get(name)
330 return self._handlers.get(name)
331
331
332 def get_handler_by_esc(self, esc_str):
332 def get_handler_by_esc(self, esc_str):
333 """Get a handler by its escape string."""
333 """Get a handler by its escape string."""
334 return self._esc_handlers.get(esc_str)
334 return self._esc_handlers.get(esc_str)
335
335
336 #-------------------------------------------------------------------------
336 #-------------------------------------------------------------------------
337 # Main prefiltering API
337 # Main prefiltering API
338 #-------------------------------------------------------------------------
338 #-------------------------------------------------------------------------
339
339
340 def prefilter_line_info(self, line_info):
340 def prefilter_line_info(self, line_info):
341 """Prefilter a line that has been converted to a LineInfo object.
341 """Prefilter a line that has been converted to a LineInfo object.
342
342
343 This implements the checker/handler part of the prefilter pipe.
343 This implements the checker/handler part of the prefilter pipe.
344 """
344 """
345 # print "prefilter_line_info: ", line_info
345 # print "prefilter_line_info: ", line_info
346 handler = self.find_handler(line_info)
346 handler = self.find_handler(line_info)
347 return handler.handle(line_info)
347 return handler.handle(line_info)
348
348
349 def find_handler(self, line_info):
349 def find_handler(self, line_info):
350 """Find a handler for the line_info by trying checkers."""
350 """Find a handler for the line_info by trying checkers."""
351 for checker in self.checkers:
351 for checker in self.checkers:
352 if checker.enabled:
352 if checker.enabled:
353 handler = checker.check(line_info)
353 handler = checker.check(line_info)
354 if handler:
354 if handler:
355 return handler
355 return handler
356 return self.get_handler_by_name('normal')
356 return self.get_handler_by_name('normal')
357
357
358 def transform_line(self, line, continue_prompt):
358 def transform_line(self, line, continue_prompt):
359 """Calls the enabled transformers in order of increasing priority."""
359 """Calls the enabled transformers in order of increasing priority."""
360 for transformer in self.transformers:
360 for transformer in self.transformers:
361 if transformer.enabled:
361 if transformer.enabled:
362 line = transformer.transform(line, continue_prompt)
362 line = transformer.transform(line, continue_prompt)
363 return line
363 return line
364
364
365 def prefilter_line(self, line, continue_prompt=False):
365 def prefilter_line(self, line, continue_prompt=False):
366 """Prefilter a single input line as text.
366 """Prefilter a single input line as text.
367
367
368 This method prefilters a single line of text by calling the
368 This method prefilters a single line of text by calling the
369 transformers and then the checkers/handlers.
369 transformers and then the checkers/handlers.
370 """
370 """
371
371
372 # print "prefilter_line: ", line, continue_prompt
372 # print "prefilter_line: ", line, continue_prompt
373 # All handlers *must* return a value, even if it's blank ('').
373 # All handlers *must* return a value, even if it's blank ('').
374
374
375 # save the line away in case we crash, so the post-mortem handler can
375 # save the line away in case we crash, so the post-mortem handler can
376 # record it
376 # record it
377 self.shell._last_input_line = line
377 self.shell._last_input_line = line
378
378
379 if not line:
379 if not line:
380 # Return immediately on purely empty lines, so that if the user
380 # Return immediately on purely empty lines, so that if the user
381 # previously typed some whitespace that started a continuation
381 # previously typed some whitespace that started a continuation
382 # prompt, he can break out of that loop with just an empty line.
382 # prompt, he can break out of that loop with just an empty line.
383 # This is how the default python prompt works.
383 # This is how the default python prompt works.
384 return ''
384 return ''
385
385
386 # At this point, we invoke our transformers.
386 # At this point, we invoke our transformers.
387 if not continue_prompt or (continue_prompt and self.multi_line_specials):
387 if not continue_prompt or (continue_prompt and self.multi_line_specials):
388 line = self.transform_line(line, continue_prompt)
388 line = self.transform_line(line, continue_prompt)
389
389
390 # Now we compute line_info for the checkers and handlers
390 # Now we compute line_info for the checkers and handlers
391 line_info = LineInfo(line, continue_prompt)
391 line_info = LineInfo(line, continue_prompt)
392
392
393 # the input history needs to track even empty lines
393 # the input history needs to track even empty lines
394 stripped = line.strip()
394 stripped = line.strip()
395
395
396 normal_handler = self.get_handler_by_name('normal')
396 normal_handler = self.get_handler_by_name('normal')
397 if not stripped:
397 if not stripped:
398 if not continue_prompt:
398 if not continue_prompt:
399 self.shell.displayhook.prompt_count -= 1
399 self.shell.displayhook.prompt_count -= 1
400
400
401 return normal_handler.handle(line_info)
401 return normal_handler.handle(line_info)
402
402
403 # special handlers are only allowed for single line statements
403 # special handlers are only allowed for single line statements
404 if continue_prompt and not self.multi_line_specials:
404 if continue_prompt and not self.multi_line_specials:
405 return normal_handler.handle(line_info)
405 return normal_handler.handle(line_info)
406
406
407 prefiltered = self.prefilter_line_info(line_info)
407 prefiltered = self.prefilter_line_info(line_info)
408 # print "prefiltered line: %r" % prefiltered
408 # print "prefiltered line: %r" % prefiltered
409 return prefiltered
409 return prefiltered
410
410
411 def prefilter_lines(self, lines, continue_prompt=False):
411 def prefilter_lines(self, lines, continue_prompt=False):
412 """Prefilter multiple input lines of text.
412 """Prefilter multiple input lines of text.
413
413
414 This is the main entry point for prefiltering multiple lines of
414 This is the main entry point for prefiltering multiple lines of
415 input. This simply calls :meth:`prefilter_line` for each line of
415 input. This simply calls :meth:`prefilter_line` for each line of
416 input.
416 input.
417
417
418 This covers cases where there are multiple lines in the user entry,
418 This covers cases where there are multiple lines in the user entry,
419 which is the case when the user goes back to a multiline history
419 which is the case when the user goes back to a multiline history
420 entry and presses enter.
420 entry and presses enter.
421 """
421 """
422 llines = lines.rstrip('\n').split('\n')
422 llines = lines.rstrip('\n').split('\n')
423 # We can get multiple lines in one shot, where multiline input 'blends'
423 # We can get multiple lines in one shot, where multiline input 'blends'
424 # into one line, in cases like recalling from the readline history
424 # into one line, in cases like recalling from the readline history
425 # buffer. We need to make sure that in such cases, we correctly
425 # buffer. We need to make sure that in such cases, we correctly
426 # communicate downstream which line is first and which are continuation
426 # communicate downstream which line is first and which are continuation
427 # ones.
427 # ones.
428 if len(llines) > 1:
428 if len(llines) > 1:
429 out = '\n'.join([self.prefilter_line(line, lnum>0)
429 out = '\n'.join([self.prefilter_line(line, lnum>0)
430 for lnum, line in enumerate(llines) ])
430 for lnum, line in enumerate(llines) ])
431 else:
431 else:
432 out = self.prefilter_line(llines[0], continue_prompt)
432 out = self.prefilter_line(llines[0], continue_prompt)
433
433
434 return out
434 return out
435
435
436 #-----------------------------------------------------------------------------
436 #-----------------------------------------------------------------------------
437 # Prefilter transformers
437 # Prefilter transformers
438 #-----------------------------------------------------------------------------
438 #-----------------------------------------------------------------------------
439
439
440
440
441 class PrefilterTransformer(Configurable):
441 class PrefilterTransformer(Configurable):
442 """Transform a line of user input."""
442 """Transform a line of user input."""
443
443
444 priority = Int(100, config=True)
444 priority = Int(100, config=True)
445 # Transformers don't currently use shell or prefilter_manager, but as we
445 # Transformers don't currently use shell or prefilter_manager, but as we
446 # move away from checkers and handlers, they will need them.
446 # move away from checkers and handlers, they will need them.
447 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
447 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
448 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
448 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
449 enabled = Bool(True, config=True)
449 enabled = Bool(True, config=True)
450
450
451 def __init__(self, shell=None, prefilter_manager=None, config=None):
451 def __init__(self, shell=None, prefilter_manager=None, config=None):
452 super(PrefilterTransformer, self).__init__(
452 super(PrefilterTransformer, self).__init__(
453 shell=shell, prefilter_manager=prefilter_manager, config=config
453 shell=shell, prefilter_manager=prefilter_manager, config=config
454 )
454 )
455 self.prefilter_manager.register_transformer(self)
455 self.prefilter_manager.register_transformer(self)
456
456
457 def transform(self, line, continue_prompt):
457 def transform(self, line, continue_prompt):
458 """Transform a line, returning the new one."""
458 """Transform a line, returning the new one."""
459 return None
459 return None
460
460
461 def __repr__(self):
461 def __repr__(self):
462 return "<%s(priority=%r, enabled=%r)>" % (
462 return "<%s(priority=%r, enabled=%r)>" % (
463 self.__class__.__name__, self.priority, self.enabled)
463 self.__class__.__name__, self.priority, self.enabled)
464
464
465
465
466 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
466 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
467 r'\s*=\s*!(?P<cmd>.*)')
467 r'\s*=\s*!(?P<cmd>.*)')
468
468
469
469
470 class AssignSystemTransformer(PrefilterTransformer):
470 class AssignSystemTransformer(PrefilterTransformer):
471 """Handle the `files = !ls` syntax."""
471 """Handle the `files = !ls` syntax."""
472
472
473 priority = Int(100, config=True)
473 priority = Int(100, config=True)
474
474
475 def transform(self, line, continue_prompt):
475 def transform(self, line, continue_prompt):
476 m = _assign_system_re.match(line)
476 m = _assign_system_re.match(line)
477 if m is not None:
477 if m is not None:
478 cmd = m.group('cmd')
478 cmd = m.group('cmd')
479 lhs = m.group('lhs')
479 lhs = m.group('lhs')
480 expr = make_quoted_expr("sc =%s" % cmd)
480 expr = make_quoted_expr("sc =%s" % cmd)
481 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
481 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
482 return new_line
482 return new_line
483 return line
483 return line
484
484
485
485
486 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
486 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
487 r'\s*=\s*%(?P<cmd>.*)')
487 r'\s*=\s*%(?P<cmd>.*)')
488
488
489 class AssignMagicTransformer(PrefilterTransformer):
489 class AssignMagicTransformer(PrefilterTransformer):
490 """Handle the `a = %who` syntax."""
490 """Handle the `a = %who` syntax."""
491
491
492 priority = Int(200, config=True)
492 priority = Int(200, config=True)
493
493
494 def transform(self, line, continue_prompt):
494 def transform(self, line, continue_prompt):
495 m = _assign_magic_re.match(line)
495 m = _assign_magic_re.match(line)
496 if m is not None:
496 if m is not None:
497 cmd = m.group('cmd')
497 cmd = m.group('cmd')
498 lhs = m.group('lhs')
498 lhs = m.group('lhs')
499 expr = make_quoted_expr(cmd)
499 expr = make_quoted_expr(cmd)
500 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
500 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
501 return new_line
501 return new_line
502 return line
502 return line
503
503
504
504
505 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
505 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
506
506
507 class PyPromptTransformer(PrefilterTransformer):
507 class PyPromptTransformer(PrefilterTransformer):
508 """Handle inputs that start with '>>> ' syntax."""
508 """Handle inputs that start with '>>> ' syntax."""
509
509
510 priority = Int(50, config=True)
510 priority = Int(50, config=True)
511
511
512 def transform(self, line, continue_prompt):
512 def transform(self, line, continue_prompt):
513
513
514 if not line or line.isspace() or line.strip() == '...':
514 if not line or line.isspace() or line.strip() == '...':
515 # This allows us to recognize multiple input prompts separated by
515 # This allows us to recognize multiple input prompts separated by
516 # blank lines and pasted in a single chunk, very common when
516 # blank lines and pasted in a single chunk, very common when
517 # pasting doctests or long tutorial passages.
517 # pasting doctests or long tutorial passages.
518 return ''
518 return ''
519 m = _classic_prompt_re.match(line)
519 m = _classic_prompt_re.match(line)
520 if m:
520 if m:
521 return line[len(m.group(0)):]
521 return line[len(m.group(0)):]
522 else:
522 else:
523 return line
523 return line
524
524
525
525
526 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
526 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
527
527
528 class IPyPromptTransformer(PrefilterTransformer):
528 class IPyPromptTransformer(PrefilterTransformer):
529 """Handle inputs that start classic IPython prompt syntax."""
529 """Handle inputs that start classic IPython prompt syntax."""
530
530
531 priority = Int(50, config=True)
531 priority = Int(50, config=True)
532
532
533 def transform(self, line, continue_prompt):
533 def transform(self, line, continue_prompt):
534
534
535 if not line or line.isspace() or line.strip() == '...':
535 if not line or line.isspace() or line.strip() == '...':
536 # This allows us to recognize multiple input prompts separated by
536 # This allows us to recognize multiple input prompts separated by
537 # blank lines and pasted in a single chunk, very common when
537 # blank lines and pasted in a single chunk, very common when
538 # pasting doctests or long tutorial passages.
538 # pasting doctests or long tutorial passages.
539 return ''
539 return ''
540 m = _ipy_prompt_re.match(line)
540 m = _ipy_prompt_re.match(line)
541 if m:
541 if m:
542 return line[len(m.group(0)):]
542 return line[len(m.group(0)):]
543 else:
543 else:
544 return line
544 return line
545
545
546 #-----------------------------------------------------------------------------
546 #-----------------------------------------------------------------------------
547 # Prefilter checkers
547 # Prefilter checkers
548 #-----------------------------------------------------------------------------
548 #-----------------------------------------------------------------------------
549
549
550
550
551 class PrefilterChecker(Configurable):
551 class PrefilterChecker(Configurable):
552 """Inspect an input line and return a handler for that line."""
552 """Inspect an input line and return a handler for that line."""
553
553
554 priority = Int(100, config=True)
554 priority = Int(100, config=True)
555 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
555 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
556 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
556 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
557 enabled = Bool(True, config=True)
557 enabled = Bool(True, config=True)
558
558
559 def __init__(self, shell=None, prefilter_manager=None, config=None):
559 def __init__(self, shell=None, prefilter_manager=None, config=None):
560 super(PrefilterChecker, self).__init__(
560 super(PrefilterChecker, self).__init__(
561 shell=shell, prefilter_manager=prefilter_manager, config=config
561 shell=shell, prefilter_manager=prefilter_manager, config=config
562 )
562 )
563 self.prefilter_manager.register_checker(self)
563 self.prefilter_manager.register_checker(self)
564
564
565 def check(self, line_info):
565 def check(self, line_info):
566 """Inspect line_info and return a handler instance or None."""
566 """Inspect line_info and return a handler instance or None."""
567 return None
567 return None
568
568
569 def __repr__(self):
569 def __repr__(self):
570 return "<%s(priority=%r, enabled=%r)>" % (
570 return "<%s(priority=%r, enabled=%r)>" % (
571 self.__class__.__name__, self.priority, self.enabled)
571 self.__class__.__name__, self.priority, self.enabled)
572
572
573
573
574 class EmacsChecker(PrefilterChecker):
574 class EmacsChecker(PrefilterChecker):
575
575
576 priority = Int(100, config=True)
576 priority = Int(100, config=True)
577 enabled = Bool(False, config=True)
577 enabled = Bool(False, config=True)
578
578
579 def check(self, line_info):
579 def check(self, line_info):
580 "Emacs ipython-mode tags certain input lines."
580 "Emacs ipython-mode tags certain input lines."
581 if line_info.line.endswith('# PYTHON-MODE'):
581 if line_info.line.endswith('# PYTHON-MODE'):
582 return self.prefilter_manager.get_handler_by_name('emacs')
582 return self.prefilter_manager.get_handler_by_name('emacs')
583 else:
583 else:
584 return None
584 return None
585
585
586
586
587 class ShellEscapeChecker(PrefilterChecker):
587 class ShellEscapeChecker(PrefilterChecker):
588
588
589 priority = Int(200, config=True)
589 priority = Int(200, config=True)
590
590
591 def check(self, line_info):
591 def check(self, line_info):
592 if line_info.line.lstrip().startswith(ESC_SHELL):
592 if line_info.line.lstrip().startswith(ESC_SHELL):
593 return self.prefilter_manager.get_handler_by_name('shell')
593 return self.prefilter_manager.get_handler_by_name('shell')
594
594
595
595
596 class MacroChecker(PrefilterChecker):
596 class MacroChecker(PrefilterChecker):
597
597
598 priority = Int(250, config=True)
598 priority = Int(250, config=True)
599
599
600 def check(self, line_info):
600 def check(self, line_info):
601 obj = self.shell.user_ns.get(line_info.ifun)
601 obj = self.shell.user_ns.get(line_info.ifun)
602 if isinstance(obj, Macro):
602 if isinstance(obj, Macro):
603 return self.prefilter_manager.get_handler_by_name('macro')
603 return self.prefilter_manager.get_handler_by_name('macro')
604 else:
604 else:
605 return None
605 return None
606
606
607
607
608 class IPyAutocallChecker(PrefilterChecker):
608 class IPyAutocallChecker(PrefilterChecker):
609
609
610 priority = Int(300, config=True)
610 priority = Int(300, config=True)
611
611
612 def check(self, line_info):
612 def check(self, line_info):
613 "Instances of IPyAutocall in user_ns get autocalled immediately"
613 "Instances of IPyAutocall in user_ns get autocalled immediately"
614 obj = self.shell.user_ns.get(line_info.ifun, None)
614 obj = self.shell.user_ns.get(line_info.ifun, None)
615 if isinstance(obj, IPyAutocall):
615 if isinstance(obj, IPyAutocall):
616 obj.set_ip(self.shell)
616 obj.set_ip(self.shell)
617 return self.prefilter_manager.get_handler_by_name('auto')
617 return self.prefilter_manager.get_handler_by_name('auto')
618 else:
618 else:
619 return None
619 return None
620
620
621
621
622 class MultiLineMagicChecker(PrefilterChecker):
622 class MultiLineMagicChecker(PrefilterChecker):
623
623
624 priority = Int(400, config=True)
624 priority = Int(400, config=True)
625
625
626 def check(self, line_info):
626 def check(self, line_info):
627 "Allow ! and !! in multi-line statements if multi_line_specials is on"
627 "Allow ! and !! in multi-line statements if multi_line_specials is on"
628 # Note that this one of the only places we check the first character of
628 # Note that this one of the only places we check the first character of
629 # ifun and *not* the pre_char. Also note that the below test matches
629 # ifun and *not* the pre_char. Also note that the below test matches
630 # both ! and !!.
630 # both ! and !!.
631 if line_info.continue_prompt \
631 if line_info.continue_prompt \
632 and self.prefilter_manager.multi_line_specials:
632 and self.prefilter_manager.multi_line_specials:
633 if line_info.ifun.startswith(ESC_MAGIC):
633 if line_info.esc == ESC_MAGIC:
634 return self.prefilter_manager.get_handler_by_name('magic')
634 return self.prefilter_manager.get_handler_by_name('magic')
635 else:
635 else:
636 return None
636 return None
637
637
638
638
639 class EscCharsChecker(PrefilterChecker):
639 class EscCharsChecker(PrefilterChecker):
640
640
641 priority = Int(500, config=True)
641 priority = Int(500, config=True)
642
642
643 def check(self, line_info):
643 def check(self, line_info):
644 """Check for escape character and return either a handler to handle it,
644 """Check for escape character and return either a handler to handle it,
645 or None if there is no escape char."""
645 or None if there is no escape char."""
646 if line_info.line[-1] == ESC_HELP \
646 if line_info.line[-1] == ESC_HELP \
647 and line_info.pre_char != ESC_SHELL \
647 and line_info.esc != ESC_SHELL \
648 and line_info.pre_char != ESC_SH_CAP:
648 and line_info.esc != ESC_SH_CAP:
649 # the ? can be at the end, but *not* for either kind of shell escape,
649 # the ? can be at the end, but *not* for either kind of shell escape,
650 # because a ? can be a vaild final char in a shell cmd
650 # because a ? can be a vaild final char in a shell cmd
651 return self.prefilter_manager.get_handler_by_name('help')
651 return self.prefilter_manager.get_handler_by_name('help')
652 else:
652 else:
653 if line_info.pre:
654 return None
653 # This returns None like it should if no handler exists
655 # This returns None like it should if no handler exists
654 return self.prefilter_manager.get_handler_by_esc(line_info.pre_char)
656 return self.prefilter_manager.get_handler_by_esc(line_info.esc)
655
657
656
658
657 class AssignmentChecker(PrefilterChecker):
659 class AssignmentChecker(PrefilterChecker):
658
660
659 priority = Int(600, config=True)
661 priority = Int(600, config=True)
660
662
661 def check(self, line_info):
663 def check(self, line_info):
662 """Check to see if user is assigning to a var for the first time, in
664 """Check to see if user is assigning to a var for the first time, in
663 which case we want to avoid any sort of automagic / autocall games.
665 which case we want to avoid any sort of automagic / autocall games.
664
666
665 This allows users to assign to either alias or magic names true python
667 This allows users to assign to either alias or magic names true python
666 variables (the magic/alias systems always take second seat to true
668 variables (the magic/alias systems always take second seat to true
667 python code). E.g. ls='hi', or ls,that=1,2"""
669 python code). E.g. ls='hi', or ls,that=1,2"""
668 if line_info.the_rest:
670 if line_info.the_rest:
669 if line_info.the_rest[0] in '=,':
671 if line_info.the_rest[0] in '=,':
670 return self.prefilter_manager.get_handler_by_name('normal')
672 return self.prefilter_manager.get_handler_by_name('normal')
671 else:
673 else:
672 return None
674 return None
673
675
674
676
675 class AutoMagicChecker(PrefilterChecker):
677 class AutoMagicChecker(PrefilterChecker):
676
678
677 priority = Int(700, config=True)
679 priority = Int(700, config=True)
678
680
679 def check(self, line_info):
681 def check(self, line_info):
680 """If the ifun is magic, and automagic is on, run it. Note: normal,
682 """If the ifun is magic, and automagic is on, run it. Note: normal,
681 non-auto magic would already have been triggered via '%' in
683 non-auto magic would already have been triggered via '%' in
682 check_esc_chars. This just checks for automagic. Also, before
684 check_esc_chars. This just checks for automagic. Also, before
683 triggering the magic handler, make sure that there is nothing in the
685 triggering the magic handler, make sure that there is nothing in the
684 user namespace which could shadow it."""
686 user namespace which could shadow it."""
685 if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun):
687 if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun):
686 return None
688 return None
687
689
688 # We have a likely magic method. Make sure we should actually call it.
690 # We have a likely magic method. Make sure we should actually call it.
689 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
691 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
690 return None
692 return None
691
693
692 head = line_info.ifun.split('.',1)[0]
694 head = line_info.ifun.split('.',1)[0]
693 if is_shadowed(head, self.shell):
695 if is_shadowed(head, self.shell):
694 return None
696 return None
695
697
696 return self.prefilter_manager.get_handler_by_name('magic')
698 return self.prefilter_manager.get_handler_by_name('magic')
697
699
698
700
699 class AliasChecker(PrefilterChecker):
701 class AliasChecker(PrefilterChecker):
700
702
701 priority = Int(800, config=True)
703 priority = Int(800, config=True)
702
704
703 def check(self, line_info):
705 def check(self, line_info):
704 "Check if the initital identifier on the line is an alias."
706 "Check if the initital identifier on the line is an alias."
705 # Note: aliases can not contain '.'
707 # Note: aliases can not contain '.'
706 head = line_info.ifun.split('.',1)[0]
708 head = line_info.ifun.split('.',1)[0]
707 if line_info.ifun not in self.shell.alias_manager \
709 if line_info.ifun not in self.shell.alias_manager \
708 or head not in self.shell.alias_manager \
710 or head not in self.shell.alias_manager \
709 or is_shadowed(head, self.shell):
711 or is_shadowed(head, self.shell):
710 return None
712 return None
711
713
712 return self.prefilter_manager.get_handler_by_name('alias')
714 return self.prefilter_manager.get_handler_by_name('alias')
713
715
714
716
715 class PythonOpsChecker(PrefilterChecker):
717 class PythonOpsChecker(PrefilterChecker):
716
718
717 priority = Int(900, config=True)
719 priority = Int(900, config=True)
718
720
719 def check(self, line_info):
721 def check(self, line_info):
720 """If the 'rest' of the line begins with a function call or pretty much
722 """If the 'rest' of the line begins with a function call or pretty much
721 any python operator, we should simply execute the line (regardless of
723 any python operator, we should simply execute the line (regardless of
722 whether or not there's a possible autocall expansion). This avoids
724 whether or not there's a possible autocall expansion). This avoids
723 spurious (and very confusing) geattr() accesses."""
725 spurious (and very confusing) geattr() accesses."""
724 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
726 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
725 return self.prefilter_manager.get_handler_by_name('normal')
727 return self.prefilter_manager.get_handler_by_name('normal')
726 else:
728 else:
727 return None
729 return None
728
730
729
731
730 class AutocallChecker(PrefilterChecker):
732 class AutocallChecker(PrefilterChecker):
731
733
732 priority = Int(1000, config=True)
734 priority = Int(1000, config=True)
733
735
734 def check(self, line_info):
736 def check(self, line_info):
735 "Check if the initial word/function is callable and autocall is on."
737 "Check if the initial word/function is callable and autocall is on."
736 if not self.shell.autocall:
738 if not self.shell.autocall:
737 return None
739 return None
738
740
739 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
741 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
740 if not oinfo['found']:
742 if not oinfo['found']:
741 return None
743 return None
742
744
743 if callable(oinfo['obj']) \
745 if callable(oinfo['obj']) \
744 and (not re_exclude_auto.match(line_info.the_rest)) \
746 and (not re_exclude_auto.match(line_info.the_rest)) \
745 and re_fun_name.match(line_info.ifun):
747 and re_fun_name.match(line_info.ifun):
746 return self.prefilter_manager.get_handler_by_name('auto')
748 return self.prefilter_manager.get_handler_by_name('auto')
747 else:
749 else:
748 return None
750 return None
749
751
750
752
751 #-----------------------------------------------------------------------------
753 #-----------------------------------------------------------------------------
752 # Prefilter handlers
754 # Prefilter handlers
753 #-----------------------------------------------------------------------------
755 #-----------------------------------------------------------------------------
754
756
755
757
756 class PrefilterHandler(Configurable):
758 class PrefilterHandler(Configurable):
757
759
758 handler_name = Unicode('normal')
760 handler_name = Unicode('normal')
759 esc_strings = List([])
761 esc_strings = List([])
760 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
762 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
761 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
763 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
762
764
763 def __init__(self, shell=None, prefilter_manager=None, config=None):
765 def __init__(self, shell=None, prefilter_manager=None, config=None):
764 super(PrefilterHandler, self).__init__(
766 super(PrefilterHandler, self).__init__(
765 shell=shell, prefilter_manager=prefilter_manager, config=config
767 shell=shell, prefilter_manager=prefilter_manager, config=config
766 )
768 )
767 self.prefilter_manager.register_handler(
769 self.prefilter_manager.register_handler(
768 self.handler_name,
770 self.handler_name,
769 self,
771 self,
770 self.esc_strings
772 self.esc_strings
771 )
773 )
772
774
773 def handle(self, line_info):
775 def handle(self, line_info):
774 # print "normal: ", line_info
776 # print "normal: ", line_info
775 """Handle normal input lines. Use as a template for handlers."""
777 """Handle normal input lines. Use as a template for handlers."""
776
778
777 # With autoindent on, we need some way to exit the input loop, and I
779 # With autoindent on, we need some way to exit the input loop, and I
778 # don't want to force the user to have to backspace all the way to
780 # don't want to force the user to have to backspace all the way to
779 # clear the line. The rule will be in this case, that either two
781 # clear the line. The rule will be in this case, that either two
780 # lines of pure whitespace in a row, or a line of pure whitespace but
782 # lines of pure whitespace in a row, or a line of pure whitespace but
781 # of a size different to the indent level, will exit the input loop.
783 # of a size different to the indent level, will exit the input loop.
782 line = line_info.line
784 line = line_info.line
783 continue_prompt = line_info.continue_prompt
785 continue_prompt = line_info.continue_prompt
784
786
785 if (continue_prompt and
787 if (continue_prompt and
786 self.shell.autoindent and
788 self.shell.autoindent and
787 line.isspace() and
789 line.isspace() and
788 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
790 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
789 line = ''
791 line = ''
790
792
791 return line
793 return line
792
794
793 def __str__(self):
795 def __str__(self):
794 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
796 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
795
797
796
798
797 class AliasHandler(PrefilterHandler):
799 class AliasHandler(PrefilterHandler):
798
800
799 handler_name = Unicode('alias')
801 handler_name = Unicode('alias')
800
802
801 def handle(self, line_info):
803 def handle(self, line_info):
802 """Handle alias input lines. """
804 """Handle alias input lines. """
803 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
805 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
804 # pre is needed, because it carries the leading whitespace. Otherwise
806 # pre is needed, because it carries the leading whitespace. Otherwise
805 # aliases won't work in indented sections.
807 # aliases won't work in indented sections.
806 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
808 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
807 make_quoted_expr(transformed))
809 make_quoted_expr(transformed))
808
810
809 return line_out
811 return line_out
810
812
811
813
812 class ShellEscapeHandler(PrefilterHandler):
814 class ShellEscapeHandler(PrefilterHandler):
813
815
814 handler_name = Unicode('shell')
816 handler_name = Unicode('shell')
815 esc_strings = List([ESC_SHELL, ESC_SH_CAP])
817 esc_strings = List([ESC_SHELL, ESC_SH_CAP])
816
818
817 def handle(self, line_info):
819 def handle(self, line_info):
818 """Execute the line in a shell, empty return value"""
820 """Execute the line in a shell, empty return value"""
819 magic_handler = self.prefilter_manager.get_handler_by_name('magic')
821 magic_handler = self.prefilter_manager.get_handler_by_name('magic')
820
822
821 line = line_info.line
823 line = line_info.line
822 if line.lstrip().startswith(ESC_SH_CAP):
824 if line.lstrip().startswith(ESC_SH_CAP):
823 # rewrite LineInfo's line, ifun and the_rest to properly hold the
825 # rewrite LineInfo's line, ifun and the_rest to properly hold the
824 # call to %sx and the actual command to be executed, so
826 # call to %sx and the actual command to be executed, so
825 # handle_magic can work correctly. Note that this works even if
827 # handle_magic can work correctly. Note that this works even if
826 # the line is indented, so it handles multi_line_specials
828 # the line is indented, so it handles multi_line_specials
827 # properly.
829 # properly.
828 new_rest = line.lstrip()[2:]
830 new_rest = line.lstrip()[2:]
829 line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest)
831 line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest)
830 line_info.ifun = 'sx'
832 line_info.ifun = 'sx'
831 line_info.the_rest = new_rest
833 line_info.the_rest = new_rest
832 return magic_handler.handle(line_info)
834 return magic_handler.handle(line_info)
833 else:
835 else:
834 cmd = line.lstrip().lstrip(ESC_SHELL)
836 cmd = line.lstrip().lstrip(ESC_SHELL)
835 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
837 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
836 make_quoted_expr(cmd))
838 make_quoted_expr(cmd))
837 return line_out
839 return line_out
838
840
839
841
840 class MacroHandler(PrefilterHandler):
842 class MacroHandler(PrefilterHandler):
841 handler_name = Unicode("macro")
843 handler_name = Unicode("macro")
842
844
843 def handle(self, line_info):
845 def handle(self, line_info):
844 obj = self.shell.user_ns.get(line_info.ifun)
846 obj = self.shell.user_ns.get(line_info.ifun)
845 pre_space = line_info.pre_whitespace
847 pre_space = line_info.pre_whitespace
846 line_sep = "\n" + pre_space
848 line_sep = "\n" + pre_space
847 return pre_space + line_sep.join(obj.value.splitlines())
849 return pre_space + line_sep.join(obj.value.splitlines())
848
850
849
851
850 class MagicHandler(PrefilterHandler):
852 class MagicHandler(PrefilterHandler):
851
853
852 handler_name = Unicode('magic')
854 handler_name = Unicode('magic')
853 esc_strings = List([ESC_MAGIC])
855 esc_strings = List([ESC_MAGIC])
854
856
855 def handle(self, line_info):
857 def handle(self, line_info):
856 """Execute magic functions."""
858 """Execute magic functions."""
857 ifun = line_info.ifun
859 ifun = line_info.ifun
858 the_rest = line_info.the_rest
860 the_rest = line_info.the_rest
859 cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
861 cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
860 make_quoted_expr(ifun + " " + the_rest))
862 make_quoted_expr(ifun + " " + the_rest))
861 return cmd
863 return cmd
862
864
863
865
864 class AutoHandler(PrefilterHandler):
866 class AutoHandler(PrefilterHandler):
865
867
866 handler_name = Unicode('auto')
868 handler_name = Unicode('auto')
867 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
869 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
868
870
869 def handle(self, line_info):
871 def handle(self, line_info):
870 """Handle lines which can be auto-executed, quoting if requested."""
872 """Handle lines which can be auto-executed, quoting if requested."""
871 line = line_info.line
873 line = line_info.line
872 ifun = line_info.ifun
874 ifun = line_info.ifun
873 the_rest = line_info.the_rest
875 the_rest = line_info.the_rest
874 pre = line_info.pre
876 pre = line_info.pre
877 esc = line_info.esc
875 continue_prompt = line_info.continue_prompt
878 continue_prompt = line_info.continue_prompt
876 obj = line_info.ofind(self)['obj']
879 obj = line_info.ofind(self)['obj']
877 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
880 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
878
881
879 # This should only be active for single-line input!
882 # This should only be active for single-line input!
880 if continue_prompt:
883 if continue_prompt:
881 return line
884 return line
882
885
883 force_auto = isinstance(obj, IPyAutocall)
886 force_auto = isinstance(obj, IPyAutocall)
884 auto_rewrite = getattr(obj, 'rewrite', True)
887 auto_rewrite = getattr(obj, 'rewrite', True)
885
888
886 if pre == ESC_QUOTE:
889 if esc == ESC_QUOTE:
887 # Auto-quote splitting on whitespace
890 # Auto-quote splitting on whitespace
888 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
891 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
889 elif pre == ESC_QUOTE2:
892 elif esc == ESC_QUOTE2:
890 # Auto-quote whole string
893 # Auto-quote whole string
891 newcmd = '%s("%s")' % (ifun,the_rest)
894 newcmd = '%s("%s")' % (ifun,the_rest)
892 elif pre == ESC_PAREN:
895 elif esc == ESC_PAREN:
893 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
896 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
894 else:
897 else:
895 # Auto-paren.
898 # Auto-paren.
896 # We only apply it to argument-less calls if the autocall
899 # We only apply it to argument-less calls if the autocall
897 # parameter is set to 2. We only need to check that autocall is <
900 # parameter is set to 2. We only need to check that autocall is <
898 # 2, since this function isn't called unless it's at least 1.
901 # 2, since this function isn't called unless it's at least 1.
899 if not the_rest and (self.shell.autocall < 2) and not force_auto:
902 if not the_rest and (self.shell.autocall < 2) and not force_auto:
900 newcmd = '%s %s' % (ifun,the_rest)
903 newcmd = '%s %s' % (ifun,the_rest)
901 auto_rewrite = False
904 auto_rewrite = False
902 else:
905 else:
903 if not force_auto and the_rest.startswith('['):
906 if not force_auto and the_rest.startswith('['):
904 if hasattr(obj,'__getitem__'):
907 if hasattr(obj,'__getitem__'):
905 # Don't autocall in this case: item access for an object
908 # Don't autocall in this case: item access for an object
906 # which is BOTH callable and implements __getitem__.
909 # which is BOTH callable and implements __getitem__.
907 newcmd = '%s %s' % (ifun,the_rest)
910 newcmd = '%s %s' % (ifun,the_rest)
908 auto_rewrite = False
911 auto_rewrite = False
909 else:
912 else:
910 # if the object doesn't support [] access, go ahead and
913 # if the object doesn't support [] access, go ahead and
911 # autocall
914 # autocall
912 newcmd = '%s(%s)' % (ifun.rstrip(),the_rest)
915 newcmd = '%s(%s)' % (ifun.rstrip(),the_rest)
913 elif the_rest.endswith(';'):
916 elif the_rest.endswith(';'):
914 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
917 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
915 else:
918 else:
916 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
919 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
917
920
918 if auto_rewrite:
921 if auto_rewrite:
919 self.shell.auto_rewrite_input(newcmd)
922 self.shell.auto_rewrite_input(newcmd)
920
923
921 return newcmd
924 return newcmd
922
925
923
926
924 class HelpHandler(PrefilterHandler):
927 class HelpHandler(PrefilterHandler):
925
928
926 handler_name = Unicode('help')
929 handler_name = Unicode('help')
927 esc_strings = List([ESC_HELP])
930 esc_strings = List([ESC_HELP])
928
931
929 def handle(self, line_info):
932 def handle(self, line_info):
930 """Try to get some help for the object.
933 """Try to get some help for the object.
931
934
932 obj? or ?obj -> basic information.
935 obj? or ?obj -> basic information.
933 obj?? or ??obj -> more details.
936 obj?? or ??obj -> more details.
934 """
937 """
935 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
938 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
936 line = line_info.line
939 line = line_info.line
937 # We need to make sure that we don't process lines which would be
940 # We need to make sure that we don't process lines which would be
938 # otherwise valid python, such as "x=1 # what?"
941 # otherwise valid python, such as "x=1 # what?"
939 try:
942 try:
940 codeop.compile_command(line)
943 codeop.compile_command(line)
941 except SyntaxError:
944 except SyntaxError:
942 # We should only handle as help stuff which is NOT valid syntax
945 # We should only handle as help stuff which is NOT valid syntax
943 if line[0]==ESC_HELP:
946 if line[0]==ESC_HELP:
944 line = line[1:]
947 line = line[1:]
945 elif line[-1]==ESC_HELP:
948 elif line[-1]==ESC_HELP:
946 line = line[:-1]
949 line = line[:-1]
947 if line:
950 if line:
948 #print 'line:<%r>' % line # dbg
951 #print 'line:<%r>' % line # dbg
949 self.shell.magic_pinfo(line)
952 self.shell.magic_pinfo(line_info.ifun)
950 else:
953 else:
951 self.shell.show_usage()
954 self.shell.show_usage()
952 return '' # Empty string is needed here!
955 return '' # Empty string is needed here!
953 except:
956 except:
954 raise
957 raise
955 # Pass any other exceptions through to the normal handler
958 # Pass any other exceptions through to the normal handler
956 return normal_handler.handle(line_info)
959 return normal_handler.handle(line_info)
957 else:
960 else:
958 # If the code compiles ok, we should handle it normally
961 # If the code compiles ok, we should handle it normally
959 return normal_handler.handle(line_info)
962 return normal_handler.handle(line_info)
960
963
961
964
962 class EmacsHandler(PrefilterHandler):
965 class EmacsHandler(PrefilterHandler):
963
966
964 handler_name = Unicode('emacs')
967 handler_name = Unicode('emacs')
965 esc_strings = List([])
968 esc_strings = List([])
966
969
967 def handle(self, line_info):
970 def handle(self, line_info):
968 """Handle input lines marked by python-mode."""
971 """Handle input lines marked by python-mode."""
969
972
970 # Currently, nothing is done. Later more functionality can be added
973 # Currently, nothing is done. Later more functionality can be added
971 # here if needed.
974 # here if needed.
972
975
973 # The input cache shouldn't be updated
976 # The input cache shouldn't be updated
974 return line_info.line
977 return line_info.line
975
978
976
979
977 #-----------------------------------------------------------------------------
980 #-----------------------------------------------------------------------------
978 # Defaults
981 # Defaults
979 #-----------------------------------------------------------------------------
982 #-----------------------------------------------------------------------------
980
983
981
984
982 _default_transformers = [
985 _default_transformers = [
983 AssignSystemTransformer,
986 AssignSystemTransformer,
984 AssignMagicTransformer,
987 AssignMagicTransformer,
985 PyPromptTransformer,
988 PyPromptTransformer,
986 IPyPromptTransformer,
989 IPyPromptTransformer,
987 ]
990 ]
988
991
989 _default_checkers = [
992 _default_checkers = [
990 EmacsChecker,
993 EmacsChecker,
991 ShellEscapeChecker,
994 ShellEscapeChecker,
992 MacroChecker,
995 MacroChecker,
993 IPyAutocallChecker,
996 IPyAutocallChecker,
994 MultiLineMagicChecker,
997 MultiLineMagicChecker,
995 EscCharsChecker,
998 EscCharsChecker,
996 AssignmentChecker,
999 AssignmentChecker,
997 AutoMagicChecker,
1000 AutoMagicChecker,
998 AliasChecker,
1001 AliasChecker,
999 PythonOpsChecker,
1002 PythonOpsChecker,
1000 AutocallChecker
1003 AutocallChecker
1001 ]
1004 ]
1002
1005
1003 _default_handlers = [
1006 _default_handlers = [
1004 PrefilterHandler,
1007 PrefilterHandler,
1005 AliasHandler,
1008 AliasHandler,
1006 ShellEscapeHandler,
1009 ShellEscapeHandler,
1007 MacroHandler,
1010 MacroHandler,
1008 MagicHandler,
1011 MagicHandler,
1009 AutoHandler,
1012 AutoHandler,
1010 HelpHandler,
1013 HelpHandler,
1011 EmacsHandler
1014 EmacsHandler
1012 ]
1015 ]
@@ -1,89 +1,86 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Simple utility for splitting user input.
3 Simple utility for splitting user input.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 * Fernando Perez
8 * Fernando Perez
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2009 The IPython Development Team
12 # Copyright (C) 2008-2009 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import re
22 import re
23 import sys
23 import sys
24
24
25 from IPython.utils import py3compat
25 from IPython.utils import py3compat
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Main function
28 # Main function
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31
31
32 # RegExp for splitting line contents into pre-char//first word-method//rest.
32 # RegExp for splitting line contents into pre-char//first word-method//rest.
33 # For clarity, each group in on one line.
33 # For clarity, each group in on one line.
34
34
35 # WARNING: update the regexp if the escapes in interactiveshell are changed, as they
35 # WARNING: update the regexp if the escapes in interactiveshell are changed, as they
36 # are hardwired in.
36 # are hardwired in.
37
37
38 # Although it's not solely driven by the regex, note that:
38 # Although it's not solely driven by the regex, note that:
39 # ,;/% only trigger if they are the first character on the line
39 # ,;/% only trigger if they are the first character on the line
40 # ! and !! trigger if they are first char(s) *or* follow an indent
40 # ! and !! trigger if they are first char(s) *or* follow an indent
41 # ? triggers as first or last char.
41 # ? triggers as first or last char.
42
42
43 # The three parts of the regex are:
43 # The four parts of the regex are:
44 # 1) pre: pre_char *or* initial whitespace
44 # 1) pre: initial whitespace
45 # 2) ifun: first word/method (mix of \w and '.')
45 # 2) esc: escape character
46 # 3) the_rest: rest of line (separated from ifun by space if non-empty)
46 # 3) ifun: first word/method (mix of \w and '.')
47 line_split = re.compile(r'^([,;/%?]|!!?|\s*)'
47 # 4) the_rest: rest of line (separated from ifun by space if non-empty)
48 line_split = re.compile(r'^(\s*)'
49 r'([,;/%?]|!!?)?'
48 r'\s*([\w\.]+)'
50 r'\s*([\w\.]+)'
49 r'(\s+.*$|$)')
51 r'(.*$|$)')
50
52
51 # r'[\w\.]+'
53 # r'[\w\.]+'
52 # r'\s*=\s*%.*'
54 # r'\s*=\s*%.*'
53
55
54 def split_user_input(line, pattern=None):
56 def split_user_input(line, pattern=None):
55 """Split user input into pre-char/whitespace, function part and rest.
57 """Split user input into pre-char/whitespace, function part and rest.
56
58
57 This is currently handles lines with '=' in them in a very inconsistent
59 This is currently handles lines with '=' in them in a very inconsistent
58 manner.
60 manner.
59 """
61 """
60 # We need to ensure that the rest of this routine deals only with unicode
62 # We need to ensure that the rest of this routine deals only with unicode
61 line = py3compat.cast_unicode(line, sys.stdin.encoding or 'utf-8')
63 line = py3compat.cast_unicode(line, sys.stdin.encoding or 'utf-8')
62
64
63 if pattern is None:
65 if pattern is None:
64 pattern = line_split
66 pattern = line_split
65 match = pattern.match(line)
67 match = pattern.match(line)
66 if not match:
68 if not match:
67 # print "match failed for line '%s'" % line
69 # print "match failed for line '%s'" % line
68 try:
70 try:
69 ifun, the_rest = line.split(None,1)
71 ifun, the_rest = line.split(None,1)
70 except ValueError:
72 except ValueError:
71 # print "split failed for line '%s'" % line
73 # print "split failed for line '%s'" % line
72 ifun, the_rest = line, u''
74 ifun, the_rest = line, u''
73 pre = re.match('^(\s*)(.*)',line).groups()[0]
75 pre = re.match('^(\s*)(.*)',line).groups()[0]
76 esc = ""
74 else:
77 else:
75 pre,ifun,the_rest = match.groups()
78 pre, esc, ifun, the_rest = match.groups()
76
79
77 if not py3compat.PY3:
80 if not py3compat.isidentifier(ifun, dotted=True):
78 # ifun has to be a valid python identifier, so it better encode into
81 the_rest = ifun + u' ' + the_rest
79 # ascii. We do still make it a unicode string so that we consistently
82 ifun = u''
80 # return unicode, but it will be one that is guaranteed to be pure ascii
81 try:
82 ifun = unicode(ifun.encode('ascii'))
83 except UnicodeEncodeError:
84 the_rest = ifun + u' ' + the_rest
85 ifun = u''
86
83
87 #print 'line:<%s>' % line # dbg
84 #print 'line:<%s>' % line # dbg
88 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
85 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
89 return pre, ifun.strip(), the_rest.lstrip()
86 return pre, esc, ifun.strip(), the_rest.lstrip()
@@ -1,172 +1,165 b''
1 """Tests for input handlers.
1 """Tests for input handlers.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Module imports
4 # Module imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6
6
7 # third party
7 # third party
8 import nose.tools as nt
8 import nose.tools as nt
9
9
10 # our own packages
10 # our own packages
11 from IPython.core import autocall
11 from IPython.core import autocall
12 from IPython.testing import decorators as dec
12 from IPython.testing import decorators as dec
13 from IPython.testing import tools as tt
13 from IPython.testing.globalipapp import get_ipython
14 from IPython.testing.globalipapp import get_ipython
14
15
15 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
16 # Globals
17 # Globals
17 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
18
19
19 # Get the public instance of IPython
20 # Get the public instance of IPython
20 ip = get_ipython()
21 ip = get_ipython()
21
22
22 failures = []
23 failures = []
23 num_tests = 0
24 num_tests = 0
24
25
25 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
26 # Test functions
27 # Test functions
27 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
28
29
29 class CallableIndexable(object):
30 class CallableIndexable(object):
30 def __getitem__(self, idx): return True
31 def __getitem__(self, idx): return True
31 def __call__(self, *args, **kws): return True
32 def __call__(self, *args, **kws): return True
32
33
33
34
34 class Autocallable(autocall.IPyAutocall):
35 class Autocallable(autocall.IPyAutocall):
35 def __call__(self):
36 def __call__(self):
36 return "called"
37 return "called"
37
38
38
39
39 def run(tests):
40 def run(tests):
40 """Loop through a list of (pre, post) inputs, where pre is the string
41 """Loop through a list of (pre, post) inputs, where pre is the string
41 handed to ipython, and post is how that string looks after it's been
42 handed to ipython, and post is how that string looks after it's been
42 transformed (i.e. ipython's notion of _i)"""
43 transformed (i.e. ipython's notion of _i)"""
43 for pre, post in tests:
44 tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests)
44 global num_tests
45 num_tests += 1
46 actual = ip.prefilter_manager.prefilter_lines(pre)
47 if actual != None:
48 actual = actual.rstrip('\n')
49 if actual != post:
50 failures.append('Expected %r to become %r, found %r' % (
51 pre, post, actual))
52
45
53
46
54 def test_handlers():
47 def test_handlers():
55 # alias expansion
48 # alias expansion
56
49
57 # We're using 'true' as our syscall of choice because it doesn't
50 # We're using 'true' as our syscall of choice because it doesn't
58 # write anything to stdout.
51 # write anything to stdout.
59
52
60 # Turn off actual execution of aliases, because it's noisy
53 # Turn off actual execution of aliases, because it's noisy
61 old_system_cmd = ip.system
54 old_system_cmd = ip.system
62 ip.system = lambda cmd: None
55 ip.system = lambda cmd: None
63
56
64
57
65 ip.alias_manager.alias_table['an_alias'] = (0, 'true')
58 ip.alias_manager.alias_table['an_alias'] = (0, 'true')
66 # These are useful for checking a particular recursive alias issue
59 # These are useful for checking a particular recursive alias issue
67 ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
60 ip.alias_manager.alias_table['top'] = (0, 'd:/cygwin/top')
68 ip.alias_manager.alias_table['d'] = (0, 'true')
61 ip.alias_manager.alias_table['d'] = (0, 'true')
69 run([("an_alias", 'get_ipython().system(u"true ")'), # alias
62 run([("an_alias", 'get_ipython().system(u"true ")'), # alias
70 # Below: recursive aliases should expand whitespace-surrounded
63 # Below: recursive aliases should expand whitespace-surrounded
71 # chars, *not* initial chars which happen to be aliases:
64 # chars, *not* initial chars which happen to be aliases:
72 ("top", 'get_ipython().system(u"d:/cygwin/top ")'),
65 ("top", 'get_ipython().system(u"d:/cygwin/top ")'),
73 ])
66 ])
74 ip.system = old_system_cmd
67 ip.system = old_system_cmd
75
68
76 call_idx = CallableIndexable()
69 call_idx = CallableIndexable()
77 ip.user_ns['call_idx'] = call_idx
70 ip.user_ns['call_idx'] = call_idx
78
71
79 # For many of the below, we're also checking that leading whitespace
72 # For many of the below, we're also checking that leading whitespace
80 # turns off the esc char, which it should unless there is a continuation
73 # turns off the esc char, which it should unless there is a continuation
81 # line.
74 # line.
82 run([('"no change"', '"no change"'), # normal
75 run([('"no change"', '"no change"'), # normal
83 ("!true", 'get_ipython().system(u"true")'), # shell_escapes
76 ("!true", 'get_ipython().system(u"true")'), # shell_escapes
84 ("!! true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic
77 ("!! true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic
85 ("!!true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic
78 ("!!true", 'get_ipython().magic(u"sx true")'), # shell_escapes + magic
86 ("%lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic
79 ("%lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic
87 ("lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic
80 ("lsmagic", 'get_ipython().magic(u"lsmagic ")'), # magic
88 #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
81 #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
89
82
90 # post-esc-char whitespace goes inside
83 # post-esc-char whitespace goes inside
91 ("! true", 'get_ipython().system(u" true")'),
84 ("! true", 'get_ipython().system(u" true")'),
92
85
93 # handle_help
86 # handle_help
94
87
95 # These are weak tests -- just looking at what the help handlers
88 # These are weak tests -- just looking at what the help handlers
96 # logs, which is not how it really does its work. But it still
89 # logs, which is not how it really does its work. But it still
97 # lets us check the key paths through the handler.
90 # lets us check the key paths through the handler.
98
91
99 ("x=1 # what?", "x=1 # what?"), # no help if valid python
92 ("x=1 # what?", "x=1 # what?"), # no help if valid python
100 ])
93 ])
101
94
102 # multi_line_specials
95 # multi_line_specials
103 ip.prefilter_manager.multi_line_specials = False
96 ip.prefilter_manager.multi_line_specials = False
104 # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
97 # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion
105 run([
98 run([
106 ('if 1:\n !true', 'if 1:\n !true'),
99 ('if 1:\n !true', 'if 1:\n !true'),
107 ('if 1:\n lsmagic', 'if 1:\n lsmagic'),
100 ('if 1:\n lsmagic', 'if 1:\n lsmagic'),
108 ('if 1:\n an_alias', 'if 1:\n an_alias'),
101 ('if 1:\n an_alias', 'if 1:\n an_alias'),
109 ])
102 ])
110
103
111 ip.prefilter_manager.multi_line_specials = True
104 ip.prefilter_manager.multi_line_specials = True
112 # initial indents must be preserved.
105 # initial indents must be preserved.
113 run([
106 run([
114 ('if 1:\n !true', 'if 1:\n get_ipython().system(u"true")'),
107 ('if 1:\n !true', 'if 1:\n get_ipython().system(u"true")'),
115 ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic(u"lsmagic ")'),
108 ('if 2:\n lsmagic', 'if 2:\n get_ipython().magic(u"lsmagic ")'),
116 ('if 1:\n an_alias', 'if 1:\n get_ipython().system(u"true ")'),
109 ('if 1:\n an_alias', 'if 1:\n get_ipython().system(u"true ")'),
117 # Weird one
110 # Weird one
118 ('if 1:\n !!true', 'if 1:\n get_ipython().magic(u"sx true")'),
111 ('if 1:\n !!true', 'if 1:\n get_ipython().magic(u"sx true")'),
119
112
120 # Even with m_l_s on, autocall is off even with special chars
113 # Even with m_l_s on, autocall is off even with special chars
121 ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
114 ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'),
122 ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'),
115 ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'),
123 ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'),
116 ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'),
124 ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'),
117 ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'),
125 # What about !!
118 # What about !!
126 ])
119 ])
127
120
128 # Objects which are instances of IPyAutocall are *always* autocalled
121 # Objects which are instances of IPyAutocall are *always* autocalled
129 autocallable = Autocallable()
122 autocallable = Autocallable()
130 ip.user_ns['autocallable'] = autocallable
123 ip.user_ns['autocallable'] = autocallable
131
124
132 # auto
125 # auto
133 ip.magic('autocall 0')
126 ip.magic('autocall 0')
134 # Only explicit escapes or instances of IPyAutocallable should get
127 # Only explicit escapes or instances of IPyAutocallable should get
135 # expanded
128 # expanded
136 run([
129 run([
137 ('len "abc"', 'len "abc"'),
130 ('len "abc"', 'len "abc"'),
138 ('autocallable', 'autocallable()'),
131 ('autocallable', 'autocallable()'),
139 (",list 1 2 3", 'list("1", "2", "3")'),
132 (",list 1 2 3", 'list("1", "2", "3")'),
140 (";list 1 2 3", 'list("1 2 3")'),
133 (";list 1 2 3", 'list("1 2 3")'),
141 ("/len range(1,4)", 'len(range(1,4))'),
134 ("/len range(1,4)", 'len(range(1,4))'),
142 ])
135 ])
143 ip.magic('autocall 1')
136 ip.magic('autocall 1')
144 run([
137 run([
145 (",list 1 2 3", 'list("1", "2", "3")'),
138 (",list 1 2 3", 'list("1", "2", "3")'),
146 (";list 1 2 3", 'list("1 2 3")'),
139 (";list 1 2 3", 'list("1 2 3")'),
147 ("/len range(1,4)", 'len(range(1,4))'),
140 ("/len range(1,4)", 'len(range(1,4))'),
148 ('len "abc"', 'len("abc")'),
141 ('len "abc"', 'len("abc")'),
149 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
142 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
150 # Autocall is turned off if first arg is [] and the object
143 # Autocall is turned off if first arg is [] and the object
151 # is both callable and indexable. Like so:
144 # is both callable and indexable. Like so:
152 ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__...
145 ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__...
153 ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
146 ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
154 ('call_idx 1', 'call_idx(1)'),
147 ('call_idx 1', 'call_idx(1)'),
155 ('len', 'len '), # only at 2 does it auto-call on single args
148 ('len', 'len '), # only at 2 does it auto-call on single args
156 ])
149 ])
157 ip.magic('autocall 2')
150 ip.magic('autocall 2')
158 run([
151 run([
159 (",list 1 2 3", 'list("1", "2", "3")'),
152 (",list 1 2 3", 'list("1", "2", "3")'),
160 (";list 1 2 3", 'list("1 2 3")'),
153 (";list 1 2 3", 'list("1 2 3")'),
161 ("/len range(1,4)", 'len(range(1,4))'),
154 ("/len range(1,4)", 'len(range(1,4))'),
162 ('len "abc"', 'len("abc")'),
155 ('len "abc"', 'len("abc")'),
163 ('len "abc";', 'len("abc");'),
156 ('len "abc";', 'len("abc");'),
164 ('len [1,2]', 'len([1,2])'),
157 ('len [1,2]', 'len([1,2])'),
165 ('call_idx [1]', 'call_idx [1]'),
158 ('call_idx [1]', 'call_idx [1]'),
166 ('call_idx 1', 'call_idx(1)'),
159 ('call_idx 1', 'call_idx(1)'),
167 # This is what's different:
160 # This is what's different:
168 ('len', 'len()'), # only at 2 does it auto-call on single args
161 ('len', 'len()'), # only at 2 does it auto-call on single args
169 ])
162 ])
170 ip.magic('autocall 1')
163 ip.magic('autocall 1')
171
164
172 nt.assert_equals(failures, [])
165 nt.assert_equals(failures, [])
General Comments 0
You need to be logged in to leave comments. Login now