##// END OF EJS Templates
ipython_kernel is now ipykernel
Min RK -
Show More
@@ -1,145 +1,145 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IPython: tools for interactive and parallel computing in Python.
3 IPython: tools for interactive and parallel computing in Python.
4
4
5 http://ipython.org
5 http://ipython.org
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2008-2011, IPython Development Team.
8 # Copyright (c) 2008-2011, IPython Development Team.
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
9 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
10 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
11 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
12 #
12 #
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14 #
14 #
15 # The full license is in the file COPYING.txt, distributed with this software.
15 # The full license is in the file COPYING.txt, distributed with this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 from __future__ import absolute_import
21 from __future__ import absolute_import
22
22
23 import os
23 import os
24 import sys
24 import sys
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Setup everything
27 # Setup everything
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 # Don't forget to also update setup.py when this changes!
30 # Don't forget to also update setup.py when this changes!
31 v = sys.version_info
31 v = sys.version_info
32 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
32 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
33 raise ImportError('IPython requires Python version 2.7 or 3.3 or above.')
33 raise ImportError('IPython requires Python version 2.7 or 3.3 or above.')
34 del v
34 del v
35
35
36 # Make it easy to import extensions - they are always directly on pythonpath.
36 # Make it easy to import extensions - they are always directly on pythonpath.
37 # Therefore, non-IPython modules can be added to extensions directory.
37 # Therefore, non-IPython modules can be added to extensions directory.
38 # This should probably be in ipapp.py.
38 # This should probably be in ipapp.py.
39 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
39 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Setup the top level names
42 # Setup the top level names
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45 from .core.getipython import get_ipython
45 from .core.getipython import get_ipython
46 from .core import release
46 from .core import release
47 from .core.application import Application
47 from .core.application import Application
48 from .terminal.embed import embed
48 from .terminal.embed import embed
49
49
50 from .core.interactiveshell import InteractiveShell
50 from .core.interactiveshell import InteractiveShell
51 from .testing import test
51 from .testing import test
52 from .utils.sysinfo import sys_info
52 from .utils.sysinfo import sys_info
53 from .utils.frame import extract_module_locals
53 from .utils.frame import extract_module_locals
54
54
55 # Release data
55 # Release data
56 __author__ = '%s <%s>' % (release.author, release.author_email)
56 __author__ = '%s <%s>' % (release.author, release.author_email)
57 __license__ = release.license
57 __license__ = release.license
58 __version__ = release.version
58 __version__ = release.version
59 version_info = release.version_info
59 version_info = release.version_info
60
60
61 def embed_kernel(module=None, local_ns=None, **kwargs):
61 def embed_kernel(module=None, local_ns=None, **kwargs):
62 """Embed and start an IPython kernel in a given scope.
62 """Embed and start an IPython kernel in a given scope.
63
63
64 If you don't want the kernel to initialize the namespace
64 If you don't want the kernel to initialize the namespace
65 from the scope of the surrounding function,
65 from the scope of the surrounding function,
66 and/or you want to load full IPython configuration,
66 and/or you want to load full IPython configuration,
67 you probably want `IPython.start_kernel()` instead.
67 you probably want `IPython.start_kernel()` instead.
68
68
69 Parameters
69 Parameters
70 ----------
70 ----------
71 module : ModuleType, optional
71 module : ModuleType, optional
72 The module to load into IPython globals (default: caller)
72 The module to load into IPython globals (default: caller)
73 local_ns : dict, optional
73 local_ns : dict, optional
74 The namespace to load into IPython user namespace (default: caller)
74 The namespace to load into IPython user namespace (default: caller)
75
75
76 kwargs : various, optional
76 kwargs : various, optional
77 Further keyword args are relayed to the IPKernelApp constructor,
77 Further keyword args are relayed to the IPKernelApp constructor,
78 allowing configuration of the Kernel. Will only have an effect
78 allowing configuration of the Kernel. Will only have an effect
79 on the first embed_kernel call for a given process.
79 on the first embed_kernel call for a given process.
80 """
80 """
81
81
82 (caller_module, caller_locals) = extract_module_locals(1)
82 (caller_module, caller_locals) = extract_module_locals(1)
83 if module is None:
83 if module is None:
84 module = caller_module
84 module = caller_module
85 if local_ns is None:
85 if local_ns is None:
86 local_ns = caller_locals
86 local_ns = caller_locals
87
87
88 # Only import .zmq when we really need it
88 # Only import .zmq when we really need it
89 from ipython_kernel.embed import embed_kernel as real_embed_kernel
89 from ipykernel.embed import embed_kernel as real_embed_kernel
90 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
90 real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
91
91
92 def start_ipython(argv=None, **kwargs):
92 def start_ipython(argv=None, **kwargs):
93 """Launch a normal IPython instance (as opposed to embedded)
93 """Launch a normal IPython instance (as opposed to embedded)
94
94
95 `IPython.embed()` puts a shell in a particular calling scope,
95 `IPython.embed()` puts a shell in a particular calling scope,
96 such as a function or method for debugging purposes,
96 such as a function or method for debugging purposes,
97 which is often not desirable.
97 which is often not desirable.
98
98
99 `start_ipython()` does full, regular IPython initialization,
99 `start_ipython()` does full, regular IPython initialization,
100 including loading startup files, configuration, etc.
100 including loading startup files, configuration, etc.
101 much of which is skipped by `embed()`.
101 much of which is skipped by `embed()`.
102
102
103 This is a public API method, and will survive implementation changes.
103 This is a public API method, and will survive implementation changes.
104
104
105 Parameters
105 Parameters
106 ----------
106 ----------
107
107
108 argv : list or None, optional
108 argv : list or None, optional
109 If unspecified or None, IPython will parse command-line options from sys.argv.
109 If unspecified or None, IPython will parse command-line options from sys.argv.
110 To prevent any command-line parsing, pass an empty list: `argv=[]`.
110 To prevent any command-line parsing, pass an empty list: `argv=[]`.
111 user_ns : dict, optional
111 user_ns : dict, optional
112 specify this dictionary to initialize the IPython user namespace with particular values.
112 specify this dictionary to initialize the IPython user namespace with particular values.
113 kwargs : various, optional
113 kwargs : various, optional
114 Any other kwargs will be passed to the Application constructor,
114 Any other kwargs will be passed to the Application constructor,
115 such as `config`.
115 such as `config`.
116 """
116 """
117 from IPython.terminal.ipapp import launch_new_instance
117 from IPython.terminal.ipapp import launch_new_instance
118 return launch_new_instance(argv=argv, **kwargs)
118 return launch_new_instance(argv=argv, **kwargs)
119
119
120 def start_kernel(argv=None, **kwargs):
120 def start_kernel(argv=None, **kwargs):
121 """Launch a normal IPython kernel instance (as opposed to embedded)
121 """Launch a normal IPython kernel instance (as opposed to embedded)
122
122
123 `IPython.embed_kernel()` puts a shell in a particular calling scope,
123 `IPython.embed_kernel()` puts a shell in a particular calling scope,
124 such as a function or method for debugging purposes,
124 such as a function or method for debugging purposes,
125 which is often not desirable.
125 which is often not desirable.
126
126
127 `start_kernel()` does full, regular IPython initialization,
127 `start_kernel()` does full, regular IPython initialization,
128 including loading startup files, configuration, etc.
128 including loading startup files, configuration, etc.
129 much of which is skipped by `embed()`.
129 much of which is skipped by `embed()`.
130
130
131 Parameters
131 Parameters
132 ----------
132 ----------
133
133
134 argv : list or None, optional
134 argv : list or None, optional
135 If unspecified or None, IPython will parse command-line options from sys.argv.
135 If unspecified or None, IPython will parse command-line options from sys.argv.
136 To prevent any command-line parsing, pass an empty list: `argv=[]`.
136 To prevent any command-line parsing, pass an empty list: `argv=[]`.
137 user_ns : dict, optional
137 user_ns : dict, optional
138 specify this dictionary to initialize the IPython user namespace with particular values.
138 specify this dictionary to initialize the IPython user namespace with particular values.
139 kwargs : various, optional
139 kwargs : various, optional
140 Any other kwargs will be passed to the Application constructor,
140 Any other kwargs will be passed to the Application constructor,
141 such as `config`.
141 such as `config`.
142 """
142 """
143 from IPython.kernel.zmq.kernelapp import launch_new_instance
143 from IPython.kernel.zmq.kernelapp import launch_new_instance
144 return launch_new_instance(argv=argv, **kwargs)
144 return launch_new_instance(argv=argv, **kwargs)
145
145
@@ -1,967 +1,967 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats."""
2 """Top-level display functions for displaying object in different formats."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from __future__ import print_function
7 from __future__ import print_function
8
8
9 import json
9 import json
10 import mimetypes
10 import mimetypes
11 import os
11 import os
12 import struct
12 import struct
13 import warnings
13 import warnings
14
14
15 from IPython.core.formatters import _safe_get_formatter_method
15 from IPython.core.formatters import _safe_get_formatter_method
16 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
16 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
17 unicode_type)
17 unicode_type)
18 from IPython.testing.skipdoctest import skip_doctest
18 from IPython.testing.skipdoctest import skip_doctest
19
19
20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
20 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
21 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
22 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
23 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
24 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
24 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
25 'publish_display_data']
25 'publish_display_data']
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # utility functions
28 # utility functions
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 def _safe_exists(path):
31 def _safe_exists(path):
32 """Check path, but don't let exceptions raise"""
32 """Check path, but don't let exceptions raise"""
33 try:
33 try:
34 return os.path.exists(path)
34 return os.path.exists(path)
35 except Exception:
35 except Exception:
36 return False
36 return False
37
37
38 def _merge(d1, d2):
38 def _merge(d1, d2):
39 """Like update, but merges sub-dicts instead of clobbering at the top level.
39 """Like update, but merges sub-dicts instead of clobbering at the top level.
40
40
41 Updates d1 in-place
41 Updates d1 in-place
42 """
42 """
43
43
44 if not isinstance(d2, dict) or not isinstance(d1, dict):
44 if not isinstance(d2, dict) or not isinstance(d1, dict):
45 return d2
45 return d2
46 for key, value in d2.items():
46 for key, value in d2.items():
47 d1[key] = _merge(d1.get(key), value)
47 d1[key] = _merge(d1.get(key), value)
48 return d1
48 return d1
49
49
50 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
50 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
51 """internal implementation of all display_foo methods
51 """internal implementation of all display_foo methods
52
52
53 Parameters
53 Parameters
54 ----------
54 ----------
55 mimetype : str
55 mimetype : str
56 The mimetype to be published (e.g. 'image/png')
56 The mimetype to be published (e.g. 'image/png')
57 objs : tuple of objects
57 objs : tuple of objects
58 The Python objects to display, or if raw=True raw text data to
58 The Python objects to display, or if raw=True raw text data to
59 display.
59 display.
60 raw : bool
60 raw : bool
61 Are the data objects raw data or Python objects that need to be
61 Are the data objects raw data or Python objects that need to be
62 formatted before display? [default: False]
62 formatted before display? [default: False]
63 metadata : dict (optional)
63 metadata : dict (optional)
64 Metadata to be associated with the specific mimetype output.
64 Metadata to be associated with the specific mimetype output.
65 """
65 """
66 if metadata:
66 if metadata:
67 metadata = {mimetype: metadata}
67 metadata = {mimetype: metadata}
68 if raw:
68 if raw:
69 # turn list of pngdata into list of { 'image/png': pngdata }
69 # turn list of pngdata into list of { 'image/png': pngdata }
70 objs = [ {mimetype: obj} for obj in objs ]
70 objs = [ {mimetype: obj} for obj in objs ]
71 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
71 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
72
72
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74 # Main functions
74 # Main functions
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76
76
77 def publish_display_data(data, metadata=None, source=None):
77 def publish_display_data(data, metadata=None, source=None):
78 """Publish data and metadata to all frontends.
78 """Publish data and metadata to all frontends.
79
79
80 See the ``display_data`` message in the messaging documentation for
80 See the ``display_data`` message in the messaging documentation for
81 more details about this message type.
81 more details about this message type.
82
82
83 The following MIME types are currently implemented:
83 The following MIME types are currently implemented:
84
84
85 * text/plain
85 * text/plain
86 * text/html
86 * text/html
87 * text/markdown
87 * text/markdown
88 * text/latex
88 * text/latex
89 * application/json
89 * application/json
90 * application/javascript
90 * application/javascript
91 * image/png
91 * image/png
92 * image/jpeg
92 * image/jpeg
93 * image/svg+xml
93 * image/svg+xml
94
94
95 Parameters
95 Parameters
96 ----------
96 ----------
97 data : dict
97 data : dict
98 A dictionary having keys that are valid MIME types (like
98 A dictionary having keys that are valid MIME types (like
99 'text/plain' or 'image/svg+xml') and values that are the data for
99 'text/plain' or 'image/svg+xml') and values that are the data for
100 that MIME type. The data itself must be a JSON'able data
100 that MIME type. The data itself must be a JSON'able data
101 structure. Minimally all data should have the 'text/plain' data,
101 structure. Minimally all data should have the 'text/plain' data,
102 which can be displayed by all frontends. If more than the plain
102 which can be displayed by all frontends. If more than the plain
103 text is given, it is up to the frontend to decide which
103 text is given, it is up to the frontend to decide which
104 representation to use.
104 representation to use.
105 metadata : dict
105 metadata : dict
106 A dictionary for metadata related to the data. This can contain
106 A dictionary for metadata related to the data. This can contain
107 arbitrary key, value pairs that frontends can use to interpret
107 arbitrary key, value pairs that frontends can use to interpret
108 the data. mime-type keys matching those in data can be used
108 the data. mime-type keys matching those in data can be used
109 to specify metadata about particular representations.
109 to specify metadata about particular representations.
110 source : str, deprecated
110 source : str, deprecated
111 Unused.
111 Unused.
112 """
112 """
113 from IPython.core.interactiveshell import InteractiveShell
113 from IPython.core.interactiveshell import InteractiveShell
114 InteractiveShell.instance().display_pub.publish(
114 InteractiveShell.instance().display_pub.publish(
115 data=data,
115 data=data,
116 metadata=metadata,
116 metadata=metadata,
117 )
117 )
118
118
119 def display(*objs, **kwargs):
119 def display(*objs, **kwargs):
120 """Display a Python object in all frontends.
120 """Display a Python object in all frontends.
121
121
122 By default all representations will be computed and sent to the frontends.
122 By default all representations will be computed and sent to the frontends.
123 Frontends can decide which representation is used and how.
123 Frontends can decide which representation is used and how.
124
124
125 Parameters
125 Parameters
126 ----------
126 ----------
127 objs : tuple of objects
127 objs : tuple of objects
128 The Python objects to display.
128 The Python objects to display.
129 raw : bool, optional
129 raw : bool, optional
130 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
130 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
131 or Python objects that need to be formatted before display? [default: False]
131 or Python objects that need to be formatted before display? [default: False]
132 include : list or tuple, optional
132 include : list or tuple, optional
133 A list of format type strings (MIME types) to include in the
133 A list of format type strings (MIME types) to include in the
134 format data dict. If this is set *only* the format types included
134 format data dict. If this is set *only* the format types included
135 in this list will be computed.
135 in this list will be computed.
136 exclude : list or tuple, optional
136 exclude : list or tuple, optional
137 A list of format type strings (MIME types) to exclude in the format
137 A list of format type strings (MIME types) to exclude in the format
138 data dict. If this is set all format types will be computed,
138 data dict. If this is set all format types will be computed,
139 except for those included in this argument.
139 except for those included in this argument.
140 metadata : dict, optional
140 metadata : dict, optional
141 A dictionary of metadata to associate with the output.
141 A dictionary of metadata to associate with the output.
142 mime-type keys in this dictionary will be associated with the individual
142 mime-type keys in this dictionary will be associated with the individual
143 representation formats, if they exist.
143 representation formats, if they exist.
144 """
144 """
145 raw = kwargs.get('raw', False)
145 raw = kwargs.get('raw', False)
146 include = kwargs.get('include')
146 include = kwargs.get('include')
147 exclude = kwargs.get('exclude')
147 exclude = kwargs.get('exclude')
148 metadata = kwargs.get('metadata')
148 metadata = kwargs.get('metadata')
149
149
150 from IPython.core.interactiveshell import InteractiveShell
150 from IPython.core.interactiveshell import InteractiveShell
151
151
152 if not raw:
152 if not raw:
153 format = InteractiveShell.instance().display_formatter.format
153 format = InteractiveShell.instance().display_formatter.format
154
154
155 for obj in objs:
155 for obj in objs:
156 if raw:
156 if raw:
157 publish_display_data(data=obj, metadata=metadata)
157 publish_display_data(data=obj, metadata=metadata)
158 else:
158 else:
159 format_dict, md_dict = format(obj, include=include, exclude=exclude)
159 format_dict, md_dict = format(obj, include=include, exclude=exclude)
160 if not format_dict:
160 if not format_dict:
161 # nothing to display (e.g. _ipython_display_ took over)
161 # nothing to display (e.g. _ipython_display_ took over)
162 continue
162 continue
163 if metadata:
163 if metadata:
164 # kwarg-specified metadata gets precedence
164 # kwarg-specified metadata gets precedence
165 _merge(md_dict, metadata)
165 _merge(md_dict, metadata)
166 publish_display_data(data=format_dict, metadata=md_dict)
166 publish_display_data(data=format_dict, metadata=md_dict)
167
167
168
168
169 def display_pretty(*objs, **kwargs):
169 def display_pretty(*objs, **kwargs):
170 """Display the pretty (default) representation of an object.
170 """Display the pretty (default) representation of an object.
171
171
172 Parameters
172 Parameters
173 ----------
173 ----------
174 objs : tuple of objects
174 objs : tuple of objects
175 The Python objects to display, or if raw=True raw text data to
175 The Python objects to display, or if raw=True raw text data to
176 display.
176 display.
177 raw : bool
177 raw : bool
178 Are the data objects raw data or Python objects that need to be
178 Are the data objects raw data or Python objects that need to be
179 formatted before display? [default: False]
179 formatted before display? [default: False]
180 metadata : dict (optional)
180 metadata : dict (optional)
181 Metadata to be associated with the specific mimetype output.
181 Metadata to be associated with the specific mimetype output.
182 """
182 """
183 _display_mimetype('text/plain', objs, **kwargs)
183 _display_mimetype('text/plain', objs, **kwargs)
184
184
185
185
186 def display_html(*objs, **kwargs):
186 def display_html(*objs, **kwargs):
187 """Display the HTML representation of an object.
187 """Display the HTML representation of an object.
188
188
189 Parameters
189 Parameters
190 ----------
190 ----------
191 objs : tuple of objects
191 objs : tuple of objects
192 The Python objects to display, or if raw=True raw HTML data to
192 The Python objects to display, or if raw=True raw HTML data to
193 display.
193 display.
194 raw : bool
194 raw : bool
195 Are the data objects raw data or Python objects that need to be
195 Are the data objects raw data or Python objects that need to be
196 formatted before display? [default: False]
196 formatted before display? [default: False]
197 metadata : dict (optional)
197 metadata : dict (optional)
198 Metadata to be associated with the specific mimetype output.
198 Metadata to be associated with the specific mimetype output.
199 """
199 """
200 _display_mimetype('text/html', objs, **kwargs)
200 _display_mimetype('text/html', objs, **kwargs)
201
201
202
202
203 def display_markdown(*objs, **kwargs):
203 def display_markdown(*objs, **kwargs):
204 """Displays the Markdown representation of an object.
204 """Displays the Markdown representation of an object.
205
205
206 Parameters
206 Parameters
207 ----------
207 ----------
208 objs : tuple of objects
208 objs : tuple of objects
209 The Python objects to display, or if raw=True raw markdown data to
209 The Python objects to display, or if raw=True raw markdown data to
210 display.
210 display.
211 raw : bool
211 raw : bool
212 Are the data objects raw data or Python objects that need to be
212 Are the data objects raw data or Python objects that need to be
213 formatted before display? [default: False]
213 formatted before display? [default: False]
214 metadata : dict (optional)
214 metadata : dict (optional)
215 Metadata to be associated with the specific mimetype output.
215 Metadata to be associated with the specific mimetype output.
216 """
216 """
217
217
218 _display_mimetype('text/markdown', objs, **kwargs)
218 _display_mimetype('text/markdown', objs, **kwargs)
219
219
220
220
221 def display_svg(*objs, **kwargs):
221 def display_svg(*objs, **kwargs):
222 """Display the SVG representation of an object.
222 """Display the SVG representation of an object.
223
223
224 Parameters
224 Parameters
225 ----------
225 ----------
226 objs : tuple of objects
226 objs : tuple of objects
227 The Python objects to display, or if raw=True raw svg data to
227 The Python objects to display, or if raw=True raw svg data to
228 display.
228 display.
229 raw : bool
229 raw : bool
230 Are the data objects raw data or Python objects that need to be
230 Are the data objects raw data or Python objects that need to be
231 formatted before display? [default: False]
231 formatted before display? [default: False]
232 metadata : dict (optional)
232 metadata : dict (optional)
233 Metadata to be associated with the specific mimetype output.
233 Metadata to be associated with the specific mimetype output.
234 """
234 """
235 _display_mimetype('image/svg+xml', objs, **kwargs)
235 _display_mimetype('image/svg+xml', objs, **kwargs)
236
236
237
237
238 def display_png(*objs, **kwargs):
238 def display_png(*objs, **kwargs):
239 """Display the PNG representation of an object.
239 """Display the PNG representation of an object.
240
240
241 Parameters
241 Parameters
242 ----------
242 ----------
243 objs : tuple of objects
243 objs : tuple of objects
244 The Python objects to display, or if raw=True raw png data to
244 The Python objects to display, or if raw=True raw png data to
245 display.
245 display.
246 raw : bool
246 raw : bool
247 Are the data objects raw data or Python objects that need to be
247 Are the data objects raw data or Python objects that need to be
248 formatted before display? [default: False]
248 formatted before display? [default: False]
249 metadata : dict (optional)
249 metadata : dict (optional)
250 Metadata to be associated with the specific mimetype output.
250 Metadata to be associated with the specific mimetype output.
251 """
251 """
252 _display_mimetype('image/png', objs, **kwargs)
252 _display_mimetype('image/png', objs, **kwargs)
253
253
254
254
255 def display_jpeg(*objs, **kwargs):
255 def display_jpeg(*objs, **kwargs):
256 """Display the JPEG representation of an object.
256 """Display the JPEG representation of an object.
257
257
258 Parameters
258 Parameters
259 ----------
259 ----------
260 objs : tuple of objects
260 objs : tuple of objects
261 The Python objects to display, or if raw=True raw JPEG data to
261 The Python objects to display, or if raw=True raw JPEG data to
262 display.
262 display.
263 raw : bool
263 raw : bool
264 Are the data objects raw data or Python objects that need to be
264 Are the data objects raw data or Python objects that need to be
265 formatted before display? [default: False]
265 formatted before display? [default: False]
266 metadata : dict (optional)
266 metadata : dict (optional)
267 Metadata to be associated with the specific mimetype output.
267 Metadata to be associated with the specific mimetype output.
268 """
268 """
269 _display_mimetype('image/jpeg', objs, **kwargs)
269 _display_mimetype('image/jpeg', objs, **kwargs)
270
270
271
271
272 def display_latex(*objs, **kwargs):
272 def display_latex(*objs, **kwargs):
273 """Display the LaTeX representation of an object.
273 """Display the LaTeX representation of an object.
274
274
275 Parameters
275 Parameters
276 ----------
276 ----------
277 objs : tuple of objects
277 objs : tuple of objects
278 The Python objects to display, or if raw=True raw latex data to
278 The Python objects to display, or if raw=True raw latex data to
279 display.
279 display.
280 raw : bool
280 raw : bool
281 Are the data objects raw data or Python objects that need to be
281 Are the data objects raw data or Python objects that need to be
282 formatted before display? [default: False]
282 formatted before display? [default: False]
283 metadata : dict (optional)
283 metadata : dict (optional)
284 Metadata to be associated with the specific mimetype output.
284 Metadata to be associated with the specific mimetype output.
285 """
285 """
286 _display_mimetype('text/latex', objs, **kwargs)
286 _display_mimetype('text/latex', objs, **kwargs)
287
287
288
288
289 def display_json(*objs, **kwargs):
289 def display_json(*objs, **kwargs):
290 """Display the JSON representation of an object.
290 """Display the JSON representation of an object.
291
291
292 Note that not many frontends support displaying JSON.
292 Note that not many frontends support displaying JSON.
293
293
294 Parameters
294 Parameters
295 ----------
295 ----------
296 objs : tuple of objects
296 objs : tuple of objects
297 The Python objects to display, or if raw=True raw json data to
297 The Python objects to display, or if raw=True raw json data to
298 display.
298 display.
299 raw : bool
299 raw : bool
300 Are the data objects raw data or Python objects that need to be
300 Are the data objects raw data or Python objects that need to be
301 formatted before display? [default: False]
301 formatted before display? [default: False]
302 metadata : dict (optional)
302 metadata : dict (optional)
303 Metadata to be associated with the specific mimetype output.
303 Metadata to be associated with the specific mimetype output.
304 """
304 """
305 _display_mimetype('application/json', objs, **kwargs)
305 _display_mimetype('application/json', objs, **kwargs)
306
306
307
307
308 def display_javascript(*objs, **kwargs):
308 def display_javascript(*objs, **kwargs):
309 """Display the Javascript representation of an object.
309 """Display the Javascript representation of an object.
310
310
311 Parameters
311 Parameters
312 ----------
312 ----------
313 objs : tuple of objects
313 objs : tuple of objects
314 The Python objects to display, or if raw=True raw javascript data to
314 The Python objects to display, or if raw=True raw javascript data to
315 display.
315 display.
316 raw : bool
316 raw : bool
317 Are the data objects raw data or Python objects that need to be
317 Are the data objects raw data or Python objects that need to be
318 formatted before display? [default: False]
318 formatted before display? [default: False]
319 metadata : dict (optional)
319 metadata : dict (optional)
320 Metadata to be associated with the specific mimetype output.
320 Metadata to be associated with the specific mimetype output.
321 """
321 """
322 _display_mimetype('application/javascript', objs, **kwargs)
322 _display_mimetype('application/javascript', objs, **kwargs)
323
323
324
324
325 def display_pdf(*objs, **kwargs):
325 def display_pdf(*objs, **kwargs):
326 """Display the PDF representation of an object.
326 """Display the PDF representation of an object.
327
327
328 Parameters
328 Parameters
329 ----------
329 ----------
330 objs : tuple of objects
330 objs : tuple of objects
331 The Python objects to display, or if raw=True raw javascript data to
331 The Python objects to display, or if raw=True raw javascript data to
332 display.
332 display.
333 raw : bool
333 raw : bool
334 Are the data objects raw data or Python objects that need to be
334 Are the data objects raw data or Python objects that need to be
335 formatted before display? [default: False]
335 formatted before display? [default: False]
336 metadata : dict (optional)
336 metadata : dict (optional)
337 Metadata to be associated with the specific mimetype output.
337 Metadata to be associated with the specific mimetype output.
338 """
338 """
339 _display_mimetype('application/pdf', objs, **kwargs)
339 _display_mimetype('application/pdf', objs, **kwargs)
340
340
341
341
342 #-----------------------------------------------------------------------------
342 #-----------------------------------------------------------------------------
343 # Smart classes
343 # Smart classes
344 #-----------------------------------------------------------------------------
344 #-----------------------------------------------------------------------------
345
345
346
346
347 class DisplayObject(object):
347 class DisplayObject(object):
348 """An object that wraps data to be displayed."""
348 """An object that wraps data to be displayed."""
349
349
350 _read_flags = 'r'
350 _read_flags = 'r'
351 _show_mem_addr = False
351 _show_mem_addr = False
352
352
353 def __init__(self, data=None, url=None, filename=None):
353 def __init__(self, data=None, url=None, filename=None):
354 """Create a display object given raw data.
354 """Create a display object given raw data.
355
355
356 When this object is returned by an expression or passed to the
356 When this object is returned by an expression or passed to the
357 display function, it will result in the data being displayed
357 display function, it will result in the data being displayed
358 in the frontend. The MIME type of the data should match the
358 in the frontend. The MIME type of the data should match the
359 subclasses used, so the Png subclass should be used for 'image/png'
359 subclasses used, so the Png subclass should be used for 'image/png'
360 data. If the data is a URL, the data will first be downloaded
360 data. If the data is a URL, the data will first be downloaded
361 and then displayed. If
361 and then displayed. If
362
362
363 Parameters
363 Parameters
364 ----------
364 ----------
365 data : unicode, str or bytes
365 data : unicode, str or bytes
366 The raw data or a URL or file to load the data from
366 The raw data or a URL or file to load the data from
367 url : unicode
367 url : unicode
368 A URL to download the data from.
368 A URL to download the data from.
369 filename : unicode
369 filename : unicode
370 Path to a local file to load the data from.
370 Path to a local file to load the data from.
371 """
371 """
372 if data is not None and isinstance(data, string_types):
372 if data is not None and isinstance(data, string_types):
373 if data.startswith('http') and url is None:
373 if data.startswith('http') and url is None:
374 url = data
374 url = data
375 filename = None
375 filename = None
376 data = None
376 data = None
377 elif _safe_exists(data) and filename is None:
377 elif _safe_exists(data) and filename is None:
378 url = None
378 url = None
379 filename = data
379 filename = data
380 data = None
380 data = None
381
381
382 self.data = data
382 self.data = data
383 self.url = url
383 self.url = url
384 self.filename = None if filename is None else unicode_type(filename)
384 self.filename = None if filename is None else unicode_type(filename)
385
385
386 self.reload()
386 self.reload()
387 self._check_data()
387 self._check_data()
388
388
389 def __repr__(self):
389 def __repr__(self):
390 if not self._show_mem_addr:
390 if not self._show_mem_addr:
391 cls = self.__class__
391 cls = self.__class__
392 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
392 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
393 else:
393 else:
394 r = super(DisplayObject, self).__repr__()
394 r = super(DisplayObject, self).__repr__()
395 return r
395 return r
396
396
397 def _check_data(self):
397 def _check_data(self):
398 """Override in subclasses if there's something to check."""
398 """Override in subclasses if there's something to check."""
399 pass
399 pass
400
400
401 def reload(self):
401 def reload(self):
402 """Reload the raw data from file or URL."""
402 """Reload the raw data from file or URL."""
403 if self.filename is not None:
403 if self.filename is not None:
404 with open(self.filename, self._read_flags) as f:
404 with open(self.filename, self._read_flags) as f:
405 self.data = f.read()
405 self.data = f.read()
406 elif self.url is not None:
406 elif self.url is not None:
407 try:
407 try:
408 try:
408 try:
409 from urllib.request import urlopen # Py3
409 from urllib.request import urlopen # Py3
410 except ImportError:
410 except ImportError:
411 from urllib2 import urlopen
411 from urllib2 import urlopen
412 response = urlopen(self.url)
412 response = urlopen(self.url)
413 self.data = response.read()
413 self.data = response.read()
414 # extract encoding from header, if there is one:
414 # extract encoding from header, if there is one:
415 encoding = None
415 encoding = None
416 for sub in response.headers['content-type'].split(';'):
416 for sub in response.headers['content-type'].split(';'):
417 sub = sub.strip()
417 sub = sub.strip()
418 if sub.startswith('charset'):
418 if sub.startswith('charset'):
419 encoding = sub.split('=')[-1].strip()
419 encoding = sub.split('=')[-1].strip()
420 break
420 break
421 # decode data, if an encoding was specified
421 # decode data, if an encoding was specified
422 if encoding:
422 if encoding:
423 self.data = self.data.decode(encoding, 'replace')
423 self.data = self.data.decode(encoding, 'replace')
424 except:
424 except:
425 self.data = None
425 self.data = None
426
426
427 class TextDisplayObject(DisplayObject):
427 class TextDisplayObject(DisplayObject):
428 """Validate that display data is text"""
428 """Validate that display data is text"""
429 def _check_data(self):
429 def _check_data(self):
430 if self.data is not None and not isinstance(self.data, string_types):
430 if self.data is not None and not isinstance(self.data, string_types):
431 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
431 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
432
432
433 class Pretty(TextDisplayObject):
433 class Pretty(TextDisplayObject):
434
434
435 def _repr_pretty_(self):
435 def _repr_pretty_(self):
436 return self.data
436 return self.data
437
437
438
438
439 class HTML(TextDisplayObject):
439 class HTML(TextDisplayObject):
440
440
441 def _repr_html_(self):
441 def _repr_html_(self):
442 return self.data
442 return self.data
443
443
444 def __html__(self):
444 def __html__(self):
445 """
445 """
446 This method exists to inform other HTML-using modules (e.g. Markupsafe,
446 This method exists to inform other HTML-using modules (e.g. Markupsafe,
447 htmltag, etc) that this object is HTML and does not need things like
447 htmltag, etc) that this object is HTML and does not need things like
448 special characters (<>&) escaped.
448 special characters (<>&) escaped.
449 """
449 """
450 return self._repr_html_()
450 return self._repr_html_()
451
451
452
452
453 class Markdown(TextDisplayObject):
453 class Markdown(TextDisplayObject):
454
454
455 def _repr_markdown_(self):
455 def _repr_markdown_(self):
456 return self.data
456 return self.data
457
457
458
458
459 class Math(TextDisplayObject):
459 class Math(TextDisplayObject):
460
460
461 def _repr_latex_(self):
461 def _repr_latex_(self):
462 s = self.data.strip('$')
462 s = self.data.strip('$')
463 return "$$%s$$" % s
463 return "$$%s$$" % s
464
464
465
465
466 class Latex(TextDisplayObject):
466 class Latex(TextDisplayObject):
467
467
468 def _repr_latex_(self):
468 def _repr_latex_(self):
469 return self.data
469 return self.data
470
470
471
471
472 class SVG(DisplayObject):
472 class SVG(DisplayObject):
473
473
474 # wrap data in a property, which extracts the <svg> tag, discarding
474 # wrap data in a property, which extracts the <svg> tag, discarding
475 # document headers
475 # document headers
476 _data = None
476 _data = None
477
477
478 @property
478 @property
479 def data(self):
479 def data(self):
480 return self._data
480 return self._data
481
481
482 @data.setter
482 @data.setter
483 def data(self, svg):
483 def data(self, svg):
484 if svg is None:
484 if svg is None:
485 self._data = None
485 self._data = None
486 return
486 return
487 # parse into dom object
487 # parse into dom object
488 from xml.dom import minidom
488 from xml.dom import minidom
489 svg = cast_bytes_py2(svg)
489 svg = cast_bytes_py2(svg)
490 x = minidom.parseString(svg)
490 x = minidom.parseString(svg)
491 # get svg tag (should be 1)
491 # get svg tag (should be 1)
492 found_svg = x.getElementsByTagName('svg')
492 found_svg = x.getElementsByTagName('svg')
493 if found_svg:
493 if found_svg:
494 svg = found_svg[0].toxml()
494 svg = found_svg[0].toxml()
495 else:
495 else:
496 # fallback on the input, trust the user
496 # fallback on the input, trust the user
497 # but this is probably an error.
497 # but this is probably an error.
498 pass
498 pass
499 svg = cast_unicode(svg)
499 svg = cast_unicode(svg)
500 self._data = svg
500 self._data = svg
501
501
502 def _repr_svg_(self):
502 def _repr_svg_(self):
503 return self.data
503 return self.data
504
504
505
505
506 class JSON(DisplayObject):
506 class JSON(DisplayObject):
507 """JSON expects a JSON-able dict or list
507 """JSON expects a JSON-able dict or list
508
508
509 not an already-serialized JSON string.
509 not an already-serialized JSON string.
510
510
511 Scalar types (None, number, string) are not allowed, only dict or list containers.
511 Scalar types (None, number, string) are not allowed, only dict or list containers.
512 """
512 """
513 # wrap data in a property, which warns about passing already-serialized JSON
513 # wrap data in a property, which warns about passing already-serialized JSON
514 _data = None
514 _data = None
515 def _check_data(self):
515 def _check_data(self):
516 if self.data is not None and not isinstance(self.data, (dict, list)):
516 if self.data is not None and not isinstance(self.data, (dict, list)):
517 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
517 raise TypeError("%s expects JSONable dict or list, not %r" % (self.__class__.__name__, self.data))
518
518
519 @property
519 @property
520 def data(self):
520 def data(self):
521 return self._data
521 return self._data
522
522
523 @data.setter
523 @data.setter
524 def data(self, data):
524 def data(self, data):
525 if isinstance(data, string_types):
525 if isinstance(data, string_types):
526 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
526 warnings.warn("JSON expects JSONable dict or list, not JSON strings")
527 data = json.loads(data)
527 data = json.loads(data)
528 self._data = data
528 self._data = data
529
529
530 def _repr_json_(self):
530 def _repr_json_(self):
531 return self.data
531 return self.data
532
532
533 css_t = """$("head").append($("<link/>").attr({
533 css_t = """$("head").append($("<link/>").attr({
534 rel: "stylesheet",
534 rel: "stylesheet",
535 type: "text/css",
535 type: "text/css",
536 href: "%s"
536 href: "%s"
537 }));
537 }));
538 """
538 """
539
539
540 lib_t1 = """$.getScript("%s", function () {
540 lib_t1 = """$.getScript("%s", function () {
541 """
541 """
542 lib_t2 = """});
542 lib_t2 = """});
543 """
543 """
544
544
545 class Javascript(TextDisplayObject):
545 class Javascript(TextDisplayObject):
546
546
547 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
547 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
548 """Create a Javascript display object given raw data.
548 """Create a Javascript display object given raw data.
549
549
550 When this object is returned by an expression or passed to the
550 When this object is returned by an expression or passed to the
551 display function, it will result in the data being displayed
551 display function, it will result in the data being displayed
552 in the frontend. If the data is a URL, the data will first be
552 in the frontend. If the data is a URL, the data will first be
553 downloaded and then displayed.
553 downloaded and then displayed.
554
554
555 In the Notebook, the containing element will be available as `element`,
555 In the Notebook, the containing element will be available as `element`,
556 and jQuery will be available. Content appended to `element` will be
556 and jQuery will be available. Content appended to `element` will be
557 visible in the output area.
557 visible in the output area.
558
558
559 Parameters
559 Parameters
560 ----------
560 ----------
561 data : unicode, str or bytes
561 data : unicode, str or bytes
562 The Javascript source code or a URL to download it from.
562 The Javascript source code or a URL to download it from.
563 url : unicode
563 url : unicode
564 A URL to download the data from.
564 A URL to download the data from.
565 filename : unicode
565 filename : unicode
566 Path to a local file to load the data from.
566 Path to a local file to load the data from.
567 lib : list or str
567 lib : list or str
568 A sequence of Javascript library URLs to load asynchronously before
568 A sequence of Javascript library URLs to load asynchronously before
569 running the source code. The full URLs of the libraries should
569 running the source code. The full URLs of the libraries should
570 be given. A single Javascript library URL can also be given as a
570 be given. A single Javascript library URL can also be given as a
571 string.
571 string.
572 css: : list or str
572 css: : list or str
573 A sequence of css files to load before running the source code.
573 A sequence of css files to load before running the source code.
574 The full URLs of the css files should be given. A single css URL
574 The full URLs of the css files should be given. A single css URL
575 can also be given as a string.
575 can also be given as a string.
576 """
576 """
577 if isinstance(lib, string_types):
577 if isinstance(lib, string_types):
578 lib = [lib]
578 lib = [lib]
579 elif lib is None:
579 elif lib is None:
580 lib = []
580 lib = []
581 if isinstance(css, string_types):
581 if isinstance(css, string_types):
582 css = [css]
582 css = [css]
583 elif css is None:
583 elif css is None:
584 css = []
584 css = []
585 if not isinstance(lib, (list,tuple)):
585 if not isinstance(lib, (list,tuple)):
586 raise TypeError('expected sequence, got: %r' % lib)
586 raise TypeError('expected sequence, got: %r' % lib)
587 if not isinstance(css, (list,tuple)):
587 if not isinstance(css, (list,tuple)):
588 raise TypeError('expected sequence, got: %r' % css)
588 raise TypeError('expected sequence, got: %r' % css)
589 self.lib = lib
589 self.lib = lib
590 self.css = css
590 self.css = css
591 super(Javascript, self).__init__(data=data, url=url, filename=filename)
591 super(Javascript, self).__init__(data=data, url=url, filename=filename)
592
592
593 def _repr_javascript_(self):
593 def _repr_javascript_(self):
594 r = ''
594 r = ''
595 for c in self.css:
595 for c in self.css:
596 r += css_t % c
596 r += css_t % c
597 for l in self.lib:
597 for l in self.lib:
598 r += lib_t1 % l
598 r += lib_t1 % l
599 r += self.data
599 r += self.data
600 r += lib_t2*len(self.lib)
600 r += lib_t2*len(self.lib)
601 return r
601 return r
602
602
603 # constants for identifying png/jpeg data
603 # constants for identifying png/jpeg data
604 _PNG = b'\x89PNG\r\n\x1a\n'
604 _PNG = b'\x89PNG\r\n\x1a\n'
605 _JPEG = b'\xff\xd8'
605 _JPEG = b'\xff\xd8'
606
606
607 def _pngxy(data):
607 def _pngxy(data):
608 """read the (width, height) from a PNG header"""
608 """read the (width, height) from a PNG header"""
609 ihdr = data.index(b'IHDR')
609 ihdr = data.index(b'IHDR')
610 # next 8 bytes are width/height
610 # next 8 bytes are width/height
611 w4h4 = data[ihdr+4:ihdr+12]
611 w4h4 = data[ihdr+4:ihdr+12]
612 return struct.unpack('>ii', w4h4)
612 return struct.unpack('>ii', w4h4)
613
613
614 def _jpegxy(data):
614 def _jpegxy(data):
615 """read the (width, height) from a JPEG header"""
615 """read the (width, height) from a JPEG header"""
616 # adapted from http://www.64lines.com/jpeg-width-height
616 # adapted from http://www.64lines.com/jpeg-width-height
617
617
618 idx = 4
618 idx = 4
619 while True:
619 while True:
620 block_size = struct.unpack('>H', data[idx:idx+2])[0]
620 block_size = struct.unpack('>H', data[idx:idx+2])[0]
621 idx = idx + block_size
621 idx = idx + block_size
622 if data[idx:idx+2] == b'\xFF\xC0':
622 if data[idx:idx+2] == b'\xFF\xC0':
623 # found Start of Frame
623 # found Start of Frame
624 iSOF = idx
624 iSOF = idx
625 break
625 break
626 else:
626 else:
627 # read another block
627 # read another block
628 idx += 2
628 idx += 2
629
629
630 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
630 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
631 return w, h
631 return w, h
632
632
633 class Image(DisplayObject):
633 class Image(DisplayObject):
634
634
635 _read_flags = 'rb'
635 _read_flags = 'rb'
636 _FMT_JPEG = u'jpeg'
636 _FMT_JPEG = u'jpeg'
637 _FMT_PNG = u'png'
637 _FMT_PNG = u'png'
638 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
638 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
639
639
640 def __init__(self, data=None, url=None, filename=None, format=u'png',
640 def __init__(self, data=None, url=None, filename=None, format=u'png',
641 embed=None, width=None, height=None, retina=False,
641 embed=None, width=None, height=None, retina=False,
642 unconfined=False, metadata=None):
642 unconfined=False, metadata=None):
643 """Create a PNG/JPEG image object given raw data.
643 """Create a PNG/JPEG image object given raw data.
644
644
645 When this object is returned by an input cell or passed to the
645 When this object is returned by an input cell or passed to the
646 display function, it will result in the image being displayed
646 display function, it will result in the image being displayed
647 in the frontend.
647 in the frontend.
648
648
649 Parameters
649 Parameters
650 ----------
650 ----------
651 data : unicode, str or bytes
651 data : unicode, str or bytes
652 The raw image data or a URL or filename to load the data from.
652 The raw image data or a URL or filename to load the data from.
653 This always results in embedded image data.
653 This always results in embedded image data.
654 url : unicode
654 url : unicode
655 A URL to download the data from. If you specify `url=`,
655 A URL to download the data from. If you specify `url=`,
656 the image data will not be embedded unless you also specify `embed=True`.
656 the image data will not be embedded unless you also specify `embed=True`.
657 filename : unicode
657 filename : unicode
658 Path to a local file to load the data from.
658 Path to a local file to load the data from.
659 Images from a file are always embedded.
659 Images from a file are always embedded.
660 format : unicode
660 format : unicode
661 The format of the image data (png/jpeg/jpg). If a filename or URL is given
661 The format of the image data (png/jpeg/jpg). If a filename or URL is given
662 for format will be inferred from the filename extension.
662 for format will be inferred from the filename extension.
663 embed : bool
663 embed : bool
664 Should the image data be embedded using a data URI (True) or be
664 Should the image data be embedded using a data URI (True) or be
665 loaded using an <img> tag. Set this to True if you want the image
665 loaded using an <img> tag. Set this to True if you want the image
666 to be viewable later with no internet connection in the notebook.
666 to be viewable later with no internet connection in the notebook.
667
667
668 Default is `True`, unless the keyword argument `url` is set, then
668 Default is `True`, unless the keyword argument `url` is set, then
669 default value is `False`.
669 default value is `False`.
670
670
671 Note that QtConsole is not able to display images if `embed` is set to `False`
671 Note that QtConsole is not able to display images if `embed` is set to `False`
672 width : int
672 width : int
673 Width to which to constrain the image in html
673 Width to which to constrain the image in html
674 height : int
674 height : int
675 Height to which to constrain the image in html
675 Height to which to constrain the image in html
676 retina : bool
676 retina : bool
677 Automatically set the width and height to half of the measured
677 Automatically set the width and height to half of the measured
678 width and height.
678 width and height.
679 This only works for embedded images because it reads the width/height
679 This only works for embedded images because it reads the width/height
680 from image data.
680 from image data.
681 For non-embedded images, you can just set the desired display width
681 For non-embedded images, you can just set the desired display width
682 and height directly.
682 and height directly.
683 unconfined: bool
683 unconfined: bool
684 Set unconfined=True to disable max-width confinement of the image.
684 Set unconfined=True to disable max-width confinement of the image.
685 metadata: dict
685 metadata: dict
686 Specify extra metadata to attach to the image.
686 Specify extra metadata to attach to the image.
687
687
688 Examples
688 Examples
689 --------
689 --------
690 # embedded image data, works in qtconsole and notebook
690 # embedded image data, works in qtconsole and notebook
691 # when passed positionally, the first arg can be any of raw image data,
691 # when passed positionally, the first arg can be any of raw image data,
692 # a URL, or a filename from which to load image data.
692 # a URL, or a filename from which to load image data.
693 # The result is always embedding image data for inline images.
693 # The result is always embedding image data for inline images.
694 Image('http://www.google.fr/images/srpr/logo3w.png')
694 Image('http://www.google.fr/images/srpr/logo3w.png')
695 Image('/path/to/image.jpg')
695 Image('/path/to/image.jpg')
696 Image(b'RAW_PNG_DATA...')
696 Image(b'RAW_PNG_DATA...')
697
697
698 # Specifying Image(url=...) does not embed the image data,
698 # Specifying Image(url=...) does not embed the image data,
699 # it only generates `<img>` tag with a link to the source.
699 # it only generates `<img>` tag with a link to the source.
700 # This will not work in the qtconsole or offline.
700 # This will not work in the qtconsole or offline.
701 Image(url='http://www.google.fr/images/srpr/logo3w.png')
701 Image(url='http://www.google.fr/images/srpr/logo3w.png')
702
702
703 """
703 """
704 if filename is not None:
704 if filename is not None:
705 ext = self._find_ext(filename)
705 ext = self._find_ext(filename)
706 elif url is not None:
706 elif url is not None:
707 ext = self._find_ext(url)
707 ext = self._find_ext(url)
708 elif data is None:
708 elif data is None:
709 raise ValueError("No image data found. Expecting filename, url, or data.")
709 raise ValueError("No image data found. Expecting filename, url, or data.")
710 elif isinstance(data, string_types) and (
710 elif isinstance(data, string_types) and (
711 data.startswith('http') or _safe_exists(data)
711 data.startswith('http') or _safe_exists(data)
712 ):
712 ):
713 ext = self._find_ext(data)
713 ext = self._find_ext(data)
714 else:
714 else:
715 ext = None
715 ext = None
716
716
717 if ext is not None:
717 if ext is not None:
718 format = ext.lower()
718 format = ext.lower()
719 if ext == u'jpg' or ext == u'jpeg':
719 if ext == u'jpg' or ext == u'jpeg':
720 format = self._FMT_JPEG
720 format = self._FMT_JPEG
721 if ext == u'png':
721 if ext == u'png':
722 format = self._FMT_PNG
722 format = self._FMT_PNG
723 elif isinstance(data, bytes) and format == 'png':
723 elif isinstance(data, bytes) and format == 'png':
724 # infer image type from image data header,
724 # infer image type from image data header,
725 # only if format might not have been specified.
725 # only if format might not have been specified.
726 if data[:2] == _JPEG:
726 if data[:2] == _JPEG:
727 format = 'jpeg'
727 format = 'jpeg'
728
728
729 self.format = unicode_type(format).lower()
729 self.format = unicode_type(format).lower()
730 self.embed = embed if embed is not None else (url is None)
730 self.embed = embed if embed is not None else (url is None)
731
731
732 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
732 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
733 raise ValueError("Cannot embed the '%s' image format" % (self.format))
733 raise ValueError("Cannot embed the '%s' image format" % (self.format))
734 self.width = width
734 self.width = width
735 self.height = height
735 self.height = height
736 self.retina = retina
736 self.retina = retina
737 self.unconfined = unconfined
737 self.unconfined = unconfined
738 self.metadata = metadata
738 self.metadata = metadata
739 super(Image, self).__init__(data=data, url=url, filename=filename)
739 super(Image, self).__init__(data=data, url=url, filename=filename)
740
740
741 if retina:
741 if retina:
742 self._retina_shape()
742 self._retina_shape()
743
743
744 def _retina_shape(self):
744 def _retina_shape(self):
745 """load pixel-doubled width and height from image data"""
745 """load pixel-doubled width and height from image data"""
746 if not self.embed:
746 if not self.embed:
747 return
747 return
748 if self.format == 'png':
748 if self.format == 'png':
749 w, h = _pngxy(self.data)
749 w, h = _pngxy(self.data)
750 elif self.format == 'jpeg':
750 elif self.format == 'jpeg':
751 w, h = _jpegxy(self.data)
751 w, h = _jpegxy(self.data)
752 else:
752 else:
753 # retina only supports png
753 # retina only supports png
754 return
754 return
755 self.width = w // 2
755 self.width = w // 2
756 self.height = h // 2
756 self.height = h // 2
757
757
758 def reload(self):
758 def reload(self):
759 """Reload the raw data from file or URL."""
759 """Reload the raw data from file or URL."""
760 if self.embed:
760 if self.embed:
761 super(Image,self).reload()
761 super(Image,self).reload()
762 if self.retina:
762 if self.retina:
763 self._retina_shape()
763 self._retina_shape()
764
764
765 def _repr_html_(self):
765 def _repr_html_(self):
766 if not self.embed:
766 if not self.embed:
767 width = height = klass = ''
767 width = height = klass = ''
768 if self.width:
768 if self.width:
769 width = ' width="%d"' % self.width
769 width = ' width="%d"' % self.width
770 if self.height:
770 if self.height:
771 height = ' height="%d"' % self.height
771 height = ' height="%d"' % self.height
772 if self.unconfined:
772 if self.unconfined:
773 klass = ' class="unconfined"'
773 klass = ' class="unconfined"'
774 return u'<img src="{url}"{width}{height}{klass}/>'.format(
774 return u'<img src="{url}"{width}{height}{klass}/>'.format(
775 url=self.url,
775 url=self.url,
776 width=width,
776 width=width,
777 height=height,
777 height=height,
778 klass=klass,
778 klass=klass,
779 )
779 )
780
780
781 def _data_and_metadata(self):
781 def _data_and_metadata(self):
782 """shortcut for returning metadata with shape information, if defined"""
782 """shortcut for returning metadata with shape information, if defined"""
783 md = {}
783 md = {}
784 if self.width:
784 if self.width:
785 md['width'] = self.width
785 md['width'] = self.width
786 if self.height:
786 if self.height:
787 md['height'] = self.height
787 md['height'] = self.height
788 if self.unconfined:
788 if self.unconfined:
789 md['unconfined'] = self.unconfined
789 md['unconfined'] = self.unconfined
790 if self.metadata:
790 if self.metadata:
791 md.update(self.metadata)
791 md.update(self.metadata)
792 if md:
792 if md:
793 return self.data, md
793 return self.data, md
794 else:
794 else:
795 return self.data
795 return self.data
796
796
797 def _repr_png_(self):
797 def _repr_png_(self):
798 if self.embed and self.format == u'png':
798 if self.embed and self.format == u'png':
799 return self._data_and_metadata()
799 return self._data_and_metadata()
800
800
801 def _repr_jpeg_(self):
801 def _repr_jpeg_(self):
802 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
802 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
803 return self._data_and_metadata()
803 return self._data_and_metadata()
804
804
805 def _find_ext(self, s):
805 def _find_ext(self, s):
806 return unicode_type(s.split('.')[-1].lower())
806 return unicode_type(s.split('.')[-1].lower())
807
807
808 class Video(DisplayObject):
808 class Video(DisplayObject):
809
809
810 def __init__(self, data=None, url=None, filename=None, embed=None, mimetype=None):
810 def __init__(self, data=None, url=None, filename=None, embed=None, mimetype=None):
811 """Create a video object given raw data or an URL.
811 """Create a video object given raw data or an URL.
812
812
813 When this object is returned by an input cell or passed to the
813 When this object is returned by an input cell or passed to the
814 display function, it will result in the video being displayed
814 display function, it will result in the video being displayed
815 in the frontend.
815 in the frontend.
816
816
817 Parameters
817 Parameters
818 ----------
818 ----------
819 data : unicode, str or bytes
819 data : unicode, str or bytes
820 The raw image data or a URL or filename to load the data from.
820 The raw image data or a URL or filename to load the data from.
821 This always results in embedded image data.
821 This always results in embedded image data.
822 url : unicode
822 url : unicode
823 A URL to download the data from. If you specify `url=`,
823 A URL to download the data from. If you specify `url=`,
824 the image data will not be embedded unless you also specify `embed=True`.
824 the image data will not be embedded unless you also specify `embed=True`.
825 filename : unicode
825 filename : unicode
826 Path to a local file to load the data from.
826 Path to a local file to load the data from.
827 Videos from a file are always embedded.
827 Videos from a file are always embedded.
828 embed : bool
828 embed : bool
829 Should the image data be embedded using a data URI (True) or be
829 Should the image data be embedded using a data URI (True) or be
830 loaded using an <img> tag. Set this to True if you want the image
830 loaded using an <img> tag. Set this to True if you want the image
831 to be viewable later with no internet connection in the notebook.
831 to be viewable later with no internet connection in the notebook.
832
832
833 Default is `True`, unless the keyword argument `url` is set, then
833 Default is `True`, unless the keyword argument `url` is set, then
834 default value is `False`.
834 default value is `False`.
835
835
836 Note that QtConsole is not able to display images if `embed` is set to `False`
836 Note that QtConsole is not able to display images if `embed` is set to `False`
837 mimetype: unicode
837 mimetype: unicode
838 Specify the mimetype in case you load in a encoded video.
838 Specify the mimetype in case you load in a encoded video.
839 Examples
839 Examples
840 --------
840 --------
841 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
841 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
842 Video('path/to/video.mp4')
842 Video('path/to/video.mp4')
843 Video('path/to/video.mp4', embed=False)
843 Video('path/to/video.mp4', embed=False)
844 """
844 """
845 if url is None and (data.startswith('http') or data.startswith('https')):
845 if url is None and (data.startswith('http') or data.startswith('https')):
846 url = data
846 url = data
847 data = None
847 data = None
848 embed = False
848 embed = False
849 elif os.path.exists(data):
849 elif os.path.exists(data):
850 filename = data
850 filename = data
851 data = None
851 data = None
852
852
853 self.mimetype = mimetype
853 self.mimetype = mimetype
854 self.embed = embed if embed is not None else (filename is not None)
854 self.embed = embed if embed is not None else (filename is not None)
855 super(Video, self).__init__(data=data, url=url, filename=filename)
855 super(Video, self).__init__(data=data, url=url, filename=filename)
856
856
857 def _repr_html_(self):
857 def _repr_html_(self):
858 # External URLs and potentially local files are not embedded into the
858 # External URLs and potentially local files are not embedded into the
859 # notebook output.
859 # notebook output.
860 if not self.embed:
860 if not self.embed:
861 url = self.url if self.url is not None else self.filename
861 url = self.url if self.url is not None else self.filename
862 output = """<video src="{0}" controls>
862 output = """<video src="{0}" controls>
863 Your browser does not support the <code>video</code> element.
863 Your browser does not support the <code>video</code> element.
864 </video>""".format(url)
864 </video>""".format(url)
865 return output
865 return output
866 # Embedded videos uses base64 encoded videos.
866 # Embedded videos uses base64 encoded videos.
867 if self.filename is not None:
867 if self.filename is not None:
868 mimetypes.init()
868 mimetypes.init()
869 mimetype, encoding = mimetypes.guess_type(self.filename)
869 mimetype, encoding = mimetypes.guess_type(self.filename)
870
870
871 video = open(self.filename, 'rb').read()
871 video = open(self.filename, 'rb').read()
872 video_encoded = video.encode('base64')
872 video_encoded = video.encode('base64')
873 else:
873 else:
874 video_encoded = self.data
874 video_encoded = self.data
875 mimetype = self.mimetype
875 mimetype = self.mimetype
876 output = """<video controls>
876 output = """<video controls>
877 <source src="data:{0};base64,{1}" type="{0}">
877 <source src="data:{0};base64,{1}" type="{0}">
878 Your browser does not support the video tag.
878 Your browser does not support the video tag.
879 </video>""".format(mimetype, video_encoded)
879 </video>""".format(mimetype, video_encoded)
880 return output
880 return output
881
881
882 def reload(self):
882 def reload(self):
883 # TODO
883 # TODO
884 pass
884 pass
885
885
886 def _repr_png_(self):
886 def _repr_png_(self):
887 # TODO
887 # TODO
888 pass
888 pass
889 def _repr_jpeg_(self):
889 def _repr_jpeg_(self):
890 # TODO
890 # TODO
891 pass
891 pass
892
892
893 def clear_output(wait=False):
893 def clear_output(wait=False):
894 """Clear the output of the current cell receiving output.
894 """Clear the output of the current cell receiving output.
895
895
896 Parameters
896 Parameters
897 ----------
897 ----------
898 wait : bool [default: false]
898 wait : bool [default: false]
899 Wait to clear the output until new output is available to replace it."""
899 Wait to clear the output until new output is available to replace it."""
900 from IPython.core.interactiveshell import InteractiveShell
900 from IPython.core.interactiveshell import InteractiveShell
901 if InteractiveShell.initialized():
901 if InteractiveShell.initialized():
902 InteractiveShell.instance().display_pub.clear_output(wait)
902 InteractiveShell.instance().display_pub.clear_output(wait)
903 else:
903 else:
904 from IPython.utils import io
904 from IPython.utils import io
905 print('\033[2K\r', file=io.stdout, end='')
905 print('\033[2K\r', file=io.stdout, end='')
906 io.stdout.flush()
906 io.stdout.flush()
907 print('\033[2K\r', file=io.stderr, end='')
907 print('\033[2K\r', file=io.stderr, end='')
908 io.stderr.flush()
908 io.stderr.flush()
909
909
910
910
911 @skip_doctest
911 @skip_doctest
912 def set_matplotlib_formats(*formats, **kwargs):
912 def set_matplotlib_formats(*formats, **kwargs):
913 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
913 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
914
914
915 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
915 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
916
916
917 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
917 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
918
918
919 To set this in your config files use the following::
919 To set this in your config files use the following::
920
920
921 c.InlineBackend.figure_formats = {'png', 'jpeg'}
921 c.InlineBackend.figure_formats = {'png', 'jpeg'}
922 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
922 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
923
923
924 Parameters
924 Parameters
925 ----------
925 ----------
926 *formats : strs
926 *formats : strs
927 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
927 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
928 **kwargs :
928 **kwargs :
929 Keyword args will be relayed to ``figure.canvas.print_figure``.
929 Keyword args will be relayed to ``figure.canvas.print_figure``.
930 """
930 """
931 from IPython.core.interactiveshell import InteractiveShell
931 from IPython.core.interactiveshell import InteractiveShell
932 from IPython.core.pylabtools import select_figure_formats
932 from IPython.core.pylabtools import select_figure_formats
933 # build kwargs, starting with InlineBackend config
933 # build kwargs, starting with InlineBackend config
934 kw = {}
934 kw = {}
935 from ipython_kernel.pylab.config import InlineBackend
935 from ipykernel.pylab.config import InlineBackend
936 cfg = InlineBackend.instance()
936 cfg = InlineBackend.instance()
937 kw.update(cfg.print_figure_kwargs)
937 kw.update(cfg.print_figure_kwargs)
938 kw.update(**kwargs)
938 kw.update(**kwargs)
939 shell = InteractiveShell.instance()
939 shell = InteractiveShell.instance()
940 select_figure_formats(shell, formats, **kw)
940 select_figure_formats(shell, formats, **kw)
941
941
942 @skip_doctest
942 @skip_doctest
943 def set_matplotlib_close(close=True):
943 def set_matplotlib_close(close=True):
944 """Set whether the inline backend closes all figures automatically or not.
944 """Set whether the inline backend closes all figures automatically or not.
945
945
946 By default, the inline backend used in the IPython Notebook will close all
946 By default, the inline backend used in the IPython Notebook will close all
947 matplotlib figures automatically after each cell is run. This means that
947 matplotlib figures automatically after each cell is run. This means that
948 plots in different cells won't interfere. Sometimes, you may want to make
948 plots in different cells won't interfere. Sometimes, you may want to make
949 a plot in one cell and then refine it in later cells. This can be accomplished
949 a plot in one cell and then refine it in later cells. This can be accomplished
950 by::
950 by::
951
951
952 In [1]: set_matplotlib_close(False)
952 In [1]: set_matplotlib_close(False)
953
953
954 To set this in your config files use the following::
954 To set this in your config files use the following::
955
955
956 c.InlineBackend.close_figures = False
956 c.InlineBackend.close_figures = False
957
957
958 Parameters
958 Parameters
959 ----------
959 ----------
960 close : bool
960 close : bool
961 Should all matplotlib figures be automatically closed after each cell is
961 Should all matplotlib figures be automatically closed after each cell is
962 run?
962 run?
963 """
963 """
964 from ipython_kernel.pylab.config import InlineBackend
964 from ipykernel.pylab.config import InlineBackend
965 cfg = InlineBackend.instance()
965 cfg = InlineBackend.instance()
966 cfg.close_figures = close
966 cfg.close_figures = close
967
967
@@ -1,311 +1,311 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython profiles.
3 An application for managing IPython profiles.
4
4
5 To be invoked as the `ipython profile` subcommand.
5 To be invoked as the `ipython profile` subcommand.
6
6
7 Authors:
7 Authors:
8
8
9 * Min RK
9 * Min RK
10
10
11 """
11 """
12 from __future__ import print_function
12 from __future__ import print_function
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 import os
25 import os
26
26
27 from traitlets.config.application import Application
27 from traitlets.config.application import Application
28 from IPython.core.application import (
28 from IPython.core.application import (
29 BaseIPythonApplication, base_flags
29 BaseIPythonApplication, base_flags
30 )
30 )
31 from IPython.core.profiledir import ProfileDir
31 from IPython.core.profiledir import ProfileDir
32 from IPython.utils.importstring import import_item
32 from IPython.utils.importstring import import_item
33 from IPython.paths import get_ipython_dir, get_ipython_package_dir
33 from IPython.paths import get_ipython_dir, get_ipython_package_dir
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from traitlets import Unicode, Bool, Dict
35 from traitlets import Unicode, Bool, Dict
36
36
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38 # Constants
38 # Constants
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40
40
41 create_help = """Create an IPython profile by name
41 create_help = """Create an IPython profile by name
42
42
43 Create an ipython profile directory by its name or
43 Create an ipython profile directory by its name or
44 profile directory path. Profile directories contain
44 profile directory path. Profile directories contain
45 configuration, log and security related files and are named
45 configuration, log and security related files and are named
46 using the convention 'profile_<name>'. By default they are
46 using the convention 'profile_<name>'. By default they are
47 located in your ipython directory. Once created, you will
47 located in your ipython directory. Once created, you will
48 can edit the configuration files in the profile
48 can edit the configuration files in the profile
49 directory to configure IPython. Most users will create a
49 directory to configure IPython. Most users will create a
50 profile directory by name,
50 profile directory by name,
51 `ipython profile create myprofile`, which will put the directory
51 `ipython profile create myprofile`, which will put the directory
52 in `<ipython_dir>/profile_myprofile`.
52 in `<ipython_dir>/profile_myprofile`.
53 """
53 """
54 list_help = """List available IPython profiles
54 list_help = """List available IPython profiles
55
55
56 List all available profiles, by profile location, that can
56 List all available profiles, by profile location, that can
57 be found in the current working directly or in the ipython
57 be found in the current working directly or in the ipython
58 directory. Profile directories are named using the convention
58 directory. Profile directories are named using the convention
59 'profile_<profile>'.
59 'profile_<profile>'.
60 """
60 """
61 profile_help = """Manage IPython profiles
61 profile_help = """Manage IPython profiles
62
62
63 Profile directories contain
63 Profile directories contain
64 configuration, log and security related files and are named
64 configuration, log and security related files and are named
65 using the convention 'profile_<name>'. By default they are
65 using the convention 'profile_<name>'. By default they are
66 located in your ipython directory. You can create profiles
66 located in your ipython directory. You can create profiles
67 with `ipython profile create <name>`, or see the profiles you
67 with `ipython profile create <name>`, or see the profiles you
68 already have with `ipython profile list`
68 already have with `ipython profile list`
69
69
70 To get started configuring IPython, simply do:
70 To get started configuring IPython, simply do:
71
71
72 $> ipython profile create
72 $> ipython profile create
73
73
74 and IPython will create the default profile in <ipython_dir>/profile_default,
74 and IPython will create the default profile in <ipython_dir>/profile_default,
75 where you can edit ipython_config.py to start configuring IPython.
75 where you can edit ipython_config.py to start configuring IPython.
76
76
77 """
77 """
78
78
79 _list_examples = "ipython profile list # list all profiles"
79 _list_examples = "ipython profile list # list all profiles"
80
80
81 _create_examples = """
81 _create_examples = """
82 ipython profile create foo # create profile foo w/ default config files
82 ipython profile create foo # create profile foo w/ default config files
83 ipython profile create foo --reset # restage default config files over current
83 ipython profile create foo --reset # restage default config files over current
84 ipython profile create foo --parallel # also stage parallel config files
84 ipython profile create foo --parallel # also stage parallel config files
85 """
85 """
86
86
87 _main_examples = """
87 _main_examples = """
88 ipython profile create -h # show the help string for the create subcommand
88 ipython profile create -h # show the help string for the create subcommand
89 ipython profile list -h # show the help string for the list subcommand
89 ipython profile list -h # show the help string for the list subcommand
90
90
91 ipython locate profile foo # print the path to the directory for profile 'foo'
91 ipython locate profile foo # print the path to the directory for profile 'foo'
92 """
92 """
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Profile Application Class (for `ipython profile` subcommand)
95 # Profile Application Class (for `ipython profile` subcommand)
96 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
97
97
98
98
99 def list_profiles_in(path):
99 def list_profiles_in(path):
100 """list profiles in a given root directory"""
100 """list profiles in a given root directory"""
101 files = os.listdir(path)
101 files = os.listdir(path)
102 profiles = []
102 profiles = []
103 for f in files:
103 for f in files:
104 try:
104 try:
105 full_path = os.path.join(path, f)
105 full_path = os.path.join(path, f)
106 except UnicodeError:
106 except UnicodeError:
107 continue
107 continue
108 if os.path.isdir(full_path) and f.startswith('profile_'):
108 if os.path.isdir(full_path) and f.startswith('profile_'):
109 profiles.append(f.split('_',1)[-1])
109 profiles.append(f.split('_',1)[-1])
110 return profiles
110 return profiles
111
111
112
112
113 def list_bundled_profiles():
113 def list_bundled_profiles():
114 """list profiles that are bundled with IPython."""
114 """list profiles that are bundled with IPython."""
115 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
115 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
116 files = os.listdir(path)
116 files = os.listdir(path)
117 profiles = []
117 profiles = []
118 for profile in files:
118 for profile in files:
119 full_path = os.path.join(path, profile)
119 full_path = os.path.join(path, profile)
120 if os.path.isdir(full_path) and profile != "__pycache__":
120 if os.path.isdir(full_path) and profile != "__pycache__":
121 profiles.append(profile)
121 profiles.append(profile)
122 return profiles
122 return profiles
123
123
124
124
125 class ProfileLocate(BaseIPythonApplication):
125 class ProfileLocate(BaseIPythonApplication):
126 description = """print the path to an IPython profile dir"""
126 description = """print the path to an IPython profile dir"""
127
127
128 def parse_command_line(self, argv=None):
128 def parse_command_line(self, argv=None):
129 super(ProfileLocate, self).parse_command_line(argv)
129 super(ProfileLocate, self).parse_command_line(argv)
130 if self.extra_args:
130 if self.extra_args:
131 self.profile = self.extra_args[0]
131 self.profile = self.extra_args[0]
132
132
133 def start(self):
133 def start(self):
134 print(self.profile_dir.location)
134 print(self.profile_dir.location)
135
135
136
136
137 class ProfileList(Application):
137 class ProfileList(Application):
138 name = u'ipython-profile'
138 name = u'ipython-profile'
139 description = list_help
139 description = list_help
140 examples = _list_examples
140 examples = _list_examples
141
141
142 aliases = Dict({
142 aliases = Dict({
143 'ipython-dir' : 'ProfileList.ipython_dir',
143 'ipython-dir' : 'ProfileList.ipython_dir',
144 'log-level' : 'Application.log_level',
144 'log-level' : 'Application.log_level',
145 })
145 })
146 flags = Dict(dict(
146 flags = Dict(dict(
147 debug = ({'Application' : {'log_level' : 0}},
147 debug = ({'Application' : {'log_level' : 0}},
148 "Set Application.log_level to 0, maximizing log output."
148 "Set Application.log_level to 0, maximizing log output."
149 )
149 )
150 ))
150 ))
151
151
152 ipython_dir = Unicode(get_ipython_dir(), config=True,
152 ipython_dir = Unicode(get_ipython_dir(), config=True,
153 help="""
153 help="""
154 The name of the IPython directory. This directory is used for logging
154 The name of the IPython directory. This directory is used for logging
155 configuration (through profiles), history storage, etc. The default
155 configuration (through profiles), history storage, etc. The default
156 is usually $HOME/.ipython. This options can also be specified through
156 is usually $HOME/.ipython. This options can also be specified through
157 the environment variable IPYTHONDIR.
157 the environment variable IPYTHONDIR.
158 """
158 """
159 )
159 )
160
160
161
161
162 def _print_profiles(self, profiles):
162 def _print_profiles(self, profiles):
163 """print list of profiles, indented."""
163 """print list of profiles, indented."""
164 for profile in profiles:
164 for profile in profiles:
165 print(' %s' % profile)
165 print(' %s' % profile)
166
166
167 def list_profile_dirs(self):
167 def list_profile_dirs(self):
168 profiles = list_bundled_profiles()
168 profiles = list_bundled_profiles()
169 if profiles:
169 if profiles:
170 print()
170 print()
171 print("Available profiles in IPython:")
171 print("Available profiles in IPython:")
172 self._print_profiles(profiles)
172 self._print_profiles(profiles)
173 print()
173 print()
174 print(" The first request for a bundled profile will copy it")
174 print(" The first request for a bundled profile will copy it")
175 print(" into your IPython directory (%s)," % self.ipython_dir)
175 print(" into your IPython directory (%s)," % self.ipython_dir)
176 print(" where you can customize it.")
176 print(" where you can customize it.")
177
177
178 profiles = list_profiles_in(self.ipython_dir)
178 profiles = list_profiles_in(self.ipython_dir)
179 if profiles:
179 if profiles:
180 print()
180 print()
181 print("Available profiles in %s:" % self.ipython_dir)
181 print("Available profiles in %s:" % self.ipython_dir)
182 self._print_profiles(profiles)
182 self._print_profiles(profiles)
183
183
184 profiles = list_profiles_in(py3compat.getcwd())
184 profiles = list_profiles_in(py3compat.getcwd())
185 if profiles:
185 if profiles:
186 print()
186 print()
187 print("Available profiles in current directory (%s):" % py3compat.getcwd())
187 print("Available profiles in current directory (%s):" % py3compat.getcwd())
188 self._print_profiles(profiles)
188 self._print_profiles(profiles)
189
189
190 print()
190 print()
191 print("To use any of the above profiles, start IPython with:")
191 print("To use any of the above profiles, start IPython with:")
192 print(" ipython --profile=<name>")
192 print(" ipython --profile=<name>")
193 print()
193 print()
194
194
195 def start(self):
195 def start(self):
196 self.list_profile_dirs()
196 self.list_profile_dirs()
197
197
198
198
199 create_flags = {}
199 create_flags = {}
200 create_flags.update(base_flags)
200 create_flags.update(base_flags)
201 # don't include '--init' flag, which implies running profile create in other apps
201 # don't include '--init' flag, which implies running profile create in other apps
202 create_flags.pop('init')
202 create_flags.pop('init')
203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
204 "reset config files in this profile to the defaults.")
204 "reset config files in this profile to the defaults.")
205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
206 "Include the config files for parallel "
206 "Include the config files for parallel "
207 "computing apps (ipengine, ipcontroller, etc.)")
207 "computing apps (ipengine, ipcontroller, etc.)")
208
208
209
209
210 class ProfileCreate(BaseIPythonApplication):
210 class ProfileCreate(BaseIPythonApplication):
211 name = u'ipython-profile'
211 name = u'ipython-profile'
212 description = create_help
212 description = create_help
213 examples = _create_examples
213 examples = _create_examples
214 auto_create = Bool(True, config=False)
214 auto_create = Bool(True, config=False)
215 def _log_format_default(self):
215 def _log_format_default(self):
216 return "[%(name)s] %(message)s"
216 return "[%(name)s] %(message)s"
217
217
218 def _copy_config_files_default(self):
218 def _copy_config_files_default(self):
219 return True
219 return True
220
220
221 parallel = Bool(False, config=True,
221 parallel = Bool(False, config=True,
222 help="whether to include parallel computing config files")
222 help="whether to include parallel computing config files")
223 def _parallel_changed(self, name, old, new):
223 def _parallel_changed(self, name, old, new):
224 parallel_files = [ 'ipcontroller_config.py',
224 parallel_files = [ 'ipcontroller_config.py',
225 'ipengine_config.py',
225 'ipengine_config.py',
226 'ipcluster_config.py'
226 'ipcluster_config.py'
227 ]
227 ]
228 if new:
228 if new:
229 for cf in parallel_files:
229 for cf in parallel_files:
230 self.config_files.append(cf)
230 self.config_files.append(cf)
231 else:
231 else:
232 for cf in parallel_files:
232 for cf in parallel_files:
233 if cf in self.config_files:
233 if cf in self.config_files:
234 self.config_files.remove(cf)
234 self.config_files.remove(cf)
235
235
236 def parse_command_line(self, argv):
236 def parse_command_line(self, argv):
237 super(ProfileCreate, self).parse_command_line(argv)
237 super(ProfileCreate, self).parse_command_line(argv)
238 # accept positional arg as profile name
238 # accept positional arg as profile name
239 if self.extra_args:
239 if self.extra_args:
240 self.profile = self.extra_args[0]
240 self.profile = self.extra_args[0]
241
241
242 flags = Dict(create_flags)
242 flags = Dict(create_flags)
243
243
244 classes = [ProfileDir]
244 classes = [ProfileDir]
245
245
246 def _import_app(self, app_path):
246 def _import_app(self, app_path):
247 """import an app class"""
247 """import an app class"""
248 app = None
248 app = None
249 name = app_path.rsplit('.', 1)[-1]
249 name = app_path.rsplit('.', 1)[-1]
250 try:
250 try:
251 app = import_item(app_path)
251 app = import_item(app_path)
252 except ImportError:
252 except ImportError:
253 self.log.info("Couldn't import %s, config file will be excluded", name)
253 self.log.info("Couldn't import %s, config file will be excluded", name)
254 except Exception:
254 except Exception:
255 self.log.warn('Unexpected error importing %s', name, exc_info=True)
255 self.log.warn('Unexpected error importing %s', name, exc_info=True)
256 return app
256 return app
257
257
258 def init_config_files(self):
258 def init_config_files(self):
259 super(ProfileCreate, self).init_config_files()
259 super(ProfileCreate, self).init_config_files()
260 # use local imports, since these classes may import from here
260 # use local imports, since these classes may import from here
261 from IPython.terminal.ipapp import TerminalIPythonApp
261 from IPython.terminal.ipapp import TerminalIPythonApp
262 apps = [TerminalIPythonApp]
262 apps = [TerminalIPythonApp]
263 for app_path in (
263 for app_path in (
264 'ipython_kernel.kernelapp.IPKernelApp',
264 'ipykernel.kernelapp.IPKernelApp',
265 ):
265 ):
266 app = self._import_app(app_path)
266 app = self._import_app(app_path)
267 if app is not None:
267 if app is not None:
268 apps.append(app)
268 apps.append(app)
269 if self.parallel:
269 if self.parallel:
270 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
270 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
271 from ipyparallel.apps.ipengineapp import IPEngineApp
271 from ipyparallel.apps.ipengineapp import IPEngineApp
272 from ipyparallel.apps.ipclusterapp import IPClusterStart
272 from ipyparallel.apps.ipclusterapp import IPClusterStart
273 apps.extend([
273 apps.extend([
274 IPControllerApp,
274 IPControllerApp,
275 IPEngineApp,
275 IPEngineApp,
276 IPClusterStart,
276 IPClusterStart,
277 ])
277 ])
278 for App in apps:
278 for App in apps:
279 app = App()
279 app = App()
280 app.config.update(self.config)
280 app.config.update(self.config)
281 app.log = self.log
281 app.log = self.log
282 app.overwrite = self.overwrite
282 app.overwrite = self.overwrite
283 app.copy_config_files=True
283 app.copy_config_files=True
284 app.ipython_dir=self.ipython_dir
284 app.ipython_dir=self.ipython_dir
285 app.profile_dir=self.profile_dir
285 app.profile_dir=self.profile_dir
286 app.init_config_files()
286 app.init_config_files()
287
287
288 def stage_default_config_file(self):
288 def stage_default_config_file(self):
289 pass
289 pass
290
290
291
291
292 class ProfileApp(Application):
292 class ProfileApp(Application):
293 name = u'ipython profile'
293 name = u'ipython profile'
294 description = profile_help
294 description = profile_help
295 examples = _main_examples
295 examples = _main_examples
296
296
297 subcommands = Dict(dict(
297 subcommands = Dict(dict(
298 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
298 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
299 list = (ProfileList, ProfileList.description.splitlines()[0]),
299 list = (ProfileList, ProfileList.description.splitlines()[0]),
300 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
300 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
301 ))
301 ))
302
302
303 def start(self):
303 def start(self):
304 if self.subapp is None:
304 if self.subapp is None:
305 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
305 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
306 print()
306 print()
307 self.print_description()
307 self.print_description()
308 self.print_subcommands()
308 self.print_subcommands()
309 self.exit(1)
309 self.exit(1)
310 else:
310 else:
311 return self.subapp.start()
311 return self.subapp.start()
@@ -1,369 +1,369 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities."""
2 """Pylab (matplotlib) support utilities."""
3 from __future__ import print_function
3 from __future__ import print_function
4
4
5 # Copyright (c) IPython Development Team.
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7
7
8 from io import BytesIO
8 from io import BytesIO
9
9
10 from IPython.core.display import _pngxy
10 from IPython.core.display import _pngxy
11 from IPython.utils.decorators import flag_calls
11 from IPython.utils.decorators import flag_calls
12 from IPython.utils import py3compat
12 from IPython.utils import py3compat
13
13
14 # If user specifies a GUI, that dictates the backend, otherwise we read the
14 # If user specifies a GUI, that dictates the backend, otherwise we read the
15 # user's mpl default from the mpl rc structure
15 # user's mpl default from the mpl rc structure
16 backends = {'tk': 'TkAgg',
16 backends = {'tk': 'TkAgg',
17 'gtk': 'GTKAgg',
17 'gtk': 'GTKAgg',
18 'gtk3': 'GTK3Agg',
18 'gtk3': 'GTK3Agg',
19 'wx': 'WXAgg',
19 'wx': 'WXAgg',
20 'qt': 'Qt4Agg', # qt3 not supported
20 'qt': 'Qt4Agg', # qt3 not supported
21 'qt4': 'Qt4Agg',
21 'qt4': 'Qt4Agg',
22 'qt5': 'Qt5Agg',
22 'qt5': 'Qt5Agg',
23 'osx': 'MacOSX',
23 'osx': 'MacOSX',
24 'nbagg': 'nbAgg',
24 'nbagg': 'nbAgg',
25 'notebook': 'nbAgg',
25 'notebook': 'nbAgg',
26 'inline' : 'module://ipython_kernel.pylab.backend_inline'}
26 'inline' : 'module://ipykernel.pylab.backend_inline'}
27
27
28 # We also need a reverse backends2guis mapping that will properly choose which
28 # We also need a reverse backends2guis mapping that will properly choose which
29 # GUI support to activate based on the desired matplotlib backend. For the
29 # GUI support to activate based on the desired matplotlib backend. For the
30 # most part it's just a reverse of the above dict, but we also need to add a
30 # most part it's just a reverse of the above dict, but we also need to add a
31 # few others that map to the same GUI manually:
31 # few others that map to the same GUI manually:
32 backend2gui = dict(zip(backends.values(), backends.keys()))
32 backend2gui = dict(zip(backends.values(), backends.keys()))
33 # Our tests expect backend2gui to just return 'qt'
33 # Our tests expect backend2gui to just return 'qt'
34 backend2gui['Qt4Agg'] = 'qt'
34 backend2gui['Qt4Agg'] = 'qt'
35 # In the reverse mapping, there are a few extra valid matplotlib backends that
35 # In the reverse mapping, there are a few extra valid matplotlib backends that
36 # map to the same GUI support
36 # map to the same GUI support
37 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
37 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
38 backend2gui['GTK3Cairo'] = 'gtk3'
38 backend2gui['GTK3Cairo'] = 'gtk3'
39 backend2gui['WX'] = 'wx'
39 backend2gui['WX'] = 'wx'
40 backend2gui['CocoaAgg'] = 'osx'
40 backend2gui['CocoaAgg'] = 'osx'
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Matplotlib utilities
43 # Matplotlib utilities
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46
46
47 def getfigs(*fig_nums):
47 def getfigs(*fig_nums):
48 """Get a list of matplotlib figures by figure numbers.
48 """Get a list of matplotlib figures by figure numbers.
49
49
50 If no arguments are given, all available figures are returned. If the
50 If no arguments are given, all available figures are returned. If the
51 argument list contains references to invalid figures, a warning is printed
51 argument list contains references to invalid figures, a warning is printed
52 but the function continues pasting further figures.
52 but the function continues pasting further figures.
53
53
54 Parameters
54 Parameters
55 ----------
55 ----------
56 figs : tuple
56 figs : tuple
57 A tuple of ints giving the figure numbers of the figures to return.
57 A tuple of ints giving the figure numbers of the figures to return.
58 """
58 """
59 from matplotlib._pylab_helpers import Gcf
59 from matplotlib._pylab_helpers import Gcf
60 if not fig_nums:
60 if not fig_nums:
61 fig_managers = Gcf.get_all_fig_managers()
61 fig_managers = Gcf.get_all_fig_managers()
62 return [fm.canvas.figure for fm in fig_managers]
62 return [fm.canvas.figure for fm in fig_managers]
63 else:
63 else:
64 figs = []
64 figs = []
65 for num in fig_nums:
65 for num in fig_nums:
66 f = Gcf.figs.get(num)
66 f = Gcf.figs.get(num)
67 if f is None:
67 if f is None:
68 print('Warning: figure %s not available.' % num)
68 print('Warning: figure %s not available.' % num)
69 else:
69 else:
70 figs.append(f.canvas.figure)
70 figs.append(f.canvas.figure)
71 return figs
71 return figs
72
72
73
73
74 def figsize(sizex, sizey):
74 def figsize(sizex, sizey):
75 """Set the default figure size to be [sizex, sizey].
75 """Set the default figure size to be [sizex, sizey].
76
76
77 This is just an easy to remember, convenience wrapper that sets::
77 This is just an easy to remember, convenience wrapper that sets::
78
78
79 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
79 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
80 """
80 """
81 import matplotlib
81 import matplotlib
82 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
82 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
83
83
84
84
85 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
85 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
86 """Print a figure to an image, and return the resulting file data
86 """Print a figure to an image, and return the resulting file data
87
87
88 Returned data will be bytes unless ``fmt='svg'``,
88 Returned data will be bytes unless ``fmt='svg'``,
89 in which case it will be unicode.
89 in which case it will be unicode.
90
90
91 Any keyword args are passed to fig.canvas.print_figure,
91 Any keyword args are passed to fig.canvas.print_figure,
92 such as ``quality`` or ``bbox_inches``.
92 such as ``quality`` or ``bbox_inches``.
93 """
93 """
94 from matplotlib import rcParams
94 from matplotlib import rcParams
95 # When there's an empty figure, we shouldn't return anything, otherwise we
95 # When there's an empty figure, we shouldn't return anything, otherwise we
96 # get big blank areas in the qt console.
96 # get big blank areas in the qt console.
97 if not fig.axes and not fig.lines:
97 if not fig.axes and not fig.lines:
98 return
98 return
99
99
100 dpi = rcParams['savefig.dpi']
100 dpi = rcParams['savefig.dpi']
101 if fmt == 'retina':
101 if fmt == 'retina':
102 dpi = dpi * 2
102 dpi = dpi * 2
103 fmt = 'png'
103 fmt = 'png'
104
104
105 # build keyword args
105 # build keyword args
106 kw = dict(
106 kw = dict(
107 format=fmt,
107 format=fmt,
108 facecolor=fig.get_facecolor(),
108 facecolor=fig.get_facecolor(),
109 edgecolor=fig.get_edgecolor(),
109 edgecolor=fig.get_edgecolor(),
110 dpi=dpi,
110 dpi=dpi,
111 bbox_inches=bbox_inches,
111 bbox_inches=bbox_inches,
112 )
112 )
113 # **kwargs get higher priority
113 # **kwargs get higher priority
114 kw.update(kwargs)
114 kw.update(kwargs)
115
115
116 bytes_io = BytesIO()
116 bytes_io = BytesIO()
117 fig.canvas.print_figure(bytes_io, **kw)
117 fig.canvas.print_figure(bytes_io, **kw)
118 data = bytes_io.getvalue()
118 data = bytes_io.getvalue()
119 if fmt == 'svg':
119 if fmt == 'svg':
120 data = data.decode('utf-8')
120 data = data.decode('utf-8')
121 return data
121 return data
122
122
123 def retina_figure(fig, **kwargs):
123 def retina_figure(fig, **kwargs):
124 """format a figure as a pixel-doubled (retina) PNG"""
124 """format a figure as a pixel-doubled (retina) PNG"""
125 pngdata = print_figure(fig, fmt='retina', **kwargs)
125 pngdata = print_figure(fig, fmt='retina', **kwargs)
126 w, h = _pngxy(pngdata)
126 w, h = _pngxy(pngdata)
127 metadata = dict(width=w//2, height=h//2)
127 metadata = dict(width=w//2, height=h//2)
128 return pngdata, metadata
128 return pngdata, metadata
129
129
130 # We need a little factory function here to create the closure where
130 # We need a little factory function here to create the closure where
131 # safe_execfile can live.
131 # safe_execfile can live.
132 def mpl_runner(safe_execfile):
132 def mpl_runner(safe_execfile):
133 """Factory to return a matplotlib-enabled runner for %run.
133 """Factory to return a matplotlib-enabled runner for %run.
134
134
135 Parameters
135 Parameters
136 ----------
136 ----------
137 safe_execfile : function
137 safe_execfile : function
138 This must be a function with the same interface as the
138 This must be a function with the same interface as the
139 :meth:`safe_execfile` method of IPython.
139 :meth:`safe_execfile` method of IPython.
140
140
141 Returns
141 Returns
142 -------
142 -------
143 A function suitable for use as the ``runner`` argument of the %run magic
143 A function suitable for use as the ``runner`` argument of the %run magic
144 function.
144 function.
145 """
145 """
146
146
147 def mpl_execfile(fname,*where,**kw):
147 def mpl_execfile(fname,*where,**kw):
148 """matplotlib-aware wrapper around safe_execfile.
148 """matplotlib-aware wrapper around safe_execfile.
149
149
150 Its interface is identical to that of the :func:`execfile` builtin.
150 Its interface is identical to that of the :func:`execfile` builtin.
151
151
152 This is ultimately a call to execfile(), but wrapped in safeties to
152 This is ultimately a call to execfile(), but wrapped in safeties to
153 properly handle interactive rendering."""
153 properly handle interactive rendering."""
154
154
155 import matplotlib
155 import matplotlib
156 import matplotlib.pylab as pylab
156 import matplotlib.pylab as pylab
157
157
158 #print '*** Matplotlib runner ***' # dbg
158 #print '*** Matplotlib runner ***' # dbg
159 # turn off rendering until end of script
159 # turn off rendering until end of script
160 is_interactive = matplotlib.rcParams['interactive']
160 is_interactive = matplotlib.rcParams['interactive']
161 matplotlib.interactive(False)
161 matplotlib.interactive(False)
162 safe_execfile(fname,*where,**kw)
162 safe_execfile(fname,*where,**kw)
163 matplotlib.interactive(is_interactive)
163 matplotlib.interactive(is_interactive)
164 # make rendering call now, if the user tried to do it
164 # make rendering call now, if the user tried to do it
165 if pylab.draw_if_interactive.called:
165 if pylab.draw_if_interactive.called:
166 pylab.draw()
166 pylab.draw()
167 pylab.draw_if_interactive.called = False
167 pylab.draw_if_interactive.called = False
168
168
169 return mpl_execfile
169 return mpl_execfile
170
170
171
171
172 def select_figure_formats(shell, formats, **kwargs):
172 def select_figure_formats(shell, formats, **kwargs):
173 """Select figure formats for the inline backend.
173 """Select figure formats for the inline backend.
174
174
175 Parameters
175 Parameters
176 ==========
176 ==========
177 shell : InteractiveShell
177 shell : InteractiveShell
178 The main IPython instance.
178 The main IPython instance.
179 formats : str or set
179 formats : str or set
180 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
180 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
181 **kwargs : any
181 **kwargs : any
182 Extra keyword arguments to be passed to fig.canvas.print_figure.
182 Extra keyword arguments to be passed to fig.canvas.print_figure.
183 """
183 """
184 from matplotlib.figure import Figure
184 from matplotlib.figure import Figure
185 from ipython_kernel.pylab import backend_inline
185 from ipykernel.pylab import backend_inline
186
186
187 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
187 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
188 png_formatter = shell.display_formatter.formatters['image/png']
188 png_formatter = shell.display_formatter.formatters['image/png']
189 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
189 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
190 pdf_formatter = shell.display_formatter.formatters['application/pdf']
190 pdf_formatter = shell.display_formatter.formatters['application/pdf']
191
191
192 if isinstance(formats, py3compat.string_types):
192 if isinstance(formats, py3compat.string_types):
193 formats = {formats}
193 formats = {formats}
194 # cast in case of list / tuple
194 # cast in case of list / tuple
195 formats = set(formats)
195 formats = set(formats)
196
196
197 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
197 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
198
198
199 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
199 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
200 bad = formats.difference(supported)
200 bad = formats.difference(supported)
201 if bad:
201 if bad:
202 bs = "%s" % ','.join([repr(f) for f in bad])
202 bs = "%s" % ','.join([repr(f) for f in bad])
203 gs = "%s" % ','.join([repr(f) for f in supported])
203 gs = "%s" % ','.join([repr(f) for f in supported])
204 raise ValueError("supported formats are: %s not %s" % (gs, bs))
204 raise ValueError("supported formats are: %s not %s" % (gs, bs))
205
205
206 if 'png' in formats:
206 if 'png' in formats:
207 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
207 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
208 if 'retina' in formats or 'png2x' in formats:
208 if 'retina' in formats or 'png2x' in formats:
209 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
209 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
210 if 'jpg' in formats or 'jpeg' in formats:
210 if 'jpg' in formats or 'jpeg' in formats:
211 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
211 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
212 if 'svg' in formats:
212 if 'svg' in formats:
213 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
213 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
214 if 'pdf' in formats:
214 if 'pdf' in formats:
215 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
215 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
216
216
217 #-----------------------------------------------------------------------------
217 #-----------------------------------------------------------------------------
218 # Code for initializing matplotlib and importing pylab
218 # Code for initializing matplotlib and importing pylab
219 #-----------------------------------------------------------------------------
219 #-----------------------------------------------------------------------------
220
220
221
221
222 def find_gui_and_backend(gui=None, gui_select=None):
222 def find_gui_and_backend(gui=None, gui_select=None):
223 """Given a gui string return the gui and mpl backend.
223 """Given a gui string return the gui and mpl backend.
224
224
225 Parameters
225 Parameters
226 ----------
226 ----------
227 gui : str
227 gui : str
228 Can be one of ('tk','gtk','wx','qt','qt4','inline').
228 Can be one of ('tk','gtk','wx','qt','qt4','inline').
229 gui_select : str
229 gui_select : str
230 Can be one of ('tk','gtk','wx','qt','qt4','inline').
230 Can be one of ('tk','gtk','wx','qt','qt4','inline').
231 This is any gui already selected by the shell.
231 This is any gui already selected by the shell.
232
232
233 Returns
233 Returns
234 -------
234 -------
235 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
235 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
236 'WXAgg','Qt4Agg','module://ipython_kernel.pylab.backend_inline').
236 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline').
237 """
237 """
238
238
239 import matplotlib
239 import matplotlib
240
240
241 if gui and gui != 'auto':
241 if gui and gui != 'auto':
242 # select backend based on requested gui
242 # select backend based on requested gui
243 backend = backends[gui]
243 backend = backends[gui]
244 else:
244 else:
245 # We need to read the backend from the original data structure, *not*
245 # We need to read the backend from the original data structure, *not*
246 # from mpl.rcParams, since a prior invocation of %matplotlib may have
246 # from mpl.rcParams, since a prior invocation of %matplotlib may have
247 # overwritten that.
247 # overwritten that.
248 # WARNING: this assumes matplotlib 1.1 or newer!!
248 # WARNING: this assumes matplotlib 1.1 or newer!!
249 backend = matplotlib.rcParamsOrig['backend']
249 backend = matplotlib.rcParamsOrig['backend']
250 # In this case, we need to find what the appropriate gui selection call
250 # In this case, we need to find what the appropriate gui selection call
251 # should be for IPython, so we can activate inputhook accordingly
251 # should be for IPython, so we can activate inputhook accordingly
252 gui = backend2gui.get(backend, None)
252 gui = backend2gui.get(backend, None)
253
253
254 # If we have already had a gui active, we need it and inline are the
254 # If we have already had a gui active, we need it and inline are the
255 # ones allowed.
255 # ones allowed.
256 if gui_select and gui != gui_select:
256 if gui_select and gui != gui_select:
257 gui = gui_select
257 gui = gui_select
258 backend = backends[gui]
258 backend = backends[gui]
259
259
260 return gui, backend
260 return gui, backend
261
261
262
262
263 def activate_matplotlib(backend):
263 def activate_matplotlib(backend):
264 """Activate the given backend and set interactive to True."""
264 """Activate the given backend and set interactive to True."""
265
265
266 import matplotlib
266 import matplotlib
267 matplotlib.interactive(True)
267 matplotlib.interactive(True)
268
268
269 # Matplotlib had a bug where even switch_backend could not force
269 # Matplotlib had a bug where even switch_backend could not force
270 # the rcParam to update. This needs to be set *before* the module
270 # the rcParam to update. This needs to be set *before* the module
271 # magic of switch_backend().
271 # magic of switch_backend().
272 matplotlib.rcParams['backend'] = backend
272 matplotlib.rcParams['backend'] = backend
273
273
274 import matplotlib.pyplot
274 import matplotlib.pyplot
275 matplotlib.pyplot.switch_backend(backend)
275 matplotlib.pyplot.switch_backend(backend)
276
276
277 # This must be imported last in the matplotlib series, after
277 # This must be imported last in the matplotlib series, after
278 # backend/interactivity choices have been made
278 # backend/interactivity choices have been made
279 import matplotlib.pylab as pylab
279 import matplotlib.pylab as pylab
280
280
281 pylab.show._needmain = False
281 pylab.show._needmain = False
282 # We need to detect at runtime whether show() is called by the user.
282 # We need to detect at runtime whether show() is called by the user.
283 # For this, we wrap it into a decorator which adds a 'called' flag.
283 # For this, we wrap it into a decorator which adds a 'called' flag.
284 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
284 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
285
285
286
286
287 def import_pylab(user_ns, import_all=True):
287 def import_pylab(user_ns, import_all=True):
288 """Populate the namespace with pylab-related values.
288 """Populate the namespace with pylab-related values.
289
289
290 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
290 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
291
291
292 Also imports a few names from IPython (figsize, display, getfigs)
292 Also imports a few names from IPython (figsize, display, getfigs)
293
293
294 """
294 """
295
295
296 # Import numpy as np/pyplot as plt are conventions we're trying to
296 # Import numpy as np/pyplot as plt are conventions we're trying to
297 # somewhat standardize on. Making them available to users by default
297 # somewhat standardize on. Making them available to users by default
298 # will greatly help this.
298 # will greatly help this.
299 s = ("import numpy\n"
299 s = ("import numpy\n"
300 "import matplotlib\n"
300 "import matplotlib\n"
301 "from matplotlib import pylab, mlab, pyplot\n"
301 "from matplotlib import pylab, mlab, pyplot\n"
302 "np = numpy\n"
302 "np = numpy\n"
303 "plt = pyplot\n"
303 "plt = pyplot\n"
304 )
304 )
305 exec(s, user_ns)
305 exec(s, user_ns)
306
306
307 if import_all:
307 if import_all:
308 s = ("from matplotlib.pylab import *\n"
308 s = ("from matplotlib.pylab import *\n"
309 "from numpy import *\n")
309 "from numpy import *\n")
310 exec(s, user_ns)
310 exec(s, user_ns)
311
311
312 # IPython symbols to add
312 # IPython symbols to add
313 user_ns['figsize'] = figsize
313 user_ns['figsize'] = figsize
314 from IPython.core.display import display
314 from IPython.core.display import display
315 # Add display and getfigs to the user's namespace
315 # Add display and getfigs to the user's namespace
316 user_ns['display'] = display
316 user_ns['display'] = display
317 user_ns['getfigs'] = getfigs
317 user_ns['getfigs'] = getfigs
318
318
319
319
320 def configure_inline_support(shell, backend):
320 def configure_inline_support(shell, backend):
321 """Configure an IPython shell object for matplotlib use.
321 """Configure an IPython shell object for matplotlib use.
322
322
323 Parameters
323 Parameters
324 ----------
324 ----------
325 shell : InteractiveShell instance
325 shell : InteractiveShell instance
326
326
327 backend : matplotlib backend
327 backend : matplotlib backend
328 """
328 """
329 # If using our svg payload backend, register the post-execution
329 # If using our svg payload backend, register the post-execution
330 # function that will pick up the results for display. This can only be
330 # function that will pick up the results for display. This can only be
331 # done with access to the real shell object.
331 # done with access to the real shell object.
332
332
333 # Note: if we can't load the inline backend, then there's no point
333 # Note: if we can't load the inline backend, then there's no point
334 # continuing (such as in terminal-only shells in environments without
334 # continuing (such as in terminal-only shells in environments without
335 # zeromq available).
335 # zeromq available).
336 try:
336 try:
337 from ipython_kernel.pylab.backend_inline import InlineBackend
337 from ipykernel.pylab.backend_inline import InlineBackend
338 except ImportError:
338 except ImportError:
339 return
339 return
340 from matplotlib import pyplot
340 from matplotlib import pyplot
341
341
342 cfg = InlineBackend.instance(parent=shell)
342 cfg = InlineBackend.instance(parent=shell)
343 cfg.shell = shell
343 cfg.shell = shell
344 if cfg not in shell.configurables:
344 if cfg not in shell.configurables:
345 shell.configurables.append(cfg)
345 shell.configurables.append(cfg)
346
346
347 if backend == backends['inline']:
347 if backend == backends['inline']:
348 from ipython_kernel.pylab.backend_inline import flush_figures
348 from ipykernel.pylab.backend_inline import flush_figures
349 shell.events.register('post_execute', flush_figures)
349 shell.events.register('post_execute', flush_figures)
350
350
351 # Save rcParams that will be overwrittern
351 # Save rcParams that will be overwrittern
352 shell._saved_rcParams = dict()
352 shell._saved_rcParams = dict()
353 for k in cfg.rc:
353 for k in cfg.rc:
354 shell._saved_rcParams[k] = pyplot.rcParams[k]
354 shell._saved_rcParams[k] = pyplot.rcParams[k]
355 # load inline_rc
355 # load inline_rc
356 pyplot.rcParams.update(cfg.rc)
356 pyplot.rcParams.update(cfg.rc)
357 else:
357 else:
358 from ipython_kernel.pylab.backend_inline import flush_figures
358 from ipykernel.pylab.backend_inline import flush_figures
359 try:
359 try:
360 shell.events.unregister('post_execute', flush_figures)
360 shell.events.unregister('post_execute', flush_figures)
361 except ValueError:
361 except ValueError:
362 pass
362 pass
363 if hasattr(shell, '_saved_rcParams'):
363 if hasattr(shell, '_saved_rcParams'):
364 pyplot.rcParams.update(shell._saved_rcParams)
364 pyplot.rcParams.update(shell._saved_rcParams)
365 del shell._saved_rcParams
365 del shell._saved_rcParams
366
366
367 # Setup the default figure format
367 # Setup the default figure format
368 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
368 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
369
369
@@ -1,152 +1,152 b''
1 # Copyright (c) IPython Development Team.
1 # Copyright (c) IPython Development Team.
2 # Distributed under the terms of the Modified BSD License.
2 # Distributed under the terms of the Modified BSD License.
3
3
4 import json
4 import json
5 import os
5 import os
6 import warnings
6 import warnings
7
7
8 import nose.tools as nt
8 import nose.tools as nt
9
9
10 from IPython.core import display
10 from IPython.core import display
11 from IPython.core.getipython import get_ipython
11 from IPython.core.getipython import get_ipython
12 from IPython import paths as ipath
12 from IPython import paths as ipath
13
13
14 import IPython.testing.decorators as dec
14 import IPython.testing.decorators as dec
15
15
16 def test_image_size():
16 def test_image_size():
17 """Simple test for display.Image(args, width=x,height=y)"""
17 """Simple test for display.Image(args, width=x,height=y)"""
18 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
18 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
19 img = display.Image(url=thisurl, width=200, height=200)
19 img = display.Image(url=thisurl, width=200, height=200)
20 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
20 nt.assert_equal(u'<img src="%s" width="200" height="200"/>' % (thisurl), img._repr_html_())
21 img = display.Image(url=thisurl, width=200)
21 img = display.Image(url=thisurl, width=200)
22 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
22 nt.assert_equal(u'<img src="%s" width="200"/>' % (thisurl), img._repr_html_())
23 img = display.Image(url=thisurl)
23 img = display.Image(url=thisurl)
24 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
24 nt.assert_equal(u'<img src="%s"/>' % (thisurl), img._repr_html_())
25 img = display.Image(url=thisurl, unconfined=True)
25 img = display.Image(url=thisurl, unconfined=True)
26 nt.assert_equal(u'<img src="%s" class="unconfined"/>' % (thisurl), img._repr_html_())
26 nt.assert_equal(u'<img src="%s" class="unconfined"/>' % (thisurl), img._repr_html_())
27
27
28 def test_retina_png():
28 def test_retina_png():
29 here = os.path.dirname(__file__)
29 here = os.path.dirname(__file__)
30 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
30 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
31 nt.assert_equal(img.height, 1)
31 nt.assert_equal(img.height, 1)
32 nt.assert_equal(img.width, 1)
32 nt.assert_equal(img.width, 1)
33 data, md = img._repr_png_()
33 data, md = img._repr_png_()
34 nt.assert_equal(md['width'], 1)
34 nt.assert_equal(md['width'], 1)
35 nt.assert_equal(md['height'], 1)
35 nt.assert_equal(md['height'], 1)
36
36
37 def test_retina_jpeg():
37 def test_retina_jpeg():
38 here = os.path.dirname(__file__)
38 here = os.path.dirname(__file__)
39 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
39 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
40 nt.assert_equal(img.height, 1)
40 nt.assert_equal(img.height, 1)
41 nt.assert_equal(img.width, 1)
41 nt.assert_equal(img.width, 1)
42 data, md = img._repr_jpeg_()
42 data, md = img._repr_jpeg_()
43 nt.assert_equal(md['width'], 1)
43 nt.assert_equal(md['width'], 1)
44 nt.assert_equal(md['height'], 1)
44 nt.assert_equal(md['height'], 1)
45
45
46 def test_image_filename_defaults():
46 def test_image_filename_defaults():
47 '''test format constraint, and validity of jpeg and png'''
47 '''test format constraint, and validity of jpeg and png'''
48 tpath = ipath.get_ipython_package_dir()
48 tpath = ipath.get_ipython_package_dir()
49 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.gif'),
49 nt.assert_raises(ValueError, display.Image, filename=os.path.join(tpath, 'testing/tests/badformat.gif'),
50 embed=True)
50 embed=True)
51 nt.assert_raises(ValueError, display.Image)
51 nt.assert_raises(ValueError, display.Image)
52 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
52 nt.assert_raises(ValueError, display.Image, data='this is not an image', format='badformat', embed=True)
53 # check boths paths to allow packages to test at build and install time
53 # check boths paths to allow packages to test at build and install time
54 imgfile = os.path.join(tpath, 'core/tests/2x2.png')
54 imgfile = os.path.join(tpath, 'core/tests/2x2.png')
55 img = display.Image(filename=imgfile)
55 img = display.Image(filename=imgfile)
56 nt.assert_equal('png', img.format)
56 nt.assert_equal('png', img.format)
57 nt.assert_is_not_none(img._repr_png_())
57 nt.assert_is_not_none(img._repr_png_())
58 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
58 img = display.Image(filename=os.path.join(tpath, 'testing/tests/logo.jpg'), embed=False)
59 nt.assert_equal('jpeg', img.format)
59 nt.assert_equal('jpeg', img.format)
60 nt.assert_is_none(img._repr_jpeg_())
60 nt.assert_is_none(img._repr_jpeg_())
61
61
62 def _get_inline_config():
62 def _get_inline_config():
63 from ipython_kernel.pylab.config import InlineBackend
63 from ipykernel.pylab.config import InlineBackend
64 return InlineBackend.instance()
64 return InlineBackend.instance()
65
65
66 @dec.skip_without('matplotlib')
66 @dec.skip_without('matplotlib')
67 def test_set_matplotlib_close():
67 def test_set_matplotlib_close():
68 cfg = _get_inline_config()
68 cfg = _get_inline_config()
69 cfg.close_figures = False
69 cfg.close_figures = False
70 display.set_matplotlib_close()
70 display.set_matplotlib_close()
71 assert cfg.close_figures
71 assert cfg.close_figures
72 display.set_matplotlib_close(False)
72 display.set_matplotlib_close(False)
73 assert not cfg.close_figures
73 assert not cfg.close_figures
74
74
75 _fmt_mime_map = {
75 _fmt_mime_map = {
76 'png': 'image/png',
76 'png': 'image/png',
77 'jpeg': 'image/jpeg',
77 'jpeg': 'image/jpeg',
78 'pdf': 'application/pdf',
78 'pdf': 'application/pdf',
79 'retina': 'image/png',
79 'retina': 'image/png',
80 'svg': 'image/svg+xml',
80 'svg': 'image/svg+xml',
81 }
81 }
82
82
83 @dec.skip_without('matplotlib')
83 @dec.skip_without('matplotlib')
84 def test_set_matplotlib_formats():
84 def test_set_matplotlib_formats():
85 from matplotlib.figure import Figure
85 from matplotlib.figure import Figure
86 formatters = get_ipython().display_formatter.formatters
86 formatters = get_ipython().display_formatter.formatters
87 for formats in [
87 for formats in [
88 ('png',),
88 ('png',),
89 ('pdf', 'svg'),
89 ('pdf', 'svg'),
90 ('jpeg', 'retina', 'png'),
90 ('jpeg', 'retina', 'png'),
91 (),
91 (),
92 ]:
92 ]:
93 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
93 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
94 display.set_matplotlib_formats(*formats)
94 display.set_matplotlib_formats(*formats)
95 for mime, f in formatters.items():
95 for mime, f in formatters.items():
96 if mime in active_mimes:
96 if mime in active_mimes:
97 nt.assert_in(Figure, f)
97 nt.assert_in(Figure, f)
98 else:
98 else:
99 nt.assert_not_in(Figure, f)
99 nt.assert_not_in(Figure, f)
100
100
101 @dec.skip_without('matplotlib')
101 @dec.skip_without('matplotlib')
102 def test_set_matplotlib_formats_kwargs():
102 def test_set_matplotlib_formats_kwargs():
103 from matplotlib.figure import Figure
103 from matplotlib.figure import Figure
104 ip = get_ipython()
104 ip = get_ipython()
105 cfg = _get_inline_config()
105 cfg = _get_inline_config()
106 cfg.print_figure_kwargs.update(dict(foo='bar'))
106 cfg.print_figure_kwargs.update(dict(foo='bar'))
107 kwargs = dict(quality=10)
107 kwargs = dict(quality=10)
108 display.set_matplotlib_formats('png', **kwargs)
108 display.set_matplotlib_formats('png', **kwargs)
109 formatter = ip.display_formatter.formatters['image/png']
109 formatter = ip.display_formatter.formatters['image/png']
110 f = formatter.lookup_by_type(Figure)
110 f = formatter.lookup_by_type(Figure)
111 cell = f.__closure__[0].cell_contents
111 cell = f.__closure__[0].cell_contents
112 expected = kwargs
112 expected = kwargs
113 expected.update(cfg.print_figure_kwargs)
113 expected.update(cfg.print_figure_kwargs)
114 nt.assert_equal(cell, expected)
114 nt.assert_equal(cell, expected)
115
115
116 def test_displayobject_repr():
116 def test_displayobject_repr():
117 h = display.HTML('<br />')
117 h = display.HTML('<br />')
118 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
118 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
119 h._show_mem_addr = True
119 h._show_mem_addr = True
120 nt.assert_equal(repr(h), object.__repr__(h))
120 nt.assert_equal(repr(h), object.__repr__(h))
121 h._show_mem_addr = False
121 h._show_mem_addr = False
122 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
122 nt.assert_equal(repr(h), '<IPython.core.display.HTML object>')
123
123
124 j = display.Javascript('')
124 j = display.Javascript('')
125 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
125 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
126 j._show_mem_addr = True
126 j._show_mem_addr = True
127 nt.assert_equal(repr(j), object.__repr__(j))
127 nt.assert_equal(repr(j), object.__repr__(j))
128 j._show_mem_addr = False
128 j._show_mem_addr = False
129 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
129 nt.assert_equal(repr(j), '<IPython.core.display.Javascript object>')
130
130
131 def test_json():
131 def test_json():
132 d = {'a': 5}
132 d = {'a': 5}
133 lis = [d]
133 lis = [d]
134 j = display.JSON(d)
134 j = display.JSON(d)
135 nt.assert_equal(j._repr_json_(), d)
135 nt.assert_equal(j._repr_json_(), d)
136
136
137 with warnings.catch_warnings(record=True) as w:
137 with warnings.catch_warnings(record=True) as w:
138 warnings.simplefilter("always")
138 warnings.simplefilter("always")
139 j = display.JSON(json.dumps(d))
139 j = display.JSON(json.dumps(d))
140 nt.assert_equal(len(w), 1)
140 nt.assert_equal(len(w), 1)
141 nt.assert_equal(j._repr_json_(), d)
141 nt.assert_equal(j._repr_json_(), d)
142
142
143 j = display.JSON(lis)
143 j = display.JSON(lis)
144 nt.assert_equal(j._repr_json_(), lis)
144 nt.assert_equal(j._repr_json_(), lis)
145
145
146 with warnings.catch_warnings(record=True) as w:
146 with warnings.catch_warnings(record=True) as w:
147 warnings.simplefilter("always")
147 warnings.simplefilter("always")
148 j = display.JSON(json.dumps(lis))
148 j = display.JSON(json.dumps(lis))
149 nt.assert_equal(len(w), 1)
149 nt.assert_equal(len(w), 1)
150 nt.assert_equal(j._repr_json_(), lis)
150 nt.assert_equal(j._repr_json_(), lis)
151
151
152
152
@@ -1,903 +1,903 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
2 """Tests for the key interactiveshell module.
3
3
4 Historically the main classes in interactiveshell have been under-tested. This
4 Historically the main classes in interactiveshell have been under-tested. This
5 module should grow as many single-method tests as possible to trap many of the
5 module should grow as many single-method tests as possible to trap many of the
6 recurring bugs we seem to encounter with high-level interaction.
6 recurring bugs we seem to encounter with high-level interaction.
7 """
7 """
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import ast
12 import ast
13 import os
13 import os
14 import signal
14 import signal
15 import shutil
15 import shutil
16 import sys
16 import sys
17 import tempfile
17 import tempfile
18 import unittest
18 import unittest
19 try:
19 try:
20 from unittest import mock
20 from unittest import mock
21 except ImportError:
21 except ImportError:
22 import mock
22 import mock
23 from os.path import join
23 from os.path import join
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from IPython.core.error import InputRejected
27 from IPython.core.error import InputRejected
28 from IPython.core.inputtransformer import InputTransformer
28 from IPython.core.inputtransformer import InputTransformer
29 from IPython.testing.decorators import (
29 from IPython.testing.decorators import (
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
30 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
31 )
31 )
32 from IPython.testing import tools as tt
32 from IPython.testing import tools as tt
33 from IPython.utils import io
33 from IPython.utils import io
34 from IPython.utils.process import find_cmd
34 from IPython.utils.process import find_cmd
35 from IPython.utils import py3compat
35 from IPython.utils import py3compat
36 from IPython.utils.py3compat import unicode_type, PY3
36 from IPython.utils.py3compat import unicode_type, PY3
37
37
38 if PY3:
38 if PY3:
39 from io import StringIO
39 from io import StringIO
40 else:
40 else:
41 from StringIO import StringIO
41 from StringIO import StringIO
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Globals
44 # Globals
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # This is used by every single test, no point repeating it ad nauseam
46 # This is used by every single test, no point repeating it ad nauseam
47 ip = get_ipython()
47 ip = get_ipython()
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Tests
50 # Tests
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 class DerivedInterrupt(KeyboardInterrupt):
53 class DerivedInterrupt(KeyboardInterrupt):
54 pass
54 pass
55
55
56 class InteractiveShellTestCase(unittest.TestCase):
56 class InteractiveShellTestCase(unittest.TestCase):
57 def test_naked_string_cells(self):
57 def test_naked_string_cells(self):
58 """Test that cells with only naked strings are fully executed"""
58 """Test that cells with only naked strings are fully executed"""
59 # First, single-line inputs
59 # First, single-line inputs
60 ip.run_cell('"a"\n')
60 ip.run_cell('"a"\n')
61 self.assertEqual(ip.user_ns['_'], 'a')
61 self.assertEqual(ip.user_ns['_'], 'a')
62 # And also multi-line cells
62 # And also multi-line cells
63 ip.run_cell('"""a\nb"""\n')
63 ip.run_cell('"""a\nb"""\n')
64 self.assertEqual(ip.user_ns['_'], 'a\nb')
64 self.assertEqual(ip.user_ns['_'], 'a\nb')
65
65
66 def test_run_empty_cell(self):
66 def test_run_empty_cell(self):
67 """Just make sure we don't get a horrible error with a blank
67 """Just make sure we don't get a horrible error with a blank
68 cell of input. Yes, I did overlook that."""
68 cell of input. Yes, I did overlook that."""
69 old_xc = ip.execution_count
69 old_xc = ip.execution_count
70 res = ip.run_cell('')
70 res = ip.run_cell('')
71 self.assertEqual(ip.execution_count, old_xc)
71 self.assertEqual(ip.execution_count, old_xc)
72 self.assertEqual(res.execution_count, None)
72 self.assertEqual(res.execution_count, None)
73
73
74 def test_run_cell_multiline(self):
74 def test_run_cell_multiline(self):
75 """Multi-block, multi-line cells must execute correctly.
75 """Multi-block, multi-line cells must execute correctly.
76 """
76 """
77 src = '\n'.join(["x=1",
77 src = '\n'.join(["x=1",
78 "y=2",
78 "y=2",
79 "if 1:",
79 "if 1:",
80 " x += 1",
80 " x += 1",
81 " y += 1",])
81 " y += 1",])
82 res = ip.run_cell(src)
82 res = ip.run_cell(src)
83 self.assertEqual(ip.user_ns['x'], 2)
83 self.assertEqual(ip.user_ns['x'], 2)
84 self.assertEqual(ip.user_ns['y'], 3)
84 self.assertEqual(ip.user_ns['y'], 3)
85 self.assertEqual(res.success, True)
85 self.assertEqual(res.success, True)
86 self.assertEqual(res.result, None)
86 self.assertEqual(res.result, None)
87
87
88 def test_multiline_string_cells(self):
88 def test_multiline_string_cells(self):
89 "Code sprinkled with multiline strings should execute (GH-306)"
89 "Code sprinkled with multiline strings should execute (GH-306)"
90 ip.run_cell('tmp=0')
90 ip.run_cell('tmp=0')
91 self.assertEqual(ip.user_ns['tmp'], 0)
91 self.assertEqual(ip.user_ns['tmp'], 0)
92 res = ip.run_cell('tmp=1;"""a\nb"""\n')
92 res = ip.run_cell('tmp=1;"""a\nb"""\n')
93 self.assertEqual(ip.user_ns['tmp'], 1)
93 self.assertEqual(ip.user_ns['tmp'], 1)
94 self.assertEqual(res.success, True)
94 self.assertEqual(res.success, True)
95 self.assertEqual(res.result, "a\nb")
95 self.assertEqual(res.result, "a\nb")
96
96
97 def test_dont_cache_with_semicolon(self):
97 def test_dont_cache_with_semicolon(self):
98 "Ending a line with semicolon should not cache the returned object (GH-307)"
98 "Ending a line with semicolon should not cache the returned object (GH-307)"
99 oldlen = len(ip.user_ns['Out'])
99 oldlen = len(ip.user_ns['Out'])
100 for cell in ['1;', '1;1;']:
100 for cell in ['1;', '1;1;']:
101 res = ip.run_cell(cell, store_history=True)
101 res = ip.run_cell(cell, store_history=True)
102 newlen = len(ip.user_ns['Out'])
102 newlen = len(ip.user_ns['Out'])
103 self.assertEqual(oldlen, newlen)
103 self.assertEqual(oldlen, newlen)
104 self.assertIsNone(res.result)
104 self.assertIsNone(res.result)
105 i = 0
105 i = 0
106 #also test the default caching behavior
106 #also test the default caching behavior
107 for cell in ['1', '1;1']:
107 for cell in ['1', '1;1']:
108 ip.run_cell(cell, store_history=True)
108 ip.run_cell(cell, store_history=True)
109 newlen = len(ip.user_ns['Out'])
109 newlen = len(ip.user_ns['Out'])
110 i += 1
110 i += 1
111 self.assertEqual(oldlen+i, newlen)
111 self.assertEqual(oldlen+i, newlen)
112
112
113 def test_syntax_error(self):
113 def test_syntax_error(self):
114 res = ip.run_cell("raise = 3")
114 res = ip.run_cell("raise = 3")
115 self.assertIsInstance(res.error_before_exec, SyntaxError)
115 self.assertIsInstance(res.error_before_exec, SyntaxError)
116
116
117 def test_In_variable(self):
117 def test_In_variable(self):
118 "Verify that In variable grows with user input (GH-284)"
118 "Verify that In variable grows with user input (GH-284)"
119 oldlen = len(ip.user_ns['In'])
119 oldlen = len(ip.user_ns['In'])
120 ip.run_cell('1;', store_history=True)
120 ip.run_cell('1;', store_history=True)
121 newlen = len(ip.user_ns['In'])
121 newlen = len(ip.user_ns['In'])
122 self.assertEqual(oldlen+1, newlen)
122 self.assertEqual(oldlen+1, newlen)
123 self.assertEqual(ip.user_ns['In'][-1],'1;')
123 self.assertEqual(ip.user_ns['In'][-1],'1;')
124
124
125 def test_magic_names_in_string(self):
125 def test_magic_names_in_string(self):
126 ip.run_cell('a = """\n%exit\n"""')
126 ip.run_cell('a = """\n%exit\n"""')
127 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
127 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
128
128
129 def test_trailing_newline(self):
129 def test_trailing_newline(self):
130 """test that running !(command) does not raise a SyntaxError"""
130 """test that running !(command) does not raise a SyntaxError"""
131 ip.run_cell('!(true)\n', False)
131 ip.run_cell('!(true)\n', False)
132 ip.run_cell('!(true)\n\n\n', False)
132 ip.run_cell('!(true)\n\n\n', False)
133
133
134 def test_gh_597(self):
134 def test_gh_597(self):
135 """Pretty-printing lists of objects with non-ascii reprs may cause
135 """Pretty-printing lists of objects with non-ascii reprs may cause
136 problems."""
136 problems."""
137 class Spam(object):
137 class Spam(object):
138 def __repr__(self):
138 def __repr__(self):
139 return "\xe9"*50
139 return "\xe9"*50
140 import IPython.core.formatters
140 import IPython.core.formatters
141 f = IPython.core.formatters.PlainTextFormatter()
141 f = IPython.core.formatters.PlainTextFormatter()
142 f([Spam(),Spam()])
142 f([Spam(),Spam()])
143
143
144
144
145 def test_future_flags(self):
145 def test_future_flags(self):
146 """Check that future flags are used for parsing code (gh-777)"""
146 """Check that future flags are used for parsing code (gh-777)"""
147 ip.run_cell('from __future__ import print_function')
147 ip.run_cell('from __future__ import print_function')
148 try:
148 try:
149 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
149 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
150 assert 'prfunc_return_val' in ip.user_ns
150 assert 'prfunc_return_val' in ip.user_ns
151 finally:
151 finally:
152 # Reset compiler flags so we don't mess up other tests.
152 # Reset compiler flags so we don't mess up other tests.
153 ip.compile.reset_compiler_flags()
153 ip.compile.reset_compiler_flags()
154
154
155 def test_future_unicode(self):
155 def test_future_unicode(self):
156 """Check that unicode_literals is imported from __future__ (gh #786)"""
156 """Check that unicode_literals is imported from __future__ (gh #786)"""
157 try:
157 try:
158 ip.run_cell(u'byte_str = "a"')
158 ip.run_cell(u'byte_str = "a"')
159 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
159 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
160 ip.run_cell('from __future__ import unicode_literals')
160 ip.run_cell('from __future__ import unicode_literals')
161 ip.run_cell(u'unicode_str = "a"')
161 ip.run_cell(u'unicode_str = "a"')
162 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
162 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
163 finally:
163 finally:
164 # Reset compiler flags so we don't mess up other tests.
164 # Reset compiler flags so we don't mess up other tests.
165 ip.compile.reset_compiler_flags()
165 ip.compile.reset_compiler_flags()
166
166
167 def test_can_pickle(self):
167 def test_can_pickle(self):
168 "Can we pickle objects defined interactively (GH-29)"
168 "Can we pickle objects defined interactively (GH-29)"
169 ip = get_ipython()
169 ip = get_ipython()
170 ip.reset()
170 ip.reset()
171 ip.run_cell(("class Mylist(list):\n"
171 ip.run_cell(("class Mylist(list):\n"
172 " def __init__(self,x=[]):\n"
172 " def __init__(self,x=[]):\n"
173 " list.__init__(self,x)"))
173 " list.__init__(self,x)"))
174 ip.run_cell("w=Mylist([1,2,3])")
174 ip.run_cell("w=Mylist([1,2,3])")
175
175
176 from pickle import dumps
176 from pickle import dumps
177
177
178 # We need to swap in our main module - this is only necessary
178 # We need to swap in our main module - this is only necessary
179 # inside the test framework, because IPython puts the interactive module
179 # inside the test framework, because IPython puts the interactive module
180 # in place (but the test framework undoes this).
180 # in place (but the test framework undoes this).
181 _main = sys.modules['__main__']
181 _main = sys.modules['__main__']
182 sys.modules['__main__'] = ip.user_module
182 sys.modules['__main__'] = ip.user_module
183 try:
183 try:
184 res = dumps(ip.user_ns["w"])
184 res = dumps(ip.user_ns["w"])
185 finally:
185 finally:
186 sys.modules['__main__'] = _main
186 sys.modules['__main__'] = _main
187 self.assertTrue(isinstance(res, bytes))
187 self.assertTrue(isinstance(res, bytes))
188
188
189 def test_global_ns(self):
189 def test_global_ns(self):
190 "Code in functions must be able to access variables outside them."
190 "Code in functions must be able to access variables outside them."
191 ip = get_ipython()
191 ip = get_ipython()
192 ip.run_cell("a = 10")
192 ip.run_cell("a = 10")
193 ip.run_cell(("def f(x):\n"
193 ip.run_cell(("def f(x):\n"
194 " return x + a"))
194 " return x + a"))
195 ip.run_cell("b = f(12)")
195 ip.run_cell("b = f(12)")
196 self.assertEqual(ip.user_ns["b"], 22)
196 self.assertEqual(ip.user_ns["b"], 22)
197
197
198 def test_bad_custom_tb(self):
198 def test_bad_custom_tb(self):
199 """Check that InteractiveShell is protected from bad custom exception handlers"""
199 """Check that InteractiveShell is protected from bad custom exception handlers"""
200 from IPython.utils import io
200 from IPython.utils import io
201 save_stderr = io.stderr
201 save_stderr = io.stderr
202 try:
202 try:
203 # capture stderr
203 # capture stderr
204 io.stderr = StringIO()
204 io.stderr = StringIO()
205 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
205 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
206 self.assertEqual(ip.custom_exceptions, (IOError,))
206 self.assertEqual(ip.custom_exceptions, (IOError,))
207 ip.run_cell(u'raise IOError("foo")')
207 ip.run_cell(u'raise IOError("foo")')
208 self.assertEqual(ip.custom_exceptions, ())
208 self.assertEqual(ip.custom_exceptions, ())
209 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
209 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
210 finally:
210 finally:
211 io.stderr = save_stderr
211 io.stderr = save_stderr
212
212
213 def test_bad_custom_tb_return(self):
213 def test_bad_custom_tb_return(self):
214 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
214 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
215 from IPython.utils import io
215 from IPython.utils import io
216 save_stderr = io.stderr
216 save_stderr = io.stderr
217 try:
217 try:
218 # capture stderr
218 # capture stderr
219 io.stderr = StringIO()
219 io.stderr = StringIO()
220 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
220 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
221 self.assertEqual(ip.custom_exceptions, (NameError,))
221 self.assertEqual(ip.custom_exceptions, (NameError,))
222 ip.run_cell(u'a=abracadabra')
222 ip.run_cell(u'a=abracadabra')
223 self.assertEqual(ip.custom_exceptions, ())
223 self.assertEqual(ip.custom_exceptions, ())
224 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
224 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
225 finally:
225 finally:
226 io.stderr = save_stderr
226 io.stderr = save_stderr
227
227
228 def test_drop_by_id(self):
228 def test_drop_by_id(self):
229 myvars = {"a":object(), "b":object(), "c": object()}
229 myvars = {"a":object(), "b":object(), "c": object()}
230 ip.push(myvars, interactive=False)
230 ip.push(myvars, interactive=False)
231 for name in myvars:
231 for name in myvars:
232 assert name in ip.user_ns, name
232 assert name in ip.user_ns, name
233 assert name in ip.user_ns_hidden, name
233 assert name in ip.user_ns_hidden, name
234 ip.user_ns['b'] = 12
234 ip.user_ns['b'] = 12
235 ip.drop_by_id(myvars)
235 ip.drop_by_id(myvars)
236 for name in ["a", "c"]:
236 for name in ["a", "c"]:
237 assert name not in ip.user_ns, name
237 assert name not in ip.user_ns, name
238 assert name not in ip.user_ns_hidden, name
238 assert name not in ip.user_ns_hidden, name
239 assert ip.user_ns['b'] == 12
239 assert ip.user_ns['b'] == 12
240 ip.reset()
240 ip.reset()
241
241
242 def test_var_expand(self):
242 def test_var_expand(self):
243 ip.user_ns['f'] = u'Ca\xf1o'
243 ip.user_ns['f'] = u'Ca\xf1o'
244 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
244 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
245 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
245 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
246 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
246 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
247 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
247 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
248
248
249 ip.user_ns['f'] = b'Ca\xc3\xb1o'
249 ip.user_ns['f'] = b'Ca\xc3\xb1o'
250 # This should not raise any exception:
250 # This should not raise any exception:
251 ip.var_expand(u'echo $f')
251 ip.var_expand(u'echo $f')
252
252
253 def test_var_expand_local(self):
253 def test_var_expand_local(self):
254 """Test local variable expansion in !system and %magic calls"""
254 """Test local variable expansion in !system and %magic calls"""
255 # !system
255 # !system
256 ip.run_cell('def test():\n'
256 ip.run_cell('def test():\n'
257 ' lvar = "ttt"\n'
257 ' lvar = "ttt"\n'
258 ' ret = !echo {lvar}\n'
258 ' ret = !echo {lvar}\n'
259 ' return ret[0]\n')
259 ' return ret[0]\n')
260 res = ip.user_ns['test']()
260 res = ip.user_ns['test']()
261 nt.assert_in('ttt', res)
261 nt.assert_in('ttt', res)
262
262
263 # %magic
263 # %magic
264 ip.run_cell('def makemacro():\n'
264 ip.run_cell('def makemacro():\n'
265 ' macroname = "macro_var_expand_locals"\n'
265 ' macroname = "macro_var_expand_locals"\n'
266 ' %macro {macroname} codestr\n')
266 ' %macro {macroname} codestr\n')
267 ip.user_ns['codestr'] = "str(12)"
267 ip.user_ns['codestr'] = "str(12)"
268 ip.run_cell('makemacro()')
268 ip.run_cell('makemacro()')
269 nt.assert_in('macro_var_expand_locals', ip.user_ns)
269 nt.assert_in('macro_var_expand_locals', ip.user_ns)
270
270
271 def test_var_expand_self(self):
271 def test_var_expand_self(self):
272 """Test variable expansion with the name 'self', which was failing.
272 """Test variable expansion with the name 'self', which was failing.
273
273
274 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
274 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
275 """
275 """
276 ip.run_cell('class cTest:\n'
276 ip.run_cell('class cTest:\n'
277 ' classvar="see me"\n'
277 ' classvar="see me"\n'
278 ' def test(self):\n'
278 ' def test(self):\n'
279 ' res = !echo Variable: {self.classvar}\n'
279 ' res = !echo Variable: {self.classvar}\n'
280 ' return res[0]\n')
280 ' return res[0]\n')
281 nt.assert_in('see me', ip.user_ns['cTest']().test())
281 nt.assert_in('see me', ip.user_ns['cTest']().test())
282
282
283 def test_bad_var_expand(self):
283 def test_bad_var_expand(self):
284 """var_expand on invalid formats shouldn't raise"""
284 """var_expand on invalid formats shouldn't raise"""
285 # SyntaxError
285 # SyntaxError
286 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
286 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
287 # NameError
287 # NameError
288 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
288 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
289 # ZeroDivisionError
289 # ZeroDivisionError
290 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
290 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
291
291
292 def test_silent_postexec(self):
292 def test_silent_postexec(self):
293 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
293 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
294 pre_explicit = mock.Mock()
294 pre_explicit = mock.Mock()
295 pre_always = mock.Mock()
295 pre_always = mock.Mock()
296 post_explicit = mock.Mock()
296 post_explicit = mock.Mock()
297 post_always = mock.Mock()
297 post_always = mock.Mock()
298
298
299 ip.events.register('pre_run_cell', pre_explicit)
299 ip.events.register('pre_run_cell', pre_explicit)
300 ip.events.register('pre_execute', pre_always)
300 ip.events.register('pre_execute', pre_always)
301 ip.events.register('post_run_cell', post_explicit)
301 ip.events.register('post_run_cell', post_explicit)
302 ip.events.register('post_execute', post_always)
302 ip.events.register('post_execute', post_always)
303
303
304 try:
304 try:
305 ip.run_cell("1", silent=True)
305 ip.run_cell("1", silent=True)
306 assert pre_always.called
306 assert pre_always.called
307 assert not pre_explicit.called
307 assert not pre_explicit.called
308 assert post_always.called
308 assert post_always.called
309 assert not post_explicit.called
309 assert not post_explicit.called
310 # double-check that non-silent exec did what we expected
310 # double-check that non-silent exec did what we expected
311 # silent to avoid
311 # silent to avoid
312 ip.run_cell("1")
312 ip.run_cell("1")
313 assert pre_explicit.called
313 assert pre_explicit.called
314 assert post_explicit.called
314 assert post_explicit.called
315 finally:
315 finally:
316 # remove post-exec
316 # remove post-exec
317 ip.events.unregister('pre_run_cell', pre_explicit)
317 ip.events.unregister('pre_run_cell', pre_explicit)
318 ip.events.unregister('pre_execute', pre_always)
318 ip.events.unregister('pre_execute', pre_always)
319 ip.events.unregister('post_run_cell', post_explicit)
319 ip.events.unregister('post_run_cell', post_explicit)
320 ip.events.unregister('post_execute', post_always)
320 ip.events.unregister('post_execute', post_always)
321
321
322 def test_silent_noadvance(self):
322 def test_silent_noadvance(self):
323 """run_cell(silent=True) doesn't advance execution_count"""
323 """run_cell(silent=True) doesn't advance execution_count"""
324 ec = ip.execution_count
324 ec = ip.execution_count
325 # silent should force store_history=False
325 # silent should force store_history=False
326 ip.run_cell("1", store_history=True, silent=True)
326 ip.run_cell("1", store_history=True, silent=True)
327
327
328 self.assertEqual(ec, ip.execution_count)
328 self.assertEqual(ec, ip.execution_count)
329 # double-check that non-silent exec did what we expected
329 # double-check that non-silent exec did what we expected
330 # silent to avoid
330 # silent to avoid
331 ip.run_cell("1", store_history=True)
331 ip.run_cell("1", store_history=True)
332 self.assertEqual(ec+1, ip.execution_count)
332 self.assertEqual(ec+1, ip.execution_count)
333
333
334 def test_silent_nodisplayhook(self):
334 def test_silent_nodisplayhook(self):
335 """run_cell(silent=True) doesn't trigger displayhook"""
335 """run_cell(silent=True) doesn't trigger displayhook"""
336 d = dict(called=False)
336 d = dict(called=False)
337
337
338 trap = ip.display_trap
338 trap = ip.display_trap
339 save_hook = trap.hook
339 save_hook = trap.hook
340
340
341 def failing_hook(*args, **kwargs):
341 def failing_hook(*args, **kwargs):
342 d['called'] = True
342 d['called'] = True
343
343
344 try:
344 try:
345 trap.hook = failing_hook
345 trap.hook = failing_hook
346 res = ip.run_cell("1", silent=True)
346 res = ip.run_cell("1", silent=True)
347 self.assertFalse(d['called'])
347 self.assertFalse(d['called'])
348 self.assertIsNone(res.result)
348 self.assertIsNone(res.result)
349 # double-check that non-silent exec did what we expected
349 # double-check that non-silent exec did what we expected
350 # silent to avoid
350 # silent to avoid
351 ip.run_cell("1")
351 ip.run_cell("1")
352 self.assertTrue(d['called'])
352 self.assertTrue(d['called'])
353 finally:
353 finally:
354 trap.hook = save_hook
354 trap.hook = save_hook
355
355
356 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
356 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
357 def test_print_softspace(self):
357 def test_print_softspace(self):
358 """Verify that softspace is handled correctly when executing multiple
358 """Verify that softspace is handled correctly when executing multiple
359 statements.
359 statements.
360
360
361 In [1]: print 1; print 2
361 In [1]: print 1; print 2
362 1
362 1
363 2
363 2
364
364
365 In [2]: print 1,; print 2
365 In [2]: print 1,; print 2
366 1 2
366 1 2
367 """
367 """
368
368
369 def test_ofind_line_magic(self):
369 def test_ofind_line_magic(self):
370 from IPython.core.magic import register_line_magic
370 from IPython.core.magic import register_line_magic
371
371
372 @register_line_magic
372 @register_line_magic
373 def lmagic(line):
373 def lmagic(line):
374 "A line magic"
374 "A line magic"
375
375
376 # Get info on line magic
376 # Get info on line magic
377 lfind = ip._ofind('lmagic')
377 lfind = ip._ofind('lmagic')
378 info = dict(found=True, isalias=False, ismagic=True,
378 info = dict(found=True, isalias=False, ismagic=True,
379 namespace = 'IPython internal', obj= lmagic.__wrapped__,
379 namespace = 'IPython internal', obj= lmagic.__wrapped__,
380 parent = None)
380 parent = None)
381 nt.assert_equal(lfind, info)
381 nt.assert_equal(lfind, info)
382
382
383 def test_ofind_cell_magic(self):
383 def test_ofind_cell_magic(self):
384 from IPython.core.magic import register_cell_magic
384 from IPython.core.magic import register_cell_magic
385
385
386 @register_cell_magic
386 @register_cell_magic
387 def cmagic(line, cell):
387 def cmagic(line, cell):
388 "A cell magic"
388 "A cell magic"
389
389
390 # Get info on cell magic
390 # Get info on cell magic
391 find = ip._ofind('cmagic')
391 find = ip._ofind('cmagic')
392 info = dict(found=True, isalias=False, ismagic=True,
392 info = dict(found=True, isalias=False, ismagic=True,
393 namespace = 'IPython internal', obj= cmagic.__wrapped__,
393 namespace = 'IPython internal', obj= cmagic.__wrapped__,
394 parent = None)
394 parent = None)
395 nt.assert_equal(find, info)
395 nt.assert_equal(find, info)
396
396
397 def test_ofind_property_with_error(self):
397 def test_ofind_property_with_error(self):
398 class A(object):
398 class A(object):
399 @property
399 @property
400 def foo(self):
400 def foo(self):
401 raise NotImplementedError()
401 raise NotImplementedError()
402 a = A()
402 a = A()
403
403
404 found = ip._ofind('a.foo', [('locals', locals())])
404 found = ip._ofind('a.foo', [('locals', locals())])
405 info = dict(found=True, isalias=False, ismagic=False,
405 info = dict(found=True, isalias=False, ismagic=False,
406 namespace='locals', obj=A.foo, parent=a)
406 namespace='locals', obj=A.foo, parent=a)
407 nt.assert_equal(found, info)
407 nt.assert_equal(found, info)
408
408
409 def test_ofind_multiple_attribute_lookups(self):
409 def test_ofind_multiple_attribute_lookups(self):
410 class A(object):
410 class A(object):
411 @property
411 @property
412 def foo(self):
412 def foo(self):
413 raise NotImplementedError()
413 raise NotImplementedError()
414
414
415 a = A()
415 a = A()
416 a.a = A()
416 a.a = A()
417 a.a.a = A()
417 a.a.a = A()
418
418
419 found = ip._ofind('a.a.a.foo', [('locals', locals())])
419 found = ip._ofind('a.a.a.foo', [('locals', locals())])
420 info = dict(found=True, isalias=False, ismagic=False,
420 info = dict(found=True, isalias=False, ismagic=False,
421 namespace='locals', obj=A.foo, parent=a.a.a)
421 namespace='locals', obj=A.foo, parent=a.a.a)
422 nt.assert_equal(found, info)
422 nt.assert_equal(found, info)
423
423
424 def test_ofind_slotted_attributes(self):
424 def test_ofind_slotted_attributes(self):
425 class A(object):
425 class A(object):
426 __slots__ = ['foo']
426 __slots__ = ['foo']
427 def __init__(self):
427 def __init__(self):
428 self.foo = 'bar'
428 self.foo = 'bar'
429
429
430 a = A()
430 a = A()
431 found = ip._ofind('a.foo', [('locals', locals())])
431 found = ip._ofind('a.foo', [('locals', locals())])
432 info = dict(found=True, isalias=False, ismagic=False,
432 info = dict(found=True, isalias=False, ismagic=False,
433 namespace='locals', obj=a.foo, parent=a)
433 namespace='locals', obj=a.foo, parent=a)
434 nt.assert_equal(found, info)
434 nt.assert_equal(found, info)
435
435
436 found = ip._ofind('a.bar', [('locals', locals())])
436 found = ip._ofind('a.bar', [('locals', locals())])
437 info = dict(found=False, isalias=False, ismagic=False,
437 info = dict(found=False, isalias=False, ismagic=False,
438 namespace=None, obj=None, parent=a)
438 namespace=None, obj=None, parent=a)
439 nt.assert_equal(found, info)
439 nt.assert_equal(found, info)
440
440
441 def test_ofind_prefers_property_to_instance_level_attribute(self):
441 def test_ofind_prefers_property_to_instance_level_attribute(self):
442 class A(object):
442 class A(object):
443 @property
443 @property
444 def foo(self):
444 def foo(self):
445 return 'bar'
445 return 'bar'
446 a = A()
446 a = A()
447 a.__dict__['foo'] = 'baz'
447 a.__dict__['foo'] = 'baz'
448 nt.assert_equal(a.foo, 'bar')
448 nt.assert_equal(a.foo, 'bar')
449 found = ip._ofind('a.foo', [('locals', locals())])
449 found = ip._ofind('a.foo', [('locals', locals())])
450 nt.assert_is(found['obj'], A.foo)
450 nt.assert_is(found['obj'], A.foo)
451
451
452 def test_custom_exception(self):
452 def test_custom_exception(self):
453 called = []
453 called = []
454 def my_handler(shell, etype, value, tb, tb_offset=None):
454 def my_handler(shell, etype, value, tb, tb_offset=None):
455 called.append(etype)
455 called.append(etype)
456 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
456 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
457
457
458 ip.set_custom_exc((ValueError,), my_handler)
458 ip.set_custom_exc((ValueError,), my_handler)
459 try:
459 try:
460 res = ip.run_cell("raise ValueError('test')")
460 res = ip.run_cell("raise ValueError('test')")
461 # Check that this was called, and only once.
461 # Check that this was called, and only once.
462 self.assertEqual(called, [ValueError])
462 self.assertEqual(called, [ValueError])
463 # Check that the error is on the result object
463 # Check that the error is on the result object
464 self.assertIsInstance(res.error_in_exec, ValueError)
464 self.assertIsInstance(res.error_in_exec, ValueError)
465 finally:
465 finally:
466 # Reset the custom exception hook
466 # Reset the custom exception hook
467 ip.set_custom_exc((), None)
467 ip.set_custom_exc((), None)
468
468
469 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
469 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
470 def test_future_environment(self):
470 def test_future_environment(self):
471 "Can we run code with & without the shell's __future__ imports?"
471 "Can we run code with & without the shell's __future__ imports?"
472 ip.run_cell("from __future__ import division")
472 ip.run_cell("from __future__ import division")
473 ip.run_cell("a = 1/2", shell_futures=True)
473 ip.run_cell("a = 1/2", shell_futures=True)
474 self.assertEqual(ip.user_ns['a'], 0.5)
474 self.assertEqual(ip.user_ns['a'], 0.5)
475 ip.run_cell("b = 1/2", shell_futures=False)
475 ip.run_cell("b = 1/2", shell_futures=False)
476 self.assertEqual(ip.user_ns['b'], 0)
476 self.assertEqual(ip.user_ns['b'], 0)
477
477
478 ip.compile.reset_compiler_flags()
478 ip.compile.reset_compiler_flags()
479 # This shouldn't leak to the shell's compiler
479 # This shouldn't leak to the shell's compiler
480 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
480 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
481 self.assertEqual(ip.user_ns['c'], 0.5)
481 self.assertEqual(ip.user_ns['c'], 0.5)
482 ip.run_cell("d = 1/2", shell_futures=True)
482 ip.run_cell("d = 1/2", shell_futures=True)
483 self.assertEqual(ip.user_ns['d'], 0)
483 self.assertEqual(ip.user_ns['d'], 0)
484
484
485 def test_mktempfile(self):
485 def test_mktempfile(self):
486 filename = ip.mktempfile()
486 filename = ip.mktempfile()
487 # Check that we can open the file again on Windows
487 # Check that we can open the file again on Windows
488 with open(filename, 'w') as f:
488 with open(filename, 'w') as f:
489 f.write('abc')
489 f.write('abc')
490
490
491 filename = ip.mktempfile(data='blah')
491 filename = ip.mktempfile(data='blah')
492 with open(filename, 'r') as f:
492 with open(filename, 'r') as f:
493 self.assertEqual(f.read(), 'blah')
493 self.assertEqual(f.read(), 'blah')
494
494
495 def test_new_main_mod(self):
495 def test_new_main_mod(self):
496 # Smoketest to check that this accepts a unicode module name
496 # Smoketest to check that this accepts a unicode module name
497 name = u'jiefmw'
497 name = u'jiefmw'
498 mod = ip.new_main_mod(u'%s.py' % name, name)
498 mod = ip.new_main_mod(u'%s.py' % name, name)
499 self.assertEqual(mod.__name__, name)
499 self.assertEqual(mod.__name__, name)
500
500
501 def test_get_exception_only(self):
501 def test_get_exception_only(self):
502 try:
502 try:
503 raise KeyboardInterrupt
503 raise KeyboardInterrupt
504 except KeyboardInterrupt:
504 except KeyboardInterrupt:
505 msg = ip.get_exception_only()
505 msg = ip.get_exception_only()
506 self.assertEqual(msg, 'KeyboardInterrupt\n')
506 self.assertEqual(msg, 'KeyboardInterrupt\n')
507
507
508 try:
508 try:
509 raise DerivedInterrupt("foo")
509 raise DerivedInterrupt("foo")
510 except KeyboardInterrupt:
510 except KeyboardInterrupt:
511 msg = ip.get_exception_only()
511 msg = ip.get_exception_only()
512 if sys.version_info[0] <= 2:
512 if sys.version_info[0] <= 2:
513 self.assertEqual(msg, 'DerivedInterrupt: foo\n')
513 self.assertEqual(msg, 'DerivedInterrupt: foo\n')
514 else:
514 else:
515 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
515 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
516
516
517 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
517 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
518
518
519 @onlyif_unicode_paths
519 @onlyif_unicode_paths
520 def setUp(self):
520 def setUp(self):
521 self.BASETESTDIR = tempfile.mkdtemp()
521 self.BASETESTDIR = tempfile.mkdtemp()
522 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
522 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
523 os.mkdir(self.TESTDIR)
523 os.mkdir(self.TESTDIR)
524 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
524 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
525 sfile.write("pass\n")
525 sfile.write("pass\n")
526 self.oldpath = py3compat.getcwd()
526 self.oldpath = py3compat.getcwd()
527 os.chdir(self.TESTDIR)
527 os.chdir(self.TESTDIR)
528 self.fname = u"Γ₯Àâtestscript.py"
528 self.fname = u"Γ₯Àâtestscript.py"
529
529
530 def tearDown(self):
530 def tearDown(self):
531 os.chdir(self.oldpath)
531 os.chdir(self.oldpath)
532 shutil.rmtree(self.BASETESTDIR)
532 shutil.rmtree(self.BASETESTDIR)
533
533
534 @onlyif_unicode_paths
534 @onlyif_unicode_paths
535 def test_1(self):
535 def test_1(self):
536 """Test safe_execfile with non-ascii path
536 """Test safe_execfile with non-ascii path
537 """
537 """
538 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
538 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
539
539
540 class ExitCodeChecks(tt.TempFileMixin):
540 class ExitCodeChecks(tt.TempFileMixin):
541 def test_exit_code_ok(self):
541 def test_exit_code_ok(self):
542 self.system('exit 0')
542 self.system('exit 0')
543 self.assertEqual(ip.user_ns['_exit_code'], 0)
543 self.assertEqual(ip.user_ns['_exit_code'], 0)
544
544
545 def test_exit_code_error(self):
545 def test_exit_code_error(self):
546 self.system('exit 1')
546 self.system('exit 1')
547 self.assertEqual(ip.user_ns['_exit_code'], 1)
547 self.assertEqual(ip.user_ns['_exit_code'], 1)
548
548
549 @skipif(not hasattr(signal, 'SIGALRM'))
549 @skipif(not hasattr(signal, 'SIGALRM'))
550 def test_exit_code_signal(self):
550 def test_exit_code_signal(self):
551 self.mktmp("import signal, time\n"
551 self.mktmp("import signal, time\n"
552 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
552 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
553 "time.sleep(1)\n")
553 "time.sleep(1)\n")
554 self.system("%s %s" % (sys.executable, self.fname))
554 self.system("%s %s" % (sys.executable, self.fname))
555 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
555 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
556
556
557 @onlyif_cmds_exist("csh")
557 @onlyif_cmds_exist("csh")
558 def test_exit_code_signal_csh(self):
558 def test_exit_code_signal_csh(self):
559 SHELL = os.environ.get('SHELL', None)
559 SHELL = os.environ.get('SHELL', None)
560 os.environ['SHELL'] = find_cmd("csh")
560 os.environ['SHELL'] = find_cmd("csh")
561 try:
561 try:
562 self.test_exit_code_signal()
562 self.test_exit_code_signal()
563 finally:
563 finally:
564 if SHELL is not None:
564 if SHELL is not None:
565 os.environ['SHELL'] = SHELL
565 os.environ['SHELL'] = SHELL
566 else:
566 else:
567 del os.environ['SHELL']
567 del os.environ['SHELL']
568
568
569 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
569 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
570 system = ip.system_raw
570 system = ip.system_raw
571
571
572 @onlyif_unicode_paths
572 @onlyif_unicode_paths
573 def test_1(self):
573 def test_1(self):
574 """Test system_raw with non-ascii cmd
574 """Test system_raw with non-ascii cmd
575 """
575 """
576 cmd = u'''python -c "'Γ₯Àâ'" '''
576 cmd = u'''python -c "'Γ₯Àâ'" '''
577 ip.system_raw(cmd)
577 ip.system_raw(cmd)
578
578
579 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
579 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
580 @mock.patch('os.system', side_effect=KeyboardInterrupt)
580 @mock.patch('os.system', side_effect=KeyboardInterrupt)
581 def test_control_c(self, *mocks):
581 def test_control_c(self, *mocks):
582 try:
582 try:
583 self.system("sleep 1 # wont happen")
583 self.system("sleep 1 # wont happen")
584 except KeyboardInterrupt:
584 except KeyboardInterrupt:
585 self.fail("system call should intercept "
585 self.fail("system call should intercept "
586 "keyboard interrupt from subprocess.call")
586 "keyboard interrupt from subprocess.call")
587 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
587 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGINT)
588
588
589 # TODO: Exit codes are currently ignored on Windows.
589 # TODO: Exit codes are currently ignored on Windows.
590 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
590 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
591 system = ip.system_piped
591 system = ip.system_piped
592
592
593 @skip_win32
593 @skip_win32
594 def test_exit_code_ok(self):
594 def test_exit_code_ok(self):
595 ExitCodeChecks.test_exit_code_ok(self)
595 ExitCodeChecks.test_exit_code_ok(self)
596
596
597 @skip_win32
597 @skip_win32
598 def test_exit_code_error(self):
598 def test_exit_code_error(self):
599 ExitCodeChecks.test_exit_code_error(self)
599 ExitCodeChecks.test_exit_code_error(self)
600
600
601 @skip_win32
601 @skip_win32
602 def test_exit_code_signal(self):
602 def test_exit_code_signal(self):
603 ExitCodeChecks.test_exit_code_signal(self)
603 ExitCodeChecks.test_exit_code_signal(self)
604
604
605 class TestModules(unittest.TestCase, tt.TempFileMixin):
605 class TestModules(unittest.TestCase, tt.TempFileMixin):
606 def test_extraneous_loads(self):
606 def test_extraneous_loads(self):
607 """Test we're not loading modules on startup that we shouldn't.
607 """Test we're not loading modules on startup that we shouldn't.
608 """
608 """
609 self.mktmp("import sys\n"
609 self.mktmp("import sys\n"
610 "print('numpy' in sys.modules)\n"
610 "print('numpy' in sys.modules)\n"
611 "print('ipyparallel' in sys.modules)\n"
611 "print('ipyparallel' in sys.modules)\n"
612 "print('ipython_kernel' in sys.modules)\n"
612 "print('ipykernel' in sys.modules)\n"
613 )
613 )
614 out = "False\nFalse\nFalse\n"
614 out = "False\nFalse\nFalse\n"
615 tt.ipexec_validate(self.fname, out)
615 tt.ipexec_validate(self.fname, out)
616
616
617 class Negator(ast.NodeTransformer):
617 class Negator(ast.NodeTransformer):
618 """Negates all number literals in an AST."""
618 """Negates all number literals in an AST."""
619 def visit_Num(self, node):
619 def visit_Num(self, node):
620 node.n = -node.n
620 node.n = -node.n
621 return node
621 return node
622
622
623 class TestAstTransform(unittest.TestCase):
623 class TestAstTransform(unittest.TestCase):
624 def setUp(self):
624 def setUp(self):
625 self.negator = Negator()
625 self.negator = Negator()
626 ip.ast_transformers.append(self.negator)
626 ip.ast_transformers.append(self.negator)
627
627
628 def tearDown(self):
628 def tearDown(self):
629 ip.ast_transformers.remove(self.negator)
629 ip.ast_transformers.remove(self.negator)
630
630
631 def test_run_cell(self):
631 def test_run_cell(self):
632 with tt.AssertPrints('-34'):
632 with tt.AssertPrints('-34'):
633 ip.run_cell('print (12 + 22)')
633 ip.run_cell('print (12 + 22)')
634
634
635 # A named reference to a number shouldn't be transformed.
635 # A named reference to a number shouldn't be transformed.
636 ip.user_ns['n'] = 55
636 ip.user_ns['n'] = 55
637 with tt.AssertNotPrints('-55'):
637 with tt.AssertNotPrints('-55'):
638 ip.run_cell('print (n)')
638 ip.run_cell('print (n)')
639
639
640 def test_timeit(self):
640 def test_timeit(self):
641 called = set()
641 called = set()
642 def f(x):
642 def f(x):
643 called.add(x)
643 called.add(x)
644 ip.push({'f':f})
644 ip.push({'f':f})
645
645
646 with tt.AssertPrints("best of "):
646 with tt.AssertPrints("best of "):
647 ip.run_line_magic("timeit", "-n1 f(1)")
647 ip.run_line_magic("timeit", "-n1 f(1)")
648 self.assertEqual(called, set([-1]))
648 self.assertEqual(called, set([-1]))
649 called.clear()
649 called.clear()
650
650
651 with tt.AssertPrints("best of "):
651 with tt.AssertPrints("best of "):
652 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
652 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
653 self.assertEqual(called, set([-2, -3]))
653 self.assertEqual(called, set([-2, -3]))
654
654
655 def test_time(self):
655 def test_time(self):
656 called = []
656 called = []
657 def f(x):
657 def f(x):
658 called.append(x)
658 called.append(x)
659 ip.push({'f':f})
659 ip.push({'f':f})
660
660
661 # Test with an expression
661 # Test with an expression
662 with tt.AssertPrints("Wall time: "):
662 with tt.AssertPrints("Wall time: "):
663 ip.run_line_magic("time", "f(5+9)")
663 ip.run_line_magic("time", "f(5+9)")
664 self.assertEqual(called, [-14])
664 self.assertEqual(called, [-14])
665 called[:] = []
665 called[:] = []
666
666
667 # Test with a statement (different code path)
667 # Test with a statement (different code path)
668 with tt.AssertPrints("Wall time: "):
668 with tt.AssertPrints("Wall time: "):
669 ip.run_line_magic("time", "a = f(-3 + -2)")
669 ip.run_line_magic("time", "a = f(-3 + -2)")
670 self.assertEqual(called, [5])
670 self.assertEqual(called, [5])
671
671
672 def test_macro(self):
672 def test_macro(self):
673 ip.push({'a':10})
673 ip.push({'a':10})
674 # The AST transformation makes this do a+=-1
674 # The AST transformation makes this do a+=-1
675 ip.define_macro("amacro", "a+=1\nprint(a)")
675 ip.define_macro("amacro", "a+=1\nprint(a)")
676
676
677 with tt.AssertPrints("9"):
677 with tt.AssertPrints("9"):
678 ip.run_cell("amacro")
678 ip.run_cell("amacro")
679 with tt.AssertPrints("8"):
679 with tt.AssertPrints("8"):
680 ip.run_cell("amacro")
680 ip.run_cell("amacro")
681
681
682 class IntegerWrapper(ast.NodeTransformer):
682 class IntegerWrapper(ast.NodeTransformer):
683 """Wraps all integers in a call to Integer()"""
683 """Wraps all integers in a call to Integer()"""
684 def visit_Num(self, node):
684 def visit_Num(self, node):
685 if isinstance(node.n, int):
685 if isinstance(node.n, int):
686 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
686 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
687 args=[node], keywords=[])
687 args=[node], keywords=[])
688 return node
688 return node
689
689
690 class TestAstTransform2(unittest.TestCase):
690 class TestAstTransform2(unittest.TestCase):
691 def setUp(self):
691 def setUp(self):
692 self.intwrapper = IntegerWrapper()
692 self.intwrapper = IntegerWrapper()
693 ip.ast_transformers.append(self.intwrapper)
693 ip.ast_transformers.append(self.intwrapper)
694
694
695 self.calls = []
695 self.calls = []
696 def Integer(*args):
696 def Integer(*args):
697 self.calls.append(args)
697 self.calls.append(args)
698 return args
698 return args
699 ip.push({"Integer": Integer})
699 ip.push({"Integer": Integer})
700
700
701 def tearDown(self):
701 def tearDown(self):
702 ip.ast_transformers.remove(self.intwrapper)
702 ip.ast_transformers.remove(self.intwrapper)
703 del ip.user_ns['Integer']
703 del ip.user_ns['Integer']
704
704
705 def test_run_cell(self):
705 def test_run_cell(self):
706 ip.run_cell("n = 2")
706 ip.run_cell("n = 2")
707 self.assertEqual(self.calls, [(2,)])
707 self.assertEqual(self.calls, [(2,)])
708
708
709 # This shouldn't throw an error
709 # This shouldn't throw an error
710 ip.run_cell("o = 2.0")
710 ip.run_cell("o = 2.0")
711 self.assertEqual(ip.user_ns['o'], 2.0)
711 self.assertEqual(ip.user_ns['o'], 2.0)
712
712
713 def test_timeit(self):
713 def test_timeit(self):
714 called = set()
714 called = set()
715 def f(x):
715 def f(x):
716 called.add(x)
716 called.add(x)
717 ip.push({'f':f})
717 ip.push({'f':f})
718
718
719 with tt.AssertPrints("best of "):
719 with tt.AssertPrints("best of "):
720 ip.run_line_magic("timeit", "-n1 f(1)")
720 ip.run_line_magic("timeit", "-n1 f(1)")
721 self.assertEqual(called, set([(1,)]))
721 self.assertEqual(called, set([(1,)]))
722 called.clear()
722 called.clear()
723
723
724 with tt.AssertPrints("best of "):
724 with tt.AssertPrints("best of "):
725 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
725 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
726 self.assertEqual(called, set([(2,), (3,)]))
726 self.assertEqual(called, set([(2,), (3,)]))
727
727
728 class ErrorTransformer(ast.NodeTransformer):
728 class ErrorTransformer(ast.NodeTransformer):
729 """Throws an error when it sees a number."""
729 """Throws an error when it sees a number."""
730 def visit_Num(self, node):
730 def visit_Num(self, node):
731 raise ValueError("test")
731 raise ValueError("test")
732
732
733 class TestAstTransformError(unittest.TestCase):
733 class TestAstTransformError(unittest.TestCase):
734 def test_unregistering(self):
734 def test_unregistering(self):
735 err_transformer = ErrorTransformer()
735 err_transformer = ErrorTransformer()
736 ip.ast_transformers.append(err_transformer)
736 ip.ast_transformers.append(err_transformer)
737
737
738 with tt.AssertPrints("unregister", channel='stderr'):
738 with tt.AssertPrints("unregister", channel='stderr'):
739 ip.run_cell("1 + 2")
739 ip.run_cell("1 + 2")
740
740
741 # This should have been removed.
741 # This should have been removed.
742 nt.assert_not_in(err_transformer, ip.ast_transformers)
742 nt.assert_not_in(err_transformer, ip.ast_transformers)
743
743
744
744
745 class StringRejector(ast.NodeTransformer):
745 class StringRejector(ast.NodeTransformer):
746 """Throws an InputRejected when it sees a string literal.
746 """Throws an InputRejected when it sees a string literal.
747
747
748 Used to verify that NodeTransformers can signal that a piece of code should
748 Used to verify that NodeTransformers can signal that a piece of code should
749 not be executed by throwing an InputRejected.
749 not be executed by throwing an InputRejected.
750 """
750 """
751
751
752 def visit_Str(self, node):
752 def visit_Str(self, node):
753 raise InputRejected("test")
753 raise InputRejected("test")
754
754
755
755
756 class TestAstTransformInputRejection(unittest.TestCase):
756 class TestAstTransformInputRejection(unittest.TestCase):
757
757
758 def setUp(self):
758 def setUp(self):
759 self.transformer = StringRejector()
759 self.transformer = StringRejector()
760 ip.ast_transformers.append(self.transformer)
760 ip.ast_transformers.append(self.transformer)
761
761
762 def tearDown(self):
762 def tearDown(self):
763 ip.ast_transformers.remove(self.transformer)
763 ip.ast_transformers.remove(self.transformer)
764
764
765 def test_input_rejection(self):
765 def test_input_rejection(self):
766 """Check that NodeTransformers can reject input."""
766 """Check that NodeTransformers can reject input."""
767
767
768 expect_exception_tb = tt.AssertPrints("InputRejected: test")
768 expect_exception_tb = tt.AssertPrints("InputRejected: test")
769 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
769 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
770
770
771 # Run the same check twice to verify that the transformer is not
771 # Run the same check twice to verify that the transformer is not
772 # disabled after raising.
772 # disabled after raising.
773 with expect_exception_tb, expect_no_cell_output:
773 with expect_exception_tb, expect_no_cell_output:
774 ip.run_cell("'unsafe'")
774 ip.run_cell("'unsafe'")
775
775
776 with expect_exception_tb, expect_no_cell_output:
776 with expect_exception_tb, expect_no_cell_output:
777 res = ip.run_cell("'unsafe'")
777 res = ip.run_cell("'unsafe'")
778
778
779 self.assertIsInstance(res.error_before_exec, InputRejected)
779 self.assertIsInstance(res.error_before_exec, InputRejected)
780
780
781 def test__IPYTHON__():
781 def test__IPYTHON__():
782 # This shouldn't raise a NameError, that's all
782 # This shouldn't raise a NameError, that's all
783 __IPYTHON__
783 __IPYTHON__
784
784
785
785
786 class DummyRepr(object):
786 class DummyRepr(object):
787 def __repr__(self):
787 def __repr__(self):
788 return "DummyRepr"
788 return "DummyRepr"
789
789
790 def _repr_html_(self):
790 def _repr_html_(self):
791 return "<b>dummy</b>"
791 return "<b>dummy</b>"
792
792
793 def _repr_javascript_(self):
793 def _repr_javascript_(self):
794 return "console.log('hi');", {'key': 'value'}
794 return "console.log('hi');", {'key': 'value'}
795
795
796
796
797 def test_user_variables():
797 def test_user_variables():
798 # enable all formatters
798 # enable all formatters
799 ip.display_formatter.active_types = ip.display_formatter.format_types
799 ip.display_formatter.active_types = ip.display_formatter.format_types
800
800
801 ip.user_ns['dummy'] = d = DummyRepr()
801 ip.user_ns['dummy'] = d = DummyRepr()
802 keys = set(['dummy', 'doesnotexist'])
802 keys = set(['dummy', 'doesnotexist'])
803 r = ip.user_expressions({ key:key for key in keys})
803 r = ip.user_expressions({ key:key for key in keys})
804
804
805 nt.assert_equal(keys, set(r.keys()))
805 nt.assert_equal(keys, set(r.keys()))
806 dummy = r['dummy']
806 dummy = r['dummy']
807 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
807 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
808 nt.assert_equal(dummy['status'], 'ok')
808 nt.assert_equal(dummy['status'], 'ok')
809 data = dummy['data']
809 data = dummy['data']
810 metadata = dummy['metadata']
810 metadata = dummy['metadata']
811 nt.assert_equal(data.get('text/html'), d._repr_html_())
811 nt.assert_equal(data.get('text/html'), d._repr_html_())
812 js, jsmd = d._repr_javascript_()
812 js, jsmd = d._repr_javascript_()
813 nt.assert_equal(data.get('application/javascript'), js)
813 nt.assert_equal(data.get('application/javascript'), js)
814 nt.assert_equal(metadata.get('application/javascript'), jsmd)
814 nt.assert_equal(metadata.get('application/javascript'), jsmd)
815
815
816 dne = r['doesnotexist']
816 dne = r['doesnotexist']
817 nt.assert_equal(dne['status'], 'error')
817 nt.assert_equal(dne['status'], 'error')
818 nt.assert_equal(dne['ename'], 'NameError')
818 nt.assert_equal(dne['ename'], 'NameError')
819
819
820 # back to text only
820 # back to text only
821 ip.display_formatter.active_types = ['text/plain']
821 ip.display_formatter.active_types = ['text/plain']
822
822
823 def test_user_expression():
823 def test_user_expression():
824 # enable all formatters
824 # enable all formatters
825 ip.display_formatter.active_types = ip.display_formatter.format_types
825 ip.display_formatter.active_types = ip.display_formatter.format_types
826 query = {
826 query = {
827 'a' : '1 + 2',
827 'a' : '1 + 2',
828 'b' : '1/0',
828 'b' : '1/0',
829 }
829 }
830 r = ip.user_expressions(query)
830 r = ip.user_expressions(query)
831 import pprint
831 import pprint
832 pprint.pprint(r)
832 pprint.pprint(r)
833 nt.assert_equal(set(r.keys()), set(query.keys()))
833 nt.assert_equal(set(r.keys()), set(query.keys()))
834 a = r['a']
834 a = r['a']
835 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
835 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
836 nt.assert_equal(a['status'], 'ok')
836 nt.assert_equal(a['status'], 'ok')
837 data = a['data']
837 data = a['data']
838 metadata = a['metadata']
838 metadata = a['metadata']
839 nt.assert_equal(data.get('text/plain'), '3')
839 nt.assert_equal(data.get('text/plain'), '3')
840
840
841 b = r['b']
841 b = r['b']
842 nt.assert_equal(b['status'], 'error')
842 nt.assert_equal(b['status'], 'error')
843 nt.assert_equal(b['ename'], 'ZeroDivisionError')
843 nt.assert_equal(b['ename'], 'ZeroDivisionError')
844
844
845 # back to text only
845 # back to text only
846 ip.display_formatter.active_types = ['text/plain']
846 ip.display_formatter.active_types = ['text/plain']
847
847
848
848
849
849
850
850
851
851
852 class TestSyntaxErrorTransformer(unittest.TestCase):
852 class TestSyntaxErrorTransformer(unittest.TestCase):
853 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
853 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
854
854
855 class SyntaxErrorTransformer(InputTransformer):
855 class SyntaxErrorTransformer(InputTransformer):
856
856
857 def push(self, line):
857 def push(self, line):
858 pos = line.find('syntaxerror')
858 pos = line.find('syntaxerror')
859 if pos >= 0:
859 if pos >= 0:
860 e = SyntaxError('input contains "syntaxerror"')
860 e = SyntaxError('input contains "syntaxerror"')
861 e.text = line
861 e.text = line
862 e.offset = pos + 1
862 e.offset = pos + 1
863 raise e
863 raise e
864 return line
864 return line
865
865
866 def reset(self):
866 def reset(self):
867 pass
867 pass
868
868
869 def setUp(self):
869 def setUp(self):
870 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
870 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
871 ip.input_splitter.python_line_transforms.append(self.transformer)
871 ip.input_splitter.python_line_transforms.append(self.transformer)
872 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
872 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
873
873
874 def tearDown(self):
874 def tearDown(self):
875 ip.input_splitter.python_line_transforms.remove(self.transformer)
875 ip.input_splitter.python_line_transforms.remove(self.transformer)
876 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
876 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
877
877
878 def test_syntaxerror_input_transformer(self):
878 def test_syntaxerror_input_transformer(self):
879 with tt.AssertPrints('1234'):
879 with tt.AssertPrints('1234'):
880 ip.run_cell('1234')
880 ip.run_cell('1234')
881 with tt.AssertPrints('SyntaxError: invalid syntax'):
881 with tt.AssertPrints('SyntaxError: invalid syntax'):
882 ip.run_cell('1 2 3') # plain python syntax error
882 ip.run_cell('1 2 3') # plain python syntax error
883 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
883 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
884 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
884 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
885 with tt.AssertPrints('3456'):
885 with tt.AssertPrints('3456'):
886 ip.run_cell('3456')
886 ip.run_cell('3456')
887
887
888
888
889
889
890 def test_warning_suppression():
890 def test_warning_suppression():
891 ip.run_cell("import warnings")
891 ip.run_cell("import warnings")
892 try:
892 try:
893 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
893 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
894 ip.run_cell("warnings.warn('asdf')")
894 ip.run_cell("warnings.warn('asdf')")
895 # Here's the real test -- if we run that again, we should get the
895 # Here's the real test -- if we run that again, we should get the
896 # warning again. Traditionally, each warning was only issued once per
896 # warning again. Traditionally, each warning was only issued once per
897 # IPython session (approximately), even if the user typed in new and
897 # IPython session (approximately), even if the user typed in new and
898 # different code that should have also triggered the warning, leading
898 # different code that should have also triggered the warning, leading
899 # to much confusion.
899 # to much confusion.
900 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
900 with tt.AssertPrints("UserWarning: asdf", channel="stderr"):
901 ip.run_cell("warnings.warn('asdf')")
901 ip.run_cell("warnings.warn('asdf')")
902 finally:
902 finally:
903 ip.run_cell("del warnings")
903 ip.run_cell("del warnings")
@@ -1,35 +1,35 b''
1 """
1 """
2 Shim to maintain backwards compatibility with old IPython.kernel imports.
2 Shim to maintain backwards compatibility with old IPython.kernel imports.
3 """
3 """
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import sys
7 import sys
8 from warnings import warn
8 from warnings import warn
9
9
10 warn("The `IPython.kernel` package has been deprecated. "
10 warn("The `IPython.kernel` package has been deprecated. "
11 "You should import from ipython_kernel or jupyter_client instead.")
11 "You should import from ipykernel or jupyter_client instead.")
12
12
13
13
14 from IPython.utils.shimmodule import ShimModule
14 from IPython.utils.shimmodule import ShimModule
15
15
16 # zmq subdir is gone
16 # zmq subdir is gone
17 sys.modules['IPython.kernel.zmq.session'] = ShimModule(
17 sys.modules['IPython.kernel.zmq.session'] = ShimModule(
18 src='IPython.kernel.zmq.session', mirror='jupyter_client.session')
18 src='IPython.kernel.zmq.session', mirror='jupyter_client.session')
19 sys.modules['IPython.kernel.zmq'] = ShimModule(
19 sys.modules['IPython.kernel.zmq'] = ShimModule(
20 src='IPython.kernel.zmq', mirror='ipython_kernel')
20 src='IPython.kernel.zmq', mirror='ipykernel')
21
21
22 for pkg in ('comm', 'inprocess'):
22 for pkg in ('comm', 'inprocess'):
23 src = 'IPython.kernel.%s' % pkg
23 src = 'IPython.kernel.%s' % pkg
24 sys.modules[src] = ShimModule(src=src, mirror='ipython_kernel.%s' % pkg)
24 sys.modules[src] = ShimModule(src=src, mirror='ipykernel.%s' % pkg)
25
25
26 for pkg in ('ioloop', 'blocking'):
26 for pkg in ('ioloop', 'blocking'):
27 src = 'IPython.kernel.%s' % pkg
27 src = 'IPython.kernel.%s' % pkg
28 sys.modules[src] = ShimModule(src=src, mirror='jupyter_client.%s' % pkg)
28 sys.modules[src] = ShimModule(src=src, mirror='jupyter_client.%s' % pkg)
29
29
30 # required for `from IPython.kernel import PKG`
30 # required for `from IPython.kernel import PKG`
31 from ipython_kernel import comm, inprocess
31 from ipykernel import comm, inprocess
32 from jupyter_client import ioloop, blocking
32 from jupyter_client import ioloop, blocking
33 # public API
33 # public API
34 from ipython_kernel.connect import *
34 from ipykernel.connect import *
35 from jupyter_client import *
35 from jupyter_client import *
@@ -1,3 +1,3 b''
1 if __name__ == '__main__':
1 if __name__ == '__main__':
2 from ipython_kernel import kernelapp as app
2 from ipykernel import kernelapp as app
3 app.launch_new_instance()
3 app.launch_new_instance()
@@ -1,2 +1,2 b''
1 from ipython_kernel.connect import *
1 from ipykernel.connect import *
2 from jupyter_client.connect import *
2 from jupyter_client.connect import *
@@ -1,12 +1,12 b''
1 """[DEPRECATED] Utilities for connecting to kernels
1 """[DEPRECATED] Utilities for connecting to kernels
2
2
3 Moved to IPython.kernel.connect
3 Moved to IPython.kernel.connect
4 """
4 """
5
5
6 import warnings
6 import warnings
7 warnings.warn("IPython.lib.kernel moved to IPython.kernel.connect in IPython 1.0",
7 warnings.warn("IPython.lib.kernel moved to IPython.kernel.connect in IPython 1.0",
8 DeprecationWarning
8 DeprecationWarning
9 )
9 )
10
10
11 from ipython_kernel.connect import *
11 from ipykernel.connect import *
12
12
@@ -1,374 +1,374 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6 """
6 """
7
7
8 # Copyright (c) IPython Development Team.
8 # Copyright (c) IPython Development Team.
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12 from __future__ import print_function
12 from __future__ import print_function
13
13
14 import logging
14 import logging
15 import os
15 import os
16 import sys
16 import sys
17
17
18 from traitlets.config.loader import Config
18 from traitlets.config.loader import Config
19 from traitlets.config.application import boolean_flag, catch_config_error, Application
19 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 from IPython.core import release
20 from IPython.core import release
21 from IPython.core import usage
21 from IPython.core import usage
22 from IPython.core.completer import IPCompleter
22 from IPython.core.completer import IPCompleter
23 from IPython.core.crashhandler import CrashHandler
23 from IPython.core.crashhandler import CrashHandler
24 from IPython.core.formatters import PlainTextFormatter
24 from IPython.core.formatters import PlainTextFormatter
25 from IPython.core.history import HistoryManager
25 from IPython.core.history import HistoryManager
26 from IPython.core.prompts import PromptManager
26 from IPython.core.prompts import PromptManager
27 from IPython.core.application import (
27 from IPython.core.application import (
28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 )
29 )
30 from IPython.core.magics import ScriptMagics
30 from IPython.core.magics import ScriptMagics
31 from IPython.core.shellapp import (
31 from IPython.core.shellapp import (
32 InteractiveShellApp, shell_flags, shell_aliases
32 InteractiveShellApp, shell_flags, shell_aliases
33 )
33 )
34 from IPython.extensions.storemagic import StoreMagics
34 from IPython.extensions.storemagic import StoreMagics
35 from IPython.terminal.interactiveshell import TerminalInteractiveShell
35 from IPython.terminal.interactiveshell import TerminalInteractiveShell
36 from IPython.utils import warn
36 from IPython.utils import warn
37 from IPython.paths import get_ipython_dir
37 from IPython.paths import get_ipython_dir
38 from traitlets import (
38 from traitlets import (
39 Bool, List, Dict,
39 Bool, List, Dict,
40 )
40 )
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Globals, utilities and helpers
43 # Globals, utilities and helpers
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 _examples = """
46 _examples = """
47 ipython --matplotlib # enable matplotlib integration
47 ipython --matplotlib # enable matplotlib integration
48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
49
49
50 ipython --log-level=DEBUG # set logging to DEBUG
50 ipython --log-level=DEBUG # set logging to DEBUG
51 ipython --profile=foo # start with profile foo
51 ipython --profile=foo # start with profile foo
52
52
53 ipython qtconsole # start the qtconsole GUI application
53 ipython qtconsole # start the qtconsole GUI application
54 ipython help qtconsole # show the help for the qtconsole subcmd
54 ipython help qtconsole # show the help for the qtconsole subcmd
55
55
56 ipython console # start the terminal-based console application
56 ipython console # start the terminal-based console application
57 ipython help console # show the help for the console subcmd
57 ipython help console # show the help for the console subcmd
58
58
59 ipython notebook # start the IPython notebook
59 ipython notebook # start the IPython notebook
60 ipython help notebook # show the help for the notebook subcmd
60 ipython help notebook # show the help for the notebook subcmd
61
61
62 ipython profile create foo # create profile foo w/ default config files
62 ipython profile create foo # create profile foo w/ default config files
63 ipython help profile # show the help for the profile subcmd
63 ipython help profile # show the help for the profile subcmd
64
64
65 ipython locate # print the path to the IPython directory
65 ipython locate # print the path to the IPython directory
66 ipython locate profile foo # print the path to the directory for profile `foo`
66 ipython locate profile foo # print the path to the directory for profile `foo`
67
67
68 ipython nbconvert # convert notebooks to/from other formats
68 ipython nbconvert # convert notebooks to/from other formats
69 """
69 """
70
70
71 #-----------------------------------------------------------------------------
71 #-----------------------------------------------------------------------------
72 # Crash handler for this application
72 # Crash handler for this application
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74
74
75 class IPAppCrashHandler(CrashHandler):
75 class IPAppCrashHandler(CrashHandler):
76 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
76 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
77
77
78 def __init__(self, app):
78 def __init__(self, app):
79 contact_name = release.author
79 contact_name = release.author
80 contact_email = release.author_email
80 contact_email = release.author_email
81 bug_tracker = 'https://github.com/ipython/ipython/issues'
81 bug_tracker = 'https://github.com/ipython/ipython/issues'
82 super(IPAppCrashHandler,self).__init__(
82 super(IPAppCrashHandler,self).__init__(
83 app, contact_name, contact_email, bug_tracker
83 app, contact_name, contact_email, bug_tracker
84 )
84 )
85
85
86 def make_report(self,traceback):
86 def make_report(self,traceback):
87 """Return a string containing a crash report."""
87 """Return a string containing a crash report."""
88
88
89 sec_sep = self.section_sep
89 sec_sep = self.section_sep
90 # Start with parent report
90 # Start with parent report
91 report = [super(IPAppCrashHandler, self).make_report(traceback)]
91 report = [super(IPAppCrashHandler, self).make_report(traceback)]
92 # Add interactive-specific info we may have
92 # Add interactive-specific info we may have
93 rpt_add = report.append
93 rpt_add = report.append
94 try:
94 try:
95 rpt_add(sec_sep+"History of session input:")
95 rpt_add(sec_sep+"History of session input:")
96 for line in self.app.shell.user_ns['_ih']:
96 for line in self.app.shell.user_ns['_ih']:
97 rpt_add(line)
97 rpt_add(line)
98 rpt_add('\n*** Last line of input (may not be in above history):\n')
98 rpt_add('\n*** Last line of input (may not be in above history):\n')
99 rpt_add(self.app.shell._last_input_line+'\n')
99 rpt_add(self.app.shell._last_input_line+'\n')
100 except:
100 except:
101 pass
101 pass
102
102
103 return ''.join(report)
103 return ''.join(report)
104
104
105 #-----------------------------------------------------------------------------
105 #-----------------------------------------------------------------------------
106 # Aliases and Flags
106 # Aliases and Flags
107 #-----------------------------------------------------------------------------
107 #-----------------------------------------------------------------------------
108 flags = dict(base_flags)
108 flags = dict(base_flags)
109 flags.update(shell_flags)
109 flags.update(shell_flags)
110 frontend_flags = {}
110 frontend_flags = {}
111 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
111 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
112 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
112 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
113 'Turn on auto editing of files with syntax errors.',
113 'Turn on auto editing of files with syntax errors.',
114 'Turn off auto editing of files with syntax errors.'
114 'Turn off auto editing of files with syntax errors.'
115 )
115 )
116 addflag('banner', 'TerminalIPythonApp.display_banner',
116 addflag('banner', 'TerminalIPythonApp.display_banner',
117 "Display a banner upon starting IPython.",
117 "Display a banner upon starting IPython.",
118 "Don't display a banner upon starting IPython."
118 "Don't display a banner upon starting IPython."
119 )
119 )
120 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
120 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
121 """Set to confirm when you try to exit IPython with an EOF (Control-D
121 """Set to confirm when you try to exit IPython with an EOF (Control-D
122 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
122 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
123 you can force a direct exit without any confirmation.""",
123 you can force a direct exit without any confirmation.""",
124 "Don't prompt the user when exiting."
124 "Don't prompt the user when exiting."
125 )
125 )
126 addflag('term-title', 'TerminalInteractiveShell.term_title',
126 addflag('term-title', 'TerminalInteractiveShell.term_title',
127 "Enable auto setting the terminal title.",
127 "Enable auto setting the terminal title.",
128 "Disable auto setting the terminal title."
128 "Disable auto setting the terminal title."
129 )
129 )
130 classic_config = Config()
130 classic_config = Config()
131 classic_config.InteractiveShell.cache_size = 0
131 classic_config.InteractiveShell.cache_size = 0
132 classic_config.PlainTextFormatter.pprint = False
132 classic_config.PlainTextFormatter.pprint = False
133 classic_config.PromptManager.in_template = '>>> '
133 classic_config.PromptManager.in_template = '>>> '
134 classic_config.PromptManager.in2_template = '... '
134 classic_config.PromptManager.in2_template = '... '
135 classic_config.PromptManager.out_template = ''
135 classic_config.PromptManager.out_template = ''
136 classic_config.InteractiveShell.separate_in = ''
136 classic_config.InteractiveShell.separate_in = ''
137 classic_config.InteractiveShell.separate_out = ''
137 classic_config.InteractiveShell.separate_out = ''
138 classic_config.InteractiveShell.separate_out2 = ''
138 classic_config.InteractiveShell.separate_out2 = ''
139 classic_config.InteractiveShell.colors = 'NoColor'
139 classic_config.InteractiveShell.colors = 'NoColor'
140 classic_config.InteractiveShell.xmode = 'Plain'
140 classic_config.InteractiveShell.xmode = 'Plain'
141
141
142 frontend_flags['classic']=(
142 frontend_flags['classic']=(
143 classic_config,
143 classic_config,
144 "Gives IPython a similar feel to the classic Python prompt."
144 "Gives IPython a similar feel to the classic Python prompt."
145 )
145 )
146 # # log doesn't make so much sense this way anymore
146 # # log doesn't make so much sense this way anymore
147 # paa('--log','-l',
147 # paa('--log','-l',
148 # action='store_true', dest='InteractiveShell.logstart',
148 # action='store_true', dest='InteractiveShell.logstart',
149 # help="Start logging to the default log file (./ipython_log.py).")
149 # help="Start logging to the default log file (./ipython_log.py).")
150 #
150 #
151 # # quick is harder to implement
151 # # quick is harder to implement
152 frontend_flags['quick']=(
152 frontend_flags['quick']=(
153 {'TerminalIPythonApp' : {'quick' : True}},
153 {'TerminalIPythonApp' : {'quick' : True}},
154 "Enable quick startup with no config files."
154 "Enable quick startup with no config files."
155 )
155 )
156
156
157 frontend_flags['i'] = (
157 frontend_flags['i'] = (
158 {'TerminalIPythonApp' : {'force_interact' : True}},
158 {'TerminalIPythonApp' : {'force_interact' : True}},
159 """If running code from the command line, become interactive afterwards."""
159 """If running code from the command line, become interactive afterwards."""
160 )
160 )
161 flags.update(frontend_flags)
161 flags.update(frontend_flags)
162
162
163 aliases = dict(base_aliases)
163 aliases = dict(base_aliases)
164 aliases.update(shell_aliases)
164 aliases.update(shell_aliases)
165
165
166 #-----------------------------------------------------------------------------
166 #-----------------------------------------------------------------------------
167 # Main classes and functions
167 # Main classes and functions
168 #-----------------------------------------------------------------------------
168 #-----------------------------------------------------------------------------
169
169
170
170
171 class LocateIPythonApp(BaseIPythonApplication):
171 class LocateIPythonApp(BaseIPythonApplication):
172 description = """print the path to the IPython dir"""
172 description = """print the path to the IPython dir"""
173 subcommands = Dict(dict(
173 subcommands = Dict(dict(
174 profile=('IPython.core.profileapp.ProfileLocate',
174 profile=('IPython.core.profileapp.ProfileLocate',
175 "print the path to an IPython profile directory",
175 "print the path to an IPython profile directory",
176 ),
176 ),
177 ))
177 ))
178 def start(self):
178 def start(self):
179 if self.subapp is not None:
179 if self.subapp is not None:
180 return self.subapp.start()
180 return self.subapp.start()
181 else:
181 else:
182 print(self.ipython_dir)
182 print(self.ipython_dir)
183
183
184
184
185 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
185 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
186 name = u'ipython'
186 name = u'ipython'
187 description = usage.cl_usage
187 description = usage.cl_usage
188 crash_handler_class = IPAppCrashHandler
188 crash_handler_class = IPAppCrashHandler
189 examples = _examples
189 examples = _examples
190
190
191 flags = Dict(flags)
191 flags = Dict(flags)
192 aliases = Dict(aliases)
192 aliases = Dict(aliases)
193 classes = List()
193 classes = List()
194 def _classes_default(self):
194 def _classes_default(self):
195 """This has to be in a method, for TerminalIPythonApp to be available."""
195 """This has to be in a method, for TerminalIPythonApp to be available."""
196 return [
196 return [
197 InteractiveShellApp, # ShellApp comes before TerminalApp, because
197 InteractiveShellApp, # ShellApp comes before TerminalApp, because
198 self.__class__, # it will also affect subclasses (e.g. QtConsole)
198 self.__class__, # it will also affect subclasses (e.g. QtConsole)
199 TerminalInteractiveShell,
199 TerminalInteractiveShell,
200 PromptManager,
200 PromptManager,
201 HistoryManager,
201 HistoryManager,
202 ProfileDir,
202 ProfileDir,
203 PlainTextFormatter,
203 PlainTextFormatter,
204 IPCompleter,
204 IPCompleter,
205 ScriptMagics,
205 ScriptMagics,
206 StoreMagics,
206 StoreMagics,
207 ]
207 ]
208
208
209 subcommands = dict(
209 subcommands = dict(
210 qtconsole=('jupyter_qtconsole.console.qtconsoleapp.JupyterQtConsoleApp',
210 qtconsole=('jupyter_qtconsole.console.qtconsoleapp.JupyterQtConsoleApp',
211 """DEPRECATD: Launch the Jupyter Qt Console."""
211 """DEPRECATD: Launch the Jupyter Qt Console."""
212 ),
212 ),
213 notebook=('jupyter_notebook.notebookapp.NotebookApp',
213 notebook=('jupyter_notebook.notebookapp.NotebookApp',
214 """DEPRECATED: Launch the IPython HTML Notebook Server."""
214 """DEPRECATED: Launch the IPython HTML Notebook Server."""
215 ),
215 ),
216 profile = ("IPython.core.profileapp.ProfileApp",
216 profile = ("IPython.core.profileapp.ProfileApp",
217 "Create and manage IPython profiles."
217 "Create and manage IPython profiles."
218 ),
218 ),
219 kernel = ("ipython_kernel.kernelapp.IPKernelApp",
219 kernel = ("ipykernel.kernelapp.IPKernelApp",
220 "Start a kernel without an attached frontend."
220 "Start a kernel without an attached frontend."
221 ),
221 ),
222 console=('jupyter_console.app.ZMQTerminalIPythonApp',
222 console=('jupyter_console.app.ZMQTerminalIPythonApp',
223 """DEPRECATED: Launch the Jupyter terminal-based Console."""
223 """DEPRECATED: Launch the Jupyter terminal-based Console."""
224 ),
224 ),
225 locate=('IPython.terminal.ipapp.LocateIPythonApp',
225 locate=('IPython.terminal.ipapp.LocateIPythonApp',
226 LocateIPythonApp.description
226 LocateIPythonApp.description
227 ),
227 ),
228 history=('IPython.core.historyapp.HistoryApp',
228 history=('IPython.core.historyapp.HistoryApp',
229 "Manage the IPython history database."
229 "Manage the IPython history database."
230 ),
230 ),
231 nbconvert=('jupyter_nbconvert.nbconvertapp.NbConvertApp',
231 nbconvert=('jupyter_nbconvert.nbconvertapp.NbConvertApp',
232 "DEPRECATED: Convert notebooks to/from other formats."
232 "DEPRECATED: Convert notebooks to/from other formats."
233 ),
233 ),
234 trust=('jupyter_nbformat.sign.TrustNotebookApp',
234 trust=('jupyter_nbformat.sign.TrustNotebookApp',
235 "DEPRECATED: Sign notebooks to trust their potentially unsafe contents at load."
235 "DEPRECATED: Sign notebooks to trust their potentially unsafe contents at load."
236 ),
236 ),
237 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
237 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
238 "DEPRECATED: Manage Jupyter kernel specifications."
238 "DEPRECATED: Manage Jupyter kernel specifications."
239 ),
239 ),
240 )
240 )
241 subcommands['install-nbextension'] = (
241 subcommands['install-nbextension'] = (
242 "jupyter_notebook.nbextensions.NBExtensionApp",
242 "jupyter_notebook.nbextensions.NBExtensionApp",
243 "DEPRECATED: Install Jupyter notebook extension files"
243 "DEPRECATED: Install Jupyter notebook extension files"
244 )
244 )
245
245
246 # *do* autocreate requested profile, but don't create the config file.
246 # *do* autocreate requested profile, but don't create the config file.
247 auto_create=Bool(True)
247 auto_create=Bool(True)
248 # configurables
248 # configurables
249 quick = Bool(False, config=True,
249 quick = Bool(False, config=True,
250 help="""Start IPython quickly by skipping the loading of config files."""
250 help="""Start IPython quickly by skipping the loading of config files."""
251 )
251 )
252 def _quick_changed(self, name, old, new):
252 def _quick_changed(self, name, old, new):
253 if new:
253 if new:
254 self.load_config_file = lambda *a, **kw: None
254 self.load_config_file = lambda *a, **kw: None
255
255
256 display_banner = Bool(True, config=True,
256 display_banner = Bool(True, config=True,
257 help="Whether to display a banner upon starting IPython."
257 help="Whether to display a banner upon starting IPython."
258 )
258 )
259
259
260 # if there is code of files to run from the cmd line, don't interact
260 # if there is code of files to run from the cmd line, don't interact
261 # unless the --i flag (App.force_interact) is true.
261 # unless the --i flag (App.force_interact) is true.
262 force_interact = Bool(False, config=True,
262 force_interact = Bool(False, config=True,
263 help="""If a command or file is given via the command-line,
263 help="""If a command or file is given via the command-line,
264 e.g. 'ipython foo.py', start an interactive shell after executing the
264 e.g. 'ipython foo.py', start an interactive shell after executing the
265 file or command."""
265 file or command."""
266 )
266 )
267 def _force_interact_changed(self, name, old, new):
267 def _force_interact_changed(self, name, old, new):
268 if new:
268 if new:
269 self.interact = True
269 self.interact = True
270
270
271 def _file_to_run_changed(self, name, old, new):
271 def _file_to_run_changed(self, name, old, new):
272 if new:
272 if new:
273 self.something_to_run = True
273 self.something_to_run = True
274 if new and not self.force_interact:
274 if new and not self.force_interact:
275 self.interact = False
275 self.interact = False
276 _code_to_run_changed = _file_to_run_changed
276 _code_to_run_changed = _file_to_run_changed
277 _module_to_run_changed = _file_to_run_changed
277 _module_to_run_changed = _file_to_run_changed
278
278
279 # internal, not-configurable
279 # internal, not-configurable
280 interact=Bool(True)
280 interact=Bool(True)
281 something_to_run=Bool(False)
281 something_to_run=Bool(False)
282
282
283 def parse_command_line(self, argv=None):
283 def parse_command_line(self, argv=None):
284 """override to allow old '-pylab' flag with deprecation warning"""
284 """override to allow old '-pylab' flag with deprecation warning"""
285
285
286 argv = sys.argv[1:] if argv is None else argv
286 argv = sys.argv[1:] if argv is None else argv
287
287
288 if '-pylab' in argv:
288 if '-pylab' in argv:
289 # deprecated `-pylab` given,
289 # deprecated `-pylab` given,
290 # warn and transform into current syntax
290 # warn and transform into current syntax
291 argv = argv[:] # copy, don't clobber
291 argv = argv[:] # copy, don't clobber
292 idx = argv.index('-pylab')
292 idx = argv.index('-pylab')
293 warn.warn("`-pylab` flag has been deprecated.\n"
293 warn.warn("`-pylab` flag has been deprecated.\n"
294 " Use `--matplotlib <backend>` and import pylab manually.")
294 " Use `--matplotlib <backend>` and import pylab manually.")
295 argv[idx] = '--pylab'
295 argv[idx] = '--pylab'
296
296
297 return super(TerminalIPythonApp, self).parse_command_line(argv)
297 return super(TerminalIPythonApp, self).parse_command_line(argv)
298
298
299 @catch_config_error
299 @catch_config_error
300 def initialize(self, argv=None):
300 def initialize(self, argv=None):
301 """Do actions after construct, but before starting the app."""
301 """Do actions after construct, but before starting the app."""
302 super(TerminalIPythonApp, self).initialize(argv)
302 super(TerminalIPythonApp, self).initialize(argv)
303 if self.subapp is not None:
303 if self.subapp is not None:
304 # don't bother initializing further, starting subapp
304 # don't bother initializing further, starting subapp
305 return
305 return
306 # print self.extra_args
306 # print self.extra_args
307 if self.extra_args and not self.something_to_run:
307 if self.extra_args and not self.something_to_run:
308 self.file_to_run = self.extra_args[0]
308 self.file_to_run = self.extra_args[0]
309 self.init_path()
309 self.init_path()
310 # create the shell
310 # create the shell
311 self.init_shell()
311 self.init_shell()
312 # and draw the banner
312 # and draw the banner
313 self.init_banner()
313 self.init_banner()
314 # Now a variety of things that happen after the banner is printed.
314 # Now a variety of things that happen after the banner is printed.
315 self.init_gui_pylab()
315 self.init_gui_pylab()
316 self.init_extensions()
316 self.init_extensions()
317 self.init_code()
317 self.init_code()
318
318
319 def init_shell(self):
319 def init_shell(self):
320 """initialize the InteractiveShell instance"""
320 """initialize the InteractiveShell instance"""
321 # Create an InteractiveShell instance.
321 # Create an InteractiveShell instance.
322 # shell.display_banner should always be False for the terminal
322 # shell.display_banner should always be False for the terminal
323 # based app, because we call shell.show_banner() by hand below
323 # based app, because we call shell.show_banner() by hand below
324 # so the banner shows *before* all extension loading stuff.
324 # so the banner shows *before* all extension loading stuff.
325 self.shell = TerminalInteractiveShell.instance(parent=self,
325 self.shell = TerminalInteractiveShell.instance(parent=self,
326 display_banner=False, profile_dir=self.profile_dir,
326 display_banner=False, profile_dir=self.profile_dir,
327 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
327 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
328 self.shell.configurables.append(self)
328 self.shell.configurables.append(self)
329
329
330 def init_banner(self):
330 def init_banner(self):
331 """optionally display the banner"""
331 """optionally display the banner"""
332 if self.display_banner and self.interact:
332 if self.display_banner and self.interact:
333 self.shell.show_banner()
333 self.shell.show_banner()
334 # Make sure there is a space below the banner.
334 # Make sure there is a space below the banner.
335 if self.log_level <= logging.INFO: print()
335 if self.log_level <= logging.INFO: print()
336
336
337 def _pylab_changed(self, name, old, new):
337 def _pylab_changed(self, name, old, new):
338 """Replace --pylab='inline' with --pylab='auto'"""
338 """Replace --pylab='inline' with --pylab='auto'"""
339 if new == 'inline':
339 if new == 'inline':
340 warn.warn("'inline' not available as pylab backend, "
340 warn.warn("'inline' not available as pylab backend, "
341 "using 'auto' instead.")
341 "using 'auto' instead.")
342 self.pylab = 'auto'
342 self.pylab = 'auto'
343
343
344 def start(self):
344 def start(self):
345 if self.subapp is not None:
345 if self.subapp is not None:
346 return self.subapp.start()
346 return self.subapp.start()
347 # perform any prexec steps:
347 # perform any prexec steps:
348 if self.interact:
348 if self.interact:
349 self.log.debug("Starting IPython's mainloop...")
349 self.log.debug("Starting IPython's mainloop...")
350 self.shell.mainloop()
350 self.shell.mainloop()
351 else:
351 else:
352 self.log.debug("IPython not interactive...")
352 self.log.debug("IPython not interactive...")
353
353
354 def load_default_config(ipython_dir=None):
354 def load_default_config(ipython_dir=None):
355 """Load the default config file from the default ipython_dir.
355 """Load the default config file from the default ipython_dir.
356
356
357 This is useful for embedded shells.
357 This is useful for embedded shells.
358 """
358 """
359 if ipython_dir is None:
359 if ipython_dir is None:
360 ipython_dir = get_ipython_dir()
360 ipython_dir = get_ipython_dir()
361
361
362 profile_dir = os.path.join(ipython_dir, 'profile_default')
362 profile_dir = os.path.join(ipython_dir, 'profile_default')
363
363
364 config = Config()
364 config = Config()
365 for cf in Application._load_config_files("ipython_config", path=profile_dir):
365 for cf in Application._load_config_files("ipython_config", path=profile_dir):
366 config.update(cf)
366 config.update(cf)
367
367
368 return config
368 return config
369
369
370 launch_new_instance = TerminalIPythonApp.launch_instance
370 launch_new_instance = TerminalIPythonApp.launch_instance
371
371
372
372
373 if __name__ == '__main__':
373 if __name__ == '__main__':
374 launch_new_instance()
374 launch_new_instance()
@@ -1,5 +1,5 b''
1 from warnings import warn
1 from warnings import warn
2
2
3 warn("IPython.utils.pickleutil has moved to ipython_kernel.pickleutil")
3 warn("IPython.utils.pickleutil has moved to ipykernel.pickleutil")
4
4
5 from ipython_kernel.pickleutil import *
5 from ipykernel.pickleutil import *
@@ -1,288 +1,288 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 """Setup script for IPython.
3 """Setup script for IPython.
4
4
5 Under Posix environments it works like a typical setup.py script.
5 Under Posix environments it works like a typical setup.py script.
6 Under Windows, the command sdist is not supported, since IPython
6 Under Windows, the command sdist is not supported, since IPython
7 requires utilities which are not available under Windows."""
7 requires utilities which are not available under Windows."""
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (c) 2008-2011, IPython Development Team.
10 # Copyright (c) 2008-2011, IPython Development Team.
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.rst, distributed with this software.
17 # The full license is in the file COPYING.rst, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Minimal Python version sanity check
21 # Minimal Python version sanity check
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 from __future__ import print_function
23 from __future__ import print_function
24
24
25 import sys
25 import sys
26
26
27 # This check is also made in IPython/__init__, don't forget to update both when
27 # This check is also made in IPython/__init__, don't forget to update both when
28 # changing Python version requirements.
28 # changing Python version requirements.
29 v = sys.version_info
29 v = sys.version_info
30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
32 print(error, file=sys.stderr)
32 print(error, file=sys.stderr)
33 sys.exit(1)
33 sys.exit(1)
34
34
35 PY3 = (sys.version_info[0] >= 3)
35 PY3 = (sys.version_info[0] >= 3)
36
36
37 # At least we're on the python version we need, move on.
37 # At least we're on the python version we need, move on.
38
38
39 #-------------------------------------------------------------------------------
39 #-------------------------------------------------------------------------------
40 # Imports
40 # Imports
41 #-------------------------------------------------------------------------------
41 #-------------------------------------------------------------------------------
42
42
43 # Stdlib imports
43 # Stdlib imports
44 import os
44 import os
45 import shutil
45 import shutil
46
46
47 from glob import glob
47 from glob import glob
48
48
49 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
49 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
50 # update it when the contents of directories change.
50 # update it when the contents of directories change.
51 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
51 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
52
52
53 from distutils.core import setup
53 from distutils.core import setup
54
54
55 # Our own imports
55 # Our own imports
56 from setupbase import target_update
56 from setupbase import target_update
57
57
58 from setupbase import (
58 from setupbase import (
59 setup_args,
59 setup_args,
60 find_packages,
60 find_packages,
61 find_package_data,
61 find_package_data,
62 check_package_data_first,
62 check_package_data_first,
63 find_entry_points,
63 find_entry_points,
64 build_scripts_entrypt,
64 build_scripts_entrypt,
65 find_data_files,
65 find_data_files,
66 check_for_readline,
66 check_for_readline,
67 git_prebuild,
67 git_prebuild,
68 get_bdist_wheel,
68 get_bdist_wheel,
69 install_symlinked,
69 install_symlinked,
70 install_lib_symlink,
70 install_lib_symlink,
71 install_scripts_for_symlink,
71 install_scripts_for_symlink,
72 unsymlink,
72 unsymlink,
73 )
73 )
74
74
75 isfile = os.path.isfile
75 isfile = os.path.isfile
76 pjoin = os.path.join
76 pjoin = os.path.join
77
77
78 #-------------------------------------------------------------------------------
78 #-------------------------------------------------------------------------------
79 # Handle OS specific things
79 # Handle OS specific things
80 #-------------------------------------------------------------------------------
80 #-------------------------------------------------------------------------------
81
81
82 if os.name in ('nt','dos'):
82 if os.name in ('nt','dos'):
83 os_name = 'windows'
83 os_name = 'windows'
84 else:
84 else:
85 os_name = os.name
85 os_name = os.name
86
86
87 # Under Windows, 'sdist' has not been supported. Now that the docs build with
87 # Under Windows, 'sdist' has not been supported. Now that the docs build with
88 # Sphinx it might work, but let's not turn it on until someone confirms that it
88 # Sphinx it might work, but let's not turn it on until someone confirms that it
89 # actually works.
89 # actually works.
90 if os_name == 'windows' and 'sdist' in sys.argv:
90 if os_name == 'windows' and 'sdist' in sys.argv:
91 print('The sdist command is not available under Windows. Exiting.')
91 print('The sdist command is not available under Windows. Exiting.')
92 sys.exit(1)
92 sys.exit(1)
93
93
94
94
95 #-------------------------------------------------------------------------------
95 #-------------------------------------------------------------------------------
96 # Things related to the IPython documentation
96 # Things related to the IPython documentation
97 #-------------------------------------------------------------------------------
97 #-------------------------------------------------------------------------------
98
98
99 # update the manuals when building a source dist
99 # update the manuals when building a source dist
100 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
100 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
101
101
102 # List of things to be updated. Each entry is a triplet of args for
102 # List of things to be updated. Each entry is a triplet of args for
103 # target_update()
103 # target_update()
104 to_update = [
104 to_update = [
105 ('docs/man/ipython.1.gz',
105 ('docs/man/ipython.1.gz',
106 ['docs/man/ipython.1'],
106 ['docs/man/ipython.1'],
107 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
107 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
108 ]
108 ]
109
109
110
110
111 [ target_update(*t) for t in to_update ]
111 [ target_update(*t) for t in to_update ]
112
112
113 #---------------------------------------------------------------------------
113 #---------------------------------------------------------------------------
114 # Find all the packages, package data, and data_files
114 # Find all the packages, package data, and data_files
115 #---------------------------------------------------------------------------
115 #---------------------------------------------------------------------------
116
116
117 packages = find_packages()
117 packages = find_packages()
118 package_data = find_package_data()
118 package_data = find_package_data()
119
119
120 data_files = find_data_files()
120 data_files = find_data_files()
121
121
122 setup_args['packages'] = packages
122 setup_args['packages'] = packages
123 setup_args['package_data'] = package_data
123 setup_args['package_data'] = package_data
124 setup_args['data_files'] = data_files
124 setup_args['data_files'] = data_files
125
125
126 #---------------------------------------------------------------------------
126 #---------------------------------------------------------------------------
127 # custom distutils commands
127 # custom distutils commands
128 #---------------------------------------------------------------------------
128 #---------------------------------------------------------------------------
129 # imports here, so they are after setuptools import if there was one
129 # imports here, so they are after setuptools import if there was one
130 from distutils.command.sdist import sdist
130 from distutils.command.sdist import sdist
131 from distutils.command.upload import upload
131 from distutils.command.upload import upload
132
132
133 class UploadWindowsInstallers(upload):
133 class UploadWindowsInstallers(upload):
134
134
135 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
135 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
136 user_options = upload.user_options + [
136 user_options = upload.user_options + [
137 ('files=', 'f', 'exe file (or glob) to upload')
137 ('files=', 'f', 'exe file (or glob) to upload')
138 ]
138 ]
139 def initialize_options(self):
139 def initialize_options(self):
140 upload.initialize_options(self)
140 upload.initialize_options(self)
141 meta = self.distribution.metadata
141 meta = self.distribution.metadata
142 base = '{name}-{version}'.format(
142 base = '{name}-{version}'.format(
143 name=meta.get_name(),
143 name=meta.get_name(),
144 version=meta.get_version()
144 version=meta.get_version()
145 )
145 )
146 self.files = os.path.join('dist', '%s.*.exe' % base)
146 self.files = os.path.join('dist', '%s.*.exe' % base)
147
147
148 def run(self):
148 def run(self):
149 for dist_file in glob(self.files):
149 for dist_file in glob(self.files):
150 self.upload_file('bdist_wininst', 'any', dist_file)
150 self.upload_file('bdist_wininst', 'any', dist_file)
151
151
152 setup_args['cmdclass'] = {
152 setup_args['cmdclass'] = {
153 'build_py': \
153 'build_py': \
154 check_package_data_first(git_prebuild('IPython')),
154 check_package_data_first(git_prebuild('IPython')),
155 'sdist' : git_prebuild('IPython', sdist),
155 'sdist' : git_prebuild('IPython', sdist),
156 'upload_wininst' : UploadWindowsInstallers,
156 'upload_wininst' : UploadWindowsInstallers,
157 'symlink': install_symlinked,
157 'symlink': install_symlinked,
158 'install_lib_symlink': install_lib_symlink,
158 'install_lib_symlink': install_lib_symlink,
159 'install_scripts_sym': install_scripts_for_symlink,
159 'install_scripts_sym': install_scripts_for_symlink,
160 'unsymlink': unsymlink,
160 'unsymlink': unsymlink,
161 }
161 }
162
162
163 ### Temporarily disable install while it's broken during the big split
163 ### Temporarily disable install while it's broken during the big split
164 from textwrap import dedent
164 from textwrap import dedent
165 from distutils.command.install import install
165 from distutils.command.install import install
166
166
167 class DisabledInstall(install):
167 class DisabledInstall(install):
168 def run(self):
168 def run(self):
169 msg = dedent("""
169 msg = dedent("""
170 While we are in the midst of The Big Split,
170 While we are in the midst of The Big Split,
171 IPython cannot be installed from master.
171 IPython cannot be installed from master.
172 You can use `pip install -e .` for an editable install,
172 You can use `pip install -e .` for an editable install,
173 which still works.
173 which still works.
174 """)
174 """)
175 print(msg, file=sys.stderr)
175 print(msg, file=sys.stderr)
176 raise SystemExit(1)
176 raise SystemExit(1)
177
177
178 setup_args['cmdclass']['install'] = DisabledInstall
178 setup_args['cmdclass']['install'] = DisabledInstall
179
179
180
180
181 #---------------------------------------------------------------------------
181 #---------------------------------------------------------------------------
182 # Handle scripts, dependencies, and setuptools specific things
182 # Handle scripts, dependencies, and setuptools specific things
183 #---------------------------------------------------------------------------
183 #---------------------------------------------------------------------------
184
184
185 # For some commands, use setuptools. Note that we do NOT list install here!
185 # For some commands, use setuptools. Note that we do NOT list install here!
186 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
186 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
187 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
187 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
188 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
188 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
189 'egg_info', 'easy_install', 'upload', 'install_egg_info',
189 'egg_info', 'easy_install', 'upload', 'install_egg_info',
190 ))
190 ))
191
191
192 if len(needs_setuptools.intersection(sys.argv)) > 0:
192 if len(needs_setuptools.intersection(sys.argv)) > 0:
193 import setuptools
193 import setuptools
194
194
195 # This dict is used for passing extra arguments that are setuptools
195 # This dict is used for passing extra arguments that are setuptools
196 # specific to setup
196 # specific to setup
197 setuptools_extra_args = {}
197 setuptools_extra_args = {}
198
198
199 # setuptools requirements
199 # setuptools requirements
200
200
201 pyzmq = 'pyzmq>=13'
201 pyzmq = 'pyzmq>=13'
202
202
203 extras_require = dict(
203 extras_require = dict(
204 parallel = ['ipyparallel'],
204 parallel = ['ipyparallel'],
205 qtconsole = ['jupyter_qtconsole'],
205 qtconsole = ['jupyter_qtconsole'],
206 doc = ['Sphinx>=1.1', 'numpydoc'],
206 doc = ['Sphinx>=1.1', 'numpydoc'],
207 test = ['nose>=0.10.1', 'requests'],
207 test = ['nose>=0.10.1', 'requests'],
208 terminal = [],
208 terminal = [],
209 kernel = ['ipython_kernel'],
209 kernel = ['ipykernel'],
210 nbformat = ['jupyter_nbformat'],
210 nbformat = ['jupyter_nbformat'],
211 notebook = ['jupyter_notebook'],
211 notebook = ['jupyter_notebook'],
212 nbconvert = ['jupyter_nbconvert']
212 nbconvert = ['jupyter_nbconvert']
213 )
213 )
214
214
215 if sys.version_info < (3, 3):
215 if sys.version_info < (3, 3):
216 extras_require['test'].append('mock')
216 extras_require['test'].append('mock')
217
217
218 install_requires = [
218 install_requires = [
219 'decorator',
219 'decorator',
220 'pickleshare',
220 'pickleshare',
221 'simplegeneric>0.8',
221 'simplegeneric>0.8',
222 'traitlets',
222 'traitlets',
223 ]
223 ]
224
224
225 # add platform-specific dependencies
225 # add platform-specific dependencies
226 if sys.platform == 'darwin':
226 if sys.platform == 'darwin':
227 install_requires.append('appnope')
227 install_requires.append('appnope')
228 if 'bdist_wheel' in sys.argv[1:] or not check_for_readline():
228 if 'bdist_wheel' in sys.argv[1:] or not check_for_readline():
229 install_requires.append('gnureadline')
229 install_requires.append('gnureadline')
230
230
231 if sys.platform.startswith('win'):
231 if sys.platform.startswith('win'):
232 extras_require['terminal'].append('pyreadline>=2.0')
232 extras_require['terminal'].append('pyreadline>=2.0')
233 else:
233 else:
234 install_requires.append('pexpect')
234 install_requires.append('pexpect')
235
235
236 everything = set()
236 everything = set()
237 for deps in extras_require.values():
237 for deps in extras_require.values():
238 everything.update(deps)
238 everything.update(deps)
239 extras_require['all'] = everything
239 extras_require['all'] = everything
240
240
241 if 'setuptools' in sys.modules:
241 if 'setuptools' in sys.modules:
242 setup_args['cmdclass']['bdist_wheel'] = get_bdist_wheel()
242 setup_args['cmdclass']['bdist_wheel'] = get_bdist_wheel()
243
243
244 setuptools_extra_args['zip_safe'] = False
244 setuptools_extra_args['zip_safe'] = False
245 setuptools_extra_args['entry_points'] = {
245 setuptools_extra_args['entry_points'] = {
246 'console_scripts': find_entry_points(),
246 'console_scripts': find_entry_points(),
247 'pygments.lexers': [
247 'pygments.lexers': [
248 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
248 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
249 'ipython = IPython.lib.lexers:IPythonLexer',
249 'ipython = IPython.lib.lexers:IPythonLexer',
250 'ipython3 = IPython.lib.lexers:IPython3Lexer',
250 'ipython3 = IPython.lib.lexers:IPython3Lexer',
251 ],
251 ],
252 }
252 }
253 setup_args['extras_require'] = extras_require
253 setup_args['extras_require'] = extras_require
254 requires = setup_args['install_requires'] = install_requires
254 requires = setup_args['install_requires'] = install_requires
255
255
256 # Script to be run by the windows binary installer after the default setup
256 # Script to be run by the windows binary installer after the default setup
257 # routine, to add shortcuts and similar windows-only things. Windows
257 # routine, to add shortcuts and similar windows-only things. Windows
258 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
258 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
259 # doesn't find them.
259 # doesn't find them.
260 if 'bdist_wininst' in sys.argv:
260 if 'bdist_wininst' in sys.argv:
261 if len(sys.argv) > 2 and \
261 if len(sys.argv) > 2 and \
262 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
262 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
263 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
263 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
264 sys.exit(1)
264 sys.exit(1)
265 setup_args['data_files'].append(
265 setup_args['data_files'].append(
266 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
266 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
267 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
267 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
268 setup_args['options'] = {"bdist_wininst":
268 setup_args['options'] = {"bdist_wininst":
269 {"install_script":
269 {"install_script":
270 "ipython_win_post_install.py"}}
270 "ipython_win_post_install.py"}}
271
271
272 else:
272 else:
273 # scripts has to be a non-empty list, or install_scripts isn't called
273 # scripts has to be a non-empty list, or install_scripts isn't called
274 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
274 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
275
275
276 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
276 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
277
277
278 #---------------------------------------------------------------------------
278 #---------------------------------------------------------------------------
279 # Do the actual setup now
279 # Do the actual setup now
280 #---------------------------------------------------------------------------
280 #---------------------------------------------------------------------------
281
281
282 setup_args.update(setuptools_extra_args)
282 setup_args.update(setuptools_extra_args)
283
283
284 def main():
284 def main():
285 setup(**setup_args)
285 setup(**setup_args)
286
286
287 if __name__ == '__main__':
287 if __name__ == '__main__':
288 main()
288 main()
General Comments 0
You need to be logged in to leave comments. Login now