##// END OF EJS Templates
docstring fixes
Matthias Bussonnier -
Show More
@@ -1,535 +1,538 b''
1 """DEPRECATED: Input transformer classes to support IPython special syntax.
1 """DEPRECATED: Input transformer classes to support IPython special syntax.
2
2
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
3 This module was deprecated in IPython 7.0, in favour of inputtransformer2.
4
4
5 This includes the machinery to recognise and transform ``%magic`` commands,
5 This includes the machinery to recognise and transform ``%magic`` commands,
6 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
6 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
7 """
7 """
8 import abc
8 import abc
9 import functools
9 import functools
10 import re
10 import re
11 import tokenize
11 import tokenize
12 from tokenize import generate_tokens, untokenize, TokenError
12 from tokenize import generate_tokens, untokenize, TokenError
13 from io import StringIO
13 from io import StringIO
14
14
15 from IPython.core.splitinput import LineInfo
15 from IPython.core.splitinput import LineInfo
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Globals
18 # Globals
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 # The escape sequences that define the syntax transformations IPython will
21 # The escape sequences that define the syntax transformations IPython will
22 # apply to user input. These can NOT be just changed here: many regular
22 # apply to user input. These can NOT be just changed here: many regular
23 # expressions and other parts of the code may use their hardcoded values, and
23 # expressions and other parts of the code may use their hardcoded values, and
24 # for all intents and purposes they constitute the 'IPython syntax', so they
24 # for all intents and purposes they constitute the 'IPython syntax', so they
25 # should be considered fixed.
25 # should be considered fixed.
26
26
27 ESC_SHELL = '!' # Send line to underlying system shell
27 ESC_SHELL = '!' # Send line to underlying system shell
28 ESC_SH_CAP = '!!' # Send line to system shell and capture output
28 ESC_SH_CAP = '!!' # Send line to system shell and capture output
29 ESC_HELP = '?' # Find information about object
29 ESC_HELP = '?' # Find information about object
30 ESC_HELP2 = '??' # Find extra-detailed information about object
30 ESC_HELP2 = '??' # Find extra-detailed information about object
31 ESC_MAGIC = '%' # Call magic function
31 ESC_MAGIC = '%' # Call magic function
32 ESC_MAGIC2 = '%%' # Call cell-magic function
32 ESC_MAGIC2 = '%%' # Call cell-magic function
33 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
33 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
34 ESC_QUOTE2 = ';' # Quote all args as a single string, call
34 ESC_QUOTE2 = ';' # Quote all args as a single string, call
35 ESC_PAREN = '/' # Call first argument with rest of line as arguments
35 ESC_PAREN = '/' # Call first argument with rest of line as arguments
36
36
37 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
37 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
38 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
38 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
39 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
39 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
40
40
41
41
42 class InputTransformer(metaclass=abc.ABCMeta):
42 class InputTransformer(metaclass=abc.ABCMeta):
43 """Abstract base class for line-based input transformers."""
43 """Abstract base class for line-based input transformers."""
44
44
45 @abc.abstractmethod
45 @abc.abstractmethod
46 def push(self, line):
46 def push(self, line):
47 """Send a line of input to the transformer, returning the transformed
47 """Send a line of input to the transformer, returning the transformed
48 input or None if the transformer is waiting for more input.
48 input or None if the transformer is waiting for more input.
49
49
50 Must be overridden by subclasses.
50 Must be overridden by subclasses.
51
51
52 Implementations may raise ``SyntaxError`` if the input is invalid. No
52 Implementations may raise ``SyntaxError`` if the input is invalid. No
53 other exceptions may be raised.
53 other exceptions may be raised.
54 """
54 """
55 pass
55 pass
56
56
57 @abc.abstractmethod
57 @abc.abstractmethod
58 def reset(self):
58 def reset(self):
59 """Return, transformed any lines that the transformer has accumulated,
59 """Return, transformed any lines that the transformer has accumulated,
60 and reset its internal state.
60 and reset its internal state.
61
61
62 Must be overridden by subclasses.
62 Must be overridden by subclasses.
63 """
63 """
64 pass
64 pass
65
65
66 @classmethod
66 @classmethod
67 def wrap(cls, func):
67 def wrap(cls, func):
68 """Can be used by subclasses as a decorator, to return a factory that
68 """Can be used by subclasses as a decorator, to return a factory that
69 will allow instantiation with the decorated object.
69 will allow instantiation with the decorated object.
70 """
70 """
71 @functools.wraps(func)
71 @functools.wraps(func)
72 def transformer_factory(**kwargs):
72 def transformer_factory(**kwargs):
73 return cls(func, **kwargs)
73 return cls(func, **kwargs)
74
74
75 return transformer_factory
75 return transformer_factory
76
76
77 class StatelessInputTransformer(InputTransformer):
77 class StatelessInputTransformer(InputTransformer):
78 """Wrapper for a stateless input transformer implemented as a function."""
78 """Wrapper for a stateless input transformer implemented as a function."""
79 def __init__(self, func):
79 def __init__(self, func):
80 self.func = func
80 self.func = func
81
81
82 def __repr__(self):
82 def __repr__(self):
83 return "StatelessInputTransformer(func={0!r})".format(self.func)
83 return "StatelessInputTransformer(func={0!r})".format(self.func)
84
84
85 def push(self, line):
85 def push(self, line):
86 """Send a line of input to the transformer, returning the
86 """Send a line of input to the transformer, returning the
87 transformed input."""
87 transformed input."""
88 return self.func(line)
88 return self.func(line)
89
89
90 def reset(self):
90 def reset(self):
91 """No-op - exists for compatibility."""
91 """No-op - exists for compatibility."""
92 pass
92 pass
93
93
94 class CoroutineInputTransformer(InputTransformer):
94 class CoroutineInputTransformer(InputTransformer):
95 """Wrapper for an input transformer implemented as a coroutine."""
95 """Wrapper for an input transformer implemented as a coroutine."""
96 def __init__(self, coro, **kwargs):
96 def __init__(self, coro, **kwargs):
97 # Prime it
97 # Prime it
98 self.coro = coro(**kwargs)
98 self.coro = coro(**kwargs)
99 next(self.coro)
99 next(self.coro)
100
100
101 def __repr__(self):
101 def __repr__(self):
102 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
102 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
103
103
104 def push(self, line):
104 def push(self, line):
105 """Send a line of input to the transformer, returning the
105 """Send a line of input to the transformer, returning the
106 transformed input or None if the transformer is waiting for more
106 transformed input or None if the transformer is waiting for more
107 input.
107 input.
108 """
108 """
109 return self.coro.send(line)
109 return self.coro.send(line)
110
110
111 def reset(self):
111 def reset(self):
112 """Return, transformed any lines that the transformer has
112 """Return, transformed any lines that the transformer has
113 accumulated, and reset its internal state.
113 accumulated, and reset its internal state.
114 """
114 """
115 return self.coro.send(None)
115 return self.coro.send(None)
116
116
117 class TokenInputTransformer(InputTransformer):
117 class TokenInputTransformer(InputTransformer):
118 """Wrapper for a token-based input transformer.
118 """Wrapper for a token-based input transformer.
119
119
120 func should accept a list of tokens (5-tuples, see tokenize docs), and
120 func should accept a list of tokens (5-tuples, see tokenize docs), and
121 return an iterable which can be passed to tokenize.untokenize().
121 return an iterable which can be passed to tokenize.untokenize().
122 """
122 """
123 def __init__(self, func):
123 def __init__(self, func):
124 self.func = func
124 self.func = func
125 self.buf = []
125 self.buf = []
126 self.reset_tokenizer()
126 self.reset_tokenizer()
127
127
128 def reset_tokenizer(self):
128 def reset_tokenizer(self):
129 it = iter(self.buf)
129 it = iter(self.buf)
130 self.tokenizer = generate_tokens(it.__next__)
130 self.tokenizer = generate_tokens(it.__next__)
131
131
132 def push(self, line):
132 def push(self, line):
133 self.buf.append(line + '\n')
133 self.buf.append(line + '\n')
134 if all(l.isspace() for l in self.buf):
134 if all(l.isspace() for l in self.buf):
135 return self.reset()
135 return self.reset()
136
136
137 tokens = []
137 tokens = []
138 stop_at_NL = False
138 stop_at_NL = False
139 try:
139 try:
140 for intok in self.tokenizer:
140 for intok in self.tokenizer:
141 tokens.append(intok)
141 tokens.append(intok)
142 t = intok[0]
142 t = intok[0]
143 if t == tokenize.NEWLINE or (stop_at_NL and t == tokenize.NL):
143 if t == tokenize.NEWLINE or (stop_at_NL and t == tokenize.NL):
144 # Stop before we try to pull a line we don't have yet
144 # Stop before we try to pull a line we don't have yet
145 break
145 break
146 elif t == tokenize.ERRORTOKEN:
146 elif t == tokenize.ERRORTOKEN:
147 stop_at_NL = True
147 stop_at_NL = True
148 except TokenError:
148 except TokenError:
149 # Multi-line statement - stop and try again with the next line
149 # Multi-line statement - stop and try again with the next line
150 self.reset_tokenizer()
150 self.reset_tokenizer()
151 return None
151 return None
152
152
153 return self.output(tokens)
153 return self.output(tokens)
154
154
155 def output(self, tokens):
155 def output(self, tokens):
156 self.buf.clear()
156 self.buf.clear()
157 self.reset_tokenizer()
157 self.reset_tokenizer()
158 return untokenize(self.func(tokens)).rstrip('\n')
158 return untokenize(self.func(tokens)).rstrip('\n')
159
159
160 def reset(self):
160 def reset(self):
161 l = ''.join(self.buf)
161 l = ''.join(self.buf)
162 self.buf.clear()
162 self.buf.clear()
163 self.reset_tokenizer()
163 self.reset_tokenizer()
164 if l:
164 if l:
165 return l.rstrip('\n')
165 return l.rstrip('\n')
166
166
167 class assemble_python_lines(TokenInputTransformer):
167 class assemble_python_lines(TokenInputTransformer):
168 def __init__(self):
168 def __init__(self):
169 super(assemble_python_lines, self).__init__(None)
169 super(assemble_python_lines, self).__init__(None)
170
170
171 def output(self, tokens):
171 def output(self, tokens):
172 return self.reset()
172 return self.reset()
173
173
174 @CoroutineInputTransformer.wrap
174 @CoroutineInputTransformer.wrap
175 def assemble_logical_lines():
175 def assemble_logical_lines():
176 r"""Join lines following explicit line continuations (\)"""
176 r"""Join lines following explicit line continuations (\)"""
177 line = ''
177 line = ''
178 while True:
178 while True:
179 line = (yield line)
179 line = (yield line)
180 if not line or line.isspace():
180 if not line or line.isspace():
181 continue
181 continue
182
182
183 parts = []
183 parts = []
184 while line is not None:
184 while line is not None:
185 if line.endswith('\\') and (not has_comment(line)):
185 if line.endswith('\\') and (not has_comment(line)):
186 parts.append(line[:-1])
186 parts.append(line[:-1])
187 line = (yield None) # Get another line
187 line = (yield None) # Get another line
188 else:
188 else:
189 parts.append(line)
189 parts.append(line)
190 break
190 break
191
191
192 # Output
192 # Output
193 line = ''.join(parts)
193 line = ''.join(parts)
194
194
195 # Utilities
195 # Utilities
196 def _make_help_call(target, esc, lspace, next_input=None):
196 def _make_help_call(target, esc, lspace, next_input=None):
197 """Prepares a pinfo(2)/psearch call from a target name and the escape
197 """Prepares a pinfo(2)/psearch call from a target name and the escape
198 (i.e. ? or ??)"""
198 (i.e. ? or ??)"""
199 method = 'pinfo2' if esc == '??' \
199 method = 'pinfo2' if esc == '??' \
200 else 'psearch' if '*' in target \
200 else 'psearch' if '*' in target \
201 else 'pinfo'
201 else 'pinfo'
202 arg = " ".join([method, target])
202 arg = " ".join([method, target])
203 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
203 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
204 t_magic_name, _, t_magic_arg_s = arg.partition(' ')
204 t_magic_name, _, t_magic_arg_s = arg.partition(' ')
205 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
205 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
206 if next_input is None:
206 if next_input is None:
207 return '%sget_ipython().run_line_magic(%r, %r)' % (lspace, t_magic_name, t_magic_arg_s)
207 return '%sget_ipython().run_line_magic(%r, %r)' % (lspace, t_magic_name, t_magic_arg_s)
208 else:
208 else:
209 return '%sget_ipython().set_next_input(%r);get_ipython().run_line_magic(%r, %r)' % \
209 return '%sget_ipython().set_next_input(%r);get_ipython().run_line_magic(%r, %r)' % \
210 (lspace, next_input, t_magic_name, t_magic_arg_s)
210 (lspace, next_input, t_magic_name, t_magic_arg_s)
211
211
212 # These define the transformations for the different escape characters.
212 # These define the transformations for the different escape characters.
213 def _tr_system(line_info):
213 def _tr_system(line_info):
214 "Translate lines escaped with: !"
214 "Translate lines escaped with: !"
215 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
215 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
216 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
216 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
217
217
218 def _tr_system2(line_info):
218 def _tr_system2(line_info):
219 "Translate lines escaped with: !!"
219 "Translate lines escaped with: !!"
220 cmd = line_info.line.lstrip()[2:]
220 cmd = line_info.line.lstrip()[2:]
221 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
221 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
222
222
223 def _tr_help(line_info):
223 def _tr_help(line_info):
224 "Translate lines escaped with: ?/??"
224 "Translate lines escaped with: ?/??"
225 # A naked help line should just fire the intro help screen
225 # A naked help line should just fire the intro help screen
226 if not line_info.line[1:]:
226 if not line_info.line[1:]:
227 return 'get_ipython().show_usage()'
227 return 'get_ipython().show_usage()'
228
228
229 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
229 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
230
230
231 def _tr_magic(line_info):
231 def _tr_magic(line_info):
232 "Translate lines escaped with: %"
232 "Translate lines escaped with: %"
233 tpl = '%sget_ipython().run_line_magic(%r, %r)'
233 tpl = '%sget_ipython().run_line_magic(%r, %r)'
234 if line_info.line.startswith(ESC_MAGIC2):
234 if line_info.line.startswith(ESC_MAGIC2):
235 return line_info.line
235 return line_info.line
236 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
236 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
237 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
237 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
238 t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
238 t_magic_name, _, t_magic_arg_s = cmd.partition(' ')
239 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
239 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
240 return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
240 return tpl % (line_info.pre, t_magic_name, t_magic_arg_s)
241
241
242 def _tr_quote(line_info):
242 def _tr_quote(line_info):
243 "Translate lines escaped with: ,"
243 "Translate lines escaped with: ,"
244 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
244 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
245 '", "'.join(line_info.the_rest.split()) )
245 '", "'.join(line_info.the_rest.split()) )
246
246
247 def _tr_quote2(line_info):
247 def _tr_quote2(line_info):
248 "Translate lines escaped with: ;"
248 "Translate lines escaped with: ;"
249 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
249 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
250 line_info.the_rest)
250 line_info.the_rest)
251
251
252 def _tr_paren(line_info):
252 def _tr_paren(line_info):
253 "Translate lines escaped with: /"
253 "Translate lines escaped with: /"
254 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
254 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
255 ", ".join(line_info.the_rest.split()))
255 ", ".join(line_info.the_rest.split()))
256
256
257 tr = { ESC_SHELL : _tr_system,
257 tr = { ESC_SHELL : _tr_system,
258 ESC_SH_CAP : _tr_system2,
258 ESC_SH_CAP : _tr_system2,
259 ESC_HELP : _tr_help,
259 ESC_HELP : _tr_help,
260 ESC_HELP2 : _tr_help,
260 ESC_HELP2 : _tr_help,
261 ESC_MAGIC : _tr_magic,
261 ESC_MAGIC : _tr_magic,
262 ESC_QUOTE : _tr_quote,
262 ESC_QUOTE : _tr_quote,
263 ESC_QUOTE2 : _tr_quote2,
263 ESC_QUOTE2 : _tr_quote2,
264 ESC_PAREN : _tr_paren }
264 ESC_PAREN : _tr_paren }
265
265
266 @StatelessInputTransformer.wrap
266 @StatelessInputTransformer.wrap
267 def escaped_commands(line):
267 def escaped_commands(line):
268 """Transform escaped commands - %magic, !system, ?help + various autocalls.
268 """Transform escaped commands - %magic, !system, ?help + various autocalls.
269 """
269 """
270 if not line or line.isspace():
270 if not line or line.isspace():
271 return line
271 return line
272 lineinf = LineInfo(line)
272 lineinf = LineInfo(line)
273 if lineinf.esc not in tr:
273 if lineinf.esc not in tr:
274 return line
274 return line
275
275
276 return tr[lineinf.esc](lineinf)
276 return tr[lineinf.esc](lineinf)
277
277
278 _initial_space_re = re.compile(r'\s*')
278 _initial_space_re = re.compile(r'\s*')
279
279
280 _help_end_re = re.compile(r"""(%{0,2}
280 _help_end_re = re.compile(r"""(%{0,2}
281 (?!\d)[\w*]+ # Variable name
281 (?!\d)[\w*]+ # Variable name
282 (\.(?!\d)[\w*]+)* # .etc.etc
282 (\.(?!\d)[\w*]+)* # .etc.etc
283 )
283 )
284 (\?\??)$ # ? or ??
284 (\?\??)$ # ? or ??
285 """,
285 """,
286 re.VERBOSE)
286 re.VERBOSE)
287
287
288 # Extra pseudotokens for multiline strings and data structures
288 # Extra pseudotokens for multiline strings and data structures
289 _MULTILINE_STRING = object()
289 _MULTILINE_STRING = object()
290 _MULTILINE_STRUCTURE = object()
290 _MULTILINE_STRUCTURE = object()
291
291
292 def _line_tokens(line):
292 def _line_tokens(line):
293 """Helper for has_comment and ends_in_comment_or_string."""
293 """Helper for has_comment and ends_in_comment_or_string."""
294 readline = StringIO(line).readline
294 readline = StringIO(line).readline
295 toktypes = set()
295 toktypes = set()
296 try:
296 try:
297 for t in generate_tokens(readline):
297 for t in generate_tokens(readline):
298 toktypes.add(t[0])
298 toktypes.add(t[0])
299 except TokenError as e:
299 except TokenError as e:
300 # There are only two cases where a TokenError is raised.
300 # There are only two cases where a TokenError is raised.
301 if 'multi-line string' in e.args[0]:
301 if 'multi-line string' in e.args[0]:
302 toktypes.add(_MULTILINE_STRING)
302 toktypes.add(_MULTILINE_STRING)
303 else:
303 else:
304 toktypes.add(_MULTILINE_STRUCTURE)
304 toktypes.add(_MULTILINE_STRUCTURE)
305 return toktypes
305 return toktypes
306
306
307 def has_comment(src):
307 def has_comment(src):
308 """Indicate whether an input line has (i.e. ends in, or is) a comment.
308 """Indicate whether an input line has (i.e. ends in, or is) a comment.
309
309
310 This uses tokenize, so it can distinguish comments from # inside strings.
310 This uses tokenize, so it can distinguish comments from # inside strings.
311
311
312 Parameters
312 Parameters
313 ----------
313 ----------
314 src : string
314 src : string
315 A single line input string.
315 A single line input string.
316
316
317 Returns
317 Returns
318 -------
318 -------
319 comment : bool
319 comment : bool
320 True if source has a comment.
320 True if source has a comment.
321 """
321 """
322 return (tokenize.COMMENT in _line_tokens(src))
322 return (tokenize.COMMENT in _line_tokens(src))
323
323
324 def ends_in_comment_or_string(src):
324 def ends_in_comment_or_string(src):
325 """Indicates whether or not an input line ends in a comment or within
325 """Indicates whether or not an input line ends in a comment or within
326 a multiline string.
326 a multiline string.
327
327
328 Parameters
328 Parameters
329 ----------
329 ----------
330 src : string
330 src : string
331 A single line input string.
331 A single line input string.
332
332
333 Returns
333 Returns
334 -------
334 -------
335 comment : bool
335 comment : bool
336 True if source ends in a comment or multiline string.
336 True if source ends in a comment or multiline string.
337 """
337 """
338 toktypes = _line_tokens(src)
338 toktypes = _line_tokens(src)
339 return (tokenize.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
339 return (tokenize.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
340
340
341
341
342 @StatelessInputTransformer.wrap
342 @StatelessInputTransformer.wrap
343 def help_end(line):
343 def help_end(line):
344 """Translate lines with ?/?? at the end"""
344 """Translate lines with ?/?? at the end"""
345 m = _help_end_re.search(line)
345 m = _help_end_re.search(line)
346 if m is None or ends_in_comment_or_string(line):
346 if m is None or ends_in_comment_or_string(line):
347 return line
347 return line
348 target = m.group(1)
348 target = m.group(1)
349 esc = m.group(3)
349 esc = m.group(3)
350 lspace = _initial_space_re.match(line).group(0)
350 lspace = _initial_space_re.match(line).group(0)
351
351
352 # If we're mid-command, put it back on the next prompt for the user.
352 # If we're mid-command, put it back on the next prompt for the user.
353 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
353 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
354
354
355 return _make_help_call(target, esc, lspace, next_input)
355 return _make_help_call(target, esc, lspace, next_input)
356
356
357
357
358 @CoroutineInputTransformer.wrap
358 @CoroutineInputTransformer.wrap
359 def cellmagic(end_on_blank_line=False):
359 def cellmagic(end_on_blank_line=False):
360 """Captures & transforms cell magics.
360 """Captures & transforms cell magics.
361
361
362 After a cell magic is started, this stores up any lines it gets until it is
362 After a cell magic is started, this stores up any lines it gets until it is
363 reset (sent None).
363 reset (sent None).
364 """
364 """
365 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
365 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
366 cellmagic_help_re = re.compile(r'%%\w+\?')
366 cellmagic_help_re = re.compile(r'%%\w+\?')
367 line = ''
367 line = ''
368 while True:
368 while True:
369 line = (yield line)
369 line = (yield line)
370 # consume leading empty lines
370 # consume leading empty lines
371 while not line:
371 while not line:
372 line = (yield line)
372 line = (yield line)
373
373
374 if not line.startswith(ESC_MAGIC2):
374 if not line.startswith(ESC_MAGIC2):
375 # This isn't a cell magic, idle waiting for reset then start over
375 # This isn't a cell magic, idle waiting for reset then start over
376 while line is not None:
376 while line is not None:
377 line = (yield line)
377 line = (yield line)
378 continue
378 continue
379
379
380 if cellmagic_help_re.match(line):
380 if cellmagic_help_re.match(line):
381 # This case will be handled by help_end
381 # This case will be handled by help_end
382 continue
382 continue
383
383
384 first = line
384 first = line
385 body = []
385 body = []
386 line = (yield None)
386 line = (yield None)
387 while (line is not None) and \
387 while (line is not None) and \
388 ((line.strip() != '') or not end_on_blank_line):
388 ((line.strip() != '') or not end_on_blank_line):
389 body.append(line)
389 body.append(line)
390 line = (yield None)
390 line = (yield None)
391
391
392 # Output
392 # Output
393 magic_name, _, first = first.partition(' ')
393 magic_name, _, first = first.partition(' ')
394 magic_name = magic_name.lstrip(ESC_MAGIC2)
394 magic_name = magic_name.lstrip(ESC_MAGIC2)
395 line = tpl % (magic_name, first, u'\n'.join(body))
395 line = tpl % (magic_name, first, u'\n'.join(body))
396
396
397
397
398 def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
398 def _strip_prompts(prompt_re, initial_re=None, turnoff_re=None):
399 """Remove matching input prompts from a block of input.
399 """Remove matching input prompts from a block of input.
400
400
401 Parameters
401 Parameters
402 ----------
402 ----------
403 prompt_re : regular expression
403 prompt_re : regular expression
404 A regular expression matching any input prompt (including continuation)
404 A regular expression matching any input prompt (including continuation)
405 initial_re : regular expression, optional
405 initial_re : regular expression, optional
406 A regular expression matching only the initial prompt, but not continuation.
406 A regular expression matching only the initial prompt, but not continuation.
407 If no initial expression is given, prompt_re will be used everywhere.
407 If no initial expression is given, prompt_re will be used everywhere.
408 Used mainly for plain Python prompts, where the continuation prompt
408 Used mainly for plain Python prompts, where the continuation prompt
409 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
409 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
410 If initial_re and prompt_re differ,
410
411 only initial_re will be tested against the first line.
411 Notes
412 -----
413 If `initial_re` and `prompt_re differ`,
414 only `initial_re` will be tested against the first line.
412 If any prompt is found on the first two lines,
415 If any prompt is found on the first two lines,
413 prompts will be stripped from the rest of the block.
416 prompts will be stripped from the rest of the block.
414 """
417 """
415 if initial_re is None:
418 if initial_re is None:
416 initial_re = prompt_re
419 initial_re = prompt_re
417 line = ''
420 line = ''
418 while True:
421 while True:
419 line = (yield line)
422 line = (yield line)
420
423
421 # First line of cell
424 # First line of cell
422 if line is None:
425 if line is None:
423 continue
426 continue
424 out, n1 = initial_re.subn('', line, count=1)
427 out, n1 = initial_re.subn('', line, count=1)
425 if turnoff_re and not n1:
428 if turnoff_re and not n1:
426 if turnoff_re.match(line):
429 if turnoff_re.match(line):
427 # We're in e.g. a cell magic; disable this transformer for
430 # We're in e.g. a cell magic; disable this transformer for
428 # the rest of the cell.
431 # the rest of the cell.
429 while line is not None:
432 while line is not None:
430 line = (yield line)
433 line = (yield line)
431 continue
434 continue
432
435
433 line = (yield out)
436 line = (yield out)
434
437
435 if line is None:
438 if line is None:
436 continue
439 continue
437 # check for any prompt on the second line of the cell,
440 # check for any prompt on the second line of the cell,
438 # because people often copy from just after the first prompt,
441 # because people often copy from just after the first prompt,
439 # so we might not see it in the first line.
442 # so we might not see it in the first line.
440 out, n2 = prompt_re.subn('', line, count=1)
443 out, n2 = prompt_re.subn('', line, count=1)
441 line = (yield out)
444 line = (yield out)
442
445
443 if n1 or n2:
446 if n1 or n2:
444 # Found a prompt in the first two lines - check for it in
447 # Found a prompt in the first two lines - check for it in
445 # the rest of the cell as well.
448 # the rest of the cell as well.
446 while line is not None:
449 while line is not None:
447 line = (yield prompt_re.sub('', line, count=1))
450 line = (yield prompt_re.sub('', line, count=1))
448
451
449 else:
452 else:
450 # Prompts not in input - wait for reset
453 # Prompts not in input - wait for reset
451 while line is not None:
454 while line is not None:
452 line = (yield line)
455 line = (yield line)
453
456
454 @CoroutineInputTransformer.wrap
457 @CoroutineInputTransformer.wrap
455 def classic_prompt():
458 def classic_prompt():
456 """Strip the >>>/... prompts of the Python interactive shell."""
459 """Strip the >>>/... prompts of the Python interactive shell."""
457 # FIXME: non-capturing version (?:...) usable?
460 # FIXME: non-capturing version (?:...) usable?
458 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
461 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
459 initial_re = re.compile(r'^>>>( |$)')
462 initial_re = re.compile(r'^>>>( |$)')
460 # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
463 # Any %magic/!system is IPython syntax, so we needn't look for >>> prompts
461 turnoff_re = re.compile(r'^[%!]')
464 turnoff_re = re.compile(r'^[%!]')
462 return _strip_prompts(prompt_re, initial_re, turnoff_re)
465 return _strip_prompts(prompt_re, initial_re, turnoff_re)
463
466
464 @CoroutineInputTransformer.wrap
467 @CoroutineInputTransformer.wrap
465 def ipy_prompt():
468 def ipy_prompt():
466 """Strip IPython's In [1]:/...: prompts."""
469 """Strip IPython's In [1]:/...: prompts."""
467 # FIXME: non-capturing version (?:...) usable?
470 # FIXME: non-capturing version (?:...) usable?
468 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
471 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
469 # Disable prompt stripping inside cell magics
472 # Disable prompt stripping inside cell magics
470 turnoff_re = re.compile(r'^%%')
473 turnoff_re = re.compile(r'^%%')
471 return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
474 return _strip_prompts(prompt_re, turnoff_re=turnoff_re)
472
475
473
476
474 @CoroutineInputTransformer.wrap
477 @CoroutineInputTransformer.wrap
475 def leading_indent():
478 def leading_indent():
476 """Remove leading indentation.
479 """Remove leading indentation.
477
480
478 If the first line starts with a spaces or tabs, the same whitespace will be
481 If the first line starts with a spaces or tabs, the same whitespace will be
479 removed from each following line until it is reset.
482 removed from each following line until it is reset.
480 """
483 """
481 space_re = re.compile(r'^[ \t]+')
484 space_re = re.compile(r'^[ \t]+')
482 line = ''
485 line = ''
483 while True:
486 while True:
484 line = (yield line)
487 line = (yield line)
485
488
486 if line is None:
489 if line is None:
487 continue
490 continue
488
491
489 m = space_re.match(line)
492 m = space_re.match(line)
490 if m:
493 if m:
491 space = m.group(0)
494 space = m.group(0)
492 while line is not None:
495 while line is not None:
493 if line.startswith(space):
496 if line.startswith(space):
494 line = line[len(space):]
497 line = line[len(space):]
495 line = (yield line)
498 line = (yield line)
496 else:
499 else:
497 # No leading spaces - wait for reset
500 # No leading spaces - wait for reset
498 while line is not None:
501 while line is not None:
499 line = (yield line)
502 line = (yield line)
500
503
501
504
502 _assign_pat = \
505 _assign_pat = \
503 r'''(?P<lhs>(\s*)
506 r'''(?P<lhs>(\s*)
504 ([\w\.]+) # Initial identifier
507 ([\w\.]+) # Initial identifier
505 (\s*,\s*
508 (\s*,\s*
506 \*?[\w\.]+)* # Further identifiers for unpacking
509 \*?[\w\.]+)* # Further identifiers for unpacking
507 \s*?,? # Trailing comma
510 \s*?,? # Trailing comma
508 )
511 )
509 \s*=\s*
512 \s*=\s*
510 '''
513 '''
511
514
512 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
515 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
513 assign_system_template = '%s = get_ipython().getoutput(%r)'
516 assign_system_template = '%s = get_ipython().getoutput(%r)'
514 @StatelessInputTransformer.wrap
517 @StatelessInputTransformer.wrap
515 def assign_from_system(line):
518 def assign_from_system(line):
516 """Transform assignment from system commands (e.g. files = !ls)"""
519 """Transform assignment from system commands (e.g. files = !ls)"""
517 m = assign_system_re.match(line)
520 m = assign_system_re.match(line)
518 if m is None:
521 if m is None:
519 return line
522 return line
520
523
521 return assign_system_template % m.group('lhs', 'cmd')
524 return assign_system_template % m.group('lhs', 'cmd')
522
525
523 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
526 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
524 assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)'
527 assign_magic_template = '%s = get_ipython().run_line_magic(%r, %r)'
525 @StatelessInputTransformer.wrap
528 @StatelessInputTransformer.wrap
526 def assign_from_magic(line):
529 def assign_from_magic(line):
527 """Transform assignment from magic commands (e.g. a = %who_ls)"""
530 """Transform assignment from magic commands (e.g. a = %who_ls)"""
528 m = assign_magic_re.match(line)
531 m = assign_magic_re.match(line)
529 if m is None:
532 if m is None:
530 return line
533 return line
531 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
534 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
532 m_lhs, m_cmd = m.group('lhs', 'cmd')
535 m_lhs, m_cmd = m.group('lhs', 'cmd')
533 t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ')
536 t_magic_name, _, t_magic_arg_s = m_cmd.partition(' ')
534 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
537 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
535 return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s)
538 return assign_magic_template % (m_lhs, t_magic_name, t_magic_arg_s)
@@ -1,707 +1,711 b''
1 """Implementation of namespace-related magic functions.
1 """Implementation of namespace-related magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import gc
16 import gc
17 import re
17 import re
18 import sys
18 import sys
19
19
20 # Our own packages
20 # Our own packages
21 from IPython.core import page
21 from IPython.core import page
22 from IPython.core.error import StdinNotImplementedError, UsageError
22 from IPython.core.error import StdinNotImplementedError, UsageError
23 from IPython.core.magic import Magics, magics_class, line_magic
23 from IPython.core.magic import Magics, magics_class, line_magic
24 from IPython.testing.skipdoctest import skip_doctest
24 from IPython.testing.skipdoctest import skip_doctest
25 from IPython.utils.encoding import DEFAULT_ENCODING
25 from IPython.utils.encoding import DEFAULT_ENCODING
26 from IPython.utils.openpy import read_py_file
26 from IPython.utils.openpy import read_py_file
27 from IPython.utils.path import get_py_filename
27 from IPython.utils.path import get_py_filename
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Magic implementation classes
30 # Magic implementation classes
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 @magics_class
33 @magics_class
34 class NamespaceMagics(Magics):
34 class NamespaceMagics(Magics):
35 """Magics to manage various aspects of the user's namespace.
35 """Magics to manage various aspects of the user's namespace.
36
36
37 These include listing variables, introspecting into them, etc.
37 These include listing variables, introspecting into them, etc.
38 """
38 """
39
39
40 @line_magic
40 @line_magic
41 def pinfo(self, parameter_s='', namespaces=None):
41 def pinfo(self, parameter_s='', namespaces=None):
42 """Provide detailed information about an object.
42 """Provide detailed information about an object.
43
43
44 '%pinfo object' is just a synonym for object? or ?object."""
44 '%pinfo object' is just a synonym for object? or ?object."""
45
45
46 #print 'pinfo par: <%s>' % parameter_s # dbg
46 #print 'pinfo par: <%s>' % parameter_s # dbg
47 # detail_level: 0 -> obj? , 1 -> obj??
47 # detail_level: 0 -> obj? , 1 -> obj??
48 detail_level = 0
48 detail_level = 0
49 # We need to detect if we got called as 'pinfo pinfo foo', which can
49 # We need to detect if we got called as 'pinfo pinfo foo', which can
50 # happen if the user types 'pinfo foo?' at the cmd line.
50 # happen if the user types 'pinfo foo?' at the cmd line.
51 pinfo,qmark1,oname,qmark2 = \
51 pinfo,qmark1,oname,qmark2 = \
52 re.match(r'(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
52 re.match(r'(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
53 if pinfo or qmark1 or qmark2:
53 if pinfo or qmark1 or qmark2:
54 detail_level = 1
54 detail_level = 1
55 if "*" in oname:
55 if "*" in oname:
56 self.psearch(oname)
56 self.psearch(oname)
57 else:
57 else:
58 self.shell._inspect('pinfo', oname, detail_level=detail_level,
58 self.shell._inspect('pinfo', oname, detail_level=detail_level,
59 namespaces=namespaces)
59 namespaces=namespaces)
60
60
61 @line_magic
61 @line_magic
62 def pinfo2(self, parameter_s='', namespaces=None):
62 def pinfo2(self, parameter_s='', namespaces=None):
63 """Provide extra detailed information about an object.
63 """Provide extra detailed information about an object.
64
64
65 '%pinfo2 object' is just a synonym for object?? or ??object."""
65 '%pinfo2 object' is just a synonym for object?? or ??object."""
66 self.shell._inspect('pinfo', parameter_s, detail_level=1,
66 self.shell._inspect('pinfo', parameter_s, detail_level=1,
67 namespaces=namespaces)
67 namespaces=namespaces)
68
68
69 @skip_doctest
69 @skip_doctest
70 @line_magic
70 @line_magic
71 def pdef(self, parameter_s='', namespaces=None):
71 def pdef(self, parameter_s='', namespaces=None):
72 """Print the call signature for any callable object.
72 """Print the call signature for any callable object.
73
73
74 If the object is a class, print the constructor information.
74 If the object is a class, print the constructor information.
75
75
76 Examples
76 Examples
77 --------
77 --------
78 ::
78 ::
79
79
80 In [3]: %pdef urllib.urlopen
80 In [3]: %pdef urllib.urlopen
81 urllib.urlopen(url, data=None, proxies=None)
81 urllib.urlopen(url, data=None, proxies=None)
82 """
82 """
83 self.shell._inspect('pdef',parameter_s, namespaces)
83 self.shell._inspect('pdef',parameter_s, namespaces)
84
84
85 @line_magic
85 @line_magic
86 def pdoc(self, parameter_s='', namespaces=None):
86 def pdoc(self, parameter_s='', namespaces=None):
87 """Print the docstring for an object.
87 """Print the docstring for an object.
88
88
89 If the given object is a class, it will print both the class and the
89 If the given object is a class, it will print both the class and the
90 constructor docstrings."""
90 constructor docstrings."""
91 self.shell._inspect('pdoc',parameter_s, namespaces)
91 self.shell._inspect('pdoc',parameter_s, namespaces)
92
92
93 @line_magic
93 @line_magic
94 def psource(self, parameter_s='', namespaces=None):
94 def psource(self, parameter_s='', namespaces=None):
95 """Print (or run through pager) the source code for an object."""
95 """Print (or run through pager) the source code for an object."""
96 if not parameter_s:
96 if not parameter_s:
97 raise UsageError('Missing object name.')
97 raise UsageError('Missing object name.')
98 self.shell._inspect('psource',parameter_s, namespaces)
98 self.shell._inspect('psource',parameter_s, namespaces)
99
99
100 @line_magic
100 @line_magic
101 def pfile(self, parameter_s='', namespaces=None):
101 def pfile(self, parameter_s='', namespaces=None):
102 """Print (or run through pager) the file where an object is defined.
102 """Print (or run through pager) the file where an object is defined.
103
103
104 The file opens at the line where the object definition begins. IPython
104 The file opens at the line where the object definition begins. IPython
105 will honor the environment variable PAGER if set, and otherwise will
105 will honor the environment variable PAGER if set, and otherwise will
106 do its best to print the file in a convenient form.
106 do its best to print the file in a convenient form.
107
107
108 If the given argument is not an object currently defined, IPython will
108 If the given argument is not an object currently defined, IPython will
109 try to interpret it as a filename (automatically adding a .py extension
109 try to interpret it as a filename (automatically adding a .py extension
110 if needed). You can thus use %pfile as a syntax highlighting code
110 if needed). You can thus use %pfile as a syntax highlighting code
111 viewer."""
111 viewer."""
112
112
113 # first interpret argument as an object name
113 # first interpret argument as an object name
114 out = self.shell._inspect('pfile',parameter_s, namespaces)
114 out = self.shell._inspect('pfile',parameter_s, namespaces)
115 # if not, try the input as a filename
115 # if not, try the input as a filename
116 if out == 'not found':
116 if out == 'not found':
117 try:
117 try:
118 filename = get_py_filename(parameter_s)
118 filename = get_py_filename(parameter_s)
119 except IOError as msg:
119 except IOError as msg:
120 print(msg)
120 print(msg)
121 return
121 return
122 page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
122 page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
123
123
124 @line_magic
124 @line_magic
125 def psearch(self, parameter_s=''):
125 def psearch(self, parameter_s=''):
126 """Search for object in namespaces by wildcard.
126 """Search for object in namespaces by wildcard.
127
127
128 %psearch [options] PATTERN [OBJECT TYPE]
128 %psearch [options] PATTERN [OBJECT TYPE]
129
129
130 Note: ? can be used as a synonym for %psearch, at the beginning or at
130 Note: ? can be used as a synonym for %psearch, at the beginning or at
131 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
131 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
132 rest of the command line must be unchanged (options come first), so
132 rest of the command line must be unchanged (options come first), so
133 for example the following forms are equivalent
133 for example the following forms are equivalent
134
134
135 %psearch -i a* function
135 %psearch -i a* function
136 -i a* function?
136 -i a* function?
137 ?-i a* function
137 ?-i a* function
138
138
139 Arguments:
139 Arguments:
140
140
141 PATTERN
141 PATTERN
142
142
143 where PATTERN is a string containing * as a wildcard similar to its
143 where PATTERN is a string containing * as a wildcard similar to its
144 use in a shell. The pattern is matched in all namespaces on the
144 use in a shell. The pattern is matched in all namespaces on the
145 search path. By default objects starting with a single _ are not
145 search path. By default objects starting with a single _ are not
146 matched, many IPython generated objects have a single
146 matched, many IPython generated objects have a single
147 underscore. The default is case insensitive matching. Matching is
147 underscore. The default is case insensitive matching. Matching is
148 also done on the attributes of objects and not only on the objects
148 also done on the attributes of objects and not only on the objects
149 in a module.
149 in a module.
150
150
151 [OBJECT TYPE]
151 [OBJECT TYPE]
152
152
153 Is the name of a python type from the types module. The name is
153 Is the name of a python type from the types module. The name is
154 given in lowercase without the ending type, ex. StringType is
154 given in lowercase without the ending type, ex. StringType is
155 written string. By adding a type here only objects matching the
155 written string. By adding a type here only objects matching the
156 given type are matched. Using all here makes the pattern match all
156 given type are matched. Using all here makes the pattern match all
157 types (this is the default).
157 types (this is the default).
158
158
159 Options:
159 Options:
160
160
161 -a: makes the pattern match even objects whose names start with a
161 -a: makes the pattern match even objects whose names start with a
162 single underscore. These names are normally omitted from the
162 single underscore. These names are normally omitted from the
163 search.
163 search.
164
164
165 -i/-c: make the pattern case insensitive/sensitive. If neither of
165 -i/-c: make the pattern case insensitive/sensitive. If neither of
166 these options are given, the default is read from your configuration
166 these options are given, the default is read from your configuration
167 file, with the option ``InteractiveShell.wildcards_case_sensitive``.
167 file, with the option ``InteractiveShell.wildcards_case_sensitive``.
168 If this option is not specified in your configuration file, IPython's
168 If this option is not specified in your configuration file, IPython's
169 internal default is to do a case sensitive search.
169 internal default is to do a case sensitive search.
170
170
171 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
171 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
172 specify can be searched in any of the following namespaces:
172 specify can be searched in any of the following namespaces:
173 'builtin', 'user', 'user_global','internal', 'alias', where
173 'builtin', 'user', 'user_global','internal', 'alias', where
174 'builtin' and 'user' are the search defaults. Note that you should
174 'builtin' and 'user' are the search defaults. Note that you should
175 not use quotes when specifying namespaces.
175 not use quotes when specifying namespaces.
176
176
177 -l: List all available object types for object matching. This function
177 -l: List all available object types for object matching. This function
178 can be used without arguments.
178 can be used without arguments.
179
179
180 'Builtin' contains the python module builtin, 'user' contains all
180 'Builtin' contains the python module builtin, 'user' contains all
181 user data, 'alias' only contain the shell aliases and no python
181 user data, 'alias' only contain the shell aliases and no python
182 objects, 'internal' contains objects used by IPython. The
182 objects, 'internal' contains objects used by IPython. The
183 'user_global' namespace is only used by embedded IPython instances,
183 'user_global' namespace is only used by embedded IPython instances,
184 and it contains module-level globals. You can add namespaces to the
184 and it contains module-level globals. You can add namespaces to the
185 search with -s or exclude them with -e (these options can be given
185 search with -s or exclude them with -e (these options can be given
186 more than once).
186 more than once).
187
187
188 Examples
188 Examples
189 --------
189 --------
190 ::
190 ::
191
191
192 %psearch a* -> objects beginning with an a
192 %psearch a* -> objects beginning with an a
193 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
193 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
194 %psearch a* function -> all functions beginning with an a
194 %psearch a* function -> all functions beginning with an a
195 %psearch re.e* -> objects beginning with an e in module re
195 %psearch re.e* -> objects beginning with an e in module re
196 %psearch r*.e* -> objects that start with e in modules starting in r
196 %psearch r*.e* -> objects that start with e in modules starting in r
197 %psearch r*.* string -> all strings in modules beginning with r
197 %psearch r*.* string -> all strings in modules beginning with r
198
198
199 Case sensitive search::
199 Case sensitive search::
200
200
201 %psearch -c a* list all object beginning with lower case a
201 %psearch -c a* list all object beginning with lower case a
202
202
203 Show objects beginning with a single _::
203 Show objects beginning with a single _::
204
204
205 %psearch -a _* list objects beginning with a single underscore
205 %psearch -a _* list objects beginning with a single underscore
206
206
207 List available objects::
207 List available objects::
208
208
209 %psearch -l list all available object types
209 %psearch -l list all available object types
210 """
210 """
211 # default namespaces to be searched
211 # default namespaces to be searched
212 def_search = ['user_local', 'user_global', 'builtin']
212 def_search = ['user_local', 'user_global', 'builtin']
213
213
214 # Process options/args
214 # Process options/args
215 opts,args = self.parse_options(parameter_s,'cias:e:l',list_all=True)
215 opts,args = self.parse_options(parameter_s,'cias:e:l',list_all=True)
216 opt = opts.get
216 opt = opts.get
217 shell = self.shell
217 shell = self.shell
218 psearch = shell.inspector.psearch
218 psearch = shell.inspector.psearch
219
219
220 # select list object types
220 # select list object types
221 list_types = False
221 list_types = False
222 if 'l' in opts:
222 if 'l' in opts:
223 list_types = True
223 list_types = True
224
224
225 # select case options
225 # select case options
226 if 'i' in opts:
226 if 'i' in opts:
227 ignore_case = True
227 ignore_case = True
228 elif 'c' in opts:
228 elif 'c' in opts:
229 ignore_case = False
229 ignore_case = False
230 else:
230 else:
231 ignore_case = not shell.wildcards_case_sensitive
231 ignore_case = not shell.wildcards_case_sensitive
232
232
233 # Build list of namespaces to search from user options
233 # Build list of namespaces to search from user options
234 def_search.extend(opt('s',[]))
234 def_search.extend(opt('s',[]))
235 ns_exclude = ns_exclude=opt('e',[])
235 ns_exclude = ns_exclude=opt('e',[])
236 ns_search = [nm for nm in def_search if nm not in ns_exclude]
236 ns_search = [nm for nm in def_search if nm not in ns_exclude]
237
237
238 # Call the actual search
238 # Call the actual search
239 try:
239 try:
240 psearch(args,shell.ns_table,ns_search,
240 psearch(args,shell.ns_table,ns_search,
241 show_all=opt('a'),ignore_case=ignore_case, list_types=list_types)
241 show_all=opt('a'),ignore_case=ignore_case, list_types=list_types)
242 except:
242 except:
243 shell.showtraceback()
243 shell.showtraceback()
244
244
245 @skip_doctest
245 @skip_doctest
246 @line_magic
246 @line_magic
247 def who_ls(self, parameter_s=''):
247 def who_ls(self, parameter_s=''):
248 """Return a sorted list of all interactive variables.
248 """Return a sorted list of all interactive variables.
249
249
250 If arguments are given, only variables of types matching these
250 If arguments are given, only variables of types matching these
251 arguments are returned.
251 arguments are returned.
252
252
253 Examples
253 Examples
254 --------
254 --------
255 Define two variables and list them with who_ls::
255 Define two variables and list them with who_ls::
256
256
257 In [1]: alpha = 123
257 In [1]: alpha = 123
258
258
259 In [2]: beta = 'test'
259 In [2]: beta = 'test'
260
260
261 In [3]: %who_ls
261 In [3]: %who_ls
262 Out[3]: ['alpha', 'beta']
262 Out[3]: ['alpha', 'beta']
263
263
264 In [4]: %who_ls int
264 In [4]: %who_ls int
265 Out[4]: ['alpha']
265 Out[4]: ['alpha']
266
266
267 In [5]: %who_ls str
267 In [5]: %who_ls str
268 Out[5]: ['beta']
268 Out[5]: ['beta']
269 """
269 """
270
270
271 user_ns = self.shell.user_ns
271 user_ns = self.shell.user_ns
272 user_ns_hidden = self.shell.user_ns_hidden
272 user_ns_hidden = self.shell.user_ns_hidden
273 nonmatching = object() # This can never be in user_ns
273 nonmatching = object() # This can never be in user_ns
274 out = [ i for i in user_ns
274 out = [ i for i in user_ns
275 if not i.startswith('_') \
275 if not i.startswith('_') \
276 and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
276 and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
277
277
278 typelist = parameter_s.split()
278 typelist = parameter_s.split()
279 if typelist:
279 if typelist:
280 typeset = set(typelist)
280 typeset = set(typelist)
281 out = [i for i in out if type(user_ns[i]).__name__ in typeset]
281 out = [i for i in out if type(user_ns[i]).__name__ in typeset]
282
282
283 out.sort()
283 out.sort()
284 return out
284 return out
285
285
286 @skip_doctest
286 @skip_doctest
287 @line_magic
287 @line_magic
288 def who(self, parameter_s=''):
288 def who(self, parameter_s=''):
289 """Print all interactive variables, with some minimal formatting.
289 """Print all interactive variables, with some minimal formatting.
290
290
291 If any arguments are given, only variables whose type matches one of
291 If any arguments are given, only variables whose type matches one of
292 these are printed. For example::
292 these are printed. For example::
293
293
294 %who function str
294 %who function str
295
295
296 will only list functions and strings, excluding all other types of
296 will only list functions and strings, excluding all other types of
297 variables. To find the proper type names, simply use type(var) at a
297 variables. To find the proper type names, simply use type(var) at a
298 command line to see how python prints type names. For example:
298 command line to see how python prints type names. For example:
299
299
300 ::
300 ::
301
301
302 In [1]: type('hello')\\
302 In [1]: type('hello')\\
303 Out[1]: <type 'str'>
303 Out[1]: <type 'str'>
304
304
305 indicates that the type name for strings is 'str'.
305 indicates that the type name for strings is 'str'.
306
306
307 ``%who`` always excludes executed names loaded through your configuration
307 ``%who`` always excludes executed names loaded through your configuration
308 file and things which are internal to IPython.
308 file and things which are internal to IPython.
309
309
310 This is deliberate, as typically you may load many modules and the
310 This is deliberate, as typically you may load many modules and the
311 purpose of %who is to show you only what you've manually defined.
311 purpose of %who is to show you only what you've manually defined.
312
312
313 Examples
313 Examples
314 --------
314 --------
315
315
316 Define two variables and list them with who::
316 Define two variables and list them with who::
317
317
318 In [1]: alpha = 123
318 In [1]: alpha = 123
319
319
320 In [2]: beta = 'test'
320 In [2]: beta = 'test'
321
321
322 In [3]: %who
322 In [3]: %who
323 alpha beta
323 alpha beta
324
324
325 In [4]: %who int
325 In [4]: %who int
326 alpha
326 alpha
327
327
328 In [5]: %who str
328 In [5]: %who str
329 beta
329 beta
330 """
330 """
331
331
332 varlist = self.who_ls(parameter_s)
332 varlist = self.who_ls(parameter_s)
333 if not varlist:
333 if not varlist:
334 if parameter_s:
334 if parameter_s:
335 print('No variables match your requested type.')
335 print('No variables match your requested type.')
336 else:
336 else:
337 print('Interactive namespace is empty.')
337 print('Interactive namespace is empty.')
338 return
338 return
339
339
340 # if we have variables, move on...
340 # if we have variables, move on...
341 count = 0
341 count = 0
342 for i in varlist:
342 for i in varlist:
343 print(i+'\t', end=' ')
343 print(i+'\t', end=' ')
344 count += 1
344 count += 1
345 if count > 8:
345 if count > 8:
346 count = 0
346 count = 0
347 print()
347 print()
348 print()
348 print()
349
349
350 @skip_doctest
350 @skip_doctest
351 @line_magic
351 @line_magic
352 def whos(self, parameter_s=''):
352 def whos(self, parameter_s=''):
353 """Like %who, but gives some extra information about each variable.
353 """Like %who, but gives some extra information about each variable.
354
354
355 The same type filtering of %who can be applied here.
355 The same type filtering of %who can be applied here.
356
356
357 For all variables, the type is printed. Additionally it prints:
357 For all variables, the type is printed. Additionally it prints:
358
358
359 - For {},[],(): their length.
359 - For {},[],(): their length.
360
360
361 - For numpy arrays, a summary with shape, number of
361 - For numpy arrays, a summary with shape, number of
362 elements, typecode and size in memory.
362 elements, typecode and size in memory.
363
363
364 - Everything else: a string representation, snipping their middle if
364 - Everything else: a string representation, snipping their middle if
365 too long.
365 too long.
366
366
367 Examples
367 Examples
368 --------
368 --------
369 Define two variables and list them with whos::
369 Define two variables and list them with whos::
370
370
371 In [1]: alpha = 123
371 In [1]: alpha = 123
372
372
373 In [2]: beta = 'test'
373 In [2]: beta = 'test'
374
374
375 In [3]: %whos
375 In [3]: %whos
376 Variable Type Data/Info
376 Variable Type Data/Info
377 --------------------------------
377 --------------------------------
378 alpha int 123
378 alpha int 123
379 beta str test
379 beta str test
380 """
380 """
381
381
382 varnames = self.who_ls(parameter_s)
382 varnames = self.who_ls(parameter_s)
383 if not varnames:
383 if not varnames:
384 if parameter_s:
384 if parameter_s:
385 print('No variables match your requested type.')
385 print('No variables match your requested type.')
386 else:
386 else:
387 print('Interactive namespace is empty.')
387 print('Interactive namespace is empty.')
388 return
388 return
389
389
390 # if we have variables, move on...
390 # if we have variables, move on...
391
391
392 # for these types, show len() instead of data:
392 # for these types, show len() instead of data:
393 seq_types = ['dict', 'list', 'tuple']
393 seq_types = ['dict', 'list', 'tuple']
394
394
395 # for numpy arrays, display summary info
395 # for numpy arrays, display summary info
396 ndarray_type = None
396 ndarray_type = None
397 if 'numpy' in sys.modules:
397 if 'numpy' in sys.modules:
398 try:
398 try:
399 from numpy import ndarray
399 from numpy import ndarray
400 except ImportError:
400 except ImportError:
401 pass
401 pass
402 else:
402 else:
403 ndarray_type = ndarray.__name__
403 ndarray_type = ndarray.__name__
404
404
405 # Find all variable names and types so we can figure out column sizes
405 # Find all variable names and types so we can figure out column sizes
406
406
407 # some types are well known and can be shorter
407 # some types are well known and can be shorter
408 abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
408 abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
409 def type_name(v):
409 def type_name(v):
410 tn = type(v).__name__
410 tn = type(v).__name__
411 return abbrevs.get(tn,tn)
411 return abbrevs.get(tn,tn)
412
412
413 varlist = [self.shell.user_ns[n] for n in varnames]
413 varlist = [self.shell.user_ns[n] for n in varnames]
414
414
415 typelist = []
415 typelist = []
416 for vv in varlist:
416 for vv in varlist:
417 tt = type_name(vv)
417 tt = type_name(vv)
418
418
419 if tt=='instance':
419 if tt=='instance':
420 typelist.append( abbrevs.get(str(vv.__class__),
420 typelist.append( abbrevs.get(str(vv.__class__),
421 str(vv.__class__)))
421 str(vv.__class__)))
422 else:
422 else:
423 typelist.append(tt)
423 typelist.append(tt)
424
424
425 # column labels and # of spaces as separator
425 # column labels and # of spaces as separator
426 varlabel = 'Variable'
426 varlabel = 'Variable'
427 typelabel = 'Type'
427 typelabel = 'Type'
428 datalabel = 'Data/Info'
428 datalabel = 'Data/Info'
429 colsep = 3
429 colsep = 3
430 # variable format strings
430 # variable format strings
431 vformat = "{0:<{varwidth}}{1:<{typewidth}}"
431 vformat = "{0:<{varwidth}}{1:<{typewidth}}"
432 aformat = "%s: %s elems, type `%s`, %s bytes"
432 aformat = "%s: %s elems, type `%s`, %s bytes"
433 # find the size of the columns to format the output nicely
433 # find the size of the columns to format the output nicely
434 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
434 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
435 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
435 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
436 # table header
436 # table header
437 print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
437 print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
438 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
438 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
439 # and the table itself
439 # and the table itself
440 kb = 1024
440 kb = 1024
441 Mb = 1048576 # kb**2
441 Mb = 1048576 # kb**2
442 for vname,var,vtype in zip(varnames,varlist,typelist):
442 for vname,var,vtype in zip(varnames,varlist,typelist):
443 print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
443 print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
444 if vtype in seq_types:
444 if vtype in seq_types:
445 print("n="+str(len(var)))
445 print("n="+str(len(var)))
446 elif vtype == ndarray_type:
446 elif vtype == ndarray_type:
447 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
447 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
448 if vtype==ndarray_type:
448 if vtype==ndarray_type:
449 # numpy
449 # numpy
450 vsize = var.size
450 vsize = var.size
451 vbytes = vsize*var.itemsize
451 vbytes = vsize*var.itemsize
452 vdtype = var.dtype
452 vdtype = var.dtype
453
453
454 if vbytes < 100000:
454 if vbytes < 100000:
455 print(aformat % (vshape, vsize, vdtype, vbytes))
455 print(aformat % (vshape, vsize, vdtype, vbytes))
456 else:
456 else:
457 print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
457 print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
458 if vbytes < Mb:
458 if vbytes < Mb:
459 print('(%s kb)' % (vbytes/kb,))
459 print('(%s kb)' % (vbytes/kb,))
460 else:
460 else:
461 print('(%s Mb)' % (vbytes/Mb,))
461 print('(%s Mb)' % (vbytes/Mb,))
462 else:
462 else:
463 try:
463 try:
464 vstr = str(var)
464 vstr = str(var)
465 except UnicodeEncodeError:
465 except UnicodeEncodeError:
466 vstr = var.encode(DEFAULT_ENCODING,
466 vstr = var.encode(DEFAULT_ENCODING,
467 'backslashreplace')
467 'backslashreplace')
468 except:
468 except:
469 vstr = "<object with id %d (str() failed)>" % id(var)
469 vstr = "<object with id %d (str() failed)>" % id(var)
470 vstr = vstr.replace('\n', '\\n')
470 vstr = vstr.replace('\n', '\\n')
471 if len(vstr) < 50:
471 if len(vstr) < 50:
472 print(vstr)
472 print(vstr)
473 else:
473 else:
474 print(vstr[:25] + "<...>" + vstr[-25:])
474 print(vstr[:25] + "<...>" + vstr[-25:])
475
475
476 @line_magic
476 @line_magic
477 def reset(self, parameter_s=''):
477 def reset(self, parameter_s=''):
478 """Resets the namespace by removing all names defined by the user, if
478 """Resets the namespace by removing all names defined by the user, if
479 called without arguments, or by removing some types of objects, such
479 called without arguments, or by removing some types of objects, such
480 as everything currently in IPython's In[] and Out[] containers (see
480 as everything currently in IPython's In[] and Out[] containers (see
481 the parameters for details).
481 the parameters for details).
482
482
483 Parameters
483 Parameters
484 ----------
484 ----------
485 -f
485 -f
486 force reset without asking for confirmation.
486 force reset without asking for confirmation.
487 -s
487 -s
488 'Soft' reset: Only clears your namespace, leaving history intact.
488 'Soft' reset: Only clears your namespace, leaving history intact.
489 References to objects may be kept. By default (without this option),
489 References to objects may be kept. By default (without this option),
490 we do a 'hard' reset, giving you a new session and removing all
490 we do a 'hard' reset, giving you a new session and removing all
491 references to objects from the current session.
491 references to objects from the current session.
492 --aggressive
492 --aggressive
493 Try to aggressively remove modules from sys.modules ; this
493 Try to aggressively remove modules from sys.modules ; this
494 may allow you to reimport Python modules that have been updated and
494 may allow you to reimport Python modules that have been updated and
495 pick up changes, but can have unattended consequences.
495 pick up changes, but can have unattended consequences.
496
496
497 in : reset input history
497 in
498 out : reset output history
498 reset input history
499 dhist : reset directory history
499 out
500 array : reset only variables that are NumPy arrays
500 reset output history
501 dhist
502 reset directory history
503 array
504 reset only variables that are NumPy arrays
501
505
502 See Also
506 See Also
503 --------
507 --------
504 reset_selective : invoked as ``%reset_selective``
508 reset_selective : invoked as ``%reset_selective``
505
509
506 Examples
510 Examples
507 --------
511 --------
508 ::
512 ::
509
513
510 In [6]: a = 1
514 In [6]: a = 1
511
515
512 In [7]: a
516 In [7]: a
513 Out[7]: 1
517 Out[7]: 1
514
518
515 In [8]: 'a' in get_ipython().user_ns
519 In [8]: 'a' in get_ipython().user_ns
516 Out[8]: True
520 Out[8]: True
517
521
518 In [9]: %reset -f
522 In [9]: %reset -f
519
523
520 In [1]: 'a' in get_ipython().user_ns
524 In [1]: 'a' in get_ipython().user_ns
521 Out[1]: False
525 Out[1]: False
522
526
523 In [2]: %reset -f in
527 In [2]: %reset -f in
524 Flushing input history
528 Flushing input history
525
529
526 In [3]: %reset -f dhist in
530 In [3]: %reset -f dhist in
527 Flushing directory history
531 Flushing directory history
528 Flushing input history
532 Flushing input history
529
533
530 Notes
534 Notes
531 -----
535 -----
532 Calling this magic from clients that do not implement standard input,
536 Calling this magic from clients that do not implement standard input,
533 such as the ipython notebook interface, will reset the namespace
537 such as the ipython notebook interface, will reset the namespace
534 without confirmation.
538 without confirmation.
535 """
539 """
536 opts, args = self.parse_options(parameter_s, "sf", "aggressive", mode="list")
540 opts, args = self.parse_options(parameter_s, "sf", "aggressive", mode="list")
537 if "f" in opts:
541 if "f" in opts:
538 ans = True
542 ans = True
539 else:
543 else:
540 try:
544 try:
541 ans = self.shell.ask_yes_no(
545 ans = self.shell.ask_yes_no(
542 "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
546 "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
543 default='n')
547 default='n')
544 except StdinNotImplementedError:
548 except StdinNotImplementedError:
545 ans = True
549 ans = True
546 if not ans:
550 if not ans:
547 print('Nothing done.')
551 print('Nothing done.')
548 return
552 return
549
553
550 if 's' in opts: # Soft reset
554 if 's' in opts: # Soft reset
551 user_ns = self.shell.user_ns
555 user_ns = self.shell.user_ns
552 for i in self.who_ls():
556 for i in self.who_ls():
553 del(user_ns[i])
557 del(user_ns[i])
554 elif len(args) == 0: # Hard reset
558 elif len(args) == 0: # Hard reset
555 self.shell.reset(new_session=False, aggressive=("aggressive" in opts))
559 self.shell.reset(new_session=False, aggressive=("aggressive" in opts))
556
560
557 # reset in/out/dhist/array: previously extensinions/clearcmd.py
561 # reset in/out/dhist/array: previously extensinions/clearcmd.py
558 ip = self.shell
562 ip = self.shell
559 user_ns = self.shell.user_ns # local lookup, heavily used
563 user_ns = self.shell.user_ns # local lookup, heavily used
560
564
561 for target in args:
565 for target in args:
562 target = target.lower() # make matches case insensitive
566 target = target.lower() # make matches case insensitive
563 if target == 'out':
567 if target == 'out':
564 print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
568 print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
565 self.shell.displayhook.flush()
569 self.shell.displayhook.flush()
566
570
567 elif target == 'in':
571 elif target == 'in':
568 print("Flushing input history")
572 print("Flushing input history")
569 pc = self.shell.displayhook.prompt_count + 1
573 pc = self.shell.displayhook.prompt_count + 1
570 for n in range(1, pc):
574 for n in range(1, pc):
571 key = '_i'+repr(n)
575 key = '_i'+repr(n)
572 user_ns.pop(key,None)
576 user_ns.pop(key,None)
573 user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
577 user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
574 hm = ip.history_manager
578 hm = ip.history_manager
575 # don't delete these, as %save and %macro depending on the
579 # don't delete these, as %save and %macro depending on the
576 # length of these lists to be preserved
580 # length of these lists to be preserved
577 hm.input_hist_parsed[:] = [''] * pc
581 hm.input_hist_parsed[:] = [''] * pc
578 hm.input_hist_raw[:] = [''] * pc
582 hm.input_hist_raw[:] = [''] * pc
579 # hm has internal machinery for _i,_ii,_iii, clear it out
583 # hm has internal machinery for _i,_ii,_iii, clear it out
580 hm._i = hm._ii = hm._iii = hm._i00 = u''
584 hm._i = hm._ii = hm._iii = hm._i00 = u''
581
585
582 elif target == 'array':
586 elif target == 'array':
583 # Support cleaning up numpy arrays
587 # Support cleaning up numpy arrays
584 try:
588 try:
585 from numpy import ndarray
589 from numpy import ndarray
586 # This must be done with items and not iteritems because
590 # This must be done with items and not iteritems because
587 # we're going to modify the dict in-place.
591 # we're going to modify the dict in-place.
588 for x,val in list(user_ns.items()):
592 for x,val in list(user_ns.items()):
589 if isinstance(val,ndarray):
593 if isinstance(val,ndarray):
590 del user_ns[x]
594 del user_ns[x]
591 except ImportError:
595 except ImportError:
592 print("reset array only works if Numpy is available.")
596 print("reset array only works if Numpy is available.")
593
597
594 elif target == 'dhist':
598 elif target == 'dhist':
595 print("Flushing directory history")
599 print("Flushing directory history")
596 del user_ns['_dh'][:]
600 del user_ns['_dh'][:]
597
601
598 else:
602 else:
599 print("Don't know how to reset ", end=' ')
603 print("Don't know how to reset ", end=' ')
600 print(target + ", please run `%reset?` for details")
604 print(target + ", please run `%reset?` for details")
601
605
602 gc.collect()
606 gc.collect()
603
607
604 @line_magic
608 @line_magic
605 def reset_selective(self, parameter_s=''):
609 def reset_selective(self, parameter_s=''):
606 """Resets the namespace by removing names defined by the user.
610 """Resets the namespace by removing names defined by the user.
607
611
608 Input/Output history are left around in case you need them.
612 Input/Output history are left around in case you need them.
609
613
610 %reset_selective [-f] regex
614 %reset_selective [-f] regex
611
615
612 No action is taken if regex is not included
616 No action is taken if regex is not included
613
617
614 Options
618 Options
615 -f : force reset without asking for confirmation.
619 -f : force reset without asking for confirmation.
616
620
617 See Also
621 See Also
618 --------
622 --------
619 reset : invoked as ``%reset``
623 reset : invoked as ``%reset``
620
624
621 Examples
625 Examples
622 --------
626 --------
623 We first fully reset the namespace so your output looks identical to
627 We first fully reset the namespace so your output looks identical to
624 this example for pedagogical reasons; in practice you do not need a
628 this example for pedagogical reasons; in practice you do not need a
625 full reset::
629 full reset::
626
630
627 In [1]: %reset -f
631 In [1]: %reset -f
628
632
629 Now, with a clean namespace we can make a few variables and use
633 Now, with a clean namespace we can make a few variables and use
630 ``%reset_selective`` to only delete names that match our regexp::
634 ``%reset_selective`` to only delete names that match our regexp::
631
635
632 In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
636 In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
633
637
634 In [3]: who_ls
638 In [3]: who_ls
635 Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
639 Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
636
640
637 In [4]: %reset_selective -f b[2-3]m
641 In [4]: %reset_selective -f b[2-3]m
638
642
639 In [5]: who_ls
643 In [5]: who_ls
640 Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
644 Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
641
645
642 In [6]: %reset_selective -f d
646 In [6]: %reset_selective -f d
643
647
644 In [7]: who_ls
648 In [7]: who_ls
645 Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
649 Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
646
650
647 In [8]: %reset_selective -f c
651 In [8]: %reset_selective -f c
648
652
649 In [9]: who_ls
653 In [9]: who_ls
650 Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
654 Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
651
655
652 In [10]: %reset_selective -f b
656 In [10]: %reset_selective -f b
653
657
654 In [11]: who_ls
658 In [11]: who_ls
655 Out[11]: ['a']
659 Out[11]: ['a']
656
660
657 Notes
661 Notes
658 -----
662 -----
659 Calling this magic from clients that do not implement standard input,
663 Calling this magic from clients that do not implement standard input,
660 such as the ipython notebook interface, will reset the namespace
664 such as the ipython notebook interface, will reset the namespace
661 without confirmation.
665 without confirmation.
662 """
666 """
663
667
664 opts, regex = self.parse_options(parameter_s,'f')
668 opts, regex = self.parse_options(parameter_s,'f')
665
669
666 if 'f' in opts:
670 if 'f' in opts:
667 ans = True
671 ans = True
668 else:
672 else:
669 try:
673 try:
670 ans = self.shell.ask_yes_no(
674 ans = self.shell.ask_yes_no(
671 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
675 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
672 default='n')
676 default='n')
673 except StdinNotImplementedError:
677 except StdinNotImplementedError:
674 ans = True
678 ans = True
675 if not ans:
679 if not ans:
676 print('Nothing done.')
680 print('Nothing done.')
677 return
681 return
678 user_ns = self.shell.user_ns
682 user_ns = self.shell.user_ns
679 if not regex:
683 if not regex:
680 print('No regex pattern specified. Nothing done.')
684 print('No regex pattern specified. Nothing done.')
681 return
685 return
682 else:
686 else:
683 try:
687 try:
684 m = re.compile(regex)
688 m = re.compile(regex)
685 except TypeError as e:
689 except TypeError as e:
686 raise TypeError('regex must be a string or compiled pattern') from e
690 raise TypeError('regex must be a string or compiled pattern') from e
687 for i in self.who_ls():
691 for i in self.who_ls():
688 if m.search(i):
692 if m.search(i):
689 del(user_ns[i])
693 del(user_ns[i])
690
694
691 @line_magic
695 @line_magic
692 def xdel(self, parameter_s=''):
696 def xdel(self, parameter_s=''):
693 """Delete a variable, trying to clear it from anywhere that
697 """Delete a variable, trying to clear it from anywhere that
694 IPython's machinery has references to it. By default, this uses
698 IPython's machinery has references to it. By default, this uses
695 the identity of the named object in the user namespace to remove
699 the identity of the named object in the user namespace to remove
696 references held under other names. The object is also removed
700 references held under other names. The object is also removed
697 from the output history.
701 from the output history.
698
702
699 Options
703 Options
700 -n : Delete the specified name from all namespaces, without
704 -n : Delete the specified name from all namespaces, without
701 checking their identity.
705 checking their identity.
702 """
706 """
703 opts, varname = self.parse_options(parameter_s,'n')
707 opts, varname = self.parse_options(parameter_s,'n')
704 try:
708 try:
705 self.shell.del_var(varname, ('n' in opts))
709 self.shell.del_var(varname, ('n' in opts))
706 except (NameError, ValueError) as e:
710 except (NameError, ValueError) as e:
707 print(type(e).__name__ +": "+ str(e))
711 print(type(e).__name__ +": "+ str(e))
@@ -1,1055 +1,1055 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 # Copyright (c) IPython Development Team.
10 # Copyright (c) IPython Development Team.
11 # Distributed under the terms of the Modified BSD License.
11 # Distributed under the terms of the Modified BSD License.
12
12
13 __all__ = ['Inspector','InspectColors']
13 __all__ = ['Inspector','InspectColors']
14
14
15 # stdlib modules
15 # stdlib modules
16 import ast
16 import ast
17 import inspect
17 import inspect
18 from inspect import signature
18 from inspect import signature
19 import linecache
19 import linecache
20 import warnings
20 import warnings
21 import os
21 import os
22 from textwrap import dedent
22 from textwrap import dedent
23 import types
23 import types
24 import io as stdlib_io
24 import io as stdlib_io
25
25
26 from typing import Union
26 from typing import Union
27
27
28 # IPython's own
28 # IPython's own
29 from IPython.core import page
29 from IPython.core import page
30 from IPython.lib.pretty import pretty
30 from IPython.lib.pretty import pretty
31 from IPython.testing.skipdoctest import skip_doctest
31 from IPython.testing.skipdoctest import skip_doctest
32 from IPython.utils import PyColorize
32 from IPython.utils import PyColorize
33 from IPython.utils import openpy
33 from IPython.utils import openpy
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.dir2 import safe_hasattr
35 from IPython.utils.dir2 import safe_hasattr
36 from IPython.utils.path import compress_user
36 from IPython.utils.path import compress_user
37 from IPython.utils.text import indent
37 from IPython.utils.text import indent
38 from IPython.utils.wildcard import list_namespace
38 from IPython.utils.wildcard import list_namespace
39 from IPython.utils.wildcard import typestr2type
39 from IPython.utils.wildcard import typestr2type
40 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
40 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
41 from IPython.utils.py3compat import cast_unicode
41 from IPython.utils.py3compat import cast_unicode
42 from IPython.utils.colorable import Colorable
42 from IPython.utils.colorable import Colorable
43 from IPython.utils.decorators import undoc
43 from IPython.utils.decorators import undoc
44
44
45 from pygments import highlight
45 from pygments import highlight
46 from pygments.lexers import PythonLexer
46 from pygments.lexers import PythonLexer
47 from pygments.formatters import HtmlFormatter
47 from pygments.formatters import HtmlFormatter
48
48
49 def pylight(code):
49 def pylight(code):
50 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
50 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
51
51
52 # builtin docstrings to ignore
52 # builtin docstrings to ignore
53 _func_call_docstring = types.FunctionType.__call__.__doc__
53 _func_call_docstring = types.FunctionType.__call__.__doc__
54 _object_init_docstring = object.__init__.__doc__
54 _object_init_docstring = object.__init__.__doc__
55 _builtin_type_docstrings = {
55 _builtin_type_docstrings = {
56 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
56 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
57 types.FunctionType, property)
57 types.FunctionType, property)
58 }
58 }
59
59
60 _builtin_func_type = type(all)
60 _builtin_func_type = type(all)
61 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
61 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
62 #****************************************************************************
62 #****************************************************************************
63 # Builtin color schemes
63 # Builtin color schemes
64
64
65 Colors = TermColors # just a shorthand
65 Colors = TermColors # just a shorthand
66
66
67 InspectColors = PyColorize.ANSICodeColors
67 InspectColors = PyColorize.ANSICodeColors
68
68
69 #****************************************************************************
69 #****************************************************************************
70 # Auxiliary functions and objects
70 # Auxiliary functions and objects
71
71
72 # 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
73 # effectively defines the order of display
73 # effectively defines the order of display
74 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
74 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
75 'length', 'file', 'definition', 'docstring', 'source',
75 'length', 'file', 'definition', 'docstring', 'source',
76 'init_definition', 'class_docstring', 'init_docstring',
76 'init_definition', 'class_docstring', 'init_docstring',
77 'call_def', 'call_docstring',
77 'call_def', 'call_docstring',
78 # 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
79 # format the object
79 # format the object
80 'ismagic', 'isalias', 'isclass', 'found', 'name'
80 'ismagic', 'isalias', 'isclass', 'found', 'name'
81 ]
81 ]
82
82
83
83
84 def object_info(**kw):
84 def object_info(**kw):
85 """Make an object info dict with all fields present."""
85 """Make an object info dict with all fields present."""
86 infodict = {k:None for k in info_fields}
86 infodict = {k:None for k in info_fields}
87 infodict.update(kw)
87 infodict.update(kw)
88 return infodict
88 return infodict
89
89
90
90
91 def get_encoding(obj):
91 def get_encoding(obj):
92 """Get encoding for python source file defining obj
92 """Get encoding for python source file defining obj
93
93
94 Returns None if obj is not defined in a sourcefile.
94 Returns None if obj is not defined in a sourcefile.
95 """
95 """
96 ofile = find_file(obj)
96 ofile = find_file(obj)
97 # run contents of file through pager starting at line where the object
97 # run contents of file through pager starting at line where the object
98 # is defined, as long as the file isn't binary and is actually on the
98 # is defined, as long as the file isn't binary and is actually on the
99 # filesystem.
99 # filesystem.
100 if ofile is None:
100 if ofile is None:
101 return None
101 return None
102 elif ofile.endswith(('.so', '.dll', '.pyd')):
102 elif ofile.endswith(('.so', '.dll', '.pyd')):
103 return None
103 return None
104 elif not os.path.isfile(ofile):
104 elif not os.path.isfile(ofile):
105 return None
105 return None
106 else:
106 else:
107 # Print only text files, not extension binaries. Note that
107 # Print only text files, not extension binaries. Note that
108 # getsourcelines returns lineno with 1-offset and page() uses
108 # getsourcelines returns lineno with 1-offset and page() uses
109 # 0-offset, so we must adjust.
109 # 0-offset, so we must adjust.
110 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
110 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
111 encoding, lines = openpy.detect_encoding(buffer.readline)
111 encoding, lines = openpy.detect_encoding(buffer.readline)
112 return encoding
112 return encoding
113
113
114 def getdoc(obj) -> Union[str,None]:
114 def getdoc(obj) -> Union[str,None]:
115 """Stable wrapper around inspect.getdoc.
115 """Stable wrapper around inspect.getdoc.
116
116
117 This can't crash because of attribute problems.
117 This can't crash because of attribute problems.
118
118
119 It also attempts to call a getdoc() method on the given object. This
119 It also attempts to call a getdoc() method on the given object. This
120 allows objects which provide their docstrings via non-standard mechanisms
120 allows objects which provide their docstrings via non-standard mechanisms
121 (like Pyro proxies) to still be inspected by ipython's ? system.
121 (like Pyro proxies) to still be inspected by ipython's ? system.
122 """
122 """
123 # Allow objects to offer customized documentation via a getdoc method:
123 # Allow objects to offer customized documentation via a getdoc method:
124 try:
124 try:
125 ds = obj.getdoc()
125 ds = obj.getdoc()
126 except Exception:
126 except Exception:
127 pass
127 pass
128 else:
128 else:
129 if isinstance(ds, str):
129 if isinstance(ds, str):
130 return inspect.cleandoc(ds)
130 return inspect.cleandoc(ds)
131 docstr = inspect.getdoc(obj)
131 docstr = inspect.getdoc(obj)
132 return docstr
132 return docstr
133
133
134
134
135 def getsource(obj, oname='') -> Union[str,None]:
135 def getsource(obj, oname='') -> Union[str,None]:
136 """Wrapper around inspect.getsource.
136 """Wrapper around inspect.getsource.
137
137
138 This can be modified by other projects to provide customized source
138 This can be modified by other projects to provide customized source
139 extraction.
139 extraction.
140
140
141 Parameters
141 Parameters
142 ----------
142 ----------
143 obj : object
143 obj : object
144 an object whose source code we will attempt to extract
144 an object whose source code we will attempt to extract
145 oname : str
145 oname : str
146 (optional) a name under which the object is known
146 (optional) a name under which the object is known
147
147
148 Returns
148 Returns
149 -------
149 -------
150 src : unicode or None
150 src : unicode or None
151
151
152 """
152 """
153
153
154 if isinstance(obj, property):
154 if isinstance(obj, property):
155 sources = []
155 sources = []
156 for attrname in ['fget', 'fset', 'fdel']:
156 for attrname in ['fget', 'fset', 'fdel']:
157 fn = getattr(obj, attrname)
157 fn = getattr(obj, attrname)
158 if fn is not None:
158 if fn is not None:
159 encoding = get_encoding(fn)
159 encoding = get_encoding(fn)
160 oname_prefix = ('%s.' % oname) if oname else ''
160 oname_prefix = ('%s.' % oname) if oname else ''
161 sources.append(''.join(('# ', oname_prefix, attrname)))
161 sources.append(''.join(('# ', oname_prefix, attrname)))
162 if inspect.isfunction(fn):
162 if inspect.isfunction(fn):
163 sources.append(dedent(getsource(fn)))
163 sources.append(dedent(getsource(fn)))
164 else:
164 else:
165 # Default str/repr only prints function name,
165 # Default str/repr only prints function name,
166 # pretty.pretty prints module name too.
166 # pretty.pretty prints module name too.
167 sources.append(
167 sources.append(
168 '%s%s = %s\n' % (oname_prefix, attrname, pretty(fn))
168 '%s%s = %s\n' % (oname_prefix, attrname, pretty(fn))
169 )
169 )
170 if sources:
170 if sources:
171 return '\n'.join(sources)
171 return '\n'.join(sources)
172 else:
172 else:
173 return None
173 return None
174
174
175 else:
175 else:
176 # Get source for non-property objects.
176 # Get source for non-property objects.
177
177
178 obj = _get_wrapped(obj)
178 obj = _get_wrapped(obj)
179
179
180 try:
180 try:
181 src = inspect.getsource(obj)
181 src = inspect.getsource(obj)
182 except TypeError:
182 except TypeError:
183 # The object itself provided no meaningful source, try looking for
183 # The object itself provided no meaningful source, try looking for
184 # its class definition instead.
184 # its class definition instead.
185 try:
185 try:
186 src = inspect.getsource(obj.__class__)
186 src = inspect.getsource(obj.__class__)
187 except (OSError, TypeError):
187 except (OSError, TypeError):
188 return None
188 return None
189 except OSError:
189 except OSError:
190 return None
190 return None
191
191
192 return src
192 return src
193
193
194
194
195 def is_simple_callable(obj):
195 def is_simple_callable(obj):
196 """True if obj is a function ()"""
196 """True if obj is a function ()"""
197 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
197 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
198 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
198 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
199
199
200 @undoc
200 @undoc
201 def getargspec(obj):
201 def getargspec(obj):
202 """Wrapper around :func:`inspect.getfullargspec`
202 """Wrapper around :func:`inspect.getfullargspec`
203
203
204 In addition to functions and methods, this can also handle objects with a
204 In addition to functions and methods, this can also handle objects with a
205 ``__call__`` attribute.
205 ``__call__`` attribute.
206
206
207 DEPRECATED: Deprecated since 7.10. Do not use, will be removed.
207 DEPRECATED: Deprecated since 7.10. Do not use, will be removed.
208 """
208 """
209
209
210 warnings.warn('`getargspec` function is deprecated as of IPython 7.10'
210 warnings.warn('`getargspec` function is deprecated as of IPython 7.10'
211 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
211 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
212
212
213 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
213 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
214 obj = obj.__call__
214 obj = obj.__call__
215
215
216 return inspect.getfullargspec(obj)
216 return inspect.getfullargspec(obj)
217
217
218 @undoc
218 @undoc
219 def format_argspec(argspec):
219 def format_argspec(argspec):
220 """Format argspect, convenience wrapper around inspect's.
220 """Format argspect, convenience wrapper around inspect's.
221
221
222 This takes a dict instead of ordered arguments and calls
222 This takes a dict instead of ordered arguments and calls
223 inspect.format_argspec with the arguments in the necessary order.
223 inspect.format_argspec with the arguments in the necessary order.
224
224
225 DEPRECATED (since 7.10): Do not use; will be removed in future versions.
225 DEPRECATED (since 7.10): Do not use; will be removed in future versions.
226 """
226 """
227
227
228 warnings.warn('`format_argspec` function is deprecated as of IPython 7.10'
228 warnings.warn('`format_argspec` function is deprecated as of IPython 7.10'
229 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
229 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
230
230
231
231
232 return inspect.formatargspec(argspec['args'], argspec['varargs'],
232 return inspect.formatargspec(argspec['args'], argspec['varargs'],
233 argspec['varkw'], argspec['defaults'])
233 argspec['varkw'], argspec['defaults'])
234
234
235 @undoc
235 @undoc
236 def call_tip(oinfo, format_call=True):
236 def call_tip(oinfo, format_call=True):
237 """DEPRECATED since 6.0. Extract call tip data from an oinfo dict."""
237 """DEPRECATED since 6.0. Extract call tip data from an oinfo dict."""
238 warnings.warn(
238 warnings.warn(
239 "`call_tip` function is deprecated as of IPython 6.0"
239 "`call_tip` function is deprecated as of IPython 6.0"
240 "and will be removed in future versions.",
240 "and will be removed in future versions.",
241 DeprecationWarning,
241 DeprecationWarning,
242 stacklevel=2,
242 stacklevel=2,
243 )
243 )
244 # Get call definition
244 # Get call definition
245 argspec = oinfo.get('argspec')
245 argspec = oinfo.get('argspec')
246 if argspec is None:
246 if argspec is None:
247 call_line = None
247 call_line = None
248 else:
248 else:
249 # Callable objects will have 'self' as their first argument, prune
249 # Callable objects will have 'self' as their first argument, prune
250 # it out if it's there for clarity (since users do *not* pass an
250 # it out if it's there for clarity (since users do *not* pass an
251 # extra first argument explicitly).
251 # extra first argument explicitly).
252 try:
252 try:
253 has_self = argspec['args'][0] == 'self'
253 has_self = argspec['args'][0] == 'self'
254 except (KeyError, IndexError):
254 except (KeyError, IndexError):
255 pass
255 pass
256 else:
256 else:
257 if has_self:
257 if has_self:
258 argspec['args'] = argspec['args'][1:]
258 argspec['args'] = argspec['args'][1:]
259
259
260 call_line = oinfo['name']+format_argspec(argspec)
260 call_line = oinfo['name']+format_argspec(argspec)
261
261
262 # Now get docstring.
262 # Now get docstring.
263 # The priority is: call docstring, constructor docstring, main one.
263 # The priority is: call docstring, constructor docstring, main one.
264 doc = oinfo.get('call_docstring')
264 doc = oinfo.get('call_docstring')
265 if doc is None:
265 if doc is None:
266 doc = oinfo.get('init_docstring')
266 doc = oinfo.get('init_docstring')
267 if doc is None:
267 if doc is None:
268 doc = oinfo.get('docstring','')
268 doc = oinfo.get('docstring','')
269
269
270 return call_line, doc
270 return call_line, doc
271
271
272
272
273 def _get_wrapped(obj):
273 def _get_wrapped(obj):
274 """Get the original object if wrapped in one or more @decorators
274 """Get the original object if wrapped in one or more @decorators
275
275
276 Some objects automatically construct similar objects on any unrecognised
276 Some objects automatically construct similar objects on any unrecognised
277 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
277 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
278 this will arbitrarily cut off after 100 levels of obj.__wrapped__
278 this will arbitrarily cut off after 100 levels of obj.__wrapped__
279 attribute access. --TK, Jan 2016
279 attribute access. --TK, Jan 2016
280 """
280 """
281 orig_obj = obj
281 orig_obj = obj
282 i = 0
282 i = 0
283 while safe_hasattr(obj, '__wrapped__'):
283 while safe_hasattr(obj, '__wrapped__'):
284 obj = obj.__wrapped__
284 obj = obj.__wrapped__
285 i += 1
285 i += 1
286 if i > 100:
286 if i > 100:
287 # __wrapped__ is probably a lie, so return the thing we started with
287 # __wrapped__ is probably a lie, so return the thing we started with
288 return orig_obj
288 return orig_obj
289 return obj
289 return obj
290
290
291 def find_file(obj) -> str:
291 def find_file(obj) -> str:
292 """Find the absolute path to the file where an object was defined.
292 """Find the absolute path to the file where an object was defined.
293
293
294 This is essentially a robust wrapper around `inspect.getabsfile`.
294 This is essentially a robust wrapper around `inspect.getabsfile`.
295
295
296 Returns None if no file can be found.
296 Returns None if no file can be found.
297
297
298 Parameters
298 Parameters
299 ----------
299 ----------
300 obj : any Python object
300 obj : any Python object
301
301
302 Returns
302 Returns
303 -------
303 -------
304 fname : str
304 fname : str
305 The absolute path to the file where the object was defined.
305 The absolute path to the file where the object was defined.
306 """
306 """
307 obj = _get_wrapped(obj)
307 obj = _get_wrapped(obj)
308
308
309 fname = None
309 fname = None
310 try:
310 try:
311 fname = inspect.getabsfile(obj)
311 fname = inspect.getabsfile(obj)
312 except TypeError:
312 except TypeError:
313 # For an instance, the file that matters is where its class was
313 # For an instance, the file that matters is where its class was
314 # declared.
314 # declared.
315 try:
315 try:
316 fname = inspect.getabsfile(obj.__class__)
316 fname = inspect.getabsfile(obj.__class__)
317 except (OSError, TypeError):
317 except (OSError, TypeError):
318 # Can happen for builtins
318 # Can happen for builtins
319 pass
319 pass
320 except OSError:
320 except OSError:
321 pass
321 pass
322
322
323 return cast_unicode(fname)
323 return cast_unicode(fname)
324
324
325
325
326 def find_source_lines(obj):
326 def find_source_lines(obj):
327 """Find the line number in a file where an object was defined.
327 """Find the line number in a file where an object was defined.
328
328
329 This is essentially a robust wrapper around `inspect.getsourcelines`.
329 This is essentially a robust wrapper around `inspect.getsourcelines`.
330
330
331 Returns None if no file can be found.
331 Returns None if no file can be found.
332
332
333 Parameters
333 Parameters
334 ----------
334 ----------
335 obj : any Python object
335 obj : any Python object
336
336
337 Returns
337 Returns
338 -------
338 -------
339 lineno : int
339 lineno : int
340 The line number where the object definition starts.
340 The line number where the object definition starts.
341 """
341 """
342 obj = _get_wrapped(obj)
342 obj = _get_wrapped(obj)
343
343
344 try:
344 try:
345 lineno = inspect.getsourcelines(obj)[1]
345 lineno = inspect.getsourcelines(obj)[1]
346 except TypeError:
346 except TypeError:
347 # For instances, try the class object like getsource() does
347 # For instances, try the class object like getsource() does
348 try:
348 try:
349 lineno = inspect.getsourcelines(obj.__class__)[1]
349 lineno = inspect.getsourcelines(obj.__class__)[1]
350 except (OSError, TypeError):
350 except (OSError, TypeError):
351 return None
351 return None
352 except OSError:
352 except OSError:
353 return None
353 return None
354
354
355 return lineno
355 return lineno
356
356
357 class Inspector(Colorable):
357 class Inspector(Colorable):
358
358
359 def __init__(self, color_table=InspectColors,
359 def __init__(self, color_table=InspectColors,
360 code_color_table=PyColorize.ANSICodeColors,
360 code_color_table=PyColorize.ANSICodeColors,
361 scheme=None,
361 scheme=None,
362 str_detail_level=0,
362 str_detail_level=0,
363 parent=None, config=None):
363 parent=None, config=None):
364 super(Inspector, self).__init__(parent=parent, config=config)
364 super(Inspector, self).__init__(parent=parent, config=config)
365 self.color_table = color_table
365 self.color_table = color_table
366 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
366 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
367 self.format = self.parser.format
367 self.format = self.parser.format
368 self.str_detail_level = str_detail_level
368 self.str_detail_level = str_detail_level
369 self.set_active_scheme(scheme)
369 self.set_active_scheme(scheme)
370
370
371 def _getdef(self,obj,oname='') -> Union[str,None]:
371 def _getdef(self,obj,oname='') -> Union[str,None]:
372 """Return the call signature for any callable object.
372 """Return the call signature for any callable object.
373
373
374 If any exception is generated, None is returned instead and the
374 If any exception is generated, None is returned instead and the
375 exception is suppressed."""
375 exception is suppressed."""
376 try:
376 try:
377 return _render_signature(signature(obj), oname)
377 return _render_signature(signature(obj), oname)
378 except:
378 except:
379 return None
379 return None
380
380
381 def __head(self,h) -> str:
381 def __head(self,h) -> str:
382 """Return a header string with proper colors."""
382 """Return a header string with proper colors."""
383 return '%s%s%s' % (self.color_table.active_colors.header,h,
383 return '%s%s%s' % (self.color_table.active_colors.header,h,
384 self.color_table.active_colors.normal)
384 self.color_table.active_colors.normal)
385
385
386 def set_active_scheme(self, scheme):
386 def set_active_scheme(self, scheme):
387 if scheme is not None:
387 if scheme is not None:
388 self.color_table.set_active_scheme(scheme)
388 self.color_table.set_active_scheme(scheme)
389 self.parser.color_table.set_active_scheme(scheme)
389 self.parser.color_table.set_active_scheme(scheme)
390
390
391 def noinfo(self, msg, oname):
391 def noinfo(self, msg, oname):
392 """Generic message when no information is found."""
392 """Generic message when no information is found."""
393 print('No %s found' % msg, end=' ')
393 print('No %s found' % msg, end=' ')
394 if oname:
394 if oname:
395 print('for %s' % oname)
395 print('for %s' % oname)
396 else:
396 else:
397 print()
397 print()
398
398
399 def pdef(self, obj, oname=''):
399 def pdef(self, obj, oname=''):
400 """Print the call signature for any callable object.
400 """Print the call signature for any callable object.
401
401
402 If the object is a class, print the constructor information."""
402 If the object is a class, print the constructor information."""
403
403
404 if not callable(obj):
404 if not callable(obj):
405 print('Object is not callable.')
405 print('Object is not callable.')
406 return
406 return
407
407
408 header = ''
408 header = ''
409
409
410 if inspect.isclass(obj):
410 if inspect.isclass(obj):
411 header = self.__head('Class constructor information:\n')
411 header = self.__head('Class constructor information:\n')
412
412
413
413
414 output = self._getdef(obj,oname)
414 output = self._getdef(obj,oname)
415 if output is None:
415 if output is None:
416 self.noinfo('definition header',oname)
416 self.noinfo('definition header',oname)
417 else:
417 else:
418 print(header,self.format(output), end=' ')
418 print(header,self.format(output), end=' ')
419
419
420 # In Python 3, all classes are new-style, so they all have __init__.
420 # In Python 3, all classes are new-style, so they all have __init__.
421 @skip_doctest
421 @skip_doctest
422 def pdoc(self, obj, oname='', formatter=None):
422 def pdoc(self, obj, oname='', formatter=None):
423 """Print the docstring for any object.
423 """Print the docstring for any object.
424
424
425 Optional:
425 Optional:
426 -formatter: a function to run the docstring through for specially
426 -formatter: a function to run the docstring through for specially
427 formatted docstrings.
427 formatted docstrings.
428
428
429 Examples
429 Examples
430 --------
430 --------
431 In [1]: class NoInit:
431 In [1]: class NoInit:
432 ...: pass
432 ...: pass
433
433
434 In [2]: class NoDoc:
434 In [2]: class NoDoc:
435 ...: def __init__(self):
435 ...: def __init__(self):
436 ...: pass
436 ...: pass
437
437
438 In [3]: %pdoc NoDoc
438 In [3]: %pdoc NoDoc
439 No documentation found for NoDoc
439 No documentation found for NoDoc
440
440
441 In [4]: %pdoc NoInit
441 In [4]: %pdoc NoInit
442 No documentation found for NoInit
442 No documentation found for NoInit
443
443
444 In [5]: obj = NoInit()
444 In [5]: obj = NoInit()
445
445
446 In [6]: %pdoc obj
446 In [6]: %pdoc obj
447 No documentation found for obj
447 No documentation found for obj
448
448
449 In [5]: obj2 = NoDoc()
449 In [5]: obj2 = NoDoc()
450
450
451 In [6]: %pdoc obj2
451 In [6]: %pdoc obj2
452 No documentation found for obj2
452 No documentation found for obj2
453 """
453 """
454
454
455 head = self.__head # For convenience
455 head = self.__head # For convenience
456 lines = []
456 lines = []
457 ds = getdoc(obj)
457 ds = getdoc(obj)
458 if formatter:
458 if formatter:
459 ds = formatter(ds).get('plain/text', ds)
459 ds = formatter(ds).get('plain/text', ds)
460 if ds:
460 if ds:
461 lines.append(head("Class docstring:"))
461 lines.append(head("Class docstring:"))
462 lines.append(indent(ds))
462 lines.append(indent(ds))
463 if inspect.isclass(obj) and hasattr(obj, '__init__'):
463 if inspect.isclass(obj) and hasattr(obj, '__init__'):
464 init_ds = getdoc(obj.__init__)
464 init_ds = getdoc(obj.__init__)
465 if init_ds is not None:
465 if init_ds is not None:
466 lines.append(head("Init docstring:"))
466 lines.append(head("Init docstring:"))
467 lines.append(indent(init_ds))
467 lines.append(indent(init_ds))
468 elif hasattr(obj,'__call__'):
468 elif hasattr(obj,'__call__'):
469 call_ds = getdoc(obj.__call__)
469 call_ds = getdoc(obj.__call__)
470 if call_ds:
470 if call_ds:
471 lines.append(head("Call docstring:"))
471 lines.append(head("Call docstring:"))
472 lines.append(indent(call_ds))
472 lines.append(indent(call_ds))
473
473
474 if not lines:
474 if not lines:
475 self.noinfo('documentation',oname)
475 self.noinfo('documentation',oname)
476 else:
476 else:
477 page.page('\n'.join(lines))
477 page.page('\n'.join(lines))
478
478
479 def psource(self, obj, oname=''):
479 def psource(self, obj, oname=''):
480 """Print the source code for an object."""
480 """Print the source code for an object."""
481
481
482 # Flush the source cache because inspect can return out-of-date source
482 # Flush the source cache because inspect can return out-of-date source
483 linecache.checkcache()
483 linecache.checkcache()
484 try:
484 try:
485 src = getsource(obj, oname=oname)
485 src = getsource(obj, oname=oname)
486 except Exception:
486 except Exception:
487 src = None
487 src = None
488
488
489 if src is None:
489 if src is None:
490 self.noinfo('source', oname)
490 self.noinfo('source', oname)
491 else:
491 else:
492 page.page(self.format(src))
492 page.page(self.format(src))
493
493
494 def pfile(self, obj, oname=''):
494 def pfile(self, obj, oname=''):
495 """Show the whole file where an object was defined."""
495 """Show the whole file where an object was defined."""
496
496
497 lineno = find_source_lines(obj)
497 lineno = find_source_lines(obj)
498 if lineno is None:
498 if lineno is None:
499 self.noinfo('file', oname)
499 self.noinfo('file', oname)
500 return
500 return
501
501
502 ofile = find_file(obj)
502 ofile = find_file(obj)
503 # run contents of file through pager starting at line where the object
503 # run contents of file through pager starting at line where the object
504 # is defined, as long as the file isn't binary and is actually on the
504 # is defined, as long as the file isn't binary and is actually on the
505 # filesystem.
505 # filesystem.
506 if ofile.endswith(('.so', '.dll', '.pyd')):
506 if ofile.endswith(('.so', '.dll', '.pyd')):
507 print('File %r is binary, not printing.' % ofile)
507 print('File %r is binary, not printing.' % ofile)
508 elif not os.path.isfile(ofile):
508 elif not os.path.isfile(ofile):
509 print('File %r does not exist, not printing.' % ofile)
509 print('File %r does not exist, not printing.' % ofile)
510 else:
510 else:
511 # Print only text files, not extension binaries. Note that
511 # Print only text files, not extension binaries. Note that
512 # getsourcelines returns lineno with 1-offset and page() uses
512 # getsourcelines returns lineno with 1-offset and page() uses
513 # 0-offset, so we must adjust.
513 # 0-offset, so we must adjust.
514 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
514 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
515
515
516
516
517 def _mime_format(self, text:str, formatter=None) -> dict:
517 def _mime_format(self, text:str, formatter=None) -> dict:
518 """Return a mime bundle representation of the input text.
518 """Return a mime bundle representation of the input text.
519
519
520 - if `formatter` is None, the returned mime bundle has
520 - if `formatter` is None, the returned mime bundle has
521 a `text/plain` field, with the input text.
521 a `text/plain` field, with the input text.
522 a `text/html` field with a `<pre>` tag containing the input text.
522 a `text/html` field with a `<pre>` tag containing the input text.
523
523
524 - if `formatter` is not None, it must be a callable transforming the
524 - if `formatter` is not None, it must be a callable transforming the
525 input text into a mime bundle. Default values for `text/plain` and
525 input text into a mime bundle. Default values for `text/plain` and
526 `text/html` representations are the ones described above.
526 `text/html` representations are the ones described above.
527
527
528 Note:
528 Note:
529
529
530 Formatters returning strings are supported but this behavior is deprecated.
530 Formatters returning strings are supported but this behavior is deprecated.
531
531
532 """
532 """
533 defaults = {
533 defaults = {
534 'text/plain': text,
534 'text/plain': text,
535 'text/html': '<pre>' + text + '</pre>'
535 'text/html': '<pre>' + text + '</pre>'
536 }
536 }
537
537
538 if formatter is None:
538 if formatter is None:
539 return defaults
539 return defaults
540 else:
540 else:
541 formatted = formatter(text)
541 formatted = formatter(text)
542
542
543 if not isinstance(formatted, dict):
543 if not isinstance(formatted, dict):
544 # Handle the deprecated behavior of a formatter returning
544 # Handle the deprecated behavior of a formatter returning
545 # a string instead of a mime bundle.
545 # a string instead of a mime bundle.
546 return {
546 return {
547 'text/plain': formatted,
547 'text/plain': formatted,
548 'text/html': '<pre>' + formatted + '</pre>'
548 'text/html': '<pre>' + formatted + '</pre>'
549 }
549 }
550
550
551 else:
551 else:
552 return dict(defaults, **formatted)
552 return dict(defaults, **formatted)
553
553
554
554
555 def format_mime(self, bundle):
555 def format_mime(self, bundle):
556
556
557 text_plain = bundle['text/plain']
557 text_plain = bundle['text/plain']
558
558
559 text = ''
559 text = ''
560 heads, bodies = list(zip(*text_plain))
560 heads, bodies = list(zip(*text_plain))
561 _len = max(len(h) for h in heads)
561 _len = max(len(h) for h in heads)
562
562
563 for head, body in zip(heads, bodies):
563 for head, body in zip(heads, bodies):
564 body = body.strip('\n')
564 body = body.strip('\n')
565 delim = '\n' if '\n' in body else ' '
565 delim = '\n' if '\n' in body else ' '
566 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
566 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
567
567
568 bundle['text/plain'] = text
568 bundle['text/plain'] = text
569 return bundle
569 return bundle
570
570
571 def _get_info(
571 def _get_info(
572 self, obj, oname="", formatter=None, info=None, detail_level=0, omit_sections=()
572 self, obj, oname="", formatter=None, info=None, detail_level=0, omit_sections=()
573 ):
573 ):
574 """Retrieve an info dict and format it.
574 """Retrieve an info dict and format it.
575
575
576 Parameters
576 Parameters
577 ----------
577 ----------
578 obj : any
578 obj : any
579 Object to inspect and return info from
579 Object to inspect and return info from
580 oname: str (default: ''):
580 oname : str (default: ''):
581 Name of the variable pointing to `obj`.
581 Name of the variable pointing to `obj`.
582 formatter : callable
582 formatter : callable
583 info:
583 info
584 already computed information
584 already computed information
585 detail_level : integer
585 detail_level : integer
586 Granularity of detail level, if set to 1, give more information.
586 Granularity of detail level, if set to 1, give more information.
587 omit_sections : container[str]
587 omit_sections : container[str]
588 Titles or keys to omit from output (can be set, tuple, etc., anything supporting `in`)
588 Titles or keys to omit from output (can be set, tuple, etc., anything supporting `in`)
589 """
589 """
590
590
591 info = self.info(obj, oname=oname, info=info, detail_level=detail_level)
591 info = self.info(obj, oname=oname, info=info, detail_level=detail_level)
592
592
593 _mime = {
593 _mime = {
594 'text/plain': [],
594 'text/plain': [],
595 'text/html': '',
595 'text/html': '',
596 }
596 }
597
597
598 def append_field(bundle, title:str, key:str, formatter=None):
598 def append_field(bundle, title:str, key:str, formatter=None):
599 if title in omit_sections or key in omit_sections:
599 if title in omit_sections or key in omit_sections:
600 return
600 return
601 field = info[key]
601 field = info[key]
602 if field is not None:
602 if field is not None:
603 formatted_field = self._mime_format(field, formatter)
603 formatted_field = self._mime_format(field, formatter)
604 bundle['text/plain'].append((title, formatted_field['text/plain']))
604 bundle['text/plain'].append((title, formatted_field['text/plain']))
605 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
605 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
606
606
607 def code_formatter(text):
607 def code_formatter(text):
608 return {
608 return {
609 'text/plain': self.format(text),
609 'text/plain': self.format(text),
610 'text/html': pylight(text)
610 'text/html': pylight(text)
611 }
611 }
612
612
613 if info['isalias']:
613 if info['isalias']:
614 append_field(_mime, 'Repr', 'string_form')
614 append_field(_mime, 'Repr', 'string_form')
615
615
616 elif info['ismagic']:
616 elif info['ismagic']:
617 if detail_level > 0:
617 if detail_level > 0:
618 append_field(_mime, 'Source', 'source', code_formatter)
618 append_field(_mime, 'Source', 'source', code_formatter)
619 else:
619 else:
620 append_field(_mime, 'Docstring', 'docstring', formatter)
620 append_field(_mime, 'Docstring', 'docstring', formatter)
621 append_field(_mime, 'File', 'file')
621 append_field(_mime, 'File', 'file')
622
622
623 elif info['isclass'] or is_simple_callable(obj):
623 elif info['isclass'] or is_simple_callable(obj):
624 # Functions, methods, classes
624 # Functions, methods, classes
625 append_field(_mime, 'Signature', 'definition', code_formatter)
625 append_field(_mime, 'Signature', 'definition', code_formatter)
626 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
626 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
627 append_field(_mime, 'Docstring', 'docstring', formatter)
627 append_field(_mime, 'Docstring', 'docstring', formatter)
628 if detail_level > 0 and info['source']:
628 if detail_level > 0 and info['source']:
629 append_field(_mime, 'Source', 'source', code_formatter)
629 append_field(_mime, 'Source', 'source', code_formatter)
630 else:
630 else:
631 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
631 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
632
632
633 append_field(_mime, 'File', 'file')
633 append_field(_mime, 'File', 'file')
634 append_field(_mime, 'Type', 'type_name')
634 append_field(_mime, 'Type', 'type_name')
635 append_field(_mime, 'Subclasses', 'subclasses')
635 append_field(_mime, 'Subclasses', 'subclasses')
636
636
637 else:
637 else:
638 # General Python objects
638 # General Python objects
639 append_field(_mime, 'Signature', 'definition', code_formatter)
639 append_field(_mime, 'Signature', 'definition', code_formatter)
640 append_field(_mime, 'Call signature', 'call_def', code_formatter)
640 append_field(_mime, 'Call signature', 'call_def', code_formatter)
641 append_field(_mime, 'Type', 'type_name')
641 append_field(_mime, 'Type', 'type_name')
642 append_field(_mime, 'String form', 'string_form')
642 append_field(_mime, 'String form', 'string_form')
643
643
644 # Namespace
644 # Namespace
645 if info['namespace'] != 'Interactive':
645 if info['namespace'] != 'Interactive':
646 append_field(_mime, 'Namespace', 'namespace')
646 append_field(_mime, 'Namespace', 'namespace')
647
647
648 append_field(_mime, 'Length', 'length')
648 append_field(_mime, 'Length', 'length')
649 append_field(_mime, 'File', 'file')
649 append_field(_mime, 'File', 'file')
650
650
651 # Source or docstring, depending on detail level and whether
651 # Source or docstring, depending on detail level and whether
652 # source found.
652 # source found.
653 if detail_level > 0 and info['source']:
653 if detail_level > 0 and info['source']:
654 append_field(_mime, 'Source', 'source', code_formatter)
654 append_field(_mime, 'Source', 'source', code_formatter)
655 else:
655 else:
656 append_field(_mime, 'Docstring', 'docstring', formatter)
656 append_field(_mime, 'Docstring', 'docstring', formatter)
657
657
658 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
658 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
659 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
659 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
660 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
660 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
661
661
662
662
663 return self.format_mime(_mime)
663 return self.format_mime(_mime)
664
664
665 def pinfo(
665 def pinfo(
666 self,
666 self,
667 obj,
667 obj,
668 oname="",
668 oname="",
669 formatter=None,
669 formatter=None,
670 info=None,
670 info=None,
671 detail_level=0,
671 detail_level=0,
672 enable_html_pager=True,
672 enable_html_pager=True,
673 omit_sections=(),
673 omit_sections=(),
674 ):
674 ):
675 """Show detailed information about an object.
675 """Show detailed information about an object.
676
676
677 Optional arguments:
677 Optional arguments:
678
678
679 - oname: name of the variable pointing to the object.
679 - oname: name of the variable pointing to the object.
680
680
681 - formatter: callable (optional)
681 - formatter: callable (optional)
682 A special formatter for docstrings.
682 A special formatter for docstrings.
683
683
684 The formatter is a callable that takes a string as an input
684 The formatter is a callable that takes a string as an input
685 and returns either a formatted string or a mime type bundle
685 and returns either a formatted string or a mime type bundle
686 in the form of a dictionary.
686 in the form of a dictionary.
687
687
688 Although the support of custom formatter returning a string
688 Although the support of custom formatter returning a string
689 instead of a mime type bundle is deprecated.
689 instead of a mime type bundle is deprecated.
690
690
691 - info: a structure with some information fields which may have been
691 - info: a structure with some information fields which may have been
692 precomputed already.
692 precomputed already.
693
693
694 - detail_level: if set to 1, more information is given.
694 - detail_level: if set to 1, more information is given.
695
695
696 - omit_sections: set of section keys and titles to omit
696 - omit_sections: set of section keys and titles to omit
697 """
697 """
698 info = self._get_info(
698 info = self._get_info(
699 obj, oname, formatter, info, detail_level, omit_sections=omit_sections
699 obj, oname, formatter, info, detail_level, omit_sections=omit_sections
700 )
700 )
701 if not enable_html_pager:
701 if not enable_html_pager:
702 del info['text/html']
702 del info['text/html']
703 page.page(info)
703 page.page(info)
704
704
705 def _info(self, obj, oname="", info=None, detail_level=0):
705 def _info(self, obj, oname="", info=None, detail_level=0):
706 """
706 """
707 Inspector.info() was likely improperly marked as deprecated
707 Inspector.info() was likely improperly marked as deprecated
708 while only a parameter was deprecated. We "un-deprecate" it.
708 while only a parameter was deprecated. We "un-deprecate" it.
709 """
709 """
710
710
711 warnings.warn(
711 warnings.warn(
712 "The `Inspector.info()` method has been un-deprecated as of 8.0 "
712 "The `Inspector.info()` method has been un-deprecated as of 8.0 "
713 "and the `formatter=` keyword removed. `Inspector._info` is now "
713 "and the `formatter=` keyword removed. `Inspector._info` is now "
714 "an alias, and you can just call `.info()` directly.",
714 "an alias, and you can just call `.info()` directly.",
715 DeprecationWarning,
715 DeprecationWarning,
716 stacklevel=2,
716 stacklevel=2,
717 )
717 )
718 return self.info(obj, oname=oname, info=info, detail_level=detail_level)
718 return self.info(obj, oname=oname, info=info, detail_level=detail_level)
719
719
720 def info(self, obj, oname="", info=None, detail_level=0) -> dict:
720 def info(self, obj, oname="", info=None, detail_level=0) -> dict:
721 """Compute a dict with detailed information about an object.
721 """Compute a dict with detailed information about an object.
722
722
723 Parameters
723 Parameters
724 ----------
724 ----------
725 obj : any
725 obj : any
726 An object to find information about
726 An object to find information about
727 oname : str (default: '')
727 oname : str (default: '')
728 Name of the variable pointing to `obj`.
728 Name of the variable pointing to `obj`.
729 info : (default: None)
729 info : (default: None)
730 A struct (dict like with attr access) with some information fields
730 A struct (dict like with attr access) with some information fields
731 which may have been precomputed already.
731 which may have been precomputed already.
732 detail_level : int (default:0)
732 detail_level : int (default:0)
733 If set to 1, more information is given.
733 If set to 1, more information is given.
734
734
735 Returns
735 Returns
736 -------
736 -------
737 An object info dict with known fields from `info_fields`. Keys are
737 An object info dict with known fields from `info_fields`. Keys are
738 strings, values are string or None.
738 strings, values are string or None.
739 """
739 """
740
740
741 if info is None:
741 if info is None:
742 ismagic = False
742 ismagic = False
743 isalias = False
743 isalias = False
744 ospace = ''
744 ospace = ''
745 else:
745 else:
746 ismagic = info.ismagic
746 ismagic = info.ismagic
747 isalias = info.isalias
747 isalias = info.isalias
748 ospace = info.namespace
748 ospace = info.namespace
749
749
750 # Get docstring, special-casing aliases:
750 # Get docstring, special-casing aliases:
751 if isalias:
751 if isalias:
752 if not callable(obj):
752 if not callable(obj):
753 try:
753 try:
754 ds = "Alias to the system command:\n %s" % obj[1]
754 ds = "Alias to the system command:\n %s" % obj[1]
755 except:
755 except:
756 ds = "Alias: " + str(obj)
756 ds = "Alias: " + str(obj)
757 else:
757 else:
758 ds = "Alias to " + str(obj)
758 ds = "Alias to " + str(obj)
759 if obj.__doc__:
759 if obj.__doc__:
760 ds += "\nDocstring:\n" + obj.__doc__
760 ds += "\nDocstring:\n" + obj.__doc__
761 else:
761 else:
762 ds = getdoc(obj)
762 ds = getdoc(obj)
763 if ds is None:
763 if ds is None:
764 ds = '<no docstring>'
764 ds = '<no docstring>'
765
765
766 # store output in a dict, we initialize it here and fill it as we go
766 # store output in a dict, we initialize it here and fill it as we go
767 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None)
767 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic, subclasses=None)
768
768
769 string_max = 200 # max size of strings to show (snipped if longer)
769 string_max = 200 # max size of strings to show (snipped if longer)
770 shalf = int((string_max - 5) / 2)
770 shalf = int((string_max - 5) / 2)
771
771
772 if ismagic:
772 if ismagic:
773 out['type_name'] = 'Magic function'
773 out['type_name'] = 'Magic function'
774 elif isalias:
774 elif isalias:
775 out['type_name'] = 'System alias'
775 out['type_name'] = 'System alias'
776 else:
776 else:
777 out['type_name'] = type(obj).__name__
777 out['type_name'] = type(obj).__name__
778
778
779 try:
779 try:
780 bclass = obj.__class__
780 bclass = obj.__class__
781 out['base_class'] = str(bclass)
781 out['base_class'] = str(bclass)
782 except:
782 except:
783 pass
783 pass
784
784
785 # String form, but snip if too long in ? form (full in ??)
785 # String form, but snip if too long in ? form (full in ??)
786 if detail_level >= self.str_detail_level:
786 if detail_level >= self.str_detail_level:
787 try:
787 try:
788 ostr = str(obj)
788 ostr = str(obj)
789 str_head = 'string_form'
789 str_head = 'string_form'
790 if not detail_level and len(ostr)>string_max:
790 if not detail_level and len(ostr)>string_max:
791 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
791 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
792 ostr = ("\n" + " " * len(str_head.expandtabs())).\
792 ostr = ("\n" + " " * len(str_head.expandtabs())).\
793 join(q.strip() for q in ostr.split("\n"))
793 join(q.strip() for q in ostr.split("\n"))
794 out[str_head] = ostr
794 out[str_head] = ostr
795 except:
795 except:
796 pass
796 pass
797
797
798 if ospace:
798 if ospace:
799 out['namespace'] = ospace
799 out['namespace'] = ospace
800
800
801 # Length (for strings and lists)
801 # Length (for strings and lists)
802 try:
802 try:
803 out['length'] = str(len(obj))
803 out['length'] = str(len(obj))
804 except Exception:
804 except Exception:
805 pass
805 pass
806
806
807 # Filename where object was defined
807 # Filename where object was defined
808 binary_file = False
808 binary_file = False
809 fname = find_file(obj)
809 fname = find_file(obj)
810 if fname is None:
810 if fname is None:
811 # if anything goes wrong, we don't want to show source, so it's as
811 # if anything goes wrong, we don't want to show source, so it's as
812 # if the file was binary
812 # if the file was binary
813 binary_file = True
813 binary_file = True
814 else:
814 else:
815 if fname.endswith(('.so', '.dll', '.pyd')):
815 if fname.endswith(('.so', '.dll', '.pyd')):
816 binary_file = True
816 binary_file = True
817 elif fname.endswith('<string>'):
817 elif fname.endswith('<string>'):
818 fname = 'Dynamically generated function. No source code available.'
818 fname = 'Dynamically generated function. No source code available.'
819 out['file'] = compress_user(fname)
819 out['file'] = compress_user(fname)
820
820
821 # Original source code for a callable, class or property.
821 # Original source code for a callable, class or property.
822 if detail_level:
822 if detail_level:
823 # Flush the source cache because inspect can return out-of-date
823 # Flush the source cache because inspect can return out-of-date
824 # source
824 # source
825 linecache.checkcache()
825 linecache.checkcache()
826 try:
826 try:
827 if isinstance(obj, property) or not binary_file:
827 if isinstance(obj, property) or not binary_file:
828 src = getsource(obj, oname)
828 src = getsource(obj, oname)
829 if src is not None:
829 if src is not None:
830 src = src.rstrip()
830 src = src.rstrip()
831 out['source'] = src
831 out['source'] = src
832
832
833 except Exception:
833 except Exception:
834 pass
834 pass
835
835
836 # Add docstring only if no source is to be shown (avoid repetitions).
836 # Add docstring only if no source is to be shown (avoid repetitions).
837 if ds and not self._source_contains_docstring(out.get('source'), ds):
837 if ds and not self._source_contains_docstring(out.get('source'), ds):
838 out['docstring'] = ds
838 out['docstring'] = ds
839
839
840 # Constructor docstring for classes
840 # Constructor docstring for classes
841 if inspect.isclass(obj):
841 if inspect.isclass(obj):
842 out['isclass'] = True
842 out['isclass'] = True
843
843
844 # get the init signature:
844 # get the init signature:
845 try:
845 try:
846 init_def = self._getdef(obj, oname)
846 init_def = self._getdef(obj, oname)
847 except AttributeError:
847 except AttributeError:
848 init_def = None
848 init_def = None
849
849
850 # get the __init__ docstring
850 # get the __init__ docstring
851 try:
851 try:
852 obj_init = obj.__init__
852 obj_init = obj.__init__
853 except AttributeError:
853 except AttributeError:
854 init_ds = None
854 init_ds = None
855 else:
855 else:
856 if init_def is None:
856 if init_def is None:
857 # Get signature from init if top-level sig failed.
857 # Get signature from init if top-level sig failed.
858 # Can happen for built-in types (list, etc.).
858 # Can happen for built-in types (list, etc.).
859 try:
859 try:
860 init_def = self._getdef(obj_init, oname)
860 init_def = self._getdef(obj_init, oname)
861 except AttributeError:
861 except AttributeError:
862 pass
862 pass
863 init_ds = getdoc(obj_init)
863 init_ds = getdoc(obj_init)
864 # Skip Python's auto-generated docstrings
864 # Skip Python's auto-generated docstrings
865 if init_ds == _object_init_docstring:
865 if init_ds == _object_init_docstring:
866 init_ds = None
866 init_ds = None
867
867
868 if init_def:
868 if init_def:
869 out['init_definition'] = init_def
869 out['init_definition'] = init_def
870
870
871 if init_ds:
871 if init_ds:
872 out['init_docstring'] = init_ds
872 out['init_docstring'] = init_ds
873
873
874 names = [sub.__name__ for sub in type.__subclasses__(obj)]
874 names = [sub.__name__ for sub in type.__subclasses__(obj)]
875 if len(names) < 10:
875 if len(names) < 10:
876 all_names = ', '.join(names)
876 all_names = ', '.join(names)
877 else:
877 else:
878 all_names = ', '.join(names[:10]+['...'])
878 all_names = ', '.join(names[:10]+['...'])
879 out['subclasses'] = all_names
879 out['subclasses'] = all_names
880 # and class docstring for instances:
880 # and class docstring for instances:
881 else:
881 else:
882 # reconstruct the function definition and print it:
882 # reconstruct the function definition and print it:
883 defln = self._getdef(obj, oname)
883 defln = self._getdef(obj, oname)
884 if defln:
884 if defln:
885 out['definition'] = defln
885 out['definition'] = defln
886
886
887 # First, check whether the instance docstring is identical to the
887 # First, check whether the instance docstring is identical to the
888 # class one, and print it separately if they don't coincide. In
888 # class one, and print it separately if they don't coincide. In
889 # most cases they will, but it's nice to print all the info for
889 # most cases they will, but it's nice to print all the info for
890 # objects which use instance-customized docstrings.
890 # objects which use instance-customized docstrings.
891 if ds:
891 if ds:
892 try:
892 try:
893 cls = getattr(obj,'__class__')
893 cls = getattr(obj,'__class__')
894 except:
894 except:
895 class_ds = None
895 class_ds = None
896 else:
896 else:
897 class_ds = getdoc(cls)
897 class_ds = getdoc(cls)
898 # Skip Python's auto-generated docstrings
898 # Skip Python's auto-generated docstrings
899 if class_ds in _builtin_type_docstrings:
899 if class_ds in _builtin_type_docstrings:
900 class_ds = None
900 class_ds = None
901 if class_ds and ds != class_ds:
901 if class_ds and ds != class_ds:
902 out['class_docstring'] = class_ds
902 out['class_docstring'] = class_ds
903
903
904 # Next, try to show constructor docstrings
904 # Next, try to show constructor docstrings
905 try:
905 try:
906 init_ds = getdoc(obj.__init__)
906 init_ds = getdoc(obj.__init__)
907 # Skip Python's auto-generated docstrings
907 # Skip Python's auto-generated docstrings
908 if init_ds == _object_init_docstring:
908 if init_ds == _object_init_docstring:
909 init_ds = None
909 init_ds = None
910 except AttributeError:
910 except AttributeError:
911 init_ds = None
911 init_ds = None
912 if init_ds:
912 if init_ds:
913 out['init_docstring'] = init_ds
913 out['init_docstring'] = init_ds
914
914
915 # Call form docstring for callable instances
915 # Call form docstring for callable instances
916 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
916 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
917 call_def = self._getdef(obj.__call__, oname)
917 call_def = self._getdef(obj.__call__, oname)
918 if call_def and (call_def != out.get('definition')):
918 if call_def and (call_def != out.get('definition')):
919 # it may never be the case that call def and definition differ,
919 # it may never be the case that call def and definition differ,
920 # but don't include the same signature twice
920 # but don't include the same signature twice
921 out['call_def'] = call_def
921 out['call_def'] = call_def
922 call_ds = getdoc(obj.__call__)
922 call_ds = getdoc(obj.__call__)
923 # Skip Python's auto-generated docstrings
923 # Skip Python's auto-generated docstrings
924 if call_ds == _func_call_docstring:
924 if call_ds == _func_call_docstring:
925 call_ds = None
925 call_ds = None
926 if call_ds:
926 if call_ds:
927 out['call_docstring'] = call_ds
927 out['call_docstring'] = call_ds
928
928
929 return object_info(**out)
929 return object_info(**out)
930
930
931 @staticmethod
931 @staticmethod
932 def _source_contains_docstring(src, doc):
932 def _source_contains_docstring(src, doc):
933 """
933 """
934 Check whether the source *src* contains the docstring *doc*.
934 Check whether the source *src* contains the docstring *doc*.
935
935
936 This is is helper function to skip displaying the docstring if the
936 This is is helper function to skip displaying the docstring if the
937 source already contains it, avoiding repetition of information.
937 source already contains it, avoiding repetition of information.
938 """
938 """
939 try:
939 try:
940 def_node, = ast.parse(dedent(src)).body
940 def_node, = ast.parse(dedent(src)).body
941 return ast.get_docstring(def_node) == doc
941 return ast.get_docstring(def_node) == doc
942 except Exception:
942 except Exception:
943 # The source can become invalid or even non-existent (because it
943 # The source can become invalid or even non-existent (because it
944 # is re-fetched from the source file) so the above code fail in
944 # is re-fetched from the source file) so the above code fail in
945 # arbitrary ways.
945 # arbitrary ways.
946 return False
946 return False
947
947
948 def psearch(self,pattern,ns_table,ns_search=[],
948 def psearch(self,pattern,ns_table,ns_search=[],
949 ignore_case=False,show_all=False, *, list_types=False):
949 ignore_case=False,show_all=False, *, list_types=False):
950 """Search namespaces with wildcards for objects.
950 """Search namespaces with wildcards for objects.
951
951
952 Arguments:
952 Arguments:
953
953
954 - pattern: string containing shell-like wildcards to use in namespace
954 - pattern: string containing shell-like wildcards to use in namespace
955 searches and optionally a type specification to narrow the search to
955 searches and optionally a type specification to narrow the search to
956 objects of that type.
956 objects of that type.
957
957
958 - ns_table: dict of name->namespaces for search.
958 - ns_table: dict of name->namespaces for search.
959
959
960 Optional arguments:
960 Optional arguments:
961
961
962 - ns_search: list of namespace names to include in search.
962 - ns_search: list of namespace names to include in search.
963
963
964 - ignore_case(False): make the search case-insensitive.
964 - ignore_case(False): make the search case-insensitive.
965
965
966 - show_all(False): show all names, including those starting with
966 - show_all(False): show all names, including those starting with
967 underscores.
967 underscores.
968
968
969 - list_types(False): list all available object types for object matching.
969 - list_types(False): list all available object types for object matching.
970 """
970 """
971 #print 'ps pattern:<%r>' % pattern # dbg
971 #print 'ps pattern:<%r>' % pattern # dbg
972
972
973 # defaults
973 # defaults
974 type_pattern = 'all'
974 type_pattern = 'all'
975 filter = ''
975 filter = ''
976
976
977 # list all object types
977 # list all object types
978 if list_types:
978 if list_types:
979 page.page('\n'.join(sorted(typestr2type)))
979 page.page('\n'.join(sorted(typestr2type)))
980 return
980 return
981
981
982 cmds = pattern.split()
982 cmds = pattern.split()
983 len_cmds = len(cmds)
983 len_cmds = len(cmds)
984 if len_cmds == 1:
984 if len_cmds == 1:
985 # Only filter pattern given
985 # Only filter pattern given
986 filter = cmds[0]
986 filter = cmds[0]
987 elif len_cmds == 2:
987 elif len_cmds == 2:
988 # Both filter and type specified
988 # Both filter and type specified
989 filter,type_pattern = cmds
989 filter,type_pattern = cmds
990 else:
990 else:
991 raise ValueError('invalid argument string for psearch: <%s>' %
991 raise ValueError('invalid argument string for psearch: <%s>' %
992 pattern)
992 pattern)
993
993
994 # filter search namespaces
994 # filter search namespaces
995 for name in ns_search:
995 for name in ns_search:
996 if name not in ns_table:
996 if name not in ns_table:
997 raise ValueError('invalid namespace <%s>. Valid names: %s' %
997 raise ValueError('invalid namespace <%s>. Valid names: %s' %
998 (name,ns_table.keys()))
998 (name,ns_table.keys()))
999
999
1000 #print 'type_pattern:',type_pattern # dbg
1000 #print 'type_pattern:',type_pattern # dbg
1001 search_result, namespaces_seen = set(), set()
1001 search_result, namespaces_seen = set(), set()
1002 for ns_name in ns_search:
1002 for ns_name in ns_search:
1003 ns = ns_table[ns_name]
1003 ns = ns_table[ns_name]
1004 # Normally, locals and globals are the same, so we just check one.
1004 # Normally, locals and globals are the same, so we just check one.
1005 if id(ns) in namespaces_seen:
1005 if id(ns) in namespaces_seen:
1006 continue
1006 continue
1007 namespaces_seen.add(id(ns))
1007 namespaces_seen.add(id(ns))
1008 tmp_res = list_namespace(ns, type_pattern, filter,
1008 tmp_res = list_namespace(ns, type_pattern, filter,
1009 ignore_case=ignore_case, show_all=show_all)
1009 ignore_case=ignore_case, show_all=show_all)
1010 search_result.update(tmp_res)
1010 search_result.update(tmp_res)
1011
1011
1012 page.page('\n'.join(sorted(search_result)))
1012 page.page('\n'.join(sorted(search_result)))
1013
1013
1014
1014
1015 def _render_signature(obj_signature, obj_name) -> str:
1015 def _render_signature(obj_signature, obj_name) -> str:
1016 """
1016 """
1017 This was mostly taken from inspect.Signature.__str__.
1017 This was mostly taken from inspect.Signature.__str__.
1018 Look there for the comments.
1018 Look there for the comments.
1019 The only change is to add linebreaks when this gets too long.
1019 The only change is to add linebreaks when this gets too long.
1020 """
1020 """
1021 result = []
1021 result = []
1022 pos_only = False
1022 pos_only = False
1023 kw_only = True
1023 kw_only = True
1024 for param in obj_signature.parameters.values():
1024 for param in obj_signature.parameters.values():
1025 if param.kind == inspect._POSITIONAL_ONLY:
1025 if param.kind == inspect._POSITIONAL_ONLY:
1026 pos_only = True
1026 pos_only = True
1027 elif pos_only:
1027 elif pos_only:
1028 result.append('/')
1028 result.append('/')
1029 pos_only = False
1029 pos_only = False
1030
1030
1031 if param.kind == inspect._VAR_POSITIONAL:
1031 if param.kind == inspect._VAR_POSITIONAL:
1032 kw_only = False
1032 kw_only = False
1033 elif param.kind == inspect._KEYWORD_ONLY and kw_only:
1033 elif param.kind == inspect._KEYWORD_ONLY and kw_only:
1034 result.append('*')
1034 result.append('*')
1035 kw_only = False
1035 kw_only = False
1036
1036
1037 result.append(str(param))
1037 result.append(str(param))
1038
1038
1039 if pos_only:
1039 if pos_only:
1040 result.append('/')
1040 result.append('/')
1041
1041
1042 # add up name, parameters, braces (2), and commas
1042 # add up name, parameters, braces (2), and commas
1043 if len(obj_name) + sum(len(r) + 2 for r in result) > 75:
1043 if len(obj_name) + sum(len(r) + 2 for r in result) > 75:
1044 # This doesn’t fit behind “Signature: ” in an inspect window.
1044 # This doesn’t fit behind “Signature: ” in an inspect window.
1045 rendered = '{}(\n{})'.format(obj_name, ''.join(
1045 rendered = '{}(\n{})'.format(obj_name, ''.join(
1046 ' {},\n'.format(r) for r in result)
1046 ' {},\n'.format(r) for r in result)
1047 )
1047 )
1048 else:
1048 else:
1049 rendered = '{}({})'.format(obj_name, ', '.join(result))
1049 rendered = '{}({})'.format(obj_name, ', '.join(result))
1050
1050
1051 if obj_signature.return_annotation is not inspect._empty:
1051 if obj_signature.return_annotation is not inspect._empty:
1052 anno = inspect.formatannotation(obj_signature.return_annotation)
1052 anno = inspect.formatannotation(obj_signature.return_annotation)
1053 rendered += ' -> {}'.format(anno)
1053 rendered += ' -> {}'.format(anno)
1054
1054
1055 return rendered
1055 return rendered
General Comments 0
You need to be logged in to leave comments. Login now