##// END OF EJS Templates
Remove unused imports from IPython.core
Thomas Kluyver -
Show More
@@ -1,185 +1,184 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A class for managing IPython extensions.
2 """A class for managing IPython extensions.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 """
7 """
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010-2011 The IPython Development Team
10 # Copyright (C) 2010-2011 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 import os
20 import os
21 from shutil import copyfile
21 from shutil import copyfile
22 import sys
22 import sys
23
23
24 from IPython.core.error import UsageError
25 from IPython.config.configurable import Configurable
24 from IPython.config.configurable import Configurable
26 from IPython.utils.traitlets import Instance
25 from IPython.utils.traitlets import Instance
27 from IPython.utils.py3compat import PY3
26 from IPython.utils.py3compat import PY3
28 if PY3:
27 if PY3:
29 from imp import reload
28 from imp import reload
30
29
31 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
32 # Main class
31 # Main class
33 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
34
33
35 class ExtensionManager(Configurable):
34 class ExtensionManager(Configurable):
36 """A class to manage IPython extensions.
35 """A class to manage IPython extensions.
37
36
38 An IPython extension is an importable Python module that has
37 An IPython extension is an importable Python module that has
39 a function with the signature::
38 a function with the signature::
40
39
41 def load_ipython_extension(ipython):
40 def load_ipython_extension(ipython):
42 # Do things with ipython
41 # Do things with ipython
43
42
44 This function is called after your extension is imported and the
43 This function is called after your extension is imported and the
45 currently active :class:`InteractiveShell` instance is passed as
44 currently active :class:`InteractiveShell` instance is passed as
46 the only argument. You can do anything you want with IPython at
45 the only argument. You can do anything you want with IPython at
47 that point, including defining new magic and aliases, adding new
46 that point, including defining new magic and aliases, adding new
48 components, etc.
47 components, etc.
49
48
50 You can also optionally define an :func:`unload_ipython_extension(ipython)`
49 You can also optionally define an :func:`unload_ipython_extension(ipython)`
51 function, which will be called if the user unloads or reloads the extension.
50 function, which will be called if the user unloads or reloads the extension.
52 The extension manager will only call :func:`load_ipython_extension` again
51 The extension manager will only call :func:`load_ipython_extension` again
53 if the extension is reloaded.
52 if the extension is reloaded.
54
53
55 You can put your extension modules anywhere you want, as long as
54 You can put your extension modules anywhere you want, as long as
56 they can be imported by Python's standard import mechanism. However,
55 they can be imported by Python's standard import mechanism. However,
57 to make it easy to write extensions, you can also put your extensions
56 to make it easy to write extensions, you can also put your extensions
58 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
57 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
59 is added to ``sys.path`` automatically.
58 is added to ``sys.path`` automatically.
60 """
59 """
61
60
62 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
61 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
63
62
64 def __init__(self, shell=None, **kwargs):
63 def __init__(self, shell=None, **kwargs):
65 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
64 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
66 self.shell.on_trait_change(
65 self.shell.on_trait_change(
67 self._on_ipython_dir_changed, 'ipython_dir'
66 self._on_ipython_dir_changed, 'ipython_dir'
68 )
67 )
69 self.loaded = set()
68 self.loaded = set()
70
69
71 def __del__(self):
70 def __del__(self):
72 self.shell.on_trait_change(
71 self.shell.on_trait_change(
73 self._on_ipython_dir_changed, 'ipython_dir', remove=True
72 self._on_ipython_dir_changed, 'ipython_dir', remove=True
74 )
73 )
75
74
76 @property
75 @property
77 def ipython_extension_dir(self):
76 def ipython_extension_dir(self):
78 return os.path.join(self.shell.ipython_dir, u'extensions')
77 return os.path.join(self.shell.ipython_dir, u'extensions')
79
78
80 def _on_ipython_dir_changed(self):
79 def _on_ipython_dir_changed(self):
81 if not os.path.isdir(self.ipython_extension_dir):
80 if not os.path.isdir(self.ipython_extension_dir):
82 os.makedirs(self.ipython_extension_dir, mode = 0o777)
81 os.makedirs(self.ipython_extension_dir, mode = 0o777)
83
82
84 def load_extension(self, module_str):
83 def load_extension(self, module_str):
85 """Load an IPython extension by its module name.
84 """Load an IPython extension by its module name.
86
85
87 Returns the string "already loaded" if the extension is already loaded,
86 Returns the string "already loaded" if the extension is already loaded,
88 "no load function" if the module doesn't have a load_ipython_extension
87 "no load function" if the module doesn't have a load_ipython_extension
89 function, or None if it succeeded.
88 function, or None if it succeeded.
90 """
89 """
91 if module_str in self.loaded:
90 if module_str in self.loaded:
92 return "already loaded"
91 return "already loaded"
93
92
94 from IPython.utils.syspathcontext import prepended_to_syspath
93 from IPython.utils.syspathcontext import prepended_to_syspath
95
94
96 with self.shell.builtin_trap:
95 with self.shell.builtin_trap:
97 if module_str not in sys.modules:
96 if module_str not in sys.modules:
98 with prepended_to_syspath(self.ipython_extension_dir):
97 with prepended_to_syspath(self.ipython_extension_dir):
99 __import__(module_str)
98 __import__(module_str)
100 mod = sys.modules[module_str]
99 mod = sys.modules[module_str]
101 if self._call_load_ipython_extension(mod):
100 if self._call_load_ipython_extension(mod):
102 self.loaded.add(module_str)
101 self.loaded.add(module_str)
103 else:
102 else:
104 return "no load function"
103 return "no load function"
105
104
106 def unload_extension(self, module_str):
105 def unload_extension(self, module_str):
107 """Unload an IPython extension by its module name.
106 """Unload an IPython extension by its module name.
108
107
109 This function looks up the extension's name in ``sys.modules`` and
108 This function looks up the extension's name in ``sys.modules`` and
110 simply calls ``mod.unload_ipython_extension(self)``.
109 simply calls ``mod.unload_ipython_extension(self)``.
111
110
112 Returns the string "no unload function" if the extension doesn't define
111 Returns the string "no unload function" if the extension doesn't define
113 a function to unload itself, "not loaded" if the extension isn't loaded,
112 a function to unload itself, "not loaded" if the extension isn't loaded,
114 otherwise None.
113 otherwise None.
115 """
114 """
116 if module_str not in self.loaded:
115 if module_str not in self.loaded:
117 return "not loaded"
116 return "not loaded"
118
117
119 if module_str in sys.modules:
118 if module_str in sys.modules:
120 mod = sys.modules[module_str]
119 mod = sys.modules[module_str]
121 if self._call_unload_ipython_extension(mod):
120 if self._call_unload_ipython_extension(mod):
122 self.loaded.discard(module_str)
121 self.loaded.discard(module_str)
123 else:
122 else:
124 return "no unload function"
123 return "no unload function"
125
124
126 def reload_extension(self, module_str):
125 def reload_extension(self, module_str):
127 """Reload an IPython extension by calling reload.
126 """Reload an IPython extension by calling reload.
128
127
129 If the module has not been loaded before,
128 If the module has not been loaded before,
130 :meth:`InteractiveShell.load_extension` is called. Otherwise
129 :meth:`InteractiveShell.load_extension` is called. Otherwise
131 :func:`reload` is called and then the :func:`load_ipython_extension`
130 :func:`reload` is called and then the :func:`load_ipython_extension`
132 function of the module, if it exists is called.
131 function of the module, if it exists is called.
133 """
132 """
134 from IPython.utils.syspathcontext import prepended_to_syspath
133 from IPython.utils.syspathcontext import prepended_to_syspath
135
134
136 if (module_str in self.loaded) and (module_str in sys.modules):
135 if (module_str in self.loaded) and (module_str in sys.modules):
137 self.unload_extension(module_str)
136 self.unload_extension(module_str)
138 mod = sys.modules[module_str]
137 mod = sys.modules[module_str]
139 with prepended_to_syspath(self.ipython_extension_dir):
138 with prepended_to_syspath(self.ipython_extension_dir):
140 reload(mod)
139 reload(mod)
141 if self._call_load_ipython_extension(mod):
140 if self._call_load_ipython_extension(mod):
142 self.loaded.add(module_str)
141 self.loaded.add(module_str)
143 else:
142 else:
144 self.load_extension(module_str)
143 self.load_extension(module_str)
145
144
146 def _call_load_ipython_extension(self, mod):
145 def _call_load_ipython_extension(self, mod):
147 if hasattr(mod, 'load_ipython_extension'):
146 if hasattr(mod, 'load_ipython_extension'):
148 mod.load_ipython_extension(self.shell)
147 mod.load_ipython_extension(self.shell)
149 return True
148 return True
150
149
151 def _call_unload_ipython_extension(self, mod):
150 def _call_unload_ipython_extension(self, mod):
152 if hasattr(mod, 'unload_ipython_extension'):
151 if hasattr(mod, 'unload_ipython_extension'):
153 mod.unload_ipython_extension(self.shell)
152 mod.unload_ipython_extension(self.shell)
154 return True
153 return True
155
154
156 def install_extension(self, url, filename=None):
155 def install_extension(self, url, filename=None):
157 """Download and install an IPython extension.
156 """Download and install an IPython extension.
158
157
159 If filename is given, the file will be so named (inside the extension
158 If filename is given, the file will be so named (inside the extension
160 directory). Otherwise, the name from the URL will be used. The file must
159 directory). Otherwise, the name from the URL will be used. The file must
161 have a .py or .zip extension; otherwise, a ValueError will be raised.
160 have a .py or .zip extension; otherwise, a ValueError will be raised.
162
161
163 Returns the full path to the installed file.
162 Returns the full path to the installed file.
164 """
163 """
165 # Ensure the extension directory exists
164 # Ensure the extension directory exists
166 if not os.path.isdir(self.ipython_extension_dir):
165 if not os.path.isdir(self.ipython_extension_dir):
167 os.makedirs(self.ipython_extension_dir, mode = 0o777)
166 os.makedirs(self.ipython_extension_dir, mode = 0o777)
168
167
169 if os.path.isfile(url):
168 if os.path.isfile(url):
170 src_filename = os.path.basename(url)
169 src_filename = os.path.basename(url)
171 copy = copyfile
170 copy = copyfile
172 else:
171 else:
173 from urllib import urlretrieve # Deferred imports
172 from urllib import urlretrieve # Deferred imports
174 from urlparse import urlparse
173 from urlparse import urlparse
175 src_filename = urlparse(url).path.split('/')[-1]
174 src_filename = urlparse(url).path.split('/')[-1]
176 copy = urlretrieve
175 copy = urlretrieve
177
176
178 if filename is None:
177 if filename is None:
179 filename = src_filename
178 filename = src_filename
180 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
179 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
181 raise ValueError("The file must have a .py or .zip extension", filename)
180 raise ValueError("The file must have a .py or .zip extension", filename)
182
181
183 filename = os.path.join(self.ipython_extension_dir, filename)
182 filename = os.path.join(self.ipython_extension_dir, filename)
184 copy(url, filename)
183 copy(url, filename)
185 return filename
184 return filename
@@ -1,30 +1,24 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Simple function to call to get the current InteractiveShell instance
2 """Simple function to call to get the current InteractiveShell instance
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2013 The IPython Development Team
6 # Copyright (C) 2013 The IPython Development Team
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 import warnings
17
18 #-----------------------------------------------------------------------------
19 # Classes and functions
13 # Classes and functions
20 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
21
15
22
16
23 def get_ipython():
17 def get_ipython():
24 """Get the global InteractiveShell instance.
18 """Get the global InteractiveShell instance.
25
19
26 Returns None if no InteractiveShell instance is registered.
20 Returns None if no InteractiveShell instance is registered.
27 """
21 """
28 from IPython.core.interactiveshell import InteractiveShell
22 from IPython.core.interactiveshell import InteractiveShell
29 if InteractiveShell.initialized():
23 if InteractiveShell.initialized():
30 return InteractiveShell.instance()
24 return InteractiveShell.instance()
@@ -1,658 +1,657 b''
1 """Analysis of text input into executable blocks.
1 """Analysis of text input into executable blocks.
2
2
3 The main class in this module, :class:`InputSplitter`, is designed to break
3 The main class in this module, :class:`InputSplitter`, is designed to break
4 input from either interactive, line-by-line environments or block-based ones,
4 input from either interactive, line-by-line environments or block-based ones,
5 into standalone blocks that can be executed by Python as 'single' statements
5 into standalone blocks that can be executed by Python as 'single' statements
6 (thus triggering sys.displayhook).
6 (thus triggering sys.displayhook).
7
7
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
9 with full support for the extended IPython syntax (magics, system calls, etc).
9 with full support for the extended IPython syntax (magics, system calls, etc).
10
10
11 For more details, see the class docstring below.
11 For more details, see the class docstring below.
12
12
13 Syntax Transformations
13 Syntax Transformations
14 ----------------------
14 ----------------------
15
15
16 One of the main jobs of the code in this file is to apply all syntax
16 One of the main jobs of the code in this file is to apply all syntax
17 transformations that make up 'the IPython language', i.e. magics, shell
17 transformations that make up 'the IPython language', i.e. magics, shell
18 escapes, etc. All transformations should be implemented as *fully stateless*
18 escapes, etc. All transformations should be implemented as *fully stateless*
19 entities, that simply take one line as their input and return a line.
19 entities, that simply take one line as their input and return a line.
20 Internally for implementation purposes they may be a normal function or a
20 Internally for implementation purposes they may be a normal function or a
21 callable object, but the only input they receive will be a single line and they
21 callable object, but the only input they receive will be a single line and they
22 should only return a line, without holding any data-dependent state between
22 should only return a line, without holding any data-dependent state between
23 calls.
23 calls.
24
24
25 As an example, the EscapedTransformer is a class so we can more clearly group
25 As an example, the EscapedTransformer is a class so we can more clearly group
26 together the functionality of dispatching to individual functions based on the
26 together the functionality of dispatching to individual functions based on the
27 starting escape character, but the only method for public use is its call
27 starting escape character, but the only method for public use is its call
28 method.
28 method.
29
29
30
30
31 ToDo
31 ToDo
32 ----
32 ----
33
33
34 - Should we make push() actually raise an exception once push_accepts_more()
34 - Should we make push() actually raise an exception once push_accepts_more()
35 returns False?
35 returns False?
36
36
37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
38 at least just attributes of a class so not really very exposed.
38 at least just attributes of a class so not really very exposed.
39
39
40 - Think about the best way to support dynamic things: automagic, autocall,
40 - Think about the best way to support dynamic things: automagic, autocall,
41 macros, etc.
41 macros, etc.
42
42
43 - Think of a better heuristic for the application of the transforms in
43 - Think of a better heuristic for the application of the transforms in
44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
45 track indentation change events (indent, dedent, nothing) and apply them only
45 track indentation change events (indent, dedent, nothing) and apply them only
46 if the indentation went up, but not otherwise.
46 if the indentation went up, but not otherwise.
47
47
48 - Think of the cleanest way for supporting user-specified transformations (the
48 - Think of the cleanest way for supporting user-specified transformations (the
49 user prefilters we had before).
49 user prefilters we had before).
50
50
51 Authors
51 Authors
52 -------
52 -------
53
53
54 * Fernando Perez
54 * Fernando Perez
55 * Brian Granger
55 * Brian Granger
56 """
56 """
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Copyright (C) 2010 The IPython Development Team
58 # Copyright (C) 2010 The IPython Development Team
59 #
59 #
60 # Distributed under the terms of the BSD License. The full license is in
60 # Distributed under the terms of the BSD License. The full license is in
61 # the file COPYING, distributed as part of this software.
61 # the file COPYING, distributed as part of this software.
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63
63
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 # Imports
65 # Imports
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67 # stdlib
67 # stdlib
68 import ast
68 import ast
69 import codeop
69 import codeop
70 import re
70 import re
71 import sys
71 import sys
72
72
73 # IPython modules
73 # IPython modules
74 from IPython.core.splitinput import split_user_input, LineInfo
75 from IPython.utils.py3compat import cast_unicode
74 from IPython.utils.py3compat import cast_unicode
76 from IPython.core.inputtransformer import (leading_indent,
75 from IPython.core.inputtransformer import (leading_indent,
77 classic_prompt,
76 classic_prompt,
78 ipy_prompt,
77 ipy_prompt,
79 cellmagic,
78 cellmagic,
80 assemble_logical_lines,
79 assemble_logical_lines,
81 help_end,
80 help_end,
82 escaped_commands,
81 escaped_commands,
83 assign_from_magic,
82 assign_from_magic,
84 assign_from_system,
83 assign_from_system,
85 assemble_python_lines,
84 assemble_python_lines,
86 )
85 )
87
86
88 # Temporary!
87 # These are available in this module for backwards compatibility.
89 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
88 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
90 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
89 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
91 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
90 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
92
91
93 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
94 # Utilities
93 # Utilities
95 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
96
95
97 # FIXME: These are general-purpose utilities that later can be moved to the
96 # FIXME: These are general-purpose utilities that later can be moved to the
98 # general ward. Kept here for now because we're being very strict about test
97 # general ward. Kept here for now because we're being very strict about test
99 # coverage with this code, and this lets us ensure that we keep 100% coverage
98 # coverage with this code, and this lets us ensure that we keep 100% coverage
100 # while developing.
99 # while developing.
101
100
102 # compiled regexps for autoindent management
101 # compiled regexps for autoindent management
103 dedent_re = re.compile('|'.join([
102 dedent_re = re.compile('|'.join([
104 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
103 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
105 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
104 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
106 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
105 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
107 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
106 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
108 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
107 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
109 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
108 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
110 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
109 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
111 ]))
110 ]))
112 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
111 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
113
112
114 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
113 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
115 # before pure comments
114 # before pure comments
116 comment_line_re = re.compile('^\s*\#')
115 comment_line_re = re.compile('^\s*\#')
117
116
118
117
119 def num_ini_spaces(s):
118 def num_ini_spaces(s):
120 """Return the number of initial spaces in a string.
119 """Return the number of initial spaces in a string.
121
120
122 Note that tabs are counted as a single space. For now, we do *not* support
121 Note that tabs are counted as a single space. For now, we do *not* support
123 mixing of tabs and spaces in the user's input.
122 mixing of tabs and spaces in the user's input.
124
123
125 Parameters
124 Parameters
126 ----------
125 ----------
127 s : string
126 s : string
128
127
129 Returns
128 Returns
130 -------
129 -------
131 n : int
130 n : int
132 """
131 """
133
132
134 ini_spaces = ini_spaces_re.match(s)
133 ini_spaces = ini_spaces_re.match(s)
135 if ini_spaces:
134 if ini_spaces:
136 return ini_spaces.end()
135 return ini_spaces.end()
137 else:
136 else:
138 return 0
137 return 0
139
138
140 def last_blank(src):
139 def last_blank(src):
141 """Determine if the input source ends in a blank.
140 """Determine if the input source ends in a blank.
142
141
143 A blank is either a newline or a line consisting of whitespace.
142 A blank is either a newline or a line consisting of whitespace.
144
143
145 Parameters
144 Parameters
146 ----------
145 ----------
147 src : string
146 src : string
148 A single or multiline string.
147 A single or multiline string.
149 """
148 """
150 if not src: return False
149 if not src: return False
151 ll = src.splitlines()[-1]
150 ll = src.splitlines()[-1]
152 return (ll == '') or ll.isspace()
151 return (ll == '') or ll.isspace()
153
152
154
153
155 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
154 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
156 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
155 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
157
156
158 def last_two_blanks(src):
157 def last_two_blanks(src):
159 """Determine if the input source ends in two blanks.
158 """Determine if the input source ends in two blanks.
160
159
161 A blank is either a newline or a line consisting of whitespace.
160 A blank is either a newline or a line consisting of whitespace.
162
161
163 Parameters
162 Parameters
164 ----------
163 ----------
165 src : string
164 src : string
166 A single or multiline string.
165 A single or multiline string.
167 """
166 """
168 if not src: return False
167 if not src: return False
169 # The logic here is tricky: I couldn't get a regexp to work and pass all
168 # The logic here is tricky: I couldn't get a regexp to work and pass all
170 # the tests, so I took a different approach: split the source by lines,
169 # the tests, so I took a different approach: split the source by lines,
171 # grab the last two and prepend '###\n' as a stand-in for whatever was in
170 # grab the last two and prepend '###\n' as a stand-in for whatever was in
172 # the body before the last two lines. Then, with that structure, it's
171 # the body before the last two lines. Then, with that structure, it's
173 # possible to analyze with two regexps. Not the most elegant solution, but
172 # possible to analyze with two regexps. Not the most elegant solution, but
174 # it works. If anyone tries to change this logic, make sure to validate
173 # it works. If anyone tries to change this logic, make sure to validate
175 # the whole test suite first!
174 # the whole test suite first!
176 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
175 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
177 return (bool(last_two_blanks_re.match(new_src)) or
176 return (bool(last_two_blanks_re.match(new_src)) or
178 bool(last_two_blanks_re2.match(new_src)) )
177 bool(last_two_blanks_re2.match(new_src)) )
179
178
180
179
181 def remove_comments(src):
180 def remove_comments(src):
182 """Remove all comments from input source.
181 """Remove all comments from input source.
183
182
184 Note: comments are NOT recognized inside of strings!
183 Note: comments are NOT recognized inside of strings!
185
184
186 Parameters
185 Parameters
187 ----------
186 ----------
188 src : string
187 src : string
189 A single or multiline input string.
188 A single or multiline input string.
190
189
191 Returns
190 Returns
192 -------
191 -------
193 String with all Python comments removed.
192 String with all Python comments removed.
194 """
193 """
195
194
196 return re.sub('#.*', '', src)
195 return re.sub('#.*', '', src)
197
196
198
197
199 def get_input_encoding():
198 def get_input_encoding():
200 """Return the default standard input encoding.
199 """Return the default standard input encoding.
201
200
202 If sys.stdin has no encoding, 'ascii' is returned."""
201 If sys.stdin has no encoding, 'ascii' is returned."""
203 # There are strange environments for which sys.stdin.encoding is None. We
202 # There are strange environments for which sys.stdin.encoding is None. We
204 # ensure that a valid encoding is returned.
203 # ensure that a valid encoding is returned.
205 encoding = getattr(sys.stdin, 'encoding', None)
204 encoding = getattr(sys.stdin, 'encoding', None)
206 if encoding is None:
205 if encoding is None:
207 encoding = 'ascii'
206 encoding = 'ascii'
208 return encoding
207 return encoding
209
208
210 #-----------------------------------------------------------------------------
209 #-----------------------------------------------------------------------------
211 # Classes and functions for normal Python syntax handling
210 # Classes and functions for normal Python syntax handling
212 #-----------------------------------------------------------------------------
211 #-----------------------------------------------------------------------------
213
212
214 class InputSplitter(object):
213 class InputSplitter(object):
215 """An object that can accumulate lines of Python source before execution.
214 """An object that can accumulate lines of Python source before execution.
216
215
217 This object is designed to be fed python source line-by-line, using
216 This object is designed to be fed python source line-by-line, using
218 :meth:`push`. It will return on each push whether the currently pushed
217 :meth:`push`. It will return on each push whether the currently pushed
219 code could be executed already. In addition, it provides a method called
218 code could be executed already. In addition, it provides a method called
220 :meth:`push_accepts_more` that can be used to query whether more input
219 :meth:`push_accepts_more` that can be used to query whether more input
221 can be pushed into a single interactive block.
220 can be pushed into a single interactive block.
222
221
223 This is a simple example of how an interactive terminal-based client can use
222 This is a simple example of how an interactive terminal-based client can use
224 this tool::
223 this tool::
225
224
226 isp = InputSplitter()
225 isp = InputSplitter()
227 while isp.push_accepts_more():
226 while isp.push_accepts_more():
228 indent = ' '*isp.indent_spaces
227 indent = ' '*isp.indent_spaces
229 prompt = '>>> ' + indent
228 prompt = '>>> ' + indent
230 line = indent + raw_input(prompt)
229 line = indent + raw_input(prompt)
231 isp.push(line)
230 isp.push(line)
232 print 'Input source was:\n', isp.source_reset(),
231 print 'Input source was:\n', isp.source_reset(),
233 """
232 """
234 # Number of spaces of indentation computed from input that has been pushed
233 # Number of spaces of indentation computed from input that has been pushed
235 # so far. This is the attributes callers should query to get the current
234 # so far. This is the attributes callers should query to get the current
236 # indentation level, in order to provide auto-indent facilities.
235 # indentation level, in order to provide auto-indent facilities.
237 indent_spaces = 0
236 indent_spaces = 0
238 # String, indicating the default input encoding. It is computed by default
237 # String, indicating the default input encoding. It is computed by default
239 # at initialization time via get_input_encoding(), but it can be reset by a
238 # at initialization time via get_input_encoding(), but it can be reset by a
240 # client with specific knowledge of the encoding.
239 # client with specific knowledge of the encoding.
241 encoding = ''
240 encoding = ''
242 # String where the current full source input is stored, properly encoded.
241 # String where the current full source input is stored, properly encoded.
243 # Reading this attribute is the normal way of querying the currently pushed
242 # Reading this attribute is the normal way of querying the currently pushed
244 # source code, that has been properly encoded.
243 # source code, that has been properly encoded.
245 source = ''
244 source = ''
246 # Code object corresponding to the current source. It is automatically
245 # Code object corresponding to the current source. It is automatically
247 # synced to the source, so it can be queried at any time to obtain the code
246 # synced to the source, so it can be queried at any time to obtain the code
248 # object; it will be None if the source doesn't compile to valid Python.
247 # object; it will be None if the source doesn't compile to valid Python.
249 code = None
248 code = None
250
249
251 # Private attributes
250 # Private attributes
252
251
253 # List with lines of input accumulated so far
252 # List with lines of input accumulated so far
254 _buffer = None
253 _buffer = None
255 # Command compiler
254 # Command compiler
256 _compile = None
255 _compile = None
257 # Mark when input has changed indentation all the way back to flush-left
256 # Mark when input has changed indentation all the way back to flush-left
258 _full_dedent = False
257 _full_dedent = False
259 # Boolean indicating whether the current block is complete
258 # Boolean indicating whether the current block is complete
260 _is_complete = None
259 _is_complete = None
261
260
262 def __init__(self):
261 def __init__(self):
263 """Create a new InputSplitter instance.
262 """Create a new InputSplitter instance.
264 """
263 """
265 self._buffer = []
264 self._buffer = []
266 self._compile = codeop.CommandCompiler()
265 self._compile = codeop.CommandCompiler()
267 self.encoding = get_input_encoding()
266 self.encoding = get_input_encoding()
268
267
269 def reset(self):
268 def reset(self):
270 """Reset the input buffer and associated state."""
269 """Reset the input buffer and associated state."""
271 self.indent_spaces = 0
270 self.indent_spaces = 0
272 self._buffer[:] = []
271 self._buffer[:] = []
273 self.source = ''
272 self.source = ''
274 self.code = None
273 self.code = None
275 self._is_complete = False
274 self._is_complete = False
276 self._full_dedent = False
275 self._full_dedent = False
277
276
278 def source_reset(self):
277 def source_reset(self):
279 """Return the input source and perform a full reset.
278 """Return the input source and perform a full reset.
280 """
279 """
281 out = self.source
280 out = self.source
282 self.reset()
281 self.reset()
283 return out
282 return out
284
283
285 def push(self, lines):
284 def push(self, lines):
286 """Push one or more lines of input.
285 """Push one or more lines of input.
287
286
288 This stores the given lines and returns a status code indicating
287 This stores the given lines and returns a status code indicating
289 whether the code forms a complete Python block or not.
288 whether the code forms a complete Python block or not.
290
289
291 Any exceptions generated in compilation are swallowed, but if an
290 Any exceptions generated in compilation are swallowed, but if an
292 exception was produced, the method returns True.
291 exception was produced, the method returns True.
293
292
294 Parameters
293 Parameters
295 ----------
294 ----------
296 lines : string
295 lines : string
297 One or more lines of Python input.
296 One or more lines of Python input.
298
297
299 Returns
298 Returns
300 -------
299 -------
301 is_complete : boolean
300 is_complete : boolean
302 True if the current input source (the result of the current input
301 True if the current input source (the result of the current input
303 plus prior inputs) forms a complete Python execution block. Note that
302 plus prior inputs) forms a complete Python execution block. Note that
304 this value is also stored as a private attribute (``_is_complete``), so it
303 this value is also stored as a private attribute (``_is_complete``), so it
305 can be queried at any time.
304 can be queried at any time.
306 """
305 """
307 self._store(lines)
306 self._store(lines)
308 source = self.source
307 source = self.source
309
308
310 # Before calling _compile(), reset the code object to None so that if an
309 # Before calling _compile(), reset the code object to None so that if an
311 # exception is raised in compilation, we don't mislead by having
310 # exception is raised in compilation, we don't mislead by having
312 # inconsistent code/source attributes.
311 # inconsistent code/source attributes.
313 self.code, self._is_complete = None, None
312 self.code, self._is_complete = None, None
314
313
315 # Honor termination lines properly
314 # Honor termination lines properly
316 if source.endswith('\\\n'):
315 if source.endswith('\\\n'):
317 return False
316 return False
318
317
319 self._update_indent(lines)
318 self._update_indent(lines)
320 try:
319 try:
321 self.code = self._compile(source, symbol="exec")
320 self.code = self._compile(source, symbol="exec")
322 # Invalid syntax can produce any of a number of different errors from
321 # Invalid syntax can produce any of a number of different errors from
323 # inside the compiler, so we have to catch them all. Syntax errors
322 # inside the compiler, so we have to catch them all. Syntax errors
324 # immediately produce a 'ready' block, so the invalid Python can be
323 # immediately produce a 'ready' block, so the invalid Python can be
325 # sent to the kernel for evaluation with possible ipython
324 # sent to the kernel for evaluation with possible ipython
326 # special-syntax conversion.
325 # special-syntax conversion.
327 except (SyntaxError, OverflowError, ValueError, TypeError,
326 except (SyntaxError, OverflowError, ValueError, TypeError,
328 MemoryError):
327 MemoryError):
329 self._is_complete = True
328 self._is_complete = True
330 else:
329 else:
331 # Compilation didn't produce any exceptions (though it may not have
330 # Compilation didn't produce any exceptions (though it may not have
332 # given a complete code object)
331 # given a complete code object)
333 self._is_complete = self.code is not None
332 self._is_complete = self.code is not None
334
333
335 return self._is_complete
334 return self._is_complete
336
335
337 def push_accepts_more(self):
336 def push_accepts_more(self):
338 """Return whether a block of interactive input can accept more input.
337 """Return whether a block of interactive input can accept more input.
339
338
340 This method is meant to be used by line-oriented frontends, who need to
339 This method is meant to be used by line-oriented frontends, who need to
341 guess whether a block is complete or not based solely on prior and
340 guess whether a block is complete or not based solely on prior and
342 current input lines. The InputSplitter considers it has a complete
341 current input lines. The InputSplitter considers it has a complete
343 interactive block and will not accept more input when either:
342 interactive block and will not accept more input when either:
344
343
345 * A SyntaxError is raised
344 * A SyntaxError is raised
346
345
347 * The code is complete and consists of a single line or a single
346 * The code is complete and consists of a single line or a single
348 non-compound statement
347 non-compound statement
349
348
350 * The code is complete and has a blank line at the end
349 * The code is complete and has a blank line at the end
351
350
352 If the current input produces a syntax error, this method immediately
351 If the current input produces a syntax error, this method immediately
353 returns False but does *not* raise the syntax error exception, as
352 returns False but does *not* raise the syntax error exception, as
354 typically clients will want to send invalid syntax to an execution
353 typically clients will want to send invalid syntax to an execution
355 backend which might convert the invalid syntax into valid Python via
354 backend which might convert the invalid syntax into valid Python via
356 one of the dynamic IPython mechanisms.
355 one of the dynamic IPython mechanisms.
357 """
356 """
358
357
359 # With incomplete input, unconditionally accept more
358 # With incomplete input, unconditionally accept more
360 # A syntax error also sets _is_complete to True - see push()
359 # A syntax error also sets _is_complete to True - see push()
361 if not self._is_complete:
360 if not self._is_complete:
362 #print("Not complete") # debug
361 #print("Not complete") # debug
363 return True
362 return True
364
363
365 # The user can make any (complete) input execute by leaving a blank line
364 # The user can make any (complete) input execute by leaving a blank line
366 last_line = self.source.splitlines()[-1]
365 last_line = self.source.splitlines()[-1]
367 if (not last_line) or last_line.isspace():
366 if (not last_line) or last_line.isspace():
368 #print("Blank line") # debug
367 #print("Blank line") # debug
369 return False
368 return False
370
369
371 # If there's just a single line or AST node, and we're flush left, as is
370 # If there's just a single line or AST node, and we're flush left, as is
372 # the case after a simple statement such as 'a=1', we want to execute it
371 # the case after a simple statement such as 'a=1', we want to execute it
373 # straight away.
372 # straight away.
374 if self.indent_spaces==0:
373 if self.indent_spaces==0:
375 if len(self.source.splitlines()) <= 1:
374 if len(self.source.splitlines()) <= 1:
376 return False
375 return False
377
376
378 try:
377 try:
379 code_ast = ast.parse(u''.join(self._buffer))
378 code_ast = ast.parse(u''.join(self._buffer))
380 except Exception:
379 except Exception:
381 #print("Can't parse AST") # debug
380 #print("Can't parse AST") # debug
382 return False
381 return False
383 else:
382 else:
384 if len(code_ast.body) == 1 and \
383 if len(code_ast.body) == 1 and \
385 not hasattr(code_ast.body[0], 'body'):
384 not hasattr(code_ast.body[0], 'body'):
386 #print("Simple statement") # debug
385 #print("Simple statement") # debug
387 return False
386 return False
388
387
389 # General fallback - accept more code
388 # General fallback - accept more code
390 return True
389 return True
391
390
392 #------------------------------------------------------------------------
391 #------------------------------------------------------------------------
393 # Private interface
392 # Private interface
394 #------------------------------------------------------------------------
393 #------------------------------------------------------------------------
395
394
396 def _find_indent(self, line):
395 def _find_indent(self, line):
397 """Compute the new indentation level for a single line.
396 """Compute the new indentation level for a single line.
398
397
399 Parameters
398 Parameters
400 ----------
399 ----------
401 line : str
400 line : str
402 A single new line of non-whitespace, non-comment Python input.
401 A single new line of non-whitespace, non-comment Python input.
403
402
404 Returns
403 Returns
405 -------
404 -------
406 indent_spaces : int
405 indent_spaces : int
407 New value for the indent level (it may be equal to self.indent_spaces
406 New value for the indent level (it may be equal to self.indent_spaces
408 if indentation doesn't change.
407 if indentation doesn't change.
409
408
410 full_dedent : boolean
409 full_dedent : boolean
411 Whether the new line causes a full flush-left dedent.
410 Whether the new line causes a full flush-left dedent.
412 """
411 """
413 indent_spaces = self.indent_spaces
412 indent_spaces = self.indent_spaces
414 full_dedent = self._full_dedent
413 full_dedent = self._full_dedent
415
414
416 inisp = num_ini_spaces(line)
415 inisp = num_ini_spaces(line)
417 if inisp < indent_spaces:
416 if inisp < indent_spaces:
418 indent_spaces = inisp
417 indent_spaces = inisp
419 if indent_spaces <= 0:
418 if indent_spaces <= 0:
420 #print 'Full dedent in text',self.source # dbg
419 #print 'Full dedent in text',self.source # dbg
421 full_dedent = True
420 full_dedent = True
422
421
423 if line.rstrip()[-1] == ':':
422 if line.rstrip()[-1] == ':':
424 indent_spaces += 4
423 indent_spaces += 4
425 elif dedent_re.match(line):
424 elif dedent_re.match(line):
426 indent_spaces -= 4
425 indent_spaces -= 4
427 if indent_spaces <= 0:
426 if indent_spaces <= 0:
428 full_dedent = True
427 full_dedent = True
429
428
430 # Safety
429 # Safety
431 if indent_spaces < 0:
430 if indent_spaces < 0:
432 indent_spaces = 0
431 indent_spaces = 0
433 #print 'safety' # dbg
432 #print 'safety' # dbg
434
433
435 return indent_spaces, full_dedent
434 return indent_spaces, full_dedent
436
435
437 def _update_indent(self, lines):
436 def _update_indent(self, lines):
438 for line in remove_comments(lines).splitlines():
437 for line in remove_comments(lines).splitlines():
439 if line and not line.isspace():
438 if line and not line.isspace():
440 self.indent_spaces, self._full_dedent = self._find_indent(line)
439 self.indent_spaces, self._full_dedent = self._find_indent(line)
441
440
442 def _store(self, lines, buffer=None, store='source'):
441 def _store(self, lines, buffer=None, store='source'):
443 """Store one or more lines of input.
442 """Store one or more lines of input.
444
443
445 If input lines are not newline-terminated, a newline is automatically
444 If input lines are not newline-terminated, a newline is automatically
446 appended."""
445 appended."""
447
446
448 if buffer is None:
447 if buffer is None:
449 buffer = self._buffer
448 buffer = self._buffer
450
449
451 if lines.endswith('\n'):
450 if lines.endswith('\n'):
452 buffer.append(lines)
451 buffer.append(lines)
453 else:
452 else:
454 buffer.append(lines+'\n')
453 buffer.append(lines+'\n')
455 setattr(self, store, self._set_source(buffer))
454 setattr(self, store, self._set_source(buffer))
456
455
457 def _set_source(self, buffer):
456 def _set_source(self, buffer):
458 return u''.join(buffer)
457 return u''.join(buffer)
459
458
460
459
461 class IPythonInputSplitter(InputSplitter):
460 class IPythonInputSplitter(InputSplitter):
462 """An input splitter that recognizes all of IPython's special syntax."""
461 """An input splitter that recognizes all of IPython's special syntax."""
463
462
464 # String with raw, untransformed input.
463 # String with raw, untransformed input.
465 source_raw = ''
464 source_raw = ''
466
465
467 # Flag to track when a transformer has stored input that it hasn't given
466 # Flag to track when a transformer has stored input that it hasn't given
468 # back yet.
467 # back yet.
469 transformer_accumulating = False
468 transformer_accumulating = False
470
469
471 # Flag to track when assemble_python_lines has stored input that it hasn't
470 # Flag to track when assemble_python_lines has stored input that it hasn't
472 # given back yet.
471 # given back yet.
473 within_python_line = False
472 within_python_line = False
474
473
475 # Private attributes
474 # Private attributes
476
475
477 # List with lines of raw input accumulated so far.
476 # List with lines of raw input accumulated so far.
478 _buffer_raw = None
477 _buffer_raw = None
479
478
480 def __init__(self, line_input_checker=True, physical_line_transforms=None,
479 def __init__(self, line_input_checker=True, physical_line_transforms=None,
481 logical_line_transforms=None, python_line_transforms=None):
480 logical_line_transforms=None, python_line_transforms=None):
482 super(IPythonInputSplitter, self).__init__()
481 super(IPythonInputSplitter, self).__init__()
483 self._buffer_raw = []
482 self._buffer_raw = []
484 self._validate = True
483 self._validate = True
485
484
486 if physical_line_transforms is not None:
485 if physical_line_transforms is not None:
487 self.physical_line_transforms = physical_line_transforms
486 self.physical_line_transforms = physical_line_transforms
488 else:
487 else:
489 self.physical_line_transforms = [leading_indent(),
488 self.physical_line_transforms = [leading_indent(),
490 classic_prompt(),
489 classic_prompt(),
491 ipy_prompt(),
490 ipy_prompt(),
492 ]
491 ]
493
492
494 self.assemble_logical_lines = assemble_logical_lines()
493 self.assemble_logical_lines = assemble_logical_lines()
495 if logical_line_transforms is not None:
494 if logical_line_transforms is not None:
496 self.logical_line_transforms = logical_line_transforms
495 self.logical_line_transforms = logical_line_transforms
497 else:
496 else:
498 self.logical_line_transforms = [cellmagic(end_on_blank_line=line_input_checker),
497 self.logical_line_transforms = [cellmagic(end_on_blank_line=line_input_checker),
499 help_end(),
498 help_end(),
500 escaped_commands(),
499 escaped_commands(),
501 assign_from_magic(),
500 assign_from_magic(),
502 assign_from_system(),
501 assign_from_system(),
503 ]
502 ]
504
503
505 self.assemble_python_lines = assemble_python_lines()
504 self.assemble_python_lines = assemble_python_lines()
506 if python_line_transforms is not None:
505 if python_line_transforms is not None:
507 self.python_line_transforms = python_line_transforms
506 self.python_line_transforms = python_line_transforms
508 else:
507 else:
509 # We don't use any of these at present
508 # We don't use any of these at present
510 self.python_line_transforms = []
509 self.python_line_transforms = []
511
510
512 @property
511 @property
513 def transforms(self):
512 def transforms(self):
514 "Quick access to all transformers."
513 "Quick access to all transformers."
515 return self.physical_line_transforms + \
514 return self.physical_line_transforms + \
516 [self.assemble_logical_lines] + self.logical_line_transforms + \
515 [self.assemble_logical_lines] + self.logical_line_transforms + \
517 [self.assemble_python_lines] + self.python_line_transforms
516 [self.assemble_python_lines] + self.python_line_transforms
518
517
519 @property
518 @property
520 def transforms_in_use(self):
519 def transforms_in_use(self):
521 """Transformers, excluding logical line transformers if we're in a
520 """Transformers, excluding logical line transformers if we're in a
522 Python line."""
521 Python line."""
523 t = self.physical_line_transforms[:]
522 t = self.physical_line_transforms[:]
524 if not self.within_python_line:
523 if not self.within_python_line:
525 t += [self.assemble_logical_lines] + self.logical_line_transforms
524 t += [self.assemble_logical_lines] + self.logical_line_transforms
526 return t + [self.assemble_python_lines] + self.python_line_transforms
525 return t + [self.assemble_python_lines] + self.python_line_transforms
527
526
528 def reset(self):
527 def reset(self):
529 """Reset the input buffer and associated state."""
528 """Reset the input buffer and associated state."""
530 super(IPythonInputSplitter, self).reset()
529 super(IPythonInputSplitter, self).reset()
531 self._buffer_raw[:] = []
530 self._buffer_raw[:] = []
532 self.source_raw = ''
531 self.source_raw = ''
533 self.transformer_accumulating = False
532 self.transformer_accumulating = False
534 self.within_python_line = False
533 self.within_python_line = False
535 for t in self.transforms:
534 for t in self.transforms:
536 t.reset()
535 t.reset()
537
536
538 def flush_transformers(self):
537 def flush_transformers(self):
539 def _flush(transform, out):
538 def _flush(transform, out):
540 if out is not None:
539 if out is not None:
541 tmp = transform.push(out)
540 tmp = transform.push(out)
542 return tmp or transform.reset() or None
541 return tmp or transform.reset() or None
543 else:
542 else:
544 return transform.reset() or None
543 return transform.reset() or None
545
544
546 out = None
545 out = None
547 for t in self.transforms_in_use:
546 for t in self.transforms_in_use:
548 out = _flush(t, out)
547 out = _flush(t, out)
549
548
550 if out is not None:
549 if out is not None:
551 self._store(out)
550 self._store(out)
552
551
553 def source_raw_reset(self):
552 def source_raw_reset(self):
554 """Return input and raw source and perform a full reset.
553 """Return input and raw source and perform a full reset.
555 """
554 """
556 self.flush_transformers()
555 self.flush_transformers()
557 out = self.source
556 out = self.source
558 out_r = self.source_raw
557 out_r = self.source_raw
559 self.reset()
558 self.reset()
560 return out, out_r
559 return out, out_r
561
560
562 def source_reset(self):
561 def source_reset(self):
563 self.flush_transformers()
562 self.flush_transformers()
564 return super(IPythonInputSplitter, self).source_reset()
563 return super(IPythonInputSplitter, self).source_reset()
565
564
566 def push_accepts_more(self):
565 def push_accepts_more(self):
567 if self.transformer_accumulating:
566 if self.transformer_accumulating:
568 return True
567 return True
569 else:
568 else:
570 return super(IPythonInputSplitter, self).push_accepts_more()
569 return super(IPythonInputSplitter, self).push_accepts_more()
571
570
572 def transform_cell(self, cell):
571 def transform_cell(self, cell):
573 """Process and translate a cell of input.
572 """Process and translate a cell of input.
574 """
573 """
575 self.reset()
574 self.reset()
576 self.push(cell)
575 self.push(cell)
577 return self.source_reset()
576 return self.source_reset()
578
577
579 def push(self, lines):
578 def push(self, lines):
580 """Push one or more lines of IPython input.
579 """Push one or more lines of IPython input.
581
580
582 This stores the given lines and returns a status code indicating
581 This stores the given lines and returns a status code indicating
583 whether the code forms a complete Python block or not, after processing
582 whether the code forms a complete Python block or not, after processing
584 all input lines for special IPython syntax.
583 all input lines for special IPython syntax.
585
584
586 Any exceptions generated in compilation are swallowed, but if an
585 Any exceptions generated in compilation are swallowed, but if an
587 exception was produced, the method returns True.
586 exception was produced, the method returns True.
588
587
589 Parameters
588 Parameters
590 ----------
589 ----------
591 lines : string
590 lines : string
592 One or more lines of Python input.
591 One or more lines of Python input.
593
592
594 Returns
593 Returns
595 -------
594 -------
596 is_complete : boolean
595 is_complete : boolean
597 True if the current input source (the result of the current input
596 True if the current input source (the result of the current input
598 plus prior inputs) forms a complete Python execution block. Note that
597 plus prior inputs) forms a complete Python execution block. Note that
599 this value is also stored as a private attribute (_is_complete), so it
598 this value is also stored as a private attribute (_is_complete), so it
600 can be queried at any time.
599 can be queried at any time.
601 """
600 """
602
601
603 # We must ensure all input is pure unicode
602 # We must ensure all input is pure unicode
604 lines = cast_unicode(lines, self.encoding)
603 lines = cast_unicode(lines, self.encoding)
605
604
606 # ''.splitlines() --> [], but we need to push the empty line to transformers
605 # ''.splitlines() --> [], but we need to push the empty line to transformers
607 lines_list = lines.splitlines()
606 lines_list = lines.splitlines()
608 if not lines_list:
607 if not lines_list:
609 lines_list = ['']
608 lines_list = ['']
610
609
611 # Store raw source before applying any transformations to it. Note
610 # Store raw source before applying any transformations to it. Note
612 # that this must be done *after* the reset() call that would otherwise
611 # that this must be done *after* the reset() call that would otherwise
613 # flush the buffer.
612 # flush the buffer.
614 self._store(lines, self._buffer_raw, 'source_raw')
613 self._store(lines, self._buffer_raw, 'source_raw')
615
614
616 for line in lines_list:
615 for line in lines_list:
617 out = self.push_line(line)
616 out = self.push_line(line)
618
617
619 return out
618 return out
620
619
621 def push_line(self, line):
620 def push_line(self, line):
622 buf = self._buffer
621 buf = self._buffer
623
622
624 def _accumulating(dbg):
623 def _accumulating(dbg):
625 #print(dbg)
624 #print(dbg)
626 self.transformer_accumulating = True
625 self.transformer_accumulating = True
627 return False
626 return False
628
627
629 for transformer in self.physical_line_transforms:
628 for transformer in self.physical_line_transforms:
630 line = transformer.push(line)
629 line = transformer.push(line)
631 if line is None:
630 if line is None:
632 return _accumulating(transformer)
631 return _accumulating(transformer)
633
632
634 if not self.within_python_line:
633 if not self.within_python_line:
635 line = self.assemble_logical_lines.push(line)
634 line = self.assemble_logical_lines.push(line)
636 if line is None:
635 if line is None:
637 return _accumulating('acc logical line')
636 return _accumulating('acc logical line')
638
637
639 for transformer in self.logical_line_transforms:
638 for transformer in self.logical_line_transforms:
640 line = transformer.push(line)
639 line = transformer.push(line)
641 if line is None:
640 if line is None:
642 return _accumulating(transformer)
641 return _accumulating(transformer)
643
642
644 line = self.assemble_python_lines.push(line)
643 line = self.assemble_python_lines.push(line)
645 if line is None:
644 if line is None:
646 self.within_python_line = True
645 self.within_python_line = True
647 return _accumulating('acc python line')
646 return _accumulating('acc python line')
648 else:
647 else:
649 self.within_python_line = False
648 self.within_python_line = False
650
649
651 for transformer in self.python_line_transforms:
650 for transformer in self.python_line_transforms:
652 line = transformer.push(line)
651 line = transformer.push(line)
653 if line is None:
652 if line is None:
654 return _accumulating(transformer)
653 return _accumulating(transformer)
655
654
656 #print("transformers clear") #debug
655 #print("transformers clear") #debug
657 self.transformer_accumulating = False
656 self.transformer_accumulating = False
658 return super(IPythonInputSplitter, self).push(line)
657 return super(IPythonInputSplitter, self).push(line)
@@ -1,444 +1,444 b''
1 import abc
1 import abc
2 import functools
2 import functools
3 import re
3 import re
4 from StringIO import StringIO
4 from StringIO import StringIO
5
5
6 from IPython.core.splitinput import split_user_input, LineInfo
6 from IPython.core.splitinput import LineInfo
7 from IPython.utils import tokenize2
7 from IPython.utils import tokenize2
8 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
8 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Globals
11 # Globals
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 # The escape sequences that define the syntax transformations IPython will
14 # The escape sequences that define the syntax transformations IPython will
15 # apply to user input. These can NOT be just changed here: many regular
15 # apply to user input. These can NOT be just changed here: many regular
16 # expressions and other parts of the code may use their hardcoded values, and
16 # expressions and other parts of the code may use their hardcoded values, and
17 # for all intents and purposes they constitute the 'IPython syntax', so they
17 # for all intents and purposes they constitute the 'IPython syntax', so they
18 # should be considered fixed.
18 # should be considered fixed.
19
19
20 ESC_SHELL = '!' # Send line to underlying system shell
20 ESC_SHELL = '!' # Send line to underlying system shell
21 ESC_SH_CAP = '!!' # Send line to system shell and capture output
21 ESC_SH_CAP = '!!' # Send line to system shell and capture output
22 ESC_HELP = '?' # Find information about object
22 ESC_HELP = '?' # Find information about object
23 ESC_HELP2 = '??' # Find extra-detailed information about object
23 ESC_HELP2 = '??' # Find extra-detailed information about object
24 ESC_MAGIC = '%' # Call magic function
24 ESC_MAGIC = '%' # Call magic function
25 ESC_MAGIC2 = '%%' # Call cell-magic function
25 ESC_MAGIC2 = '%%' # Call cell-magic function
26 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
26 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
27 ESC_QUOTE2 = ';' # Quote all args as a single string, call
27 ESC_QUOTE2 = ';' # Quote all args as a single string, call
28 ESC_PAREN = '/' # Call first argument with rest of line as arguments
28 ESC_PAREN = '/' # Call first argument with rest of line as arguments
29
29
30 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
30 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
31 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
31 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
32 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
32 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
33
33
34
34
35 class InputTransformer(object):
35 class InputTransformer(object):
36 """Abstract base class for line-based input transformers."""
36 """Abstract base class for line-based input transformers."""
37 __metaclass__ = abc.ABCMeta
37 __metaclass__ = abc.ABCMeta
38
38
39 @abc.abstractmethod
39 @abc.abstractmethod
40 def push(self, line):
40 def push(self, line):
41 """Send a line of input to the transformer, returning the transformed
41 """Send a line of input to the transformer, returning the transformed
42 input or None if the transformer is waiting for more input.
42 input or None if the transformer is waiting for more input.
43
43
44 Must be overridden by subclasses.
44 Must be overridden by subclasses.
45 """
45 """
46 pass
46 pass
47
47
48 @abc.abstractmethod
48 @abc.abstractmethod
49 def reset(self):
49 def reset(self):
50 """Return, transformed any lines that the transformer has accumulated,
50 """Return, transformed any lines that the transformer has accumulated,
51 and reset its internal state.
51 and reset its internal state.
52
52
53 Must be overridden by subclasses.
53 Must be overridden by subclasses.
54 """
54 """
55 pass
55 pass
56
56
57 @classmethod
57 @classmethod
58 def wrap(cls, func):
58 def wrap(cls, func):
59 """Can be used by subclasses as a decorator, to return a factory that
59 """Can be used by subclasses as a decorator, to return a factory that
60 will allow instantiation with the decorated object.
60 will allow instantiation with the decorated object.
61 """
61 """
62 @functools.wraps(func)
62 @functools.wraps(func)
63 def transformer_factory(**kwargs):
63 def transformer_factory(**kwargs):
64 return cls(func, **kwargs)
64 return cls(func, **kwargs)
65
65
66 return transformer_factory
66 return transformer_factory
67
67
68 class StatelessInputTransformer(InputTransformer):
68 class StatelessInputTransformer(InputTransformer):
69 """Wrapper for a stateless input transformer implemented as a function."""
69 """Wrapper for a stateless input transformer implemented as a function."""
70 def __init__(self, func):
70 def __init__(self, func):
71 self.func = func
71 self.func = func
72
72
73 def __repr__(self):
73 def __repr__(self):
74 return "StatelessInputTransformer(func={!r})".format(self.func)
74 return "StatelessInputTransformer(func={!r})".format(self.func)
75
75
76 def push(self, line):
76 def push(self, line):
77 """Send a line of input to the transformer, returning the
77 """Send a line of input to the transformer, returning the
78 transformed input."""
78 transformed input."""
79 return self.func(line)
79 return self.func(line)
80
80
81 def reset(self):
81 def reset(self):
82 """No-op - exists for compatibility."""
82 """No-op - exists for compatibility."""
83 pass
83 pass
84
84
85 class CoroutineInputTransformer(InputTransformer):
85 class CoroutineInputTransformer(InputTransformer):
86 """Wrapper for an input transformer implemented as a coroutine."""
86 """Wrapper for an input transformer implemented as a coroutine."""
87 def __init__(self, coro, **kwargs):
87 def __init__(self, coro, **kwargs):
88 # Prime it
88 # Prime it
89 self.coro = coro(**kwargs)
89 self.coro = coro(**kwargs)
90 next(self.coro)
90 next(self.coro)
91
91
92 def __repr__(self):
92 def __repr__(self):
93 return "CoroutineInputTransformer(coro={!r})".format(self.coro)
93 return "CoroutineInputTransformer(coro={!r})".format(self.coro)
94
94
95 def push(self, line):
95 def push(self, line):
96 """Send a line of input to the transformer, returning the
96 """Send a line of input to the transformer, returning the
97 transformed input or None if the transformer is waiting for more
97 transformed input or None if the transformer is waiting for more
98 input.
98 input.
99 """
99 """
100 return self.coro.send(line)
100 return self.coro.send(line)
101
101
102 def reset(self):
102 def reset(self):
103 """Return, transformed any lines that the transformer has
103 """Return, transformed any lines that the transformer has
104 accumulated, and reset its internal state.
104 accumulated, and reset its internal state.
105 """
105 """
106 return self.coro.send(None)
106 return self.coro.send(None)
107
107
108 class TokenInputTransformer(InputTransformer):
108 class TokenInputTransformer(InputTransformer):
109 """Wrapper for a token-based input transformer.
109 """Wrapper for a token-based input transformer.
110
110
111 func should accept a list of tokens (5-tuples, see tokenize docs), and
111 func should accept a list of tokens (5-tuples, see tokenize docs), and
112 return an iterable which can be passed to tokenize.untokenize().
112 return an iterable which can be passed to tokenize.untokenize().
113 """
113 """
114 def __init__(self, func):
114 def __init__(self, func):
115 self.func = func
115 self.func = func
116 self.current_line = ""
116 self.current_line = ""
117 self.line_used = False
117 self.line_used = False
118 self.reset_tokenizer()
118 self.reset_tokenizer()
119
119
120 def reset_tokenizer(self):
120 def reset_tokenizer(self):
121 self.tokenizer = generate_tokens(self.get_line)
121 self.tokenizer = generate_tokens(self.get_line)
122
122
123 def get_line(self):
123 def get_line(self):
124 if self.line_used:
124 if self.line_used:
125 raise TokenError
125 raise TokenError
126 self.line_used = True
126 self.line_used = True
127 return self.current_line
127 return self.current_line
128
128
129 def push(self, line):
129 def push(self, line):
130 self.current_line += line + "\n"
130 self.current_line += line + "\n"
131 if self.current_line.isspace():
131 if self.current_line.isspace():
132 return self.reset()
132 return self.reset()
133
133
134 self.line_used = False
134 self.line_used = False
135 tokens = []
135 tokens = []
136 stop_at_NL = False
136 stop_at_NL = False
137 try:
137 try:
138 for intok in self.tokenizer:
138 for intok in self.tokenizer:
139 tokens.append(intok)
139 tokens.append(intok)
140 t = intok[0]
140 t = intok[0]
141 if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
141 if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
142 # Stop before we try to pull a line we don't have yet
142 # Stop before we try to pull a line we don't have yet
143 break
143 break
144 elif t == tokenize2.ERRORTOKEN:
144 elif t == tokenize2.ERRORTOKEN:
145 stop_at_NL = True
145 stop_at_NL = True
146 except TokenError:
146 except TokenError:
147 # Multi-line statement - stop and try again with the next line
147 # Multi-line statement - stop and try again with the next line
148 self.reset_tokenizer()
148 self.reset_tokenizer()
149 return None
149 return None
150
150
151 return self.output(tokens)
151 return self.output(tokens)
152
152
153 def output(self, tokens):
153 def output(self, tokens):
154 self.current_line = ""
154 self.current_line = ""
155 self.reset_tokenizer()
155 self.reset_tokenizer()
156 return untokenize(self.func(tokens)).rstrip('\n')
156 return untokenize(self.func(tokens)).rstrip('\n')
157
157
158 def reset(self):
158 def reset(self):
159 l = self.current_line
159 l = self.current_line
160 self.current_line = ""
160 self.current_line = ""
161 self.reset_tokenizer()
161 self.reset_tokenizer()
162 if l:
162 if l:
163 return l.rstrip('\n')
163 return l.rstrip('\n')
164
164
165 class assemble_python_lines(TokenInputTransformer):
165 class assemble_python_lines(TokenInputTransformer):
166 def __init__(self):
166 def __init__(self):
167 super(assemble_python_lines, self).__init__(None)
167 super(assemble_python_lines, self).__init__(None)
168
168
169 def output(self, tokens):
169 def output(self, tokens):
170 return self.reset()
170 return self.reset()
171
171
172 @CoroutineInputTransformer.wrap
172 @CoroutineInputTransformer.wrap
173 def assemble_logical_lines():
173 def assemble_logical_lines():
174 """Join lines following explicit line continuations (\)"""
174 """Join lines following explicit line continuations (\)"""
175 line = ''
175 line = ''
176 while True:
176 while True:
177 line = (yield line)
177 line = (yield line)
178 if not line or line.isspace():
178 if not line or line.isspace():
179 continue
179 continue
180
180
181 parts = []
181 parts = []
182 while line is not None:
182 while line is not None:
183 if line.endswith('\\') and (not has_comment(line)):
183 if line.endswith('\\') and (not has_comment(line)):
184 parts.append(line[:-1])
184 parts.append(line[:-1])
185 line = (yield None) # Get another line
185 line = (yield None) # Get another line
186 else:
186 else:
187 parts.append(line)
187 parts.append(line)
188 break
188 break
189
189
190 # Output
190 # Output
191 line = ''.join(parts)
191 line = ''.join(parts)
192
192
193 # Utilities
193 # Utilities
194 def _make_help_call(target, esc, lspace, next_input=None):
194 def _make_help_call(target, esc, lspace, next_input=None):
195 """Prepares a pinfo(2)/psearch call from a target name and the escape
195 """Prepares a pinfo(2)/psearch call from a target name and the escape
196 (i.e. ? or ??)"""
196 (i.e. ? or ??)"""
197 method = 'pinfo2' if esc == '??' \
197 method = 'pinfo2' if esc == '??' \
198 else 'psearch' if '*' in target \
198 else 'psearch' if '*' in target \
199 else 'pinfo'
199 else 'pinfo'
200 arg = " ".join([method, target])
200 arg = " ".join([method, target])
201 if next_input is None:
201 if next_input is None:
202 return '%sget_ipython().magic(%r)' % (lspace, arg)
202 return '%sget_ipython().magic(%r)' % (lspace, arg)
203 else:
203 else:
204 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
204 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
205 (lspace, next_input, arg)
205 (lspace, next_input, arg)
206
206
207 # These define the transformations for the different escape characters.
207 # These define the transformations for the different escape characters.
208 def _tr_system(line_info):
208 def _tr_system(line_info):
209 "Translate lines escaped with: !"
209 "Translate lines escaped with: !"
210 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
210 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
211 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
211 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
212
212
213 def _tr_system2(line_info):
213 def _tr_system2(line_info):
214 "Translate lines escaped with: !!"
214 "Translate lines escaped with: !!"
215 cmd = line_info.line.lstrip()[2:]
215 cmd = line_info.line.lstrip()[2:]
216 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
216 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
217
217
218 def _tr_help(line_info):
218 def _tr_help(line_info):
219 "Translate lines escaped with: ?/??"
219 "Translate lines escaped with: ?/??"
220 # A naked help line should just fire the intro help screen
220 # A naked help line should just fire the intro help screen
221 if not line_info.line[1:]:
221 if not line_info.line[1:]:
222 return 'get_ipython().show_usage()'
222 return 'get_ipython().show_usage()'
223
223
224 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
224 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
225
225
226 def _tr_magic(line_info):
226 def _tr_magic(line_info):
227 "Translate lines escaped with: %"
227 "Translate lines escaped with: %"
228 tpl = '%sget_ipython().magic(%r)'
228 tpl = '%sget_ipython().magic(%r)'
229 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
229 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
230 return tpl % (line_info.pre, cmd)
230 return tpl % (line_info.pre, cmd)
231
231
232 def _tr_quote(line_info):
232 def _tr_quote(line_info):
233 "Translate lines escaped with: ,"
233 "Translate lines escaped with: ,"
234 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
234 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
235 '", "'.join(line_info.the_rest.split()) )
235 '", "'.join(line_info.the_rest.split()) )
236
236
237 def _tr_quote2(line_info):
237 def _tr_quote2(line_info):
238 "Translate lines escaped with: ;"
238 "Translate lines escaped with: ;"
239 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
239 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
240 line_info.the_rest)
240 line_info.the_rest)
241
241
242 def _tr_paren(line_info):
242 def _tr_paren(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 tr = { ESC_SHELL : _tr_system,
247 tr = { ESC_SHELL : _tr_system,
248 ESC_SH_CAP : _tr_system2,
248 ESC_SH_CAP : _tr_system2,
249 ESC_HELP : _tr_help,
249 ESC_HELP : _tr_help,
250 ESC_HELP2 : _tr_help,
250 ESC_HELP2 : _tr_help,
251 ESC_MAGIC : _tr_magic,
251 ESC_MAGIC : _tr_magic,
252 ESC_QUOTE : _tr_quote,
252 ESC_QUOTE : _tr_quote,
253 ESC_QUOTE2 : _tr_quote2,
253 ESC_QUOTE2 : _tr_quote2,
254 ESC_PAREN : _tr_paren }
254 ESC_PAREN : _tr_paren }
255
255
256 @StatelessInputTransformer.wrap
256 @StatelessInputTransformer.wrap
257 def escaped_commands(line):
257 def escaped_commands(line):
258 """Transform escaped commands - %magic, !system, ?help + various autocalls.
258 """Transform escaped commands - %magic, !system, ?help + various autocalls.
259 """
259 """
260 if not line or line.isspace():
260 if not line or line.isspace():
261 return line
261 return line
262 lineinf = LineInfo(line)
262 lineinf = LineInfo(line)
263 if lineinf.esc not in tr:
263 if lineinf.esc not in tr:
264 return line
264 return line
265
265
266 return tr[lineinf.esc](lineinf)
266 return tr[lineinf.esc](lineinf)
267
267
268 _initial_space_re = re.compile(r'\s*')
268 _initial_space_re = re.compile(r'\s*')
269
269
270 _help_end_re = re.compile(r"""(%{0,2}
270 _help_end_re = re.compile(r"""(%{0,2}
271 [a-zA-Z_*][\w*]* # Variable name
271 [a-zA-Z_*][\w*]* # Variable name
272 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
272 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
273 )
273 )
274 (\?\??)$ # ? or ??""",
274 (\?\??)$ # ? or ??""",
275 re.VERBOSE)
275 re.VERBOSE)
276
276
277 def has_comment(src):
277 def has_comment(src):
278 """Indicate whether an input line has (i.e. ends in, or is) a comment.
278 """Indicate whether an input line has (i.e. ends in, or is) a comment.
279
279
280 This uses tokenize, so it can distinguish comments from # inside strings.
280 This uses tokenize, so it can distinguish comments from # inside strings.
281
281
282 Parameters
282 Parameters
283 ----------
283 ----------
284 src : string
284 src : string
285 A single line input string.
285 A single line input string.
286
286
287 Returns
287 Returns
288 -------
288 -------
289 comment : bool
289 comment : bool
290 True if source has a comment.
290 True if source has a comment.
291 """
291 """
292 readline = StringIO(src).readline
292 readline = StringIO(src).readline
293 toktypes = set()
293 toktypes = set()
294 try:
294 try:
295 for t in generate_tokens(readline):
295 for t in generate_tokens(readline):
296 toktypes.add(t[0])
296 toktypes.add(t[0])
297 except TokenError:
297 except TokenError:
298 pass
298 pass
299 return(tokenize2.COMMENT in toktypes)
299 return(tokenize2.COMMENT in toktypes)
300
300
301
301
302 @StatelessInputTransformer.wrap
302 @StatelessInputTransformer.wrap
303 def help_end(line):
303 def help_end(line):
304 """Translate lines with ?/?? at the end"""
304 """Translate lines with ?/?? at the end"""
305 m = _help_end_re.search(line)
305 m = _help_end_re.search(line)
306 if m is None or has_comment(line):
306 if m is None or has_comment(line):
307 return line
307 return line
308 target = m.group(1)
308 target = m.group(1)
309 esc = m.group(3)
309 esc = m.group(3)
310 lspace = _initial_space_re.match(line).group(0)
310 lspace = _initial_space_re.match(line).group(0)
311
311
312 # If we're mid-command, put it back on the next prompt for the user.
312 # If we're mid-command, put it back on the next prompt for the user.
313 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
313 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
314
314
315 return _make_help_call(target, esc, lspace, next_input)
315 return _make_help_call(target, esc, lspace, next_input)
316
316
317
317
318 @CoroutineInputTransformer.wrap
318 @CoroutineInputTransformer.wrap
319 def cellmagic(end_on_blank_line=False):
319 def cellmagic(end_on_blank_line=False):
320 """Captures & transforms cell magics.
320 """Captures & transforms cell magics.
321
321
322 After a cell magic is started, this stores up any lines it gets until it is
322 After a cell magic is started, this stores up any lines it gets until it is
323 reset (sent None).
323 reset (sent None).
324 """
324 """
325 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
325 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
326 cellmagic_help_re = re.compile('%%\w+\?')
326 cellmagic_help_re = re.compile('%%\w+\?')
327 line = ''
327 line = ''
328 while True:
328 while True:
329 line = (yield line)
329 line = (yield line)
330 if (not line) or (not line.startswith(ESC_MAGIC2)):
330 if (not line) or (not line.startswith(ESC_MAGIC2)):
331 continue
331 continue
332
332
333 if cellmagic_help_re.match(line):
333 if cellmagic_help_re.match(line):
334 # This case will be handled by help_end
334 # This case will be handled by help_end
335 continue
335 continue
336
336
337 first = line
337 first = line
338 body = []
338 body = []
339 line = (yield None)
339 line = (yield None)
340 while (line is not None) and \
340 while (line is not None) and \
341 ((line.strip() != '') or not end_on_blank_line):
341 ((line.strip() != '') or not end_on_blank_line):
342 body.append(line)
342 body.append(line)
343 line = (yield None)
343 line = (yield None)
344
344
345 # Output
345 # Output
346 magic_name, _, first = first.partition(' ')
346 magic_name, _, first = first.partition(' ')
347 magic_name = magic_name.lstrip(ESC_MAGIC2)
347 magic_name = magic_name.lstrip(ESC_MAGIC2)
348 line = tpl % (magic_name, first, u'\n'.join(body))
348 line = tpl % (magic_name, first, u'\n'.join(body))
349
349
350
350
351 def _strip_prompts(prompt_re):
351 def _strip_prompts(prompt_re):
352 """Remove matching input prompts from a block of input."""
352 """Remove matching input prompts from a block of input."""
353 line = ''
353 line = ''
354 while True:
354 while True:
355 line = (yield line)
355 line = (yield line)
356
356
357 # First line of cell
357 # First line of cell
358 if line is None:
358 if line is None:
359 continue
359 continue
360 out, n1 = prompt_re.subn('', line, count=1)
360 out, n1 = prompt_re.subn('', line, count=1)
361 line = (yield out)
361 line = (yield out)
362
362
363 # Second line of cell, because people often copy from just after the
363 # Second line of cell, because people often copy from just after the
364 # first prompt, so we might not see it in the first line.
364 # first prompt, so we might not see it in the first line.
365 if line is None:
365 if line is None:
366 continue
366 continue
367 out, n2 = prompt_re.subn('', line, count=1)
367 out, n2 = prompt_re.subn('', line, count=1)
368 line = (yield out)
368 line = (yield out)
369
369
370 if n1 or n2:
370 if n1 or n2:
371 # Found the input prompt in the first two lines - check for it in
371 # Found the input prompt in the first two lines - check for it in
372 # the rest of the cell as well.
372 # the rest of the cell as well.
373 while line is not None:
373 while line is not None:
374 line = (yield prompt_re.sub('', line, count=1))
374 line = (yield prompt_re.sub('', line, count=1))
375
375
376 else:
376 else:
377 # Prompts not in input - wait for reset
377 # Prompts not in input - wait for reset
378 while line is not None:
378 while line is not None:
379 line = (yield line)
379 line = (yield line)
380
380
381 @CoroutineInputTransformer.wrap
381 @CoroutineInputTransformer.wrap
382 def classic_prompt():
382 def classic_prompt():
383 """Strip the >>>/... prompts of the Python interactive shell."""
383 """Strip the >>>/... prompts of the Python interactive shell."""
384 prompt_re = re.compile(r'^(>>> ?|^\.\.\. ?)')
384 prompt_re = re.compile(r'^(>>> ?|^\.\.\. ?)')
385 return _strip_prompts(prompt_re)
385 return _strip_prompts(prompt_re)
386
386
387 @CoroutineInputTransformer.wrap
387 @CoroutineInputTransformer.wrap
388 def ipy_prompt():
388 def ipy_prompt():
389 """Strip IPython's In [1]:/...: prompts."""
389 """Strip IPython's In [1]:/...: prompts."""
390 prompt_re = re.compile(r'^(In \[\d+\]: |^\ \ \ \.\.\.+: )')
390 prompt_re = re.compile(r'^(In \[\d+\]: |^\ \ \ \.\.\.+: )')
391 return _strip_prompts(prompt_re)
391 return _strip_prompts(prompt_re)
392
392
393
393
394 @CoroutineInputTransformer.wrap
394 @CoroutineInputTransformer.wrap
395 def leading_indent():
395 def leading_indent():
396 """Remove leading indentation.
396 """Remove leading indentation.
397
397
398 If the first line starts with a spaces or tabs, the same whitespace will be
398 If the first line starts with a spaces or tabs, the same whitespace will be
399 removed from each following line until it is reset.
399 removed from each following line until it is reset.
400 """
400 """
401 space_re = re.compile(r'^[ \t]+')
401 space_re = re.compile(r'^[ \t]+')
402 line = ''
402 line = ''
403 while True:
403 while True:
404 line = (yield line)
404 line = (yield line)
405
405
406 if line is None:
406 if line is None:
407 continue
407 continue
408
408
409 m = space_re.match(line)
409 m = space_re.match(line)
410 if m:
410 if m:
411 space = m.group(0)
411 space = m.group(0)
412 while line is not None:
412 while line is not None:
413 if line.startswith(space):
413 if line.startswith(space):
414 line = line[len(space):]
414 line = line[len(space):]
415 line = (yield line)
415 line = (yield line)
416 else:
416 else:
417 # No leading spaces - wait for reset
417 # No leading spaces - wait for reset
418 while line is not None:
418 while line is not None:
419 line = (yield line)
419 line = (yield line)
420
420
421
421
422 assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
422 assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
423 r'\s*=\s*!\s*(?P<cmd>.*)')
423 r'\s*=\s*!\s*(?P<cmd>.*)')
424 assign_system_template = '%s = get_ipython().getoutput(%r)'
424 assign_system_template = '%s = get_ipython().getoutput(%r)'
425 @StatelessInputTransformer.wrap
425 @StatelessInputTransformer.wrap
426 def assign_from_system(line):
426 def assign_from_system(line):
427 """Transform assignment from system commands (e.g. files = !ls)"""
427 """Transform assignment from system commands (e.g. files = !ls)"""
428 m = assign_system_re.match(line)
428 m = assign_system_re.match(line)
429 if m is None:
429 if m is None:
430 return line
430 return line
431
431
432 return assign_system_template % m.group('lhs', 'cmd')
432 return assign_system_template % m.group('lhs', 'cmd')
433
433
434 assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
434 assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
435 r'\s*=\s*%\s*(?P<cmd>.*)')
435 r'\s*=\s*%\s*(?P<cmd>.*)')
436 assign_magic_template = '%s = get_ipython().magic(%r)'
436 assign_magic_template = '%s = get_ipython().magic(%r)'
437 @StatelessInputTransformer.wrap
437 @StatelessInputTransformer.wrap
438 def assign_from_magic(line):
438 def assign_from_magic(line):
439 """Transform assignment from magic commands (e.g. a = %who_ls)"""
439 """Transform assignment from magic commands (e.g. a = %who_ls)"""
440 m = assign_magic_re.match(line)
440 m = assign_magic_re.match(line)
441 if m is None:
441 if m is None:
442 return line
442 return line
443
443
444 return assign_magic_template % m.group('lhs', 'cmd')
444 return assign_magic_template % m.group('lhs', 'cmd')
@@ -1,677 +1,676 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9
9
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Stdlib
17 # Stdlib
18 import json
19 import os
18 import os
20 import re
19 import re
21 import sys
20 import sys
22 import types
21 import types
23 from getopt import getopt, GetoptError
22 from getopt import getopt, GetoptError
24
23
25 # Our own
24 # Our own
26 from IPython.config.configurable import Configurable
25 from IPython.config.configurable import Configurable
27 from IPython.core import oinspect
26 from IPython.core import oinspect
28 from IPython.core.error import UsageError
27 from IPython.core.error import UsageError
29 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
28 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
30 from IPython.external.decorator import decorator
29 from IPython.external.decorator import decorator
31 from IPython.utils.ipstruct import Struct
30 from IPython.utils.ipstruct import Struct
32 from IPython.utils.process import arg_split
31 from IPython.utils.process import arg_split
33 from IPython.utils.text import dedent
32 from IPython.utils.text import dedent
34 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
33 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
35 from IPython.utils.warn import error
34 from IPython.utils.warn import error
36
35
37 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
38 # Globals
37 # Globals
39 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
40
39
41 # A dict we'll use for each class that has magics, used as temporary storage to
40 # A dict we'll use for each class that has magics, used as temporary storage to
42 # pass information between the @line/cell_magic method decorators and the
41 # pass information between the @line/cell_magic method decorators and the
43 # @magics_class class decorator, because the method decorators have no
42 # @magics_class class decorator, because the method decorators have no
44 # access to the class when they run. See for more details:
43 # access to the class when they run. See for more details:
45 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
44 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
46
45
47 magics = dict(line={}, cell={})
46 magics = dict(line={}, cell={})
48
47
49 magic_kinds = ('line', 'cell')
48 magic_kinds = ('line', 'cell')
50 magic_spec = ('line', 'cell', 'line_cell')
49 magic_spec = ('line', 'cell', 'line_cell')
51 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
50 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
52
51
53 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
54 # Utility classes and functions
53 # Utility classes and functions
55 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
56
55
57 class Bunch: pass
56 class Bunch: pass
58
57
59
58
60 def on_off(tag):
59 def on_off(tag):
61 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
60 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
62 return ['OFF','ON'][tag]
61 return ['OFF','ON'][tag]
63
62
64
63
65 def compress_dhist(dh):
64 def compress_dhist(dh):
66 """Compress a directory history into a new one with at most 20 entries.
65 """Compress a directory history into a new one with at most 20 entries.
67
66
68 Return a new list made from the first and last 10 elements of dhist after
67 Return a new list made from the first and last 10 elements of dhist after
69 removal of duplicates.
68 removal of duplicates.
70 """
69 """
71 head, tail = dh[:-10], dh[-10:]
70 head, tail = dh[:-10], dh[-10:]
72
71
73 newhead = []
72 newhead = []
74 done = set()
73 done = set()
75 for h in head:
74 for h in head:
76 if h in done:
75 if h in done:
77 continue
76 continue
78 newhead.append(h)
77 newhead.append(h)
79 done.add(h)
78 done.add(h)
80
79
81 return newhead + tail
80 return newhead + tail
82
81
83
82
84 def needs_local_scope(func):
83 def needs_local_scope(func):
85 """Decorator to mark magic functions which need to local scope to run."""
84 """Decorator to mark magic functions which need to local scope to run."""
86 func.needs_local_scope = True
85 func.needs_local_scope = True
87 return func
86 return func
88
87
89 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
90 # Class and method decorators for registering magics
89 # Class and method decorators for registering magics
91 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
92
91
93 def magics_class(cls):
92 def magics_class(cls):
94 """Class decorator for all subclasses of the main Magics class.
93 """Class decorator for all subclasses of the main Magics class.
95
94
96 Any class that subclasses Magics *must* also apply this decorator, to
95 Any class that subclasses Magics *must* also apply this decorator, to
97 ensure that all the methods that have been decorated as line/cell magics
96 ensure that all the methods that have been decorated as line/cell magics
98 get correctly registered in the class instance. This is necessary because
97 get correctly registered in the class instance. This is necessary because
99 when method decorators run, the class does not exist yet, so they
98 when method decorators run, the class does not exist yet, so they
100 temporarily store their information into a module global. Application of
99 temporarily store their information into a module global. Application of
101 this class decorator copies that global data to the class instance and
100 this class decorator copies that global data to the class instance and
102 clears the global.
101 clears the global.
103
102
104 Obviously, this mechanism is not thread-safe, which means that the
103 Obviously, this mechanism is not thread-safe, which means that the
105 *creation* of subclasses of Magic should only be done in a single-thread
104 *creation* of subclasses of Magic should only be done in a single-thread
106 context. Instantiation of the classes has no restrictions. Given that
105 context. Instantiation of the classes has no restrictions. Given that
107 these classes are typically created at IPython startup time and before user
106 these classes are typically created at IPython startup time and before user
108 application code becomes active, in practice this should not pose any
107 application code becomes active, in practice this should not pose any
109 problems.
108 problems.
110 """
109 """
111 cls.registered = True
110 cls.registered = True
112 cls.magics = dict(line = magics['line'],
111 cls.magics = dict(line = magics['line'],
113 cell = magics['cell'])
112 cell = magics['cell'])
114 magics['line'] = {}
113 magics['line'] = {}
115 magics['cell'] = {}
114 magics['cell'] = {}
116 return cls
115 return cls
117
116
118
117
119 def record_magic(dct, magic_kind, magic_name, func):
118 def record_magic(dct, magic_kind, magic_name, func):
120 """Utility function to store a function as a magic of a specific kind.
119 """Utility function to store a function as a magic of a specific kind.
121
120
122 Parameters
121 Parameters
123 ----------
122 ----------
124 dct : dict
123 dct : dict
125 A dictionary with 'line' and 'cell' subdicts.
124 A dictionary with 'line' and 'cell' subdicts.
126
125
127 magic_kind : str
126 magic_kind : str
128 Kind of magic to be stored.
127 Kind of magic to be stored.
129
128
130 magic_name : str
129 magic_name : str
131 Key to store the magic as.
130 Key to store the magic as.
132
131
133 func : function
132 func : function
134 Callable object to store.
133 Callable object to store.
135 """
134 """
136 if magic_kind == 'line_cell':
135 if magic_kind == 'line_cell':
137 dct['line'][magic_name] = dct['cell'][magic_name] = func
136 dct['line'][magic_name] = dct['cell'][magic_name] = func
138 else:
137 else:
139 dct[magic_kind][magic_name] = func
138 dct[magic_kind][magic_name] = func
140
139
141
140
142 def validate_type(magic_kind):
141 def validate_type(magic_kind):
143 """Ensure that the given magic_kind is valid.
142 """Ensure that the given magic_kind is valid.
144
143
145 Check that the given magic_kind is one of the accepted spec types (stored
144 Check that the given magic_kind is one of the accepted spec types (stored
146 in the global `magic_spec`), raise ValueError otherwise.
145 in the global `magic_spec`), raise ValueError otherwise.
147 """
146 """
148 if magic_kind not in magic_spec:
147 if magic_kind not in magic_spec:
149 raise ValueError('magic_kind must be one of %s, %s given' %
148 raise ValueError('magic_kind must be one of %s, %s given' %
150 magic_kinds, magic_kind)
149 magic_kinds, magic_kind)
151
150
152
151
153 # The docstrings for the decorator below will be fairly similar for the two
152 # The docstrings for the decorator below will be fairly similar for the two
154 # types (method and function), so we generate them here once and reuse the
153 # types (method and function), so we generate them here once and reuse the
155 # templates below.
154 # templates below.
156 _docstring_template = \
155 _docstring_template = \
157 """Decorate the given {0} as {1} magic.
156 """Decorate the given {0} as {1} magic.
158
157
159 The decorator can be used with or without arguments, as follows.
158 The decorator can be used with or without arguments, as follows.
160
159
161 i) without arguments: it will create a {1} magic named as the {0} being
160 i) without arguments: it will create a {1} magic named as the {0} being
162 decorated::
161 decorated::
163
162
164 @deco
163 @deco
165 def foo(...)
164 def foo(...)
166
165
167 will create a {1} magic named `foo`.
166 will create a {1} magic named `foo`.
168
167
169 ii) with one string argument: which will be used as the actual name of the
168 ii) with one string argument: which will be used as the actual name of the
170 resulting magic::
169 resulting magic::
171
170
172 @deco('bar')
171 @deco('bar')
173 def foo(...)
172 def foo(...)
174
173
175 will create a {1} magic named `bar`.
174 will create a {1} magic named `bar`.
176 """
175 """
177
176
178 # These two are decorator factories. While they are conceptually very similar,
177 # These two are decorator factories. While they are conceptually very similar,
179 # there are enough differences in the details that it's simpler to have them
178 # there are enough differences in the details that it's simpler to have them
180 # written as completely standalone functions rather than trying to share code
179 # written as completely standalone functions rather than trying to share code
181 # and make a single one with convoluted logic.
180 # and make a single one with convoluted logic.
182
181
183 def _method_magic_marker(magic_kind):
182 def _method_magic_marker(magic_kind):
184 """Decorator factory for methods in Magics subclasses.
183 """Decorator factory for methods in Magics subclasses.
185 """
184 """
186
185
187 validate_type(magic_kind)
186 validate_type(magic_kind)
188
187
189 # This is a closure to capture the magic_kind. We could also use a class,
188 # This is a closure to capture the magic_kind. We could also use a class,
190 # but it's overkill for just that one bit of state.
189 # but it's overkill for just that one bit of state.
191 def magic_deco(arg):
190 def magic_deco(arg):
192 call = lambda f, *a, **k: f(*a, **k)
191 call = lambda f, *a, **k: f(*a, **k)
193
192
194 if callable(arg):
193 if callable(arg):
195 # "Naked" decorator call (just @foo, no args)
194 # "Naked" decorator call (just @foo, no args)
196 func = arg
195 func = arg
197 name = func.func_name
196 name = func.func_name
198 retval = decorator(call, func)
197 retval = decorator(call, func)
199 record_magic(magics, magic_kind, name, name)
198 record_magic(magics, magic_kind, name, name)
200 elif isinstance(arg, basestring):
199 elif isinstance(arg, basestring):
201 # Decorator called with arguments (@foo('bar'))
200 # Decorator called with arguments (@foo('bar'))
202 name = arg
201 name = arg
203 def mark(func, *a, **kw):
202 def mark(func, *a, **kw):
204 record_magic(magics, magic_kind, name, func.func_name)
203 record_magic(magics, magic_kind, name, func.func_name)
205 return decorator(call, func)
204 return decorator(call, func)
206 retval = mark
205 retval = mark
207 else:
206 else:
208 raise TypeError("Decorator can only be called with "
207 raise TypeError("Decorator can only be called with "
209 "string or function")
208 "string or function")
210 return retval
209 return retval
211
210
212 # Ensure the resulting decorator has a usable docstring
211 # Ensure the resulting decorator has a usable docstring
213 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
212 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
214 return magic_deco
213 return magic_deco
215
214
216
215
217 def _function_magic_marker(magic_kind):
216 def _function_magic_marker(magic_kind):
218 """Decorator factory for standalone functions.
217 """Decorator factory for standalone functions.
219 """
218 """
220 validate_type(magic_kind)
219 validate_type(magic_kind)
221
220
222 # This is a closure to capture the magic_kind. We could also use a class,
221 # This is a closure to capture the magic_kind. We could also use a class,
223 # but it's overkill for just that one bit of state.
222 # but it's overkill for just that one bit of state.
224 def magic_deco(arg):
223 def magic_deco(arg):
225 call = lambda f, *a, **k: f(*a, **k)
224 call = lambda f, *a, **k: f(*a, **k)
226
225
227 # Find get_ipython() in the caller's namespace
226 # Find get_ipython() in the caller's namespace
228 caller = sys._getframe(1)
227 caller = sys._getframe(1)
229 for ns in ['f_locals', 'f_globals', 'f_builtins']:
228 for ns in ['f_locals', 'f_globals', 'f_builtins']:
230 get_ipython = getattr(caller, ns).get('get_ipython')
229 get_ipython = getattr(caller, ns).get('get_ipython')
231 if get_ipython is not None:
230 if get_ipython is not None:
232 break
231 break
233 else:
232 else:
234 raise NameError('Decorator can only run in context where '
233 raise NameError('Decorator can only run in context where '
235 '`get_ipython` exists')
234 '`get_ipython` exists')
236
235
237 ip = get_ipython()
236 ip = get_ipython()
238
237
239 if callable(arg):
238 if callable(arg):
240 # "Naked" decorator call (just @foo, no args)
239 # "Naked" decorator call (just @foo, no args)
241 func = arg
240 func = arg
242 name = func.func_name
241 name = func.func_name
243 ip.register_magic_function(func, magic_kind, name)
242 ip.register_magic_function(func, magic_kind, name)
244 retval = decorator(call, func)
243 retval = decorator(call, func)
245 elif isinstance(arg, basestring):
244 elif isinstance(arg, basestring):
246 # Decorator called with arguments (@foo('bar'))
245 # Decorator called with arguments (@foo('bar'))
247 name = arg
246 name = arg
248 def mark(func, *a, **kw):
247 def mark(func, *a, **kw):
249 ip.register_magic_function(func, magic_kind, name)
248 ip.register_magic_function(func, magic_kind, name)
250 return decorator(call, func)
249 return decorator(call, func)
251 retval = mark
250 retval = mark
252 else:
251 else:
253 raise TypeError("Decorator can only be called with "
252 raise TypeError("Decorator can only be called with "
254 "string or function")
253 "string or function")
255 return retval
254 return retval
256
255
257 # Ensure the resulting decorator has a usable docstring
256 # Ensure the resulting decorator has a usable docstring
258 ds = _docstring_template.format('function', magic_kind)
257 ds = _docstring_template.format('function', magic_kind)
259
258
260 ds += dedent("""
259 ds += dedent("""
261 Note: this decorator can only be used in a context where IPython is already
260 Note: this decorator can only be used in a context where IPython is already
262 active, so that the `get_ipython()` call succeeds. You can therefore use
261 active, so that the `get_ipython()` call succeeds. You can therefore use
263 it in your startup files loaded after IPython initializes, but *not* in the
262 it in your startup files loaded after IPython initializes, but *not* in the
264 IPython configuration file itself, which is executed before IPython is
263 IPython configuration file itself, which is executed before IPython is
265 fully up and running. Any file located in the `startup` subdirectory of
264 fully up and running. Any file located in the `startup` subdirectory of
266 your configuration profile will be OK in this sense.
265 your configuration profile will be OK in this sense.
267 """)
266 """)
268
267
269 magic_deco.__doc__ = ds
268 magic_deco.__doc__ = ds
270 return magic_deco
269 return magic_deco
271
270
272
271
273 # Create the actual decorators for public use
272 # Create the actual decorators for public use
274
273
275 # These three are used to decorate methods in class definitions
274 # These three are used to decorate methods in class definitions
276 line_magic = _method_magic_marker('line')
275 line_magic = _method_magic_marker('line')
277 cell_magic = _method_magic_marker('cell')
276 cell_magic = _method_magic_marker('cell')
278 line_cell_magic = _method_magic_marker('line_cell')
277 line_cell_magic = _method_magic_marker('line_cell')
279
278
280 # These three decorate standalone functions and perform the decoration
279 # These three decorate standalone functions and perform the decoration
281 # immediately. They can only run where get_ipython() works
280 # immediately. They can only run where get_ipython() works
282 register_line_magic = _function_magic_marker('line')
281 register_line_magic = _function_magic_marker('line')
283 register_cell_magic = _function_magic_marker('cell')
282 register_cell_magic = _function_magic_marker('cell')
284 register_line_cell_magic = _function_magic_marker('line_cell')
283 register_line_cell_magic = _function_magic_marker('line_cell')
285
284
286 #-----------------------------------------------------------------------------
285 #-----------------------------------------------------------------------------
287 # Core Magic classes
286 # Core Magic classes
288 #-----------------------------------------------------------------------------
287 #-----------------------------------------------------------------------------
289
288
290 class MagicsManager(Configurable):
289 class MagicsManager(Configurable):
291 """Object that handles all magic-related functionality for IPython.
290 """Object that handles all magic-related functionality for IPython.
292 """
291 """
293 # Non-configurable class attributes
292 # Non-configurable class attributes
294
293
295 # A two-level dict, first keyed by magic type, then by magic function, and
294 # A two-level dict, first keyed by magic type, then by magic function, and
296 # holding the actual callable object as value. This is the dict used for
295 # holding the actual callable object as value. This is the dict used for
297 # magic function dispatch
296 # magic function dispatch
298 magics = Dict
297 magics = Dict
299
298
300 # A registry of the original objects that we've been given holding magics.
299 # A registry of the original objects that we've been given holding magics.
301 registry = Dict
300 registry = Dict
302
301
303 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
302 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
304
303
305 auto_magic = Bool(True, config=True, help=
304 auto_magic = Bool(True, config=True, help=
306 "Automatically call line magics without requiring explicit % prefix")
305 "Automatically call line magics without requiring explicit % prefix")
307
306
308 def _auto_magic_changed(self, name, value):
307 def _auto_magic_changed(self, name, value):
309 self.shell.automagic = value
308 self.shell.automagic = value
310
309
311 _auto_status = [
310 _auto_status = [
312 'Automagic is OFF, % prefix IS needed for line magics.',
311 'Automagic is OFF, % prefix IS needed for line magics.',
313 'Automagic is ON, % prefix IS NOT needed for line magics.']
312 'Automagic is ON, % prefix IS NOT needed for line magics.']
314
313
315 user_magics = Instance('IPython.core.magics.UserMagics')
314 user_magics = Instance('IPython.core.magics.UserMagics')
316
315
317 def __init__(self, shell=None, config=None, user_magics=None, **traits):
316 def __init__(self, shell=None, config=None, user_magics=None, **traits):
318
317
319 super(MagicsManager, self).__init__(shell=shell, config=config,
318 super(MagicsManager, self).__init__(shell=shell, config=config,
320 user_magics=user_magics, **traits)
319 user_magics=user_magics, **traits)
321 self.magics = dict(line={}, cell={})
320 self.magics = dict(line={}, cell={})
322 # Let's add the user_magics to the registry for uniformity, so *all*
321 # Let's add the user_magics to the registry for uniformity, so *all*
323 # registered magic containers can be found there.
322 # registered magic containers can be found there.
324 self.registry[user_magics.__class__.__name__] = user_magics
323 self.registry[user_magics.__class__.__name__] = user_magics
325
324
326 def auto_status(self):
325 def auto_status(self):
327 """Return descriptive string with automagic status."""
326 """Return descriptive string with automagic status."""
328 return self._auto_status[self.auto_magic]
327 return self._auto_status[self.auto_magic]
329
328
330 def lsmagic(self):
329 def lsmagic(self):
331 """Return a dict of currently available magic functions.
330 """Return a dict of currently available magic functions.
332
331
333 The return dict has the keys 'line' and 'cell', corresponding to the
332 The return dict has the keys 'line' and 'cell', corresponding to the
334 two types of magics we support. Each value is a list of names.
333 two types of magics we support. Each value is a list of names.
335 """
334 """
336 return self.magics
335 return self.magics
337
336
338 def lsmagic_docs(self, brief=False, missing=''):
337 def lsmagic_docs(self, brief=False, missing=''):
339 """Return dict of documentation of magic functions.
338 """Return dict of documentation of magic functions.
340
339
341 The return dict has the keys 'line' and 'cell', corresponding to the
340 The return dict has the keys 'line' and 'cell', corresponding to the
342 two types of magics we support. Each value is a dict keyed by magic
341 two types of magics we support. Each value is a dict keyed by magic
343 name whose value is the function docstring. If a docstring is
342 name whose value is the function docstring. If a docstring is
344 unavailable, the value of `missing` is used instead.
343 unavailable, the value of `missing` is used instead.
345
344
346 If brief is True, only the first line of each docstring will be returned.
345 If brief is True, only the first line of each docstring will be returned.
347 """
346 """
348 docs = {}
347 docs = {}
349 for m_type in self.magics:
348 for m_type in self.magics:
350 m_docs = {}
349 m_docs = {}
351 for m_name, m_func in self.magics[m_type].iteritems():
350 for m_name, m_func in self.magics[m_type].iteritems():
352 if m_func.__doc__:
351 if m_func.__doc__:
353 if brief:
352 if brief:
354 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
353 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
355 else:
354 else:
356 m_docs[m_name] = m_func.__doc__.rstrip()
355 m_docs[m_name] = m_func.__doc__.rstrip()
357 else:
356 else:
358 m_docs[m_name] = missing
357 m_docs[m_name] = missing
359 docs[m_type] = m_docs
358 docs[m_type] = m_docs
360 return docs
359 return docs
361
360
362 def register(self, *magic_objects):
361 def register(self, *magic_objects):
363 """Register one or more instances of Magics.
362 """Register one or more instances of Magics.
364
363
365 Take one or more classes or instances of classes that subclass the main
364 Take one or more classes or instances of classes that subclass the main
366 `core.Magic` class, and register them with IPython to use the magic
365 `core.Magic` class, and register them with IPython to use the magic
367 functions they provide. The registration process will then ensure that
366 functions they provide. The registration process will then ensure that
368 any methods that have decorated to provide line and/or cell magics will
367 any methods that have decorated to provide line and/or cell magics will
369 be recognized with the `%x`/`%%x` syntax as a line/cell magic
368 be recognized with the `%x`/`%%x` syntax as a line/cell magic
370 respectively.
369 respectively.
371
370
372 If classes are given, they will be instantiated with the default
371 If classes are given, they will be instantiated with the default
373 constructor. If your classes need a custom constructor, you should
372 constructor. If your classes need a custom constructor, you should
374 instanitate them first and pass the instance.
373 instanitate them first and pass the instance.
375
374
376 The provided arguments can be an arbitrary mix of classes and instances.
375 The provided arguments can be an arbitrary mix of classes and instances.
377
376
378 Parameters
377 Parameters
379 ----------
378 ----------
380 magic_objects : one or more classes or instances
379 magic_objects : one or more classes or instances
381 """
380 """
382 # Start by validating them to ensure they have all had their magic
381 # Start by validating them to ensure they have all had their magic
383 # methods registered at the instance level
382 # methods registered at the instance level
384 for m in magic_objects:
383 for m in magic_objects:
385 if not m.registered:
384 if not m.registered:
386 raise ValueError("Class of magics %r was constructed without "
385 raise ValueError("Class of magics %r was constructed without "
387 "the @register_magics class decorator")
386 "the @register_magics class decorator")
388 if type(m) in (type, MetaHasTraits):
387 if type(m) in (type, MetaHasTraits):
389 # If we're given an uninstantiated class
388 # If we're given an uninstantiated class
390 m = m(shell=self.shell)
389 m = m(shell=self.shell)
391
390
392 # Now that we have an instance, we can register it and update the
391 # Now that we have an instance, we can register it and update the
393 # table of callables
392 # table of callables
394 self.registry[m.__class__.__name__] = m
393 self.registry[m.__class__.__name__] = m
395 for mtype in magic_kinds:
394 for mtype in magic_kinds:
396 self.magics[mtype].update(m.magics[mtype])
395 self.magics[mtype].update(m.magics[mtype])
397
396
398 def register_function(self, func, magic_kind='line', magic_name=None):
397 def register_function(self, func, magic_kind='line', magic_name=None):
399 """Expose a standalone function as magic function for IPython.
398 """Expose a standalone function as magic function for IPython.
400
399
401 This will create an IPython magic (line, cell or both) from a
400 This will create an IPython magic (line, cell or both) from a
402 standalone function. The functions should have the following
401 standalone function. The functions should have the following
403 signatures:
402 signatures:
404
403
405 * For line magics: `def f(line)`
404 * For line magics: `def f(line)`
406 * For cell magics: `def f(line, cell)`
405 * For cell magics: `def f(line, cell)`
407 * For a function that does both: `def f(line, cell=None)`
406 * For a function that does both: `def f(line, cell=None)`
408
407
409 In the latter case, the function will be called with `cell==None` when
408 In the latter case, the function will be called with `cell==None` when
410 invoked as `%f`, and with cell as a string when invoked as `%%f`.
409 invoked as `%f`, and with cell as a string when invoked as `%%f`.
411
410
412 Parameters
411 Parameters
413 ----------
412 ----------
414 func : callable
413 func : callable
415 Function to be registered as a magic.
414 Function to be registered as a magic.
416
415
417 magic_kind : str
416 magic_kind : str
418 Kind of magic, one of 'line', 'cell' or 'line_cell'
417 Kind of magic, one of 'line', 'cell' or 'line_cell'
419
418
420 magic_name : optional str
419 magic_name : optional str
421 If given, the name the magic will have in the IPython namespace. By
420 If given, the name the magic will have in the IPython namespace. By
422 default, the name of the function itself is used.
421 default, the name of the function itself is used.
423 """
422 """
424
423
425 # Create the new method in the user_magics and register it in the
424 # Create the new method in the user_magics and register it in the
426 # global table
425 # global table
427 validate_type(magic_kind)
426 validate_type(magic_kind)
428 magic_name = func.func_name if magic_name is None else magic_name
427 magic_name = func.func_name if magic_name is None else magic_name
429 setattr(self.user_magics, magic_name, func)
428 setattr(self.user_magics, magic_name, func)
430 record_magic(self.magics, magic_kind, magic_name, func)
429 record_magic(self.magics, magic_kind, magic_name, func)
431
430
432 def define_magic(self, name, func):
431 def define_magic(self, name, func):
433 """[Deprecated] Expose own function as magic function for IPython.
432 """[Deprecated] Expose own function as magic function for IPython.
434
433
435 Example::
434 Example::
436
435
437 def foo_impl(self, parameter_s=''):
436 def foo_impl(self, parameter_s=''):
438 'My very own magic!. (Use docstrings, IPython reads them).'
437 'My very own magic!. (Use docstrings, IPython reads them).'
439 print 'Magic function. Passed parameter is between < >:'
438 print 'Magic function. Passed parameter is between < >:'
440 print '<%s>' % parameter_s
439 print '<%s>' % parameter_s
441 print 'The self object is:', self
440 print 'The self object is:', self
442
441
443 ip.define_magic('foo',foo_impl)
442 ip.define_magic('foo',foo_impl)
444 """
443 """
445 meth = types.MethodType(func, self.user_magics)
444 meth = types.MethodType(func, self.user_magics)
446 setattr(self.user_magics, name, meth)
445 setattr(self.user_magics, name, meth)
447 record_magic(self.magics, 'line', name, meth)
446 record_magic(self.magics, 'line', name, meth)
448
447
449 def register_alias(self, alias_name, magic_name, magic_kind='line'):
448 def register_alias(self, alias_name, magic_name, magic_kind='line'):
450 """Register an alias to a magic function.
449 """Register an alias to a magic function.
451
450
452 The alias is an instance of :class:`MagicAlias`, which holds the
451 The alias is an instance of :class:`MagicAlias`, which holds the
453 name and kind of the magic it should call. Binding is done at
452 name and kind of the magic it should call. Binding is done at
454 call time, so if the underlying magic function is changed the alias
453 call time, so if the underlying magic function is changed the alias
455 will call the new function.
454 will call the new function.
456
455
457 Parameters
456 Parameters
458 ----------
457 ----------
459 alias_name : str
458 alias_name : str
460 The name of the magic to be registered.
459 The name of the magic to be registered.
461
460
462 magic_name : str
461 magic_name : str
463 The name of an existing magic.
462 The name of an existing magic.
464
463
465 magic_kind : str
464 magic_kind : str
466 Kind of magic, one of 'line' or 'cell'
465 Kind of magic, one of 'line' or 'cell'
467 """
466 """
468
467
469 # `validate_type` is too permissive, as it allows 'line_cell'
468 # `validate_type` is too permissive, as it allows 'line_cell'
470 # which we do not handle.
469 # which we do not handle.
471 if magic_kind not in magic_kinds:
470 if magic_kind not in magic_kinds:
472 raise ValueError('magic_kind must be one of %s, %s given' %
471 raise ValueError('magic_kind must be one of %s, %s given' %
473 magic_kinds, magic_kind)
472 magic_kinds, magic_kind)
474
473
475 alias = MagicAlias(self.shell, magic_name, magic_kind)
474 alias = MagicAlias(self.shell, magic_name, magic_kind)
476 setattr(self.user_magics, alias_name, alias)
475 setattr(self.user_magics, alias_name, alias)
477 record_magic(self.magics, magic_kind, alias_name, alias)
476 record_magic(self.magics, magic_kind, alias_name, alias)
478
477
479 # Key base class that provides the central functionality for magics.
478 # Key base class that provides the central functionality for magics.
480
479
481 class Magics(object):
480 class Magics(object):
482 """Base class for implementing magic functions.
481 """Base class for implementing magic functions.
483
482
484 Shell functions which can be reached as %function_name. All magic
483 Shell functions which can be reached as %function_name. All magic
485 functions should accept a string, which they can parse for their own
484 functions should accept a string, which they can parse for their own
486 needs. This can make some functions easier to type, eg `%cd ../`
485 needs. This can make some functions easier to type, eg `%cd ../`
487 vs. `%cd("../")`
486 vs. `%cd("../")`
488
487
489 Classes providing magic functions need to subclass this class, and they
488 Classes providing magic functions need to subclass this class, and they
490 MUST:
489 MUST:
491
490
492 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
491 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
493 individual methods as magic functions, AND
492 individual methods as magic functions, AND
494
493
495 - Use the class decorator `@magics_class` to ensure that the magic
494 - Use the class decorator `@magics_class` to ensure that the magic
496 methods are properly registered at the instance level upon instance
495 methods are properly registered at the instance level upon instance
497 initialization.
496 initialization.
498
497
499 See :mod:`magic_functions` for examples of actual implementation classes.
498 See :mod:`magic_functions` for examples of actual implementation classes.
500 """
499 """
501 # Dict holding all command-line options for each magic.
500 # Dict holding all command-line options for each magic.
502 options_table = None
501 options_table = None
503 # Dict for the mapping of magic names to methods, set by class decorator
502 # Dict for the mapping of magic names to methods, set by class decorator
504 magics = None
503 magics = None
505 # Flag to check that the class decorator was properly applied
504 # Flag to check that the class decorator was properly applied
506 registered = False
505 registered = False
507 # Instance of IPython shell
506 # Instance of IPython shell
508 shell = None
507 shell = None
509
508
510 def __init__(self, shell):
509 def __init__(self, shell):
511 if not(self.__class__.registered):
510 if not(self.__class__.registered):
512 raise ValueError('Magics subclass without registration - '
511 raise ValueError('Magics subclass without registration - '
513 'did you forget to apply @magics_class?')
512 'did you forget to apply @magics_class?')
514 self.shell = shell
513 self.shell = shell
515 self.options_table = {}
514 self.options_table = {}
516 # The method decorators are run when the instance doesn't exist yet, so
515 # The method decorators are run when the instance doesn't exist yet, so
517 # they can only record the names of the methods they are supposed to
516 # they can only record the names of the methods they are supposed to
518 # grab. Only now, that the instance exists, can we create the proper
517 # grab. Only now, that the instance exists, can we create the proper
519 # mapping to bound methods. So we read the info off the original names
518 # mapping to bound methods. So we read the info off the original names
520 # table and replace each method name by the actual bound method.
519 # table and replace each method name by the actual bound method.
521 # But we mustn't clobber the *class* mapping, in case of multiple instances.
520 # But we mustn't clobber the *class* mapping, in case of multiple instances.
522 class_magics = self.magics
521 class_magics = self.magics
523 self.magics = {}
522 self.magics = {}
524 for mtype in magic_kinds:
523 for mtype in magic_kinds:
525 tab = self.magics[mtype] = {}
524 tab = self.magics[mtype] = {}
526 cls_tab = class_magics[mtype]
525 cls_tab = class_magics[mtype]
527 for magic_name, meth_name in cls_tab.iteritems():
526 for magic_name, meth_name in cls_tab.iteritems():
528 if isinstance(meth_name, basestring):
527 if isinstance(meth_name, basestring):
529 # it's a method name, grab it
528 # it's a method name, grab it
530 tab[magic_name] = getattr(self, meth_name)
529 tab[magic_name] = getattr(self, meth_name)
531 else:
530 else:
532 # it's the real thing
531 # it's the real thing
533 tab[magic_name] = meth_name
532 tab[magic_name] = meth_name
534
533
535 def arg_err(self,func):
534 def arg_err(self,func):
536 """Print docstring if incorrect arguments were passed"""
535 """Print docstring if incorrect arguments were passed"""
537 print 'Error in arguments:'
536 print 'Error in arguments:'
538 print oinspect.getdoc(func)
537 print oinspect.getdoc(func)
539
538
540 def format_latex(self, strng):
539 def format_latex(self, strng):
541 """Format a string for latex inclusion."""
540 """Format a string for latex inclusion."""
542
541
543 # Characters that need to be escaped for latex:
542 # Characters that need to be escaped for latex:
544 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
543 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
545 # Magic command names as headers:
544 # Magic command names as headers:
546 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
545 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
547 re.MULTILINE)
546 re.MULTILINE)
548 # Magic commands
547 # Magic commands
549 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
548 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
550 re.MULTILINE)
549 re.MULTILINE)
551 # Paragraph continue
550 # Paragraph continue
552 par_re = re.compile(r'\\$',re.MULTILINE)
551 par_re = re.compile(r'\\$',re.MULTILINE)
553
552
554 # The "\n" symbol
553 # The "\n" symbol
555 newline_re = re.compile(r'\\n')
554 newline_re = re.compile(r'\\n')
556
555
557 # Now build the string for output:
556 # Now build the string for output:
558 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
557 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
559 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
558 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
560 strng)
559 strng)
561 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
560 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
562 strng = par_re.sub(r'\\\\',strng)
561 strng = par_re.sub(r'\\\\',strng)
563 strng = escape_re.sub(r'\\\1',strng)
562 strng = escape_re.sub(r'\\\1',strng)
564 strng = newline_re.sub(r'\\textbackslash{}n',strng)
563 strng = newline_re.sub(r'\\textbackslash{}n',strng)
565 return strng
564 return strng
566
565
567 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
566 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
568 """Parse options passed to an argument string.
567 """Parse options passed to an argument string.
569
568
570 The interface is similar to that of getopt(), but it returns back a
569 The interface is similar to that of getopt(), but it returns back a
571 Struct with the options as keys and the stripped argument string still
570 Struct with the options as keys and the stripped argument string still
572 as a string.
571 as a string.
573
572
574 arg_str is quoted as a true sys.argv vector by using shlex.split.
573 arg_str is quoted as a true sys.argv vector by using shlex.split.
575 This allows us to easily expand variables, glob files, quote
574 This allows us to easily expand variables, glob files, quote
576 arguments, etc.
575 arguments, etc.
577
576
578 Options:
577 Options:
579 -mode: default 'string'. If given as 'list', the argument string is
578 -mode: default 'string'. If given as 'list', the argument string is
580 returned as a list (split on whitespace) instead of a string.
579 returned as a list (split on whitespace) instead of a string.
581
580
582 -list_all: put all option values in lists. Normally only options
581 -list_all: put all option values in lists. Normally only options
583 appearing more than once are put in a list.
582 appearing more than once are put in a list.
584
583
585 -posix (True): whether to split the input line in POSIX mode or not,
584 -posix (True): whether to split the input line in POSIX mode or not,
586 as per the conventions outlined in the shlex module from the
585 as per the conventions outlined in the shlex module from the
587 standard library."""
586 standard library."""
588
587
589 # inject default options at the beginning of the input line
588 # inject default options at the beginning of the input line
590 caller = sys._getframe(1).f_code.co_name
589 caller = sys._getframe(1).f_code.co_name
591 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
590 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
592
591
593 mode = kw.get('mode','string')
592 mode = kw.get('mode','string')
594 if mode not in ['string','list']:
593 if mode not in ['string','list']:
595 raise ValueError('incorrect mode given: %s' % mode)
594 raise ValueError('incorrect mode given: %s' % mode)
596 # Get options
595 # Get options
597 list_all = kw.get('list_all',0)
596 list_all = kw.get('list_all',0)
598 posix = kw.get('posix', os.name == 'posix')
597 posix = kw.get('posix', os.name == 'posix')
599 strict = kw.get('strict', True)
598 strict = kw.get('strict', True)
600
599
601 # Check if we have more than one argument to warrant extra processing:
600 # Check if we have more than one argument to warrant extra processing:
602 odict = {} # Dictionary with options
601 odict = {} # Dictionary with options
603 args = arg_str.split()
602 args = arg_str.split()
604 if len(args) >= 1:
603 if len(args) >= 1:
605 # If the list of inputs only has 0 or 1 thing in it, there's no
604 # If the list of inputs only has 0 or 1 thing in it, there's no
606 # need to look for options
605 # need to look for options
607 argv = arg_split(arg_str, posix, strict)
606 argv = arg_split(arg_str, posix, strict)
608 # Do regular option processing
607 # Do regular option processing
609 try:
608 try:
610 opts,args = getopt(argv, opt_str, long_opts)
609 opts,args = getopt(argv, opt_str, long_opts)
611 except GetoptError as e:
610 except GetoptError as e:
612 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
611 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
613 " ".join(long_opts)))
612 " ".join(long_opts)))
614 for o,a in opts:
613 for o,a in opts:
615 if o.startswith('--'):
614 if o.startswith('--'):
616 o = o[2:]
615 o = o[2:]
617 else:
616 else:
618 o = o[1:]
617 o = o[1:]
619 try:
618 try:
620 odict[o].append(a)
619 odict[o].append(a)
621 except AttributeError:
620 except AttributeError:
622 odict[o] = [odict[o],a]
621 odict[o] = [odict[o],a]
623 except KeyError:
622 except KeyError:
624 if list_all:
623 if list_all:
625 odict[o] = [a]
624 odict[o] = [a]
626 else:
625 else:
627 odict[o] = a
626 odict[o] = a
628
627
629 # Prepare opts,args for return
628 # Prepare opts,args for return
630 opts = Struct(odict)
629 opts = Struct(odict)
631 if mode == 'string':
630 if mode == 'string':
632 args = ' '.join(args)
631 args = ' '.join(args)
633
632
634 return opts,args
633 return opts,args
635
634
636 def default_option(self, fn, optstr):
635 def default_option(self, fn, optstr):
637 """Make an entry in the options_table for fn, with value optstr"""
636 """Make an entry in the options_table for fn, with value optstr"""
638
637
639 if fn not in self.lsmagic():
638 if fn not in self.lsmagic():
640 error("%s is not a magic function" % fn)
639 error("%s is not a magic function" % fn)
641 self.options_table[fn] = optstr
640 self.options_table[fn] = optstr
642
641
643 class MagicAlias(object):
642 class MagicAlias(object):
644 """An alias to another magic function.
643 """An alias to another magic function.
645
644
646 An alias is determined by its magic name and magic kind. Lookup
645 An alias is determined by its magic name and magic kind. Lookup
647 is done at call time, so if the underlying magic changes the alias
646 is done at call time, so if the underlying magic changes the alias
648 will call the new function.
647 will call the new function.
649
648
650 Use the :meth:`MagicsManager.register_alias` method or the
649 Use the :meth:`MagicsManager.register_alias` method or the
651 `%alias_magic` magic function to create and register a new alias.
650 `%alias_magic` magic function to create and register a new alias.
652 """
651 """
653 def __init__(self, shell, magic_name, magic_kind):
652 def __init__(self, shell, magic_name, magic_kind):
654 self.shell = shell
653 self.shell = shell
655 self.magic_name = magic_name
654 self.magic_name = magic_name
656 self.magic_kind = magic_kind
655 self.magic_kind = magic_kind
657
656
658 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
657 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
659 self.__doc__ = "Alias for `%s`." % self.pretty_target
658 self.__doc__ = "Alias for `%s`." % self.pretty_target
660
659
661 self._in_call = False
660 self._in_call = False
662
661
663 def __call__(self, *args, **kwargs):
662 def __call__(self, *args, **kwargs):
664 """Call the magic alias."""
663 """Call the magic alias."""
665 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
664 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
666 if fn is None:
665 if fn is None:
667 raise UsageError("Magic `%s` not found." % self.pretty_target)
666 raise UsageError("Magic `%s` not found." % self.pretty_target)
668
667
669 # Protect against infinite recursion.
668 # Protect against infinite recursion.
670 if self._in_call:
669 if self._in_call:
671 raise UsageError("Infinite recursion detected; "
670 raise UsageError("Infinite recursion detected; "
672 "magic aliases cannot call themselves.")
671 "magic aliases cannot call themselves.")
673 self._in_call = True
672 self._in_call = True
674 try:
673 try:
675 return fn(*args, **kwargs)
674 return fn(*args, **kwargs)
676 finally:
675 finally:
677 self._in_call = False
676 self._in_call = False
@@ -1,648 +1,647 b''
1 """Implementation of basic magic functions.
1 """Implementation of basic 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 from __future__ import print_function
14 from __future__ import print_function
15
15
16 # Stdlib
16 # Stdlib
17 import io
17 import io
18 import json
18 import json
19 import sys
19 import sys
20 from pprint import pformat
20 from pprint import pformat
21
21
22 # Our own packages
22 # Our own packages
23 from IPython.core import magic_arguments
23 from IPython.core import magic_arguments, page
24 from IPython.core.error import UsageError
24 from IPython.core.error import UsageError
25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
26 from IPython.utils.text import format_screen, dedent, indent
26 from IPython.utils.text import format_screen, dedent, indent
27 from IPython.core import magic_arguments, page
28 from IPython.testing.skipdoctest import skip_doctest
27 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.utils.ipstruct import Struct
28 from IPython.utils.ipstruct import Struct
30 from IPython.utils.path import unquote_filename
29 from IPython.utils.path import unquote_filename
31 from IPython.utils.warn import warn, error
30 from IPython.utils.warn import warn, error
32
31
33 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
34 # Magics class implementation
33 # Magics class implementation
35 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
36
35
37 class MagicsDisplay(object):
36 class MagicsDisplay(object):
38 def __init__(self, magics_manager):
37 def __init__(self, magics_manager):
39 self.magics_manager = magics_manager
38 self.magics_manager = magics_manager
40
39
41 def _lsmagic(self):
40 def _lsmagic(self):
42 """The main implementation of the %lsmagic"""
41 """The main implementation of the %lsmagic"""
43 mesc = magic_escapes['line']
42 mesc = magic_escapes['line']
44 cesc = magic_escapes['cell']
43 cesc = magic_escapes['cell']
45 mman = self.magics_manager
44 mman = self.magics_manager
46 magics = mman.lsmagic()
45 magics = mman.lsmagic()
47 out = ['Available line magics:',
46 out = ['Available line magics:',
48 mesc + (' '+mesc).join(sorted(magics['line'])),
47 mesc + (' '+mesc).join(sorted(magics['line'])),
49 '',
48 '',
50 'Available cell magics:',
49 'Available cell magics:',
51 cesc + (' '+cesc).join(sorted(magics['cell'])),
50 cesc + (' '+cesc).join(sorted(magics['cell'])),
52 '',
51 '',
53 mman.auto_status()]
52 mman.auto_status()]
54 return '\n'.join(out)
53 return '\n'.join(out)
55
54
56 def _repr_pretty_(self, p, cycle):
55 def _repr_pretty_(self, p, cycle):
57 p.text(self._lsmagic())
56 p.text(self._lsmagic())
58
57
59 def __str__(self):
58 def __str__(self):
60 return self._lsmagic()
59 return self._lsmagic()
61
60
62 def _jsonable(self):
61 def _jsonable(self):
63 """turn magics dict into jsonable dict of the same structure
62 """turn magics dict into jsonable dict of the same structure
64
63
65 replaces object instances with their class names as strings
64 replaces object instances with their class names as strings
66 """
65 """
67 magic_dict = {}
66 magic_dict = {}
68 mman = self.magics_manager
67 mman = self.magics_manager
69 magics = mman.lsmagic()
68 magics = mman.lsmagic()
70 for key, subdict in magics.items():
69 for key, subdict in magics.items():
71 d = {}
70 d = {}
72 magic_dict[key] = d
71 magic_dict[key] = d
73 for name, obj in subdict.items():
72 for name, obj in subdict.items():
74 try:
73 try:
75 classname = obj.im_class.__name__
74 classname = obj.im_class.__name__
76 except AttributeError:
75 except AttributeError:
77 classname = 'Other'
76 classname = 'Other'
78
77
79 d[name] = classname
78 d[name] = classname
80 return magic_dict
79 return magic_dict
81
80
82 def _repr_json_(self):
81 def _repr_json_(self):
83 return json.dumps(self._jsonable())
82 return json.dumps(self._jsonable())
84
83
85
84
86 @magics_class
85 @magics_class
87 class BasicMagics(Magics):
86 class BasicMagics(Magics):
88 """Magics that provide central IPython functionality.
87 """Magics that provide central IPython functionality.
89
88
90 These are various magics that don't fit into specific categories but that
89 These are various magics that don't fit into specific categories but that
91 are all part of the base 'IPython experience'."""
90 are all part of the base 'IPython experience'."""
92
91
93 @magic_arguments.magic_arguments()
92 @magic_arguments.magic_arguments()
94 @magic_arguments.argument(
93 @magic_arguments.argument(
95 '-l', '--line', action='store_true',
94 '-l', '--line', action='store_true',
96 help="""Create a line magic alias."""
95 help="""Create a line magic alias."""
97 )
96 )
98 @magic_arguments.argument(
97 @magic_arguments.argument(
99 '-c', '--cell', action='store_true',
98 '-c', '--cell', action='store_true',
100 help="""Create a cell magic alias."""
99 help="""Create a cell magic alias."""
101 )
100 )
102 @magic_arguments.argument(
101 @magic_arguments.argument(
103 'name',
102 'name',
104 help="""Name of the magic to be created."""
103 help="""Name of the magic to be created."""
105 )
104 )
106 @magic_arguments.argument(
105 @magic_arguments.argument(
107 'target',
106 'target',
108 help="""Name of the existing line or cell magic."""
107 help="""Name of the existing line or cell magic."""
109 )
108 )
110 @line_magic
109 @line_magic
111 def alias_magic(self, line=''):
110 def alias_magic(self, line=''):
112 """Create an alias for an existing line or cell magic.
111 """Create an alias for an existing line or cell magic.
113
112
114 Examples
113 Examples
115 --------
114 --------
116 ::
115 ::
117 In [1]: %alias_magic t timeit
116 In [1]: %alias_magic t timeit
118 Created `%t` as an alias for `%timeit`.
117 Created `%t` as an alias for `%timeit`.
119 Created `%%t` as an alias for `%%timeit`.
118 Created `%%t` as an alias for `%%timeit`.
120
119
121 In [2]: %t -n1 pass
120 In [2]: %t -n1 pass
122 1 loops, best of 3: 954 ns per loop
121 1 loops, best of 3: 954 ns per loop
123
122
124 In [3]: %%t -n1
123 In [3]: %%t -n1
125 ...: pass
124 ...: pass
126 ...:
125 ...:
127 1 loops, best of 3: 954 ns per loop
126 1 loops, best of 3: 954 ns per loop
128
127
129 In [4]: %alias_magic --cell whereami pwd
128 In [4]: %alias_magic --cell whereami pwd
130 UsageError: Cell magic function `%%pwd` not found.
129 UsageError: Cell magic function `%%pwd` not found.
131 In [5]: %alias_magic --line whereami pwd
130 In [5]: %alias_magic --line whereami pwd
132 Created `%whereami` as an alias for `%pwd`.
131 Created `%whereami` as an alias for `%pwd`.
133
132
134 In [6]: %whereami
133 In [6]: %whereami
135 Out[6]: u'/home/testuser'
134 Out[6]: u'/home/testuser'
136 """
135 """
137 args = magic_arguments.parse_argstring(self.alias_magic, line)
136 args = magic_arguments.parse_argstring(self.alias_magic, line)
138 shell = self.shell
137 shell = self.shell
139 mman = self.shell.magics_manager
138 mman = self.shell.magics_manager
140 escs = ''.join(magic_escapes.values())
139 escs = ''.join(magic_escapes.values())
141
140
142 target = args.target.lstrip(escs)
141 target = args.target.lstrip(escs)
143 name = args.name.lstrip(escs)
142 name = args.name.lstrip(escs)
144
143
145 # Find the requested magics.
144 # Find the requested magics.
146 m_line = shell.find_magic(target, 'line')
145 m_line = shell.find_magic(target, 'line')
147 m_cell = shell.find_magic(target, 'cell')
146 m_cell = shell.find_magic(target, 'cell')
148 if args.line and m_line is None:
147 if args.line and m_line is None:
149 raise UsageError('Line magic function `%s%s` not found.' %
148 raise UsageError('Line magic function `%s%s` not found.' %
150 (magic_escapes['line'], target))
149 (magic_escapes['line'], target))
151 if args.cell and m_cell is None:
150 if args.cell and m_cell is None:
152 raise UsageError('Cell magic function `%s%s` not found.' %
151 raise UsageError('Cell magic function `%s%s` not found.' %
153 (magic_escapes['cell'], target))
152 (magic_escapes['cell'], target))
154
153
155 # If --line and --cell are not specified, default to the ones
154 # If --line and --cell are not specified, default to the ones
156 # that are available.
155 # that are available.
157 if not args.line and not args.cell:
156 if not args.line and not args.cell:
158 if not m_line and not m_cell:
157 if not m_line and not m_cell:
159 raise UsageError(
158 raise UsageError(
160 'No line or cell magic with name `%s` found.' % target
159 'No line or cell magic with name `%s` found.' % target
161 )
160 )
162 args.line = bool(m_line)
161 args.line = bool(m_line)
163 args.cell = bool(m_cell)
162 args.cell = bool(m_cell)
164
163
165 if args.line:
164 if args.line:
166 mman.register_alias(name, target, 'line')
165 mman.register_alias(name, target, 'line')
167 print('Created `%s%s` as an alias for `%s%s`.' % (
166 print('Created `%s%s` as an alias for `%s%s`.' % (
168 magic_escapes['line'], name,
167 magic_escapes['line'], name,
169 magic_escapes['line'], target))
168 magic_escapes['line'], target))
170
169
171 if args.cell:
170 if args.cell:
172 mman.register_alias(name, target, 'cell')
171 mman.register_alias(name, target, 'cell')
173 print('Created `%s%s` as an alias for `%s%s`.' % (
172 print('Created `%s%s` as an alias for `%s%s`.' % (
174 magic_escapes['cell'], name,
173 magic_escapes['cell'], name,
175 magic_escapes['cell'], target))
174 magic_escapes['cell'], target))
176
175
177 @line_magic
176 @line_magic
178 def lsmagic(self, parameter_s=''):
177 def lsmagic(self, parameter_s=''):
179 """List currently available magic functions."""
178 """List currently available magic functions."""
180 return MagicsDisplay(self.shell.magics_manager)
179 return MagicsDisplay(self.shell.magics_manager)
181
180
182 def _magic_docs(self, brief=False, rest=False):
181 def _magic_docs(self, brief=False, rest=False):
183 """Return docstrings from magic functions."""
182 """Return docstrings from magic functions."""
184 mman = self.shell.magics_manager
183 mman = self.shell.magics_manager
185 docs = mman.lsmagic_docs(brief, missing='No documentation')
184 docs = mman.lsmagic_docs(brief, missing='No documentation')
186
185
187 if rest:
186 if rest:
188 format_string = '**%s%s**::\n\n%s\n\n'
187 format_string = '**%s%s**::\n\n%s\n\n'
189 else:
188 else:
190 format_string = '%s%s:\n%s\n'
189 format_string = '%s%s:\n%s\n'
191
190
192 return ''.join(
191 return ''.join(
193 [format_string % (magic_escapes['line'], fname,
192 [format_string % (magic_escapes['line'], fname,
194 indent(dedent(fndoc)))
193 indent(dedent(fndoc)))
195 for fname, fndoc in sorted(docs['line'].items())]
194 for fname, fndoc in sorted(docs['line'].items())]
196 +
195 +
197 [format_string % (magic_escapes['cell'], fname,
196 [format_string % (magic_escapes['cell'], fname,
198 indent(dedent(fndoc)))
197 indent(dedent(fndoc)))
199 for fname, fndoc in sorted(docs['cell'].items())]
198 for fname, fndoc in sorted(docs['cell'].items())]
200 )
199 )
201
200
202 @line_magic
201 @line_magic
203 def magic(self, parameter_s=''):
202 def magic(self, parameter_s=''):
204 """Print information about the magic function system.
203 """Print information about the magic function system.
205
204
206 Supported formats: -latex, -brief, -rest
205 Supported formats: -latex, -brief, -rest
207 """
206 """
208
207
209 mode = ''
208 mode = ''
210 try:
209 try:
211 mode = parameter_s.split()[0][1:]
210 mode = parameter_s.split()[0][1:]
212 if mode == 'rest':
211 if mode == 'rest':
213 rest_docs = []
212 rest_docs = []
214 except IndexError:
213 except IndexError:
215 pass
214 pass
216
215
217 brief = (mode == 'brief')
216 brief = (mode == 'brief')
218 rest = (mode == 'rest')
217 rest = (mode == 'rest')
219 magic_docs = self._magic_docs(brief, rest)
218 magic_docs = self._magic_docs(brief, rest)
220
219
221 if mode == 'latex':
220 if mode == 'latex':
222 print(self.format_latex(magic_docs))
221 print(self.format_latex(magic_docs))
223 return
222 return
224 else:
223 else:
225 magic_docs = format_screen(magic_docs)
224 magic_docs = format_screen(magic_docs)
226
225
227 out = ["""
226 out = ["""
228 IPython's 'magic' functions
227 IPython's 'magic' functions
229 ===========================
228 ===========================
230
229
231 The magic function system provides a series of functions which allow you to
230 The magic function system provides a series of functions which allow you to
232 control the behavior of IPython itself, plus a lot of system-type
231 control the behavior of IPython itself, plus a lot of system-type
233 features. There are two kinds of magics, line-oriented and cell-oriented.
232 features. There are two kinds of magics, line-oriented and cell-oriented.
234
233
235 Line magics are prefixed with the % character and work much like OS
234 Line magics are prefixed with the % character and work much like OS
236 command-line calls: they get as an argument the rest of the line, where
235 command-line calls: they get as an argument the rest of the line, where
237 arguments are passed without parentheses or quotes. For example, this will
236 arguments are passed without parentheses or quotes. For example, this will
238 time the given statement::
237 time the given statement::
239
238
240 %timeit range(1000)
239 %timeit range(1000)
241
240
242 Cell magics are prefixed with a double %%, and they are functions that get as
241 Cell magics are prefixed with a double %%, and they are functions that get as
243 an argument not only the rest of the line, but also the lines below it in a
242 an argument not only the rest of the line, but also the lines below it in a
244 separate argument. These magics are called with two arguments: the rest of the
243 separate argument. These magics are called with two arguments: the rest of the
245 call line and the body of the cell, consisting of the lines below the first.
244 call line and the body of the cell, consisting of the lines below the first.
246 For example::
245 For example::
247
246
248 %%timeit x = numpy.random.randn((100, 100))
247 %%timeit x = numpy.random.randn((100, 100))
249 numpy.linalg.svd(x)
248 numpy.linalg.svd(x)
250
249
251 will time the execution of the numpy svd routine, running the assignment of x
250 will time the execution of the numpy svd routine, running the assignment of x
252 as part of the setup phase, which is not timed.
251 as part of the setup phase, which is not timed.
253
252
254 In a line-oriented client (the terminal or Qt console IPython), starting a new
253 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 input with %% will automatically enter cell mode, and IPython will continue
254 input with %% will automatically enter cell mode, and IPython will continue
256 reading input until a blank line is given. In the notebook, simply type the
255 reading input until a blank line is given. In the notebook, simply type the
257 whole cell as one entity, but keep in mind that the %% escape can only be at
256 whole cell as one entity, but keep in mind that the %% escape can only be at
258 the very start of the cell.
257 the very start of the cell.
259
258
260 NOTE: If you have 'automagic' enabled (via the command line option or with the
259 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 %automagic function), you don't need to type in the % explicitly for line
260 %automagic function), you don't need to type in the % explicitly for line
262 magics; cell magics always require an explicit '%%' escape. By default,
261 magics; cell magics always require an explicit '%%' escape. By default,
263 IPython ships with automagic on, so you should only rarely need the % escape.
262 IPython ships with automagic on, so you should only rarely need the % escape.
264
263
265 Example: typing '%cd mydir' (without the quotes) changes you working directory
264 Example: typing '%cd mydir' (without the quotes) changes you working directory
266 to 'mydir', if it exists.
265 to 'mydir', if it exists.
267
266
268 For a list of the available magic functions, use %lsmagic. For a description
267 For a list of the available magic functions, use %lsmagic. For a description
269 of any of them, type %magic_name?, e.g. '%cd?'.
268 of any of them, type %magic_name?, e.g. '%cd?'.
270
269
271 Currently the magic system has the following functions:""",
270 Currently the magic system has the following functions:""",
272 magic_docs,
271 magic_docs,
273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
272 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 str(self.lsmagic()),
273 str(self.lsmagic()),
275 ]
274 ]
276 page.page('\n'.join(out))
275 page.page('\n'.join(out))
277
276
278
277
279 @line_magic
278 @line_magic
280 def page(self, parameter_s=''):
279 def page(self, parameter_s=''):
281 """Pretty print the object and display it through a pager.
280 """Pretty print the object and display it through a pager.
282
281
283 %page [options] OBJECT
282 %page [options] OBJECT
284
283
285 If no object is given, use _ (last output).
284 If no object is given, use _ (last output).
286
285
287 Options:
286 Options:
288
287
289 -r: page str(object), don't pretty-print it."""
288 -r: page str(object), don't pretty-print it."""
290
289
291 # After a function contributed by Olivier Aubert, slightly modified.
290 # After a function contributed by Olivier Aubert, slightly modified.
292
291
293 # Process options/args
292 # Process options/args
294 opts, args = self.parse_options(parameter_s, 'r')
293 opts, args = self.parse_options(parameter_s, 'r')
295 raw = 'r' in opts
294 raw = 'r' in opts
296
295
297 oname = args and args or '_'
296 oname = args and args or '_'
298 info = self.shell._ofind(oname)
297 info = self.shell._ofind(oname)
299 if info['found']:
298 if info['found']:
300 txt = (raw and str or pformat)( info['obj'] )
299 txt = (raw and str or pformat)( info['obj'] )
301 page.page(txt)
300 page.page(txt)
302 else:
301 else:
303 print('Object `%s` not found' % oname)
302 print('Object `%s` not found' % oname)
304
303
305 @line_magic
304 @line_magic
306 def profile(self, parameter_s=''):
305 def profile(self, parameter_s=''):
307 """Print your currently active IPython profile."""
306 """Print your currently active IPython profile."""
308 from IPython.core.application import BaseIPythonApplication
307 from IPython.core.application import BaseIPythonApplication
309 if BaseIPythonApplication.initialized():
308 if BaseIPythonApplication.initialized():
310 print(BaseIPythonApplication.instance().profile)
309 print(BaseIPythonApplication.instance().profile)
311 else:
310 else:
312 error("profile is an application-level value, but you don't appear to be in an IPython application")
311 error("profile is an application-level value, but you don't appear to be in an IPython application")
313
312
314 @line_magic
313 @line_magic
315 def pprint(self, parameter_s=''):
314 def pprint(self, parameter_s=''):
316 """Toggle pretty printing on/off."""
315 """Toggle pretty printing on/off."""
317 ptformatter = self.shell.display_formatter.formatters['text/plain']
316 ptformatter = self.shell.display_formatter.formatters['text/plain']
318 ptformatter.pprint = bool(1 - ptformatter.pprint)
317 ptformatter.pprint = bool(1 - ptformatter.pprint)
319 print('Pretty printing has been turned',
318 print('Pretty printing has been turned',
320 ['OFF','ON'][ptformatter.pprint])
319 ['OFF','ON'][ptformatter.pprint])
321
320
322 @line_magic
321 @line_magic
323 def colors(self, parameter_s=''):
322 def colors(self, parameter_s=''):
324 """Switch color scheme for prompts, info system and exception handlers.
323 """Switch color scheme for prompts, info system and exception handlers.
325
324
326 Currently implemented schemes: NoColor, Linux, LightBG.
325 Currently implemented schemes: NoColor, Linux, LightBG.
327
326
328 Color scheme names are not case-sensitive.
327 Color scheme names are not case-sensitive.
329
328
330 Examples
329 Examples
331 --------
330 --------
332 To get a plain black and white terminal::
331 To get a plain black and white terminal::
333
332
334 %colors nocolor
333 %colors nocolor
335 """
334 """
336 def color_switch_err(name):
335 def color_switch_err(name):
337 warn('Error changing %s color schemes.\n%s' %
336 warn('Error changing %s color schemes.\n%s' %
338 (name, sys.exc_info()[1]))
337 (name, sys.exc_info()[1]))
339
338
340
339
341 new_scheme = parameter_s.strip()
340 new_scheme = parameter_s.strip()
342 if not new_scheme:
341 if not new_scheme:
343 raise UsageError(
342 raise UsageError(
344 "%colors: you must specify a color scheme. See '%colors?'")
343 "%colors: you must specify a color scheme. See '%colors?'")
345 return
344 return
346 # local shortcut
345 # local shortcut
347 shell = self.shell
346 shell = self.shell
348
347
349 import IPython.utils.rlineimpl as readline
348 import IPython.utils.rlineimpl as readline
350
349
351 if not shell.colors_force and \
350 if not shell.colors_force and \
352 not readline.have_readline and \
351 not readline.have_readline and \
353 (sys.platform == "win32" or sys.platform == "cli"):
352 (sys.platform == "win32" or sys.platform == "cli"):
354 msg = """\
353 msg = """\
355 Proper color support under MS Windows requires the pyreadline library.
354 Proper color support under MS Windows requires the pyreadline library.
356 You can find it at:
355 You can find it at:
357 http://ipython.org/pyreadline.html
356 http://ipython.org/pyreadline.html
358 Gary's readline needs the ctypes module, from:
357 Gary's readline needs the ctypes module, from:
359 http://starship.python.net/crew/theller/ctypes
358 http://starship.python.net/crew/theller/ctypes
360 (Note that ctypes is already part of Python versions 2.5 and newer).
359 (Note that ctypes is already part of Python versions 2.5 and newer).
361
360
362 Defaulting color scheme to 'NoColor'"""
361 Defaulting color scheme to 'NoColor'"""
363 new_scheme = 'NoColor'
362 new_scheme = 'NoColor'
364 warn(msg)
363 warn(msg)
365
364
366 # readline option is 0
365 # readline option is 0
367 if not shell.colors_force and not shell.has_readline:
366 if not shell.colors_force and not shell.has_readline:
368 new_scheme = 'NoColor'
367 new_scheme = 'NoColor'
369
368
370 # Set prompt colors
369 # Set prompt colors
371 try:
370 try:
372 shell.prompt_manager.color_scheme = new_scheme
371 shell.prompt_manager.color_scheme = new_scheme
373 except:
372 except:
374 color_switch_err('prompt')
373 color_switch_err('prompt')
375 else:
374 else:
376 shell.colors = \
375 shell.colors = \
377 shell.prompt_manager.color_scheme_table.active_scheme_name
376 shell.prompt_manager.color_scheme_table.active_scheme_name
378 # Set exception colors
377 # Set exception colors
379 try:
378 try:
380 shell.InteractiveTB.set_colors(scheme = new_scheme)
379 shell.InteractiveTB.set_colors(scheme = new_scheme)
381 shell.SyntaxTB.set_colors(scheme = new_scheme)
380 shell.SyntaxTB.set_colors(scheme = new_scheme)
382 except:
381 except:
383 color_switch_err('exception')
382 color_switch_err('exception')
384
383
385 # Set info (for 'object?') colors
384 # Set info (for 'object?') colors
386 if shell.color_info:
385 if shell.color_info:
387 try:
386 try:
388 shell.inspector.set_active_scheme(new_scheme)
387 shell.inspector.set_active_scheme(new_scheme)
389 except:
388 except:
390 color_switch_err('object inspector')
389 color_switch_err('object inspector')
391 else:
390 else:
392 shell.inspector.set_active_scheme('NoColor')
391 shell.inspector.set_active_scheme('NoColor')
393
392
394 @line_magic
393 @line_magic
395 def xmode(self, parameter_s=''):
394 def xmode(self, parameter_s=''):
396 """Switch modes for the exception handlers.
395 """Switch modes for the exception handlers.
397
396
398 Valid modes: Plain, Context and Verbose.
397 Valid modes: Plain, Context and Verbose.
399
398
400 If called without arguments, acts as a toggle."""
399 If called without arguments, acts as a toggle."""
401
400
402 def xmode_switch_err(name):
401 def xmode_switch_err(name):
403 warn('Error changing %s exception modes.\n%s' %
402 warn('Error changing %s exception modes.\n%s' %
404 (name,sys.exc_info()[1]))
403 (name,sys.exc_info()[1]))
405
404
406 shell = self.shell
405 shell = self.shell
407 new_mode = parameter_s.strip().capitalize()
406 new_mode = parameter_s.strip().capitalize()
408 try:
407 try:
409 shell.InteractiveTB.set_mode(mode=new_mode)
408 shell.InteractiveTB.set_mode(mode=new_mode)
410 print('Exception reporting mode:',shell.InteractiveTB.mode)
409 print('Exception reporting mode:',shell.InteractiveTB.mode)
411 except:
410 except:
412 xmode_switch_err('user')
411 xmode_switch_err('user')
413
412
414 @line_magic
413 @line_magic
415 def quickref(self,arg):
414 def quickref(self,arg):
416 """ Show a quick reference sheet """
415 """ Show a quick reference sheet """
417 from IPython.core.usage import quick_reference
416 from IPython.core.usage import quick_reference
418 qr = quick_reference + self._magic_docs(brief=True)
417 qr = quick_reference + self._magic_docs(brief=True)
419 page.page(qr)
418 page.page(qr)
420
419
421 @line_magic
420 @line_magic
422 def doctest_mode(self, parameter_s=''):
421 def doctest_mode(self, parameter_s=''):
423 """Toggle doctest mode on and off.
422 """Toggle doctest mode on and off.
424
423
425 This mode is intended to make IPython behave as much as possible like a
424 This mode is intended to make IPython behave as much as possible like a
426 plain Python shell, from the perspective of how its prompts, exceptions
425 plain Python shell, from the perspective of how its prompts, exceptions
427 and output look. This makes it easy to copy and paste parts of a
426 and output look. This makes it easy to copy and paste parts of a
428 session into doctests. It does so by:
427 session into doctests. It does so by:
429
428
430 - Changing the prompts to the classic ``>>>`` ones.
429 - Changing the prompts to the classic ``>>>`` ones.
431 - Changing the exception reporting mode to 'Plain'.
430 - Changing the exception reporting mode to 'Plain'.
432 - Disabling pretty-printing of output.
431 - Disabling pretty-printing of output.
433
432
434 Note that IPython also supports the pasting of code snippets that have
433 Note that IPython also supports the pasting of code snippets that have
435 leading '>>>' and '...' prompts in them. This means that you can paste
434 leading '>>>' and '...' prompts in them. This means that you can paste
436 doctests from files or docstrings (even if they have leading
435 doctests from files or docstrings (even if they have leading
437 whitespace), and the code will execute correctly. You can then use
436 whitespace), and the code will execute correctly. You can then use
438 '%history -t' to see the translated history; this will give you the
437 '%history -t' to see the translated history; this will give you the
439 input after removal of all the leading prompts and whitespace, which
438 input after removal of all the leading prompts and whitespace, which
440 can be pasted back into an editor.
439 can be pasted back into an editor.
441
440
442 With these features, you can switch into this mode easily whenever you
441 With these features, you can switch into this mode easily whenever you
443 need to do testing and changes to doctests, without having to leave
442 need to do testing and changes to doctests, without having to leave
444 your existing IPython session.
443 your existing IPython session.
445 """
444 """
446
445
447 # Shorthands
446 # Shorthands
448 shell = self.shell
447 shell = self.shell
449 pm = shell.prompt_manager
448 pm = shell.prompt_manager
450 meta = shell.meta
449 meta = shell.meta
451 disp_formatter = self.shell.display_formatter
450 disp_formatter = self.shell.display_formatter
452 ptformatter = disp_formatter.formatters['text/plain']
451 ptformatter = disp_formatter.formatters['text/plain']
453 # dstore is a data store kept in the instance metadata bag to track any
452 # dstore is a data store kept in the instance metadata bag to track any
454 # changes we make, so we can undo them later.
453 # changes we make, so we can undo them later.
455 dstore = meta.setdefault('doctest_mode',Struct())
454 dstore = meta.setdefault('doctest_mode',Struct())
456 save_dstore = dstore.setdefault
455 save_dstore = dstore.setdefault
457
456
458 # save a few values we'll need to recover later
457 # save a few values we'll need to recover later
459 mode = save_dstore('mode',False)
458 mode = save_dstore('mode',False)
460 save_dstore('rc_pprint',ptformatter.pprint)
459 save_dstore('rc_pprint',ptformatter.pprint)
461 save_dstore('xmode',shell.InteractiveTB.mode)
460 save_dstore('xmode',shell.InteractiveTB.mode)
462 save_dstore('rc_separate_out',shell.separate_out)
461 save_dstore('rc_separate_out',shell.separate_out)
463 save_dstore('rc_separate_out2',shell.separate_out2)
462 save_dstore('rc_separate_out2',shell.separate_out2)
464 save_dstore('rc_prompts_pad_left',pm.justify)
463 save_dstore('rc_prompts_pad_left',pm.justify)
465 save_dstore('rc_separate_in',shell.separate_in)
464 save_dstore('rc_separate_in',shell.separate_in)
466 save_dstore('rc_active_types',disp_formatter.active_types)
465 save_dstore('rc_active_types',disp_formatter.active_types)
467 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
466 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
468
467
469 if mode == False:
468 if mode == False:
470 # turn on
469 # turn on
471 pm.in_template = '>>> '
470 pm.in_template = '>>> '
472 pm.in2_template = '... '
471 pm.in2_template = '... '
473 pm.out_template = ''
472 pm.out_template = ''
474
473
475 # Prompt separators like plain python
474 # Prompt separators like plain python
476 shell.separate_in = ''
475 shell.separate_in = ''
477 shell.separate_out = ''
476 shell.separate_out = ''
478 shell.separate_out2 = ''
477 shell.separate_out2 = ''
479
478
480 pm.justify = False
479 pm.justify = False
481
480
482 ptformatter.pprint = False
481 ptformatter.pprint = False
483 disp_formatter.active_types = ['text/plain']
482 disp_formatter.active_types = ['text/plain']
484
483
485 shell.magic('xmode Plain')
484 shell.magic('xmode Plain')
486 else:
485 else:
487 # turn off
486 # turn off
488 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
487 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
489
488
490 shell.separate_in = dstore.rc_separate_in
489 shell.separate_in = dstore.rc_separate_in
491
490
492 shell.separate_out = dstore.rc_separate_out
491 shell.separate_out = dstore.rc_separate_out
493 shell.separate_out2 = dstore.rc_separate_out2
492 shell.separate_out2 = dstore.rc_separate_out2
494
493
495 pm.justify = dstore.rc_prompts_pad_left
494 pm.justify = dstore.rc_prompts_pad_left
496
495
497 ptformatter.pprint = dstore.rc_pprint
496 ptformatter.pprint = dstore.rc_pprint
498 disp_formatter.active_types = dstore.rc_active_types
497 disp_formatter.active_types = dstore.rc_active_types
499
498
500 shell.magic('xmode ' + dstore.xmode)
499 shell.magic('xmode ' + dstore.xmode)
501
500
502 # Store new mode and inform
501 # Store new mode and inform
503 dstore.mode = bool(1-int(mode))
502 dstore.mode = bool(1-int(mode))
504 mode_label = ['OFF','ON'][dstore.mode]
503 mode_label = ['OFF','ON'][dstore.mode]
505 print('Doctest mode is:', mode_label)
504 print('Doctest mode is:', mode_label)
506
505
507 @line_magic
506 @line_magic
508 def gui(self, parameter_s=''):
507 def gui(self, parameter_s=''):
509 """Enable or disable IPython GUI event loop integration.
508 """Enable or disable IPython GUI event loop integration.
510
509
511 %gui [GUINAME]
510 %gui [GUINAME]
512
511
513 This magic replaces IPython's threaded shells that were activated
512 This magic replaces IPython's threaded shells that were activated
514 using the (pylab/wthread/etc.) command line flags. GUI toolkits
513 using the (pylab/wthread/etc.) command line flags. GUI toolkits
515 can now be enabled at runtime and keyboard
514 can now be enabled at runtime and keyboard
516 interrupts should work without any problems. The following toolkits
515 interrupts should work without any problems. The following toolkits
517 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
516 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
518
517
519 %gui wx # enable wxPython event loop integration
518 %gui wx # enable wxPython event loop integration
520 %gui qt4|qt # enable PyQt4 event loop integration
519 %gui qt4|qt # enable PyQt4 event loop integration
521 %gui gtk # enable PyGTK event loop integration
520 %gui gtk # enable PyGTK event loop integration
522 %gui gtk3 # enable Gtk3 event loop integration
521 %gui gtk3 # enable Gtk3 event loop integration
523 %gui tk # enable Tk event loop integration
522 %gui tk # enable Tk event loop integration
524 %gui osx # enable Cocoa event loop integration
523 %gui osx # enable Cocoa event loop integration
525 # (requires %matplotlib 1.1)
524 # (requires %matplotlib 1.1)
526 %gui # disable all event loop integration
525 %gui # disable all event loop integration
527
526
528 WARNING: after any of these has been called you can simply create
527 WARNING: after any of these has been called you can simply create
529 an application object, but DO NOT start the event loop yourself, as
528 an application object, but DO NOT start the event loop yourself, as
530 we have already handled that.
529 we have already handled that.
531 """
530 """
532 opts, arg = self.parse_options(parameter_s, '')
531 opts, arg = self.parse_options(parameter_s, '')
533 if arg=='': arg = None
532 if arg=='': arg = None
534 try:
533 try:
535 return self.shell.enable_gui(arg)
534 return self.shell.enable_gui(arg)
536 except Exception as e:
535 except Exception as e:
537 # print simple error message, rather than traceback if we can't
536 # print simple error message, rather than traceback if we can't
538 # hook up the GUI
537 # hook up the GUI
539 error(str(e))
538 error(str(e))
540
539
541 @skip_doctest
540 @skip_doctest
542 @line_magic
541 @line_magic
543 def precision(self, s=''):
542 def precision(self, s=''):
544 """Set floating point precision for pretty printing.
543 """Set floating point precision for pretty printing.
545
544
546 Can set either integer precision or a format string.
545 Can set either integer precision or a format string.
547
546
548 If numpy has been imported and precision is an int,
547 If numpy has been imported and precision is an int,
549 numpy display precision will also be set, via ``numpy.set_printoptions``.
548 numpy display precision will also be set, via ``numpy.set_printoptions``.
550
549
551 If no argument is given, defaults will be restored.
550 If no argument is given, defaults will be restored.
552
551
553 Examples
552 Examples
554 --------
553 --------
555 ::
554 ::
556
555
557 In [1]: from math import pi
556 In [1]: from math import pi
558
557
559 In [2]: %precision 3
558 In [2]: %precision 3
560 Out[2]: u'%.3f'
559 Out[2]: u'%.3f'
561
560
562 In [3]: pi
561 In [3]: pi
563 Out[3]: 3.142
562 Out[3]: 3.142
564
563
565 In [4]: %precision %i
564 In [4]: %precision %i
566 Out[4]: u'%i'
565 Out[4]: u'%i'
567
566
568 In [5]: pi
567 In [5]: pi
569 Out[5]: 3
568 Out[5]: 3
570
569
571 In [6]: %precision %e
570 In [6]: %precision %e
572 Out[6]: u'%e'
571 Out[6]: u'%e'
573
572
574 In [7]: pi**10
573 In [7]: pi**10
575 Out[7]: 9.364805e+04
574 Out[7]: 9.364805e+04
576
575
577 In [8]: %precision
576 In [8]: %precision
578 Out[8]: u'%r'
577 Out[8]: u'%r'
579
578
580 In [9]: pi**10
579 In [9]: pi**10
581 Out[9]: 93648.047476082982
580 Out[9]: 93648.047476082982
582 """
581 """
583 ptformatter = self.shell.display_formatter.formatters['text/plain']
582 ptformatter = self.shell.display_formatter.formatters['text/plain']
584 ptformatter.float_precision = s
583 ptformatter.float_precision = s
585 return ptformatter.float_format
584 return ptformatter.float_format
586
585
587 @magic_arguments.magic_arguments()
586 @magic_arguments.magic_arguments()
588 @magic_arguments.argument(
587 @magic_arguments.argument(
589 '-e', '--export', action='store_true', default=False,
588 '-e', '--export', action='store_true', default=False,
590 help='Export IPython history as a notebook. The filename argument '
589 help='Export IPython history as a notebook. The filename argument '
591 'is used to specify the notebook name and format. For example '
590 'is used to specify the notebook name and format. For example '
592 'a filename of notebook.ipynb will result in a notebook name '
591 'a filename of notebook.ipynb will result in a notebook name '
593 'of "notebook" and a format of "json". Likewise using a ".py" '
592 'of "notebook" and a format of "json". Likewise using a ".py" '
594 'file extension will write the notebook as a Python script'
593 'file extension will write the notebook as a Python script'
595 )
594 )
596 @magic_arguments.argument(
595 @magic_arguments.argument(
597 '-f', '--format',
596 '-f', '--format',
598 help='Convert an existing IPython notebook to a new format. This option '
597 help='Convert an existing IPython notebook to a new format. This option '
599 'specifies the new format and can have the values: json, py. '
598 'specifies the new format and can have the values: json, py. '
600 'The target filename is chosen automatically based on the new '
599 'The target filename is chosen automatically based on the new '
601 'format. The filename argument gives the name of the source file.'
600 'format. The filename argument gives the name of the source file.'
602 )
601 )
603 @magic_arguments.argument(
602 @magic_arguments.argument(
604 'filename', type=unicode,
603 'filename', type=unicode,
605 help='Notebook name or filename'
604 help='Notebook name or filename'
606 )
605 )
607 @line_magic
606 @line_magic
608 def notebook(self, s):
607 def notebook(self, s):
609 """Export and convert IPython notebooks.
608 """Export and convert IPython notebooks.
610
609
611 This function can export the current IPython history to a notebook file
610 This function can export the current IPython history to a notebook file
612 or can convert an existing notebook file into a different format. For
611 or can convert an existing notebook file into a different format. For
613 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
612 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
614 To export the history to "foo.py" do "%notebook -e foo.py". To convert
613 To export the history to "foo.py" do "%notebook -e foo.py". To convert
615 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
614 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
616 formats include (json/ipynb, py).
615 formats include (json/ipynb, py).
617 """
616 """
618 args = magic_arguments.parse_argstring(self.notebook, s)
617 args = magic_arguments.parse_argstring(self.notebook, s)
619
618
620 from IPython.nbformat import current
619 from IPython.nbformat import current
621 args.filename = unquote_filename(args.filename)
620 args.filename = unquote_filename(args.filename)
622 if args.export:
621 if args.export:
623 fname, name, format = current.parse_filename(args.filename)
622 fname, name, format = current.parse_filename(args.filename)
624 cells = []
623 cells = []
625 hist = list(self.shell.history_manager.get_range())
624 hist = list(self.shell.history_manager.get_range())
626 for session, prompt_number, input in hist[:-1]:
625 for session, prompt_number, input in hist[:-1]:
627 cells.append(current.new_code_cell(prompt_number=prompt_number,
626 cells.append(current.new_code_cell(prompt_number=prompt_number,
628 input=input))
627 input=input))
629 worksheet = current.new_worksheet(cells=cells)
628 worksheet = current.new_worksheet(cells=cells)
630 nb = current.new_notebook(name=name,worksheets=[worksheet])
629 nb = current.new_notebook(name=name,worksheets=[worksheet])
631 with io.open(fname, 'w', encoding='utf-8') as f:
630 with io.open(fname, 'w', encoding='utf-8') as f:
632 current.write(nb, f, format);
631 current.write(nb, f, format);
633 elif args.format is not None:
632 elif args.format is not None:
634 old_fname, old_name, old_format = current.parse_filename(args.filename)
633 old_fname, old_name, old_format = current.parse_filename(args.filename)
635 new_format = args.format
634 new_format = args.format
636 if new_format == u'xml':
635 if new_format == u'xml':
637 raise ValueError('Notebooks cannot be written as xml.')
636 raise ValueError('Notebooks cannot be written as xml.')
638 elif new_format == u'ipynb' or new_format == u'json':
637 elif new_format == u'ipynb' or new_format == u'json':
639 new_fname = old_name + u'.ipynb'
638 new_fname = old_name + u'.ipynb'
640 new_format = u'json'
639 new_format = u'json'
641 elif new_format == u'py':
640 elif new_format == u'py':
642 new_fname = old_name + u'.py'
641 new_fname = old_name + u'.py'
643 else:
642 else:
644 raise ValueError('Invalid notebook format: %s' % new_format)
643 raise ValueError('Invalid notebook format: %s' % new_format)
645 with io.open(old_fname, 'r', encoding='utf-8') as f:
644 with io.open(old_fname, 'r', encoding='utf-8') as f:
646 nb = current.read(f, old_format)
645 nb = current.read(f, old_format)
647 with io.open(new_fname, 'w', encoding='utf-8') as f:
646 with io.open(new_fname, 'w', encoding='utf-8') as f:
648 current.write(nb, f, new_format)
647 current.write(nb, f, new_format)
@@ -1,885 +1,882 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 __all__ = ['Inspector','InspectColors']
18 __all__ = ['Inspector','InspectColors']
19
19
20 # stdlib modules
20 # stdlib modules
21 import __builtin__
22 import inspect
21 import inspect
23 import linecache
22 import linecache
24 import os
23 import os
25 import sys
26 import types
24 import types
27 import io as stdlib_io
25 import io as stdlib_io
28
26
29 from collections import namedtuple
30 try:
27 try:
31 from itertools import izip_longest
28 from itertools import izip_longest
32 except ImportError:
29 except ImportError:
33 from itertools import zip_longest as izip_longest
30 from itertools import zip_longest as izip_longest
34
31
35 # IPython's own
32 # IPython's own
36 from IPython.core import page
33 from IPython.core import page
37 from IPython.testing.skipdoctest import skip_doctest_py3
34 from IPython.testing.skipdoctest import skip_doctest_py3
38 from IPython.utils import PyColorize
35 from IPython.utils import PyColorize
39 from IPython.utils import io
36 from IPython.utils import io
40 from IPython.utils import openpy
37 from IPython.utils import openpy
41 from IPython.utils import py3compat
38 from IPython.utils import py3compat
42 from IPython.utils.text import indent
39 from IPython.utils.text import indent
43 from IPython.utils.wildcard import list_namespace
40 from IPython.utils.wildcard import list_namespace
44 from IPython.utils.coloransi import *
41 from IPython.utils.coloransi import *
45 from IPython.utils.py3compat import cast_unicode
42 from IPython.utils.py3compat import cast_unicode
46
43
47 #****************************************************************************
44 #****************************************************************************
48 # Builtin color schemes
45 # Builtin color schemes
49
46
50 Colors = TermColors # just a shorthand
47 Colors = TermColors # just a shorthand
51
48
52 # Build a few color schemes
49 # Build a few color schemes
53 NoColor = ColorScheme(
50 NoColor = ColorScheme(
54 'NoColor',{
51 'NoColor',{
55 'header' : Colors.NoColor,
52 'header' : Colors.NoColor,
56 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
53 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
57 } )
54 } )
58
55
59 LinuxColors = ColorScheme(
56 LinuxColors = ColorScheme(
60 'Linux',{
57 'Linux',{
61 'header' : Colors.LightRed,
58 'header' : Colors.LightRed,
62 'normal' : Colors.Normal # color off (usu. Colors.Normal)
59 'normal' : Colors.Normal # color off (usu. Colors.Normal)
63 } )
60 } )
64
61
65 LightBGColors = ColorScheme(
62 LightBGColors = ColorScheme(
66 'LightBG',{
63 'LightBG',{
67 'header' : Colors.Red,
64 'header' : Colors.Red,
68 'normal' : Colors.Normal # color off (usu. Colors.Normal)
65 'normal' : Colors.Normal # color off (usu. Colors.Normal)
69 } )
66 } )
70
67
71 # Build table of color schemes (needed by the parser)
68 # Build table of color schemes (needed by the parser)
72 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
69 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
73 'Linux')
70 'Linux')
74
71
75 #****************************************************************************
72 #****************************************************************************
76 # Auxiliary functions and objects
73 # Auxiliary functions and objects
77
74
78 # See the messaging spec for the definition of all these fields. This list
75 # See the messaging spec for the definition of all these fields. This list
79 # effectively defines the order of display
76 # effectively defines the order of display
80 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
77 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
81 'length', 'file', 'definition', 'docstring', 'source',
78 'length', 'file', 'definition', 'docstring', 'source',
82 'init_definition', 'class_docstring', 'init_docstring',
79 'init_definition', 'class_docstring', 'init_docstring',
83 'call_def', 'call_docstring',
80 'call_def', 'call_docstring',
84 # These won't be printed but will be used to determine how to
81 # These won't be printed but will be used to determine how to
85 # format the object
82 # format the object
86 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
83 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
87 ]
84 ]
88
85
89
86
90 def object_info(**kw):
87 def object_info(**kw):
91 """Make an object info dict with all fields present."""
88 """Make an object info dict with all fields present."""
92 infodict = dict(izip_longest(info_fields, [None]))
89 infodict = dict(izip_longest(info_fields, [None]))
93 infodict.update(kw)
90 infodict.update(kw)
94 return infodict
91 return infodict
95
92
96
93
97 def get_encoding(obj):
94 def get_encoding(obj):
98 """Get encoding for python source file defining obj
95 """Get encoding for python source file defining obj
99
96
100 Returns None if obj is not defined in a sourcefile.
97 Returns None if obj is not defined in a sourcefile.
101 """
98 """
102 ofile = find_file(obj)
99 ofile = find_file(obj)
103 # run contents of file through pager starting at line where the object
100 # run contents of file through pager starting at line where the object
104 # is defined, as long as the file isn't binary and is actually on the
101 # is defined, as long as the file isn't binary and is actually on the
105 # filesystem.
102 # filesystem.
106 if ofile is None:
103 if ofile is None:
107 return None
104 return None
108 elif ofile.endswith(('.so', '.dll', '.pyd')):
105 elif ofile.endswith(('.so', '.dll', '.pyd')):
109 return None
106 return None
110 elif not os.path.isfile(ofile):
107 elif not os.path.isfile(ofile):
111 return None
108 return None
112 else:
109 else:
113 # Print only text files, not extension binaries. Note that
110 # Print only text files, not extension binaries. Note that
114 # getsourcelines returns lineno with 1-offset and page() uses
111 # getsourcelines returns lineno with 1-offset and page() uses
115 # 0-offset, so we must adjust.
112 # 0-offset, so we must adjust.
116 buffer = stdlib_io.open(ofile, 'rb') # Tweaked to use io.open for Python 2
113 buffer = stdlib_io.open(ofile, 'rb') # Tweaked to use io.open for Python 2
117 encoding, lines = openpy.detect_encoding(buffer.readline)
114 encoding, lines = openpy.detect_encoding(buffer.readline)
118 return encoding
115 return encoding
119
116
120 def getdoc(obj):
117 def getdoc(obj):
121 """Stable wrapper around inspect.getdoc.
118 """Stable wrapper around inspect.getdoc.
122
119
123 This can't crash because of attribute problems.
120 This can't crash because of attribute problems.
124
121
125 It also attempts to call a getdoc() method on the given object. This
122 It also attempts to call a getdoc() method on the given object. This
126 allows objects which provide their docstrings via non-standard mechanisms
123 allows objects which provide their docstrings via non-standard mechanisms
127 (like Pyro proxies) to still be inspected by ipython's ? system."""
124 (like Pyro proxies) to still be inspected by ipython's ? system."""
128 # Allow objects to offer customized documentation via a getdoc method:
125 # Allow objects to offer customized documentation via a getdoc method:
129 try:
126 try:
130 ds = obj.getdoc()
127 ds = obj.getdoc()
131 except Exception:
128 except Exception:
132 pass
129 pass
133 else:
130 else:
134 # if we get extra info, we add it to the normal docstring.
131 # if we get extra info, we add it to the normal docstring.
135 if isinstance(ds, basestring):
132 if isinstance(ds, basestring):
136 return inspect.cleandoc(ds)
133 return inspect.cleandoc(ds)
137
134
138 try:
135 try:
139 docstr = inspect.getdoc(obj)
136 docstr = inspect.getdoc(obj)
140 encoding = get_encoding(obj)
137 encoding = get_encoding(obj)
141 return py3compat.cast_unicode(docstr, encoding=encoding)
138 return py3compat.cast_unicode(docstr, encoding=encoding)
142 except Exception:
139 except Exception:
143 # Harden against an inspect failure, which can occur with
140 # Harden against an inspect failure, which can occur with
144 # SWIG-wrapped extensions.
141 # SWIG-wrapped extensions.
145 raise
142 raise
146 return None
143 return None
147
144
148
145
149 def getsource(obj,is_binary=False):
146 def getsource(obj,is_binary=False):
150 """Wrapper around inspect.getsource.
147 """Wrapper around inspect.getsource.
151
148
152 This can be modified by other projects to provide customized source
149 This can be modified by other projects to provide customized source
153 extraction.
150 extraction.
154
151
155 Inputs:
152 Inputs:
156
153
157 - obj: an object whose source code we will attempt to extract.
154 - obj: an object whose source code we will attempt to extract.
158
155
159 Optional inputs:
156 Optional inputs:
160
157
161 - is_binary: whether the object is known to come from a binary source.
158 - is_binary: whether the object is known to come from a binary source.
162 This implementation will skip returning any output for binary objects, but
159 This implementation will skip returning any output for binary objects, but
163 custom extractors may know how to meaningfully process them."""
160 custom extractors may know how to meaningfully process them."""
164
161
165 if is_binary:
162 if is_binary:
166 return None
163 return None
167 else:
164 else:
168 # get source if obj was decorated with @decorator
165 # get source if obj was decorated with @decorator
169 if hasattr(obj,"__wrapped__"):
166 if hasattr(obj,"__wrapped__"):
170 obj = obj.__wrapped__
167 obj = obj.__wrapped__
171 try:
168 try:
172 src = inspect.getsource(obj)
169 src = inspect.getsource(obj)
173 except TypeError:
170 except TypeError:
174 if hasattr(obj,'__class__'):
171 if hasattr(obj,'__class__'):
175 src = inspect.getsource(obj.__class__)
172 src = inspect.getsource(obj.__class__)
176 encoding = get_encoding(obj)
173 encoding = get_encoding(obj)
177 return cast_unicode(src, encoding=encoding)
174 return cast_unicode(src, encoding=encoding)
178
175
179 def getargspec(obj):
176 def getargspec(obj):
180 """Get the names and default values of a function's arguments.
177 """Get the names and default values of a function's arguments.
181
178
182 A tuple of four things is returned: (args, varargs, varkw, defaults).
179 A tuple of four things is returned: (args, varargs, varkw, defaults).
183 'args' is a list of the argument names (it may contain nested lists).
180 'args' is a list of the argument names (it may contain nested lists).
184 'varargs' and 'varkw' are the names of the * and ** arguments or None.
181 'varargs' and 'varkw' are the names of the * and ** arguments or None.
185 'defaults' is an n-tuple of the default values of the last n arguments.
182 'defaults' is an n-tuple of the default values of the last n arguments.
186
183
187 Modified version of inspect.getargspec from the Python Standard
184 Modified version of inspect.getargspec from the Python Standard
188 Library."""
185 Library."""
189
186
190 if inspect.isfunction(obj):
187 if inspect.isfunction(obj):
191 func_obj = obj
188 func_obj = obj
192 elif inspect.ismethod(obj):
189 elif inspect.ismethod(obj):
193 func_obj = obj.im_func
190 func_obj = obj.im_func
194 elif hasattr(obj, '__call__'):
191 elif hasattr(obj, '__call__'):
195 func_obj = obj.__call__
192 func_obj = obj.__call__
196 else:
193 else:
197 raise TypeError('arg is not a Python function')
194 raise TypeError('arg is not a Python function')
198 args, varargs, varkw = inspect.getargs(func_obj.func_code)
195 args, varargs, varkw = inspect.getargs(func_obj.func_code)
199 return args, varargs, varkw, func_obj.func_defaults
196 return args, varargs, varkw, func_obj.func_defaults
200
197
201
198
202 def format_argspec(argspec):
199 def format_argspec(argspec):
203 """Format argspect, convenience wrapper around inspect's.
200 """Format argspect, convenience wrapper around inspect's.
204
201
205 This takes a dict instead of ordered arguments and calls
202 This takes a dict instead of ordered arguments and calls
206 inspect.format_argspec with the arguments in the necessary order.
203 inspect.format_argspec with the arguments in the necessary order.
207 """
204 """
208 return inspect.formatargspec(argspec['args'], argspec['varargs'],
205 return inspect.formatargspec(argspec['args'], argspec['varargs'],
209 argspec['varkw'], argspec['defaults'])
206 argspec['varkw'], argspec['defaults'])
210
207
211
208
212 def call_tip(oinfo, format_call=True):
209 def call_tip(oinfo, format_call=True):
213 """Extract call tip data from an oinfo dict.
210 """Extract call tip data from an oinfo dict.
214
211
215 Parameters
212 Parameters
216 ----------
213 ----------
217 oinfo : dict
214 oinfo : dict
218
215
219 format_call : bool, optional
216 format_call : bool, optional
220 If True, the call line is formatted and returned as a string. If not, a
217 If True, the call line is formatted and returned as a string. If not, a
221 tuple of (name, argspec) is returned.
218 tuple of (name, argspec) is returned.
222
219
223 Returns
220 Returns
224 -------
221 -------
225 call_info : None, str or (str, dict) tuple.
222 call_info : None, str or (str, dict) tuple.
226 When format_call is True, the whole call information is formattted as a
223 When format_call is True, the whole call information is formattted as a
227 single string. Otherwise, the object's name and its argspec dict are
224 single string. Otherwise, the object's name and its argspec dict are
228 returned. If no call information is available, None is returned.
225 returned. If no call information is available, None is returned.
229
226
230 docstring : str or None
227 docstring : str or None
231 The most relevant docstring for calling purposes is returned, if
228 The most relevant docstring for calling purposes is returned, if
232 available. The priority is: call docstring for callable instances, then
229 available. The priority is: call docstring for callable instances, then
233 constructor docstring for classes, then main object's docstring otherwise
230 constructor docstring for classes, then main object's docstring otherwise
234 (regular functions).
231 (regular functions).
235 """
232 """
236 # Get call definition
233 # Get call definition
237 argspec = oinfo.get('argspec')
234 argspec = oinfo.get('argspec')
238 if argspec is None:
235 if argspec is None:
239 call_line = None
236 call_line = None
240 else:
237 else:
241 # Callable objects will have 'self' as their first argument, prune
238 # Callable objects will have 'self' as their first argument, prune
242 # it out if it's there for clarity (since users do *not* pass an
239 # it out if it's there for clarity (since users do *not* pass an
243 # extra first argument explicitly).
240 # extra first argument explicitly).
244 try:
241 try:
245 has_self = argspec['args'][0] == 'self'
242 has_self = argspec['args'][0] == 'self'
246 except (KeyError, IndexError):
243 except (KeyError, IndexError):
247 pass
244 pass
248 else:
245 else:
249 if has_self:
246 if has_self:
250 argspec['args'] = argspec['args'][1:]
247 argspec['args'] = argspec['args'][1:]
251
248
252 call_line = oinfo['name']+format_argspec(argspec)
249 call_line = oinfo['name']+format_argspec(argspec)
253
250
254 # Now get docstring.
251 # Now get docstring.
255 # The priority is: call docstring, constructor docstring, main one.
252 # The priority is: call docstring, constructor docstring, main one.
256 doc = oinfo.get('call_docstring')
253 doc = oinfo.get('call_docstring')
257 if doc is None:
254 if doc is None:
258 doc = oinfo.get('init_docstring')
255 doc = oinfo.get('init_docstring')
259 if doc is None:
256 if doc is None:
260 doc = oinfo.get('docstring','')
257 doc = oinfo.get('docstring','')
261
258
262 return call_line, doc
259 return call_line, doc
263
260
264 def safe_hasattr(obj, attr):
261 def safe_hasattr(obj, attr):
265 """In recent versions of Python, hasattr() only catches AttributeError.
262 """In recent versions of Python, hasattr() only catches AttributeError.
266 This catches all errors.
263 This catches all errors.
267 """
264 """
268 try:
265 try:
269 getattr(obj, attr)
266 getattr(obj, attr)
270 return True
267 return True
271 except:
268 except:
272 return False
269 return False
273
270
274
271
275 def find_file(obj):
272 def find_file(obj):
276 """Find the absolute path to the file where an object was defined.
273 """Find the absolute path to the file where an object was defined.
277
274
278 This is essentially a robust wrapper around `inspect.getabsfile`.
275 This is essentially a robust wrapper around `inspect.getabsfile`.
279
276
280 Returns None if no file can be found.
277 Returns None if no file can be found.
281
278
282 Parameters
279 Parameters
283 ----------
280 ----------
284 obj : any Python object
281 obj : any Python object
285
282
286 Returns
283 Returns
287 -------
284 -------
288 fname : str
285 fname : str
289 The absolute path to the file where the object was defined.
286 The absolute path to the file where the object was defined.
290 """
287 """
291 # get source if obj was decorated with @decorator
288 # get source if obj was decorated with @decorator
292 if safe_hasattr(obj, '__wrapped__'):
289 if safe_hasattr(obj, '__wrapped__'):
293 obj = obj.__wrapped__
290 obj = obj.__wrapped__
294
291
295 fname = None
292 fname = None
296 try:
293 try:
297 fname = inspect.getabsfile(obj)
294 fname = inspect.getabsfile(obj)
298 except TypeError:
295 except TypeError:
299 # For an instance, the file that matters is where its class was
296 # For an instance, the file that matters is where its class was
300 # declared.
297 # declared.
301 if hasattr(obj, '__class__'):
298 if hasattr(obj, '__class__'):
302 try:
299 try:
303 fname = inspect.getabsfile(obj.__class__)
300 fname = inspect.getabsfile(obj.__class__)
304 except TypeError:
301 except TypeError:
305 # Can happen for builtins
302 # Can happen for builtins
306 pass
303 pass
307 except:
304 except:
308 pass
305 pass
309 return cast_unicode(fname)
306 return cast_unicode(fname)
310
307
311
308
312 def find_source_lines(obj):
309 def find_source_lines(obj):
313 """Find the line number in a file where an object was defined.
310 """Find the line number in a file where an object was defined.
314
311
315 This is essentially a robust wrapper around `inspect.getsourcelines`.
312 This is essentially a robust wrapper around `inspect.getsourcelines`.
316
313
317 Returns None if no file can be found.
314 Returns None if no file can be found.
318
315
319 Parameters
316 Parameters
320 ----------
317 ----------
321 obj : any Python object
318 obj : any Python object
322
319
323 Returns
320 Returns
324 -------
321 -------
325 lineno : int
322 lineno : int
326 The line number where the object definition starts.
323 The line number where the object definition starts.
327 """
324 """
328 # get source if obj was decorated with @decorator
325 # get source if obj was decorated with @decorator
329 if safe_hasattr(obj, '__wrapped__'):
326 if safe_hasattr(obj, '__wrapped__'):
330 obj = obj.__wrapped__
327 obj = obj.__wrapped__
331
328
332 try:
329 try:
333 try:
330 try:
334 lineno = inspect.getsourcelines(obj)[1]
331 lineno = inspect.getsourcelines(obj)[1]
335 except TypeError:
332 except TypeError:
336 # For instances, try the class object like getsource() does
333 # For instances, try the class object like getsource() does
337 if hasattr(obj, '__class__'):
334 if hasattr(obj, '__class__'):
338 lineno = inspect.getsourcelines(obj.__class__)[1]
335 lineno = inspect.getsourcelines(obj.__class__)[1]
339 else:
336 else:
340 lineno = None
337 lineno = None
341 except:
338 except:
342 return None
339 return None
343
340
344 return lineno
341 return lineno
345
342
346
343
347 class Inspector:
344 class Inspector:
348 def __init__(self, color_table=InspectColors,
345 def __init__(self, color_table=InspectColors,
349 code_color_table=PyColorize.ANSICodeColors,
346 code_color_table=PyColorize.ANSICodeColors,
350 scheme='NoColor',
347 scheme='NoColor',
351 str_detail_level=0):
348 str_detail_level=0):
352 self.color_table = color_table
349 self.color_table = color_table
353 self.parser = PyColorize.Parser(code_color_table,out='str')
350 self.parser = PyColorize.Parser(code_color_table,out='str')
354 self.format = self.parser.format
351 self.format = self.parser.format
355 self.str_detail_level = str_detail_level
352 self.str_detail_level = str_detail_level
356 self.set_active_scheme(scheme)
353 self.set_active_scheme(scheme)
357
354
358 def _getdef(self,obj,oname=''):
355 def _getdef(self,obj,oname=''):
359 """Return the call signature for any callable object.
356 """Return the call signature for any callable object.
360
357
361 If any exception is generated, None is returned instead and the
358 If any exception is generated, None is returned instead and the
362 exception is suppressed."""
359 exception is suppressed."""
363
360
364 try:
361 try:
365 hdef = oname + inspect.formatargspec(*getargspec(obj))
362 hdef = oname + inspect.formatargspec(*getargspec(obj))
366 return cast_unicode(hdef)
363 return cast_unicode(hdef)
367 except:
364 except:
368 return None
365 return None
369
366
370 def __head(self,h):
367 def __head(self,h):
371 """Return a header string with proper colors."""
368 """Return a header string with proper colors."""
372 return '%s%s%s' % (self.color_table.active_colors.header,h,
369 return '%s%s%s' % (self.color_table.active_colors.header,h,
373 self.color_table.active_colors.normal)
370 self.color_table.active_colors.normal)
374
371
375 def set_active_scheme(self, scheme):
372 def set_active_scheme(self, scheme):
376 self.color_table.set_active_scheme(scheme)
373 self.color_table.set_active_scheme(scheme)
377 self.parser.color_table.set_active_scheme(scheme)
374 self.parser.color_table.set_active_scheme(scheme)
378
375
379 def noinfo(self, msg, oname):
376 def noinfo(self, msg, oname):
380 """Generic message when no information is found."""
377 """Generic message when no information is found."""
381 print('No %s found' % msg, end=' ')
378 print('No %s found' % msg, end=' ')
382 if oname:
379 if oname:
383 print('for %s' % oname)
380 print('for %s' % oname)
384 else:
381 else:
385 print()
382 print()
386
383
387 def pdef(self, obj, oname=''):
384 def pdef(self, obj, oname=''):
388 """Print the call signature for any callable object.
385 """Print the call signature for any callable object.
389
386
390 If the object is a class, print the constructor information."""
387 If the object is a class, print the constructor information."""
391
388
392 if not callable(obj):
389 if not callable(obj):
393 print('Object is not callable.')
390 print('Object is not callable.')
394 return
391 return
395
392
396 header = ''
393 header = ''
397
394
398 if inspect.isclass(obj):
395 if inspect.isclass(obj):
399 header = self.__head('Class constructor information:\n')
396 header = self.__head('Class constructor information:\n')
400 obj = obj.__init__
397 obj = obj.__init__
401 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
398 elif (not py3compat.PY3) and type(obj) is types.InstanceType:
402 obj = obj.__call__
399 obj = obj.__call__
403
400
404 output = self._getdef(obj,oname)
401 output = self._getdef(obj,oname)
405 if output is None:
402 if output is None:
406 self.noinfo('definition header',oname)
403 self.noinfo('definition header',oname)
407 else:
404 else:
408 print(header,self.format(output), end=' ', file=io.stdout)
405 print(header,self.format(output), end=' ', file=io.stdout)
409
406
410 # In Python 3, all classes are new-style, so they all have __init__.
407 # In Python 3, all classes are new-style, so they all have __init__.
411 @skip_doctest_py3
408 @skip_doctest_py3
412 def pdoc(self,obj,oname='',formatter = None):
409 def pdoc(self,obj,oname='',formatter = None):
413 """Print the docstring for any object.
410 """Print the docstring for any object.
414
411
415 Optional:
412 Optional:
416 -formatter: a function to run the docstring through for specially
413 -formatter: a function to run the docstring through for specially
417 formatted docstrings.
414 formatted docstrings.
418
415
419 Examples
416 Examples
420 --------
417 --------
421
418
422 In [1]: class NoInit:
419 In [1]: class NoInit:
423 ...: pass
420 ...: pass
424
421
425 In [2]: class NoDoc:
422 In [2]: class NoDoc:
426 ...: def __init__(self):
423 ...: def __init__(self):
427 ...: pass
424 ...: pass
428
425
429 In [3]: %pdoc NoDoc
426 In [3]: %pdoc NoDoc
430 No documentation found for NoDoc
427 No documentation found for NoDoc
431
428
432 In [4]: %pdoc NoInit
429 In [4]: %pdoc NoInit
433 No documentation found for NoInit
430 No documentation found for NoInit
434
431
435 In [5]: obj = NoInit()
432 In [5]: obj = NoInit()
436
433
437 In [6]: %pdoc obj
434 In [6]: %pdoc obj
438 No documentation found for obj
435 No documentation found for obj
439
436
440 In [5]: obj2 = NoDoc()
437 In [5]: obj2 = NoDoc()
441
438
442 In [6]: %pdoc obj2
439 In [6]: %pdoc obj2
443 No documentation found for obj2
440 No documentation found for obj2
444 """
441 """
445
442
446 head = self.__head # For convenience
443 head = self.__head # For convenience
447 lines = []
444 lines = []
448 ds = getdoc(obj)
445 ds = getdoc(obj)
449 if formatter:
446 if formatter:
450 ds = formatter(ds)
447 ds = formatter(ds)
451 if ds:
448 if ds:
452 lines.append(head("Class Docstring:"))
449 lines.append(head("Class Docstring:"))
453 lines.append(indent(ds))
450 lines.append(indent(ds))
454 if inspect.isclass(obj) and hasattr(obj, '__init__'):
451 if inspect.isclass(obj) and hasattr(obj, '__init__'):
455 init_ds = getdoc(obj.__init__)
452 init_ds = getdoc(obj.__init__)
456 if init_ds is not None:
453 if init_ds is not None:
457 lines.append(head("Constructor Docstring:"))
454 lines.append(head("Constructor Docstring:"))
458 lines.append(indent(init_ds))
455 lines.append(indent(init_ds))
459 elif hasattr(obj,'__call__'):
456 elif hasattr(obj,'__call__'):
460 call_ds = getdoc(obj.__call__)
457 call_ds = getdoc(obj.__call__)
461 if call_ds:
458 if call_ds:
462 lines.append(head("Calling Docstring:"))
459 lines.append(head("Calling Docstring:"))
463 lines.append(indent(call_ds))
460 lines.append(indent(call_ds))
464
461
465 if not lines:
462 if not lines:
466 self.noinfo('documentation',oname)
463 self.noinfo('documentation',oname)
467 else:
464 else:
468 page.page('\n'.join(lines))
465 page.page('\n'.join(lines))
469
466
470 def psource(self,obj,oname=''):
467 def psource(self,obj,oname=''):
471 """Print the source code for an object."""
468 """Print the source code for an object."""
472
469
473 # Flush the source cache because inspect can return out-of-date source
470 # Flush the source cache because inspect can return out-of-date source
474 linecache.checkcache()
471 linecache.checkcache()
475 try:
472 try:
476 src = getsource(obj)
473 src = getsource(obj)
477 except:
474 except:
478 self.noinfo('source',oname)
475 self.noinfo('source',oname)
479 else:
476 else:
480 page.page(self.format(src))
477 page.page(self.format(src))
481
478
482 def pfile(self, obj, oname=''):
479 def pfile(self, obj, oname=''):
483 """Show the whole file where an object was defined."""
480 """Show the whole file where an object was defined."""
484
481
485 lineno = find_source_lines(obj)
482 lineno = find_source_lines(obj)
486 if lineno is None:
483 if lineno is None:
487 self.noinfo('file', oname)
484 self.noinfo('file', oname)
488 return
485 return
489
486
490 ofile = find_file(obj)
487 ofile = find_file(obj)
491 # run contents of file through pager starting at line where the object
488 # run contents of file through pager starting at line where the object
492 # is defined, as long as the file isn't binary and is actually on the
489 # is defined, as long as the file isn't binary and is actually on the
493 # filesystem.
490 # filesystem.
494 if ofile.endswith(('.so', '.dll', '.pyd')):
491 if ofile.endswith(('.so', '.dll', '.pyd')):
495 print('File %r is binary, not printing.' % ofile)
492 print('File %r is binary, not printing.' % ofile)
496 elif not os.path.isfile(ofile):
493 elif not os.path.isfile(ofile):
497 print('File %r does not exist, not printing.' % ofile)
494 print('File %r does not exist, not printing.' % ofile)
498 else:
495 else:
499 # Print only text files, not extension binaries. Note that
496 # Print only text files, not extension binaries. Note that
500 # getsourcelines returns lineno with 1-offset and page() uses
497 # getsourcelines returns lineno with 1-offset and page() uses
501 # 0-offset, so we must adjust.
498 # 0-offset, so we must adjust.
502 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
499 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
503
500
504 def _format_fields(self, fields, title_width=12):
501 def _format_fields(self, fields, title_width=12):
505 """Formats a list of fields for display.
502 """Formats a list of fields for display.
506
503
507 Parameters
504 Parameters
508 ----------
505 ----------
509 fields : list
506 fields : list
510 A list of 2-tuples: (field_title, field_content)
507 A list of 2-tuples: (field_title, field_content)
511 title_width : int
508 title_width : int
512 How many characters to pad titles to. Default 12.
509 How many characters to pad titles to. Default 12.
513 """
510 """
514 out = []
511 out = []
515 header = self.__head
512 header = self.__head
516 for title, content in fields:
513 for title, content in fields:
517 if len(content.splitlines()) > 1:
514 if len(content.splitlines()) > 1:
518 title = header(title + ":") + "\n"
515 title = header(title + ":") + "\n"
519 else:
516 else:
520 title = header((title+":").ljust(title_width))
517 title = header((title+":").ljust(title_width))
521 out.append(cast_unicode(title) + cast_unicode(content))
518 out.append(cast_unicode(title) + cast_unicode(content))
522 return "\n".join(out)
519 return "\n".join(out)
523
520
524 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
521 # The fields to be displayed by pinfo: (fancy_name, key_in_info_dict)
525 pinfo_fields1 = [("Type", "type_name"),
522 pinfo_fields1 = [("Type", "type_name"),
526 ]
523 ]
527
524
528 pinfo_fields2 = [("String Form", "string_form"),
525 pinfo_fields2 = [("String Form", "string_form"),
529 ]
526 ]
530
527
531 pinfo_fields3 = [("Length", "length"),
528 pinfo_fields3 = [("Length", "length"),
532 ("File", "file"),
529 ("File", "file"),
533 ("Definition", "definition"),
530 ("Definition", "definition"),
534 ]
531 ]
535
532
536 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
533 pinfo_fields_obj = [("Class Docstring", "class_docstring"),
537 ("Constructor Docstring","init_docstring"),
534 ("Constructor Docstring","init_docstring"),
538 ("Call def", "call_def"),
535 ("Call def", "call_def"),
539 ("Call docstring", "call_docstring")]
536 ("Call docstring", "call_docstring")]
540
537
541 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
538 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
542 """Show detailed information about an object.
539 """Show detailed information about an object.
543
540
544 Optional arguments:
541 Optional arguments:
545
542
546 - oname: name of the variable pointing to the object.
543 - oname: name of the variable pointing to the object.
547
544
548 - formatter: special formatter for docstrings (see pdoc)
545 - formatter: special formatter for docstrings (see pdoc)
549
546
550 - info: a structure with some information fields which may have been
547 - info: a structure with some information fields which may have been
551 precomputed already.
548 precomputed already.
552
549
553 - detail_level: if set to 1, more information is given.
550 - detail_level: if set to 1, more information is given.
554 """
551 """
555 info = self.info(obj, oname=oname, formatter=formatter,
552 info = self.info(obj, oname=oname, formatter=formatter,
556 info=info, detail_level=detail_level)
553 info=info, detail_level=detail_level)
557 displayfields = []
554 displayfields = []
558 def add_fields(fields):
555 def add_fields(fields):
559 for title, key in fields:
556 for title, key in fields:
560 field = info[key]
557 field = info[key]
561 if field is not None:
558 if field is not None:
562 displayfields.append((title, field.rstrip()))
559 displayfields.append((title, field.rstrip()))
563
560
564 add_fields(self.pinfo_fields1)
561 add_fields(self.pinfo_fields1)
565
562
566 # Base class for old-style instances
563 # Base class for old-style instances
567 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
564 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
568 displayfields.append(("Base Class", info['base_class'].rstrip()))
565 displayfields.append(("Base Class", info['base_class'].rstrip()))
569
566
570 add_fields(self.pinfo_fields2)
567 add_fields(self.pinfo_fields2)
571
568
572 # Namespace
569 # Namespace
573 if info['namespace'] != 'Interactive':
570 if info['namespace'] != 'Interactive':
574 displayfields.append(("Namespace", info['namespace'].rstrip()))
571 displayfields.append(("Namespace", info['namespace'].rstrip()))
575
572
576 add_fields(self.pinfo_fields3)
573 add_fields(self.pinfo_fields3)
577
574
578 # Source or docstring, depending on detail level and whether
575 # Source or docstring, depending on detail level and whether
579 # source found.
576 # source found.
580 if detail_level > 0 and info['source'] is not None:
577 if detail_level > 0 and info['source'] is not None:
581 displayfields.append(("Source",
578 displayfields.append(("Source",
582 self.format(cast_unicode(info['source']))))
579 self.format(cast_unicode(info['source']))))
583 elif info['docstring'] is not None:
580 elif info['docstring'] is not None:
584 displayfields.append(("Docstring", info["docstring"]))
581 displayfields.append(("Docstring", info["docstring"]))
585
582
586 # Constructor info for classes
583 # Constructor info for classes
587 if info['isclass']:
584 if info['isclass']:
588 if info['init_definition'] or info['init_docstring']:
585 if info['init_definition'] or info['init_docstring']:
589 displayfields.append(("Constructor information", ""))
586 displayfields.append(("Constructor information", ""))
590 if info['init_definition'] is not None:
587 if info['init_definition'] is not None:
591 displayfields.append((" Definition",
588 displayfields.append((" Definition",
592 info['init_definition'].rstrip()))
589 info['init_definition'].rstrip()))
593 if info['init_docstring'] is not None:
590 if info['init_docstring'] is not None:
594 displayfields.append((" Docstring",
591 displayfields.append((" Docstring",
595 indent(info['init_docstring'])))
592 indent(info['init_docstring'])))
596
593
597 # Info for objects:
594 # Info for objects:
598 else:
595 else:
599 add_fields(self.pinfo_fields_obj)
596 add_fields(self.pinfo_fields_obj)
600
597
601 # Finally send to printer/pager:
598 # Finally send to printer/pager:
602 if displayfields:
599 if displayfields:
603 page.page(self._format_fields(displayfields))
600 page.page(self._format_fields(displayfields))
604
601
605 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
602 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
606 """Compute a dict with detailed information about an object.
603 """Compute a dict with detailed information about an object.
607
604
608 Optional arguments:
605 Optional arguments:
609
606
610 - oname: name of the variable pointing to the object.
607 - oname: name of the variable pointing to the object.
611
608
612 - formatter: special formatter for docstrings (see pdoc)
609 - formatter: special formatter for docstrings (see pdoc)
613
610
614 - info: a structure with some information fields which may have been
611 - info: a structure with some information fields which may have been
615 precomputed already.
612 precomputed already.
616
613
617 - detail_level: if set to 1, more information is given.
614 - detail_level: if set to 1, more information is given.
618 """
615 """
619
616
620 obj_type = type(obj)
617 obj_type = type(obj)
621
618
622 header = self.__head
619 header = self.__head
623 if info is None:
620 if info is None:
624 ismagic = 0
621 ismagic = 0
625 isalias = 0
622 isalias = 0
626 ospace = ''
623 ospace = ''
627 else:
624 else:
628 ismagic = info.ismagic
625 ismagic = info.ismagic
629 isalias = info.isalias
626 isalias = info.isalias
630 ospace = info.namespace
627 ospace = info.namespace
631
628
632 # Get docstring, special-casing aliases:
629 # Get docstring, special-casing aliases:
633 if isalias:
630 if isalias:
634 if not callable(obj):
631 if not callable(obj):
635 try:
632 try:
636 ds = "Alias to the system command:\n %s" % obj[1]
633 ds = "Alias to the system command:\n %s" % obj[1]
637 except:
634 except:
638 ds = "Alias: " + str(obj)
635 ds = "Alias: " + str(obj)
639 else:
636 else:
640 ds = "Alias to " + str(obj)
637 ds = "Alias to " + str(obj)
641 if obj.__doc__:
638 if obj.__doc__:
642 ds += "\nDocstring:\n" + obj.__doc__
639 ds += "\nDocstring:\n" + obj.__doc__
643 else:
640 else:
644 ds = getdoc(obj)
641 ds = getdoc(obj)
645 if ds is None:
642 if ds is None:
646 ds = '<no docstring>'
643 ds = '<no docstring>'
647 if formatter is not None:
644 if formatter is not None:
648 ds = formatter(ds)
645 ds = formatter(ds)
649
646
650 # store output in a dict, we initialize it here and fill it as we go
647 # store output in a dict, we initialize it here and fill it as we go
651 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
648 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
652
649
653 string_max = 200 # max size of strings to show (snipped if longer)
650 string_max = 200 # max size of strings to show (snipped if longer)
654 shalf = int((string_max -5)/2)
651 shalf = int((string_max -5)/2)
655
652
656 if ismagic:
653 if ismagic:
657 obj_type_name = 'Magic function'
654 obj_type_name = 'Magic function'
658 elif isalias:
655 elif isalias:
659 obj_type_name = 'System alias'
656 obj_type_name = 'System alias'
660 else:
657 else:
661 obj_type_name = obj_type.__name__
658 obj_type_name = obj_type.__name__
662 out['type_name'] = obj_type_name
659 out['type_name'] = obj_type_name
663
660
664 try:
661 try:
665 bclass = obj.__class__
662 bclass = obj.__class__
666 out['base_class'] = str(bclass)
663 out['base_class'] = str(bclass)
667 except: pass
664 except: pass
668
665
669 # String form, but snip if too long in ? form (full in ??)
666 # String form, but snip if too long in ? form (full in ??)
670 if detail_level >= self.str_detail_level:
667 if detail_level >= self.str_detail_level:
671 try:
668 try:
672 ostr = str(obj)
669 ostr = str(obj)
673 str_head = 'string_form'
670 str_head = 'string_form'
674 if not detail_level and len(ostr)>string_max:
671 if not detail_level and len(ostr)>string_max:
675 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
672 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
676 ostr = ("\n" + " " * len(str_head.expandtabs())).\
673 ostr = ("\n" + " " * len(str_head.expandtabs())).\
677 join(q.strip() for q in ostr.split("\n"))
674 join(q.strip() for q in ostr.split("\n"))
678 out[str_head] = ostr
675 out[str_head] = ostr
679 except:
676 except:
680 pass
677 pass
681
678
682 if ospace:
679 if ospace:
683 out['namespace'] = ospace
680 out['namespace'] = ospace
684
681
685 # Length (for strings and lists)
682 # Length (for strings and lists)
686 try:
683 try:
687 out['length'] = str(len(obj))
684 out['length'] = str(len(obj))
688 except: pass
685 except: pass
689
686
690 # Filename where object was defined
687 # Filename where object was defined
691 binary_file = False
688 binary_file = False
692 fname = find_file(obj)
689 fname = find_file(obj)
693 if fname is None:
690 if fname is None:
694 # if anything goes wrong, we don't want to show source, so it's as
691 # if anything goes wrong, we don't want to show source, so it's as
695 # if the file was binary
692 # if the file was binary
696 binary_file = True
693 binary_file = True
697 else:
694 else:
698 if fname.endswith(('.so', '.dll', '.pyd')):
695 if fname.endswith(('.so', '.dll', '.pyd')):
699 binary_file = True
696 binary_file = True
700 elif fname.endswith('<string>'):
697 elif fname.endswith('<string>'):
701 fname = 'Dynamically generated function. No source code available.'
698 fname = 'Dynamically generated function. No source code available.'
702 out['file'] = fname
699 out['file'] = fname
703
700
704 # reconstruct the function definition and print it:
701 # reconstruct the function definition and print it:
705 defln = self._getdef(obj, oname)
702 defln = self._getdef(obj, oname)
706 if defln:
703 if defln:
707 out['definition'] = self.format(defln)
704 out['definition'] = self.format(defln)
708
705
709 # Docstrings only in detail 0 mode, since source contains them (we
706 # Docstrings only in detail 0 mode, since source contains them (we
710 # avoid repetitions). If source fails, we add them back, see below.
707 # avoid repetitions). If source fails, we add them back, see below.
711 if ds and detail_level == 0:
708 if ds and detail_level == 0:
712 out['docstring'] = ds
709 out['docstring'] = ds
713
710
714 # Original source code for any callable
711 # Original source code for any callable
715 if detail_level:
712 if detail_level:
716 # Flush the source cache because inspect can return out-of-date
713 # Flush the source cache because inspect can return out-of-date
717 # source
714 # source
718 linecache.checkcache()
715 linecache.checkcache()
719 source = None
716 source = None
720 try:
717 try:
721 try:
718 try:
722 source = getsource(obj, binary_file)
719 source = getsource(obj, binary_file)
723 except TypeError:
720 except TypeError:
724 if hasattr(obj, '__class__'):
721 if hasattr(obj, '__class__'):
725 source = getsource(obj.__class__, binary_file)
722 source = getsource(obj.__class__, binary_file)
726 if source is not None:
723 if source is not None:
727 out['source'] = source.rstrip()
724 out['source'] = source.rstrip()
728 except Exception:
725 except Exception:
729 pass
726 pass
730
727
731 if ds and source is None:
728 if ds and source is None:
732 out['docstring'] = ds
729 out['docstring'] = ds
733
730
734
731
735 # Constructor docstring for classes
732 # Constructor docstring for classes
736 if inspect.isclass(obj):
733 if inspect.isclass(obj):
737 out['isclass'] = True
734 out['isclass'] = True
738 # reconstruct the function definition and print it:
735 # reconstruct the function definition and print it:
739 try:
736 try:
740 obj_init = obj.__init__
737 obj_init = obj.__init__
741 except AttributeError:
738 except AttributeError:
742 init_def = init_ds = None
739 init_def = init_ds = None
743 else:
740 else:
744 init_def = self._getdef(obj_init,oname)
741 init_def = self._getdef(obj_init,oname)
745 init_ds = getdoc(obj_init)
742 init_ds = getdoc(obj_init)
746 # Skip Python's auto-generated docstrings
743 # Skip Python's auto-generated docstrings
747 if init_ds and \
744 if init_ds and \
748 init_ds.startswith('x.__init__(...) initializes'):
745 init_ds.startswith('x.__init__(...) initializes'):
749 init_ds = None
746 init_ds = None
750
747
751 if init_def or init_ds:
748 if init_def or init_ds:
752 if init_def:
749 if init_def:
753 out['init_definition'] = self.format(init_def)
750 out['init_definition'] = self.format(init_def)
754 if init_ds:
751 if init_ds:
755 out['init_docstring'] = init_ds
752 out['init_docstring'] = init_ds
756
753
757 # and class docstring for instances:
754 # and class docstring for instances:
758 else:
755 else:
759 # First, check whether the instance docstring is identical to the
756 # First, check whether the instance docstring is identical to the
760 # class one, and print it separately if they don't coincide. In
757 # class one, and print it separately if they don't coincide. In
761 # most cases they will, but it's nice to print all the info for
758 # most cases they will, but it's nice to print all the info for
762 # objects which use instance-customized docstrings.
759 # objects which use instance-customized docstrings.
763 if ds:
760 if ds:
764 try:
761 try:
765 cls = getattr(obj,'__class__')
762 cls = getattr(obj,'__class__')
766 except:
763 except:
767 class_ds = None
764 class_ds = None
768 else:
765 else:
769 class_ds = getdoc(cls)
766 class_ds = getdoc(cls)
770 # Skip Python's auto-generated docstrings
767 # Skip Python's auto-generated docstrings
771 if class_ds and \
768 if class_ds and \
772 (class_ds.startswith('function(code, globals[,') or \
769 (class_ds.startswith('function(code, globals[,') or \
773 class_ds.startswith('instancemethod(function, instance,') or \
770 class_ds.startswith('instancemethod(function, instance,') or \
774 class_ds.startswith('module(name[,') ):
771 class_ds.startswith('module(name[,') ):
775 class_ds = None
772 class_ds = None
776 if class_ds and ds != class_ds:
773 if class_ds and ds != class_ds:
777 out['class_docstring'] = class_ds
774 out['class_docstring'] = class_ds
778
775
779 # Next, try to show constructor docstrings
776 # Next, try to show constructor docstrings
780 try:
777 try:
781 init_ds = getdoc(obj.__init__)
778 init_ds = getdoc(obj.__init__)
782 # Skip Python's auto-generated docstrings
779 # Skip Python's auto-generated docstrings
783 if init_ds and \
780 if init_ds and \
784 init_ds.startswith('x.__init__(...) initializes'):
781 init_ds.startswith('x.__init__(...) initializes'):
785 init_ds = None
782 init_ds = None
786 except AttributeError:
783 except AttributeError:
787 init_ds = None
784 init_ds = None
788 if init_ds:
785 if init_ds:
789 out['init_docstring'] = init_ds
786 out['init_docstring'] = init_ds
790
787
791 # Call form docstring for callable instances
788 # Call form docstring for callable instances
792 if safe_hasattr(obj, '__call__'):
789 if safe_hasattr(obj, '__call__'):
793 call_def = self._getdef(obj.__call__, oname)
790 call_def = self._getdef(obj.__call__, oname)
794 if call_def is not None:
791 if call_def is not None:
795 out['call_def'] = self.format(call_def)
792 out['call_def'] = self.format(call_def)
796 call_ds = getdoc(obj.__call__)
793 call_ds = getdoc(obj.__call__)
797 # Skip Python's auto-generated docstrings
794 # Skip Python's auto-generated docstrings
798 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
795 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
799 call_ds = None
796 call_ds = None
800 if call_ds:
797 if call_ds:
801 out['call_docstring'] = call_ds
798 out['call_docstring'] = call_ds
802
799
803 # Compute the object's argspec as a callable. The key is to decide
800 # Compute the object's argspec as a callable. The key is to decide
804 # whether to pull it from the object itself, from its __init__ or
801 # whether to pull it from the object itself, from its __init__ or
805 # from its __call__ method.
802 # from its __call__ method.
806
803
807 if inspect.isclass(obj):
804 if inspect.isclass(obj):
808 # Old-style classes need not have an __init__
805 # Old-style classes need not have an __init__
809 callable_obj = getattr(obj, "__init__", None)
806 callable_obj = getattr(obj, "__init__", None)
810 elif callable(obj):
807 elif callable(obj):
811 callable_obj = obj
808 callable_obj = obj
812 else:
809 else:
813 callable_obj = None
810 callable_obj = None
814
811
815 if callable_obj:
812 if callable_obj:
816 try:
813 try:
817 args, varargs, varkw, defaults = getargspec(callable_obj)
814 args, varargs, varkw, defaults = getargspec(callable_obj)
818 except (TypeError, AttributeError):
815 except (TypeError, AttributeError):
819 # For extensions/builtins we can't retrieve the argspec
816 # For extensions/builtins we can't retrieve the argspec
820 pass
817 pass
821 else:
818 else:
822 out['argspec'] = dict(args=args, varargs=varargs,
819 out['argspec'] = dict(args=args, varargs=varargs,
823 varkw=varkw, defaults=defaults)
820 varkw=varkw, defaults=defaults)
824
821
825 return object_info(**out)
822 return object_info(**out)
826
823
827
824
828 def psearch(self,pattern,ns_table,ns_search=[],
825 def psearch(self,pattern,ns_table,ns_search=[],
829 ignore_case=False,show_all=False):
826 ignore_case=False,show_all=False):
830 """Search namespaces with wildcards for objects.
827 """Search namespaces with wildcards for objects.
831
828
832 Arguments:
829 Arguments:
833
830
834 - pattern: string containing shell-like wildcards to use in namespace
831 - pattern: string containing shell-like wildcards to use in namespace
835 searches and optionally a type specification to narrow the search to
832 searches and optionally a type specification to narrow the search to
836 objects of that type.
833 objects of that type.
837
834
838 - ns_table: dict of name->namespaces for search.
835 - ns_table: dict of name->namespaces for search.
839
836
840 Optional arguments:
837 Optional arguments:
841
838
842 - ns_search: list of namespace names to include in search.
839 - ns_search: list of namespace names to include in search.
843
840
844 - ignore_case(False): make the search case-insensitive.
841 - ignore_case(False): make the search case-insensitive.
845
842
846 - show_all(False): show all names, including those starting with
843 - show_all(False): show all names, including those starting with
847 underscores.
844 underscores.
848 """
845 """
849 #print 'ps pattern:<%r>' % pattern # dbg
846 #print 'ps pattern:<%r>' % pattern # dbg
850
847
851 # defaults
848 # defaults
852 type_pattern = 'all'
849 type_pattern = 'all'
853 filter = ''
850 filter = ''
854
851
855 cmds = pattern.split()
852 cmds = pattern.split()
856 len_cmds = len(cmds)
853 len_cmds = len(cmds)
857 if len_cmds == 1:
854 if len_cmds == 1:
858 # Only filter pattern given
855 # Only filter pattern given
859 filter = cmds[0]
856 filter = cmds[0]
860 elif len_cmds == 2:
857 elif len_cmds == 2:
861 # Both filter and type specified
858 # Both filter and type specified
862 filter,type_pattern = cmds
859 filter,type_pattern = cmds
863 else:
860 else:
864 raise ValueError('invalid argument string for psearch: <%s>' %
861 raise ValueError('invalid argument string for psearch: <%s>' %
865 pattern)
862 pattern)
866
863
867 # filter search namespaces
864 # filter search namespaces
868 for name in ns_search:
865 for name in ns_search:
869 if name not in ns_table:
866 if name not in ns_table:
870 raise ValueError('invalid namespace <%s>. Valid names: %s' %
867 raise ValueError('invalid namespace <%s>. Valid names: %s' %
871 (name,ns_table.keys()))
868 (name,ns_table.keys()))
872
869
873 #print 'type_pattern:',type_pattern # dbg
870 #print 'type_pattern:',type_pattern # dbg
874 search_result, namespaces_seen = set(), set()
871 search_result, namespaces_seen = set(), set()
875 for ns_name in ns_search:
872 for ns_name in ns_search:
876 ns = ns_table[ns_name]
873 ns = ns_table[ns_name]
877 # Normally, locals and globals are the same, so we just check one.
874 # Normally, locals and globals are the same, so we just check one.
878 if id(ns) in namespaces_seen:
875 if id(ns) in namespaces_seen:
879 continue
876 continue
880 namespaces_seen.add(id(ns))
877 namespaces_seen.add(id(ns))
881 tmp_res = list_namespace(ns, type_pattern, filter,
878 tmp_res = list_namespace(ns, type_pattern, filter,
882 ignore_case=ignore_case, show_all=show_all)
879 ignore_case=ignore_case, show_all=show_all)
883 search_result.update(tmp_res)
880 search_result.update(tmp_res)
884
881
885 page.page('\n'.join(sorted(search_result)))
882 page.page('\n'.join(sorted(search_result)))
@@ -1,749 +1,745 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Prefiltering components.
3 Prefiltering components.
4
4
5 Prefilters transform user input before it is exec'd by Python. These
5 Prefilters transform user input before it is exec'd by Python. These
6 transforms are used to implement additional syntax such as !ls and %magic.
6 transforms are used to implement additional syntax such as !ls and %magic.
7
7
8 Authors:
8 Authors:
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Dan Milstein
12 * Dan Milstein
13 * Ville Vainio
13 * Ville Vainio
14 """
14 """
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Copyright (C) 2008-2011 The IPython Development Team
17 # Copyright (C) 2008-2011 The IPython Development Team
18 #
18 #
19 # Distributed under the terms of the BSD License. The full license is in
19 # Distributed under the terms of the BSD License. The full license is in
20 # the file COPYING, distributed as part of this software.
20 # the file COPYING, distributed as part of this software.
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Imports
24 # Imports
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 import re
27 import re
28
28
29 from IPython.core.autocall import IPyAutocall
29 from IPython.core.autocall import IPyAutocall
30 from IPython.config.configurable import Configurable
30 from IPython.config.configurable import Configurable
31 from IPython.core.inputsplitter import (
31 from IPython.core.inputsplitter import (
32 ESC_SHELL,
33 ESC_SH_CAP,
34 ESC_HELP,
35 ESC_MAGIC,
32 ESC_MAGIC,
36 ESC_MAGIC2,
37 ESC_QUOTE,
33 ESC_QUOTE,
38 ESC_QUOTE2,
34 ESC_QUOTE2,
39 ESC_PAREN,
35 ESC_PAREN,
40 )
36 )
41 from IPython.core.macro import Macro
37 from IPython.core.macro import Macro
42 from IPython.core.splitinput import LineInfo
38 from IPython.core.splitinput import LineInfo
43
39
44 from IPython.utils.traitlets import (
40 from IPython.utils.traitlets import (
45 List, Integer, Unicode, CBool, Bool, Instance, CRegExp
41 List, Integer, Unicode, CBool, Bool, Instance, CRegExp
46 )
42 )
47
43
48 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
49 # Global utilities, errors and constants
45 # Global utilities, errors and constants
50 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
51
47
52
48
53 class PrefilterError(Exception):
49 class PrefilterError(Exception):
54 pass
50 pass
55
51
56
52
57 # RegExp to identify potential function names
53 # RegExp to identify potential function names
58 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
54 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
59
55
60 # RegExp to exclude strings with this start from autocalling. In
56 # RegExp to exclude strings with this start from autocalling. In
61 # particular, all binary operators should be excluded, so that if foo is
57 # particular, all binary operators should be excluded, so that if foo is
62 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
58 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
63 # characters '!=()' don't need to be checked for, as the checkPythonChars
59 # characters '!=()' don't need to be checked for, as the checkPythonChars
64 # routine explicitely does so, to catch direct calls and rebindings of
60 # routine explicitely does so, to catch direct calls and rebindings of
65 # existing names.
61 # existing names.
66
62
67 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
63 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
68 # it affects the rest of the group in square brackets.
64 # it affects the rest of the group in square brackets.
69 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
65 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
70 r'|^is |^not |^in |^and |^or ')
66 r'|^is |^not |^in |^and |^or ')
71
67
72 # try to catch also methods for stuff in lists/tuples/dicts: off
68 # try to catch also methods for stuff in lists/tuples/dicts: off
73 # (experimental). For this to work, the line_split regexp would need
69 # (experimental). For this to work, the line_split regexp would need
74 # to be modified so it wouldn't break things at '['. That line is
70 # to be modified so it wouldn't break things at '['. That line is
75 # nasty enough that I shouldn't change it until I can test it _well_.
71 # nasty enough that I shouldn't change it until I can test it _well_.
76 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
72 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
77
73
78
74
79 # Handler Check Utilities
75 # Handler Check Utilities
80 def is_shadowed(identifier, ip):
76 def is_shadowed(identifier, ip):
81 """Is the given identifier defined in one of the namespaces which shadow
77 """Is the given identifier defined in one of the namespaces which shadow
82 the alias and magic namespaces? Note that an identifier is different
78 the alias and magic namespaces? Note that an identifier is different
83 than ifun, because it can not contain a '.' character."""
79 than ifun, because it can not contain a '.' character."""
84 # This is much safer than calling ofind, which can change state
80 # This is much safer than calling ofind, which can change state
85 return (identifier in ip.user_ns \
81 return (identifier in ip.user_ns \
86 or identifier in ip.user_global_ns \
82 or identifier in ip.user_global_ns \
87 or identifier in ip.ns_table['builtin'])
83 or identifier in ip.ns_table['builtin'])
88
84
89
85
90 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
91 # Main Prefilter manager
87 # Main Prefilter manager
92 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
93
89
94
90
95 class PrefilterManager(Configurable):
91 class PrefilterManager(Configurable):
96 """Main prefilter component.
92 """Main prefilter component.
97
93
98 The IPython prefilter is run on all user input before it is run. The
94 The IPython prefilter is run on all user input before it is run. The
99 prefilter consumes lines of input and produces transformed lines of
95 prefilter consumes lines of input and produces transformed lines of
100 input.
96 input.
101
97
102 The iplementation consists of two phases:
98 The iplementation consists of two phases:
103
99
104 1. Transformers
100 1. Transformers
105 2. Checkers and handlers
101 2. Checkers and handlers
106
102
107 Over time, we plan on deprecating the checkers and handlers and doing
103 Over time, we plan on deprecating the checkers and handlers and doing
108 everything in the transformers.
104 everything in the transformers.
109
105
110 The transformers are instances of :class:`PrefilterTransformer` and have
106 The transformers are instances of :class:`PrefilterTransformer` and have
111 a single method :meth:`transform` that takes a line and returns a
107 a single method :meth:`transform` that takes a line and returns a
112 transformed line. The transformation can be accomplished using any
108 transformed line. The transformation can be accomplished using any
113 tool, but our current ones use regular expressions for speed.
109 tool, but our current ones use regular expressions for speed.
114
110
115 After all the transformers have been run, the line is fed to the checkers,
111 After all the transformers have been run, the line is fed to the checkers,
116 which are instances of :class:`PrefilterChecker`. The line is passed to
112 which are instances of :class:`PrefilterChecker`. The line is passed to
117 the :meth:`check` method, which either returns `None` or a
113 the :meth:`check` method, which either returns `None` or a
118 :class:`PrefilterHandler` instance. If `None` is returned, the other
114 :class:`PrefilterHandler` instance. If `None` is returned, the other
119 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
115 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
120 the line is passed to the :meth:`handle` method of the returned
116 the line is passed to the :meth:`handle` method of the returned
121 handler and no further checkers are tried.
117 handler and no further checkers are tried.
122
118
123 Both transformers and checkers have a `priority` attribute, that determines
119 Both transformers and checkers have a `priority` attribute, that determines
124 the order in which they are called. Smaller priorities are tried first.
120 the order in which they are called. Smaller priorities are tried first.
125
121
126 Both transformers and checkers also have `enabled` attribute, which is
122 Both transformers and checkers also have `enabled` attribute, which is
127 a boolean that determines if the instance is used.
123 a boolean that determines if the instance is used.
128
124
129 Users or developers can change the priority or enabled attribute of
125 Users or developers can change the priority or enabled attribute of
130 transformers or checkers, but they must call the :meth:`sort_checkers`
126 transformers or checkers, but they must call the :meth:`sort_checkers`
131 or :meth:`sort_transformers` method after changing the priority.
127 or :meth:`sort_transformers` method after changing the priority.
132 """
128 """
133
129
134 multi_line_specials = CBool(True, config=True)
130 multi_line_specials = CBool(True, config=True)
135 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
131 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
136
132
137 def __init__(self, shell=None, **kwargs):
133 def __init__(self, shell=None, **kwargs):
138 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
134 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
139 self.shell = shell
135 self.shell = shell
140 self.init_transformers()
136 self.init_transformers()
141 self.init_handlers()
137 self.init_handlers()
142 self.init_checkers()
138 self.init_checkers()
143
139
144 #-------------------------------------------------------------------------
140 #-------------------------------------------------------------------------
145 # API for managing transformers
141 # API for managing transformers
146 #-------------------------------------------------------------------------
142 #-------------------------------------------------------------------------
147
143
148 def init_transformers(self):
144 def init_transformers(self):
149 """Create the default transformers."""
145 """Create the default transformers."""
150 self._transformers = []
146 self._transformers = []
151 for transformer_cls in _default_transformers:
147 for transformer_cls in _default_transformers:
152 transformer_cls(
148 transformer_cls(
153 shell=self.shell, prefilter_manager=self, parent=self
149 shell=self.shell, prefilter_manager=self, parent=self
154 )
150 )
155
151
156 def sort_transformers(self):
152 def sort_transformers(self):
157 """Sort the transformers by priority.
153 """Sort the transformers by priority.
158
154
159 This must be called after the priority of a transformer is changed.
155 This must be called after the priority of a transformer is changed.
160 The :meth:`register_transformer` method calls this automatically.
156 The :meth:`register_transformer` method calls this automatically.
161 """
157 """
162 self._transformers.sort(key=lambda x: x.priority)
158 self._transformers.sort(key=lambda x: x.priority)
163
159
164 @property
160 @property
165 def transformers(self):
161 def transformers(self):
166 """Return a list of checkers, sorted by priority."""
162 """Return a list of checkers, sorted by priority."""
167 return self._transformers
163 return self._transformers
168
164
169 def register_transformer(self, transformer):
165 def register_transformer(self, transformer):
170 """Register a transformer instance."""
166 """Register a transformer instance."""
171 if transformer not in self._transformers:
167 if transformer not in self._transformers:
172 self._transformers.append(transformer)
168 self._transformers.append(transformer)
173 self.sort_transformers()
169 self.sort_transformers()
174
170
175 def unregister_transformer(self, transformer):
171 def unregister_transformer(self, transformer):
176 """Unregister a transformer instance."""
172 """Unregister a transformer instance."""
177 if transformer in self._transformers:
173 if transformer in self._transformers:
178 self._transformers.remove(transformer)
174 self._transformers.remove(transformer)
179
175
180 #-------------------------------------------------------------------------
176 #-------------------------------------------------------------------------
181 # API for managing checkers
177 # API for managing checkers
182 #-------------------------------------------------------------------------
178 #-------------------------------------------------------------------------
183
179
184 def init_checkers(self):
180 def init_checkers(self):
185 """Create the default checkers."""
181 """Create the default checkers."""
186 self._checkers = []
182 self._checkers = []
187 for checker in _default_checkers:
183 for checker in _default_checkers:
188 checker(
184 checker(
189 shell=self.shell, prefilter_manager=self, parent=self
185 shell=self.shell, prefilter_manager=self, parent=self
190 )
186 )
191
187
192 def sort_checkers(self):
188 def sort_checkers(self):
193 """Sort the checkers by priority.
189 """Sort the checkers by priority.
194
190
195 This must be called after the priority of a checker is changed.
191 This must be called after the priority of a checker is changed.
196 The :meth:`register_checker` method calls this automatically.
192 The :meth:`register_checker` method calls this automatically.
197 """
193 """
198 self._checkers.sort(key=lambda x: x.priority)
194 self._checkers.sort(key=lambda x: x.priority)
199
195
200 @property
196 @property
201 def checkers(self):
197 def checkers(self):
202 """Return a list of checkers, sorted by priority."""
198 """Return a list of checkers, sorted by priority."""
203 return self._checkers
199 return self._checkers
204
200
205 def register_checker(self, checker):
201 def register_checker(self, checker):
206 """Register a checker instance."""
202 """Register a checker instance."""
207 if checker not in self._checkers:
203 if checker not in self._checkers:
208 self._checkers.append(checker)
204 self._checkers.append(checker)
209 self.sort_checkers()
205 self.sort_checkers()
210
206
211 def unregister_checker(self, checker):
207 def unregister_checker(self, checker):
212 """Unregister a checker instance."""
208 """Unregister a checker instance."""
213 if checker in self._checkers:
209 if checker in self._checkers:
214 self._checkers.remove(checker)
210 self._checkers.remove(checker)
215
211
216 #-------------------------------------------------------------------------
212 #-------------------------------------------------------------------------
217 # API for managing checkers
213 # API for managing checkers
218 #-------------------------------------------------------------------------
214 #-------------------------------------------------------------------------
219
215
220 def init_handlers(self):
216 def init_handlers(self):
221 """Create the default handlers."""
217 """Create the default handlers."""
222 self._handlers = {}
218 self._handlers = {}
223 self._esc_handlers = {}
219 self._esc_handlers = {}
224 for handler in _default_handlers:
220 for handler in _default_handlers:
225 handler(
221 handler(
226 shell=self.shell, prefilter_manager=self, parent=self
222 shell=self.shell, prefilter_manager=self, parent=self
227 )
223 )
228
224
229 @property
225 @property
230 def handlers(self):
226 def handlers(self):
231 """Return a dict of all the handlers."""
227 """Return a dict of all the handlers."""
232 return self._handlers
228 return self._handlers
233
229
234 def register_handler(self, name, handler, esc_strings):
230 def register_handler(self, name, handler, esc_strings):
235 """Register a handler instance by name with esc_strings."""
231 """Register a handler instance by name with esc_strings."""
236 self._handlers[name] = handler
232 self._handlers[name] = handler
237 for esc_str in esc_strings:
233 for esc_str in esc_strings:
238 self._esc_handlers[esc_str] = handler
234 self._esc_handlers[esc_str] = handler
239
235
240 def unregister_handler(self, name, handler, esc_strings):
236 def unregister_handler(self, name, handler, esc_strings):
241 """Unregister a handler instance by name with esc_strings."""
237 """Unregister a handler instance by name with esc_strings."""
242 try:
238 try:
243 del self._handlers[name]
239 del self._handlers[name]
244 except KeyError:
240 except KeyError:
245 pass
241 pass
246 for esc_str in esc_strings:
242 for esc_str in esc_strings:
247 h = self._esc_handlers.get(esc_str)
243 h = self._esc_handlers.get(esc_str)
248 if h is handler:
244 if h is handler:
249 del self._esc_handlers[esc_str]
245 del self._esc_handlers[esc_str]
250
246
251 def get_handler_by_name(self, name):
247 def get_handler_by_name(self, name):
252 """Get a handler by its name."""
248 """Get a handler by its name."""
253 return self._handlers.get(name)
249 return self._handlers.get(name)
254
250
255 def get_handler_by_esc(self, esc_str):
251 def get_handler_by_esc(self, esc_str):
256 """Get a handler by its escape string."""
252 """Get a handler by its escape string."""
257 return self._esc_handlers.get(esc_str)
253 return self._esc_handlers.get(esc_str)
258
254
259 #-------------------------------------------------------------------------
255 #-------------------------------------------------------------------------
260 # Main prefiltering API
256 # Main prefiltering API
261 #-------------------------------------------------------------------------
257 #-------------------------------------------------------------------------
262
258
263 def prefilter_line_info(self, line_info):
259 def prefilter_line_info(self, line_info):
264 """Prefilter a line that has been converted to a LineInfo object.
260 """Prefilter a line that has been converted to a LineInfo object.
265
261
266 This implements the checker/handler part of the prefilter pipe.
262 This implements the checker/handler part of the prefilter pipe.
267 """
263 """
268 # print "prefilter_line_info: ", line_info
264 # print "prefilter_line_info: ", line_info
269 handler = self.find_handler(line_info)
265 handler = self.find_handler(line_info)
270 return handler.handle(line_info)
266 return handler.handle(line_info)
271
267
272 def find_handler(self, line_info):
268 def find_handler(self, line_info):
273 """Find a handler for the line_info by trying checkers."""
269 """Find a handler for the line_info by trying checkers."""
274 for checker in self.checkers:
270 for checker in self.checkers:
275 if checker.enabled:
271 if checker.enabled:
276 handler = checker.check(line_info)
272 handler = checker.check(line_info)
277 if handler:
273 if handler:
278 return handler
274 return handler
279 return self.get_handler_by_name('normal')
275 return self.get_handler_by_name('normal')
280
276
281 def transform_line(self, line, continue_prompt):
277 def transform_line(self, line, continue_prompt):
282 """Calls the enabled transformers in order of increasing priority."""
278 """Calls the enabled transformers in order of increasing priority."""
283 for transformer in self.transformers:
279 for transformer in self.transformers:
284 if transformer.enabled:
280 if transformer.enabled:
285 line = transformer.transform(line, continue_prompt)
281 line = transformer.transform(line, continue_prompt)
286 return line
282 return line
287
283
288 def prefilter_line(self, line, continue_prompt=False):
284 def prefilter_line(self, line, continue_prompt=False):
289 """Prefilter a single input line as text.
285 """Prefilter a single input line as text.
290
286
291 This method prefilters a single line of text by calling the
287 This method prefilters a single line of text by calling the
292 transformers and then the checkers/handlers.
288 transformers and then the checkers/handlers.
293 """
289 """
294
290
295 # print "prefilter_line: ", line, continue_prompt
291 # print "prefilter_line: ", line, continue_prompt
296 # All handlers *must* return a value, even if it's blank ('').
292 # All handlers *must* return a value, even if it's blank ('').
297
293
298 # save the line away in case we crash, so the post-mortem handler can
294 # save the line away in case we crash, so the post-mortem handler can
299 # record it
295 # record it
300 self.shell._last_input_line = line
296 self.shell._last_input_line = line
301
297
302 if not line:
298 if not line:
303 # Return immediately on purely empty lines, so that if the user
299 # Return immediately on purely empty lines, so that if the user
304 # previously typed some whitespace that started a continuation
300 # previously typed some whitespace that started a continuation
305 # prompt, he can break out of that loop with just an empty line.
301 # prompt, he can break out of that loop with just an empty line.
306 # This is how the default python prompt works.
302 # This is how the default python prompt works.
307 return ''
303 return ''
308
304
309 # At this point, we invoke our transformers.
305 # At this point, we invoke our transformers.
310 if not continue_prompt or (continue_prompt and self.multi_line_specials):
306 if not continue_prompt or (continue_prompt and self.multi_line_specials):
311 line = self.transform_line(line, continue_prompt)
307 line = self.transform_line(line, continue_prompt)
312
308
313 # Now we compute line_info for the checkers and handlers
309 # Now we compute line_info for the checkers and handlers
314 line_info = LineInfo(line, continue_prompt)
310 line_info = LineInfo(line, continue_prompt)
315
311
316 # the input history needs to track even empty lines
312 # the input history needs to track even empty lines
317 stripped = line.strip()
313 stripped = line.strip()
318
314
319 normal_handler = self.get_handler_by_name('normal')
315 normal_handler = self.get_handler_by_name('normal')
320 if not stripped:
316 if not stripped:
321 return normal_handler.handle(line_info)
317 return normal_handler.handle(line_info)
322
318
323 # special handlers are only allowed for single line statements
319 # special handlers are only allowed for single line statements
324 if continue_prompt and not self.multi_line_specials:
320 if continue_prompt and not self.multi_line_specials:
325 return normal_handler.handle(line_info)
321 return normal_handler.handle(line_info)
326
322
327 prefiltered = self.prefilter_line_info(line_info)
323 prefiltered = self.prefilter_line_info(line_info)
328 # print "prefiltered line: %r" % prefiltered
324 # print "prefiltered line: %r" % prefiltered
329 return prefiltered
325 return prefiltered
330
326
331 def prefilter_lines(self, lines, continue_prompt=False):
327 def prefilter_lines(self, lines, continue_prompt=False):
332 """Prefilter multiple input lines of text.
328 """Prefilter multiple input lines of text.
333
329
334 This is the main entry point for prefiltering multiple lines of
330 This is the main entry point for prefiltering multiple lines of
335 input. This simply calls :meth:`prefilter_line` for each line of
331 input. This simply calls :meth:`prefilter_line` for each line of
336 input.
332 input.
337
333
338 This covers cases where there are multiple lines in the user entry,
334 This covers cases where there are multiple lines in the user entry,
339 which is the case when the user goes back to a multiline history
335 which is the case when the user goes back to a multiline history
340 entry and presses enter.
336 entry and presses enter.
341 """
337 """
342 llines = lines.rstrip('\n').split('\n')
338 llines = lines.rstrip('\n').split('\n')
343 # We can get multiple lines in one shot, where multiline input 'blends'
339 # We can get multiple lines in one shot, where multiline input 'blends'
344 # into one line, in cases like recalling from the readline history
340 # into one line, in cases like recalling from the readline history
345 # buffer. We need to make sure that in such cases, we correctly
341 # buffer. We need to make sure that in such cases, we correctly
346 # communicate downstream which line is first and which are continuation
342 # communicate downstream which line is first and which are continuation
347 # ones.
343 # ones.
348 if len(llines) > 1:
344 if len(llines) > 1:
349 out = '\n'.join([self.prefilter_line(line, lnum>0)
345 out = '\n'.join([self.prefilter_line(line, lnum>0)
350 for lnum, line in enumerate(llines) ])
346 for lnum, line in enumerate(llines) ])
351 else:
347 else:
352 out = self.prefilter_line(llines[0], continue_prompt)
348 out = self.prefilter_line(llines[0], continue_prompt)
353
349
354 return out
350 return out
355
351
356 #-----------------------------------------------------------------------------
352 #-----------------------------------------------------------------------------
357 # Prefilter transformers
353 # Prefilter transformers
358 #-----------------------------------------------------------------------------
354 #-----------------------------------------------------------------------------
359
355
360
356
361 class PrefilterTransformer(Configurable):
357 class PrefilterTransformer(Configurable):
362 """Transform a line of user input."""
358 """Transform a line of user input."""
363
359
364 priority = Integer(100, config=True)
360 priority = Integer(100, config=True)
365 # Transformers don't currently use shell or prefilter_manager, but as we
361 # Transformers don't currently use shell or prefilter_manager, but as we
366 # move away from checkers and handlers, they will need them.
362 # move away from checkers and handlers, they will need them.
367 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
363 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
368 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
364 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
369 enabled = Bool(True, config=True)
365 enabled = Bool(True, config=True)
370
366
371 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
367 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
372 super(PrefilterTransformer, self).__init__(
368 super(PrefilterTransformer, self).__init__(
373 shell=shell, prefilter_manager=prefilter_manager, **kwargs
369 shell=shell, prefilter_manager=prefilter_manager, **kwargs
374 )
370 )
375 self.prefilter_manager.register_transformer(self)
371 self.prefilter_manager.register_transformer(self)
376
372
377 def transform(self, line, continue_prompt):
373 def transform(self, line, continue_prompt):
378 """Transform a line, returning the new one."""
374 """Transform a line, returning the new one."""
379 return None
375 return None
380
376
381 def __repr__(self):
377 def __repr__(self):
382 return "<%s(priority=%r, enabled=%r)>" % (
378 return "<%s(priority=%r, enabled=%r)>" % (
383 self.__class__.__name__, self.priority, self.enabled)
379 self.__class__.__name__, self.priority, self.enabled)
384
380
385
381
386 #-----------------------------------------------------------------------------
382 #-----------------------------------------------------------------------------
387 # Prefilter checkers
383 # Prefilter checkers
388 #-----------------------------------------------------------------------------
384 #-----------------------------------------------------------------------------
389
385
390
386
391 class PrefilterChecker(Configurable):
387 class PrefilterChecker(Configurable):
392 """Inspect an input line and return a handler for that line."""
388 """Inspect an input line and return a handler for that line."""
393
389
394 priority = Integer(100, config=True)
390 priority = Integer(100, config=True)
395 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
391 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
396 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
392 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
397 enabled = Bool(True, config=True)
393 enabled = Bool(True, config=True)
398
394
399 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
395 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
400 super(PrefilterChecker, self).__init__(
396 super(PrefilterChecker, self).__init__(
401 shell=shell, prefilter_manager=prefilter_manager, **kwargs
397 shell=shell, prefilter_manager=prefilter_manager, **kwargs
402 )
398 )
403 self.prefilter_manager.register_checker(self)
399 self.prefilter_manager.register_checker(self)
404
400
405 def check(self, line_info):
401 def check(self, line_info):
406 """Inspect line_info and return a handler instance or None."""
402 """Inspect line_info and return a handler instance or None."""
407 return None
403 return None
408
404
409 def __repr__(self):
405 def __repr__(self):
410 return "<%s(priority=%r, enabled=%r)>" % (
406 return "<%s(priority=%r, enabled=%r)>" % (
411 self.__class__.__name__, self.priority, self.enabled)
407 self.__class__.__name__, self.priority, self.enabled)
412
408
413
409
414 class EmacsChecker(PrefilterChecker):
410 class EmacsChecker(PrefilterChecker):
415
411
416 priority = Integer(100, config=True)
412 priority = Integer(100, config=True)
417 enabled = Bool(False, config=True)
413 enabled = Bool(False, config=True)
418
414
419 def check(self, line_info):
415 def check(self, line_info):
420 "Emacs ipython-mode tags certain input lines."
416 "Emacs ipython-mode tags certain input lines."
421 if line_info.line.endswith('# PYTHON-MODE'):
417 if line_info.line.endswith('# PYTHON-MODE'):
422 return self.prefilter_manager.get_handler_by_name('emacs')
418 return self.prefilter_manager.get_handler_by_name('emacs')
423 else:
419 else:
424 return None
420 return None
425
421
426
422
427 class MacroChecker(PrefilterChecker):
423 class MacroChecker(PrefilterChecker):
428
424
429 priority = Integer(250, config=True)
425 priority = Integer(250, config=True)
430
426
431 def check(self, line_info):
427 def check(self, line_info):
432 obj = self.shell.user_ns.get(line_info.ifun)
428 obj = self.shell.user_ns.get(line_info.ifun)
433 if isinstance(obj, Macro):
429 if isinstance(obj, Macro):
434 return self.prefilter_manager.get_handler_by_name('macro')
430 return self.prefilter_manager.get_handler_by_name('macro')
435 else:
431 else:
436 return None
432 return None
437
433
438
434
439 class IPyAutocallChecker(PrefilterChecker):
435 class IPyAutocallChecker(PrefilterChecker):
440
436
441 priority = Integer(300, config=True)
437 priority = Integer(300, config=True)
442
438
443 def check(self, line_info):
439 def check(self, line_info):
444 "Instances of IPyAutocall in user_ns get autocalled immediately"
440 "Instances of IPyAutocall in user_ns get autocalled immediately"
445 obj = self.shell.user_ns.get(line_info.ifun, None)
441 obj = self.shell.user_ns.get(line_info.ifun, None)
446 if isinstance(obj, IPyAutocall):
442 if isinstance(obj, IPyAutocall):
447 obj.set_ip(self.shell)
443 obj.set_ip(self.shell)
448 return self.prefilter_manager.get_handler_by_name('auto')
444 return self.prefilter_manager.get_handler_by_name('auto')
449 else:
445 else:
450 return None
446 return None
451
447
452
448
453 class AssignmentChecker(PrefilterChecker):
449 class AssignmentChecker(PrefilterChecker):
454
450
455 priority = Integer(600, config=True)
451 priority = Integer(600, config=True)
456
452
457 def check(self, line_info):
453 def check(self, line_info):
458 """Check to see if user is assigning to a var for the first time, in
454 """Check to see if user is assigning to a var for the first time, in
459 which case we want to avoid any sort of automagic / autocall games.
455 which case we want to avoid any sort of automagic / autocall games.
460
456
461 This allows users to assign to either alias or magic names true python
457 This allows users to assign to either alias or magic names true python
462 variables (the magic/alias systems always take second seat to true
458 variables (the magic/alias systems always take second seat to true
463 python code). E.g. ls='hi', or ls,that=1,2"""
459 python code). E.g. ls='hi', or ls,that=1,2"""
464 if line_info.the_rest:
460 if line_info.the_rest:
465 if line_info.the_rest[0] in '=,':
461 if line_info.the_rest[0] in '=,':
466 return self.prefilter_manager.get_handler_by_name('normal')
462 return self.prefilter_manager.get_handler_by_name('normal')
467 else:
463 else:
468 return None
464 return None
469
465
470
466
471 class AutoMagicChecker(PrefilterChecker):
467 class AutoMagicChecker(PrefilterChecker):
472
468
473 priority = Integer(700, config=True)
469 priority = Integer(700, config=True)
474
470
475 def check(self, line_info):
471 def check(self, line_info):
476 """If the ifun is magic, and automagic is on, run it. Note: normal,
472 """If the ifun is magic, and automagic is on, run it. Note: normal,
477 non-auto magic would already have been triggered via '%' in
473 non-auto magic would already have been triggered via '%' in
478 check_esc_chars. This just checks for automagic. Also, before
474 check_esc_chars. This just checks for automagic. Also, before
479 triggering the magic handler, make sure that there is nothing in the
475 triggering the magic handler, make sure that there is nothing in the
480 user namespace which could shadow it."""
476 user namespace which could shadow it."""
481 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
477 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
482 return None
478 return None
483
479
484 # We have a likely magic method. Make sure we should actually call it.
480 # We have a likely magic method. Make sure we should actually call it.
485 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
481 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
486 return None
482 return None
487
483
488 head = line_info.ifun.split('.',1)[0]
484 head = line_info.ifun.split('.',1)[0]
489 if is_shadowed(head, self.shell):
485 if is_shadowed(head, self.shell):
490 return None
486 return None
491
487
492 return self.prefilter_manager.get_handler_by_name('magic')
488 return self.prefilter_manager.get_handler_by_name('magic')
493
489
494
490
495 class AliasChecker(PrefilterChecker):
491 class AliasChecker(PrefilterChecker):
496
492
497 priority = Integer(800, config=True)
493 priority = Integer(800, config=True)
498
494
499 def check(self, line_info):
495 def check(self, line_info):
500 "Check if the initital identifier on the line is an alias."
496 "Check if the initital identifier on the line is an alias."
501 # Note: aliases can not contain '.'
497 # Note: aliases can not contain '.'
502 head = line_info.ifun.split('.',1)[0]
498 head = line_info.ifun.split('.',1)[0]
503 if line_info.ifun not in self.shell.alias_manager \
499 if line_info.ifun not in self.shell.alias_manager \
504 or head not in self.shell.alias_manager \
500 or head not in self.shell.alias_manager \
505 or is_shadowed(head, self.shell):
501 or is_shadowed(head, self.shell):
506 return None
502 return None
507
503
508 return self.prefilter_manager.get_handler_by_name('alias')
504 return self.prefilter_manager.get_handler_by_name('alias')
509
505
510
506
511 class PythonOpsChecker(PrefilterChecker):
507 class PythonOpsChecker(PrefilterChecker):
512
508
513 priority = Integer(900, config=True)
509 priority = Integer(900, config=True)
514
510
515 def check(self, line_info):
511 def check(self, line_info):
516 """If the 'rest' of the line begins with a function call or pretty much
512 """If the 'rest' of the line begins with a function call or pretty much
517 any python operator, we should simply execute the line (regardless of
513 any python operator, we should simply execute the line (regardless of
518 whether or not there's a possible autocall expansion). This avoids
514 whether or not there's a possible autocall expansion). This avoids
519 spurious (and very confusing) geattr() accesses."""
515 spurious (and very confusing) geattr() accesses."""
520 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
516 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
521 return self.prefilter_manager.get_handler_by_name('normal')
517 return self.prefilter_manager.get_handler_by_name('normal')
522 else:
518 else:
523 return None
519 return None
524
520
525
521
526 class AutocallChecker(PrefilterChecker):
522 class AutocallChecker(PrefilterChecker):
527
523
528 priority = Integer(1000, config=True)
524 priority = Integer(1000, config=True)
529
525
530 function_name_regexp = CRegExp(re_fun_name, config=True,
526 function_name_regexp = CRegExp(re_fun_name, config=True,
531 help="RegExp to identify potential function names.")
527 help="RegExp to identify potential function names.")
532 exclude_regexp = CRegExp(re_exclude_auto, config=True,
528 exclude_regexp = CRegExp(re_exclude_auto, config=True,
533 help="RegExp to exclude strings with this start from autocalling.")
529 help="RegExp to exclude strings with this start from autocalling.")
534
530
535 def check(self, line_info):
531 def check(self, line_info):
536 "Check if the initial word/function is callable and autocall is on."
532 "Check if the initial word/function is callable and autocall is on."
537 if not self.shell.autocall:
533 if not self.shell.autocall:
538 return None
534 return None
539
535
540 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
536 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
541 if not oinfo['found']:
537 if not oinfo['found']:
542 return None
538 return None
543
539
544 if callable(oinfo['obj']) \
540 if callable(oinfo['obj']) \
545 and (not self.exclude_regexp.match(line_info.the_rest)) \
541 and (not self.exclude_regexp.match(line_info.the_rest)) \
546 and self.function_name_regexp.match(line_info.ifun):
542 and self.function_name_regexp.match(line_info.ifun):
547 return self.prefilter_manager.get_handler_by_name('auto')
543 return self.prefilter_manager.get_handler_by_name('auto')
548 else:
544 else:
549 return None
545 return None
550
546
551
547
552 #-----------------------------------------------------------------------------
548 #-----------------------------------------------------------------------------
553 # Prefilter handlers
549 # Prefilter handlers
554 #-----------------------------------------------------------------------------
550 #-----------------------------------------------------------------------------
555
551
556
552
557 class PrefilterHandler(Configurable):
553 class PrefilterHandler(Configurable):
558
554
559 handler_name = Unicode('normal')
555 handler_name = Unicode('normal')
560 esc_strings = List([])
556 esc_strings = List([])
561 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
557 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
562 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
558 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
563
559
564 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
560 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
565 super(PrefilterHandler, self).__init__(
561 super(PrefilterHandler, self).__init__(
566 shell=shell, prefilter_manager=prefilter_manager, **kwargs
562 shell=shell, prefilter_manager=prefilter_manager, **kwargs
567 )
563 )
568 self.prefilter_manager.register_handler(
564 self.prefilter_manager.register_handler(
569 self.handler_name,
565 self.handler_name,
570 self,
566 self,
571 self.esc_strings
567 self.esc_strings
572 )
568 )
573
569
574 def handle(self, line_info):
570 def handle(self, line_info):
575 # print "normal: ", line_info
571 # print "normal: ", line_info
576 """Handle normal input lines. Use as a template for handlers."""
572 """Handle normal input lines. Use as a template for handlers."""
577
573
578 # With autoindent on, we need some way to exit the input loop, and I
574 # With autoindent on, we need some way to exit the input loop, and I
579 # don't want to force the user to have to backspace all the way to
575 # don't want to force the user to have to backspace all the way to
580 # clear the line. The rule will be in this case, that either two
576 # clear the line. The rule will be in this case, that either two
581 # lines of pure whitespace in a row, or a line of pure whitespace but
577 # lines of pure whitespace in a row, or a line of pure whitespace but
582 # of a size different to the indent level, will exit the input loop.
578 # of a size different to the indent level, will exit the input loop.
583 line = line_info.line
579 line = line_info.line
584 continue_prompt = line_info.continue_prompt
580 continue_prompt = line_info.continue_prompt
585
581
586 if (continue_prompt and
582 if (continue_prompt and
587 self.shell.autoindent and
583 self.shell.autoindent and
588 line.isspace() and
584 line.isspace() and
589 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
585 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
590 line = ''
586 line = ''
591
587
592 return line
588 return line
593
589
594 def __str__(self):
590 def __str__(self):
595 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
591 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
596
592
597
593
598 class AliasHandler(PrefilterHandler):
594 class AliasHandler(PrefilterHandler):
599
595
600 handler_name = Unicode('alias')
596 handler_name = Unicode('alias')
601
597
602 def handle(self, line_info):
598 def handle(self, line_info):
603 """Handle alias input lines. """
599 """Handle alias input lines. """
604 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
600 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
605 # pre is needed, because it carries the leading whitespace. Otherwise
601 # pre is needed, because it carries the leading whitespace. Otherwise
606 # aliases won't work in indented sections.
602 # aliases won't work in indented sections.
607 line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed)
603 line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed)
608
604
609 return line_out
605 return line_out
610
606
611
607
612 class MacroHandler(PrefilterHandler):
608 class MacroHandler(PrefilterHandler):
613 handler_name = Unicode("macro")
609 handler_name = Unicode("macro")
614
610
615 def handle(self, line_info):
611 def handle(self, line_info):
616 obj = self.shell.user_ns.get(line_info.ifun)
612 obj = self.shell.user_ns.get(line_info.ifun)
617 pre_space = line_info.pre_whitespace
613 pre_space = line_info.pre_whitespace
618 line_sep = "\n" + pre_space
614 line_sep = "\n" + pre_space
619 return pre_space + line_sep.join(obj.value.splitlines())
615 return pre_space + line_sep.join(obj.value.splitlines())
620
616
621
617
622 class MagicHandler(PrefilterHandler):
618 class MagicHandler(PrefilterHandler):
623
619
624 handler_name = Unicode('magic')
620 handler_name = Unicode('magic')
625 esc_strings = List([ESC_MAGIC])
621 esc_strings = List([ESC_MAGIC])
626
622
627 def handle(self, line_info):
623 def handle(self, line_info):
628 """Execute magic functions."""
624 """Execute magic functions."""
629 ifun = line_info.ifun
625 ifun = line_info.ifun
630 the_rest = line_info.the_rest
626 the_rest = line_info.the_rest
631 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
627 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
632 (ifun + " " + the_rest))
628 (ifun + " " + the_rest))
633 return cmd
629 return cmd
634
630
635
631
636 class AutoHandler(PrefilterHandler):
632 class AutoHandler(PrefilterHandler):
637
633
638 handler_name = Unicode('auto')
634 handler_name = Unicode('auto')
639 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
635 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
640
636
641 def handle(self, line_info):
637 def handle(self, line_info):
642 """Handle lines which can be auto-executed, quoting if requested."""
638 """Handle lines which can be auto-executed, quoting if requested."""
643 line = line_info.line
639 line = line_info.line
644 ifun = line_info.ifun
640 ifun = line_info.ifun
645 the_rest = line_info.the_rest
641 the_rest = line_info.the_rest
646 pre = line_info.pre
642 pre = line_info.pre
647 esc = line_info.esc
643 esc = line_info.esc
648 continue_prompt = line_info.continue_prompt
644 continue_prompt = line_info.continue_prompt
649 obj = line_info.ofind(self.shell)['obj']
645 obj = line_info.ofind(self.shell)['obj']
650 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
646 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
651
647
652 # This should only be active for single-line input!
648 # This should only be active for single-line input!
653 if continue_prompt:
649 if continue_prompt:
654 return line
650 return line
655
651
656 force_auto = isinstance(obj, IPyAutocall)
652 force_auto = isinstance(obj, IPyAutocall)
657
653
658 # User objects sometimes raise exceptions on attribute access other
654 # User objects sometimes raise exceptions on attribute access other
659 # than AttributeError (we've seen it in the past), so it's safest to be
655 # than AttributeError (we've seen it in the past), so it's safest to be
660 # ultra-conservative here and catch all.
656 # ultra-conservative here and catch all.
661 try:
657 try:
662 auto_rewrite = obj.rewrite
658 auto_rewrite = obj.rewrite
663 except Exception:
659 except Exception:
664 auto_rewrite = True
660 auto_rewrite = True
665
661
666 if esc == ESC_QUOTE:
662 if esc == ESC_QUOTE:
667 # Auto-quote splitting on whitespace
663 # Auto-quote splitting on whitespace
668 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
664 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
669 elif esc == ESC_QUOTE2:
665 elif esc == ESC_QUOTE2:
670 # Auto-quote whole string
666 # Auto-quote whole string
671 newcmd = '%s("%s")' % (ifun,the_rest)
667 newcmd = '%s("%s")' % (ifun,the_rest)
672 elif esc == ESC_PAREN:
668 elif esc == ESC_PAREN:
673 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
669 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
674 else:
670 else:
675 # Auto-paren.
671 # Auto-paren.
676 if force_auto:
672 if force_auto:
677 # Don't rewrite if it is already a call.
673 # Don't rewrite if it is already a call.
678 do_rewrite = not the_rest.startswith('(')
674 do_rewrite = not the_rest.startswith('(')
679 else:
675 else:
680 if not the_rest:
676 if not the_rest:
681 # We only apply it to argument-less calls if the autocall
677 # We only apply it to argument-less calls if the autocall
682 # parameter is set to 2.
678 # parameter is set to 2.
683 do_rewrite = (self.shell.autocall >= 2)
679 do_rewrite = (self.shell.autocall >= 2)
684 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
680 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
685 # Don't autocall in this case: item access for an object
681 # Don't autocall in this case: item access for an object
686 # which is BOTH callable and implements __getitem__.
682 # which is BOTH callable and implements __getitem__.
687 do_rewrite = False
683 do_rewrite = False
688 else:
684 else:
689 do_rewrite = True
685 do_rewrite = True
690
686
691 # Figure out the rewritten command
687 # Figure out the rewritten command
692 if do_rewrite:
688 if do_rewrite:
693 if the_rest.endswith(';'):
689 if the_rest.endswith(';'):
694 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
690 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
695 else:
691 else:
696 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
692 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
697 else:
693 else:
698 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
694 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
699 return normal_handler.handle(line_info)
695 return normal_handler.handle(line_info)
700
696
701 # Display the rewritten call
697 # Display the rewritten call
702 if auto_rewrite:
698 if auto_rewrite:
703 self.shell.auto_rewrite_input(newcmd)
699 self.shell.auto_rewrite_input(newcmd)
704
700
705 return newcmd
701 return newcmd
706
702
707
703
708 class EmacsHandler(PrefilterHandler):
704 class EmacsHandler(PrefilterHandler):
709
705
710 handler_name = Unicode('emacs')
706 handler_name = Unicode('emacs')
711 esc_strings = List([])
707 esc_strings = List([])
712
708
713 def handle(self, line_info):
709 def handle(self, line_info):
714 """Handle input lines marked by python-mode."""
710 """Handle input lines marked by python-mode."""
715
711
716 # Currently, nothing is done. Later more functionality can be added
712 # Currently, nothing is done. Later more functionality can be added
717 # here if needed.
713 # here if needed.
718
714
719 # The input cache shouldn't be updated
715 # The input cache shouldn't be updated
720 return line_info.line
716 return line_info.line
721
717
722
718
723 #-----------------------------------------------------------------------------
719 #-----------------------------------------------------------------------------
724 # Defaults
720 # Defaults
725 #-----------------------------------------------------------------------------
721 #-----------------------------------------------------------------------------
726
722
727
723
728 _default_transformers = [
724 _default_transformers = [
729 ]
725 ]
730
726
731 _default_checkers = [
727 _default_checkers = [
732 EmacsChecker,
728 EmacsChecker,
733 MacroChecker,
729 MacroChecker,
734 IPyAutocallChecker,
730 IPyAutocallChecker,
735 AssignmentChecker,
731 AssignmentChecker,
736 AutoMagicChecker,
732 AutoMagicChecker,
737 AliasChecker,
733 AliasChecker,
738 PythonOpsChecker,
734 PythonOpsChecker,
739 AutocallChecker
735 AutocallChecker
740 ]
736 ]
741
737
742 _default_handlers = [
738 _default_handlers = [
743 PrefilterHandler,
739 PrefilterHandler,
744 AliasHandler,
740 AliasHandler,
745 MacroHandler,
741 MacroHandler,
746 MagicHandler,
742 MagicHandler,
747 AutoHandler,
743 AutoHandler,
748 EmacsHandler
744 EmacsHandler
749 ]
745 ]
@@ -1,83 +1,79 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for completerlib.
2 """Tests for completerlib.
3
3
4 """
4 """
5 from __future__ import absolute_import
5 from __future__ import absolute_import
6
6
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Imports
8 # Imports
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 import os
11 import os
12 import shutil
12 import shutil
13 import sys
13 import sys
14 import tempfile
14 import tempfile
15 import unittest
15 import unittest
16 from os.path import join
16 from os.path import join
17
17
18 import nose.tools as nt
19 from nose import SkipTest
20
21 from IPython.core.completerlib import magic_run_completer, module_completion
18 from IPython.core.completerlib import magic_run_completer, module_completion
22 from IPython.utils import py3compat
23 from IPython.utils.tempdir import TemporaryDirectory
19 from IPython.utils.tempdir import TemporaryDirectory
24
20
25
21
26 class MockEvent(object):
22 class MockEvent(object):
27 def __init__(self, line):
23 def __init__(self, line):
28 self.line = line
24 self.line = line
29
25
30 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
31 # Test functions begin
27 # Test functions begin
32 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
33 class Test_magic_run_completer(unittest.TestCase):
29 class Test_magic_run_completer(unittest.TestCase):
34 def setUp(self):
30 def setUp(self):
35 self.BASETESTDIR = tempfile.mkdtemp()
31 self.BASETESTDIR = tempfile.mkdtemp()
36 for fil in [u"aaø.py", u"a.py", u"b.py"]:
32 for fil in [u"aaø.py", u"a.py", u"b.py"]:
37 with open(join(self.BASETESTDIR, fil), "w") as sfile:
33 with open(join(self.BASETESTDIR, fil), "w") as sfile:
38 sfile.write("pass\n")
34 sfile.write("pass\n")
39 self.oldpath = os.getcwdu()
35 self.oldpath = os.getcwdu()
40 os.chdir(self.BASETESTDIR)
36 os.chdir(self.BASETESTDIR)
41
37
42 def tearDown(self):
38 def tearDown(self):
43 os.chdir(self.oldpath)
39 os.chdir(self.oldpath)
44 shutil.rmtree(self.BASETESTDIR)
40 shutil.rmtree(self.BASETESTDIR)
45
41
46 def test_1(self):
42 def test_1(self):
47 """Test magic_run_completer, should match two alterntives
43 """Test magic_run_completer, should match two alterntives
48 """
44 """
49 event = MockEvent(u"%run a")
45 event = MockEvent(u"%run a")
50 mockself = None
46 mockself = None
51 match = set(magic_run_completer(mockself, event))
47 match = set(magic_run_completer(mockself, event))
52 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
48 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
53
49
54 def test_2(self):
50 def test_2(self):
55 """Test magic_run_completer, should match one alterntive
51 """Test magic_run_completer, should match one alterntive
56 """
52 """
57 event = MockEvent(u"%run aa")
53 event = MockEvent(u"%run aa")
58 mockself = None
54 mockself = None
59 match = set(magic_run_completer(mockself, event))
55 match = set(magic_run_completer(mockself, event))
60 self.assertEqual(match, set([u"aaø.py"]))
56 self.assertEqual(match, set([u"aaø.py"]))
61
57
62 def test_3(self):
58 def test_3(self):
63 """Test magic_run_completer with unterminated " """
59 """Test magic_run_completer with unterminated " """
64 event = MockEvent(u'%run "a')
60 event = MockEvent(u'%run "a')
65 mockself = None
61 mockself = None
66 match = set(magic_run_completer(mockself, event))
62 match = set(magic_run_completer(mockself, event))
67 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
63 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
68
64
69 def test_import_invalid_module(self):
65 def test_import_invalid_module(self):
70 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
66 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
71 invalid_module_names = set(['foo-bar', 'foo:bar', '10foo'])
67 invalid_module_names = set(['foo-bar', 'foo:bar', '10foo'])
72 valid_module_names = set(['foobar'])
68 valid_module_names = set(['foobar'])
73 with TemporaryDirectory() as tmpdir:
69 with TemporaryDirectory() as tmpdir:
74 sys.path.insert( 0, tmpdir )
70 sys.path.insert( 0, tmpdir )
75 for name in invalid_module_names | valid_module_names:
71 for name in invalid_module_names | valid_module_names:
76 filename = os.path.join(tmpdir, name + '.py')
72 filename = os.path.join(tmpdir, name + '.py')
77 open(filename, 'w').close()
73 open(filename, 'w').close()
78
74
79 s = set( module_completion('import foo') )
75 s = set( module_completion('import foo') )
80 intersection = s.intersection(invalid_module_names)
76 intersection = s.intersection(invalid_module_names)
81 self.assertFalse(intersection, intersection)
77 self.assertFalse(intersection, intersection)
82
78
83 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
79 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
@@ -1,142 +1,142 b''
1 """Tests for debugging machinery.
1 """Tests for debugging machinery.
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 import sys
15 import sys
16
16
17 # third-party
17 # third-party
18 import nose.tools as nt
18 import nose.tools as nt
19
19
20 # Our own
20 # Our own
21 from IPython.core import debugger
21 from IPython.core import debugger
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Helper classes, from CPython's Pdb test suite
24 # Helper classes, from CPython's Pdb test suite
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 class _FakeInput(object):
27 class _FakeInput(object):
28 """
28 """
29 A fake input stream for pdb's interactive debugger. Whenever a
29 A fake input stream for pdb's interactive debugger. Whenever a
30 line is read, print it (to simulate the user typing it), and then
30 line is read, print it (to simulate the user typing it), and then
31 return it. The set of lines to return is specified in the
31 return it. The set of lines to return is specified in the
32 constructor; they should not have trailing newlines.
32 constructor; they should not have trailing newlines.
33 """
33 """
34 def __init__(self, lines):
34 def __init__(self, lines):
35 self.lines = iter(lines)
35 self.lines = iter(lines)
36
36
37 def readline(self):
37 def readline(self):
38 line = next(self.lines)
38 line = next(self.lines)
39 print line
39 print line
40 return line+'\n'
40 return line+'\n'
41
41
42 class PdbTestInput(object):
42 class PdbTestInput(object):
43 """Context manager that makes testing Pdb in doctests easier."""
43 """Context manager that makes testing Pdb in doctests easier."""
44
44
45 def __init__(self, input):
45 def __init__(self, input):
46 self.input = input
46 self.input = input
47
47
48 def __enter__(self):
48 def __enter__(self):
49 self.real_stdin = sys.stdin
49 self.real_stdin = sys.stdin
50 sys.stdin = _FakeInput(self.input)
50 sys.stdin = _FakeInput(self.input)
51
51
52 def __exit__(self, *exc):
52 def __exit__(self, *exc):
53 sys.stdin = self.real_stdin
53 sys.stdin = self.real_stdin
54
54
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 # Tests
56 # Tests
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58
58
59 def test_longer_repr():
59 def test_longer_repr():
60 from repr import repr as trepr
60 from repr import repr as trepr
61
61
62 a = '1234567890'* 7
62 a = '1234567890'* 7
63 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
63 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
64 a_trunc = "'123456789012...8901234567890'"
64 a_trunc = "'123456789012...8901234567890'"
65 nt.assert_equal(trepr(a), a_trunc)
65 nt.assert_equal(trepr(a), a_trunc)
66 # The creation of our tracer modifies the repr module's repr function
66 # The creation of our tracer modifies the repr module's repr function
67 # in-place, since that global is used directly by the stdlib's pdb module.
67 # in-place, since that global is used directly by the stdlib's pdb module.
68 t = debugger.Tracer()
68 t = debugger.Tracer()
69 nt.assert_equal(trepr(a), ar)
69 nt.assert_equal(trepr(a), ar)
70
70
71 def test_ipdb_magics():
71 def test_ipdb_magics():
72 '''Test calling some IPython magics from ipdb.
72 '''Test calling some IPython magics from ipdb.
73
73
74 First, set up some test functions and classes which we can inspect.
74 First, set up some test functions and classes which we can inspect.
75
75
76 >>> class ExampleClass(object):
76 >>> class ExampleClass(object):
77 ... """Docstring for ExampleClass."""
77 ... """Docstring for ExampleClass."""
78 ... def __init__(self):
78 ... def __init__(self):
79 ... """Docstring for ExampleClass.__init__"""
79 ... """Docstring for ExampleClass.__init__"""
80 ... pass
80 ... pass
81 ... def __str__(self):
81 ... def __str__(self):
82 ... return "ExampleClass()"
82 ... return "ExampleClass()"
83
83
84 >>> def example_function(x, y, z="hello"):
84 >>> def example_function(x, y, z="hello"):
85 ... """Docstring for example_function."""
85 ... """Docstring for example_function."""
86 ... pass
86 ... pass
87
87
88 Create a function which triggers ipdb.
88 Create a function which triggers ipdb.
89
89
90 >>> def trigger_ipdb():
90 >>> def trigger_ipdb():
91 ... a = ExampleClass()
91 ... a = ExampleClass()
92 ... debugger.Pdb().set_trace()
92 ... debugger.Pdb().set_trace()
93
93
94 >>> with PdbTestInput([
94 >>> with PdbTestInput([
95 ... 'pdef example_function',
95 ... 'pdef example_function',
96 ... 'pdoc ExampleClass',
96 ... 'pdoc ExampleClass',
97 ... 'pinfo a',
97 ... 'pinfo a',
98 ... 'continue',
98 ... 'continue',
99 ... ]):
99 ... ]):
100 ... trigger_ipdb()
100 ... trigger_ipdb()
101 --Return--
101 --Return--
102 None
102 None
103 > <doctest ...>(3)trigger_ipdb()
103 > <doctest ...>(3)trigger_ipdb()
104 1 def trigger_ipdb():
104 1 def trigger_ipdb():
105 2 a = ExampleClass()
105 2 a = ExampleClass()
106 ----> 3 debugger.Pdb().set_trace()
106 ----> 3 debugger.Pdb().set_trace()
107 <BLANKLINE>
107 <BLANKLINE>
108 ipdb> pdef example_function
108 ipdb> pdef example_function
109 example_function(x, y, z='hello')
109 example_function(x, y, z='hello')
110 ipdb> pdoc ExampleClass
110 ipdb> pdoc ExampleClass
111 Class Docstring:
111 Class Docstring:
112 Docstring for ExampleClass.
112 Docstring for ExampleClass.
113 Constructor Docstring:
113 Constructor Docstring:
114 Docstring for ExampleClass.__init__
114 Docstring for ExampleClass.__init__
115 ipdb> pinfo a
115 ipdb> pinfo a
116 Type: ExampleClass
116 Type: ExampleClass
117 String Form:ExampleClass()
117 String Form:ExampleClass()
118 Namespace: Locals
118 Namespace: Locals
119 File: ...
119 File: ...
120 Docstring: Docstring for ExampleClass.
120 Docstring: Docstring for ExampleClass.
121 Constructor Docstring:Docstring for ExampleClass.__init__
121 Constructor Docstring:Docstring for ExampleClass.__init__
122 ipdb> continue
122 ipdb> continue
123 '''
123 '''
124
124
125 def test_ipdb_magics():
125 def test_ipdb_magics2():
126 '''Test ipdb with a very short function.
126 '''Test ipdb with a very short function.
127
127
128 >>> def bar():
128 >>> def bar():
129 ... pass
129 ... pass
130
130
131 Run ipdb.
131 Run ipdb.
132
132
133 >>> with PdbTestInput([
133 >>> with PdbTestInput([
134 ... 'continue',
134 ... 'continue',
135 ... ]):
135 ... ]):
136 ... debugger.Pdb().runcall(bar)
136 ... debugger.Pdb().runcall(bar)
137 > <doctest ...>(2)bar()
137 > <doctest ...>(2)bar()
138 1 def bar():
138 1 def bar():
139 ----> 2 pass
139 ----> 2 pass
140 <BLANKLINE>
140 <BLANKLINE>
141 ipdb> continue
141 ipdb> continue
142 '''
142 '''
@@ -1,17 +1,17 b''
1 """Tests for the FakeModule objects.
1 """Tests for the FakeModule objects.
2 """
2 """
3
3
4 import nose.tools as nt
4 import nose.tools as nt
5
5
6 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
6 from IPython.core.fakemodule import FakeModule
7
7
8 # Make a fakemod and check a few properties
8 # Make a fakemod and check a few properties
9 def test_mk_fakemod():
9 def test_mk_fakemod():
10 fm = FakeModule()
10 fm = FakeModule()
11 yield nt.assert_true,fm
11 yield nt.assert_true,fm
12 yield nt.assert_true,lambda : hasattr(fm,'__file__')
12 yield nt.assert_true,lambda : hasattr(fm,'__file__')
13
13
14 def test_mk_fakemod_fromdict():
14 def test_mk_fakemod_fromdict():
15 """Test making a FakeModule object with initial data"""
15 """Test making a FakeModule object with initial data"""
16 fm = FakeModule(dict(hello=True))
16 fm = FakeModule(dict(hello=True))
17 nt.assert_true(fm.hello)
17 nt.assert_true(fm.hello)
@@ -1,91 +1,90 b''
1 """Tests for the Formatters.
1 """Tests for the Formatters.
2 """
2 """
3
3
4 from math import pi
4 from math import pi
5
5
6 try:
6 try:
7 import numpy
7 import numpy
8 except:
8 except:
9 numpy = None
9 numpy = None
10 import nose.tools as nt
10 import nose.tools as nt
11
11
12 from IPython.core.formatters import FormatterABC, PlainTextFormatter
12 from IPython.core.formatters import PlainTextFormatter
13 from IPython.lib import pretty
14
13
15 class A(object):
14 class A(object):
16 def __repr__(self):
15 def __repr__(self):
17 return 'A()'
16 return 'A()'
18
17
19 class B(A):
18 class B(A):
20 def __repr__(self):
19 def __repr__(self):
21 return 'B()'
20 return 'B()'
22
21
23 class BadPretty(object):
22 class BadPretty(object):
24 _repr_pretty_ = None
23 _repr_pretty_ = None
25
24
26 class GoodPretty(object):
25 class GoodPretty(object):
27 def _repr_pretty_(self, pp, cycle):
26 def _repr_pretty_(self, pp, cycle):
28 pp.text('foo')
27 pp.text('foo')
29
28
30 def __repr__(self):
29 def __repr__(self):
31 return 'GoodPretty()'
30 return 'GoodPretty()'
32
31
33 def foo_printer(obj, pp, cycle):
32 def foo_printer(obj, pp, cycle):
34 pp.text('foo')
33 pp.text('foo')
35
34
36 def test_pretty():
35 def test_pretty():
37 f = PlainTextFormatter()
36 f = PlainTextFormatter()
38 f.for_type(A, foo_printer)
37 f.for_type(A, foo_printer)
39 nt.assert_equal(f(A()), 'foo')
38 nt.assert_equal(f(A()), 'foo')
40 nt.assert_equal(f(B()), 'foo')
39 nt.assert_equal(f(B()), 'foo')
41 nt.assert_equal(f(GoodPretty()), 'foo')
40 nt.assert_equal(f(GoodPretty()), 'foo')
42 # Just don't raise an exception for the following:
41 # Just don't raise an exception for the following:
43 f(BadPretty())
42 f(BadPretty())
44
43
45 f.pprint = False
44 f.pprint = False
46 nt.assert_equal(f(A()), 'A()')
45 nt.assert_equal(f(A()), 'A()')
47 nt.assert_equal(f(B()), 'B()')
46 nt.assert_equal(f(B()), 'B()')
48 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
47 nt.assert_equal(f(GoodPretty()), 'GoodPretty()')
49
48
50
49
51 def test_deferred():
50 def test_deferred():
52 f = PlainTextFormatter()
51 f = PlainTextFormatter()
53
52
54 def test_precision():
53 def test_precision():
55 """test various values for float_precision."""
54 """test various values for float_precision."""
56 f = PlainTextFormatter()
55 f = PlainTextFormatter()
57 nt.assert_equal(f(pi), repr(pi))
56 nt.assert_equal(f(pi), repr(pi))
58 f.float_precision = 0
57 f.float_precision = 0
59 if numpy:
58 if numpy:
60 po = numpy.get_printoptions()
59 po = numpy.get_printoptions()
61 nt.assert_equal(po['precision'], 0)
60 nt.assert_equal(po['precision'], 0)
62 nt.assert_equal(f(pi), '3')
61 nt.assert_equal(f(pi), '3')
63 f.float_precision = 2
62 f.float_precision = 2
64 if numpy:
63 if numpy:
65 po = numpy.get_printoptions()
64 po = numpy.get_printoptions()
66 nt.assert_equal(po['precision'], 2)
65 nt.assert_equal(po['precision'], 2)
67 nt.assert_equal(f(pi), '3.14')
66 nt.assert_equal(f(pi), '3.14')
68 f.float_precision = '%g'
67 f.float_precision = '%g'
69 if numpy:
68 if numpy:
70 po = numpy.get_printoptions()
69 po = numpy.get_printoptions()
71 nt.assert_equal(po['precision'], 2)
70 nt.assert_equal(po['precision'], 2)
72 nt.assert_equal(f(pi), '3.14159')
71 nt.assert_equal(f(pi), '3.14159')
73 f.float_precision = '%e'
72 f.float_precision = '%e'
74 nt.assert_equal(f(pi), '3.141593e+00')
73 nt.assert_equal(f(pi), '3.141593e+00')
75 f.float_precision = ''
74 f.float_precision = ''
76 if numpy:
75 if numpy:
77 po = numpy.get_printoptions()
76 po = numpy.get_printoptions()
78 nt.assert_equal(po['precision'], 8)
77 nt.assert_equal(po['precision'], 8)
79 nt.assert_equal(f(pi), repr(pi))
78 nt.assert_equal(f(pi), repr(pi))
80
79
81 def test_bad_precision():
80 def test_bad_precision():
82 """test various invalid values for float_precision."""
81 """test various invalid values for float_precision."""
83 f = PlainTextFormatter()
82 f = PlainTextFormatter()
84 def set_fp(p):
83 def set_fp(p):
85 f.float_precision=p
84 f.float_precision=p
86 nt.assert_raises(ValueError, set_fp, '%')
85 nt.assert_raises(ValueError, set_fp, '%')
87 nt.assert_raises(ValueError, set_fp, '%.3f%i')
86 nt.assert_raises(ValueError, set_fp, '%.3f%i')
88 nt.assert_raises(ValueError, set_fp, 'foo')
87 nt.assert_raises(ValueError, set_fp, 'foo')
89 nt.assert_raises(ValueError, set_fp, -1)
88 nt.assert_raises(ValueError, set_fp, -1)
90
89
91
90
@@ -1,185 +1,183 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for the IPython tab-completion machinery.
2 """Tests for the IPython tab-completion machinery.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Module imports
5 # Module imports
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7
7
8 # stdlib
8 # stdlib
9 import os
9 import os
10 import shutil
11 import sys
10 import sys
12 import tempfile
11 import tempfile
13 import unittest
14 from datetime import datetime
12 from datetime import datetime
15
13
16 # third party
14 # third party
17 import nose.tools as nt
15 import nose.tools as nt
18
16
19 # our own packages
17 # our own packages
20 from IPython.config.loader import Config
18 from IPython.config.loader import Config
21 from IPython.utils.tempdir import TemporaryDirectory
19 from IPython.utils.tempdir import TemporaryDirectory
22 from IPython.core.history import HistoryManager, extract_hist_ranges
20 from IPython.core.history import HistoryManager, extract_hist_ranges
23 from IPython.utils import py3compat
21 from IPython.utils import py3compat
24
22
25 def setUp():
23 def setUp():
26 nt.assert_equal(sys.getdefaultencoding(), "utf-8" if py3compat.PY3 else "ascii")
24 nt.assert_equal(sys.getdefaultencoding(), "utf-8" if py3compat.PY3 else "ascii")
27
25
28 def test_history():
26 def test_history():
29 ip = get_ipython()
27 ip = get_ipython()
30 with TemporaryDirectory() as tmpdir:
28 with TemporaryDirectory() as tmpdir:
31 hist_manager_ori = ip.history_manager
29 hist_manager_ori = ip.history_manager
32 hist_file = os.path.join(tmpdir, 'history.sqlite')
30 hist_file = os.path.join(tmpdir, 'history.sqlite')
33 try:
31 try:
34 ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file)
32 ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file)
35 hist = [u'a=1', u'def f():\n test = 1\n return test', u"b='€Æ¾÷ß'"]
33 hist = [u'a=1', u'def f():\n test = 1\n return test', u"b='€Æ¾÷ß'"]
36 for i, h in enumerate(hist, start=1):
34 for i, h in enumerate(hist, start=1):
37 ip.history_manager.store_inputs(i, h)
35 ip.history_manager.store_inputs(i, h)
38
36
39 ip.history_manager.db_log_output = True
37 ip.history_manager.db_log_output = True
40 # Doesn't match the input, but we'll just check it's stored.
38 # Doesn't match the input, but we'll just check it's stored.
41 ip.history_manager.output_hist_reprs[3] = "spam"
39 ip.history_manager.output_hist_reprs[3] = "spam"
42 ip.history_manager.store_output(3)
40 ip.history_manager.store_output(3)
43
41
44 nt.assert_equal(ip.history_manager.input_hist_raw, [''] + hist)
42 nt.assert_equal(ip.history_manager.input_hist_raw, [''] + hist)
45
43
46 # Detailed tests for _get_range_session
44 # Detailed tests for _get_range_session
47 grs = ip.history_manager._get_range_session
45 grs = ip.history_manager._get_range_session
48 nt.assert_equal(list(grs(start=2,stop=-1)), zip([0], [2], hist[1:-1]))
46 nt.assert_equal(list(grs(start=2,stop=-1)), zip([0], [2], hist[1:-1]))
49 nt.assert_equal(list(grs(start=-2)), zip([0,0], [2,3], hist[-2:]))
47 nt.assert_equal(list(grs(start=-2)), zip([0,0], [2,3], hist[-2:]))
50 nt.assert_equal(list(grs(output=True)), zip([0,0,0], [1,2,3], zip(hist, [None,None,'spam'])))
48 nt.assert_equal(list(grs(output=True)), zip([0,0,0], [1,2,3], zip(hist, [None,None,'spam'])))
51
49
52 # Check whether specifying a range beyond the end of the current
50 # Check whether specifying a range beyond the end of the current
53 # session results in an error (gh-804)
51 # session results in an error (gh-804)
54 ip.magic('%hist 2-500')
52 ip.magic('%hist 2-500')
55
53
56 # Check that we can write non-ascii characters to a file
54 # Check that we can write non-ascii characters to a file
57 ip.magic("%%hist -f %s" % os.path.join(tmpdir, "test1"))
55 ip.magic("%%hist -f %s" % os.path.join(tmpdir, "test1"))
58 ip.magic("%%hist -pf %s" % os.path.join(tmpdir, "test2"))
56 ip.magic("%%hist -pf %s" % os.path.join(tmpdir, "test2"))
59 ip.magic("%%hist -nf %s" % os.path.join(tmpdir, "test3"))
57 ip.magic("%%hist -nf %s" % os.path.join(tmpdir, "test3"))
60 ip.magic("%%save %s 1-10" % os.path.join(tmpdir, "test4"))
58 ip.magic("%%save %s 1-10" % os.path.join(tmpdir, "test4"))
61
59
62 # New session
60 # New session
63 ip.history_manager.reset()
61 ip.history_manager.reset()
64 newcmds = [u"z=5",
62 newcmds = [u"z=5",
65 u"class X(object):\n pass",
63 u"class X(object):\n pass",
66 u"k='p'",
64 u"k='p'",
67 u"z=5"]
65 u"z=5"]
68 for i, cmd in enumerate(newcmds, start=1):
66 for i, cmd in enumerate(newcmds, start=1):
69 ip.history_manager.store_inputs(i, cmd)
67 ip.history_manager.store_inputs(i, cmd)
70 gothist = ip.history_manager.get_range(start=1, stop=4)
68 gothist = ip.history_manager.get_range(start=1, stop=4)
71 nt.assert_equal(list(gothist), zip([0,0,0],[1,2,3], newcmds))
69 nt.assert_equal(list(gothist), zip([0,0,0],[1,2,3], newcmds))
72 # Previous session:
70 # Previous session:
73 gothist = ip.history_manager.get_range(-1, 1, 4)
71 gothist = ip.history_manager.get_range(-1, 1, 4)
74 nt.assert_equal(list(gothist), zip([1,1,1],[1,2,3], hist))
72 nt.assert_equal(list(gothist), zip([1,1,1],[1,2,3], hist))
75
73
76 newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)]
74 newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)]
77
75
78 # Check get_hist_tail
76 # Check get_hist_tail
79 gothist = ip.history_manager.get_tail(5, output=True,
77 gothist = ip.history_manager.get_tail(5, output=True,
80 include_latest=True)
78 include_latest=True)
81 expected = [(1, 3, (hist[-1], "spam"))] \
79 expected = [(1, 3, (hist[-1], "spam"))] \
82 + [(s, n, (c, None)) for (s, n, c) in newhist]
80 + [(s, n, (c, None)) for (s, n, c) in newhist]
83 nt.assert_equal(list(gothist), expected)
81 nt.assert_equal(list(gothist), expected)
84
82
85 gothist = ip.history_manager.get_tail(2)
83 gothist = ip.history_manager.get_tail(2)
86 expected = newhist[-3:-1]
84 expected = newhist[-3:-1]
87 nt.assert_equal(list(gothist), expected)
85 nt.assert_equal(list(gothist), expected)
88
86
89 # Check get_hist_search
87 # Check get_hist_search
90 gothist = ip.history_manager.search("*test*")
88 gothist = ip.history_manager.search("*test*")
91 nt.assert_equal(list(gothist), [(1,2,hist[1])] )
89 nt.assert_equal(list(gothist), [(1,2,hist[1])] )
92
90
93 gothist = ip.history_manager.search("*=*")
91 gothist = ip.history_manager.search("*=*")
94 nt.assert_equal(list(gothist),
92 nt.assert_equal(list(gothist),
95 [(1, 1, hist[0]),
93 [(1, 1, hist[0]),
96 (1, 2, hist[1]),
94 (1, 2, hist[1]),
97 (1, 3, hist[2]),
95 (1, 3, hist[2]),
98 newhist[0],
96 newhist[0],
99 newhist[2],
97 newhist[2],
100 newhist[3]])
98 newhist[3]])
101
99
102 gothist = ip.history_manager.search("*=*", n=4)
100 gothist = ip.history_manager.search("*=*", n=4)
103 nt.assert_equal(list(gothist),
101 nt.assert_equal(list(gothist),
104 [(1, 3, hist[2]),
102 [(1, 3, hist[2]),
105 newhist[0],
103 newhist[0],
106 newhist[2],
104 newhist[2],
107 newhist[3]])
105 newhist[3]])
108
106
109 gothist = ip.history_manager.search("*=*", unique=True)
107 gothist = ip.history_manager.search("*=*", unique=True)
110 nt.assert_equal(list(gothist),
108 nt.assert_equal(list(gothist),
111 [(1, 1, hist[0]),
109 [(1, 1, hist[0]),
112 (1, 2, hist[1]),
110 (1, 2, hist[1]),
113 (1, 3, hist[2]),
111 (1, 3, hist[2]),
114 newhist[2],
112 newhist[2],
115 newhist[3]])
113 newhist[3]])
116
114
117 gothist = ip.history_manager.search("*=*", unique=True, n=3)
115 gothist = ip.history_manager.search("*=*", unique=True, n=3)
118 nt.assert_equal(list(gothist),
116 nt.assert_equal(list(gothist),
119 [(1, 3, hist[2]),
117 [(1, 3, hist[2]),
120 newhist[2],
118 newhist[2],
121 newhist[3]])
119 newhist[3]])
122
120
123 gothist = ip.history_manager.search("b*", output=True)
121 gothist = ip.history_manager.search("b*", output=True)
124 nt.assert_equal(list(gothist), [(1,3,(hist[2],"spam"))] )
122 nt.assert_equal(list(gothist), [(1,3,(hist[2],"spam"))] )
125
123
126 # Cross testing: check that magic %save can get previous session.
124 # Cross testing: check that magic %save can get previous session.
127 testfilename = os.path.realpath(os.path.join(tmpdir, "test.py"))
125 testfilename = os.path.realpath(os.path.join(tmpdir, "test.py"))
128 ip.magic("save " + testfilename + " ~1/1-3")
126 ip.magic("save " + testfilename + " ~1/1-3")
129 with py3compat.open(testfilename, encoding='utf-8') as testfile:
127 with py3compat.open(testfilename, encoding='utf-8') as testfile:
130 nt.assert_equal(testfile.read(),
128 nt.assert_equal(testfile.read(),
131 u"# coding: utf-8\n" + u"\n".join(hist)+u"\n")
129 u"# coding: utf-8\n" + u"\n".join(hist)+u"\n")
132
130
133 # Duplicate line numbers - check that it doesn't crash, and
131 # Duplicate line numbers - check that it doesn't crash, and
134 # gets a new session
132 # gets a new session
135 ip.history_manager.store_inputs(1, "rogue")
133 ip.history_manager.store_inputs(1, "rogue")
136 ip.history_manager.writeout_cache()
134 ip.history_manager.writeout_cache()
137 nt.assert_equal(ip.history_manager.session_number, 3)
135 nt.assert_equal(ip.history_manager.session_number, 3)
138 finally:
136 finally:
139 # Restore history manager
137 # Restore history manager
140 ip.history_manager = hist_manager_ori
138 ip.history_manager = hist_manager_ori
141
139
142
140
143 def test_extract_hist_ranges():
141 def test_extract_hist_ranges():
144 instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/"
142 instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/"
145 expected = [(0, 1, 2), # 0 == current session
143 expected = [(0, 1, 2), # 0 == current session
146 (2, 3, 4),
144 (2, 3, 4),
147 (-4, 5, 7),
145 (-4, 5, 7),
148 (-4, 7, 10),
146 (-4, 7, 10),
149 (-9, 2, None), # None == to end
147 (-9, 2, None), # None == to end
150 (-8, 1, None),
148 (-8, 1, None),
151 (-7, 1, 6),
149 (-7, 1, 6),
152 (-10, 1, None)]
150 (-10, 1, None)]
153 actual = list(extract_hist_ranges(instr))
151 actual = list(extract_hist_ranges(instr))
154 nt.assert_equal(actual, expected)
152 nt.assert_equal(actual, expected)
155
153
156 def test_magic_rerun():
154 def test_magic_rerun():
157 """Simple test for %rerun (no args -> rerun last line)"""
155 """Simple test for %rerun (no args -> rerun last line)"""
158 ip = get_ipython()
156 ip = get_ipython()
159 ip.run_cell("a = 10", store_history=True)
157 ip.run_cell("a = 10", store_history=True)
160 ip.run_cell("a += 1", store_history=True)
158 ip.run_cell("a += 1", store_history=True)
161 nt.assert_equal(ip.user_ns["a"], 11)
159 nt.assert_equal(ip.user_ns["a"], 11)
162 ip.run_cell("%rerun", store_history=True)
160 ip.run_cell("%rerun", store_history=True)
163 nt.assert_equal(ip.user_ns["a"], 12)
161 nt.assert_equal(ip.user_ns["a"], 12)
164
162
165 def test_timestamp_type():
163 def test_timestamp_type():
166 ip = get_ipython()
164 ip = get_ipython()
167 info = ip.history_manager.get_session_info()
165 info = ip.history_manager.get_session_info()
168 nt.assert_true(isinstance(info[1], datetime))
166 nt.assert_true(isinstance(info[1], datetime))
169
167
170 def test_hist_file_config():
168 def test_hist_file_config():
171 cfg = Config()
169 cfg = Config()
172 tfile = tempfile.NamedTemporaryFile(delete=False)
170 tfile = tempfile.NamedTemporaryFile(delete=False)
173 cfg.HistoryManager.hist_file = tfile.name
171 cfg.HistoryManager.hist_file = tfile.name
174 try:
172 try:
175 hm = HistoryManager(shell=get_ipython(), config=cfg)
173 hm = HistoryManager(shell=get_ipython(), config=cfg)
176 nt.assert_equal(hm.hist_file, cfg.HistoryManager.hist_file)
174 nt.assert_equal(hm.hist_file, cfg.HistoryManager.hist_file)
177 finally:
175 finally:
178 try:
176 try:
179 os.remove(tfile.name)
177 os.remove(tfile.name)
180 except OSError:
178 except OSError:
181 # same catch as in testing.tools.TempFileMixin
179 # same catch as in testing.tools.TempFileMixin
182 # On Windows, even though we close the file, we still can't
180 # On Windows, even though we close the file, we still can't
183 # delete it. I have no clue why
181 # delete it. I have no clue why
184 pass
182 pass
185
183
@@ -1,572 +1,564 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the inputsplitter module.
2 """Tests for the inputsplitter module.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 * Fernando Perez
6 * Fernando Perez
7 * Robert Kern
7 * Robert Kern
8 """
8 """
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010-2011 The IPython Development Team
10 # Copyright (C) 2010-2011 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # stdlib
19 # stdlib
20 import unittest
20 import unittest
21 import sys
21 import sys
22
22
23 # Third party
23 # Third party
24 import nose.tools as nt
24 import nose.tools as nt
25
25
26 # Our own
26 # Our own
27 from IPython.core import inputsplitter as isp
27 from IPython.core import inputsplitter as isp
28 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
28 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
29 from IPython.testing import tools as tt
29 from IPython.testing import tools as tt
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Semi-complete examples (also used as tests)
33 # Semi-complete examples (also used as tests)
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36 # Note: at the bottom, there's a slightly more complete version of this that
36 # Note: at the bottom, there's a slightly more complete version of this that
37 # can be useful during development of code here.
37 # can be useful during development of code here.
38
38
39 def mini_interactive_loop(input_func):
39 def mini_interactive_loop(input_func):
40 """Minimal example of the logic of an interactive interpreter loop.
40 """Minimal example of the logic of an interactive interpreter loop.
41
41
42 This serves as an example, and it is used by the test system with a fake
42 This serves as an example, and it is used by the test system with a fake
43 raw_input that simulates interactive input."""
43 raw_input that simulates interactive input."""
44
44
45 from IPython.core.inputsplitter import InputSplitter
45 from IPython.core.inputsplitter import InputSplitter
46
46
47 isp = InputSplitter()
47 isp = InputSplitter()
48 # In practice, this input loop would be wrapped in an outside loop to read
48 # In practice, this input loop would be wrapped in an outside loop to read
49 # input indefinitely, until some exit/quit command was issued. Here we
49 # input indefinitely, until some exit/quit command was issued. Here we
50 # only illustrate the basic inner loop.
50 # only illustrate the basic inner loop.
51 while isp.push_accepts_more():
51 while isp.push_accepts_more():
52 indent = ' '*isp.indent_spaces
52 indent = ' '*isp.indent_spaces
53 prompt = '>>> ' + indent
53 prompt = '>>> ' + indent
54 line = indent + input_func(prompt)
54 line = indent + input_func(prompt)
55 isp.push(line)
55 isp.push(line)
56
56
57 # Here we just return input so we can use it in a test suite, but a real
57 # Here we just return input so we can use it in a test suite, but a real
58 # interpreter would instead send it for execution somewhere.
58 # interpreter would instead send it for execution somewhere.
59 src = isp.source_reset()
59 src = isp.source_reset()
60 #print 'Input source was:\n', src # dbg
60 #print 'Input source was:\n', src # dbg
61 return src
61 return src
62
62
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64 # Test utilities, just for local use
64 # Test utilities, just for local use
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66
66
67 def assemble(block):
67 def assemble(block):
68 """Assemble a block into multi-line sub-blocks."""
68 """Assemble a block into multi-line sub-blocks."""
69 return ['\n'.join(sub_block)+'\n' for sub_block in block]
69 return ['\n'.join(sub_block)+'\n' for sub_block in block]
70
70
71
71
72 def pseudo_input(lines):
72 def pseudo_input(lines):
73 """Return a function that acts like raw_input but feeds the input list."""
73 """Return a function that acts like raw_input but feeds the input list."""
74 ilines = iter(lines)
74 ilines = iter(lines)
75 def raw_in(prompt):
75 def raw_in(prompt):
76 try:
76 try:
77 return next(ilines)
77 return next(ilines)
78 except StopIteration:
78 except StopIteration:
79 return ''
79 return ''
80 return raw_in
80 return raw_in
81
81
82 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
83 # Tests
83 # Tests
84 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
85 def test_spaces():
85 def test_spaces():
86 tests = [('', 0),
86 tests = [('', 0),
87 (' ', 1),
87 (' ', 1),
88 ('\n', 0),
88 ('\n', 0),
89 (' \n', 1),
89 (' \n', 1),
90 ('x', 0),
90 ('x', 0),
91 (' x', 1),
91 (' x', 1),
92 (' x',2),
92 (' x',2),
93 (' x',4),
93 (' x',4),
94 # Note: tabs are counted as a single whitespace!
94 # Note: tabs are counted as a single whitespace!
95 ('\tx', 1),
95 ('\tx', 1),
96 ('\t x', 2),
96 ('\t x', 2),
97 ]
97 ]
98 tt.check_pairs(isp.num_ini_spaces, tests)
98 tt.check_pairs(isp.num_ini_spaces, tests)
99
99
100
100
101 def test_remove_comments():
101 def test_remove_comments():
102 tests = [('text', 'text'),
102 tests = [('text', 'text'),
103 ('text # comment', 'text '),
103 ('text # comment', 'text '),
104 ('text # comment\n', 'text \n'),
104 ('text # comment\n', 'text \n'),
105 ('text # comment \n', 'text \n'),
105 ('text # comment \n', 'text \n'),
106 ('line # c \nline\n','line \nline\n'),
106 ('line # c \nline\n','line \nline\n'),
107 ('line # c \nline#c2 \nline\nline #c\n\n',
107 ('line # c \nline#c2 \nline\nline #c\n\n',
108 'line \nline\nline\nline \n\n'),
108 'line \nline\nline\nline \n\n'),
109 ]
109 ]
110 tt.check_pairs(isp.remove_comments, tests)
110 tt.check_pairs(isp.remove_comments, tests)
111
111
112
112
113 def test_get_input_encoding():
113 def test_get_input_encoding():
114 encoding = isp.get_input_encoding()
114 encoding = isp.get_input_encoding()
115 nt.assert_true(isinstance(encoding, basestring))
115 nt.assert_true(isinstance(encoding, basestring))
116 # simple-minded check that at least encoding a simple string works with the
116 # simple-minded check that at least encoding a simple string works with the
117 # encoding we got.
117 # encoding we got.
118 nt.assert_equal(u'test'.encode(encoding), b'test')
118 nt.assert_equal(u'test'.encode(encoding), b'test')
119
119
120
120
121 class NoInputEncodingTestCase(unittest.TestCase):
121 class NoInputEncodingTestCase(unittest.TestCase):
122 def setUp(self):
122 def setUp(self):
123 self.old_stdin = sys.stdin
123 self.old_stdin = sys.stdin
124 class X: pass
124 class X: pass
125 fake_stdin = X()
125 fake_stdin = X()
126 sys.stdin = fake_stdin
126 sys.stdin = fake_stdin
127
127
128 def test(self):
128 def test(self):
129 # Verify that if sys.stdin has no 'encoding' attribute we do the right
129 # Verify that if sys.stdin has no 'encoding' attribute we do the right
130 # thing
130 # thing
131 enc = isp.get_input_encoding()
131 enc = isp.get_input_encoding()
132 self.assertEqual(enc, 'ascii')
132 self.assertEqual(enc, 'ascii')
133
133
134 def tearDown(self):
134 def tearDown(self):
135 sys.stdin = self.old_stdin
135 sys.stdin = self.old_stdin
136
136
137
137
138 class InputSplitterTestCase(unittest.TestCase):
138 class InputSplitterTestCase(unittest.TestCase):
139 def setUp(self):
139 def setUp(self):
140 self.isp = isp.InputSplitter()
140 self.isp = isp.InputSplitter()
141
141
142 def test_reset(self):
142 def test_reset(self):
143 isp = self.isp
143 isp = self.isp
144 isp.push('x=1')
144 isp.push('x=1')
145 isp.reset()
145 isp.reset()
146 self.assertEqual(isp._buffer, [])
146 self.assertEqual(isp._buffer, [])
147 self.assertEqual(isp.indent_spaces, 0)
147 self.assertEqual(isp.indent_spaces, 0)
148 self.assertEqual(isp.source, '')
148 self.assertEqual(isp.source, '')
149 self.assertEqual(isp.code, None)
149 self.assertEqual(isp.code, None)
150 self.assertEqual(isp._is_complete, False)
150 self.assertEqual(isp._is_complete, False)
151
151
152 def test_source(self):
152 def test_source(self):
153 self.isp._store('1')
153 self.isp._store('1')
154 self.isp._store('2')
154 self.isp._store('2')
155 self.assertEqual(self.isp.source, '1\n2\n')
155 self.assertEqual(self.isp.source, '1\n2\n')
156 self.assertTrue(len(self.isp._buffer)>0)
156 self.assertTrue(len(self.isp._buffer)>0)
157 self.assertEqual(self.isp.source_reset(), '1\n2\n')
157 self.assertEqual(self.isp.source_reset(), '1\n2\n')
158 self.assertEqual(self.isp._buffer, [])
158 self.assertEqual(self.isp._buffer, [])
159 self.assertEqual(self.isp.source, '')
159 self.assertEqual(self.isp.source, '')
160
160
161 def test_indent(self):
161 def test_indent(self):
162 isp = self.isp # shorthand
162 isp = self.isp # shorthand
163 isp.push('x=1')
163 isp.push('x=1')
164 self.assertEqual(isp.indent_spaces, 0)
164 self.assertEqual(isp.indent_spaces, 0)
165 isp.push('if 1:\n x=1')
165 isp.push('if 1:\n x=1')
166 self.assertEqual(isp.indent_spaces, 4)
166 self.assertEqual(isp.indent_spaces, 4)
167 isp.push('y=2\n')
167 isp.push('y=2\n')
168 self.assertEqual(isp.indent_spaces, 0)
168 self.assertEqual(isp.indent_spaces, 0)
169
169
170 def test_indent2(self):
170 def test_indent2(self):
171 isp = self.isp
171 isp = self.isp
172 isp.push('if 1:')
172 isp.push('if 1:')
173 self.assertEqual(isp.indent_spaces, 4)
173 self.assertEqual(isp.indent_spaces, 4)
174 isp.push(' x=1')
174 isp.push(' x=1')
175 self.assertEqual(isp.indent_spaces, 4)
175 self.assertEqual(isp.indent_spaces, 4)
176 # Blank lines shouldn't change the indent level
176 # Blank lines shouldn't change the indent level
177 isp.push(' '*2)
177 isp.push(' '*2)
178 self.assertEqual(isp.indent_spaces, 4)
178 self.assertEqual(isp.indent_spaces, 4)
179
179
180 def test_indent3(self):
180 def test_indent3(self):
181 isp = self.isp
181 isp = self.isp
182 # When a multiline statement contains parens or multiline strings, we
182 # When a multiline statement contains parens or multiline strings, we
183 # shouldn't get confused.
183 # shouldn't get confused.
184 isp.push("if 1:")
184 isp.push("if 1:")
185 isp.push(" x = (1+\n 2)")
185 isp.push(" x = (1+\n 2)")
186 self.assertEqual(isp.indent_spaces, 4)
186 self.assertEqual(isp.indent_spaces, 4)
187
187
188 def test_indent4(self):
188 def test_indent4(self):
189 isp = self.isp
189 isp = self.isp
190 # whitespace after ':' should not screw up indent level
190 # whitespace after ':' should not screw up indent level
191 isp.push('if 1: \n x=1')
191 isp.push('if 1: \n x=1')
192 self.assertEqual(isp.indent_spaces, 4)
192 self.assertEqual(isp.indent_spaces, 4)
193 isp.push('y=2\n')
193 isp.push('y=2\n')
194 self.assertEqual(isp.indent_spaces, 0)
194 self.assertEqual(isp.indent_spaces, 0)
195 isp.push('if 1:\t\n x=1')
195 isp.push('if 1:\t\n x=1')
196 self.assertEqual(isp.indent_spaces, 4)
196 self.assertEqual(isp.indent_spaces, 4)
197 isp.push('y=2\n')
197 isp.push('y=2\n')
198 self.assertEqual(isp.indent_spaces, 0)
198 self.assertEqual(isp.indent_spaces, 0)
199
199
200 def test_dedent_pass(self):
200 def test_dedent_pass(self):
201 isp = self.isp # shorthand
201 isp = self.isp # shorthand
202 # should NOT cause dedent
202 # should NOT cause dedent
203 isp.push('if 1:\n passes = 5')
203 isp.push('if 1:\n passes = 5')
204 self.assertEqual(isp.indent_spaces, 4)
204 self.assertEqual(isp.indent_spaces, 4)
205 isp.push('if 1:\n pass')
205 isp.push('if 1:\n pass')
206 self.assertEqual(isp.indent_spaces, 0)
206 self.assertEqual(isp.indent_spaces, 0)
207 isp.push('if 1:\n pass ')
207 isp.push('if 1:\n pass ')
208 self.assertEqual(isp.indent_spaces, 0)
208 self.assertEqual(isp.indent_spaces, 0)
209
209
210 def test_dedent_break(self):
210 def test_dedent_break(self):
211 isp = self.isp # shorthand
211 isp = self.isp # shorthand
212 # should NOT cause dedent
212 # should NOT cause dedent
213 isp.push('while 1:\n breaks = 5')
213 isp.push('while 1:\n breaks = 5')
214 self.assertEqual(isp.indent_spaces, 4)
214 self.assertEqual(isp.indent_spaces, 4)
215 isp.push('while 1:\n break')
215 isp.push('while 1:\n break')
216 self.assertEqual(isp.indent_spaces, 0)
216 self.assertEqual(isp.indent_spaces, 0)
217 isp.push('while 1:\n break ')
217 isp.push('while 1:\n break ')
218 self.assertEqual(isp.indent_spaces, 0)
218 self.assertEqual(isp.indent_spaces, 0)
219
219
220 def test_dedent_continue(self):
220 def test_dedent_continue(self):
221 isp = self.isp # shorthand
221 isp = self.isp # shorthand
222 # should NOT cause dedent
222 # should NOT cause dedent
223 isp.push('while 1:\n continues = 5')
223 isp.push('while 1:\n continues = 5')
224 self.assertEqual(isp.indent_spaces, 4)
224 self.assertEqual(isp.indent_spaces, 4)
225 isp.push('while 1:\n continue')
225 isp.push('while 1:\n continue')
226 self.assertEqual(isp.indent_spaces, 0)
226 self.assertEqual(isp.indent_spaces, 0)
227 isp.push('while 1:\n continue ')
227 isp.push('while 1:\n continue ')
228 self.assertEqual(isp.indent_spaces, 0)
228 self.assertEqual(isp.indent_spaces, 0)
229
229
230 def test_dedent_raise(self):
230 def test_dedent_raise(self):
231 isp = self.isp # shorthand
231 isp = self.isp # shorthand
232 # should NOT cause dedent
232 # should NOT cause dedent
233 isp.push('if 1:\n raised = 4')
233 isp.push('if 1:\n raised = 4')
234 self.assertEqual(isp.indent_spaces, 4)
234 self.assertEqual(isp.indent_spaces, 4)
235 isp.push('if 1:\n raise TypeError()')
235 isp.push('if 1:\n raise TypeError()')
236 self.assertEqual(isp.indent_spaces, 0)
236 self.assertEqual(isp.indent_spaces, 0)
237 isp.push('if 1:\n raise')
237 isp.push('if 1:\n raise')
238 self.assertEqual(isp.indent_spaces, 0)
238 self.assertEqual(isp.indent_spaces, 0)
239 isp.push('if 1:\n raise ')
239 isp.push('if 1:\n raise ')
240 self.assertEqual(isp.indent_spaces, 0)
240 self.assertEqual(isp.indent_spaces, 0)
241
241
242 def test_dedent_return(self):
242 def test_dedent_return(self):
243 isp = self.isp # shorthand
243 isp = self.isp # shorthand
244 # should NOT cause dedent
244 # should NOT cause dedent
245 isp.push('if 1:\n returning = 4')
245 isp.push('if 1:\n returning = 4')
246 self.assertEqual(isp.indent_spaces, 4)
246 self.assertEqual(isp.indent_spaces, 4)
247 isp.push('if 1:\n return 5 + 493')
247 isp.push('if 1:\n return 5 + 493')
248 self.assertEqual(isp.indent_spaces, 0)
248 self.assertEqual(isp.indent_spaces, 0)
249 isp.push('if 1:\n return')
249 isp.push('if 1:\n return')
250 self.assertEqual(isp.indent_spaces, 0)
250 self.assertEqual(isp.indent_spaces, 0)
251 isp.push('if 1:\n return ')
251 isp.push('if 1:\n return ')
252 self.assertEqual(isp.indent_spaces, 0)
252 self.assertEqual(isp.indent_spaces, 0)
253 isp.push('if 1:\n return(0)')
253 isp.push('if 1:\n return(0)')
254 self.assertEqual(isp.indent_spaces, 0)
254 self.assertEqual(isp.indent_spaces, 0)
255
255
256 def test_push(self):
256 def test_push(self):
257 isp = self.isp
257 isp = self.isp
258 self.assertTrue(isp.push('x=1'))
258 self.assertTrue(isp.push('x=1'))
259
259
260 def test_push2(self):
260 def test_push2(self):
261 isp = self.isp
261 isp = self.isp
262 self.assertFalse(isp.push('if 1:'))
262 self.assertFalse(isp.push('if 1:'))
263 for line in [' x=1', '# a comment', ' y=2']:
263 for line in [' x=1', '# a comment', ' y=2']:
264 print(line)
264 print(line)
265 self.assertTrue(isp.push(line))
265 self.assertTrue(isp.push(line))
266
266
267 def test_push3(self):
267 def test_push3(self):
268 isp = self.isp
268 isp = self.isp
269 isp.push('if True:')
269 isp.push('if True:')
270 isp.push(' a = 1')
270 isp.push(' a = 1')
271 self.assertFalse(isp.push('b = [1,'))
271 self.assertFalse(isp.push('b = [1,'))
272
272
273 def test_push_accepts_more(self):
273 def test_push_accepts_more(self):
274 isp = self.isp
274 isp = self.isp
275 isp.push('x=1')
275 isp.push('x=1')
276 self.assertFalse(isp.push_accepts_more())
276 self.assertFalse(isp.push_accepts_more())
277
277
278 def test_push_accepts_more2(self):
278 def test_push_accepts_more2(self):
279 isp = self.isp
279 isp = self.isp
280 isp.push('if 1:')
280 isp.push('if 1:')
281 self.assertTrue(isp.push_accepts_more())
281 self.assertTrue(isp.push_accepts_more())
282 isp.push(' x=1')
282 isp.push(' x=1')
283 self.assertTrue(isp.push_accepts_more())
283 self.assertTrue(isp.push_accepts_more())
284 isp.push('')
284 isp.push('')
285 self.assertFalse(isp.push_accepts_more())
285 self.assertFalse(isp.push_accepts_more())
286
286
287 def test_push_accepts_more3(self):
287 def test_push_accepts_more3(self):
288 isp = self.isp
288 isp = self.isp
289 isp.push("x = (2+\n3)")
289 isp.push("x = (2+\n3)")
290 self.assertFalse(isp.push_accepts_more())
290 self.assertFalse(isp.push_accepts_more())
291
291
292 def test_push_accepts_more4(self):
292 def test_push_accepts_more4(self):
293 isp = self.isp
293 isp = self.isp
294 # When a multiline statement contains parens or multiline strings, we
294 # When a multiline statement contains parens or multiline strings, we
295 # shouldn't get confused.
295 # shouldn't get confused.
296 # FIXME: we should be able to better handle de-dents in statements like
296 # FIXME: we should be able to better handle de-dents in statements like
297 # multiline strings and multiline expressions (continued with \ or
297 # multiline strings and multiline expressions (continued with \ or
298 # parens). Right now we aren't handling the indentation tracking quite
298 # parens). Right now we aren't handling the indentation tracking quite
299 # correctly with this, though in practice it may not be too much of a
299 # correctly with this, though in practice it may not be too much of a
300 # problem. We'll need to see.
300 # problem. We'll need to see.
301 isp.push("if 1:")
301 isp.push("if 1:")
302 isp.push(" x = (2+")
302 isp.push(" x = (2+")
303 isp.push(" 3)")
303 isp.push(" 3)")
304 self.assertTrue(isp.push_accepts_more())
304 self.assertTrue(isp.push_accepts_more())
305 isp.push(" y = 3")
305 isp.push(" y = 3")
306 self.assertTrue(isp.push_accepts_more())
306 self.assertTrue(isp.push_accepts_more())
307 isp.push('')
307 isp.push('')
308 self.assertFalse(isp.push_accepts_more())
308 self.assertFalse(isp.push_accepts_more())
309
309
310 def test_push_accepts_more5(self):
310 def test_push_accepts_more5(self):
311 isp = self.isp
311 isp = self.isp
312 isp.push('try:')
312 isp.push('try:')
313 isp.push(' a = 5')
313 isp.push(' a = 5')
314 isp.push('except:')
314 isp.push('except:')
315 isp.push(' raise')
315 isp.push(' raise')
316 # We want to be able to add an else: block at this point, so it should
316 # We want to be able to add an else: block at this point, so it should
317 # wait for a blank line.
317 # wait for a blank line.
318 self.assertTrue(isp.push_accepts_more())
318 self.assertTrue(isp.push_accepts_more())
319
319
320 def test_continuation(self):
320 def test_continuation(self):
321 isp = self.isp
321 isp = self.isp
322 isp.push("import os, \\")
322 isp.push("import os, \\")
323 self.assertTrue(isp.push_accepts_more())
323 self.assertTrue(isp.push_accepts_more())
324 isp.push("sys")
324 isp.push("sys")
325 self.assertFalse(isp.push_accepts_more())
325 self.assertFalse(isp.push_accepts_more())
326
326
327 def test_syntax_error(self):
327 def test_syntax_error(self):
328 isp = self.isp
328 isp = self.isp
329 # Syntax errors immediately produce a 'ready' block, so the invalid
329 # Syntax errors immediately produce a 'ready' block, so the invalid
330 # Python can be sent to the kernel for evaluation with possible ipython
330 # Python can be sent to the kernel for evaluation with possible ipython
331 # special-syntax conversion.
331 # special-syntax conversion.
332 isp.push('run foo')
332 isp.push('run foo')
333 self.assertFalse(isp.push_accepts_more())
333 self.assertFalse(isp.push_accepts_more())
334
334
335 def test_unicode(self):
335 def test_unicode(self):
336 self.isp.push(u"Pérez")
336 self.isp.push(u"Pérez")
337 self.isp.push(u'\xc3\xa9')
337 self.isp.push(u'\xc3\xa9')
338 self.isp.push(u"u'\xc3\xa9'")
338 self.isp.push(u"u'\xc3\xa9'")
339
339
340 def test_line_continuation(self):
340 def test_line_continuation(self):
341 """ Test issue #2108."""
341 """ Test issue #2108."""
342 isp = self.isp
342 isp = self.isp
343 # A blank line after a line continuation should not accept more
343 # A blank line after a line continuation should not accept more
344 isp.push("1 \\\n\n")
344 isp.push("1 \\\n\n")
345 self.assertFalse(isp.push_accepts_more())
345 self.assertFalse(isp.push_accepts_more())
346 # Whitespace after a \ is a SyntaxError. The only way to test that
346 # Whitespace after a \ is a SyntaxError. The only way to test that
347 # here is to test that push doesn't accept more (as with
347 # here is to test that push doesn't accept more (as with
348 # test_syntax_error() above).
348 # test_syntax_error() above).
349 isp.push(r"1 \ ")
349 isp.push(r"1 \ ")
350 self.assertFalse(isp.push_accepts_more())
350 self.assertFalse(isp.push_accepts_more())
351 # Even if the line is continuable (c.f. the regular Python
351 # Even if the line is continuable (c.f. the regular Python
352 # interpreter)
352 # interpreter)
353 isp.push(r"(1 \ ")
353 isp.push(r"(1 \ ")
354 self.assertFalse(isp.push_accepts_more())
354 self.assertFalse(isp.push_accepts_more())
355
355
356 class InteractiveLoopTestCase(unittest.TestCase):
356 class InteractiveLoopTestCase(unittest.TestCase):
357 """Tests for an interactive loop like a python shell.
357 """Tests for an interactive loop like a python shell.
358 """
358 """
359 def check_ns(self, lines, ns):
359 def check_ns(self, lines, ns):
360 """Validate that the given input lines produce the resulting namespace.
360 """Validate that the given input lines produce the resulting namespace.
361
361
362 Note: the input lines are given exactly as they would be typed in an
362 Note: the input lines are given exactly as they would be typed in an
363 auto-indenting environment, as mini_interactive_loop above already does
363 auto-indenting environment, as mini_interactive_loop above already does
364 auto-indenting and prepends spaces to the input.
364 auto-indenting and prepends spaces to the input.
365 """
365 """
366 src = mini_interactive_loop(pseudo_input(lines))
366 src = mini_interactive_loop(pseudo_input(lines))
367 test_ns = {}
367 test_ns = {}
368 exec src in test_ns
368 exec src in test_ns
369 # We can't check that the provided ns is identical to the test_ns,
369 # We can't check that the provided ns is identical to the test_ns,
370 # because Python fills test_ns with extra keys (copyright, etc). But
370 # because Python fills test_ns with extra keys (copyright, etc). But
371 # we can check that the given dict is *contained* in test_ns
371 # we can check that the given dict is *contained* in test_ns
372 for k,v in ns.iteritems():
372 for k,v in ns.iteritems():
373 self.assertEqual(test_ns[k], v)
373 self.assertEqual(test_ns[k], v)
374
374
375 def test_simple(self):
375 def test_simple(self):
376 self.check_ns(['x=1'], dict(x=1))
376 self.check_ns(['x=1'], dict(x=1))
377
377
378 def test_simple2(self):
378 def test_simple2(self):
379 self.check_ns(['if 1:', 'x=2'], dict(x=2))
379 self.check_ns(['if 1:', 'x=2'], dict(x=2))
380
380
381 def test_xy(self):
381 def test_xy(self):
382 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
382 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
383
383
384 def test_abc(self):
384 def test_abc(self):
385 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
385 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
386
386
387 def test_multi(self):
387 def test_multi(self):
388 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
388 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
389
389
390
390
391 def test_LineInfo():
392 """Simple test for LineInfo construction and str()"""
393 linfo = isp.LineInfo(' %cd /home')
394 nt.assert_equal(str(linfo), 'LineInfo [ |%|cd|/home]')
395
396
397
398
399 class IPythonInputTestCase(InputSplitterTestCase):
391 class IPythonInputTestCase(InputSplitterTestCase):
400 """By just creating a new class whose .isp is a different instance, we
392 """By just creating a new class whose .isp is a different instance, we
401 re-run the same test battery on the new input splitter.
393 re-run the same test battery on the new input splitter.
402
394
403 In addition, this runs the tests over the syntax and syntax_ml dicts that
395 In addition, this runs the tests over the syntax and syntax_ml dicts that
404 were tested by individual functions, as part of the OO interface.
396 were tested by individual functions, as part of the OO interface.
405
397
406 It also makes some checks on the raw buffer storage.
398 It also makes some checks on the raw buffer storage.
407 """
399 """
408
400
409 def setUp(self):
401 def setUp(self):
410 self.isp = isp.IPythonInputSplitter()
402 self.isp = isp.IPythonInputSplitter()
411
403
412 def test_syntax(self):
404 def test_syntax(self):
413 """Call all single-line syntax tests from the main object"""
405 """Call all single-line syntax tests from the main object"""
414 isp = self.isp
406 isp = self.isp
415 for example in syntax.itervalues():
407 for example in syntax.itervalues():
416 for raw, out_t in example:
408 for raw, out_t in example:
417 if raw.startswith(' '):
409 if raw.startswith(' '):
418 continue
410 continue
419
411
420 isp.push(raw+'\n')
412 isp.push(raw+'\n')
421 out, out_raw = isp.source_raw_reset()
413 out, out_raw = isp.source_raw_reset()
422 self.assertEqual(out.rstrip(), out_t,
414 self.assertEqual(out.rstrip(), out_t,
423 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
415 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
424 self.assertEqual(out_raw.rstrip(), raw.rstrip())
416 self.assertEqual(out_raw.rstrip(), raw.rstrip())
425
417
426 def test_syntax_multiline(self):
418 def test_syntax_multiline(self):
427 isp = self.isp
419 isp = self.isp
428 for example in syntax_ml.itervalues():
420 for example in syntax_ml.itervalues():
429 for line_pairs in example:
421 for line_pairs in example:
430 out_t_parts = []
422 out_t_parts = []
431 raw_parts = []
423 raw_parts = []
432 for lraw, out_t_part in line_pairs:
424 for lraw, out_t_part in line_pairs:
433 if out_t_part is not None:
425 if out_t_part is not None:
434 out_t_parts.append(out_t_part)
426 out_t_parts.append(out_t_part)
435
427
436 if lraw is not None:
428 if lraw is not None:
437 isp.push(lraw)
429 isp.push(lraw)
438 raw_parts.append(lraw)
430 raw_parts.append(lraw)
439
431
440 out, out_raw = isp.source_raw_reset()
432 out, out_raw = isp.source_raw_reset()
441 out_t = '\n'.join(out_t_parts).rstrip()
433 out_t = '\n'.join(out_t_parts).rstrip()
442 raw = '\n'.join(raw_parts).rstrip()
434 raw = '\n'.join(raw_parts).rstrip()
443 self.assertEqual(out.rstrip(), out_t)
435 self.assertEqual(out.rstrip(), out_t)
444 self.assertEqual(out_raw.rstrip(), raw)
436 self.assertEqual(out_raw.rstrip(), raw)
445
437
446 def test_syntax_multiline_cell(self):
438 def test_syntax_multiline_cell(self):
447 isp = self.isp
439 isp = self.isp
448 for example in syntax_ml.itervalues():
440 for example in syntax_ml.itervalues():
449
441
450 out_t_parts = []
442 out_t_parts = []
451 for line_pairs in example:
443 for line_pairs in example:
452 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
444 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
453 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
445 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
454 out = isp.transform_cell(raw)
446 out = isp.transform_cell(raw)
455 # Match ignoring trailing whitespace
447 # Match ignoring trailing whitespace
456 self.assertEqual(out.rstrip(), out_t.rstrip())
448 self.assertEqual(out.rstrip(), out_t.rstrip())
457
449
458 #-----------------------------------------------------------------------------
450 #-----------------------------------------------------------------------------
459 # Main - use as a script, mostly for developer experiments
451 # Main - use as a script, mostly for developer experiments
460 #-----------------------------------------------------------------------------
452 #-----------------------------------------------------------------------------
461
453
462 if __name__ == '__main__':
454 if __name__ == '__main__':
463 # A simple demo for interactive experimentation. This code will not get
455 # A simple demo for interactive experimentation. This code will not get
464 # picked up by any test suite.
456 # picked up by any test suite.
465 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
457 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
466
458
467 # configure here the syntax to use, prompt and whether to autoindent
459 # configure here the syntax to use, prompt and whether to autoindent
468 #isp, start_prompt = InputSplitter(), '>>> '
460 #isp, start_prompt = InputSplitter(), '>>> '
469 isp, start_prompt = IPythonInputSplitter(), 'In> '
461 isp, start_prompt = IPythonInputSplitter(), 'In> '
470
462
471 autoindent = True
463 autoindent = True
472 #autoindent = False
464 #autoindent = False
473
465
474 try:
466 try:
475 while True:
467 while True:
476 prompt = start_prompt
468 prompt = start_prompt
477 while isp.push_accepts_more():
469 while isp.push_accepts_more():
478 indent = ' '*isp.indent_spaces
470 indent = ' '*isp.indent_spaces
479 if autoindent:
471 if autoindent:
480 line = indent + raw_input(prompt+indent)
472 line = indent + raw_input(prompt+indent)
481 else:
473 else:
482 line = raw_input(prompt)
474 line = raw_input(prompt)
483 isp.push(line)
475 isp.push(line)
484 prompt = '... '
476 prompt = '... '
485
477
486 # Here we just return input so we can use it in a test suite, but a
478 # Here we just return input so we can use it in a test suite, but a
487 # real interpreter would instead send it for execution somewhere.
479 # real interpreter would instead send it for execution somewhere.
488 #src = isp.source; raise EOFError # dbg
480 #src = isp.source; raise EOFError # dbg
489 src, raw = isp.source_raw_reset()
481 src, raw = isp.source_raw_reset()
490 print 'Input source was:\n', src
482 print 'Input source was:\n', src
491 print 'Raw source was:\n', raw
483 print 'Raw source was:\n', raw
492 except EOFError:
484 except EOFError:
493 print 'Bye'
485 print 'Bye'
494
486
495 # Tests for cell magics support
487 # Tests for cell magics support
496
488
497 def test_last_blank():
489 def test_last_blank():
498 nt.assert_false(isp.last_blank(''))
490 nt.assert_false(isp.last_blank(''))
499 nt.assert_false(isp.last_blank('abc'))
491 nt.assert_false(isp.last_blank('abc'))
500 nt.assert_false(isp.last_blank('abc\n'))
492 nt.assert_false(isp.last_blank('abc\n'))
501 nt.assert_false(isp.last_blank('abc\na'))
493 nt.assert_false(isp.last_blank('abc\na'))
502
494
503 nt.assert_true(isp.last_blank('\n'))
495 nt.assert_true(isp.last_blank('\n'))
504 nt.assert_true(isp.last_blank('\n '))
496 nt.assert_true(isp.last_blank('\n '))
505 nt.assert_true(isp.last_blank('abc\n '))
497 nt.assert_true(isp.last_blank('abc\n '))
506 nt.assert_true(isp.last_blank('abc\n\n'))
498 nt.assert_true(isp.last_blank('abc\n\n'))
507 nt.assert_true(isp.last_blank('abc\nd\n\n'))
499 nt.assert_true(isp.last_blank('abc\nd\n\n'))
508 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
500 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
509 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
501 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
510
502
511
503
512 def test_last_two_blanks():
504 def test_last_two_blanks():
513 nt.assert_false(isp.last_two_blanks(''))
505 nt.assert_false(isp.last_two_blanks(''))
514 nt.assert_false(isp.last_two_blanks('abc'))
506 nt.assert_false(isp.last_two_blanks('abc'))
515 nt.assert_false(isp.last_two_blanks('abc\n'))
507 nt.assert_false(isp.last_two_blanks('abc\n'))
516 nt.assert_false(isp.last_two_blanks('abc\n\na'))
508 nt.assert_false(isp.last_two_blanks('abc\n\na'))
517 nt.assert_false(isp.last_two_blanks('abc\n \n'))
509 nt.assert_false(isp.last_two_blanks('abc\n \n'))
518 nt.assert_false(isp.last_two_blanks('abc\n\n'))
510 nt.assert_false(isp.last_two_blanks('abc\n\n'))
519
511
520 nt.assert_true(isp.last_two_blanks('\n\n'))
512 nt.assert_true(isp.last_two_blanks('\n\n'))
521 nt.assert_true(isp.last_two_blanks('\n\n '))
513 nt.assert_true(isp.last_two_blanks('\n\n '))
522 nt.assert_true(isp.last_two_blanks('\n \n'))
514 nt.assert_true(isp.last_two_blanks('\n \n'))
523 nt.assert_true(isp.last_two_blanks('abc\n\n '))
515 nt.assert_true(isp.last_two_blanks('abc\n\n '))
524 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
516 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
525 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
517 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
526 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
518 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
527 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
519 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
528 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
520 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
529 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
521 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
530
522
531
523
532 class CellMagicsCommon(object):
524 class CellMagicsCommon(object):
533
525
534 def test_whole_cell(self):
526 def test_whole_cell(self):
535 src = "%%cellm line\nbody\n"
527 src = "%%cellm line\nbody\n"
536 sp = self.sp
528 sp = self.sp
537 sp.push(src)
529 sp.push(src)
538 out = sp.source_reset()
530 out = sp.source_reset()
539 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
531 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
540 nt.assert_equal(out, py3compat.u_format(ref))
532 nt.assert_equal(out, py3compat.u_format(ref))
541
533
542 def test_cellmagic_help(self):
534 def test_cellmagic_help(self):
543 self.sp.push('%%cellm?')
535 self.sp.push('%%cellm?')
544 nt.assert_false(self.sp.push_accepts_more())
536 nt.assert_false(self.sp.push_accepts_more())
545
537
546 def tearDown(self):
538 def tearDown(self):
547 self.sp.reset()
539 self.sp.reset()
548
540
549
541
550 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
542 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
551 sp = isp.IPythonInputSplitter(line_input_checker=False)
543 sp = isp.IPythonInputSplitter(line_input_checker=False)
552
544
553 def test_incremental(self):
545 def test_incremental(self):
554 sp = self.sp
546 sp = self.sp
555 sp.push('%%cellm firstline\n')
547 sp.push('%%cellm firstline\n')
556 nt.assert_true(sp.push_accepts_more()) #1
548 nt.assert_true(sp.push_accepts_more()) #1
557 sp.push('line2\n')
549 sp.push('line2\n')
558 nt.assert_true(sp.push_accepts_more()) #2
550 nt.assert_true(sp.push_accepts_more()) #2
559 sp.push('\n')
551 sp.push('\n')
560 # This should accept a blank line and carry on until the cell is reset
552 # This should accept a blank line and carry on until the cell is reset
561 nt.assert_true(sp.push_accepts_more()) #3
553 nt.assert_true(sp.push_accepts_more()) #3
562
554
563 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
555 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
564 sp = isp.IPythonInputSplitter(line_input_checker=True)
556 sp = isp.IPythonInputSplitter(line_input_checker=True)
565
557
566 def test_incremental(self):
558 def test_incremental(self):
567 sp = self.sp
559 sp = self.sp
568 sp.push('%%cellm line2\n')
560 sp.push('%%cellm line2\n')
569 nt.assert_true(sp.push_accepts_more()) #1
561 nt.assert_true(sp.push_accepts_more()) #1
570 sp.push('\n')
562 sp.push('\n')
571 # In this case, a blank line should end the cell magic
563 # In this case, a blank line should end the cell magic
572 nt.assert_false(sp.push_accepts_more()) #2
564 nt.assert_false(sp.push_accepts_more()) #2
@@ -1,423 +1,422 b''
1 import tokenize
1 import tokenize
2 import unittest
3 import nose.tools as nt
2 import nose.tools as nt
4
3
5 from IPython.testing import tools as tt
4 from IPython.testing import tools as tt
6 from IPython.utils import py3compat
5 from IPython.utils import py3compat
7 u_fmt = py3compat.u_format
6 u_fmt = py3compat.u_format
8
7
9 from IPython.core import inputtransformer as ipt
8 from IPython.core import inputtransformer as ipt
10
9
11 def transform_and_reset(transformer):
10 def transform_and_reset(transformer):
12 transformer = transformer()
11 transformer = transformer()
13 def transform(inp):
12 def transform(inp):
14 try:
13 try:
15 return transformer.push(inp)
14 return transformer.push(inp)
16 finally:
15 finally:
17 transformer.reset()
16 transformer.reset()
18
17
19 return transform
18 return transform
20
19
21 # Transformer tests
20 # Transformer tests
22 def transform_checker(tests, transformer, **kwargs):
21 def transform_checker(tests, transformer, **kwargs):
23 """Utility to loop over test inputs"""
22 """Utility to loop over test inputs"""
24 transformer = transformer(**kwargs)
23 transformer = transformer(**kwargs)
25 try:
24 try:
26 for inp, tr in tests:
25 for inp, tr in tests:
27 if inp is None:
26 if inp is None:
28 out = transformer.reset()
27 out = transformer.reset()
29 else:
28 else:
30 out = transformer.push(inp)
29 out = transformer.push(inp)
31 nt.assert_equal(out, tr)
30 nt.assert_equal(out, tr)
32 finally:
31 finally:
33 transformer.reset()
32 transformer.reset()
34
33
35 # Data for all the syntax tests in the form of lists of pairs of
34 # Data for all the syntax tests in the form of lists of pairs of
36 # raw/transformed input. We store it here as a global dict so that we can use
35 # raw/transformed input. We store it here as a global dict so that we can use
37 # it both within single-function tests and also to validate the behavior of the
36 # it both within single-function tests and also to validate the behavior of the
38 # larger objects
37 # larger objects
39
38
40 syntax = \
39 syntax = \
41 dict(assign_system =
40 dict(assign_system =
42 [(i,py3compat.u_format(o)) for i,o in \
41 [(i,py3compat.u_format(o)) for i,o in \
43 [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"),
42 [(u'a =! ls', "a = get_ipython().getoutput({u}'ls')"),
44 (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"),
43 (u'b = !ls', "b = get_ipython().getoutput({u}'ls')"),
45 ('x=1', 'x=1'), # normal input is unmodified
44 ('x=1', 'x=1'), # normal input is unmodified
46 (' ',' '), # blank lines are kept intact
45 (' ',' '), # blank lines are kept intact
47 ]],
46 ]],
48
47
49 assign_magic =
48 assign_magic =
50 [(i,py3compat.u_format(o)) for i,o in \
49 [(i,py3compat.u_format(o)) for i,o in \
51 [(u'a =% who', "a = get_ipython().magic({u}'who')"),
50 [(u'a =% who', "a = get_ipython().magic({u}'who')"),
52 (u'b = %who', "b = get_ipython().magic({u}'who')"),
51 (u'b = %who', "b = get_ipython().magic({u}'who')"),
53 ('x=1', 'x=1'), # normal input is unmodified
52 ('x=1', 'x=1'), # normal input is unmodified
54 (' ',' '), # blank lines are kept intact
53 (' ',' '), # blank lines are kept intact
55 ]],
54 ]],
56
55
57 classic_prompt =
56 classic_prompt =
58 [('>>> x=1', 'x=1'),
57 [('>>> x=1', 'x=1'),
59 ('x=1', 'x=1'), # normal input is unmodified
58 ('x=1', 'x=1'), # normal input is unmodified
60 (' ', ' '), # blank lines are kept intact
59 (' ', ' '), # blank lines are kept intact
61 ],
60 ],
62
61
63 ipy_prompt =
62 ipy_prompt =
64 [('In [1]: x=1', 'x=1'),
63 [('In [1]: x=1', 'x=1'),
65 ('x=1', 'x=1'), # normal input is unmodified
64 ('x=1', 'x=1'), # normal input is unmodified
66 (' ',' '), # blank lines are kept intact
65 (' ',' '), # blank lines are kept intact
67 ],
66 ],
68
67
69 # Tests for the escape transformer to leave normal code alone
68 # Tests for the escape transformer to leave normal code alone
70 escaped_noesc =
69 escaped_noesc =
71 [ (' ', ' '),
70 [ (' ', ' '),
72 ('x=1', 'x=1'),
71 ('x=1', 'x=1'),
73 ],
72 ],
74
73
75 # System calls
74 # System calls
76 escaped_shell =
75 escaped_shell =
77 [(i,py3compat.u_format(o)) for i,o in \
76 [(i,py3compat.u_format(o)) for i,o in \
78 [ (u'!ls', "get_ipython().system({u}'ls')"),
77 [ (u'!ls', "get_ipython().system({u}'ls')"),
79 # Double-escape shell, this means to capture the output of the
78 # Double-escape shell, this means to capture the output of the
80 # subprocess and return it
79 # subprocess and return it
81 (u'!!ls', "get_ipython().getoutput({u}'ls')"),
80 (u'!!ls', "get_ipython().getoutput({u}'ls')"),
82 ]],
81 ]],
83
82
84 # Help/object info
83 # Help/object info
85 escaped_help =
84 escaped_help =
86 [(i,py3compat.u_format(o)) for i,o in \
85 [(i,py3compat.u_format(o)) for i,o in \
87 [ (u'?', 'get_ipython().show_usage()'),
86 [ (u'?', 'get_ipython().show_usage()'),
88 (u'?x1', "get_ipython().magic({u}'pinfo x1')"),
87 (u'?x1', "get_ipython().magic({u}'pinfo x1')"),
89 (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"),
88 (u'??x2', "get_ipython().magic({u}'pinfo2 x2')"),
90 (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"),
89 (u'?a.*s', "get_ipython().magic({u}'psearch a.*s')"),
91 (u'?%hist1', "get_ipython().magic({u}'pinfo %hist1')"),
90 (u'?%hist1', "get_ipython().magic({u}'pinfo %hist1')"),
92 (u'?%%hist2', "get_ipython().magic({u}'pinfo %%hist2')"),
91 (u'?%%hist2', "get_ipython().magic({u}'pinfo %%hist2')"),
93 (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"),
92 (u'?abc = qwe', "get_ipython().magic({u}'pinfo abc')"),
94 ]],
93 ]],
95
94
96 end_help =
95 end_help =
97 [(i,py3compat.u_format(o)) for i,o in \
96 [(i,py3compat.u_format(o)) for i,o in \
98 [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"),
97 [ (u'x3?', "get_ipython().magic({u}'pinfo x3')"),
99 (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"),
98 (u'x4??', "get_ipython().magic({u}'pinfo2 x4')"),
100 (u'%hist1?', "get_ipython().magic({u}'pinfo %hist1')"),
99 (u'%hist1?', "get_ipython().magic({u}'pinfo %hist1')"),
101 (u'%hist2??', "get_ipython().magic({u}'pinfo2 %hist2')"),
100 (u'%hist2??', "get_ipython().magic({u}'pinfo2 %hist2')"),
102 (u'%%hist3?', "get_ipython().magic({u}'pinfo %%hist3')"),
101 (u'%%hist3?', "get_ipython().magic({u}'pinfo %%hist3')"),
103 (u'%%hist4??', "get_ipython().magic({u}'pinfo2 %%hist4')"),
102 (u'%%hist4??', "get_ipython().magic({u}'pinfo2 %%hist4')"),
104 (u'f*?', "get_ipython().magic({u}'psearch f*')"),
103 (u'f*?', "get_ipython().magic({u}'psearch f*')"),
105 (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"),
104 (u'ax.*aspe*?', "get_ipython().magic({u}'psearch ax.*aspe*')"),
106 (u'a = abc?', "get_ipython().set_next_input({u}'a = abc');"
105 (u'a = abc?', "get_ipython().set_next_input({u}'a = abc');"
107 "get_ipython().magic({u}'pinfo abc')"),
106 "get_ipython().magic({u}'pinfo abc')"),
108 (u'a = abc.qe??', "get_ipython().set_next_input({u}'a = abc.qe');"
107 (u'a = abc.qe??', "get_ipython().set_next_input({u}'a = abc.qe');"
109 "get_ipython().magic({u}'pinfo2 abc.qe')"),
108 "get_ipython().magic({u}'pinfo2 abc.qe')"),
110 (u'a = *.items?', "get_ipython().set_next_input({u}'a = *.items');"
109 (u'a = *.items?', "get_ipython().set_next_input({u}'a = *.items');"
111 "get_ipython().magic({u}'psearch *.items')"),
110 "get_ipython().magic({u}'psearch *.items')"),
112 (u'plot(a?', "get_ipython().set_next_input({u}'plot(a');"
111 (u'plot(a?', "get_ipython().set_next_input({u}'plot(a');"
113 "get_ipython().magic({u}'pinfo a')"),
112 "get_ipython().magic({u}'pinfo a')"),
114 (u'a*2 #comment?', 'a*2 #comment?'),
113 (u'a*2 #comment?', 'a*2 #comment?'),
115 ]],
114 ]],
116
115
117 # Explicit magic calls
116 # Explicit magic calls
118 escaped_magic =
117 escaped_magic =
119 [(i,py3compat.u_format(o)) for i,o in \
118 [(i,py3compat.u_format(o)) for i,o in \
120 [ (u'%cd', "get_ipython().magic({u}'cd')"),
119 [ (u'%cd', "get_ipython().magic({u}'cd')"),
121 (u'%cd /home', "get_ipython().magic({u}'cd /home')"),
120 (u'%cd /home', "get_ipython().magic({u}'cd /home')"),
122 # Backslashes need to be escaped.
121 # Backslashes need to be escaped.
123 (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"),
122 (u'%cd C:\\User', "get_ipython().magic({u}'cd C:\\\\User')"),
124 (u' %magic', " get_ipython().magic({u}'magic')"),
123 (u' %magic', " get_ipython().magic({u}'magic')"),
125 ]],
124 ]],
126
125
127 # Quoting with separate arguments
126 # Quoting with separate arguments
128 escaped_quote =
127 escaped_quote =
129 [ (',f', 'f("")'),
128 [ (',f', 'f("")'),
130 (',f x', 'f("x")'),
129 (',f x', 'f("x")'),
131 (' ,f y', ' f("y")'),
130 (' ,f y', ' f("y")'),
132 (',f a b', 'f("a", "b")'),
131 (',f a b', 'f("a", "b")'),
133 ],
132 ],
134
133
135 # Quoting with single argument
134 # Quoting with single argument
136 escaped_quote2 =
135 escaped_quote2 =
137 [ (';f', 'f("")'),
136 [ (';f', 'f("")'),
138 (';f x', 'f("x")'),
137 (';f x', 'f("x")'),
139 (' ;f y', ' f("y")'),
138 (' ;f y', ' f("y")'),
140 (';f a b', 'f("a b")'),
139 (';f a b', 'f("a b")'),
141 ],
140 ],
142
141
143 # Simply apply parens
142 # Simply apply parens
144 escaped_paren =
143 escaped_paren =
145 [ ('/f', 'f()'),
144 [ ('/f', 'f()'),
146 ('/f x', 'f(x)'),
145 ('/f x', 'f(x)'),
147 (' /f y', ' f(y)'),
146 (' /f y', ' f(y)'),
148 ('/f a b', 'f(a, b)'),
147 ('/f a b', 'f(a, b)'),
149 ],
148 ],
150
149
151 # Check that we transform prompts before other transforms
150 # Check that we transform prompts before other transforms
152 mixed =
151 mixed =
153 [(i,py3compat.u_format(o)) for i,o in \
152 [(i,py3compat.u_format(o)) for i,o in \
154 [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"),
153 [ (u'In [1]: %lsmagic', "get_ipython().magic({u}'lsmagic')"),
155 (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"),
154 (u'>>> %lsmagic', "get_ipython().magic({u}'lsmagic')"),
156 (u'In [2]: !ls', "get_ipython().system({u}'ls')"),
155 (u'In [2]: !ls', "get_ipython().system({u}'ls')"),
157 (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"),
156 (u'In [3]: abs?', "get_ipython().magic({u}'pinfo abs')"),
158 (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"),
157 (u'In [4]: b = %who', "b = get_ipython().magic({u}'who')"),
159 ]],
158 ]],
160 )
159 )
161
160
162 # multiline syntax examples. Each of these should be a list of lists, with
161 # multiline syntax examples. Each of these should be a list of lists, with
163 # each entry itself having pairs of raw/transformed input. The union (with
162 # each entry itself having pairs of raw/transformed input. The union (with
164 # '\n'.join() of the transformed inputs is what the splitter should produce
163 # '\n'.join() of the transformed inputs is what the splitter should produce
165 # when fed the raw lines one at a time via push.
164 # when fed the raw lines one at a time via push.
166 syntax_ml = \
165 syntax_ml = \
167 dict(classic_prompt =
166 dict(classic_prompt =
168 [ [('>>> for i in range(10):','for i in range(10):'),
167 [ [('>>> for i in range(10):','for i in range(10):'),
169 ('... print i',' print i'),
168 ('... print i',' print i'),
170 ('... ', ''),
169 ('... ', ''),
171 ],
170 ],
172 [('>>> a="""','a="""'),
171 [('>>> a="""','a="""'),
173 ('... 123"""','123"""'),
172 ('... 123"""','123"""'),
174 ],
173 ],
175 [('a="""','a="""'),
174 [('a="""','a="""'),
176 ('... 123','123'),
175 ('... 123','123'),
177 ('... 456"""','456"""'),
176 ('... 456"""','456"""'),
178 ],
177 ],
179 [('a="""','a="""'),
178 [('a="""','a="""'),
180 ('123','123'),
179 ('123','123'),
181 ('... 456"""','... 456"""'),
180 ('... 456"""','... 456"""'),
182 ],
181 ],
183 [('>>> def f(x):', 'def f(x):'),
182 [('>>> def f(x):', 'def f(x):'),
184 ('...', ''),
183 ('...', ''),
185 ('... return x', ' return x'),
184 ('... return x', ' return x'),
186 ],
185 ],
187 ],
186 ],
188
187
189 ipy_prompt =
188 ipy_prompt =
190 [ [('In [24]: for i in range(10):','for i in range(10):'),
189 [ [('In [24]: for i in range(10):','for i in range(10):'),
191 (' ....: print i',' print i'),
190 (' ....: print i',' print i'),
192 (' ....: ', ''),
191 (' ....: ', ''),
193 ],
192 ],
194 [('In [2]: a="""','a="""'),
193 [('In [2]: a="""','a="""'),
195 (' ...: 123"""','123"""'),
194 (' ...: 123"""','123"""'),
196 ],
195 ],
197 [('a="""','a="""'),
196 [('a="""','a="""'),
198 (' ...: 123','123'),
197 (' ...: 123','123'),
199 (' ...: 456"""','456"""'),
198 (' ...: 456"""','456"""'),
200 ],
199 ],
201 [('a="""','a="""'),
200 [('a="""','a="""'),
202 ('123','123'),
201 ('123','123'),
203 (' ...: 456"""',' ...: 456"""'),
202 (' ...: 456"""',' ...: 456"""'),
204 ],
203 ],
205 ],
204 ],
206
205
207 multiline_datastructure_prompt =
206 multiline_datastructure_prompt =
208 [ [('>>> a = [1,','a = [1,'),
207 [ [('>>> a = [1,','a = [1,'),
209 ('... 2]','2]'),
208 ('... 2]','2]'),
210 ],
209 ],
211 ],
210 ],
212
211
213 multiline_datastructure =
212 multiline_datastructure =
214 [ [('b = ("%s"', None),
213 [ [('b = ("%s"', None),
215 ('# comment', None),
214 ('# comment', None),
216 ('%foo )', 'b = ("%s"\n# comment\n%foo )'),
215 ('%foo )', 'b = ("%s"\n# comment\n%foo )'),
217 ],
216 ],
218 ],
217 ],
219
218
220 leading_indent =
219 leading_indent =
221 [ [(' print "hi"','print "hi"'),
220 [ [(' print "hi"','print "hi"'),
222 ],
221 ],
223 [(' for a in range(5):','for a in range(5):'),
222 [(' for a in range(5):','for a in range(5):'),
224 (' a*2',' a*2'),
223 (' a*2',' a*2'),
225 ],
224 ],
226 [(' a="""','a="""'),
225 [(' a="""','a="""'),
227 (' 123"""','123"""'),
226 (' 123"""','123"""'),
228 ],
227 ],
229 [('a="""','a="""'),
228 [('a="""','a="""'),
230 (' 123"""',' 123"""'),
229 (' 123"""',' 123"""'),
231 ],
230 ],
232 ],
231 ],
233
232
234 cellmagic =
233 cellmagic =
235 [ [(u'%%foo a', None),
234 [ [(u'%%foo a', None),
236 (None, u_fmt("get_ipython().run_cell_magic({u}'foo', {u}'a', {u}'')")),
235 (None, u_fmt("get_ipython().run_cell_magic({u}'foo', {u}'a', {u}'')")),
237 ],
236 ],
238 [(u'%%bar 123', None),
237 [(u'%%bar 123', None),
239 (u'hello', None),
238 (u'hello', None),
240 (None , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
239 (None , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
241 ],
240 ],
242 ],
241 ],
243
242
244 escaped =
243 escaped =
245 [ [('%abc def \\', None),
244 [ [('%abc def \\', None),
246 ('ghi', u_fmt("get_ipython().magic({u}'abc def ghi')")),
245 ('ghi', u_fmt("get_ipython().magic({u}'abc def ghi')")),
247 ],
246 ],
248 [('%abc def \\', None),
247 [('%abc def \\', None),
249 ('ghi\\', None),
248 ('ghi\\', None),
250 (None, u_fmt("get_ipython().magic({u}'abc def ghi')")),
249 (None, u_fmt("get_ipython().magic({u}'abc def ghi')")),
251 ],
250 ],
252 ],
251 ],
253
252
254 assign_magic =
253 assign_magic =
255 [ [(u'a = %bc de \\', None),
254 [ [(u'a = %bc de \\', None),
256 (u'fg', u_fmt("a = get_ipython().magic({u}'bc de fg')")),
255 (u'fg', u_fmt("a = get_ipython().magic({u}'bc de fg')")),
257 ],
256 ],
258 [(u'a = %bc de \\', None),
257 [(u'a = %bc de \\', None),
259 (u'fg\\', None),
258 (u'fg\\', None),
260 (None, u_fmt("a = get_ipython().magic({u}'bc de fg')")),
259 (None, u_fmt("a = get_ipython().magic({u}'bc de fg')")),
261 ],
260 ],
262 ],
261 ],
263
262
264 assign_system =
263 assign_system =
265 [ [(u'a = !bc de \\', None),
264 [ [(u'a = !bc de \\', None),
266 (u'fg', u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
265 (u'fg', u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
267 ],
266 ],
268 [(u'a = !bc de \\', None),
267 [(u'a = !bc de \\', None),
269 (u'fg\\', None),
268 (u'fg\\', None),
270 (None, u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
269 (None, u_fmt("a = get_ipython().getoutput({u}'bc de fg')")),
271 ],
270 ],
272 ],
271 ],
273 )
272 )
274
273
275
274
276 def test_assign_system():
275 def test_assign_system():
277 tt.check_pairs(transform_and_reset(ipt.assign_from_system), syntax['assign_system'])
276 tt.check_pairs(transform_and_reset(ipt.assign_from_system), syntax['assign_system'])
278
277
279 def test_assign_magic():
278 def test_assign_magic():
280 tt.check_pairs(transform_and_reset(ipt.assign_from_magic), syntax['assign_magic'])
279 tt.check_pairs(transform_and_reset(ipt.assign_from_magic), syntax['assign_magic'])
281
280
282 def test_classic_prompt():
281 def test_classic_prompt():
283 tt.check_pairs(transform_and_reset(ipt.classic_prompt), syntax['classic_prompt'])
282 tt.check_pairs(transform_and_reset(ipt.classic_prompt), syntax['classic_prompt'])
284 for example in syntax_ml['classic_prompt']:
283 for example in syntax_ml['classic_prompt']:
285 transform_checker(example, ipt.classic_prompt)
284 transform_checker(example, ipt.classic_prompt)
286 for example in syntax_ml['multiline_datastructure_prompt']:
285 for example in syntax_ml['multiline_datastructure_prompt']:
287 transform_checker(example, ipt.classic_prompt)
286 transform_checker(example, ipt.classic_prompt)
288
287
289
288
290 def test_ipy_prompt():
289 def test_ipy_prompt():
291 tt.check_pairs(transform_and_reset(ipt.ipy_prompt), syntax['ipy_prompt'])
290 tt.check_pairs(transform_and_reset(ipt.ipy_prompt), syntax['ipy_prompt'])
292 for example in syntax_ml['ipy_prompt']:
291 for example in syntax_ml['ipy_prompt']:
293 transform_checker(example, ipt.ipy_prompt)
292 transform_checker(example, ipt.ipy_prompt)
294
293
295 def test_assemble_logical_lines():
294 def test_assemble_logical_lines():
296 tests = \
295 tests = \
297 [ [(u"a = \\", None),
296 [ [(u"a = \\", None),
298 (u"123", u"a = 123"),
297 (u"123", u"a = 123"),
299 ],
298 ],
300 [(u"a = \\", None), # Test resetting when within a multi-line string
299 [(u"a = \\", None), # Test resetting when within a multi-line string
301 (u"12 *\\", None),
300 (u"12 *\\", None),
302 (None, u"a = 12 *"),
301 (None, u"a = 12 *"),
303 ],
302 ],
304 [(u"# foo\\", u"# foo\\"), # Comments can't be continued like this
303 [(u"# foo\\", u"# foo\\"), # Comments can't be continued like this
305 ],
304 ],
306 ]
305 ]
307 for example in tests:
306 for example in tests:
308 transform_checker(example, ipt.assemble_logical_lines)
307 transform_checker(example, ipt.assemble_logical_lines)
309
308
310 def test_assemble_python_lines():
309 def test_assemble_python_lines():
311 tests = \
310 tests = \
312 [ [(u"a = '''", None),
311 [ [(u"a = '''", None),
313 (u"abc'''", u"a = '''\nabc'''"),
312 (u"abc'''", u"a = '''\nabc'''"),
314 ],
313 ],
315 [(u"a = '''", None), # Test resetting when within a multi-line string
314 [(u"a = '''", None), # Test resetting when within a multi-line string
316 (u"def", None),
315 (u"def", None),
317 (None, u"a = '''\ndef"),
316 (None, u"a = '''\ndef"),
318 ],
317 ],
319 [(u"a = [1,", None),
318 [(u"a = [1,", None),
320 (u"2]", u"a = [1,\n2]"),
319 (u"2]", u"a = [1,\n2]"),
321 ],
320 ],
322 [(u"a = [1,", None), # Test resetting when within a multi-line string
321 [(u"a = [1,", None), # Test resetting when within a multi-line string
323 (u"2,", None),
322 (u"2,", None),
324 (None, u"a = [1,\n2,"),
323 (None, u"a = [1,\n2,"),
325 ],
324 ],
326 ] + syntax_ml['multiline_datastructure']
325 ] + syntax_ml['multiline_datastructure']
327 for example in tests:
326 for example in tests:
328 transform_checker(example, ipt.assemble_python_lines)
327 transform_checker(example, ipt.assemble_python_lines)
329
328
330
329
331 def test_help_end():
330 def test_help_end():
332 tt.check_pairs(transform_and_reset(ipt.help_end), syntax['end_help'])
331 tt.check_pairs(transform_and_reset(ipt.help_end), syntax['end_help'])
333
332
334 def test_escaped_noesc():
333 def test_escaped_noesc():
335 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_noesc'])
334 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_noesc'])
336
335
337
336
338 def test_escaped_shell():
337 def test_escaped_shell():
339 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_shell'])
338 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_shell'])
340
339
341
340
342 def test_escaped_help():
341 def test_escaped_help():
343 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_help'])
342 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_help'])
344
343
345
344
346 def test_escaped_magic():
345 def test_escaped_magic():
347 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_magic'])
346 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_magic'])
348
347
349
348
350 def test_escaped_quote():
349 def test_escaped_quote():
351 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote'])
350 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote'])
352
351
353
352
354 def test_escaped_quote2():
353 def test_escaped_quote2():
355 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote2'])
354 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote2'])
356
355
357
356
358 def test_escaped_paren():
357 def test_escaped_paren():
359 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_paren'])
358 tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_paren'])
360
359
361
360
362 def test_cellmagic():
361 def test_cellmagic():
363 for example in syntax_ml['cellmagic']:
362 for example in syntax_ml['cellmagic']:
364 transform_checker(example, ipt.cellmagic)
363 transform_checker(example, ipt.cellmagic)
365
364
366 line_example = [(u'%%bar 123', None),
365 line_example = [(u'%%bar 123', None),
367 (u'hello', None),
366 (u'hello', None),
368 (u'' , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
367 (u'' , u_fmt("get_ipython().run_cell_magic({u}'bar', {u}'123', {u}'hello')")),
369 ]
368 ]
370 transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True)
369 transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True)
371
370
372 def test_has_comment():
371 def test_has_comment():
373 tests = [('text', False),
372 tests = [('text', False),
374 ('text #comment', True),
373 ('text #comment', True),
375 ('text #comment\n', True),
374 ('text #comment\n', True),
376 ('#comment', True),
375 ('#comment', True),
377 ('#comment\n', True),
376 ('#comment\n', True),
378 ('a = "#string"', False),
377 ('a = "#string"', False),
379 ('a = "#string" # comment', True),
378 ('a = "#string" # comment', True),
380 ('a #comment not "string"', True),
379 ('a #comment not "string"', True),
381 ]
380 ]
382 tt.check_pairs(ipt.has_comment, tests)
381 tt.check_pairs(ipt.has_comment, tests)
383
382
384 @ipt.TokenInputTransformer.wrap
383 @ipt.TokenInputTransformer.wrap
385 def decistmt(tokens):
384 def decistmt(tokens):
386 """Substitute Decimals for floats in a string of statements.
385 """Substitute Decimals for floats in a string of statements.
387
386
388 Based on an example from the tokenize module docs.
387 Based on an example from the tokenize module docs.
389 """
388 """
390 result = []
389 result = []
391 for toknum, tokval, _, _, _ in tokens:
390 for toknum, tokval, _, _, _ in tokens:
392 if toknum == tokenize.NUMBER and '.' in tokval: # replace NUMBER tokens
391 if toknum == tokenize.NUMBER and '.' in tokval: # replace NUMBER tokens
393 for newtok in [
392 for newtok in [
394 (tokenize.NAME, 'Decimal'),
393 (tokenize.NAME, 'Decimal'),
395 (tokenize.OP, '('),
394 (tokenize.OP, '('),
396 (tokenize.STRING, repr(tokval)),
395 (tokenize.STRING, repr(tokval)),
397 (tokenize.OP, ')')
396 (tokenize.OP, ')')
398 ]:
397 ]:
399 yield newtok
398 yield newtok
400 else:
399 else:
401 yield (toknum, tokval)
400 yield (toknum, tokval)
402
401
403
402
404
403
405 def test_token_input_transformer():
404 def test_token_input_transformer():
406 tests = [(u'1.2', u_fmt(u"Decimal ({u}'1.2')")),
405 tests = [(u'1.2', u_fmt(u"Decimal ({u}'1.2')")),
407 (u'"1.2"', u'"1.2"'),
406 (u'"1.2"', u'"1.2"'),
408 ]
407 ]
409 tt.check_pairs(transform_and_reset(decistmt), tests)
408 tt.check_pairs(transform_and_reset(decistmt), tests)
410 ml_tests = \
409 ml_tests = \
411 [ [(u"a = 1.2; b = '''x", None),
410 [ [(u"a = 1.2; b = '''x", None),
412 (u"y'''", u_fmt(u"a =Decimal ({u}'1.2');b ='''x\ny'''")),
411 (u"y'''", u_fmt(u"a =Decimal ({u}'1.2');b ='''x\ny'''")),
413 ],
412 ],
414 [(u"a = [1.2,", None),
413 [(u"a = [1.2,", None),
415 (u"3]", u_fmt(u"a =[Decimal ({u}'1.2'),\n3 ]")),
414 (u"3]", u_fmt(u"a =[Decimal ({u}'1.2'),\n3 ]")),
416 ],
415 ],
417 [(u"a = '''foo", None), # Test resetting when within a multi-line string
416 [(u"a = '''foo", None), # Test resetting when within a multi-line string
418 (u"bar", None),
417 (u"bar", None),
419 (None, u"a = '''foo\nbar"),
418 (None, u"a = '''foo\nbar"),
420 ],
419 ],
421 ]
420 ]
422 for example in ml_tests:
421 for example in ml_tests:
423 transform_checker(example, decistmt)
422 transform_checker(example, decistmt)
@@ -1,260 +1,254 b''
1 """Tests for the key interactiveshell module, where the main ipython class is defined.
1 """Tests for the key interactiveshell module, where the main ipython class is defined.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Module imports
4 # Module imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6
6
7 # stdlib
8 import os
9 import shutil
10 import tempfile
11
12 # third party
7 # third party
13 import nose.tools as nt
8 import nose.tools as nt
14
9
15 # our own packages
10 # our own packages
16 from IPython.testing.globalipapp import get_ipython
11 from IPython.testing.globalipapp import get_ipython
17 from IPython.utils import py3compat
18
12
19 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
20 # Globals
14 # Globals
21 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
22
16
23 # Get the public instance of IPython
17 # Get the public instance of IPython
24 ip = get_ipython()
18 ip = get_ipython()
25
19
26 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
27 # Test functions
21 # Test functions
28 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
29
23
30 def test_reset():
24 def test_reset():
31 """reset must clear most namespaces."""
25 """reset must clear most namespaces."""
32
26
33 # Check that reset runs without error
27 # Check that reset runs without error
34 ip.reset()
28 ip.reset()
35
29
36 # Once we've reset it (to clear of any junk that might have been there from
30 # Once we've reset it (to clear of any junk that might have been there from
37 # other tests, we can count how many variables are in the user's namespace
31 # other tests, we can count how many variables are in the user's namespace
38 nvars_user_ns = len(ip.user_ns)
32 nvars_user_ns = len(ip.user_ns)
39 nvars_hidden = len(ip.user_ns_hidden)
33 nvars_hidden = len(ip.user_ns_hidden)
40
34
41 # Now add a few variables to user_ns, and check that reset clears them
35 # Now add a few variables to user_ns, and check that reset clears them
42 ip.user_ns['x'] = 1
36 ip.user_ns['x'] = 1
43 ip.user_ns['y'] = 1
37 ip.user_ns['y'] = 1
44 ip.reset()
38 ip.reset()
45
39
46 # Finally, check that all namespaces have only as many variables as we
40 # Finally, check that all namespaces have only as many variables as we
47 # expect to find in them:
41 # expect to find in them:
48 nt.assert_equal(len(ip.user_ns), nvars_user_ns)
42 nt.assert_equal(len(ip.user_ns), nvars_user_ns)
49 nt.assert_equal(len(ip.user_ns_hidden), nvars_hidden)
43 nt.assert_equal(len(ip.user_ns_hidden), nvars_hidden)
50
44
51
45
52 # Tests for reporting of exceptions in various modes, handling of SystemExit,
46 # Tests for reporting of exceptions in various modes, handling of SystemExit,
53 # and %tb functionality. This is really a mix of testing ultraTB and interactiveshell.
47 # and %tb functionality. This is really a mix of testing ultraTB and interactiveshell.
54
48
55 def doctest_tb_plain():
49 def doctest_tb_plain():
56 """
50 """
57 In [18]: xmode plain
51 In [18]: xmode plain
58 Exception reporting mode: Plain
52 Exception reporting mode: Plain
59
53
60 In [19]: run simpleerr.py
54 In [19]: run simpleerr.py
61 Traceback (most recent call last):
55 Traceback (most recent call last):
62 ...line 32, in <module>
56 ...line 32, in <module>
63 bar(mode)
57 bar(mode)
64 ...line 16, in bar
58 ...line 16, in bar
65 div0()
59 div0()
66 ...line 8, in div0
60 ...line 8, in div0
67 x/y
61 x/y
68 ZeroDivisionError: ...
62 ZeroDivisionError: ...
69 """
63 """
70
64
71
65
72 def doctest_tb_context():
66 def doctest_tb_context():
73 """
67 """
74 In [3]: xmode context
68 In [3]: xmode context
75 Exception reporting mode: Context
69 Exception reporting mode: Context
76
70
77 In [4]: run simpleerr.py
71 In [4]: run simpleerr.py
78 ---------------------------------------------------------------------------
72 ---------------------------------------------------------------------------
79 ZeroDivisionError Traceback (most recent call last)
73 ZeroDivisionError Traceback (most recent call last)
80 <BLANKLINE>
74 <BLANKLINE>
81 ... in <module>()
75 ... in <module>()
82 30 mode = 'div'
76 30 mode = 'div'
83 31
77 31
84 ---> 32 bar(mode)
78 ---> 32 bar(mode)
85 <BLANKLINE>
79 <BLANKLINE>
86 ... in bar(mode)
80 ... in bar(mode)
87 14 "bar"
81 14 "bar"
88 15 if mode=='div':
82 15 if mode=='div':
89 ---> 16 div0()
83 ---> 16 div0()
90 17 elif mode=='exit':
84 17 elif mode=='exit':
91 18 try:
85 18 try:
92 <BLANKLINE>
86 <BLANKLINE>
93 ... in div0()
87 ... in div0()
94 6 x = 1
88 6 x = 1
95 7 y = 0
89 7 y = 0
96 ----> 8 x/y
90 ----> 8 x/y
97 9
91 9
98 10 def sysexit(stat, mode):
92 10 def sysexit(stat, mode):
99 <BLANKLINE>
93 <BLANKLINE>
100 ZeroDivisionError: ...
94 ZeroDivisionError: ...
101 """
95 """
102
96
103
97
104 def doctest_tb_verbose():
98 def doctest_tb_verbose():
105 """
99 """
106 In [5]: xmode verbose
100 In [5]: xmode verbose
107 Exception reporting mode: Verbose
101 Exception reporting mode: Verbose
108
102
109 In [6]: run simpleerr.py
103 In [6]: run simpleerr.py
110 ---------------------------------------------------------------------------
104 ---------------------------------------------------------------------------
111 ZeroDivisionError Traceback (most recent call last)
105 ZeroDivisionError Traceback (most recent call last)
112 <BLANKLINE>
106 <BLANKLINE>
113 ... in <module>()
107 ... in <module>()
114 30 mode = 'div'
108 30 mode = 'div'
115 31
109 31
116 ---> 32 bar(mode)
110 ---> 32 bar(mode)
117 global bar = <function bar at ...>
111 global bar = <function bar at ...>
118 global mode = 'div'
112 global mode = 'div'
119 <BLANKLINE>
113 <BLANKLINE>
120 ... in bar(mode='div')
114 ... in bar(mode='div')
121 14 "bar"
115 14 "bar"
122 15 if mode=='div':
116 15 if mode=='div':
123 ---> 16 div0()
117 ---> 16 div0()
124 global div0 = <function div0 at ...>
118 global div0 = <function div0 at ...>
125 17 elif mode=='exit':
119 17 elif mode=='exit':
126 18 try:
120 18 try:
127 <BLANKLINE>
121 <BLANKLINE>
128 ... in div0()
122 ... in div0()
129 6 x = 1
123 6 x = 1
130 7 y = 0
124 7 y = 0
131 ----> 8 x/y
125 ----> 8 x/y
132 x = 1
126 x = 1
133 y = 0
127 y = 0
134 9
128 9
135 10 def sysexit(stat, mode):
129 10 def sysexit(stat, mode):
136 <BLANKLINE>
130 <BLANKLINE>
137 ZeroDivisionError: ...
131 ZeroDivisionError: ...
138 """
132 """
139
133
140 def doctest_tb_sysexit():
134 def doctest_tb_sysexit():
141 """
135 """
142 In [17]: %xmode plain
136 In [17]: %xmode plain
143 Exception reporting mode: Plain
137 Exception reporting mode: Plain
144
138
145 In [18]: %run simpleerr.py exit
139 In [18]: %run simpleerr.py exit
146 An exception has occurred, use %tb to see the full traceback.
140 An exception has occurred, use %tb to see the full traceback.
147 SystemExit: (1, 'Mode = exit')
141 SystemExit: (1, 'Mode = exit')
148
142
149 In [19]: %run simpleerr.py exit 2
143 In [19]: %run simpleerr.py exit 2
150 An exception has occurred, use %tb to see the full traceback.
144 An exception has occurred, use %tb to see the full traceback.
151 SystemExit: (2, 'Mode = exit')
145 SystemExit: (2, 'Mode = exit')
152
146
153 In [20]: %tb
147 In [20]: %tb
154 Traceback (most recent call last):
148 Traceback (most recent call last):
155 File ... in <module>
149 File ... in <module>
156 bar(mode)
150 bar(mode)
157 File ... line 22, in bar
151 File ... line 22, in bar
158 sysexit(stat, mode)
152 sysexit(stat, mode)
159 File ... line 11, in sysexit
153 File ... line 11, in sysexit
160 raise SystemExit(stat, 'Mode = %s' % mode)
154 raise SystemExit(stat, 'Mode = %s' % mode)
161 SystemExit: (2, 'Mode = exit')
155 SystemExit: (2, 'Mode = exit')
162
156
163 In [21]: %xmode context
157 In [21]: %xmode context
164 Exception reporting mode: Context
158 Exception reporting mode: Context
165
159
166 In [22]: %tb
160 In [22]: %tb
167 ---------------------------------------------------------------------------
161 ---------------------------------------------------------------------------
168 SystemExit Traceback (most recent call last)
162 SystemExit Traceback (most recent call last)
169 <BLANKLINE>
163 <BLANKLINE>
170 ...<module>()
164 ...<module>()
171 30 mode = 'div'
165 30 mode = 'div'
172 31
166 31
173 ---> 32 bar(mode)
167 ---> 32 bar(mode)
174 <BLANKLINE>
168 <BLANKLINE>
175 ...bar(mode)
169 ...bar(mode)
176 20 except:
170 20 except:
177 21 stat = 1
171 21 stat = 1
178 ---> 22 sysexit(stat, mode)
172 ---> 22 sysexit(stat, mode)
179 23 else:
173 23 else:
180 24 raise ValueError('Unknown mode')
174 24 raise ValueError('Unknown mode')
181 <BLANKLINE>
175 <BLANKLINE>
182 ...sysexit(stat, mode)
176 ...sysexit(stat, mode)
183 9
177 9
184 10 def sysexit(stat, mode):
178 10 def sysexit(stat, mode):
185 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
179 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
186 12
180 12
187 13 def bar(mode):
181 13 def bar(mode):
188 <BLANKLINE>
182 <BLANKLINE>
189 SystemExit: (2, 'Mode = exit')
183 SystemExit: (2, 'Mode = exit')
190
184
191 In [23]: %xmode verbose
185 In [23]: %xmode verbose
192 Exception reporting mode: Verbose
186 Exception reporting mode: Verbose
193
187
194 In [24]: %tb
188 In [24]: %tb
195 ---------------------------------------------------------------------------
189 ---------------------------------------------------------------------------
196 SystemExit Traceback (most recent call last)
190 SystemExit Traceback (most recent call last)
197 <BLANKLINE>
191 <BLANKLINE>
198 ... in <module>()
192 ... in <module>()
199 30 mode = 'div'
193 30 mode = 'div'
200 31
194 31
201 ---> 32 bar(mode)
195 ---> 32 bar(mode)
202 global bar = <function bar at ...>
196 global bar = <function bar at ...>
203 global mode = 'exit'
197 global mode = 'exit'
204 <BLANKLINE>
198 <BLANKLINE>
205 ... in bar(mode='exit')
199 ... in bar(mode='exit')
206 20 except:
200 20 except:
207 21 stat = 1
201 21 stat = 1
208 ---> 22 sysexit(stat, mode)
202 ---> 22 sysexit(stat, mode)
209 global sysexit = <function sysexit at ...>
203 global sysexit = <function sysexit at ...>
210 stat = 2
204 stat = 2
211 mode = 'exit'
205 mode = 'exit'
212 23 else:
206 23 else:
213 24 raise ValueError('Unknown mode')
207 24 raise ValueError('Unknown mode')
214 <BLANKLINE>
208 <BLANKLINE>
215 ... in sysexit(stat=2, mode='exit')
209 ... in sysexit(stat=2, mode='exit')
216 9
210 9
217 10 def sysexit(stat, mode):
211 10 def sysexit(stat, mode):
218 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
212 ---> 11 raise SystemExit(stat, 'Mode = %s' % mode)
219 global SystemExit = undefined
213 global SystemExit = undefined
220 stat = 2
214 stat = 2
221 mode = 'exit'
215 mode = 'exit'
222 12
216 12
223 13 def bar(mode):
217 13 def bar(mode):
224 <BLANKLINE>
218 <BLANKLINE>
225 SystemExit: (2, 'Mode = exit')
219 SystemExit: (2, 'Mode = exit')
226 """
220 """
227
221
228
222
229 def test_run_cell():
223 def test_run_cell():
230 import textwrap
224 import textwrap
231 ip.run_cell('a = 10\na+=1')
225 ip.run_cell('a = 10\na+=1')
232 ip.run_cell('assert a == 11\nassert 1')
226 ip.run_cell('assert a == 11\nassert 1')
233
227
234 nt.assert_equal(ip.user_ns['a'], 11)
228 nt.assert_equal(ip.user_ns['a'], 11)
235 complex = textwrap.dedent("""
229 complex = textwrap.dedent("""
236 if 1:
230 if 1:
237 print "hello"
231 print "hello"
238 if 1:
232 if 1:
239 print "world"
233 print "world"
240
234
241 if 2:
235 if 2:
242 print "foo"
236 print "foo"
243
237
244 if 3:
238 if 3:
245 print "bar"
239 print "bar"
246
240
247 if 4:
241 if 4:
248 print "bar"
242 print "bar"
249
243
250 """)
244 """)
251 # Simply verifies that this kind of input is run
245 # Simply verifies that this kind of input is run
252 ip.run_cell(complex)
246 ip.run_cell(complex)
253
247
254
248
255 def test_db():
249 def test_db():
256 """Test the internal database used for variable persistence."""
250 """Test the internal database used for variable persistence."""
257 ip.db['__unittest_'] = 12
251 ip.db['__unittest_'] = 12
258 nt.assert_equal(ip.db['__unittest_'], 12)
252 nt.assert_equal(ip.db['__unittest_'], 12)
259 del ip.db['__unittest_']
253 del ip.db['__unittest_']
260 assert '__unittest_' not in ip.db
254 assert '__unittest_' not in ip.db
@@ -1,868 +1,866 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions.
2 """Tests for various magic functions.
3
3
4 Needs to be run by nose (to make ipython session available).
4 Needs to be run by nose (to make ipython session available).
5 """
5 """
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Imports
9 # Imports
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import io
12 import io
13 import os
13 import os
14 import sys
14 import sys
15 from StringIO import StringIO
15 from StringIO import StringIO
16 from unittest import TestCase
16 from unittest import TestCase
17
17
18 try:
18 try:
19 from importlib import invalidate_caches # Required from Python 3.3
19 from importlib import invalidate_caches # Required from Python 3.3
20 except ImportError:
20 except ImportError:
21 def invalidate_caches():
21 def invalidate_caches():
22 pass
22 pass
23
23
24 import nose.tools as nt
24 import nose.tools as nt
25
25
26 from IPython.core import magic
26 from IPython.core import magic
27 from IPython.core.magic import (Magics, magics_class, line_magic,
27 from IPython.core.magic import (Magics, magics_class, line_magic,
28 cell_magic, line_cell_magic,
28 cell_magic, line_cell_magic,
29 register_line_magic, register_cell_magic,
29 register_line_magic, register_cell_magic,
30 register_line_cell_magic)
30 register_line_cell_magic)
31 from IPython.core.magics import execution, script, code
31 from IPython.core.magics import execution, script, code
32 from IPython.nbformat.v3.tests.nbexamples import nb0
32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 from IPython.nbformat import current
33 from IPython.nbformat import current
34 from IPython.testing import decorators as dec
34 from IPython.testing import decorators as dec
35 from IPython.testing import tools as tt
35 from IPython.testing import tools as tt
36 from IPython.utils import py3compat
36 from IPython.utils import py3compat
37 from IPython.utils.io import capture_output
37 from IPython.utils.io import capture_output
38 from IPython.utils.tempdir import TemporaryDirectory
38 from IPython.utils.tempdir import TemporaryDirectory
39 from IPython.utils.process import find_cmd
39 from IPython.utils.process import find_cmd
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Test functions begin
42 # Test functions begin
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45 @magic.magics_class
45 @magic.magics_class
46 class DummyMagics(magic.Magics): pass
46 class DummyMagics(magic.Magics): pass
47
47
48 def test_rehashx():
48 def test_rehashx():
49 # clear up everything
49 # clear up everything
50 _ip = get_ipython()
50 _ip = get_ipython()
51 _ip.alias_manager.alias_table.clear()
51 _ip.alias_manager.alias_table.clear()
52 del _ip.db['syscmdlist']
52 del _ip.db['syscmdlist']
53
53
54 _ip.magic('rehashx')
54 _ip.magic('rehashx')
55 # Practically ALL ipython development systems will have more than 10 aliases
55 # Practically ALL ipython development systems will have more than 10 aliases
56
56
57 nt.assert_true(len(_ip.alias_manager.alias_table) > 10)
57 nt.assert_true(len(_ip.alias_manager.alias_table) > 10)
58 for key, val in _ip.alias_manager.alias_table.iteritems():
58 for key, val in _ip.alias_manager.alias_table.iteritems():
59 # we must strip dots from alias names
59 # we must strip dots from alias names
60 nt.assert_not_in('.', key)
60 nt.assert_not_in('.', key)
61
61
62 # rehashx must fill up syscmdlist
62 # rehashx must fill up syscmdlist
63 scoms = _ip.db['syscmdlist']
63 scoms = _ip.db['syscmdlist']
64 nt.assert_true(len(scoms) > 10)
64 nt.assert_true(len(scoms) > 10)
65
65
66
66
67 def test_magic_parse_options():
67 def test_magic_parse_options():
68 """Test that we don't mangle paths when parsing magic options."""
68 """Test that we don't mangle paths when parsing magic options."""
69 ip = get_ipython()
69 ip = get_ipython()
70 path = 'c:\\x'
70 path = 'c:\\x'
71 m = DummyMagics(ip)
71 m = DummyMagics(ip)
72 opts = m.parse_options('-f %s' % path,'f:')[0]
72 opts = m.parse_options('-f %s' % path,'f:')[0]
73 # argv splitting is os-dependent
73 # argv splitting is os-dependent
74 if os.name == 'posix':
74 if os.name == 'posix':
75 expected = 'c:x'
75 expected = 'c:x'
76 else:
76 else:
77 expected = path
77 expected = path
78 nt.assert_equal(opts['f'], expected)
78 nt.assert_equal(opts['f'], expected)
79
79
80 def test_magic_parse_long_options():
80 def test_magic_parse_long_options():
81 """Magic.parse_options can handle --foo=bar long options"""
81 """Magic.parse_options can handle --foo=bar long options"""
82 ip = get_ipython()
82 ip = get_ipython()
83 m = DummyMagics(ip)
83 m = DummyMagics(ip)
84 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
84 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
85 nt.assert_in('foo', opts)
85 nt.assert_in('foo', opts)
86 nt.assert_in('bar', opts)
86 nt.assert_in('bar', opts)
87 nt.assert_equal(opts['bar'], "bubble")
87 nt.assert_equal(opts['bar'], "bubble")
88
88
89
89
90 @dec.skip_without('sqlite3')
90 @dec.skip_without('sqlite3')
91 def doctest_hist_f():
91 def doctest_hist_f():
92 """Test %hist -f with temporary filename.
92 """Test %hist -f with temporary filename.
93
93
94 In [9]: import tempfile
94 In [9]: import tempfile
95
95
96 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
96 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
97
97
98 In [11]: %hist -nl -f $tfile 3
98 In [11]: %hist -nl -f $tfile 3
99
99
100 In [13]: import os; os.unlink(tfile)
100 In [13]: import os; os.unlink(tfile)
101 """
101 """
102
102
103
103
104 @dec.skip_without('sqlite3')
104 @dec.skip_without('sqlite3')
105 def doctest_hist_r():
105 def doctest_hist_r():
106 """Test %hist -r
106 """Test %hist -r
107
107
108 XXX - This test is not recording the output correctly. For some reason, in
108 XXX - This test is not recording the output correctly. For some reason, in
109 testing mode the raw history isn't getting populated. No idea why.
109 testing mode the raw history isn't getting populated. No idea why.
110 Disabling the output checking for now, though at least we do run it.
110 Disabling the output checking for now, though at least we do run it.
111
111
112 In [1]: 'hist' in _ip.lsmagic()
112 In [1]: 'hist' in _ip.lsmagic()
113 Out[1]: True
113 Out[1]: True
114
114
115 In [2]: x=1
115 In [2]: x=1
116
116
117 In [3]: %hist -rl 2
117 In [3]: %hist -rl 2
118 x=1 # random
118 x=1 # random
119 %hist -r 2
119 %hist -r 2
120 """
120 """
121
121
122
122
123 @dec.skip_without('sqlite3')
123 @dec.skip_without('sqlite3')
124 def doctest_hist_op():
124 def doctest_hist_op():
125 """Test %hist -op
125 """Test %hist -op
126
126
127 In [1]: class b(float):
127 In [1]: class b(float):
128 ...: pass
128 ...: pass
129 ...:
129 ...:
130
130
131 In [2]: class s(object):
131 In [2]: class s(object):
132 ...: def __str__(self):
132 ...: def __str__(self):
133 ...: return 's'
133 ...: return 's'
134 ...:
134 ...:
135
135
136 In [3]:
136 In [3]:
137
137
138 In [4]: class r(b):
138 In [4]: class r(b):
139 ...: def __repr__(self):
139 ...: def __repr__(self):
140 ...: return 'r'
140 ...: return 'r'
141 ...:
141 ...:
142
142
143 In [5]: class sr(s,r): pass
143 In [5]: class sr(s,r): pass
144 ...:
144 ...:
145
145
146 In [6]:
146 In [6]:
147
147
148 In [7]: bb=b()
148 In [7]: bb=b()
149
149
150 In [8]: ss=s()
150 In [8]: ss=s()
151
151
152 In [9]: rr=r()
152 In [9]: rr=r()
153
153
154 In [10]: ssrr=sr()
154 In [10]: ssrr=sr()
155
155
156 In [11]: 4.5
156 In [11]: 4.5
157 Out[11]: 4.5
157 Out[11]: 4.5
158
158
159 In [12]: str(ss)
159 In [12]: str(ss)
160 Out[12]: 's'
160 Out[12]: 's'
161
161
162 In [13]:
162 In [13]:
163
163
164 In [14]: %hist -op
164 In [14]: %hist -op
165 >>> class b:
165 >>> class b:
166 ... pass
166 ... pass
167 ...
167 ...
168 >>> class s(b):
168 >>> class s(b):
169 ... def __str__(self):
169 ... def __str__(self):
170 ... return 's'
170 ... return 's'
171 ...
171 ...
172 >>>
172 >>>
173 >>> class r(b):
173 >>> class r(b):
174 ... def __repr__(self):
174 ... def __repr__(self):
175 ... return 'r'
175 ... return 'r'
176 ...
176 ...
177 >>> class sr(s,r): pass
177 >>> class sr(s,r): pass
178 >>>
178 >>>
179 >>> bb=b()
179 >>> bb=b()
180 >>> ss=s()
180 >>> ss=s()
181 >>> rr=r()
181 >>> rr=r()
182 >>> ssrr=sr()
182 >>> ssrr=sr()
183 >>> 4.5
183 >>> 4.5
184 4.5
184 4.5
185 >>> str(ss)
185 >>> str(ss)
186 's'
186 's'
187 >>>
187 >>>
188 """
188 """
189
189
190
190
191 @dec.skip_without('sqlite3')
191 @dec.skip_without('sqlite3')
192 def test_macro():
192 def test_macro():
193 ip = get_ipython()
193 ip = get_ipython()
194 ip.history_manager.reset() # Clear any existing history.
194 ip.history_manager.reset() # Clear any existing history.
195 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
195 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
196 for i, cmd in enumerate(cmds, start=1):
196 for i, cmd in enumerate(cmds, start=1):
197 ip.history_manager.store_inputs(i, cmd)
197 ip.history_manager.store_inputs(i, cmd)
198 ip.magic("macro test 1-3")
198 ip.magic("macro test 1-3")
199 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
199 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
200
200
201 # List macros
201 # List macros
202 nt.assert_in("test", ip.magic("macro"))
202 nt.assert_in("test", ip.magic("macro"))
203
203
204
204
205 @dec.skip_without('sqlite3')
205 @dec.skip_without('sqlite3')
206 def test_macro_run():
206 def test_macro_run():
207 """Test that we can run a multi-line macro successfully."""
207 """Test that we can run a multi-line macro successfully."""
208 ip = get_ipython()
208 ip = get_ipython()
209 ip.history_manager.reset()
209 ip.history_manager.reset()
210 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
210 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
211 "%macro test 2-3"]
211 "%macro test 2-3"]
212 for cmd in cmds:
212 for cmd in cmds:
213 ip.run_cell(cmd, store_history=True)
213 ip.run_cell(cmd, store_history=True)
214 nt.assert_equal(ip.user_ns["test"].value,
214 nt.assert_equal(ip.user_ns["test"].value,
215 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
215 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
216 with tt.AssertPrints("12"):
216 with tt.AssertPrints("12"):
217 ip.run_cell("test")
217 ip.run_cell("test")
218 with tt.AssertPrints("13"):
218 with tt.AssertPrints("13"):
219 ip.run_cell("test")
219 ip.run_cell("test")
220
220
221
221
222 def test_magic_magic():
222 def test_magic_magic():
223 """Test %magic"""
223 """Test %magic"""
224 ip = get_ipython()
224 ip = get_ipython()
225 with capture_output() as captured:
225 with capture_output() as captured:
226 ip.magic("magic")
226 ip.magic("magic")
227
227
228 stdout = captured.stdout
228 stdout = captured.stdout
229 nt.assert_in('%magic', stdout)
229 nt.assert_in('%magic', stdout)
230 nt.assert_in('IPython', stdout)
230 nt.assert_in('IPython', stdout)
231 nt.assert_in('Available', stdout)
231 nt.assert_in('Available', stdout)
232
232
233
233
234 @dec.skipif_not_numpy
234 @dec.skipif_not_numpy
235 def test_numpy_reset_array_undec():
235 def test_numpy_reset_array_undec():
236 "Test '%reset array' functionality"
236 "Test '%reset array' functionality"
237 _ip.ex('import numpy as np')
237 _ip.ex('import numpy as np')
238 _ip.ex('a = np.empty(2)')
238 _ip.ex('a = np.empty(2)')
239 nt.assert_in('a', _ip.user_ns)
239 nt.assert_in('a', _ip.user_ns)
240 _ip.magic('reset -f array')
240 _ip.magic('reset -f array')
241 nt.assert_not_in('a', _ip.user_ns)
241 nt.assert_not_in('a', _ip.user_ns)
242
242
243 def test_reset_out():
243 def test_reset_out():
244 "Test '%reset out' magic"
244 "Test '%reset out' magic"
245 _ip.run_cell("parrot = 'dead'", store_history=True)
245 _ip.run_cell("parrot = 'dead'", store_history=True)
246 # test '%reset -f out', make an Out prompt
246 # test '%reset -f out', make an Out prompt
247 _ip.run_cell("parrot", store_history=True)
247 _ip.run_cell("parrot", store_history=True)
248 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
248 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
249 _ip.magic('reset -f out')
249 _ip.magic('reset -f out')
250 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
250 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
251 nt.assert_equal(len(_ip.user_ns['Out']), 0)
251 nt.assert_equal(len(_ip.user_ns['Out']), 0)
252
252
253 def test_reset_in():
253 def test_reset_in():
254 "Test '%reset in' magic"
254 "Test '%reset in' magic"
255 # test '%reset -f in'
255 # test '%reset -f in'
256 _ip.run_cell("parrot", store_history=True)
256 _ip.run_cell("parrot", store_history=True)
257 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
257 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
258 _ip.magic('%reset -f in')
258 _ip.magic('%reset -f in')
259 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
259 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
260 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
260 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
261
261
262 def test_reset_dhist():
262 def test_reset_dhist():
263 "Test '%reset dhist' magic"
263 "Test '%reset dhist' magic"
264 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
264 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
265 _ip.magic('cd ' + os.path.dirname(nt.__file__))
265 _ip.magic('cd ' + os.path.dirname(nt.__file__))
266 _ip.magic('cd -')
266 _ip.magic('cd -')
267 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
267 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
268 _ip.magic('reset -f dhist')
268 _ip.magic('reset -f dhist')
269 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
269 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
270 _ip.run_cell("_dh = [d for d in tmp]") #restore
270 _ip.run_cell("_dh = [d for d in tmp]") #restore
271
271
272 def test_reset_in_length():
272 def test_reset_in_length():
273 "Test that '%reset in' preserves In[] length"
273 "Test that '%reset in' preserves In[] length"
274 _ip.run_cell("print 'foo'")
274 _ip.run_cell("print 'foo'")
275 _ip.run_cell("reset -f in")
275 _ip.run_cell("reset -f in")
276 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
276 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
277
277
278 def test_tb_syntaxerror():
278 def test_tb_syntaxerror():
279 """test %tb after a SyntaxError"""
279 """test %tb after a SyntaxError"""
280 ip = get_ipython()
280 ip = get_ipython()
281 ip.run_cell("for")
281 ip.run_cell("for")
282
282
283 # trap and validate stdout
283 # trap and validate stdout
284 save_stdout = sys.stdout
284 save_stdout = sys.stdout
285 try:
285 try:
286 sys.stdout = StringIO()
286 sys.stdout = StringIO()
287 ip.run_cell("%tb")
287 ip.run_cell("%tb")
288 out = sys.stdout.getvalue()
288 out = sys.stdout.getvalue()
289 finally:
289 finally:
290 sys.stdout = save_stdout
290 sys.stdout = save_stdout
291 # trim output, and only check the last line
291 # trim output, and only check the last line
292 last_line = out.rstrip().splitlines()[-1].strip()
292 last_line = out.rstrip().splitlines()[-1].strip()
293 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
293 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
294
294
295
295
296 def test_time():
296 def test_time():
297 ip = get_ipython()
297 ip = get_ipython()
298
298
299 with tt.AssertPrints("Wall time: "):
299 with tt.AssertPrints("Wall time: "):
300 ip.run_cell("%time None")
300 ip.run_cell("%time None")
301
301
302 ip.run_cell("def f(kmjy):\n"
302 ip.run_cell("def f(kmjy):\n"
303 " %time print (2*kmjy)")
303 " %time print (2*kmjy)")
304
304
305 with tt.AssertPrints("Wall time: "):
305 with tt.AssertPrints("Wall time: "):
306 with tt.AssertPrints("hihi", suppress=False):
306 with tt.AssertPrints("hihi", suppress=False):
307 ip.run_cell("f('hi')")
307 ip.run_cell("f('hi')")
308
308
309
309
310 @dec.skip_win32
310 @dec.skip_win32
311 def test_time2():
311 def test_time2():
312 ip = get_ipython()
312 ip = get_ipython()
313
313
314 with tt.AssertPrints("CPU times: user "):
314 with tt.AssertPrints("CPU times: user "):
315 ip.run_cell("%time None")
315 ip.run_cell("%time None")
316
316
317 def test_time3():
317 def test_time3():
318 """Erroneous magic function calls, issue gh-3334"""
318 """Erroneous magic function calls, issue gh-3334"""
319 ip = get_ipython()
319 ip = get_ipython()
320 ip.user_ns.pop('run', None)
320 ip.user_ns.pop('run', None)
321
321
322 with tt.AssertNotPrints("not found", channel='stderr'):
322 with tt.AssertNotPrints("not found", channel='stderr'):
323 ip.run_cell("%%time\n"
323 ip.run_cell("%%time\n"
324 "run = 0\n"
324 "run = 0\n"
325 "run += 1")
325 "run += 1")
326
326
327 def test_doctest_mode():
327 def test_doctest_mode():
328 "Toggle doctest_mode twice, it should be a no-op and run without error"
328 "Toggle doctest_mode twice, it should be a no-op and run without error"
329 _ip.magic('doctest_mode')
329 _ip.magic('doctest_mode')
330 _ip.magic('doctest_mode')
330 _ip.magic('doctest_mode')
331
331
332
332
333 def test_parse_options():
333 def test_parse_options():
334 """Tests for basic options parsing in magics."""
334 """Tests for basic options parsing in magics."""
335 # These are only the most minimal of tests, more should be added later. At
335 # These are only the most minimal of tests, more should be added later. At
336 # the very least we check that basic text/unicode calls work OK.
336 # the very least we check that basic text/unicode calls work OK.
337 m = DummyMagics(_ip)
337 m = DummyMagics(_ip)
338 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
338 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
339 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
339 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
340
340
341
341
342 def test_dirops():
342 def test_dirops():
343 """Test various directory handling operations."""
343 """Test various directory handling operations."""
344 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
344 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
345 curpath = os.getcwdu
345 curpath = os.getcwdu
346 startdir = os.getcwdu()
346 startdir = os.getcwdu()
347 ipdir = os.path.realpath(_ip.ipython_dir)
347 ipdir = os.path.realpath(_ip.ipython_dir)
348 try:
348 try:
349 _ip.magic('cd "%s"' % ipdir)
349 _ip.magic('cd "%s"' % ipdir)
350 nt.assert_equal(curpath(), ipdir)
350 nt.assert_equal(curpath(), ipdir)
351 _ip.magic('cd -')
351 _ip.magic('cd -')
352 nt.assert_equal(curpath(), startdir)
352 nt.assert_equal(curpath(), startdir)
353 _ip.magic('pushd "%s"' % ipdir)
353 _ip.magic('pushd "%s"' % ipdir)
354 nt.assert_equal(curpath(), ipdir)
354 nt.assert_equal(curpath(), ipdir)
355 _ip.magic('popd')
355 _ip.magic('popd')
356 nt.assert_equal(curpath(), startdir)
356 nt.assert_equal(curpath(), startdir)
357 finally:
357 finally:
358 os.chdir(startdir)
358 os.chdir(startdir)
359
359
360
360
361 def test_xmode():
361 def test_xmode():
362 # Calling xmode three times should be a no-op
362 # Calling xmode three times should be a no-op
363 xmode = _ip.InteractiveTB.mode
363 xmode = _ip.InteractiveTB.mode
364 for i in range(3):
364 for i in range(3):
365 _ip.magic("xmode")
365 _ip.magic("xmode")
366 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
366 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
367
367
368 def test_reset_hard():
368 def test_reset_hard():
369 monitor = []
369 monitor = []
370 class A(object):
370 class A(object):
371 def __del__(self):
371 def __del__(self):
372 monitor.append(1)
372 monitor.append(1)
373 def __repr__(self):
373 def __repr__(self):
374 return "<A instance>"
374 return "<A instance>"
375
375
376 _ip.user_ns["a"] = A()
376 _ip.user_ns["a"] = A()
377 _ip.run_cell("a")
377 _ip.run_cell("a")
378
378
379 nt.assert_equal(monitor, [])
379 nt.assert_equal(monitor, [])
380 _ip.magic("reset -f")
380 _ip.magic("reset -f")
381 nt.assert_equal(monitor, [1])
381 nt.assert_equal(monitor, [1])
382
382
383 class TestXdel(tt.TempFileMixin):
383 class TestXdel(tt.TempFileMixin):
384 def test_xdel(self):
384 def test_xdel(self):
385 """Test that references from %run are cleared by xdel."""
385 """Test that references from %run are cleared by xdel."""
386 src = ("class A(object):\n"
386 src = ("class A(object):\n"
387 " monitor = []\n"
387 " monitor = []\n"
388 " def __del__(self):\n"
388 " def __del__(self):\n"
389 " self.monitor.append(1)\n"
389 " self.monitor.append(1)\n"
390 "a = A()\n")
390 "a = A()\n")
391 self.mktmp(src)
391 self.mktmp(src)
392 # %run creates some hidden references...
392 # %run creates some hidden references...
393 _ip.magic("run %s" % self.fname)
393 _ip.magic("run %s" % self.fname)
394 # ... as does the displayhook.
394 # ... as does the displayhook.
395 _ip.run_cell("a")
395 _ip.run_cell("a")
396
396
397 monitor = _ip.user_ns["A"].monitor
397 monitor = _ip.user_ns["A"].monitor
398 nt.assert_equal(monitor, [])
398 nt.assert_equal(monitor, [])
399
399
400 _ip.magic("xdel a")
400 _ip.magic("xdel a")
401
401
402 # Check that a's __del__ method has been called.
402 # Check that a's __del__ method has been called.
403 nt.assert_equal(monitor, [1])
403 nt.assert_equal(monitor, [1])
404
404
405 def doctest_who():
405 def doctest_who():
406 """doctest for %who
406 """doctest for %who
407
407
408 In [1]: %reset -f
408 In [1]: %reset -f
409
409
410 In [2]: alpha = 123
410 In [2]: alpha = 123
411
411
412 In [3]: beta = 'beta'
412 In [3]: beta = 'beta'
413
413
414 In [4]: %who int
414 In [4]: %who int
415 alpha
415 alpha
416
416
417 In [5]: %who str
417 In [5]: %who str
418 beta
418 beta
419
419
420 In [6]: %whos
420 In [6]: %whos
421 Variable Type Data/Info
421 Variable Type Data/Info
422 ----------------------------
422 ----------------------------
423 alpha int 123
423 alpha int 123
424 beta str beta
424 beta str beta
425
425
426 In [7]: %who_ls
426 In [7]: %who_ls
427 Out[7]: ['alpha', 'beta']
427 Out[7]: ['alpha', 'beta']
428 """
428 """
429
429
430 def test_whos():
430 def test_whos():
431 """Check that whos is protected against objects where repr() fails."""
431 """Check that whos is protected against objects where repr() fails."""
432 class A(object):
432 class A(object):
433 def __repr__(self):
433 def __repr__(self):
434 raise Exception()
434 raise Exception()
435 _ip.user_ns['a'] = A()
435 _ip.user_ns['a'] = A()
436 _ip.magic("whos")
436 _ip.magic("whos")
437
437
438 @py3compat.u_format
438 @py3compat.u_format
439 def doctest_precision():
439 def doctest_precision():
440 """doctest for %precision
440 """doctest for %precision
441
441
442 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
442 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
443
443
444 In [2]: %precision 5
444 In [2]: %precision 5
445 Out[2]: {u}'%.5f'
445 Out[2]: {u}'%.5f'
446
446
447 In [3]: f.float_format
447 In [3]: f.float_format
448 Out[3]: {u}'%.5f'
448 Out[3]: {u}'%.5f'
449
449
450 In [4]: %precision %e
450 In [4]: %precision %e
451 Out[4]: {u}'%e'
451 Out[4]: {u}'%e'
452
452
453 In [5]: f(3.1415927)
453 In [5]: f(3.1415927)
454 Out[5]: {u}'3.141593e+00'
454 Out[5]: {u}'3.141593e+00'
455 """
455 """
456
456
457 def test_psearch():
457 def test_psearch():
458 with tt.AssertPrints("dict.fromkeys"):
458 with tt.AssertPrints("dict.fromkeys"):
459 _ip.run_cell("dict.fr*?")
459 _ip.run_cell("dict.fr*?")
460
460
461 def test_timeit_shlex():
461 def test_timeit_shlex():
462 """test shlex issues with timeit (#1109)"""
462 """test shlex issues with timeit (#1109)"""
463 _ip.ex("def f(*a,**kw): pass")
463 _ip.ex("def f(*a,**kw): pass")
464 _ip.magic('timeit -n1 "this is a bug".count(" ")')
464 _ip.magic('timeit -n1 "this is a bug".count(" ")')
465 _ip.magic('timeit -r1 -n1 f(" ", 1)')
465 _ip.magic('timeit -r1 -n1 f(" ", 1)')
466 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
466 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
467 _ip.magic('timeit -r1 -n1 ("a " + "b")')
467 _ip.magic('timeit -r1 -n1 ("a " + "b")')
468 _ip.magic('timeit -r1 -n1 f("a " + "b")')
468 _ip.magic('timeit -r1 -n1 f("a " + "b")')
469 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
469 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
470
470
471
471
472 def test_timeit_arguments():
472 def test_timeit_arguments():
473 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
473 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
474 _ip.magic("timeit ('#')")
474 _ip.magic("timeit ('#')")
475
475
476
476
477 def test_timeit_special_syntax():
477 def test_timeit_special_syntax():
478 "Test %%timeit with IPython special syntax"
478 "Test %%timeit with IPython special syntax"
479 from IPython.core.magic import register_line_magic
480
481 @register_line_magic
479 @register_line_magic
482 def lmagic(line):
480 def lmagic(line):
483 ip = get_ipython()
481 ip = get_ipython()
484 ip.user_ns['lmagic_out'] = line
482 ip.user_ns['lmagic_out'] = line
485
483
486 # line mode test
484 # line mode test
487 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
485 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
488 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
486 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
489 # cell mode test
487 # cell mode test
490 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
488 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
491 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
489 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
492
490
493
491
494 @dec.skipif(execution.profile is None)
492 @dec.skipif(execution.profile is None)
495 def test_prun_quotes():
493 def test_prun_quotes():
496 "Test that prun does not clobber string escapes (GH #1302)"
494 "Test that prun does not clobber string escapes (GH #1302)"
497 _ip.magic(r"prun -q x = '\t'")
495 _ip.magic(r"prun -q x = '\t'")
498 nt.assert_equal(_ip.user_ns['x'], '\t')
496 nt.assert_equal(_ip.user_ns['x'], '\t')
499
497
500 def test_extension():
498 def test_extension():
501 tmpdir = TemporaryDirectory()
499 tmpdir = TemporaryDirectory()
502 orig_ipython_dir = _ip.ipython_dir
500 orig_ipython_dir = _ip.ipython_dir
503 try:
501 try:
504 _ip.ipython_dir = tmpdir.name
502 _ip.ipython_dir = tmpdir.name
505 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
503 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
506 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
504 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
507 _ip.magic("install_ext %s" % url)
505 _ip.magic("install_ext %s" % url)
508 _ip.user_ns.pop('arq', None)
506 _ip.user_ns.pop('arq', None)
509 invalidate_caches() # Clear import caches
507 invalidate_caches() # Clear import caches
510 _ip.magic("load_ext daft_extension")
508 _ip.magic("load_ext daft_extension")
511 nt.assert_equal(_ip.user_ns['arq'], 185)
509 nt.assert_equal(_ip.user_ns['arq'], 185)
512 _ip.magic("unload_ext daft_extension")
510 _ip.magic("unload_ext daft_extension")
513 assert 'arq' not in _ip.user_ns
511 assert 'arq' not in _ip.user_ns
514 finally:
512 finally:
515 _ip.ipython_dir = orig_ipython_dir
513 _ip.ipython_dir = orig_ipython_dir
516 tmpdir.cleanup()
514 tmpdir.cleanup()
517
515
518 def test_notebook_export_json():
516 def test_notebook_export_json():
519 with TemporaryDirectory() as td:
517 with TemporaryDirectory() as td:
520 outfile = os.path.join(td, "nb.ipynb")
518 outfile = os.path.join(td, "nb.ipynb")
521 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
519 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
522 _ip.magic("notebook -e %s" % outfile)
520 _ip.magic("notebook -e %s" % outfile)
523
521
524 def test_notebook_export_py():
522 def test_notebook_export_py():
525 with TemporaryDirectory() as td:
523 with TemporaryDirectory() as td:
526 outfile = os.path.join(td, "nb.py")
524 outfile = os.path.join(td, "nb.py")
527 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
525 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
528 _ip.magic("notebook -e %s" % outfile)
526 _ip.magic("notebook -e %s" % outfile)
529
527
530 def test_notebook_reformat_py():
528 def test_notebook_reformat_py():
531 with TemporaryDirectory() as td:
529 with TemporaryDirectory() as td:
532 infile = os.path.join(td, "nb.ipynb")
530 infile = os.path.join(td, "nb.ipynb")
533 with io.open(infile, 'w', encoding='utf-8') as f:
531 with io.open(infile, 'w', encoding='utf-8') as f:
534 current.write(nb0, f, 'json')
532 current.write(nb0, f, 'json')
535
533
536 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
534 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
537 _ip.magic("notebook -f py %s" % infile)
535 _ip.magic("notebook -f py %s" % infile)
538
536
539 def test_notebook_reformat_json():
537 def test_notebook_reformat_json():
540 with TemporaryDirectory() as td:
538 with TemporaryDirectory() as td:
541 infile = os.path.join(td, "nb.py")
539 infile = os.path.join(td, "nb.py")
542 with io.open(infile, 'w', encoding='utf-8') as f:
540 with io.open(infile, 'w', encoding='utf-8') as f:
543 current.write(nb0, f, 'py')
541 current.write(nb0, f, 'py')
544
542
545 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
543 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
546 _ip.magic("notebook -f ipynb %s" % infile)
544 _ip.magic("notebook -f ipynb %s" % infile)
547 _ip.magic("notebook -f json %s" % infile)
545 _ip.magic("notebook -f json %s" % infile)
548
546
549 def test_env():
547 def test_env():
550 env = _ip.magic("env")
548 env = _ip.magic("env")
551 assert isinstance(env, dict), type(env)
549 assert isinstance(env, dict), type(env)
552
550
553
551
554 class CellMagicTestCase(TestCase):
552 class CellMagicTestCase(TestCase):
555
553
556 def check_ident(self, magic):
554 def check_ident(self, magic):
557 # Manually called, we get the result
555 # Manually called, we get the result
558 out = _ip.run_cell_magic(magic, 'a', 'b')
556 out = _ip.run_cell_magic(magic, 'a', 'b')
559 nt.assert_equal(out, ('a','b'))
557 nt.assert_equal(out, ('a','b'))
560 # Via run_cell, it goes into the user's namespace via displayhook
558 # Via run_cell, it goes into the user's namespace via displayhook
561 _ip.run_cell('%%' + magic +' c\nd')
559 _ip.run_cell('%%' + magic +' c\nd')
562 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
560 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
563
561
564 def test_cell_magic_func_deco(self):
562 def test_cell_magic_func_deco(self):
565 "Cell magic using simple decorator"
563 "Cell magic using simple decorator"
566 @register_cell_magic
564 @register_cell_magic
567 def cellm(line, cell):
565 def cellm(line, cell):
568 return line, cell
566 return line, cell
569
567
570 self.check_ident('cellm')
568 self.check_ident('cellm')
571
569
572 def test_cell_magic_reg(self):
570 def test_cell_magic_reg(self):
573 "Cell magic manually registered"
571 "Cell magic manually registered"
574 def cellm(line, cell):
572 def cellm(line, cell):
575 return line, cell
573 return line, cell
576
574
577 _ip.register_magic_function(cellm, 'cell', 'cellm2')
575 _ip.register_magic_function(cellm, 'cell', 'cellm2')
578 self.check_ident('cellm2')
576 self.check_ident('cellm2')
579
577
580 def test_cell_magic_class(self):
578 def test_cell_magic_class(self):
581 "Cell magics declared via a class"
579 "Cell magics declared via a class"
582 @magics_class
580 @magics_class
583 class MyMagics(Magics):
581 class MyMagics(Magics):
584
582
585 @cell_magic
583 @cell_magic
586 def cellm3(self, line, cell):
584 def cellm3(self, line, cell):
587 return line, cell
585 return line, cell
588
586
589 _ip.register_magics(MyMagics)
587 _ip.register_magics(MyMagics)
590 self.check_ident('cellm3')
588 self.check_ident('cellm3')
591
589
592 def test_cell_magic_class2(self):
590 def test_cell_magic_class2(self):
593 "Cell magics declared via a class, #2"
591 "Cell magics declared via a class, #2"
594 @magics_class
592 @magics_class
595 class MyMagics2(Magics):
593 class MyMagics2(Magics):
596
594
597 @cell_magic('cellm4')
595 @cell_magic('cellm4')
598 def cellm33(self, line, cell):
596 def cellm33(self, line, cell):
599 return line, cell
597 return line, cell
600
598
601 _ip.register_magics(MyMagics2)
599 _ip.register_magics(MyMagics2)
602 self.check_ident('cellm4')
600 self.check_ident('cellm4')
603 # Check that nothing is registered as 'cellm33'
601 # Check that nothing is registered as 'cellm33'
604 c33 = _ip.find_cell_magic('cellm33')
602 c33 = _ip.find_cell_magic('cellm33')
605 nt.assert_equal(c33, None)
603 nt.assert_equal(c33, None)
606
604
607 def test_file():
605 def test_file():
608 """Basic %%file"""
606 """Basic %%file"""
609 ip = get_ipython()
607 ip = get_ipython()
610 with TemporaryDirectory() as td:
608 with TemporaryDirectory() as td:
611 fname = os.path.join(td, 'file1')
609 fname = os.path.join(td, 'file1')
612 ip.run_cell_magic("file", fname, u'\n'.join([
610 ip.run_cell_magic("file", fname, u'\n'.join([
613 'line1',
611 'line1',
614 'line2',
612 'line2',
615 ]))
613 ]))
616 with open(fname) as f:
614 with open(fname) as f:
617 s = f.read()
615 s = f.read()
618 nt.assert_in('line1\n', s)
616 nt.assert_in('line1\n', s)
619 nt.assert_in('line2', s)
617 nt.assert_in('line2', s)
620
618
621 def test_file_var_expand():
619 def test_file_var_expand():
622 """%%file $filename"""
620 """%%file $filename"""
623 ip = get_ipython()
621 ip = get_ipython()
624 with TemporaryDirectory() as td:
622 with TemporaryDirectory() as td:
625 fname = os.path.join(td, 'file1')
623 fname = os.path.join(td, 'file1')
626 ip.user_ns['filename'] = fname
624 ip.user_ns['filename'] = fname
627 ip.run_cell_magic("file", '$filename', u'\n'.join([
625 ip.run_cell_magic("file", '$filename', u'\n'.join([
628 'line1',
626 'line1',
629 'line2',
627 'line2',
630 ]))
628 ]))
631 with open(fname) as f:
629 with open(fname) as f:
632 s = f.read()
630 s = f.read()
633 nt.assert_in('line1\n', s)
631 nt.assert_in('line1\n', s)
634 nt.assert_in('line2', s)
632 nt.assert_in('line2', s)
635
633
636 def test_file_unicode():
634 def test_file_unicode():
637 """%%file with unicode cell"""
635 """%%file with unicode cell"""
638 ip = get_ipython()
636 ip = get_ipython()
639 with TemporaryDirectory() as td:
637 with TemporaryDirectory() as td:
640 fname = os.path.join(td, 'file1')
638 fname = os.path.join(td, 'file1')
641 ip.run_cell_magic("file", fname, u'\n'.join([
639 ip.run_cell_magic("file", fname, u'\n'.join([
642 u'liné1',
640 u'liné1',
643 u'liné2',
641 u'liné2',
644 ]))
642 ]))
645 with io.open(fname, encoding='utf-8') as f:
643 with io.open(fname, encoding='utf-8') as f:
646 s = f.read()
644 s = f.read()
647 nt.assert_in(u'liné1\n', s)
645 nt.assert_in(u'liné1\n', s)
648 nt.assert_in(u'liné2', s)
646 nt.assert_in(u'liné2', s)
649
647
650 def test_file_amend():
648 def test_file_amend():
651 """%%file -a amends files"""
649 """%%file -a amends files"""
652 ip = get_ipython()
650 ip = get_ipython()
653 with TemporaryDirectory() as td:
651 with TemporaryDirectory() as td:
654 fname = os.path.join(td, 'file2')
652 fname = os.path.join(td, 'file2')
655 ip.run_cell_magic("file", fname, u'\n'.join([
653 ip.run_cell_magic("file", fname, u'\n'.join([
656 'line1',
654 'line1',
657 'line2',
655 'line2',
658 ]))
656 ]))
659 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
657 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
660 'line3',
658 'line3',
661 'line4',
659 'line4',
662 ]))
660 ]))
663 with open(fname) as f:
661 with open(fname) as f:
664 s = f.read()
662 s = f.read()
665 nt.assert_in('line1\n', s)
663 nt.assert_in('line1\n', s)
666 nt.assert_in('line3\n', s)
664 nt.assert_in('line3\n', s)
667
665
668
666
669 def test_script_config():
667 def test_script_config():
670 ip = get_ipython()
668 ip = get_ipython()
671 ip.config.ScriptMagics.script_magics = ['whoda']
669 ip.config.ScriptMagics.script_magics = ['whoda']
672 sm = script.ScriptMagics(shell=ip)
670 sm = script.ScriptMagics(shell=ip)
673 nt.assert_in('whoda', sm.magics['cell'])
671 nt.assert_in('whoda', sm.magics['cell'])
674
672
675 @dec.skip_win32
673 @dec.skip_win32
676 def test_script_out():
674 def test_script_out():
677 ip = get_ipython()
675 ip = get_ipython()
678 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
676 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
679 nt.assert_equal(ip.user_ns['output'], 'hi\n')
677 nt.assert_equal(ip.user_ns['output'], 'hi\n')
680
678
681 @dec.skip_win32
679 @dec.skip_win32
682 def test_script_err():
680 def test_script_err():
683 ip = get_ipython()
681 ip = get_ipython()
684 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
682 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
685 nt.assert_equal(ip.user_ns['error'], 'hello\n')
683 nt.assert_equal(ip.user_ns['error'], 'hello\n')
686
684
687 @dec.skip_win32
685 @dec.skip_win32
688 def test_script_out_err():
686 def test_script_out_err():
689 ip = get_ipython()
687 ip = get_ipython()
690 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
688 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
691 nt.assert_equal(ip.user_ns['output'], 'hi\n')
689 nt.assert_equal(ip.user_ns['output'], 'hi\n')
692 nt.assert_equal(ip.user_ns['error'], 'hello\n')
690 nt.assert_equal(ip.user_ns['error'], 'hello\n')
693
691
694 @dec.skip_win32
692 @dec.skip_win32
695 def test_script_bg_out():
693 def test_script_bg_out():
696 ip = get_ipython()
694 ip = get_ipython()
697 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
695 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
698 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
696 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
699
697
700 @dec.skip_win32
698 @dec.skip_win32
701 def test_script_bg_err():
699 def test_script_bg_err():
702 ip = get_ipython()
700 ip = get_ipython()
703 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
701 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
704 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
702 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
705
703
706 @dec.skip_win32
704 @dec.skip_win32
707 def test_script_bg_out_err():
705 def test_script_bg_out_err():
708 ip = get_ipython()
706 ip = get_ipython()
709 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
707 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
710 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
708 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
711 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
709 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
712
710
713 def test_script_defaults():
711 def test_script_defaults():
714 ip = get_ipython()
712 ip = get_ipython()
715 for cmd in ['sh', 'bash', 'perl', 'ruby']:
713 for cmd in ['sh', 'bash', 'perl', 'ruby']:
716 try:
714 try:
717 find_cmd(cmd)
715 find_cmd(cmd)
718 except Exception:
716 except Exception:
719 pass
717 pass
720 else:
718 else:
721 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
719 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
722
720
723
721
724 @magics_class
722 @magics_class
725 class FooFoo(Magics):
723 class FooFoo(Magics):
726 """class with both %foo and %%foo magics"""
724 """class with both %foo and %%foo magics"""
727 @line_magic('foo')
725 @line_magic('foo')
728 def line_foo(self, line):
726 def line_foo(self, line):
729 "I am line foo"
727 "I am line foo"
730 pass
728 pass
731
729
732 @cell_magic("foo")
730 @cell_magic("foo")
733 def cell_foo(self, line, cell):
731 def cell_foo(self, line, cell):
734 "I am cell foo, not line foo"
732 "I am cell foo, not line foo"
735 pass
733 pass
736
734
737 def test_line_cell_info():
735 def test_line_cell_info():
738 """%%foo and %foo magics are distinguishable to inspect"""
736 """%%foo and %foo magics are distinguishable to inspect"""
739 ip = get_ipython()
737 ip = get_ipython()
740 ip.magics_manager.register(FooFoo)
738 ip.magics_manager.register(FooFoo)
741 oinfo = ip.object_inspect('foo')
739 oinfo = ip.object_inspect('foo')
742 nt.assert_true(oinfo['found'])
740 nt.assert_true(oinfo['found'])
743 nt.assert_true(oinfo['ismagic'])
741 nt.assert_true(oinfo['ismagic'])
744
742
745 oinfo = ip.object_inspect('%%foo')
743 oinfo = ip.object_inspect('%%foo')
746 nt.assert_true(oinfo['found'])
744 nt.assert_true(oinfo['found'])
747 nt.assert_true(oinfo['ismagic'])
745 nt.assert_true(oinfo['ismagic'])
748 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
746 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
749
747
750 oinfo = ip.object_inspect('%foo')
748 oinfo = ip.object_inspect('%foo')
751 nt.assert_true(oinfo['found'])
749 nt.assert_true(oinfo['found'])
752 nt.assert_true(oinfo['ismagic'])
750 nt.assert_true(oinfo['ismagic'])
753 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
751 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
754
752
755 def test_multiple_magics():
753 def test_multiple_magics():
756 ip = get_ipython()
754 ip = get_ipython()
757 foo1 = FooFoo(ip)
755 foo1 = FooFoo(ip)
758 foo2 = FooFoo(ip)
756 foo2 = FooFoo(ip)
759 mm = ip.magics_manager
757 mm = ip.magics_manager
760 mm.register(foo1)
758 mm.register(foo1)
761 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
759 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
762 mm.register(foo2)
760 mm.register(foo2)
763 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
761 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
764
762
765 def test_alias_magic():
763 def test_alias_magic():
766 """Test %alias_magic."""
764 """Test %alias_magic."""
767 ip = get_ipython()
765 ip = get_ipython()
768 mm = ip.magics_manager
766 mm = ip.magics_manager
769
767
770 # Basic operation: both cell and line magics are created, if possible.
768 # Basic operation: both cell and line magics are created, if possible.
771 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
769 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
772 nt.assert_in('timeit_alias', mm.magics['line'])
770 nt.assert_in('timeit_alias', mm.magics['line'])
773 nt.assert_in('timeit_alias', mm.magics['cell'])
771 nt.assert_in('timeit_alias', mm.magics['cell'])
774
772
775 # --cell is specified, line magic not created.
773 # --cell is specified, line magic not created.
776 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
774 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
777 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
775 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
778 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
776 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
779
777
780 # Test that line alias is created successfully.
778 # Test that line alias is created successfully.
781 ip.run_line_magic('alias_magic', '--line env_alias env')
779 ip.run_line_magic('alias_magic', '--line env_alias env')
782 nt.assert_equal(ip.run_line_magic('env', ''),
780 nt.assert_equal(ip.run_line_magic('env', ''),
783 ip.run_line_magic('env_alias', ''))
781 ip.run_line_magic('env_alias', ''))
784
782
785 def test_save():
783 def test_save():
786 """Test %save."""
784 """Test %save."""
787 ip = get_ipython()
785 ip = get_ipython()
788 ip.history_manager.reset() # Clear any existing history.
786 ip.history_manager.reset() # Clear any existing history.
789 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
787 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
790 for i, cmd in enumerate(cmds, start=1):
788 for i, cmd in enumerate(cmds, start=1):
791 ip.history_manager.store_inputs(i, cmd)
789 ip.history_manager.store_inputs(i, cmd)
792 with TemporaryDirectory() as tmpdir:
790 with TemporaryDirectory() as tmpdir:
793 file = os.path.join(tmpdir, "testsave.py")
791 file = os.path.join(tmpdir, "testsave.py")
794 ip.run_line_magic("save", "%s 1-10" % file)
792 ip.run_line_magic("save", "%s 1-10" % file)
795 with open(file) as f:
793 with open(file) as f:
796 content = f.read()
794 content = f.read()
797 nt.assert_equal(content.count(cmds[0]), 1)
795 nt.assert_equal(content.count(cmds[0]), 1)
798 nt.assert_in('coding: utf-8', content)
796 nt.assert_in('coding: utf-8', content)
799 ip.run_line_magic("save", "-a %s 1-10" % file)
797 ip.run_line_magic("save", "-a %s 1-10" % file)
800 with open(file) as f:
798 with open(file) as f:
801 content = f.read()
799 content = f.read()
802 nt.assert_equal(content.count(cmds[0]), 2)
800 nt.assert_equal(content.count(cmds[0]), 2)
803 nt.assert_in('coding: utf-8', content)
801 nt.assert_in('coding: utf-8', content)
804
802
805
803
806 def test_store():
804 def test_store():
807 """Test %store."""
805 """Test %store."""
808 ip = get_ipython()
806 ip = get_ipython()
809 ip.run_line_magic('load_ext', 'storemagic')
807 ip.run_line_magic('load_ext', 'storemagic')
810
808
811 # make sure the storage is empty
809 # make sure the storage is empty
812 ip.run_line_magic('store', '-z')
810 ip.run_line_magic('store', '-z')
813 ip.user_ns['var'] = 42
811 ip.user_ns['var'] = 42
814 ip.run_line_magic('store', 'var')
812 ip.run_line_magic('store', 'var')
815 ip.user_ns['var'] = 39
813 ip.user_ns['var'] = 39
816 ip.run_line_magic('store', '-r')
814 ip.run_line_magic('store', '-r')
817 nt.assert_equal(ip.user_ns['var'], 42)
815 nt.assert_equal(ip.user_ns['var'], 42)
818
816
819 ip.run_line_magic('store', '-d var')
817 ip.run_line_magic('store', '-d var')
820 ip.user_ns['var'] = 39
818 ip.user_ns['var'] = 39
821 ip.run_line_magic('store' , '-r')
819 ip.run_line_magic('store' , '-r')
822 nt.assert_equal(ip.user_ns['var'], 39)
820 nt.assert_equal(ip.user_ns['var'], 39)
823
821
824
822
825 def _run_edit_test(arg_s, exp_filename=None,
823 def _run_edit_test(arg_s, exp_filename=None,
826 exp_lineno=-1,
824 exp_lineno=-1,
827 exp_contents=None,
825 exp_contents=None,
828 exp_is_temp=None):
826 exp_is_temp=None):
829 ip = get_ipython()
827 ip = get_ipython()
830 M = code.CodeMagics(ip)
828 M = code.CodeMagics(ip)
831 last_call = ['','']
829 last_call = ['','']
832 opts,args = M.parse_options(arg_s,'prxn:')
830 opts,args = M.parse_options(arg_s,'prxn:')
833 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
831 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
834
832
835 if exp_filename is not None:
833 if exp_filename is not None:
836 nt.assert_equal(exp_filename, filename)
834 nt.assert_equal(exp_filename, filename)
837 if exp_contents is not None:
835 if exp_contents is not None:
838 with io.open(filename, 'r') as f:
836 with io.open(filename, 'r') as f:
839 contents = f.read()
837 contents = f.read()
840 nt.assert_equal(exp_contents, contents)
838 nt.assert_equal(exp_contents, contents)
841 if exp_lineno != -1:
839 if exp_lineno != -1:
842 nt.assert_equal(exp_lineno, lineno)
840 nt.assert_equal(exp_lineno, lineno)
843 if exp_is_temp is not None:
841 if exp_is_temp is not None:
844 nt.assert_equal(exp_is_temp, is_temp)
842 nt.assert_equal(exp_is_temp, is_temp)
845
843
846
844
847 def test_edit_interactive():
845 def test_edit_interactive():
848 """%edit on interactively defined objects"""
846 """%edit on interactively defined objects"""
849 ip = get_ipython()
847 ip = get_ipython()
850 n = ip.execution_count
848 n = ip.execution_count
851 ip.run_cell(u"def foo(): return 1", store_history=True)
849 ip.run_cell(u"def foo(): return 1", store_history=True)
852
850
853 try:
851 try:
854 _run_edit_test("foo")
852 _run_edit_test("foo")
855 except code.InteractivelyDefined as e:
853 except code.InteractivelyDefined as e:
856 nt.assert_equal(e.index, n)
854 nt.assert_equal(e.index, n)
857 else:
855 else:
858 raise AssertionError("Should have raised InteractivelyDefined")
856 raise AssertionError("Should have raised InteractivelyDefined")
859
857
860
858
861 def test_edit_cell():
859 def test_edit_cell():
862 """%edit [cell id]"""
860 """%edit [cell id]"""
863 ip = get_ipython()
861 ip = get_ipython()
864
862
865 ip.run_cell(u"def foo(): return 1", store_history=True)
863 ip.run_cell(u"def foo(): return 1", store_history=True)
866
864
867 # test
865 # test
868 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
866 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
@@ -1,305 +1,305 b''
1 """Tests for the object inspection functionality.
1 """Tests for the object inspection functionality.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2010-2011 The IPython Development Team.
4 # Copyright (C) 2010-2011 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the BSD License.
6 # Distributed under the terms of the 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 from __future__ import print_function
14 from __future__ import print_function
15
15
16 # Stdlib imports
16 # Stdlib imports
17 import os
17 import os
18 import re
18 import re
19
19
20 # Third-party imports
20 # Third-party imports
21 import nose.tools as nt
21 import nose.tools as nt
22
22
23 # Our own imports
23 # Our own imports
24 from .. import oinspect
24 from .. import oinspect
25 from IPython.core.magic import (Magics, magics_class, line_magic,
25 from IPython.core.magic import (Magics, magics_class, line_magic,
26 cell_magic, line_cell_magic,
26 cell_magic, line_cell_magic,
27 register_line_magic, register_cell_magic,
27 register_line_magic, register_cell_magic,
28 register_line_cell_magic)
28 register_line_cell_magic)
29 from IPython.external.decorator import decorator
29 from IPython.external.decorator import decorator
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31
31
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Globals and constants
34 # Globals and constants
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37 inspector = oinspect.Inspector()
37 inspector = oinspect.Inspector()
38 ip = get_ipython()
38 ip = get_ipython()
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Local utilities
41 # Local utilities
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 # WARNING: since this test checks the line number where a function is
44 # WARNING: since this test checks the line number where a function is
45 # defined, if any code is inserted above, the following line will need to be
45 # defined, if any code is inserted above, the following line will need to be
46 # updated. Do NOT insert any whitespace between the next line and the function
46 # updated. Do NOT insert any whitespace between the next line and the function
47 # definition below.
47 # definition below.
48 THIS_LINE_NUMBER = 48 # Put here the actual number of this line
48 THIS_LINE_NUMBER = 48 # Put here the actual number of this line
49 def test_find_source_lines():
49 def test_find_source_lines():
50 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
50 nt.assert_equal(oinspect.find_source_lines(test_find_source_lines),
51 THIS_LINE_NUMBER+1)
51 THIS_LINE_NUMBER+1)
52
52
53
53
54 # A couple of utilities to ensure these tests work the same from a source or a
54 # A couple of utilities to ensure these tests work the same from a source or a
55 # binary install
55 # binary install
56 def pyfile(fname):
56 def pyfile(fname):
57 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
57 return os.path.normcase(re.sub('.py[co]$', '.py', fname))
58
58
59
59
60 def match_pyfiles(f1, f2):
60 def match_pyfiles(f1, f2):
61 nt.assert_equal(pyfile(f1), pyfile(f2))
61 nt.assert_equal(pyfile(f1), pyfile(f2))
62
62
63
63
64 def test_find_file():
64 def test_find_file():
65 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
65 match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
66
66
67
67
68 def test_find_file_decorated1():
68 def test_find_file_decorated1():
69
69
70 @decorator
70 @decorator
71 def noop1(f):
71 def noop1(f):
72 def wrapper():
72 def wrapper():
73 return f(*a, **kw)
73 return f(*a, **kw)
74 return wrapper
74 return wrapper
75
75
76 @noop1
76 @noop1
77 def f(x):
77 def f(x):
78 "My docstring"
78 "My docstring"
79
79
80 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
80 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
81 nt.assert_equal(f.__doc__, "My docstring")
81 nt.assert_equal(f.__doc__, "My docstring")
82
82
83
83
84 def test_find_file_decorated2():
84 def test_find_file_decorated2():
85
85
86 @decorator
86 @decorator
87 def noop2(f, *a, **kw):
87 def noop2(f, *a, **kw):
88 return f(*a, **kw)
88 return f(*a, **kw)
89
89
90 @noop2
90 @noop2
91 def f(x):
91 def f(x):
92 "My docstring 2"
92 "My docstring 2"
93
93
94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
94 match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
95 nt.assert_equal(f.__doc__, "My docstring 2")
95 nt.assert_equal(f.__doc__, "My docstring 2")
96
96
97
97
98 def test_find_file_magic():
98 def test_find_file_magic():
99 run = ip.find_line_magic('run')
99 run = ip.find_line_magic('run')
100 nt.assert_not_equal(oinspect.find_file(run), None)
100 nt.assert_not_equal(oinspect.find_file(run), None)
101
101
102
102
103 # A few generic objects we can then inspect in the tests below
103 # A few generic objects we can then inspect in the tests below
104
104
105 class Call(object):
105 class Call(object):
106 """This is the class docstring."""
106 """This is the class docstring."""
107
107
108 def __init__(self, x, y=1):
108 def __init__(self, x, y=1):
109 """This is the constructor docstring."""
109 """This is the constructor docstring."""
110
110
111 def __call__(self, *a, **kw):
111 def __call__(self, *a, **kw):
112 """This is the call docstring."""
112 """This is the call docstring."""
113
113
114 def method(self, x, z=2):
114 def method(self, x, z=2):
115 """Some method's docstring"""
115 """Some method's docstring"""
116
116
117
117
118 class OldStyle:
118 class OldStyle:
119 """An old-style class for testing."""
119 """An old-style class for testing."""
120 pass
120 pass
121
121
122
122
123 def f(x, y=2, *a, **kw):
123 def f(x, y=2, *a, **kw):
124 """A simple function."""
124 """A simple function."""
125
125
126
126
127 def g(y, z=3, *a, **kw):
127 def g(y, z=3, *a, **kw):
128 pass # no docstring
128 pass # no docstring
129
129
130
130
131 @register_line_magic
131 @register_line_magic
132 def lmagic(line):
132 def lmagic(line):
133 "A line magic"
133 "A line magic"
134
134
135
135
136 @register_cell_magic
136 @register_cell_magic
137 def cmagic(line, cell):
137 def cmagic(line, cell):
138 "A cell magic"
138 "A cell magic"
139
139
140
140
141 @register_line_cell_magic
141 @register_line_cell_magic
142 def lcmagic(line, cell=None):
142 def lcmagic(line, cell=None):
143 "A line/cell magic"
143 "A line/cell magic"
144
144
145
145
146 @magics_class
146 @magics_class
147 class SimpleMagics(Magics):
147 class SimpleMagics(Magics):
148 @line_magic
148 @line_magic
149 def Clmagic(self, cline):
149 def Clmagic(self, cline):
150 "A class-based line magic"
150 "A class-based line magic"
151
151
152 @cell_magic
152 @cell_magic
153 def Ccmagic(self, cline, ccell):
153 def Ccmagic(self, cline, ccell):
154 "A class-based cell magic"
154 "A class-based cell magic"
155
155
156 @line_cell_magic
156 @line_cell_magic
157 def Clcmagic(self, cline, ccell=None):
157 def Clcmagic(self, cline, ccell=None):
158 "A class-based line/cell magic"
158 "A class-based line/cell magic"
159
159
160
160
161 class Awkward(object):
161 class Awkward(object):
162 def __getattr__(self, name):
162 def __getattr__(self, name):
163 raise Exception(name)
163 raise Exception(name)
164
164
165
165
166 def check_calltip(obj, name, call, docstring):
166 def check_calltip(obj, name, call, docstring):
167 """Generic check pattern all calltip tests will use"""
167 """Generic check pattern all calltip tests will use"""
168 info = inspector.info(obj, name)
168 info = inspector.info(obj, name)
169 call_line, ds = oinspect.call_tip(info)
169 call_line, ds = oinspect.call_tip(info)
170 nt.assert_equal(call_line, call)
170 nt.assert_equal(call_line, call)
171 nt.assert_equal(ds, docstring)
171 nt.assert_equal(ds, docstring)
172
172
173 #-----------------------------------------------------------------------------
173 #-----------------------------------------------------------------------------
174 # Tests
174 # Tests
175 #-----------------------------------------------------------------------------
175 #-----------------------------------------------------------------------------
176
176
177 def test_calltip_class():
177 def test_calltip_class():
178 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
178 check_calltip(Call, 'Call', 'Call(x, y=1)', Call.__init__.__doc__)
179
179
180
180
181 def test_calltip_instance():
181 def test_calltip_instance():
182 c = Call(1)
182 c = Call(1)
183 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
183 check_calltip(c, 'c', 'c(*a, **kw)', c.__call__.__doc__)
184
184
185
185
186 def test_calltip_method():
186 def test_calltip_method():
187 c = Call(1)
187 c = Call(1)
188 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
188 check_calltip(c.method, 'c.method', 'c.method(x, z=2)', c.method.__doc__)
189
189
190
190
191 def test_calltip_function():
191 def test_calltip_function():
192 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
192 check_calltip(f, 'f', 'f(x, y=2, *a, **kw)', f.__doc__)
193
193
194
194
195 def test_calltip_function2():
195 def test_calltip_function2():
196 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
196 check_calltip(g, 'g', 'g(y, z=3, *a, **kw)', '<no docstring>')
197
197
198
198
199 def test_calltip_builtin():
199 def test_calltip_builtin():
200 check_calltip(sum, 'sum', None, sum.__doc__)
200 check_calltip(sum, 'sum', None, sum.__doc__)
201
201
202
202
203 def test_calltip_line_magic():
203 def test_calltip_line_magic():
204 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
204 check_calltip(lmagic, 'lmagic', 'lmagic(line)', "A line magic")
205
205
206
206
207 def test_calltip_cell_magic():
207 def test_calltip_cell_magic():
208 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
208 check_calltip(cmagic, 'cmagic', 'cmagic(line, cell)', "A cell magic")
209
209
210
210
211 def test_calltip_line_magic():
211 def test_calltip_line_cell_magic():
212 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
212 check_calltip(lcmagic, 'lcmagic', 'lcmagic(line, cell=None)',
213 "A line/cell magic")
213 "A line/cell magic")
214
214
215
215
216 def test_class_magics():
216 def test_class_magics():
217 cm = SimpleMagics(ip)
217 cm = SimpleMagics(ip)
218 ip.register_magics(cm)
218 ip.register_magics(cm)
219 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
219 check_calltip(cm.Clmagic, 'Clmagic', 'Clmagic(cline)',
220 "A class-based line magic")
220 "A class-based line magic")
221 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
221 check_calltip(cm.Ccmagic, 'Ccmagic', 'Ccmagic(cline, ccell)',
222 "A class-based cell magic")
222 "A class-based cell magic")
223 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
223 check_calltip(cm.Clcmagic, 'Clcmagic', 'Clcmagic(cline, ccell=None)',
224 "A class-based line/cell magic")
224 "A class-based line/cell magic")
225
225
226
226
227 def test_info():
227 def test_info():
228 "Check that Inspector.info fills out various fields as expected."
228 "Check that Inspector.info fills out various fields as expected."
229 i = inspector.info(Call, oname='Call')
229 i = inspector.info(Call, oname='Call')
230 nt.assert_equal(i['type_name'], 'type')
230 nt.assert_equal(i['type_name'], 'type')
231 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
231 expted_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
232 nt.assert_equal(i['base_class'], expted_class)
232 nt.assert_equal(i['base_class'], expted_class)
233 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
233 nt.assert_equal(i['string_form'], "<class 'IPython.core.tests.test_oinspect.Call'>")
234 fname = __file__
234 fname = __file__
235 if fname.endswith(".pyc"):
235 if fname.endswith(".pyc"):
236 fname = fname[:-1]
236 fname = fname[:-1]
237 # case-insensitive comparison needed on some filesystems
237 # case-insensitive comparison needed on some filesystems
238 # e.g. Windows:
238 # e.g. Windows:
239 nt.assert_equal(i['file'].lower(), fname.lower())
239 nt.assert_equal(i['file'].lower(), fname.lower())
240 nt.assert_equal(i['definition'], 'Call(self, *a, **kw)\n')
240 nt.assert_equal(i['definition'], 'Call(self, *a, **kw)\n')
241 nt.assert_equal(i['docstring'], Call.__doc__)
241 nt.assert_equal(i['docstring'], Call.__doc__)
242 nt.assert_equal(i['source'], None)
242 nt.assert_equal(i['source'], None)
243 nt.assert_true(i['isclass'])
243 nt.assert_true(i['isclass'])
244 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
244 nt.assert_equal(i['init_definition'], "Call(self, x, y=1)\n")
245 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
245 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
246
246
247 i = inspector.info(Call, detail_level=1)
247 i = inspector.info(Call, detail_level=1)
248 nt.assert_not_equal(i['source'], None)
248 nt.assert_not_equal(i['source'], None)
249 nt.assert_equal(i['docstring'], None)
249 nt.assert_equal(i['docstring'], None)
250
250
251 c = Call(1)
251 c = Call(1)
252 c.__doc__ = "Modified instance docstring"
252 c.__doc__ = "Modified instance docstring"
253 i = inspector.info(c)
253 i = inspector.info(c)
254 nt.assert_equal(i['type_name'], 'Call')
254 nt.assert_equal(i['type_name'], 'Call')
255 nt.assert_equal(i['docstring'], "Modified instance docstring")
255 nt.assert_equal(i['docstring'], "Modified instance docstring")
256 nt.assert_equal(i['class_docstring'], Call.__doc__)
256 nt.assert_equal(i['class_docstring'], Call.__doc__)
257 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
257 nt.assert_equal(i['init_docstring'], Call.__init__.__doc__)
258 nt.assert_equal(i['call_docstring'], c.__call__.__doc__)
258 nt.assert_equal(i['call_docstring'], c.__call__.__doc__)
259
259
260 # Test old-style classes, which for example may not have an __init__ method.
260 # Test old-style classes, which for example may not have an __init__ method.
261 if not py3compat.PY3:
261 if not py3compat.PY3:
262 i = inspector.info(OldStyle)
262 i = inspector.info(OldStyle)
263 nt.assert_equal(i['type_name'], 'classobj')
263 nt.assert_equal(i['type_name'], 'classobj')
264
264
265 i = inspector.info(OldStyle())
265 i = inspector.info(OldStyle())
266 nt.assert_equal(i['type_name'], 'instance')
266 nt.assert_equal(i['type_name'], 'instance')
267 nt.assert_equal(i['docstring'], OldStyle.__doc__)
267 nt.assert_equal(i['docstring'], OldStyle.__doc__)
268
268
269 def test_info_awkward():
269 def test_info_awkward():
270 # Just test that this doesn't throw an error.
270 # Just test that this doesn't throw an error.
271 i = inspector.info(Awkward())
271 i = inspector.info(Awkward())
272
272
273 def test_getdoc():
273 def test_getdoc():
274 class A(object):
274 class A(object):
275 """standard docstring"""
275 """standard docstring"""
276 pass
276 pass
277
277
278 class B(object):
278 class B(object):
279 """standard docstring"""
279 """standard docstring"""
280 def getdoc(self):
280 def getdoc(self):
281 return "custom docstring"
281 return "custom docstring"
282
282
283 class C(object):
283 class C(object):
284 """standard docstring"""
284 """standard docstring"""
285 def getdoc(self):
285 def getdoc(self):
286 return None
286 return None
287
287
288 a = A()
288 a = A()
289 b = B()
289 b = B()
290 c = C()
290 c = C()
291
291
292 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
292 nt.assert_equal(oinspect.getdoc(a), "standard docstring")
293 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
293 nt.assert_equal(oinspect.getdoc(b), "custom docstring")
294 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
294 nt.assert_equal(oinspect.getdoc(c), "standard docstring")
295
295
296 def test_pdef():
296 def test_pdef():
297 # See gh-1914
297 # See gh-1914
298 def foo(): pass
298 def foo(): pass
299 inspector.pdef(foo, 'foo')
299 inspector.pdef(foo, 'foo')
300
300
301 def test_pinfo_nonascii():
301 def test_pinfo_nonascii():
302 # See gh-1177
302 # See gh-1177
303 from . import nonascii2
303 from . import nonascii2
304 ip.user_ns['nonascii2'] = nonascii2
304 ip.user_ns['nonascii2'] = nonascii2
305 ip._inspect('pinfo', 'nonascii2', detail_level=1)
305 ip._inspect('pinfo', 'nonascii2', detail_level=1)
@@ -1,99 +1,99 b''
1 """Tests for input manipulation machinery."""
1 """Tests for input manipulation machinery."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Imports
4 # Imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 import nose.tools as nt
6 import nose.tools as nt
7
7
8 from IPython.core.prefilter import AutocallChecker
8 from IPython.core.prefilter import AutocallChecker
9 from IPython.testing import tools as tt, decorators as dec
9 from IPython.testing import decorators as dec
10 from IPython.testing.globalipapp import get_ipython
10 from IPython.testing.globalipapp import get_ipython
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Tests
13 # Tests
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 ip = get_ipython()
15 ip = get_ipython()
16
16
17 @dec.parametric
17 @dec.parametric
18 def test_prefilter():
18 def test_prefilter():
19 """Test user input conversions"""
19 """Test user input conversions"""
20
20
21 # pairs of (raw, expected correct) input
21 # pairs of (raw, expected correct) input
22 pairs = [ ('2+2','2+2'),
22 pairs = [ ('2+2','2+2'),
23 ]
23 ]
24
24
25 for raw, correct in pairs:
25 for raw, correct in pairs:
26 yield nt.assert_equal(ip.prefilter(raw), correct)
26 yield nt.assert_equal(ip.prefilter(raw), correct)
27
27
28
28
29 @dec.parametric
29 @dec.parametric
30 def test_autocall_binops():
30 def test_autocall_binops():
31 """See https://github.com/ipython/ipython/issues/81"""
31 """See https://github.com/ipython/ipython/issues/81"""
32 ip.magic('autocall 2')
32 ip.magic('autocall 2')
33 f = lambda x: x
33 f = lambda x: x
34 ip.user_ns['f'] = f
34 ip.user_ns['f'] = f
35 try:
35 try:
36 yield nt.assert_equal(ip.prefilter('f 1'),'f(1)')
36 yield nt.assert_equal(ip.prefilter('f 1'),'f(1)')
37 for t in ['f +1', 'f -1']:
37 for t in ['f +1', 'f -1']:
38 yield nt.assert_equal(ip.prefilter(t), t)
38 yield nt.assert_equal(ip.prefilter(t), t)
39
39
40 # Run tests again with a more permissive exclude_regexp, which will
40 # Run tests again with a more permissive exclude_regexp, which will
41 # allow transformation of binary operations ('f -1' -> 'f(-1)').
41 # allow transformation of binary operations ('f -1' -> 'f(-1)').
42 pm = ip.prefilter_manager
42 pm = ip.prefilter_manager
43 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
43 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
44 config=pm.config)
44 config=pm.config)
45 try:
45 try:
46 ac.priority = 1
46 ac.priority = 1
47 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
47 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
48 pm.sort_checkers()
48 pm.sort_checkers()
49
49
50 yield nt.assert_equal(ip.prefilter('f -1'), 'f(-1)')
50 yield nt.assert_equal(ip.prefilter('f -1'), 'f(-1)')
51 yield nt.assert_equal(ip.prefilter('f +1'), 'f(+1)')
51 yield nt.assert_equal(ip.prefilter('f +1'), 'f(+1)')
52 finally:
52 finally:
53 pm.unregister_checker(ac)
53 pm.unregister_checker(ac)
54 finally:
54 finally:
55 ip.magic('autocall 0')
55 ip.magic('autocall 0')
56 del ip.user_ns['f']
56 del ip.user_ns['f']
57
57
58
58
59 @dec.parametric
59 @dec.parametric
60 def test_issue_114():
60 def test_issue_114():
61 """Check that multiline string literals don't expand as magic
61 """Check that multiline string literals don't expand as magic
62 see http://github.com/ipython/ipython/issues/114"""
62 see http://github.com/ipython/ipython/issues/114"""
63
63
64 template = '"""\n%s\n"""'
64 template = '"""\n%s\n"""'
65 # Store the current value of multi_line_specials and turn it off before
65 # Store the current value of multi_line_specials and turn it off before
66 # running test, since it could be true (case in which the test doesn't make
66 # running test, since it could be true (case in which the test doesn't make
67 # sense, as multiline string literals *will* expand as magic in that case).
67 # sense, as multiline string literals *will* expand as magic in that case).
68 msp = ip.prefilter_manager.multi_line_specials
68 msp = ip.prefilter_manager.multi_line_specials
69 ip.prefilter_manager.multi_line_specials = False
69 ip.prefilter_manager.multi_line_specials = False
70 try:
70 try:
71 for mgk in ip.magics_manager.lsmagic()['line']:
71 for mgk in ip.magics_manager.lsmagic()['line']:
72 raw = template % mgk
72 raw = template % mgk
73 yield nt.assert_equal(ip.prefilter(raw), raw)
73 yield nt.assert_equal(ip.prefilter(raw), raw)
74 finally:
74 finally:
75 ip.prefilter_manager.multi_line_specials = msp
75 ip.prefilter_manager.multi_line_specials = msp
76
76
77
77
78 def test_prefilter_attribute_errors():
78 def test_prefilter_attribute_errors():
79 """Capture exceptions thrown by user objects on attribute access.
79 """Capture exceptions thrown by user objects on attribute access.
80
80
81 See http://github.com/ipython/ipython/issues/988."""
81 See http://github.com/ipython/ipython/issues/988."""
82
82
83 class X(object):
83 class X(object):
84 def __getattr__(self, k):
84 def __getattr__(self, k):
85 raise ValueError('broken object')
85 raise ValueError('broken object')
86 def __call__(self, x):
86 def __call__(self, x):
87 return x
87 return x
88
88
89 # Create a callable broken object
89 # Create a callable broken object
90 ip.user_ns['x'] = X()
90 ip.user_ns['x'] = X()
91 ip.magic('autocall 2')
91 ip.magic('autocall 2')
92 try:
92 try:
93 # Even if x throws an attribute error when looking at its rewrite
93 # Even if x throws an attribute error when looking at its rewrite
94 # attribute, we should not crash. So the test here is simply making
94 # attribute, we should not crash. So the test here is simply making
95 # the prefilter call and not having an exception.
95 # the prefilter call and not having an exception.
96 ip.prefilter('x 1')
96 ip.prefilter('x 1')
97 finally:
97 finally:
98 del ip.user_ns['x']
98 del ip.user_ns['x']
99 ip.magic('autocall 0')
99 ip.magic('autocall 0')
@@ -1,151 +1,150 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for profile-related functions.
2 """Tests for profile-related functions.
3
3
4 Currently only the startup-dir functionality is tested, but more tests should
4 Currently only the startup-dir functionality is tested, but more tests should
5 be added for:
5 be added for:
6
6
7 * ipython profile create
7 * ipython profile create
8 * ipython profile list
8 * ipython profile list
9 * ipython profile create --parallel
9 * ipython profile create --parallel
10 * security dir permissions
10 * security dir permissions
11
11
12 Authors
12 Authors
13 -------
13 -------
14
14
15 * MinRK
15 * MinRK
16
16
17 """
17 """
18 from __future__ import absolute_import
18 from __future__ import absolute_import
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import os
24 import os
25 import shutil
25 import shutil
26 import sys
26 import sys
27 import tempfile
27 import tempfile
28
28
29 from unittest import TestCase
29 from unittest import TestCase
30
30
31 import nose.tools as nt
31 import nose.tools as nt
32 from nose import SkipTest
33
32
34 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
33 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
35 from IPython.core.profiledir import ProfileDir
34 from IPython.core.profiledir import ProfileDir
36
35
37 from IPython.testing import decorators as dec
36 from IPython.testing import decorators as dec
38 from IPython.testing import tools as tt
37 from IPython.testing import tools as tt
39 from IPython.utils import py3compat
38 from IPython.utils import py3compat
40
39
41
40
42 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
43 # Globals
42 # Globals
44 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
45 TMP_TEST_DIR = tempfile.mkdtemp()
44 TMP_TEST_DIR = tempfile.mkdtemp()
46 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
47 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
48
47
49 #
48 #
50 # Setup/teardown functions/decorators
49 # Setup/teardown functions/decorators
51 #
50 #
52
51
53 def setup():
52 def setup():
54 """Setup test environment for the module:
53 """Setup test environment for the module:
55
54
56 - Adds dummy home dir tree
55 - Adds dummy home dir tree
57 """
56 """
58 # Do not mask exceptions here. In particular, catching WindowsError is a
57 # Do not mask exceptions here. In particular, catching WindowsError is a
59 # problem because that exception is only defined on Windows...
58 # problem because that exception is only defined on Windows...
60 os.makedirs(IP_TEST_DIR)
59 os.makedirs(IP_TEST_DIR)
61
60
62
61
63 def teardown():
62 def teardown():
64 """Teardown test environment for the module:
63 """Teardown test environment for the module:
65
64
66 - Remove dummy home dir tree
65 - Remove dummy home dir tree
67 """
66 """
68 # Note: we remove the parent test dir, which is the root of all test
67 # Note: we remove the parent test dir, which is the root of all test
69 # subdirs we may have created. Use shutil instead of os.removedirs, so
68 # subdirs we may have created. Use shutil instead of os.removedirs, so
70 # that non-empty directories are all recursively removed.
69 # that non-empty directories are all recursively removed.
71 shutil.rmtree(TMP_TEST_DIR)
70 shutil.rmtree(TMP_TEST_DIR)
72
71
73
72
74 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
75 # Test functions
74 # Test functions
76 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
77 def win32_without_pywin32():
76 def win32_without_pywin32():
78 if sys.platform == 'win32':
77 if sys.platform == 'win32':
79 try:
78 try:
80 import pywin32
79 import pywin32
81 except ImportError:
80 except ImportError:
82 return True
81 return True
83 return False
82 return False
84
83
85
84
86 class ProfileStartupTest(TestCase):
85 class ProfileStartupTest(TestCase):
87 def setUp(self):
86 def setUp(self):
88 # create profile dir
87 # create profile dir
89 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
90 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
91 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
92
91
93 def tearDown(self):
92 def tearDown(self):
94 # We must remove this profile right away so its presence doesn't
93 # We must remove this profile right away so its presence doesn't
95 # confuse other tests.
94 # confuse other tests.
96 shutil.rmtree(self.pd.location)
95 shutil.rmtree(self.pd.location)
97
96
98 def init(self, startup_file, startup, test):
97 def init(self, startup_file, startup, test):
99 # write startup python file
98 # write startup python file
100 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
101 f.write(startup)
100 f.write(startup)
102 # write simple test file, to check that the startup file was run
101 # write simple test file, to check that the startup file was run
103 with open(self.fname, 'w') as f:
102 with open(self.fname, 'w') as f:
104 f.write(py3compat.doctest_refactor_print(test))
103 f.write(py3compat.doctest_refactor_print(test))
105
104
106 def validate(self, output):
105 def validate(self, output):
107 tt.ipexec_validate(self.fname, output, '', options=self.options)
106 tt.ipexec_validate(self.fname, output, '', options=self.options)
108
107
109 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
110 def test_startup_py(self):
109 def test_startup_py(self):
111 self.init('00-start.py', 'zzz=123\n',
110 self.init('00-start.py', 'zzz=123\n',
112 py3compat.doctest_refactor_print('print zzz\n'))
111 py3compat.doctest_refactor_print('print zzz\n'))
113 self.validate('123')
112 self.validate('123')
114
113
115 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
116 def test_startup_ipy(self):
115 def test_startup_ipy(self):
117 self.init('00-start.ipy', '%profile\n', '')
116 self.init('00-start.ipy', '%profile\n', '')
118 self.validate('test')
117 self.validate('test')
119
118
120
119
121 def test_list_profiles_in():
120 def test_list_profiles_in():
122 # No need to remove these directories and files, as they will get nuked in
121 # No need to remove these directories and files, as they will get nuked in
123 # the module-level teardown.
122 # the module-level teardown.
124 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
125 td = py3compat.str_to_unicode(td)
124 td = py3compat.str_to_unicode(td)
126 for name in ('profile_foo', u'profile_ünicode', 'profile_hello',
125 for name in ('profile_foo', u'profile_ünicode', 'profile_hello',
127 'not_a_profile'):
126 'not_a_profile'):
128 os.mkdir(os.path.join(td, name))
127 os.mkdir(os.path.join(td, name))
129 with open(os.path.join(td, 'profile_file'), 'w') as f:
128 with open(os.path.join(td, 'profile_file'), 'w') as f:
130 f.write("I am not a profile directory")
129 f.write("I am not a profile directory")
131 profiles = list_profiles_in(td)
130 profiles = list_profiles_in(td)
132
131
133 # unicode normalization can turn u'ünicode' into u'u\0308nicode',
132 # unicode normalization can turn u'ünicode' into u'u\0308nicode',
134 # so only check for *nicode, and that creating a ProfileDir from the
133 # so only check for *nicode, and that creating a ProfileDir from the
135 # name remains valid
134 # name remains valid
136 found_unicode = False
135 found_unicode = False
137 for p in list(profiles):
136 for p in list(profiles):
138 if p.endswith('nicode'):
137 if p.endswith('nicode'):
139 pd = ProfileDir.find_profile_dir_by_name(td, p)
138 pd = ProfileDir.find_profile_dir_by_name(td, p)
140 profiles.remove(p)
139 profiles.remove(p)
141 found_unicode = True
140 found_unicode = True
142 break
141 break
143 nt.assert_true(found_unicode)
142 nt.assert_true(found_unicode)
144 nt.assert_equal(set(profiles), set(['foo', 'hello']))
143 nt.assert_equal(set(profiles), set(['foo', 'hello']))
145
144
146
145
147 def test_list_bundled_profiles():
146 def test_list_bundled_profiles():
148 # This variable will need to be updated when a new profile gets bundled
147 # This variable will need to be updated when a new profile gets bundled
149 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
148 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
150 bundled = sorted(list_bundled_profiles())
149 bundled = sorted(list_bundled_profiles())
151 nt.assert_equal(bundled, bundled_true)
150 nt.assert_equal(bundled, bundled_true)
@@ -1,111 +1,109 b''
1 # -*- coding: utf-8
1 # -*- coding: utf-8
2 """Tests for prompt generation."""
2 """Tests for prompt generation."""
3
3
4 import unittest
4 import unittest
5
5
6 import os
6 import os
7 import nose.tools as nt
8
7
9 from IPython.testing import tools as tt, decorators as dec
8 from IPython.testing import tools as tt, decorators as dec
10 from IPython.core.prompts import PromptManager, LazyEvaluate
9 from IPython.core.prompts import PromptManager, LazyEvaluate
11 from IPython.testing.globalipapp import get_ipython
10 from IPython.testing.globalipapp import get_ipython
12 from IPython.utils import py3compat
13 from IPython.utils.tempdir import TemporaryDirectory
11 from IPython.utils.tempdir import TemporaryDirectory
14
12
15 ip = get_ipython()
13 ip = get_ipython()
16
14
17
15
18 class PromptTests(unittest.TestCase):
16 class PromptTests(unittest.TestCase):
19 def setUp(self):
17 def setUp(self):
20 self.pm = PromptManager(shell=ip, config=ip.config)
18 self.pm = PromptManager(shell=ip, config=ip.config)
21
19
22 def test_multiline_prompt(self):
20 def test_multiline_prompt(self):
23 self.pm.in_template = "[In]\n>>>"
21 self.pm.in_template = "[In]\n>>>"
24 self.pm.render('in')
22 self.pm.render('in')
25 self.assertEqual(self.pm.width, 3)
23 self.assertEqual(self.pm.width, 3)
26 self.assertEqual(self.pm.txtwidth, 3)
24 self.assertEqual(self.pm.txtwidth, 3)
27
25
28 self.pm.in_template = '[In]\n'
26 self.pm.in_template = '[In]\n'
29 self.pm.render('in')
27 self.pm.render('in')
30 self.assertEqual(self.pm.width, 0)
28 self.assertEqual(self.pm.width, 0)
31 self.assertEqual(self.pm.txtwidth, 0)
29 self.assertEqual(self.pm.txtwidth, 0)
32
30
33 def test_translate_abbreviations(self):
31 def test_translate_abbreviations(self):
34 def do_translate(template):
32 def do_translate(template):
35 self.pm.in_template = template
33 self.pm.in_template = template
36 return self.pm.templates['in']
34 return self.pm.templates['in']
37
35
38 pairs = [(r'%n>', '{color.number}{count}{color.prompt}>'),
36 pairs = [(r'%n>', '{color.number}{count}{color.prompt}>'),
39 (r'\T', '{time}'),
37 (r'\T', '{time}'),
40 (r'\n', '\n')
38 (r'\n', '\n')
41 ]
39 ]
42
40
43 tt.check_pairs(do_translate, pairs)
41 tt.check_pairs(do_translate, pairs)
44
42
45 def test_user_ns(self):
43 def test_user_ns(self):
46 self.pm.color_scheme = 'NoColor'
44 self.pm.color_scheme = 'NoColor'
47 ip.ex("foo='bar'")
45 ip.ex("foo='bar'")
48 self.pm.in_template = "In [{foo}]"
46 self.pm.in_template = "In [{foo}]"
49 prompt = self.pm.render('in')
47 prompt = self.pm.render('in')
50 self.assertEqual(prompt, u'In [bar]')
48 self.assertEqual(prompt, u'In [bar]')
51
49
52 def test_builtins(self):
50 def test_builtins(self):
53 self.pm.color_scheme = 'NoColor'
51 self.pm.color_scheme = 'NoColor'
54 self.pm.in_template = "In [{int}]"
52 self.pm.in_template = "In [{int}]"
55 prompt = self.pm.render('in')
53 prompt = self.pm.render('in')
56 self.assertEqual(prompt, u"In [%r]" % int)
54 self.assertEqual(prompt, u"In [%r]" % int)
57
55
58 def test_undefined(self):
56 def test_undefined(self):
59 self.pm.color_scheme = 'NoColor'
57 self.pm.color_scheme = 'NoColor'
60 self.pm.in_template = "In [{foo_dne}]"
58 self.pm.in_template = "In [{foo_dne}]"
61 prompt = self.pm.render('in')
59 prompt = self.pm.render('in')
62 self.assertEqual(prompt, u"In [<ERROR: 'foo_dne' not found>]")
60 self.assertEqual(prompt, u"In [<ERROR: 'foo_dne' not found>]")
63
61
64 def test_render(self):
62 def test_render(self):
65 self.pm.in_template = r'\#>'
63 self.pm.in_template = r'\#>'
66 self.assertEqual(self.pm.render('in',color=False), '%d>' % ip.execution_count)
64 self.assertEqual(self.pm.render('in',color=False), '%d>' % ip.execution_count)
67
65
68 def test_render_unicode_cwd(self):
66 def test_render_unicode_cwd(self):
69 save = os.getcwdu()
67 save = os.getcwdu()
70 with TemporaryDirectory(u'ünicødé') as td:
68 with TemporaryDirectory(u'ünicødé') as td:
71 os.chdir(td)
69 os.chdir(td)
72 self.pm.in_template = r'\w [\#]'
70 self.pm.in_template = r'\w [\#]'
73 p = self.pm.render('in', color=False)
71 p = self.pm.render('in', color=False)
74 self.assertEqual(p, u"%s [%i]" % (os.getcwdu(), ip.execution_count))
72 self.assertEqual(p, u"%s [%i]" % (os.getcwdu(), ip.execution_count))
75 os.chdir(save)
73 os.chdir(save)
76
74
77 def test_lazy_eval_unicode(self):
75 def test_lazy_eval_unicode(self):
78 u = u'ünicødé'
76 u = u'ünicødé'
79 lz = LazyEvaluate(lambda : u)
77 lz = LazyEvaluate(lambda : u)
80 # str(lz) would fail
78 # str(lz) would fail
81 self.assertEqual(unicode(lz), u)
79 self.assertEqual(unicode(lz), u)
82 self.assertEqual(format(lz), u)
80 self.assertEqual(format(lz), u)
83
81
84 def test_lazy_eval_nonascii_bytes(self):
82 def test_lazy_eval_nonascii_bytes(self):
85 u = u'ünicødé'
83 u = u'ünicødé'
86 b = u.encode('utf8')
84 b = u.encode('utf8')
87 lz = LazyEvaluate(lambda : b)
85 lz = LazyEvaluate(lambda : b)
88 # unicode(lz) would fail
86 # unicode(lz) would fail
89 self.assertEqual(str(lz), str(b))
87 self.assertEqual(str(lz), str(b))
90 self.assertEqual(format(lz), str(b))
88 self.assertEqual(format(lz), str(b))
91
89
92 def test_lazy_eval_float(self):
90 def test_lazy_eval_float(self):
93 f = 0.503
91 f = 0.503
94 lz = LazyEvaluate(lambda : f)
92 lz = LazyEvaluate(lambda : f)
95
93
96 self.assertEqual(str(lz), str(f))
94 self.assertEqual(str(lz), str(f))
97 self.assertEqual(unicode(lz), unicode(f))
95 self.assertEqual(unicode(lz), unicode(f))
98 self.assertEqual(format(lz), str(f))
96 self.assertEqual(format(lz), str(f))
99 self.assertEqual(format(lz, '.1'), '0.5')
97 self.assertEqual(format(lz, '.1'), '0.5')
100
98
101 @dec.skip_win32
99 @dec.skip_win32
102 def test_cwd_x(self):
100 def test_cwd_x(self):
103 self.pm.in_template = r"\X0"
101 self.pm.in_template = r"\X0"
104 save = os.getcwdu()
102 save = os.getcwdu()
105 os.chdir(os.path.expanduser('~'))
103 os.chdir(os.path.expanduser('~'))
106 p = self.pm.render('in', color=False)
104 p = self.pm.render('in', color=False)
107 try:
105 try:
108 self.assertEqual(p, '~')
106 self.assertEqual(p, '~')
109 finally:
107 finally:
110 os.chdir(save)
108 os.chdir(save)
111
109
@@ -1,51 +1,49 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for shellapp module.
2 """Tests for shellapp module.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 * Bradley Froehle
6 * Bradley Froehle
7 """
7 """
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2012 The IPython Development Team
9 # Copyright (C) 2012 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 import unittest
18 import unittest
19
19
20 import nose.tools as nt
21
22 from IPython.testing import decorators as dec
20 from IPython.testing import decorators as dec
23 from IPython.testing import tools as tt
21 from IPython.testing import tools as tt
24
22
25 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
23 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
26 """Test the behavior of the file_to_run parameter."""
24 """Test the behavior of the file_to_run parameter."""
27
25
28 def test_py_script_file_attribute(self):
26 def test_py_script_file_attribute(self):
29 """Test that `__file__` is set when running `ipython file.py`"""
27 """Test that `__file__` is set when running `ipython file.py`"""
30 src = "print(__file__)\n"
28 src = "print(__file__)\n"
31 self.mktmp(src)
29 self.mktmp(src)
32
30
33 if dec.module_not_available('sqlite3'):
31 if dec.module_not_available('sqlite3'):
34 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
32 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
35 else:
33 else:
36 err = None
34 err = None
37 tt.ipexec_validate(self.fname, self.fname, err)
35 tt.ipexec_validate(self.fname, self.fname, err)
38
36
39 def test_ipy_script_file_attribute(self):
37 def test_ipy_script_file_attribute(self):
40 """Test that `__file__` is set when running `ipython file.ipy`"""
38 """Test that `__file__` is set when running `ipython file.ipy`"""
41 src = "print(__file__)\n"
39 src = "print(__file__)\n"
42 self.mktmp(src, ext='.ipy')
40 self.mktmp(src, ext='.ipy')
43
41
44 if dec.module_not_available('sqlite3'):
42 if dec.module_not_available('sqlite3'):
45 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
43 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
46 else:
44 else:
47 err = None
45 err = None
48 tt.ipexec_validate(self.fname, self.fname, err)
46 tt.ipexec_validate(self.fname, self.fname, err)
49
47
50 # Ideally we would also test that `__file__` is not set in the
48 # Ideally we would also test that `__file__` is not set in the
51 # interactive namespace after running `ipython -i <file>`.
49 # interactive namespace after running `ipython -i <file>`.
@@ -1,35 +1,42 b''
1 # coding: utf-8
1 # coding: utf-8
2 from IPython.core.splitinput import split_user_input
2 import nose.tools as nt
3
4 from IPython.core.splitinput import split_user_input, LineInfo
3 from IPython.testing import tools as tt
5 from IPython.testing import tools as tt
4 from IPython.utils import py3compat
6 from IPython.utils import py3compat
5
7
6 tests = [
8 tests = [
7 ('x=1', ('', '', 'x', '=1')),
9 ('x=1', ('', '', 'x', '=1')),
8 ('?', ('', '?', '', '')),
10 ('?', ('', '?', '', '')),
9 ('??', ('', '??', '', '')),
11 ('??', ('', '??', '', '')),
10 (' ?', (' ', '?', '', '')),
12 (' ?', (' ', '?', '', '')),
11 (' ??', (' ', '??', '', '')),
13 (' ??', (' ', '??', '', '')),
12 ('??x', ('', '??', 'x', '')),
14 ('??x', ('', '??', 'x', '')),
13 ('?x=1', ('', '?', 'x', '=1')),
15 ('?x=1', ('', '?', 'x', '=1')),
14 ('!ls', ('', '!', 'ls', '')),
16 ('!ls', ('', '!', 'ls', '')),
15 (' !ls', (' ', '!', 'ls', '')),
17 (' !ls', (' ', '!', 'ls', '')),
16 ('!!ls', ('', '!!', 'ls', '')),
18 ('!!ls', ('', '!!', 'ls', '')),
17 (' !!ls', (' ', '!!', 'ls', '')),
19 (' !!ls', (' ', '!!', 'ls', '')),
18 (',ls', ('', ',', 'ls', '')),
20 (',ls', ('', ',', 'ls', '')),
19 (';ls', ('', ';', 'ls', '')),
21 (';ls', ('', ';', 'ls', '')),
20 (' ;ls', (' ', ';', 'ls', '')),
22 (' ;ls', (' ', ';', 'ls', '')),
21 ('f.g(x)', ('', '', 'f.g', '(x)')),
23 ('f.g(x)', ('', '', 'f.g', '(x)')),
22 ('f.g (x)', ('', '', 'f.g', '(x)')),
24 ('f.g (x)', ('', '', 'f.g', '(x)')),
23 ('?%hist1', ('', '?', '%hist1', '')),
25 ('?%hist1', ('', '?', '%hist1', '')),
24 ('?%%hist2', ('', '?', '%%hist2', '')),
26 ('?%%hist2', ('', '?', '%%hist2', '')),
25 ('??%hist3', ('', '??', '%hist3', '')),
27 ('??%hist3', ('', '??', '%hist3', '')),
26 ('??%%hist4', ('', '??', '%%hist4', '')),
28 ('??%%hist4', ('', '??', '%%hist4', '')),
27 ('?x*', ('', '?', 'x*', '')),
29 ('?x*', ('', '?', 'x*', '')),
28 ]
30 ]
29 if py3compat.PY3:
31 if py3compat.PY3:
30 tests.append((u"Pérez Fernando", (u'', u'', u'Pérez', u'Fernando')))
32 tests.append((u"Pérez Fernando", (u'', u'', u'Pérez', u'Fernando')))
31 else:
33 else:
32 tests.append((u"Pérez Fernando", (u'', u'', u'P', u'érez Fernando')))
34 tests.append((u"Pérez Fernando", (u'', u'', u'P', u'érez Fernando')))
33
35
34 def test_split_user_input():
36 def test_split_user_input():
35 return tt.check_pairs(split_user_input, tests)
37 return tt.check_pairs(split_user_input, tests)
38
39 def test_LineInfo():
40 """Simple test for LineInfo construction and str()"""
41 linfo = LineInfo(' %cd /home')
42 nt.assert_equal(str(linfo), 'LineInfo [ |%|cd|/home]')
General Comments 0
You need to be logged in to leave comments. Login now