##// END OF EJS Templates
Fixed #4580 -- Deprecated %profile.
Susan Tan -
Show More
@@ -1,654 +1,655 b''
1 """Implementation of basic magic functions.
1 """Implementation of basic magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 from __future__ import print_function
14 from __future__ import print_function
15
15
16 # Stdlib
16 # Stdlib
17 import io
17 import io
18 import json
18 import json
19 import sys
19 import sys
20 from pprint import pformat
20 from pprint import pformat
21
21
22 # Our own packages
22 # Our own packages
23 from IPython.core import magic_arguments, page
23 from IPython.core import magic_arguments, page
24 from IPython.core.error import UsageError
24 from IPython.core.error import UsageError
25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
26 from IPython.utils.text import format_screen, dedent, indent
26 from IPython.utils.text import format_screen, dedent, indent
27 from IPython.testing.skipdoctest import skip_doctest
27 from IPython.testing.skipdoctest import skip_doctest
28 from IPython.utils.ipstruct import Struct
28 from IPython.utils.ipstruct import Struct
29 from IPython.utils.path import unquote_filename
29 from IPython.utils.path import unquote_filename
30 from IPython.utils.py3compat import unicode_type
30 from IPython.utils.py3compat import unicode_type
31 from IPython.utils.warn import warn, error
31 from IPython.utils.warn import warn, error
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Magics class implementation
34 # Magics class implementation
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37 class MagicsDisplay(object):
37 class MagicsDisplay(object):
38 def __init__(self, magics_manager):
38 def __init__(self, magics_manager):
39 self.magics_manager = magics_manager
39 self.magics_manager = magics_manager
40
40
41 def _lsmagic(self):
41 def _lsmagic(self):
42 """The main implementation of the %lsmagic"""
42 """The main implementation of the %lsmagic"""
43 mesc = magic_escapes['line']
43 mesc = magic_escapes['line']
44 cesc = magic_escapes['cell']
44 cesc = magic_escapes['cell']
45 mman = self.magics_manager
45 mman = self.magics_manager
46 magics = mman.lsmagic()
46 magics = mman.lsmagic()
47 out = ['Available line magics:',
47 out = ['Available line magics:',
48 mesc + (' '+mesc).join(sorted(magics['line'])),
48 mesc + (' '+mesc).join(sorted(magics['line'])),
49 '',
49 '',
50 'Available cell magics:',
50 'Available cell magics:',
51 cesc + (' '+cesc).join(sorted(magics['cell'])),
51 cesc + (' '+cesc).join(sorted(magics['cell'])),
52 '',
52 '',
53 mman.auto_status()]
53 mman.auto_status()]
54 return '\n'.join(out)
54 return '\n'.join(out)
55
55
56 def _repr_pretty_(self, p, cycle):
56 def _repr_pretty_(self, p, cycle):
57 p.text(self._lsmagic())
57 p.text(self._lsmagic())
58
58
59 def __str__(self):
59 def __str__(self):
60 return self._lsmagic()
60 return self._lsmagic()
61
61
62 def _jsonable(self):
62 def _jsonable(self):
63 """turn magics dict into jsonable dict of the same structure
63 """turn magics dict into jsonable dict of the same structure
64
64
65 replaces object instances with their class names as strings
65 replaces object instances with their class names as strings
66 """
66 """
67 magic_dict = {}
67 magic_dict = {}
68 mman = self.magics_manager
68 mman = self.magics_manager
69 magics = mman.lsmagic()
69 magics = mman.lsmagic()
70 for key, subdict in magics.items():
70 for key, subdict in magics.items():
71 d = {}
71 d = {}
72 magic_dict[key] = d
72 magic_dict[key] = d
73 for name, obj in subdict.items():
73 for name, obj in subdict.items():
74 try:
74 try:
75 classname = obj.__self__.__class__.__name__
75 classname = obj.__self__.__class__.__name__
76 except AttributeError:
76 except AttributeError:
77 classname = 'Other'
77 classname = 'Other'
78
78
79 d[name] = classname
79 d[name] = classname
80 return magic_dict
80 return magic_dict
81
81
82 def _repr_json_(self):
82 def _repr_json_(self):
83 return json.dumps(self._jsonable())
83 return json.dumps(self._jsonable())
84
84
85
85
86 @magics_class
86 @magics_class
87 class BasicMagics(Magics):
87 class BasicMagics(Magics):
88 """Magics that provide central IPython functionality.
88 """Magics that provide central IPython functionality.
89
89
90 These are various magics that don't fit into specific categories but that
90 These are various magics that don't fit into specific categories but that
91 are all part of the base 'IPython experience'."""
91 are all part of the base 'IPython experience'."""
92
92
93 @magic_arguments.magic_arguments()
93 @magic_arguments.magic_arguments()
94 @magic_arguments.argument(
94 @magic_arguments.argument(
95 '-l', '--line', action='store_true',
95 '-l', '--line', action='store_true',
96 help="""Create a line magic alias."""
96 help="""Create a line magic alias."""
97 )
97 )
98 @magic_arguments.argument(
98 @magic_arguments.argument(
99 '-c', '--cell', action='store_true',
99 '-c', '--cell', action='store_true',
100 help="""Create a cell magic alias."""
100 help="""Create a cell magic alias."""
101 )
101 )
102 @magic_arguments.argument(
102 @magic_arguments.argument(
103 'name',
103 'name',
104 help="""Name of the magic to be created."""
104 help="""Name of the magic to be created."""
105 )
105 )
106 @magic_arguments.argument(
106 @magic_arguments.argument(
107 'target',
107 'target',
108 help="""Name of the existing line or cell magic."""
108 help="""Name of the existing line or cell magic."""
109 )
109 )
110 @line_magic
110 @line_magic
111 def alias_magic(self, line=''):
111 def alias_magic(self, line=''):
112 """Create an alias for an existing line or cell magic.
112 """Create an alias for an existing line or cell magic.
113
113
114 Examples
114 Examples
115 --------
115 --------
116 ::
116 ::
117
117
118 In [1]: %alias_magic t timeit
118 In [1]: %alias_magic t timeit
119 Created `%t` as an alias for `%timeit`.
119 Created `%t` as an alias for `%timeit`.
120 Created `%%t` as an alias for `%%timeit`.
120 Created `%%t` as an alias for `%%timeit`.
121
121
122 In [2]: %t -n1 pass
122 In [2]: %t -n1 pass
123 1 loops, best of 3: 954 ns per loop
123 1 loops, best of 3: 954 ns per loop
124
124
125 In [3]: %%t -n1
125 In [3]: %%t -n1
126 ...: pass
126 ...: pass
127 ...:
127 ...:
128 1 loops, best of 3: 954 ns per loop
128 1 loops, best of 3: 954 ns per loop
129
129
130 In [4]: %alias_magic --cell whereami pwd
130 In [4]: %alias_magic --cell whereami pwd
131 UsageError: Cell magic function `%%pwd` not found.
131 UsageError: Cell magic function `%%pwd` not found.
132 In [5]: %alias_magic --line whereami pwd
132 In [5]: %alias_magic --line whereami pwd
133 Created `%whereami` as an alias for `%pwd`.
133 Created `%whereami` as an alias for `%pwd`.
134
134
135 In [6]: %whereami
135 In [6]: %whereami
136 Out[6]: u'/home/testuser'
136 Out[6]: u'/home/testuser'
137 """
137 """
138 args = magic_arguments.parse_argstring(self.alias_magic, line)
138 args = magic_arguments.parse_argstring(self.alias_magic, line)
139 shell = self.shell
139 shell = self.shell
140 mman = self.shell.magics_manager
140 mman = self.shell.magics_manager
141 escs = ''.join(magic_escapes.values())
141 escs = ''.join(magic_escapes.values())
142
142
143 target = args.target.lstrip(escs)
143 target = args.target.lstrip(escs)
144 name = args.name.lstrip(escs)
144 name = args.name.lstrip(escs)
145
145
146 # Find the requested magics.
146 # Find the requested magics.
147 m_line = shell.find_magic(target, 'line')
147 m_line = shell.find_magic(target, 'line')
148 m_cell = shell.find_magic(target, 'cell')
148 m_cell = shell.find_magic(target, 'cell')
149 if args.line and m_line is None:
149 if args.line and m_line is None:
150 raise UsageError('Line magic function `%s%s` not found.' %
150 raise UsageError('Line magic function `%s%s` not found.' %
151 (magic_escapes['line'], target))
151 (magic_escapes['line'], target))
152 if args.cell and m_cell is None:
152 if args.cell and m_cell is None:
153 raise UsageError('Cell magic function `%s%s` not found.' %
153 raise UsageError('Cell magic function `%s%s` not found.' %
154 (magic_escapes['cell'], target))
154 (magic_escapes['cell'], target))
155
155
156 # If --line and --cell are not specified, default to the ones
156 # If --line and --cell are not specified, default to the ones
157 # that are available.
157 # that are available.
158 if not args.line and not args.cell:
158 if not args.line and not args.cell:
159 if not m_line and not m_cell:
159 if not m_line and not m_cell:
160 raise UsageError(
160 raise UsageError(
161 'No line or cell magic with name `%s` found.' % target
161 'No line or cell magic with name `%s` found.' % target
162 )
162 )
163 args.line = bool(m_line)
163 args.line = bool(m_line)
164 args.cell = bool(m_cell)
164 args.cell = bool(m_cell)
165
165
166 if args.line:
166 if args.line:
167 mman.register_alias(name, target, 'line')
167 mman.register_alias(name, target, 'line')
168 print('Created `%s%s` as an alias for `%s%s`.' % (
168 print('Created `%s%s` as an alias for `%s%s`.' % (
169 magic_escapes['line'], name,
169 magic_escapes['line'], name,
170 magic_escapes['line'], target))
170 magic_escapes['line'], target))
171
171
172 if args.cell:
172 if args.cell:
173 mman.register_alias(name, target, 'cell')
173 mman.register_alias(name, target, 'cell')
174 print('Created `%s%s` as an alias for `%s%s`.' % (
174 print('Created `%s%s` as an alias for `%s%s`.' % (
175 magic_escapes['cell'], name,
175 magic_escapes['cell'], name,
176 magic_escapes['cell'], target))
176 magic_escapes['cell'], target))
177
177
178 @line_magic
178 @line_magic
179 def lsmagic(self, parameter_s=''):
179 def lsmagic(self, parameter_s=''):
180 """List currently available magic functions."""
180 """List currently available magic functions."""
181 return MagicsDisplay(self.shell.magics_manager)
181 return MagicsDisplay(self.shell.magics_manager)
182
182
183 def _magic_docs(self, brief=False, rest=False):
183 def _magic_docs(self, brief=False, rest=False):
184 """Return docstrings from magic functions."""
184 """Return docstrings from magic functions."""
185 mman = self.shell.magics_manager
185 mman = self.shell.magics_manager
186 docs = mman.lsmagic_docs(brief, missing='No documentation')
186 docs = mman.lsmagic_docs(brief, missing='No documentation')
187
187
188 if rest:
188 if rest:
189 format_string = '**%s%s**::\n\n%s\n\n'
189 format_string = '**%s%s**::\n\n%s\n\n'
190 else:
190 else:
191 format_string = '%s%s:\n%s\n'
191 format_string = '%s%s:\n%s\n'
192
192
193 return ''.join(
193 return ''.join(
194 [format_string % (magic_escapes['line'], fname,
194 [format_string % (magic_escapes['line'], fname,
195 indent(dedent(fndoc)))
195 indent(dedent(fndoc)))
196 for fname, fndoc in sorted(docs['line'].items())]
196 for fname, fndoc in sorted(docs['line'].items())]
197 +
197 +
198 [format_string % (magic_escapes['cell'], fname,
198 [format_string % (magic_escapes['cell'], fname,
199 indent(dedent(fndoc)))
199 indent(dedent(fndoc)))
200 for fname, fndoc in sorted(docs['cell'].items())]
200 for fname, fndoc in sorted(docs['cell'].items())]
201 )
201 )
202
202
203 @line_magic
203 @line_magic
204 def magic(self, parameter_s=''):
204 def magic(self, parameter_s=''):
205 """Print information about the magic function system.
205 """Print information about the magic function system.
206
206
207 Supported formats: -latex, -brief, -rest
207 Supported formats: -latex, -brief, -rest
208 """
208 """
209
209
210 mode = ''
210 mode = ''
211 try:
211 try:
212 mode = parameter_s.split()[0][1:]
212 mode = parameter_s.split()[0][1:]
213 if mode == 'rest':
213 if mode == 'rest':
214 rest_docs = []
214 rest_docs = []
215 except IndexError:
215 except IndexError:
216 pass
216 pass
217
217
218 brief = (mode == 'brief')
218 brief = (mode == 'brief')
219 rest = (mode == 'rest')
219 rest = (mode == 'rest')
220 magic_docs = self._magic_docs(brief, rest)
220 magic_docs = self._magic_docs(brief, rest)
221
221
222 if mode == 'latex':
222 if mode == 'latex':
223 print(self.format_latex(magic_docs))
223 print(self.format_latex(magic_docs))
224 return
224 return
225 else:
225 else:
226 magic_docs = format_screen(magic_docs)
226 magic_docs = format_screen(magic_docs)
227
227
228 out = ["""
228 out = ["""
229 IPython's 'magic' functions
229 IPython's 'magic' functions
230 ===========================
230 ===========================
231
231
232 The magic function system provides a series of functions which allow you to
232 The magic function system provides a series of functions which allow you to
233 control the behavior of IPython itself, plus a lot of system-type
233 control the behavior of IPython itself, plus a lot of system-type
234 features. There are two kinds of magics, line-oriented and cell-oriented.
234 features. There are two kinds of magics, line-oriented and cell-oriented.
235
235
236 Line magics are prefixed with the % character and work much like OS
236 Line magics are prefixed with the % character and work much like OS
237 command-line calls: they get as an argument the rest of the line, where
237 command-line calls: they get as an argument the rest of the line, where
238 arguments are passed without parentheses or quotes. For example, this will
238 arguments are passed without parentheses or quotes. For example, this will
239 time the given statement::
239 time the given statement::
240
240
241 %timeit range(1000)
241 %timeit range(1000)
242
242
243 Cell magics are prefixed with a double %%, and they are functions that get as
243 Cell magics are prefixed with a double %%, and they are functions that get as
244 an argument not only the rest of the line, but also the lines below it in a
244 an argument not only the rest of the line, but also the lines below it in a
245 separate argument. These magics are called with two arguments: the rest of the
245 separate argument. These magics are called with two arguments: the rest of the
246 call line and the body of the cell, consisting of the lines below the first.
246 call line and the body of the cell, consisting of the lines below the first.
247 For example::
247 For example::
248
248
249 %%timeit x = numpy.random.randn((100, 100))
249 %%timeit x = numpy.random.randn((100, 100))
250 numpy.linalg.svd(x)
250 numpy.linalg.svd(x)
251
251
252 will time the execution of the numpy svd routine, running the assignment of x
252 will time the execution of the numpy svd routine, running the assignment of x
253 as part of the setup phase, which is not timed.
253 as part of the setup phase, which is not timed.
254
254
255 In a line-oriented client (the terminal or Qt console IPython), starting a new
255 In a line-oriented client (the terminal or Qt console IPython), starting a new
256 input with %% will automatically enter cell mode, and IPython will continue
256 input with %% will automatically enter cell mode, and IPython will continue
257 reading input until a blank line is given. In the notebook, simply type the
257 reading input until a blank line is given. In the notebook, simply type the
258 whole cell as one entity, but keep in mind that the %% escape can only be at
258 whole cell as one entity, but keep in mind that the %% escape can only be at
259 the very start of the cell.
259 the very start of the cell.
260
260
261 NOTE: If you have 'automagic' enabled (via the command line option or with the
261 NOTE: If you have 'automagic' enabled (via the command line option or with the
262 %automagic function), you don't need to type in the % explicitly for line
262 %automagic function), you don't need to type in the % explicitly for line
263 magics; cell magics always require an explicit '%%' escape. By default,
263 magics; cell magics always require an explicit '%%' escape. By default,
264 IPython ships with automagic on, so you should only rarely need the % escape.
264 IPython ships with automagic on, so you should only rarely need the % escape.
265
265
266 Example: typing '%cd mydir' (without the quotes) changes you working directory
266 Example: typing '%cd mydir' (without the quotes) changes you working directory
267 to 'mydir', if it exists.
267 to 'mydir', if it exists.
268
268
269 For a list of the available magic functions, use %lsmagic. For a description
269 For a list of the available magic functions, use %lsmagic. For a description
270 of any of them, type %magic_name?, e.g. '%cd?'.
270 of any of them, type %magic_name?, e.g. '%cd?'.
271
271
272 Currently the magic system has the following functions:""",
272 Currently the magic system has the following functions:""",
273 magic_docs,
273 magic_docs,
274 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
274 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
275 str(self.lsmagic()),
275 str(self.lsmagic()),
276 ]
276 ]
277 page.page('\n'.join(out))
277 page.page('\n'.join(out))
278
278
279
279
280 @line_magic
280 @line_magic
281 def page(self, parameter_s=''):
281 def page(self, parameter_s=''):
282 """Pretty print the object and display it through a pager.
282 """Pretty print the object and display it through a pager.
283
283
284 %page [options] OBJECT
284 %page [options] OBJECT
285
285
286 If no object is given, use _ (last output).
286 If no object is given, use _ (last output).
287
287
288 Options:
288 Options:
289
289
290 -r: page str(object), don't pretty-print it."""
290 -r: page str(object), don't pretty-print it."""
291
291
292 # After a function contributed by Olivier Aubert, slightly modified.
292 # After a function contributed by Olivier Aubert, slightly modified.
293
293
294 # Process options/args
294 # Process options/args
295 opts, args = self.parse_options(parameter_s, 'r')
295 opts, args = self.parse_options(parameter_s, 'r')
296 raw = 'r' in opts
296 raw = 'r' in opts
297
297
298 oname = args and args or '_'
298 oname = args and args or '_'
299 info = self.shell._ofind(oname)
299 info = self.shell._ofind(oname)
300 if info['found']:
300 if info['found']:
301 txt = (raw and str or pformat)( info['obj'] )
301 txt = (raw and str or pformat)( info['obj'] )
302 page.page(txt)
302 page.page(txt)
303 else:
303 else:
304 print('Object `%s` not found' % oname)
304 print('Object `%s` not found' % oname)
305
305
306 @line_magic
306 @line_magic
307 def profile(self, parameter_s=''):
307 def profile(self, parameter_s=''):
308 """Print your currently active IPython profile.
308 """Print your currently active IPython profile.
309
309
310 See Also
310 See Also
311 --------
311 --------
312 prun : run code using the Python profiler
312 prun : run code using the Python profiler
313 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
313 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
314 """
314 """
315 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
315 from IPython.core.application import BaseIPythonApplication
316 from IPython.core.application import BaseIPythonApplication
316 if BaseIPythonApplication.initialized():
317 if BaseIPythonApplication.initialized():
317 print(BaseIPythonApplication.instance().profile)
318 print(BaseIPythonApplication.instance().profile)
318 else:
319 else:
319 error("profile is an application-level value, but you don't appear to be in an IPython application")
320 error("profile is an application-level value, but you don't appear to be in an IPython application")
320
321
321 @line_magic
322 @line_magic
322 def pprint(self, parameter_s=''):
323 def pprint(self, parameter_s=''):
323 """Toggle pretty printing on/off."""
324 """Toggle pretty printing on/off."""
324 ptformatter = self.shell.display_formatter.formatters['text/plain']
325 ptformatter = self.shell.display_formatter.formatters['text/plain']
325 ptformatter.pprint = bool(1 - ptformatter.pprint)
326 ptformatter.pprint = bool(1 - ptformatter.pprint)
326 print('Pretty printing has been turned',
327 print('Pretty printing has been turned',
327 ['OFF','ON'][ptformatter.pprint])
328 ['OFF','ON'][ptformatter.pprint])
328
329
329 @line_magic
330 @line_magic
330 def colors(self, parameter_s=''):
331 def colors(self, parameter_s=''):
331 """Switch color scheme for prompts, info system and exception handlers.
332 """Switch color scheme for prompts, info system and exception handlers.
332
333
333 Currently implemented schemes: NoColor, Linux, LightBG.
334 Currently implemented schemes: NoColor, Linux, LightBG.
334
335
335 Color scheme names are not case-sensitive.
336 Color scheme names are not case-sensitive.
336
337
337 Examples
338 Examples
338 --------
339 --------
339 To get a plain black and white terminal::
340 To get a plain black and white terminal::
340
341
341 %colors nocolor
342 %colors nocolor
342 """
343 """
343 def color_switch_err(name):
344 def color_switch_err(name):
344 warn('Error changing %s color schemes.\n%s' %
345 warn('Error changing %s color schemes.\n%s' %
345 (name, sys.exc_info()[1]))
346 (name, sys.exc_info()[1]))
346
347
347
348
348 new_scheme = parameter_s.strip()
349 new_scheme = parameter_s.strip()
349 if not new_scheme:
350 if not new_scheme:
350 raise UsageError(
351 raise UsageError(
351 "%colors: you must specify a color scheme. See '%colors?'")
352 "%colors: you must specify a color scheme. See '%colors?'")
352 # local shortcut
353 # local shortcut
353 shell = self.shell
354 shell = self.shell
354
355
355 import IPython.utils.rlineimpl as readline
356 import IPython.utils.rlineimpl as readline
356
357
357 if not shell.colors_force and \
358 if not shell.colors_force and \
358 not readline.have_readline and \
359 not readline.have_readline and \
359 (sys.platform == "win32" or sys.platform == "cli"):
360 (sys.platform == "win32" or sys.platform == "cli"):
360 msg = """\
361 msg = """\
361 Proper color support under MS Windows requires the pyreadline library.
362 Proper color support under MS Windows requires the pyreadline library.
362 You can find it at:
363 You can find it at:
363 http://ipython.org/pyreadline.html
364 http://ipython.org/pyreadline.html
364 Gary's readline needs the ctypes module, from:
365 Gary's readline needs the ctypes module, from:
365 http://starship.python.net/crew/theller/ctypes
366 http://starship.python.net/crew/theller/ctypes
366 (Note that ctypes is already part of Python versions 2.5 and newer).
367 (Note that ctypes is already part of Python versions 2.5 and newer).
367
368
368 Defaulting color scheme to 'NoColor'"""
369 Defaulting color scheme to 'NoColor'"""
369 new_scheme = 'NoColor'
370 new_scheme = 'NoColor'
370 warn(msg)
371 warn(msg)
371
372
372 # readline option is 0
373 # readline option is 0
373 if not shell.colors_force and not shell.has_readline:
374 if not shell.colors_force and not shell.has_readline:
374 new_scheme = 'NoColor'
375 new_scheme = 'NoColor'
375
376
376 # Set prompt colors
377 # Set prompt colors
377 try:
378 try:
378 shell.prompt_manager.color_scheme = new_scheme
379 shell.prompt_manager.color_scheme = new_scheme
379 except:
380 except:
380 color_switch_err('prompt')
381 color_switch_err('prompt')
381 else:
382 else:
382 shell.colors = \
383 shell.colors = \
383 shell.prompt_manager.color_scheme_table.active_scheme_name
384 shell.prompt_manager.color_scheme_table.active_scheme_name
384 # Set exception colors
385 # Set exception colors
385 try:
386 try:
386 shell.InteractiveTB.set_colors(scheme = new_scheme)
387 shell.InteractiveTB.set_colors(scheme = new_scheme)
387 shell.SyntaxTB.set_colors(scheme = new_scheme)
388 shell.SyntaxTB.set_colors(scheme = new_scheme)
388 except:
389 except:
389 color_switch_err('exception')
390 color_switch_err('exception')
390
391
391 # Set info (for 'object?') colors
392 # Set info (for 'object?') colors
392 if shell.color_info:
393 if shell.color_info:
393 try:
394 try:
394 shell.inspector.set_active_scheme(new_scheme)
395 shell.inspector.set_active_scheme(new_scheme)
395 except:
396 except:
396 color_switch_err('object inspector')
397 color_switch_err('object inspector')
397 else:
398 else:
398 shell.inspector.set_active_scheme('NoColor')
399 shell.inspector.set_active_scheme('NoColor')
399
400
400 @line_magic
401 @line_magic
401 def xmode(self, parameter_s=''):
402 def xmode(self, parameter_s=''):
402 """Switch modes for the exception handlers.
403 """Switch modes for the exception handlers.
403
404
404 Valid modes: Plain, Context and Verbose.
405 Valid modes: Plain, Context and Verbose.
405
406
406 If called without arguments, acts as a toggle."""
407 If called without arguments, acts as a toggle."""
407
408
408 def xmode_switch_err(name):
409 def xmode_switch_err(name):
409 warn('Error changing %s exception modes.\n%s' %
410 warn('Error changing %s exception modes.\n%s' %
410 (name,sys.exc_info()[1]))
411 (name,sys.exc_info()[1]))
411
412
412 shell = self.shell
413 shell = self.shell
413 new_mode = parameter_s.strip().capitalize()
414 new_mode = parameter_s.strip().capitalize()
414 try:
415 try:
415 shell.InteractiveTB.set_mode(mode=new_mode)
416 shell.InteractiveTB.set_mode(mode=new_mode)
416 print('Exception reporting mode:',shell.InteractiveTB.mode)
417 print('Exception reporting mode:',shell.InteractiveTB.mode)
417 except:
418 except:
418 xmode_switch_err('user')
419 xmode_switch_err('user')
419
420
420 @line_magic
421 @line_magic
421 def quickref(self,arg):
422 def quickref(self,arg):
422 """ Show a quick reference sheet """
423 """ Show a quick reference sheet """
423 from IPython.core.usage import quick_reference
424 from IPython.core.usage import quick_reference
424 qr = quick_reference + self._magic_docs(brief=True)
425 qr = quick_reference + self._magic_docs(brief=True)
425 page.page(qr)
426 page.page(qr)
426
427
427 @line_magic
428 @line_magic
428 def doctest_mode(self, parameter_s=''):
429 def doctest_mode(self, parameter_s=''):
429 """Toggle doctest mode on and off.
430 """Toggle doctest mode on and off.
430
431
431 This mode is intended to make IPython behave as much as possible like a
432 This mode is intended to make IPython behave as much as possible like a
432 plain Python shell, from the perspective of how its prompts, exceptions
433 plain Python shell, from the perspective of how its prompts, exceptions
433 and output look. This makes it easy to copy and paste parts of a
434 and output look. This makes it easy to copy and paste parts of a
434 session into doctests. It does so by:
435 session into doctests. It does so by:
435
436
436 - Changing the prompts to the classic ``>>>`` ones.
437 - Changing the prompts to the classic ``>>>`` ones.
437 - Changing the exception reporting mode to 'Plain'.
438 - Changing the exception reporting mode to 'Plain'.
438 - Disabling pretty-printing of output.
439 - Disabling pretty-printing of output.
439
440
440 Note that IPython also supports the pasting of code snippets that have
441 Note that IPython also supports the pasting of code snippets that have
441 leading '>>>' and '...' prompts in them. This means that you can paste
442 leading '>>>' and '...' prompts in them. This means that you can paste
442 doctests from files or docstrings (even if they have leading
443 doctests from files or docstrings (even if they have leading
443 whitespace), and the code will execute correctly. You can then use
444 whitespace), and the code will execute correctly. You can then use
444 '%history -t' to see the translated history; this will give you the
445 '%history -t' to see the translated history; this will give you the
445 input after removal of all the leading prompts and whitespace, which
446 input after removal of all the leading prompts and whitespace, which
446 can be pasted back into an editor.
447 can be pasted back into an editor.
447
448
448 With these features, you can switch into this mode easily whenever you
449 With these features, you can switch into this mode easily whenever you
449 need to do testing and changes to doctests, without having to leave
450 need to do testing and changes to doctests, without having to leave
450 your existing IPython session.
451 your existing IPython session.
451 """
452 """
452
453
453 # Shorthands
454 # Shorthands
454 shell = self.shell
455 shell = self.shell
455 pm = shell.prompt_manager
456 pm = shell.prompt_manager
456 meta = shell.meta
457 meta = shell.meta
457 disp_formatter = self.shell.display_formatter
458 disp_formatter = self.shell.display_formatter
458 ptformatter = disp_formatter.formatters['text/plain']
459 ptformatter = disp_formatter.formatters['text/plain']
459 # dstore is a data store kept in the instance metadata bag to track any
460 # dstore is a data store kept in the instance metadata bag to track any
460 # changes we make, so we can undo them later.
461 # changes we make, so we can undo them later.
461 dstore = meta.setdefault('doctest_mode',Struct())
462 dstore = meta.setdefault('doctest_mode',Struct())
462 save_dstore = dstore.setdefault
463 save_dstore = dstore.setdefault
463
464
464 # save a few values we'll need to recover later
465 # save a few values we'll need to recover later
465 mode = save_dstore('mode',False)
466 mode = save_dstore('mode',False)
466 save_dstore('rc_pprint',ptformatter.pprint)
467 save_dstore('rc_pprint',ptformatter.pprint)
467 save_dstore('xmode',shell.InteractiveTB.mode)
468 save_dstore('xmode',shell.InteractiveTB.mode)
468 save_dstore('rc_separate_out',shell.separate_out)
469 save_dstore('rc_separate_out',shell.separate_out)
469 save_dstore('rc_separate_out2',shell.separate_out2)
470 save_dstore('rc_separate_out2',shell.separate_out2)
470 save_dstore('rc_prompts_pad_left',pm.justify)
471 save_dstore('rc_prompts_pad_left',pm.justify)
471 save_dstore('rc_separate_in',shell.separate_in)
472 save_dstore('rc_separate_in',shell.separate_in)
472 save_dstore('rc_active_types',disp_formatter.active_types)
473 save_dstore('rc_active_types',disp_formatter.active_types)
473 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
474 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
474
475
475 if mode == False:
476 if mode == False:
476 # turn on
477 # turn on
477 pm.in_template = '>>> '
478 pm.in_template = '>>> '
478 pm.in2_template = '... '
479 pm.in2_template = '... '
479 pm.out_template = ''
480 pm.out_template = ''
480
481
481 # Prompt separators like plain python
482 # Prompt separators like plain python
482 shell.separate_in = ''
483 shell.separate_in = ''
483 shell.separate_out = ''
484 shell.separate_out = ''
484 shell.separate_out2 = ''
485 shell.separate_out2 = ''
485
486
486 pm.justify = False
487 pm.justify = False
487
488
488 ptformatter.pprint = False
489 ptformatter.pprint = False
489 disp_formatter.active_types = ['text/plain']
490 disp_formatter.active_types = ['text/plain']
490
491
491 shell.magic('xmode Plain')
492 shell.magic('xmode Plain')
492 else:
493 else:
493 # turn off
494 # turn off
494 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
495 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
495
496
496 shell.separate_in = dstore.rc_separate_in
497 shell.separate_in = dstore.rc_separate_in
497
498
498 shell.separate_out = dstore.rc_separate_out
499 shell.separate_out = dstore.rc_separate_out
499 shell.separate_out2 = dstore.rc_separate_out2
500 shell.separate_out2 = dstore.rc_separate_out2
500
501
501 pm.justify = dstore.rc_prompts_pad_left
502 pm.justify = dstore.rc_prompts_pad_left
502
503
503 ptformatter.pprint = dstore.rc_pprint
504 ptformatter.pprint = dstore.rc_pprint
504 disp_formatter.active_types = dstore.rc_active_types
505 disp_formatter.active_types = dstore.rc_active_types
505
506
506 shell.magic('xmode ' + dstore.xmode)
507 shell.magic('xmode ' + dstore.xmode)
507
508
508 # Store new mode and inform
509 # Store new mode and inform
509 dstore.mode = bool(1-int(mode))
510 dstore.mode = bool(1-int(mode))
510 mode_label = ['OFF','ON'][dstore.mode]
511 mode_label = ['OFF','ON'][dstore.mode]
511 print('Doctest mode is:', mode_label)
512 print('Doctest mode is:', mode_label)
512
513
513 @line_magic
514 @line_magic
514 def gui(self, parameter_s=''):
515 def gui(self, parameter_s=''):
515 """Enable or disable IPython GUI event loop integration.
516 """Enable or disable IPython GUI event loop integration.
516
517
517 %gui [GUINAME]
518 %gui [GUINAME]
518
519
519 This magic replaces IPython's threaded shells that were activated
520 This magic replaces IPython's threaded shells that were activated
520 using the (pylab/wthread/etc.) command line flags. GUI toolkits
521 using the (pylab/wthread/etc.) command line flags. GUI toolkits
521 can now be enabled at runtime and keyboard
522 can now be enabled at runtime and keyboard
522 interrupts should work without any problems. The following toolkits
523 interrupts should work without any problems. The following toolkits
523 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
524 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
524
525
525 %gui wx # enable wxPython event loop integration
526 %gui wx # enable wxPython event loop integration
526 %gui qt4|qt # enable PyQt4 event loop integration
527 %gui qt4|qt # enable PyQt4 event loop integration
527 %gui gtk # enable PyGTK event loop integration
528 %gui gtk # enable PyGTK event loop integration
528 %gui gtk3 # enable Gtk3 event loop integration
529 %gui gtk3 # enable Gtk3 event loop integration
529 %gui tk # enable Tk event loop integration
530 %gui tk # enable Tk event loop integration
530 %gui osx # enable Cocoa event loop integration
531 %gui osx # enable Cocoa event loop integration
531 # (requires %matplotlib 1.1)
532 # (requires %matplotlib 1.1)
532 %gui # disable all event loop integration
533 %gui # disable all event loop integration
533
534
534 WARNING: after any of these has been called you can simply create
535 WARNING: after any of these has been called you can simply create
535 an application object, but DO NOT start the event loop yourself, as
536 an application object, but DO NOT start the event loop yourself, as
536 we have already handled that.
537 we have already handled that.
537 """
538 """
538 opts, arg = self.parse_options(parameter_s, '')
539 opts, arg = self.parse_options(parameter_s, '')
539 if arg=='': arg = None
540 if arg=='': arg = None
540 try:
541 try:
541 return self.shell.enable_gui(arg)
542 return self.shell.enable_gui(arg)
542 except Exception as e:
543 except Exception as e:
543 # print simple error message, rather than traceback if we can't
544 # print simple error message, rather than traceback if we can't
544 # hook up the GUI
545 # hook up the GUI
545 error(str(e))
546 error(str(e))
546
547
547 @skip_doctest
548 @skip_doctest
548 @line_magic
549 @line_magic
549 def precision(self, s=''):
550 def precision(self, s=''):
550 """Set floating point precision for pretty printing.
551 """Set floating point precision for pretty printing.
551
552
552 Can set either integer precision or a format string.
553 Can set either integer precision or a format string.
553
554
554 If numpy has been imported and precision is an int,
555 If numpy has been imported and precision is an int,
555 numpy display precision will also be set, via ``numpy.set_printoptions``.
556 numpy display precision will also be set, via ``numpy.set_printoptions``.
556
557
557 If no argument is given, defaults will be restored.
558 If no argument is given, defaults will be restored.
558
559
559 Examples
560 Examples
560 --------
561 --------
561 ::
562 ::
562
563
563 In [1]: from math import pi
564 In [1]: from math import pi
564
565
565 In [2]: %precision 3
566 In [2]: %precision 3
566 Out[2]: u'%.3f'
567 Out[2]: u'%.3f'
567
568
568 In [3]: pi
569 In [3]: pi
569 Out[3]: 3.142
570 Out[3]: 3.142
570
571
571 In [4]: %precision %i
572 In [4]: %precision %i
572 Out[4]: u'%i'
573 Out[4]: u'%i'
573
574
574 In [5]: pi
575 In [5]: pi
575 Out[5]: 3
576 Out[5]: 3
576
577
577 In [6]: %precision %e
578 In [6]: %precision %e
578 Out[6]: u'%e'
579 Out[6]: u'%e'
579
580
580 In [7]: pi**10
581 In [7]: pi**10
581 Out[7]: 9.364805e+04
582 Out[7]: 9.364805e+04
582
583
583 In [8]: %precision
584 In [8]: %precision
584 Out[8]: u'%r'
585 Out[8]: u'%r'
585
586
586 In [9]: pi**10
587 In [9]: pi**10
587 Out[9]: 93648.047476082982
588 Out[9]: 93648.047476082982
588 """
589 """
589 ptformatter = self.shell.display_formatter.formatters['text/plain']
590 ptformatter = self.shell.display_formatter.formatters['text/plain']
590 ptformatter.float_precision = s
591 ptformatter.float_precision = s
591 return ptformatter.float_format
592 return ptformatter.float_format
592
593
593 @magic_arguments.magic_arguments()
594 @magic_arguments.magic_arguments()
594 @magic_arguments.argument(
595 @magic_arguments.argument(
595 '-e', '--export', action='store_true', default=False,
596 '-e', '--export', action='store_true', default=False,
596 help='Export IPython history as a notebook. The filename argument '
597 help='Export IPython history as a notebook. The filename argument '
597 'is used to specify the notebook name and format. For example '
598 'is used to specify the notebook name and format. For example '
598 'a filename of notebook.ipynb will result in a notebook name '
599 'a filename of notebook.ipynb will result in a notebook name '
599 'of "notebook" and a format of "json". Likewise using a ".py" '
600 'of "notebook" and a format of "json". Likewise using a ".py" '
600 'file extension will write the notebook as a Python script'
601 'file extension will write the notebook as a Python script'
601 )
602 )
602 @magic_arguments.argument(
603 @magic_arguments.argument(
603 '-f', '--format',
604 '-f', '--format',
604 help='Convert an existing IPython notebook to a new format. This option '
605 help='Convert an existing IPython notebook to a new format. This option '
605 'specifies the new format and can have the values: json, py. '
606 'specifies the new format and can have the values: json, py. '
606 'The target filename is chosen automatically based on the new '
607 'The target filename is chosen automatically based on the new '
607 'format. The filename argument gives the name of the source file.'
608 'format. The filename argument gives the name of the source file.'
608 )
609 )
609 @magic_arguments.argument(
610 @magic_arguments.argument(
610 'filename', type=unicode_type,
611 'filename', type=unicode_type,
611 help='Notebook name or filename'
612 help='Notebook name or filename'
612 )
613 )
613 @line_magic
614 @line_magic
614 def notebook(self, s):
615 def notebook(self, s):
615 """Export and convert IPython notebooks.
616 """Export and convert IPython notebooks.
616
617
617 This function can export the current IPython history to a notebook file
618 This function can export the current IPython history to a notebook file
618 or can convert an existing notebook file into a different format. For
619 or can convert an existing notebook file into a different format. For
619 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
620 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
620 To export the history to "foo.py" do "%notebook -e foo.py". To convert
621 To export the history to "foo.py" do "%notebook -e foo.py". To convert
621 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
622 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
622 formats include (json/ipynb, py).
623 formats include (json/ipynb, py).
623 """
624 """
624 args = magic_arguments.parse_argstring(self.notebook, s)
625 args = magic_arguments.parse_argstring(self.notebook, s)
625
626
626 from IPython.nbformat import current
627 from IPython.nbformat import current
627 args.filename = unquote_filename(args.filename)
628 args.filename = unquote_filename(args.filename)
628 if args.export:
629 if args.export:
629 fname, name, format = current.parse_filename(args.filename)
630 fname, name, format = current.parse_filename(args.filename)
630 cells = []
631 cells = []
631 hist = list(self.shell.history_manager.get_range())
632 hist = list(self.shell.history_manager.get_range())
632 for session, prompt_number, input in hist[:-1]:
633 for session, prompt_number, input in hist[:-1]:
633 cells.append(current.new_code_cell(prompt_number=prompt_number,
634 cells.append(current.new_code_cell(prompt_number=prompt_number,
634 input=input))
635 input=input))
635 worksheet = current.new_worksheet(cells=cells)
636 worksheet = current.new_worksheet(cells=cells)
636 nb = current.new_notebook(name=name,worksheets=[worksheet])
637 nb = current.new_notebook(name=name,worksheets=[worksheet])
637 with io.open(fname, 'w', encoding='utf-8') as f:
638 with io.open(fname, 'w', encoding='utf-8') as f:
638 current.write(nb, f, format);
639 current.write(nb, f, format);
639 elif args.format is not None:
640 elif args.format is not None:
640 old_fname, old_name, old_format = current.parse_filename(args.filename)
641 old_fname, old_name, old_format = current.parse_filename(args.filename)
641 new_format = args.format
642 new_format = args.format
642 if new_format == u'xml':
643 if new_format == u'xml':
643 raise ValueError('Notebooks cannot be written as xml.')
644 raise ValueError('Notebooks cannot be written as xml.')
644 elif new_format == u'ipynb' or new_format == u'json':
645 elif new_format == u'ipynb' or new_format == u'json':
645 new_fname = old_name + u'.ipynb'
646 new_fname = old_name + u'.ipynb'
646 new_format = u'json'
647 new_format = u'json'
647 elif new_format == u'py':
648 elif new_format == u'py':
648 new_fname = old_name + u'.py'
649 new_fname = old_name + u'.py'
649 else:
650 else:
650 raise ValueError('Invalid notebook format: %s' % new_format)
651 raise ValueError('Invalid notebook format: %s' % new_format)
651 with io.open(old_fname, 'r', encoding='utf-8') as f:
652 with io.open(old_fname, 'r', encoding='utf-8') as f:
652 nb = current.read(f, old_format)
653 nb = current.read(f, old_format)
653 with io.open(new_fname, 'w', encoding='utf-8') as f:
654 with io.open(new_fname, 'w', encoding='utf-8') as f:
654 current.write(nb, f, new_format)
655 current.write(nb, f, new_format)
@@ -1,153 +1,153 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for profile-related functions.
2 """Tests for profile-related functions.
3
3
4 Currently only the startup-dir functionality is tested, but more tests should
4 Currently only the startup-dir functionality is tested, but more tests should
5 be added for:
5 be added for:
6
6
7 * ipython profile create
7 * ipython profile create
8 * ipython profile list
8 * ipython profile list
9 * ipython profile create --parallel
9 * ipython profile create --parallel
10 * security dir permissions
10 * security dir permissions
11
11
12 Authors
12 Authors
13 -------
13 -------
14
14
15 * MinRK
15 * MinRK
16
16
17 """
17 """
18 from __future__ import absolute_import
18 from __future__ import absolute_import
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import os
24 import os
25 import shutil
25 import shutil
26 import sys
26 import sys
27 import tempfile
27 import tempfile
28
28
29 from unittest import TestCase
29 from unittest import TestCase
30
30
31 import nose.tools as nt
31 import nose.tools as nt
32
32
33 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
33 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
34 from IPython.core.profiledir import ProfileDir
34 from IPython.core.profiledir import ProfileDir
35
35
36 from IPython.testing import decorators as dec
36 from IPython.testing import decorators as dec
37 from IPython.testing import tools as tt
37 from IPython.testing import tools as tt
38 from IPython.utils import py3compat
38 from IPython.utils import py3compat
39
39
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Globals
42 # Globals
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 TMP_TEST_DIR = tempfile.mkdtemp()
44 TMP_TEST_DIR = tempfile.mkdtemp()
45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
45 HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
46 IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
47
47
48 #
48 #
49 # Setup/teardown functions/decorators
49 # Setup/teardown functions/decorators
50 #
50 #
51
51
52 def setup():
52 def setup():
53 """Setup test environment for the module:
53 """Setup test environment for the module:
54
54
55 - Adds dummy home dir tree
55 - Adds dummy home dir tree
56 """
56 """
57 # Do not mask exceptions here. In particular, catching WindowsError is a
57 # Do not mask exceptions here. In particular, catching WindowsError is a
58 # problem because that exception is only defined on Windows...
58 # problem because that exception is only defined on Windows...
59 os.makedirs(IP_TEST_DIR)
59 os.makedirs(IP_TEST_DIR)
60
60
61
61
62 def teardown():
62 def teardown():
63 """Teardown test environment for the module:
63 """Teardown test environment for the module:
64
64
65 - Remove dummy home dir tree
65 - Remove dummy home dir tree
66 """
66 """
67 # Note: we remove the parent test dir, which is the root of all test
67 # Note: we remove the parent test dir, which is the root of all test
68 # subdirs we may have created. Use shutil instead of os.removedirs, so
68 # subdirs we may have created. Use shutil instead of os.removedirs, so
69 # that non-empty directories are all recursively removed.
69 # that non-empty directories are all recursively removed.
70 shutil.rmtree(TMP_TEST_DIR)
70 shutil.rmtree(TMP_TEST_DIR)
71
71
72
72
73 #-----------------------------------------------------------------------------
73 #-----------------------------------------------------------------------------
74 # Test functions
74 # Test functions
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76 def win32_without_pywin32():
76 def win32_without_pywin32():
77 if sys.platform == 'win32':
77 if sys.platform == 'win32':
78 try:
78 try:
79 import pywin32
79 import pywin32
80 except ImportError:
80 except ImportError:
81 return True
81 return True
82 return False
82 return False
83
83
84
84
85 class ProfileStartupTest(TestCase):
85 class ProfileStartupTest(TestCase):
86 def setUp(self):
86 def setUp(self):
87 # create profile dir
87 # create profile dir
88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
88 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, 'test')
89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
89 self.options = ['--ipython-dir', IP_TEST_DIR, '--profile', 'test']
90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
90 self.fname = os.path.join(TMP_TEST_DIR, 'test.py')
91
91
92 def tearDown(self):
92 def tearDown(self):
93 # We must remove this profile right away so its presence doesn't
93 # We must remove this profile right away so its presence doesn't
94 # confuse other tests.
94 # confuse other tests.
95 shutil.rmtree(self.pd.location)
95 shutil.rmtree(self.pd.location)
96
96
97 def init(self, startup_file, startup, test):
97 def init(self, startup_file, startup, test):
98 # write startup python file
98 # write startup python file
99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
99 with open(os.path.join(self.pd.startup_dir, startup_file), 'w') as f:
100 f.write(startup)
100 f.write(startup)
101 # write simple test file, to check that the startup file was run
101 # write simple test file, to check that the startup file was run
102 with open(self.fname, 'w') as f:
102 with open(self.fname, 'w') as f:
103 f.write(py3compat.doctest_refactor_print(test))
103 f.write(py3compat.doctest_refactor_print(test))
104
104
105 def validate(self, output):
105 def validate(self, output):
106 tt.ipexec_validate(self.fname, output, '', options=self.options)
106 tt.ipexec_validate(self.fname, output, '', options=self.options)
107
107
108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
108 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
109 def test_startup_py(self):
109 def test_startup_py(self):
110 self.init('00-start.py', 'zzz=123\n',
110 self.init('00-start.py', 'zzz=123\n',
111 py3compat.doctest_refactor_print('print zzz\n'))
111 py3compat.doctest_refactor_print('print zzz\n'))
112 self.validate('123')
112 self.validate('123')
113
113
114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
114 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
115 def test_startup_ipy(self):
115 def test_startup_ipy(self):
116 self.init('00-start.ipy', '%profile\n', '')
116 self.init('00-start.ipy', '%xmode plain\n', '')
117 self.validate('test')
117 self.validate('Exception reporting mode: Plain')
118
118
119
119
120 def test_list_profiles_in():
120 def test_list_profiles_in():
121 # No need to remove these directories and files, as they will get nuked in
121 # No need to remove these directories and files, as they will get nuked in
122 # the module-level teardown.
122 # the module-level teardown.
123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
123 td = tempfile.mkdtemp(dir=TMP_TEST_DIR)
124 td = py3compat.str_to_unicode(td)
124 td = py3compat.str_to_unicode(td)
125 for name in ('profile_foo', 'profile_hello', 'not_a_profile'):
125 for name in ('profile_foo', 'profile_hello', 'not_a_profile'):
126 os.mkdir(os.path.join(td, name))
126 os.mkdir(os.path.join(td, name))
127 if dec.unicode_paths:
127 if dec.unicode_paths:
128 os.mkdir(os.path.join(td, u'profile_ünicode'))
128 os.mkdir(os.path.join(td, u'profile_ünicode'))
129
129
130 with open(os.path.join(td, 'profile_file'), 'w') as f:
130 with open(os.path.join(td, 'profile_file'), 'w') as f:
131 f.write("I am not a profile directory")
131 f.write("I am not a profile directory")
132 profiles = list_profiles_in(td)
132 profiles = list_profiles_in(td)
133
133
134 # unicode normalization can turn u'ünicode' into u'u\0308nicode',
134 # unicode normalization can turn u'ünicode' into u'u\0308nicode',
135 # so only check for *nicode, and that creating a ProfileDir from the
135 # so only check for *nicode, and that creating a ProfileDir from the
136 # name remains valid
136 # name remains valid
137 found_unicode = False
137 found_unicode = False
138 for p in list(profiles):
138 for p in list(profiles):
139 if p.endswith('nicode'):
139 if p.endswith('nicode'):
140 pd = ProfileDir.find_profile_dir_by_name(td, p)
140 pd = ProfileDir.find_profile_dir_by_name(td, p)
141 profiles.remove(p)
141 profiles.remove(p)
142 found_unicode = True
142 found_unicode = True
143 break
143 break
144 if dec.unicode_paths:
144 if dec.unicode_paths:
145 nt.assert_true(found_unicode)
145 nt.assert_true(found_unicode)
146 nt.assert_equal(set(profiles), set(['foo', 'hello']))
146 nt.assert_equal(set(profiles), set(['foo', 'hello']))
147
147
148
148
149 def test_list_bundled_profiles():
149 def test_list_bundled_profiles():
150 # This variable will need to be updated when a new profile gets bundled
150 # This variable will need to be updated when a new profile gets bundled
151 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
151 bundled_true = [u'cluster', u'math', u'pysh', u'sympy']
152 bundled = sorted(list_bundled_profiles())
152 bundled = sorted(list_bundled_profiles())
153 nt.assert_equal(bundled, bundled_true)
153 nt.assert_equal(bundled, bundled_true)
General Comments 0
You need to be logged in to leave comments. Login now