##// END OF EJS Templates
Move globlist and its test under utils.path
Takafumi Arakaki -
Show More
@@ -1,1050 +1,1036 b''
1 """Implementation of execution-related magic functions.
1 """Implementation of execution-related magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import __builtin__ as builtin_mod
16 import __builtin__ as builtin_mod
17 import bdb
17 import bdb
18 import os
18 import os
19 import sys
19 import sys
20 import time
20 import time
21 from StringIO import StringIO
21 from StringIO import StringIO
22 from glob import glob
23
22
24 # cProfile was added in Python2.5
23 # cProfile was added in Python2.5
25 try:
24 try:
26 import cProfile as profile
25 import cProfile as profile
27 import pstats
26 import pstats
28 except ImportError:
27 except ImportError:
29 # profile isn't bundled by default in Debian for license reasons
28 # profile isn't bundled by default in Debian for license reasons
30 try:
29 try:
31 import profile, pstats
30 import profile, pstats
32 except ImportError:
31 except ImportError:
33 profile = pstats = None
32 profile = pstats = None
34
33
35 # Our own packages
34 # Our own packages
36 from IPython.core import debugger, oinspect
35 from IPython.core import debugger, oinspect
37 from IPython.core import magic_arguments
36 from IPython.core import magic_arguments
38 from IPython.core import page
37 from IPython.core import page
39 from IPython.core.error import UsageError
38 from IPython.core.error import UsageError
40 from IPython.core.macro import Macro
39 from IPython.core.macro import Macro
41 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
40 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
42 line_cell_magic, on_off, needs_local_scope)
41 line_cell_magic, on_off, needs_local_scope)
43 from IPython.testing.skipdoctest import skip_doctest
42 from IPython.testing.skipdoctest import skip_doctest
44 from IPython.utils import py3compat
43 from IPython.utils import py3compat
45 from IPython.utils.io import capture_output
44 from IPython.utils.io import capture_output
46 from IPython.utils.ipstruct import Struct
45 from IPython.utils.ipstruct import Struct
47 from IPython.utils.module_paths import find_mod
46 from IPython.utils.module_paths import find_mod
48 from IPython.utils.path import get_py_filename, unquote_filename
47 from IPython.utils.path import get_py_filename, unquote_filename, globlist
49 from IPython.utils.timing import clock, clock2
48 from IPython.utils.timing import clock, clock2
50 from IPython.utils.warn import warn, error
49 from IPython.utils.warn import warn, error
51
50
52
51
53 def globlist(args):
54 """
55 Do glob expansion for each element in `args` and return a flattened list.
56
57 Unmatched glob pattern will remain as-is in the returned list.
58
59 """
60 expanded = []
61 for a in args:
62 expanded.extend(glob(a) or [a])
63 return expanded
64
65
66 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
67 # Magic implementation classes
53 # Magic implementation classes
68 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
69
55
70 @magics_class
56 @magics_class
71 class ExecutionMagics(Magics):
57 class ExecutionMagics(Magics):
72 """Magics related to code execution, debugging, profiling, etc.
58 """Magics related to code execution, debugging, profiling, etc.
73
59
74 """
60 """
75
61
76 def __init__(self, shell):
62 def __init__(self, shell):
77 super(ExecutionMagics, self).__init__(shell)
63 super(ExecutionMagics, self).__init__(shell)
78 if profile is None:
64 if profile is None:
79 self.prun = self.profile_missing_notice
65 self.prun = self.profile_missing_notice
80 # Default execution function used to actually run user code.
66 # Default execution function used to actually run user code.
81 self.default_runner = None
67 self.default_runner = None
82
68
83 def profile_missing_notice(self, *args, **kwargs):
69 def profile_missing_notice(self, *args, **kwargs):
84 error("""\
70 error("""\
85 The profile module could not be found. It has been removed from the standard
71 The profile module could not be found. It has been removed from the standard
86 python packages because of its non-free license. To use profiling, install the
72 python packages because of its non-free license. To use profiling, install the
87 python-profiler package from non-free.""")
73 python-profiler package from non-free.""")
88
74
89 @skip_doctest
75 @skip_doctest
90 @line_cell_magic
76 @line_cell_magic
91 def prun(self, parameter_s='', cell=None, user_mode=True,
77 def prun(self, parameter_s='', cell=None, user_mode=True,
92 opts=None,arg_lst=None,prog_ns=None):
78 opts=None,arg_lst=None,prog_ns=None):
93
79
94 """Run a statement through the python code profiler.
80 """Run a statement through the python code profiler.
95
81
96 Usage, in line mode:
82 Usage, in line mode:
97 %prun [options] statement
83 %prun [options] statement
98
84
99 Usage, in cell mode:
85 Usage, in cell mode:
100 %%prun [options] [statement]
86 %%prun [options] [statement]
101 code...
87 code...
102 code...
88 code...
103
89
104 In cell mode, the additional code lines are appended to the (possibly
90 In cell mode, the additional code lines are appended to the (possibly
105 empty) statement in the first line. Cell mode allows you to easily
91 empty) statement in the first line. Cell mode allows you to easily
106 profile multiline blocks without having to put them in a separate
92 profile multiline blocks without having to put them in a separate
107 function.
93 function.
108
94
109 The given statement (which doesn't require quote marks) is run via the
95 The given statement (which doesn't require quote marks) is run via the
110 python profiler in a manner similar to the profile.run() function.
96 python profiler in a manner similar to the profile.run() function.
111 Namespaces are internally managed to work correctly; profile.run
97 Namespaces are internally managed to work correctly; profile.run
112 cannot be used in IPython because it makes certain assumptions about
98 cannot be used in IPython because it makes certain assumptions about
113 namespaces which do not hold under IPython.
99 namespaces which do not hold under IPython.
114
100
115 Options:
101 Options:
116
102
117 -l <limit>: you can place restrictions on what or how much of the
103 -l <limit>: you can place restrictions on what or how much of the
118 profile gets printed. The limit value can be:
104 profile gets printed. The limit value can be:
119
105
120 * A string: only information for function names containing this string
106 * A string: only information for function names containing this string
121 is printed.
107 is printed.
122
108
123 * An integer: only these many lines are printed.
109 * An integer: only these many lines are printed.
124
110
125 * A float (between 0 and 1): this fraction of the report is printed
111 * A float (between 0 and 1): this fraction of the report is printed
126 (for example, use a limit of 0.4 to see the topmost 40% only).
112 (for example, use a limit of 0.4 to see the topmost 40% only).
127
113
128 You can combine several limits with repeated use of the option. For
114 You can combine several limits with repeated use of the option. For
129 example, '-l __init__ -l 5' will print only the topmost 5 lines of
115 example, '-l __init__ -l 5' will print only the topmost 5 lines of
130 information about class constructors.
116 information about class constructors.
131
117
132 -r: return the pstats.Stats object generated by the profiling. This
118 -r: return the pstats.Stats object generated by the profiling. This
133 object has all the information about the profile in it, and you can
119 object has all the information about the profile in it, and you can
134 later use it for further analysis or in other functions.
120 later use it for further analysis or in other functions.
135
121
136 -s <key>: sort profile by given key. You can provide more than one key
122 -s <key>: sort profile by given key. You can provide more than one key
137 by using the option several times: '-s key1 -s key2 -s key3...'. The
123 by using the option several times: '-s key1 -s key2 -s key3...'. The
138 default sorting key is 'time'.
124 default sorting key is 'time'.
139
125
140 The following is copied verbatim from the profile documentation
126 The following is copied verbatim from the profile documentation
141 referenced below:
127 referenced below:
142
128
143 When more than one key is provided, additional keys are used as
129 When more than one key is provided, additional keys are used as
144 secondary criteria when the there is equality in all keys selected
130 secondary criteria when the there is equality in all keys selected
145 before them.
131 before them.
146
132
147 Abbreviations can be used for any key names, as long as the
133 Abbreviations can be used for any key names, as long as the
148 abbreviation is unambiguous. The following are the keys currently
134 abbreviation is unambiguous. The following are the keys currently
149 defined:
135 defined:
150
136
151 Valid Arg Meaning
137 Valid Arg Meaning
152 "calls" call count
138 "calls" call count
153 "cumulative" cumulative time
139 "cumulative" cumulative time
154 "file" file name
140 "file" file name
155 "module" file name
141 "module" file name
156 "pcalls" primitive call count
142 "pcalls" primitive call count
157 "line" line number
143 "line" line number
158 "name" function name
144 "name" function name
159 "nfl" name/file/line
145 "nfl" name/file/line
160 "stdname" standard name
146 "stdname" standard name
161 "time" internal time
147 "time" internal time
162
148
163 Note that all sorts on statistics are in descending order (placing
149 Note that all sorts on statistics are in descending order (placing
164 most time consuming items first), where as name, file, and line number
150 most time consuming items first), where as name, file, and line number
165 searches are in ascending order (i.e., alphabetical). The subtle
151 searches are in ascending order (i.e., alphabetical). The subtle
166 distinction between "nfl" and "stdname" is that the standard name is a
152 distinction between "nfl" and "stdname" is that the standard name is a
167 sort of the name as printed, which means that the embedded line
153 sort of the name as printed, which means that the embedded line
168 numbers get compared in an odd way. For example, lines 3, 20, and 40
154 numbers get compared in an odd way. For example, lines 3, 20, and 40
169 would (if the file names were the same) appear in the string order
155 would (if the file names were the same) appear in the string order
170 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
156 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
171 line numbers. In fact, sort_stats("nfl") is the same as
157 line numbers. In fact, sort_stats("nfl") is the same as
172 sort_stats("name", "file", "line").
158 sort_stats("name", "file", "line").
173
159
174 -T <filename>: save profile results as shown on screen to a text
160 -T <filename>: save profile results as shown on screen to a text
175 file. The profile is still shown on screen.
161 file. The profile is still shown on screen.
176
162
177 -D <filename>: save (via dump_stats) profile statistics to given
163 -D <filename>: save (via dump_stats) profile statistics to given
178 filename. This data is in a format understood by the pstats module, and
164 filename. This data is in a format understood by the pstats module, and
179 is generated by a call to the dump_stats() method of profile
165 is generated by a call to the dump_stats() method of profile
180 objects. The profile is still shown on screen.
166 objects. The profile is still shown on screen.
181
167
182 -q: suppress output to the pager. Best used with -T and/or -D above.
168 -q: suppress output to the pager. Best used with -T and/or -D above.
183
169
184 If you want to run complete programs under the profiler's control, use
170 If you want to run complete programs under the profiler's control, use
185 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
171 '%run -p [prof_opts] filename.py [args to program]' where prof_opts
186 contains profiler specific options as described here.
172 contains profiler specific options as described here.
187
173
188 You can read the complete documentation for the profile module with::
174 You can read the complete documentation for the profile module with::
189
175
190 In [1]: import profile; profile.help()
176 In [1]: import profile; profile.help()
191 """
177 """
192
178
193 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
179 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
194
180
195 if user_mode: # regular user call
181 if user_mode: # regular user call
196 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:q',
182 opts,arg_str = self.parse_options(parameter_s,'D:l:rs:T:q',
197 list_all=True, posix=False)
183 list_all=True, posix=False)
198 namespace = self.shell.user_ns
184 namespace = self.shell.user_ns
199 if cell is not None:
185 if cell is not None:
200 arg_str += '\n' + cell
186 arg_str += '\n' + cell
201 else: # called to run a program by %run -p
187 else: # called to run a program by %run -p
202 try:
188 try:
203 filename = get_py_filename(arg_lst[0])
189 filename = get_py_filename(arg_lst[0])
204 except IOError as e:
190 except IOError as e:
205 try:
191 try:
206 msg = str(e)
192 msg = str(e)
207 except UnicodeError:
193 except UnicodeError:
208 msg = e.message
194 msg = e.message
209 error(msg)
195 error(msg)
210 return
196 return
211
197
212 arg_str = 'execfile(filename,prog_ns)'
198 arg_str = 'execfile(filename,prog_ns)'
213 namespace = {
199 namespace = {
214 'execfile': self.shell.safe_execfile,
200 'execfile': self.shell.safe_execfile,
215 'prog_ns': prog_ns,
201 'prog_ns': prog_ns,
216 'filename': filename
202 'filename': filename
217 }
203 }
218
204
219 opts.merge(opts_def)
205 opts.merge(opts_def)
220
206
221 prof = profile.Profile()
207 prof = profile.Profile()
222 try:
208 try:
223 prof = prof.runctx(arg_str,namespace,namespace)
209 prof = prof.runctx(arg_str,namespace,namespace)
224 sys_exit = ''
210 sys_exit = ''
225 except SystemExit:
211 except SystemExit:
226 sys_exit = """*** SystemExit exception caught in code being profiled."""
212 sys_exit = """*** SystemExit exception caught in code being profiled."""
227
213
228 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
214 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
229
215
230 lims = opts.l
216 lims = opts.l
231 if lims:
217 if lims:
232 lims = [] # rebuild lims with ints/floats/strings
218 lims = [] # rebuild lims with ints/floats/strings
233 for lim in opts.l:
219 for lim in opts.l:
234 try:
220 try:
235 lims.append(int(lim))
221 lims.append(int(lim))
236 except ValueError:
222 except ValueError:
237 try:
223 try:
238 lims.append(float(lim))
224 lims.append(float(lim))
239 except ValueError:
225 except ValueError:
240 lims.append(lim)
226 lims.append(lim)
241
227
242 # Trap output.
228 # Trap output.
243 stdout_trap = StringIO()
229 stdout_trap = StringIO()
244
230
245 if hasattr(stats,'stream'):
231 if hasattr(stats,'stream'):
246 # In newer versions of python, the stats object has a 'stream'
232 # In newer versions of python, the stats object has a 'stream'
247 # attribute to write into.
233 # attribute to write into.
248 stats.stream = stdout_trap
234 stats.stream = stdout_trap
249 stats.print_stats(*lims)
235 stats.print_stats(*lims)
250 else:
236 else:
251 # For older versions, we manually redirect stdout during printing
237 # For older versions, we manually redirect stdout during printing
252 sys_stdout = sys.stdout
238 sys_stdout = sys.stdout
253 try:
239 try:
254 sys.stdout = stdout_trap
240 sys.stdout = stdout_trap
255 stats.print_stats(*lims)
241 stats.print_stats(*lims)
256 finally:
242 finally:
257 sys.stdout = sys_stdout
243 sys.stdout = sys_stdout
258
244
259 output = stdout_trap.getvalue()
245 output = stdout_trap.getvalue()
260 output = output.rstrip()
246 output = output.rstrip()
261
247
262 if 'q' not in opts:
248 if 'q' not in opts:
263 page.page(output)
249 page.page(output)
264 print sys_exit,
250 print sys_exit,
265
251
266 dump_file = opts.D[0]
252 dump_file = opts.D[0]
267 text_file = opts.T[0]
253 text_file = opts.T[0]
268 if dump_file:
254 if dump_file:
269 dump_file = unquote_filename(dump_file)
255 dump_file = unquote_filename(dump_file)
270 prof.dump_stats(dump_file)
256 prof.dump_stats(dump_file)
271 print '\n*** Profile stats marshalled to file',\
257 print '\n*** Profile stats marshalled to file',\
272 repr(dump_file)+'.',sys_exit
258 repr(dump_file)+'.',sys_exit
273 if text_file:
259 if text_file:
274 text_file = unquote_filename(text_file)
260 text_file = unquote_filename(text_file)
275 pfile = open(text_file,'w')
261 pfile = open(text_file,'w')
276 pfile.write(output)
262 pfile.write(output)
277 pfile.close()
263 pfile.close()
278 print '\n*** Profile printout saved to text file',\
264 print '\n*** Profile printout saved to text file',\
279 repr(text_file)+'.',sys_exit
265 repr(text_file)+'.',sys_exit
280
266
281 if opts.has_key('r'):
267 if opts.has_key('r'):
282 return stats
268 return stats
283 else:
269 else:
284 return None
270 return None
285
271
286 @line_magic
272 @line_magic
287 def pdb(self, parameter_s=''):
273 def pdb(self, parameter_s=''):
288 """Control the automatic calling of the pdb interactive debugger.
274 """Control the automatic calling of the pdb interactive debugger.
289
275
290 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
276 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
291 argument it works as a toggle.
277 argument it works as a toggle.
292
278
293 When an exception is triggered, IPython can optionally call the
279 When an exception is triggered, IPython can optionally call the
294 interactive pdb debugger after the traceback printout. %pdb toggles
280 interactive pdb debugger after the traceback printout. %pdb toggles
295 this feature on and off.
281 this feature on and off.
296
282
297 The initial state of this feature is set in your configuration
283 The initial state of this feature is set in your configuration
298 file (the option is ``InteractiveShell.pdb``).
284 file (the option is ``InteractiveShell.pdb``).
299
285
300 If you want to just activate the debugger AFTER an exception has fired,
286 If you want to just activate the debugger AFTER an exception has fired,
301 without having to type '%pdb on' and rerunning your code, you can use
287 without having to type '%pdb on' and rerunning your code, you can use
302 the %debug magic."""
288 the %debug magic."""
303
289
304 par = parameter_s.strip().lower()
290 par = parameter_s.strip().lower()
305
291
306 if par:
292 if par:
307 try:
293 try:
308 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
294 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
309 except KeyError:
295 except KeyError:
310 print ('Incorrect argument. Use on/1, off/0, '
296 print ('Incorrect argument. Use on/1, off/0, '
311 'or nothing for a toggle.')
297 'or nothing for a toggle.')
312 return
298 return
313 else:
299 else:
314 # toggle
300 # toggle
315 new_pdb = not self.shell.call_pdb
301 new_pdb = not self.shell.call_pdb
316
302
317 # set on the shell
303 # set on the shell
318 self.shell.call_pdb = new_pdb
304 self.shell.call_pdb = new_pdb
319 print 'Automatic pdb calling has been turned',on_off(new_pdb)
305 print 'Automatic pdb calling has been turned',on_off(new_pdb)
320
306
321 @line_magic
307 @line_magic
322 def debug(self, parameter_s=''):
308 def debug(self, parameter_s=''):
323 """Activate the interactive debugger in post-mortem mode.
309 """Activate the interactive debugger in post-mortem mode.
324
310
325 If an exception has just occurred, this lets you inspect its stack
311 If an exception has just occurred, this lets you inspect its stack
326 frames interactively. Note that this will always work only on the last
312 frames interactively. Note that this will always work only on the last
327 traceback that occurred, so you must call this quickly after an
313 traceback that occurred, so you must call this quickly after an
328 exception that you wish to inspect has fired, because if another one
314 exception that you wish to inspect has fired, because if another one
329 occurs, it clobbers the previous one.
315 occurs, it clobbers the previous one.
330
316
331 If you want IPython to automatically do this on every exception, see
317 If you want IPython to automatically do this on every exception, see
332 the %pdb magic for more details.
318 the %pdb magic for more details.
333 """
319 """
334 self.shell.debugger(force=True)
320 self.shell.debugger(force=True)
335
321
336 @line_magic
322 @line_magic
337 def tb(self, s):
323 def tb(self, s):
338 """Print the last traceback with the currently active exception mode.
324 """Print the last traceback with the currently active exception mode.
339
325
340 See %xmode for changing exception reporting modes."""
326 See %xmode for changing exception reporting modes."""
341 self.shell.showtraceback()
327 self.shell.showtraceback()
342
328
343 @skip_doctest
329 @skip_doctest
344 @line_magic
330 @line_magic
345 def run(self, parameter_s='', runner=None,
331 def run(self, parameter_s='', runner=None,
346 file_finder=get_py_filename):
332 file_finder=get_py_filename):
347 """Run the named file inside IPython as a program.
333 """Run the named file inside IPython as a program.
348
334
349 Usage:\\
335 Usage:\\
350 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options] -G] file [args]
336 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options] -G] file [args]
351
337
352 Parameters after the filename are passed as command-line arguments to
338 Parameters after the filename are passed as command-line arguments to
353 the program (put in sys.argv). Then, control returns to IPython's
339 the program (put in sys.argv). Then, control returns to IPython's
354 prompt.
340 prompt.
355
341
356 This is similar to running at a system prompt:\\
342 This is similar to running at a system prompt:\\
357 $ python file args\\
343 $ python file args\\
358 but with the advantage of giving you IPython's tracebacks, and of
344 but with the advantage of giving you IPython's tracebacks, and of
359 loading all variables into your interactive namespace for further use
345 loading all variables into your interactive namespace for further use
360 (unless -p is used, see below).
346 (unless -p is used, see below).
361
347
362 The file is executed in a namespace initially consisting only of
348 The file is executed in a namespace initially consisting only of
363 __name__=='__main__' and sys.argv constructed as indicated. It thus
349 __name__=='__main__' and sys.argv constructed as indicated. It thus
364 sees its environment as if it were being run as a stand-alone program
350 sees its environment as if it were being run as a stand-alone program
365 (except for sharing global objects such as previously imported
351 (except for sharing global objects such as previously imported
366 modules). But after execution, the IPython interactive namespace gets
352 modules). But after execution, the IPython interactive namespace gets
367 updated with all variables defined in the program (except for __name__
353 updated with all variables defined in the program (except for __name__
368 and sys.argv). This allows for very convenient loading of code for
354 and sys.argv). This allows for very convenient loading of code for
369 interactive work, while giving each program a 'clean sheet' to run in.
355 interactive work, while giving each program a 'clean sheet' to run in.
370
356
371 Arguments are expanded using shell-like glob match. Patterns
357 Arguments are expanded using shell-like glob match. Patterns
372 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
358 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
373 tilde '~' will be expanded into user's home directory. Unlike
359 tilde '~' will be expanded into user's home directory. Unlike
374 real shells, quotation does not suppress expansions. Use back
360 real shells, quotation does not suppress expansions. Use back
375 slash (e.g., '\\*') to suppress expansions. To completely
361 slash (e.g., '\\*') to suppress expansions. To completely
376 disable these expansions, you can use -G flag.
362 disable these expansions, you can use -G flag.
377
363
378 Options:
364 Options:
379
365
380 -n: __name__ is NOT set to '__main__', but to the running file's name
366 -n: __name__ is NOT set to '__main__', but to the running file's name
381 without extension (as python does under import). This allows running
367 without extension (as python does under import). This allows running
382 scripts and reloading the definitions in them without calling code
368 scripts and reloading the definitions in them without calling code
383 protected by an ' if __name__ == "__main__" ' clause.
369 protected by an ' if __name__ == "__main__" ' clause.
384
370
385 -i: run the file in IPython's namespace instead of an empty one. This
371 -i: run the file in IPython's namespace instead of an empty one. This
386 is useful if you are experimenting with code written in a text editor
372 is useful if you are experimenting with code written in a text editor
387 which depends on variables defined interactively.
373 which depends on variables defined interactively.
388
374
389 -e: ignore sys.exit() calls or SystemExit exceptions in the script
375 -e: ignore sys.exit() calls or SystemExit exceptions in the script
390 being run. This is particularly useful if IPython is being used to
376 being run. This is particularly useful if IPython is being used to
391 run unittests, which always exit with a sys.exit() call. In such
377 run unittests, which always exit with a sys.exit() call. In such
392 cases you are interested in the output of the test results, not in
378 cases you are interested in the output of the test results, not in
393 seeing a traceback of the unittest module.
379 seeing a traceback of the unittest module.
394
380
395 -t: print timing information at the end of the run. IPython will give
381 -t: print timing information at the end of the run. IPython will give
396 you an estimated CPU time consumption for your script, which under
382 you an estimated CPU time consumption for your script, which under
397 Unix uses the resource module to avoid the wraparound problems of
383 Unix uses the resource module to avoid the wraparound problems of
398 time.clock(). Under Unix, an estimate of time spent on system tasks
384 time.clock(). Under Unix, an estimate of time spent on system tasks
399 is also given (for Windows platforms this is reported as 0.0).
385 is also given (for Windows platforms this is reported as 0.0).
400
386
401 If -t is given, an additional -N<N> option can be given, where <N>
387 If -t is given, an additional -N<N> option can be given, where <N>
402 must be an integer indicating how many times you want the script to
388 must be an integer indicating how many times you want the script to
403 run. The final timing report will include total and per run results.
389 run. The final timing report will include total and per run results.
404
390
405 For example (testing the script uniq_stable.py)::
391 For example (testing the script uniq_stable.py)::
406
392
407 In [1]: run -t uniq_stable
393 In [1]: run -t uniq_stable
408
394
409 IPython CPU timings (estimated):\\
395 IPython CPU timings (estimated):\\
410 User : 0.19597 s.\\
396 User : 0.19597 s.\\
411 System: 0.0 s.\\
397 System: 0.0 s.\\
412
398
413 In [2]: run -t -N5 uniq_stable
399 In [2]: run -t -N5 uniq_stable
414
400
415 IPython CPU timings (estimated):\\
401 IPython CPU timings (estimated):\\
416 Total runs performed: 5\\
402 Total runs performed: 5\\
417 Times : Total Per run\\
403 Times : Total Per run\\
418 User : 0.910862 s, 0.1821724 s.\\
404 User : 0.910862 s, 0.1821724 s.\\
419 System: 0.0 s, 0.0 s.
405 System: 0.0 s, 0.0 s.
420
406
421 -d: run your program under the control of pdb, the Python debugger.
407 -d: run your program under the control of pdb, the Python debugger.
422 This allows you to execute your program step by step, watch variables,
408 This allows you to execute your program step by step, watch variables,
423 etc. Internally, what IPython does is similar to calling:
409 etc. Internally, what IPython does is similar to calling:
424
410
425 pdb.run('execfile("YOURFILENAME")')
411 pdb.run('execfile("YOURFILENAME")')
426
412
427 with a breakpoint set on line 1 of your file. You can change the line
413 with a breakpoint set on line 1 of your file. You can change the line
428 number for this automatic breakpoint to be <N> by using the -bN option
414 number for this automatic breakpoint to be <N> by using the -bN option
429 (where N must be an integer). For example::
415 (where N must be an integer). For example::
430
416
431 %run -d -b40 myscript
417 %run -d -b40 myscript
432
418
433 will set the first breakpoint at line 40 in myscript.py. Note that
419 will set the first breakpoint at line 40 in myscript.py. Note that
434 the first breakpoint must be set on a line which actually does
420 the first breakpoint must be set on a line which actually does
435 something (not a comment or docstring) for it to stop execution.
421 something (not a comment or docstring) for it to stop execution.
436
422
437 When the pdb debugger starts, you will see a (Pdb) prompt. You must
423 When the pdb debugger starts, you will see a (Pdb) prompt. You must
438 first enter 'c' (without quotes) to start execution up to the first
424 first enter 'c' (without quotes) to start execution up to the first
439 breakpoint.
425 breakpoint.
440
426
441 Entering 'help' gives information about the use of the debugger. You
427 Entering 'help' gives information about the use of the debugger. You
442 can easily see pdb's full documentation with "import pdb;pdb.help()"
428 can easily see pdb's full documentation with "import pdb;pdb.help()"
443 at a prompt.
429 at a prompt.
444
430
445 -p: run program under the control of the Python profiler module (which
431 -p: run program under the control of the Python profiler module (which
446 prints a detailed report of execution times, function calls, etc).
432 prints a detailed report of execution times, function calls, etc).
447
433
448 You can pass other options after -p which affect the behavior of the
434 You can pass other options after -p which affect the behavior of the
449 profiler itself. See the docs for %prun for details.
435 profiler itself. See the docs for %prun for details.
450
436
451 In this mode, the program's variables do NOT propagate back to the
437 In this mode, the program's variables do NOT propagate back to the
452 IPython interactive namespace (because they remain in the namespace
438 IPython interactive namespace (because they remain in the namespace
453 where the profiler executes them).
439 where the profiler executes them).
454
440
455 Internally this triggers a call to %prun, see its documentation for
441 Internally this triggers a call to %prun, see its documentation for
456 details on the options available specifically for profiling.
442 details on the options available specifically for profiling.
457
443
458 There is one special usage for which the text above doesn't apply:
444 There is one special usage for which the text above doesn't apply:
459 if the filename ends with .ipy, the file is run as ipython script,
445 if the filename ends with .ipy, the file is run as ipython script,
460 just as if the commands were written on IPython prompt.
446 just as if the commands were written on IPython prompt.
461
447
462 -m: specify module name to load instead of script path. Similar to
448 -m: specify module name to load instead of script path. Similar to
463 the -m option for the python interpreter. Use this option last if you
449 the -m option for the python interpreter. Use this option last if you
464 want to combine with other %run options. Unlike the python interpreter
450 want to combine with other %run options. Unlike the python interpreter
465 only source modules are allowed no .pyc or .pyo files.
451 only source modules are allowed no .pyc or .pyo files.
466 For example::
452 For example::
467
453
468 %run -m example
454 %run -m example
469
455
470 will run the example module.
456 will run the example module.
471
457
472 -G: disable shell-like glob expansion of arguments.
458 -G: disable shell-like glob expansion of arguments.
473
459
474 """
460 """
475
461
476 # get arguments and set sys.argv for program to be run.
462 # get arguments and set sys.argv for program to be run.
477 opts, arg_lst = self.parse_options(parameter_s,
463 opts, arg_lst = self.parse_options(parameter_s,
478 'nidtN:b:pD:l:rs:T:em:G',
464 'nidtN:b:pD:l:rs:T:em:G',
479 mode='list', list_all=1)
465 mode='list', list_all=1)
480 if "m" in opts:
466 if "m" in opts:
481 modulename = opts["m"][0]
467 modulename = opts["m"][0]
482 modpath = find_mod(modulename)
468 modpath = find_mod(modulename)
483 if modpath is None:
469 if modpath is None:
484 warn('%r is not a valid modulename on sys.path'%modulename)
470 warn('%r is not a valid modulename on sys.path'%modulename)
485 return
471 return
486 arg_lst = [modpath] + arg_lst
472 arg_lst = [modpath] + arg_lst
487 try:
473 try:
488 filename = file_finder(arg_lst[0])
474 filename = file_finder(arg_lst[0])
489 except IndexError:
475 except IndexError:
490 warn('you must provide at least a filename.')
476 warn('you must provide at least a filename.')
491 print '\n%run:\n', oinspect.getdoc(self.run)
477 print '\n%run:\n', oinspect.getdoc(self.run)
492 return
478 return
493 except IOError as e:
479 except IOError as e:
494 try:
480 try:
495 msg = str(e)
481 msg = str(e)
496 except UnicodeError:
482 except UnicodeError:
497 msg = e.message
483 msg = e.message
498 error(msg)
484 error(msg)
499 return
485 return
500
486
501 if filename.lower().endswith('.ipy'):
487 if filename.lower().endswith('.ipy'):
502 self.shell.safe_execfile_ipy(filename)
488 self.shell.safe_execfile_ipy(filename)
503 return
489 return
504
490
505 # Control the response to exit() calls made by the script being run
491 # Control the response to exit() calls made by the script being run
506 exit_ignore = 'e' in opts
492 exit_ignore = 'e' in opts
507
493
508 # Make sure that the running script gets a proper sys.argv as if it
494 # Make sure that the running script gets a proper sys.argv as if it
509 # were run from a system shell.
495 # were run from a system shell.
510 save_argv = sys.argv # save it for later restoring
496 save_argv = sys.argv # save it for later restoring
511
497
512 if 'G' in opts:
498 if 'G' in opts:
513 args = arg_lst[1:]
499 args = arg_lst[1:]
514 else:
500 else:
515 # tilde and glob expansion
501 # tilde and glob expansion
516 args = globlist(map(os.path.expanduser, arg_lst[1:]))
502 args = globlist(map(os.path.expanduser, arg_lst[1:]))
517
503
518 sys.argv = [filename] + args # put in the proper filename
504 sys.argv = [filename] + args # put in the proper filename
519 # protect sys.argv from potential unicode strings on Python 2:
505 # protect sys.argv from potential unicode strings on Python 2:
520 if not py3compat.PY3:
506 if not py3compat.PY3:
521 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
507 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
522
508
523 if 'i' in opts:
509 if 'i' in opts:
524 # Run in user's interactive namespace
510 # Run in user's interactive namespace
525 prog_ns = self.shell.user_ns
511 prog_ns = self.shell.user_ns
526 __name__save = self.shell.user_ns['__name__']
512 __name__save = self.shell.user_ns['__name__']
527 prog_ns['__name__'] = '__main__'
513 prog_ns['__name__'] = '__main__'
528 main_mod = self.shell.new_main_mod(prog_ns)
514 main_mod = self.shell.new_main_mod(prog_ns)
529 else:
515 else:
530 # Run in a fresh, empty namespace
516 # Run in a fresh, empty namespace
531 if 'n' in opts:
517 if 'n' in opts:
532 name = os.path.splitext(os.path.basename(filename))[0]
518 name = os.path.splitext(os.path.basename(filename))[0]
533 else:
519 else:
534 name = '__main__'
520 name = '__main__'
535
521
536 main_mod = self.shell.new_main_mod()
522 main_mod = self.shell.new_main_mod()
537 prog_ns = main_mod.__dict__
523 prog_ns = main_mod.__dict__
538 prog_ns['__name__'] = name
524 prog_ns['__name__'] = name
539
525
540 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
526 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
541 # set the __file__ global in the script's namespace
527 # set the __file__ global in the script's namespace
542 prog_ns['__file__'] = filename
528 prog_ns['__file__'] = filename
543
529
544 # pickle fix. See interactiveshell for an explanation. But we need to
530 # pickle fix. See interactiveshell for an explanation. But we need to
545 # make sure that, if we overwrite __main__, we replace it at the end
531 # make sure that, if we overwrite __main__, we replace it at the end
546 main_mod_name = prog_ns['__name__']
532 main_mod_name = prog_ns['__name__']
547
533
548 if main_mod_name == '__main__':
534 if main_mod_name == '__main__':
549 restore_main = sys.modules['__main__']
535 restore_main = sys.modules['__main__']
550 else:
536 else:
551 restore_main = False
537 restore_main = False
552
538
553 # This needs to be undone at the end to prevent holding references to
539 # This needs to be undone at the end to prevent holding references to
554 # every single object ever created.
540 # every single object ever created.
555 sys.modules[main_mod_name] = main_mod
541 sys.modules[main_mod_name] = main_mod
556
542
557 try:
543 try:
558 stats = None
544 stats = None
559 with self.shell.readline_no_record:
545 with self.shell.readline_no_record:
560 if 'p' in opts:
546 if 'p' in opts:
561 stats = self.prun('', None, False, opts, arg_lst, prog_ns)
547 stats = self.prun('', None, False, opts, arg_lst, prog_ns)
562 else:
548 else:
563 if 'd' in opts:
549 if 'd' in opts:
564 deb = debugger.Pdb(self.shell.colors)
550 deb = debugger.Pdb(self.shell.colors)
565 # reset Breakpoint state, which is moronically kept
551 # reset Breakpoint state, which is moronically kept
566 # in a class
552 # in a class
567 bdb.Breakpoint.next = 1
553 bdb.Breakpoint.next = 1
568 bdb.Breakpoint.bplist = {}
554 bdb.Breakpoint.bplist = {}
569 bdb.Breakpoint.bpbynumber = [None]
555 bdb.Breakpoint.bpbynumber = [None]
570 # Set an initial breakpoint to stop execution
556 # Set an initial breakpoint to stop execution
571 maxtries = 10
557 maxtries = 10
572 bp = int(opts.get('b', [1])[0])
558 bp = int(opts.get('b', [1])[0])
573 checkline = deb.checkline(filename, bp)
559 checkline = deb.checkline(filename, bp)
574 if not checkline:
560 if not checkline:
575 for bp in range(bp + 1, bp + maxtries + 1):
561 for bp in range(bp + 1, bp + maxtries + 1):
576 if deb.checkline(filename, bp):
562 if deb.checkline(filename, bp):
577 break
563 break
578 else:
564 else:
579 msg = ("\nI failed to find a valid line to set "
565 msg = ("\nI failed to find a valid line to set "
580 "a breakpoint\n"
566 "a breakpoint\n"
581 "after trying up to line: %s.\n"
567 "after trying up to line: %s.\n"
582 "Please set a valid breakpoint manually "
568 "Please set a valid breakpoint manually "
583 "with the -b option." % bp)
569 "with the -b option." % bp)
584 error(msg)
570 error(msg)
585 return
571 return
586 # if we find a good linenumber, set the breakpoint
572 # if we find a good linenumber, set the breakpoint
587 deb.do_break('%s:%s' % (filename, bp))
573 deb.do_break('%s:%s' % (filename, bp))
588 # Start file run
574 # Start file run
589 print "NOTE: Enter 'c' at the",
575 print "NOTE: Enter 'c' at the",
590 print "%s prompt to start your script." % deb.prompt
576 print "%s prompt to start your script." % deb.prompt
591 ns = {'execfile': py3compat.execfile, 'prog_ns': prog_ns}
577 ns = {'execfile': py3compat.execfile, 'prog_ns': prog_ns}
592 try:
578 try:
593 deb.run('execfile("%s", prog_ns)' % filename, ns)
579 deb.run('execfile("%s", prog_ns)' % filename, ns)
594
580
595 except:
581 except:
596 etype, value, tb = sys.exc_info()
582 etype, value, tb = sys.exc_info()
597 # Skip three frames in the traceback: the %run one,
583 # Skip three frames in the traceback: the %run one,
598 # one inside bdb.py, and the command-line typed by the
584 # one inside bdb.py, and the command-line typed by the
599 # user (run by exec in pdb itself).
585 # user (run by exec in pdb itself).
600 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
586 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
601 else:
587 else:
602 if runner is None:
588 if runner is None:
603 runner = self.default_runner
589 runner = self.default_runner
604 if runner is None:
590 if runner is None:
605 runner = self.shell.safe_execfile
591 runner = self.shell.safe_execfile
606 if 't' in opts:
592 if 't' in opts:
607 # timed execution
593 # timed execution
608 try:
594 try:
609 nruns = int(opts['N'][0])
595 nruns = int(opts['N'][0])
610 if nruns < 1:
596 if nruns < 1:
611 error('Number of runs must be >=1')
597 error('Number of runs must be >=1')
612 return
598 return
613 except (KeyError):
599 except (KeyError):
614 nruns = 1
600 nruns = 1
615 twall0 = time.time()
601 twall0 = time.time()
616 if nruns == 1:
602 if nruns == 1:
617 t0 = clock2()
603 t0 = clock2()
618 runner(filename, prog_ns, prog_ns,
604 runner(filename, prog_ns, prog_ns,
619 exit_ignore=exit_ignore)
605 exit_ignore=exit_ignore)
620 t1 = clock2()
606 t1 = clock2()
621 t_usr = t1[0] - t0[0]
607 t_usr = t1[0] - t0[0]
622 t_sys = t1[1] - t0[1]
608 t_sys = t1[1] - t0[1]
623 print "\nIPython CPU timings (estimated):"
609 print "\nIPython CPU timings (estimated):"
624 print " User : %10.2f s." % t_usr
610 print " User : %10.2f s." % t_usr
625 print " System : %10.2f s." % t_sys
611 print " System : %10.2f s." % t_sys
626 else:
612 else:
627 runs = range(nruns)
613 runs = range(nruns)
628 t0 = clock2()
614 t0 = clock2()
629 for nr in runs:
615 for nr in runs:
630 runner(filename, prog_ns, prog_ns,
616 runner(filename, prog_ns, prog_ns,
631 exit_ignore=exit_ignore)
617 exit_ignore=exit_ignore)
632 t1 = clock2()
618 t1 = clock2()
633 t_usr = t1[0] - t0[0]
619 t_usr = t1[0] - t0[0]
634 t_sys = t1[1] - t0[1]
620 t_sys = t1[1] - t0[1]
635 print "\nIPython CPU timings (estimated):"
621 print "\nIPython CPU timings (estimated):"
636 print "Total runs performed:", nruns
622 print "Total runs performed:", nruns
637 print " Times : %10.2f %10.2f" % ('Total', 'Per run')
623 print " Times : %10.2f %10.2f" % ('Total', 'Per run')
638 print " User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)
624 print " User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)
639 print " System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)
625 print " System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)
640 twall1 = time.time()
626 twall1 = time.time()
641 print "Wall time: %10.2f s." % (twall1 - twall0)
627 print "Wall time: %10.2f s." % (twall1 - twall0)
642
628
643 else:
629 else:
644 # regular execution
630 # regular execution
645 runner(filename, prog_ns, prog_ns, exit_ignore=exit_ignore)
631 runner(filename, prog_ns, prog_ns, exit_ignore=exit_ignore)
646
632
647 if 'i' in opts:
633 if 'i' in opts:
648 self.shell.user_ns['__name__'] = __name__save
634 self.shell.user_ns['__name__'] = __name__save
649 else:
635 else:
650 # The shell MUST hold a reference to prog_ns so after %run
636 # The shell MUST hold a reference to prog_ns so after %run
651 # exits, the python deletion mechanism doesn't zero it out
637 # exits, the python deletion mechanism doesn't zero it out
652 # (leaving dangling references).
638 # (leaving dangling references).
653 self.shell.cache_main_mod(prog_ns, filename)
639 self.shell.cache_main_mod(prog_ns, filename)
654 # update IPython interactive namespace
640 # update IPython interactive namespace
655
641
656 # Some forms of read errors on the file may mean the
642 # Some forms of read errors on the file may mean the
657 # __name__ key was never set; using pop we don't have to
643 # __name__ key was never set; using pop we don't have to
658 # worry about a possible KeyError.
644 # worry about a possible KeyError.
659 prog_ns.pop('__name__', None)
645 prog_ns.pop('__name__', None)
660
646
661 self.shell.user_ns.update(prog_ns)
647 self.shell.user_ns.update(prog_ns)
662 finally:
648 finally:
663 # It's a bit of a mystery why, but __builtins__ can change from
649 # It's a bit of a mystery why, but __builtins__ can change from
664 # being a module to becoming a dict missing some key data after
650 # being a module to becoming a dict missing some key data after
665 # %run. As best I can see, this is NOT something IPython is doing
651 # %run. As best I can see, this is NOT something IPython is doing
666 # at all, and similar problems have been reported before:
652 # at all, and similar problems have been reported before:
667 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
653 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
668 # Since this seems to be done by the interpreter itself, the best
654 # Since this seems to be done by the interpreter itself, the best
669 # we can do is to at least restore __builtins__ for the user on
655 # we can do is to at least restore __builtins__ for the user on
670 # exit.
656 # exit.
671 self.shell.user_ns['__builtins__'] = builtin_mod
657 self.shell.user_ns['__builtins__'] = builtin_mod
672
658
673 # Ensure key global structures are restored
659 # Ensure key global structures are restored
674 sys.argv = save_argv
660 sys.argv = save_argv
675 if restore_main:
661 if restore_main:
676 sys.modules['__main__'] = restore_main
662 sys.modules['__main__'] = restore_main
677 else:
663 else:
678 # Remove from sys.modules the reference to main_mod we'd
664 # Remove from sys.modules the reference to main_mod we'd
679 # added. Otherwise it will trap references to objects
665 # added. Otherwise it will trap references to objects
680 # contained therein.
666 # contained therein.
681 del sys.modules[main_mod_name]
667 del sys.modules[main_mod_name]
682
668
683 return stats
669 return stats
684
670
685 @skip_doctest
671 @skip_doctest
686 @line_cell_magic
672 @line_cell_magic
687 def timeit(self, line='', cell=None):
673 def timeit(self, line='', cell=None):
688 """Time execution of a Python statement or expression
674 """Time execution of a Python statement or expression
689
675
690 Usage, in line mode:
676 Usage, in line mode:
691 %timeit [-n<N> -r<R> [-t|-c]] statement
677 %timeit [-n<N> -r<R> [-t|-c]] statement
692 or in cell mode:
678 or in cell mode:
693 %%timeit [-n<N> -r<R> [-t|-c]] setup_code
679 %%timeit [-n<N> -r<R> [-t|-c]] setup_code
694 code
680 code
695 code...
681 code...
696
682
697 Time execution of a Python statement or expression using the timeit
683 Time execution of a Python statement or expression using the timeit
698 module. This function can be used both as a line and cell magic:
684 module. This function can be used both as a line and cell magic:
699
685
700 - In line mode you can time a single-line statement (though multiple
686 - In line mode you can time a single-line statement (though multiple
701 ones can be chained with using semicolons).
687 ones can be chained with using semicolons).
702
688
703 - In cell mode, the statement in the first line is used as setup code
689 - In cell mode, the statement in the first line is used as setup code
704 (executed but not timed) and the body of the cell is timed. The cell
690 (executed but not timed) and the body of the cell is timed. The cell
705 body has access to any variables created in the setup code.
691 body has access to any variables created in the setup code.
706
692
707 Options:
693 Options:
708 -n<N>: execute the given statement <N> times in a loop. If this value
694 -n<N>: execute the given statement <N> times in a loop. If this value
709 is not given, a fitting value is chosen.
695 is not given, a fitting value is chosen.
710
696
711 -r<R>: repeat the loop iteration <R> times and take the best result.
697 -r<R>: repeat the loop iteration <R> times and take the best result.
712 Default: 3
698 Default: 3
713
699
714 -t: use time.time to measure the time, which is the default on Unix.
700 -t: use time.time to measure the time, which is the default on Unix.
715 This function measures wall time.
701 This function measures wall time.
716
702
717 -c: use time.clock to measure the time, which is the default on
703 -c: use time.clock to measure the time, which is the default on
718 Windows and measures wall time. On Unix, resource.getrusage is used
704 Windows and measures wall time. On Unix, resource.getrusage is used
719 instead and returns the CPU user time.
705 instead and returns the CPU user time.
720
706
721 -p<P>: use a precision of <P> digits to display the timing result.
707 -p<P>: use a precision of <P> digits to display the timing result.
722 Default: 3
708 Default: 3
723
709
724
710
725 Examples
711 Examples
726 --------
712 --------
727 ::
713 ::
728
714
729 In [1]: %timeit pass
715 In [1]: %timeit pass
730 10000000 loops, best of 3: 53.3 ns per loop
716 10000000 loops, best of 3: 53.3 ns per loop
731
717
732 In [2]: u = None
718 In [2]: u = None
733
719
734 In [3]: %timeit u is None
720 In [3]: %timeit u is None
735 10000000 loops, best of 3: 184 ns per loop
721 10000000 loops, best of 3: 184 ns per loop
736
722
737 In [4]: %timeit -r 4 u == None
723 In [4]: %timeit -r 4 u == None
738 1000000 loops, best of 4: 242 ns per loop
724 1000000 loops, best of 4: 242 ns per loop
739
725
740 In [5]: import time
726 In [5]: import time
741
727
742 In [6]: %timeit -n1 time.sleep(2)
728 In [6]: %timeit -n1 time.sleep(2)
743 1 loops, best of 3: 2 s per loop
729 1 loops, best of 3: 2 s per loop
744
730
745
731
746 The times reported by %timeit will be slightly higher than those
732 The times reported by %timeit will be slightly higher than those
747 reported by the timeit.py script when variables are accessed. This is
733 reported by the timeit.py script when variables are accessed. This is
748 due to the fact that %timeit executes the statement in the namespace
734 due to the fact that %timeit executes the statement in the namespace
749 of the shell, compared with timeit.py, which uses a single setup
735 of the shell, compared with timeit.py, which uses a single setup
750 statement to import function or create variables. Generally, the bias
736 statement to import function or create variables. Generally, the bias
751 does not matter as long as results from timeit.py are not mixed with
737 does not matter as long as results from timeit.py are not mixed with
752 those from %timeit."""
738 those from %timeit."""
753
739
754 import timeit
740 import timeit
755 import math
741 import math
756
742
757 # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
743 # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
758 # certain terminals. Until we figure out a robust way of
744 # certain terminals. Until we figure out a robust way of
759 # auto-detecting if the terminal can deal with it, use plain 'us' for
745 # auto-detecting if the terminal can deal with it, use plain 'us' for
760 # microseconds. I am really NOT happy about disabling the proper
746 # microseconds. I am really NOT happy about disabling the proper
761 # 'micro' prefix, but crashing is worse... If anyone knows what the
747 # 'micro' prefix, but crashing is worse... If anyone knows what the
762 # right solution for this is, I'm all ears...
748 # right solution for this is, I'm all ears...
763 #
749 #
764 # Note: using
750 # Note: using
765 #
751 #
766 # s = u'\xb5'
752 # s = u'\xb5'
767 # s.encode(sys.getdefaultencoding())
753 # s.encode(sys.getdefaultencoding())
768 #
754 #
769 # is not sufficient, as I've seen terminals where that fails but
755 # is not sufficient, as I've seen terminals where that fails but
770 # print s
756 # print s
771 #
757 #
772 # succeeds
758 # succeeds
773 #
759 #
774 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
760 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
775
761
776 #units = [u"s", u"ms",u'\xb5',"ns"]
762 #units = [u"s", u"ms",u'\xb5',"ns"]
777 units = [u"s", u"ms",u'us',"ns"]
763 units = [u"s", u"ms",u'us',"ns"]
778
764
779 scaling = [1, 1e3, 1e6, 1e9]
765 scaling = [1, 1e3, 1e6, 1e9]
780
766
781 opts, stmt = self.parse_options(line,'n:r:tcp:',
767 opts, stmt = self.parse_options(line,'n:r:tcp:',
782 posix=False, strict=False)
768 posix=False, strict=False)
783 if stmt == "" and cell is None:
769 if stmt == "" and cell is None:
784 return
770 return
785 timefunc = timeit.default_timer
771 timefunc = timeit.default_timer
786 number = int(getattr(opts, "n", 0))
772 number = int(getattr(opts, "n", 0))
787 repeat = int(getattr(opts, "r", timeit.default_repeat))
773 repeat = int(getattr(opts, "r", timeit.default_repeat))
788 precision = int(getattr(opts, "p", 3))
774 precision = int(getattr(opts, "p", 3))
789 if hasattr(opts, "t"):
775 if hasattr(opts, "t"):
790 timefunc = time.time
776 timefunc = time.time
791 if hasattr(opts, "c"):
777 if hasattr(opts, "c"):
792 timefunc = clock
778 timefunc = clock
793
779
794 timer = timeit.Timer(timer=timefunc)
780 timer = timeit.Timer(timer=timefunc)
795 # this code has tight coupling to the inner workings of timeit.Timer,
781 # this code has tight coupling to the inner workings of timeit.Timer,
796 # but is there a better way to achieve that the code stmt has access
782 # but is there a better way to achieve that the code stmt has access
797 # to the shell namespace?
783 # to the shell namespace?
798 transform = self.shell.input_splitter.transform_cell
784 transform = self.shell.input_splitter.transform_cell
799 if cell is None:
785 if cell is None:
800 # called as line magic
786 # called as line magic
801 setup = 'pass'
787 setup = 'pass'
802 stmt = timeit.reindent(transform(stmt), 8)
788 stmt = timeit.reindent(transform(stmt), 8)
803 else:
789 else:
804 setup = timeit.reindent(transform(stmt), 4)
790 setup = timeit.reindent(transform(stmt), 4)
805 stmt = timeit.reindent(transform(cell), 8)
791 stmt = timeit.reindent(transform(cell), 8)
806
792
807 # From Python 3.3, this template uses new-style string formatting.
793 # From Python 3.3, this template uses new-style string formatting.
808 if sys.version_info >= (3, 3):
794 if sys.version_info >= (3, 3):
809 src = timeit.template.format(stmt=stmt, setup=setup)
795 src = timeit.template.format(stmt=stmt, setup=setup)
810 else:
796 else:
811 src = timeit.template % dict(stmt=stmt, setup=setup)
797 src = timeit.template % dict(stmt=stmt, setup=setup)
812
798
813 # Track compilation time so it can be reported if too long
799 # Track compilation time so it can be reported if too long
814 # Minimum time above which compilation time will be reported
800 # Minimum time above which compilation time will be reported
815 tc_min = 0.1
801 tc_min = 0.1
816
802
817 t0 = clock()
803 t0 = clock()
818 code = compile(src, "<magic-timeit>", "exec")
804 code = compile(src, "<magic-timeit>", "exec")
819 tc = clock()-t0
805 tc = clock()-t0
820
806
821 ns = {}
807 ns = {}
822 exec code in self.shell.user_ns, ns
808 exec code in self.shell.user_ns, ns
823 timer.inner = ns["inner"]
809 timer.inner = ns["inner"]
824
810
825 if number == 0:
811 if number == 0:
826 # determine number so that 0.2 <= total time < 2.0
812 # determine number so that 0.2 <= total time < 2.0
827 number = 1
813 number = 1
828 for i in range(1, 10):
814 for i in range(1, 10):
829 if timer.timeit(number) >= 0.2:
815 if timer.timeit(number) >= 0.2:
830 break
816 break
831 number *= 10
817 number *= 10
832
818
833 best = min(timer.repeat(repeat, number)) / number
819 best = min(timer.repeat(repeat, number)) / number
834
820
835 if best > 0.0 and best < 1000.0:
821 if best > 0.0 and best < 1000.0:
836 order = min(-int(math.floor(math.log10(best)) // 3), 3)
822 order = min(-int(math.floor(math.log10(best)) // 3), 3)
837 elif best >= 1000.0:
823 elif best >= 1000.0:
838 order = 0
824 order = 0
839 else:
825 else:
840 order = 3
826 order = 3
841 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
827 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
842 precision,
828 precision,
843 best * scaling[order],
829 best * scaling[order],
844 units[order])
830 units[order])
845 if tc > tc_min:
831 if tc > tc_min:
846 print "Compiler time: %.2f s" % tc
832 print "Compiler time: %.2f s" % tc
847
833
848 @skip_doctest
834 @skip_doctest
849 @needs_local_scope
835 @needs_local_scope
850 @line_magic
836 @line_magic
851 def time(self,parameter_s, user_locals):
837 def time(self,parameter_s, user_locals):
852 """Time execution of a Python statement or expression.
838 """Time execution of a Python statement or expression.
853
839
854 The CPU and wall clock times are printed, and the value of the
840 The CPU and wall clock times are printed, and the value of the
855 expression (if any) is returned. Note that under Win32, system time
841 expression (if any) is returned. Note that under Win32, system time
856 is always reported as 0, since it can not be measured.
842 is always reported as 0, since it can not be measured.
857
843
858 This function provides very basic timing functionality. In Python
844 This function provides very basic timing functionality. In Python
859 2.3, the timeit module offers more control and sophistication, so this
845 2.3, the timeit module offers more control and sophistication, so this
860 could be rewritten to use it (patches welcome).
846 could be rewritten to use it (patches welcome).
861
847
862 Examples
848 Examples
863 --------
849 --------
864 ::
850 ::
865
851
866 In [1]: time 2**128
852 In [1]: time 2**128
867 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
853 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
868 Wall time: 0.00
854 Wall time: 0.00
869 Out[1]: 340282366920938463463374607431768211456L
855 Out[1]: 340282366920938463463374607431768211456L
870
856
871 In [2]: n = 1000000
857 In [2]: n = 1000000
872
858
873 In [3]: time sum(range(n))
859 In [3]: time sum(range(n))
874 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
860 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
875 Wall time: 1.37
861 Wall time: 1.37
876 Out[3]: 499999500000L
862 Out[3]: 499999500000L
877
863
878 In [4]: time print 'hello world'
864 In [4]: time print 'hello world'
879 hello world
865 hello world
880 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
866 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
881 Wall time: 0.00
867 Wall time: 0.00
882
868
883 Note that the time needed by Python to compile the given expression
869 Note that the time needed by Python to compile the given expression
884 will be reported if it is more than 0.1s. In this example, the
870 will be reported if it is more than 0.1s. In this example, the
885 actual exponentiation is done by Python at compilation time, so while
871 actual exponentiation is done by Python at compilation time, so while
886 the expression can take a noticeable amount of time to compute, that
872 the expression can take a noticeable amount of time to compute, that
887 time is purely due to the compilation:
873 time is purely due to the compilation:
888
874
889 In [5]: time 3**9999;
875 In [5]: time 3**9999;
890 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
876 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
891 Wall time: 0.00 s
877 Wall time: 0.00 s
892
878
893 In [6]: time 3**999999;
879 In [6]: time 3**999999;
894 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
880 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
895 Wall time: 0.00 s
881 Wall time: 0.00 s
896 Compiler : 0.78 s
882 Compiler : 0.78 s
897 """
883 """
898
884
899 # fail immediately if the given expression can't be compiled
885 # fail immediately if the given expression can't be compiled
900
886
901 expr = self.shell.prefilter(parameter_s,False)
887 expr = self.shell.prefilter(parameter_s,False)
902
888
903 # Minimum time above which compilation time will be reported
889 # Minimum time above which compilation time will be reported
904 tc_min = 0.1
890 tc_min = 0.1
905
891
906 try:
892 try:
907 mode = 'eval'
893 mode = 'eval'
908 t0 = clock()
894 t0 = clock()
909 code = compile(expr,'<timed eval>',mode)
895 code = compile(expr,'<timed eval>',mode)
910 tc = clock()-t0
896 tc = clock()-t0
911 except SyntaxError:
897 except SyntaxError:
912 mode = 'exec'
898 mode = 'exec'
913 t0 = clock()
899 t0 = clock()
914 code = compile(expr,'<timed exec>',mode)
900 code = compile(expr,'<timed exec>',mode)
915 tc = clock()-t0
901 tc = clock()-t0
916 # skew measurement as little as possible
902 # skew measurement as little as possible
917 glob = self.shell.user_ns
903 glob = self.shell.user_ns
918 wtime = time.time
904 wtime = time.time
919 # time execution
905 # time execution
920 wall_st = wtime()
906 wall_st = wtime()
921 if mode=='eval':
907 if mode=='eval':
922 st = clock2()
908 st = clock2()
923 out = eval(code, glob, user_locals)
909 out = eval(code, glob, user_locals)
924 end = clock2()
910 end = clock2()
925 else:
911 else:
926 st = clock2()
912 st = clock2()
927 exec code in glob, user_locals
913 exec code in glob, user_locals
928 end = clock2()
914 end = clock2()
929 out = None
915 out = None
930 wall_end = wtime()
916 wall_end = wtime()
931 # Compute actual times and report
917 # Compute actual times and report
932 wall_time = wall_end-wall_st
918 wall_time = wall_end-wall_st
933 cpu_user = end[0]-st[0]
919 cpu_user = end[0]-st[0]
934 cpu_sys = end[1]-st[1]
920 cpu_sys = end[1]-st[1]
935 cpu_tot = cpu_user+cpu_sys
921 cpu_tot = cpu_user+cpu_sys
936 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
922 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
937 (cpu_user,cpu_sys,cpu_tot)
923 (cpu_user,cpu_sys,cpu_tot)
938 print "Wall time: %.2f s" % wall_time
924 print "Wall time: %.2f s" % wall_time
939 if tc > tc_min:
925 if tc > tc_min:
940 print "Compiler : %.2f s" % tc
926 print "Compiler : %.2f s" % tc
941 return out
927 return out
942
928
943 @skip_doctest
929 @skip_doctest
944 @line_magic
930 @line_magic
945 def macro(self, parameter_s=''):
931 def macro(self, parameter_s=''):
946 """Define a macro for future re-execution. It accepts ranges of history,
932 """Define a macro for future re-execution. It accepts ranges of history,
947 filenames or string objects.
933 filenames or string objects.
948
934
949 Usage:\\
935 Usage:\\
950 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
936 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
951
937
952 Options:
938 Options:
953
939
954 -r: use 'raw' input. By default, the 'processed' history is used,
940 -r: use 'raw' input. By default, the 'processed' history is used,
955 so that magics are loaded in their transformed version to valid
941 so that magics are loaded in their transformed version to valid
956 Python. If this option is given, the raw input as typed as the
942 Python. If this option is given, the raw input as typed as the
957 command line is used instead.
943 command line is used instead.
958
944
959 This will define a global variable called `name` which is a string
945 This will define a global variable called `name` which is a string
960 made of joining the slices and lines you specify (n1,n2,... numbers
946 made of joining the slices and lines you specify (n1,n2,... numbers
961 above) from your input history into a single string. This variable
947 above) from your input history into a single string. This variable
962 acts like an automatic function which re-executes those lines as if
948 acts like an automatic function which re-executes those lines as if
963 you had typed them. You just type 'name' at the prompt and the code
949 you had typed them. You just type 'name' at the prompt and the code
964 executes.
950 executes.
965
951
966 The syntax for indicating input ranges is described in %history.
952 The syntax for indicating input ranges is described in %history.
967
953
968 Note: as a 'hidden' feature, you can also use traditional python slice
954 Note: as a 'hidden' feature, you can also use traditional python slice
969 notation, where N:M means numbers N through M-1.
955 notation, where N:M means numbers N through M-1.
970
956
971 For example, if your history contains (%hist prints it)::
957 For example, if your history contains (%hist prints it)::
972
958
973 44: x=1
959 44: x=1
974 45: y=3
960 45: y=3
975 46: z=x+y
961 46: z=x+y
976 47: print x
962 47: print x
977 48: a=5
963 48: a=5
978 49: print 'x',x,'y',y
964 49: print 'x',x,'y',y
979
965
980 you can create a macro with lines 44 through 47 (included) and line 49
966 you can create a macro with lines 44 through 47 (included) and line 49
981 called my_macro with::
967 called my_macro with::
982
968
983 In [55]: %macro my_macro 44-47 49
969 In [55]: %macro my_macro 44-47 49
984
970
985 Now, typing `my_macro` (without quotes) will re-execute all this code
971 Now, typing `my_macro` (without quotes) will re-execute all this code
986 in one pass.
972 in one pass.
987
973
988 You don't need to give the line-numbers in order, and any given line
974 You don't need to give the line-numbers in order, and any given line
989 number can appear multiple times. You can assemble macros with any
975 number can appear multiple times. You can assemble macros with any
990 lines from your input history in any order.
976 lines from your input history in any order.
991
977
992 The macro is a simple object which holds its value in an attribute,
978 The macro is a simple object which holds its value in an attribute,
993 but IPython's display system checks for macros and executes them as
979 but IPython's display system checks for macros and executes them as
994 code instead of printing them when you type their name.
980 code instead of printing them when you type their name.
995
981
996 You can view a macro's contents by explicitly printing it with::
982 You can view a macro's contents by explicitly printing it with::
997
983
998 print macro_name
984 print macro_name
999
985
1000 """
986 """
1001 opts,args = self.parse_options(parameter_s,'r',mode='list')
987 opts,args = self.parse_options(parameter_s,'r',mode='list')
1002 if not args: # List existing macros
988 if not args: # List existing macros
1003 return sorted(k for k,v in self.shell.user_ns.iteritems() if\
989 return sorted(k for k,v in self.shell.user_ns.iteritems() if\
1004 isinstance(v, Macro))
990 isinstance(v, Macro))
1005 if len(args) == 1:
991 if len(args) == 1:
1006 raise UsageError(
992 raise UsageError(
1007 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
993 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1008 name, codefrom = args[0], " ".join(args[1:])
994 name, codefrom = args[0], " ".join(args[1:])
1009
995
1010 #print 'rng',ranges # dbg
996 #print 'rng',ranges # dbg
1011 try:
997 try:
1012 lines = self.shell.find_user_code(codefrom, 'r' in opts)
998 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1013 except (ValueError, TypeError) as e:
999 except (ValueError, TypeError) as e:
1014 print e.args[0]
1000 print e.args[0]
1015 return
1001 return
1016 macro = Macro(lines)
1002 macro = Macro(lines)
1017 self.shell.define_macro(name, macro)
1003 self.shell.define_macro(name, macro)
1018 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
1004 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
1019 print '=== Macro contents: ==='
1005 print '=== Macro contents: ==='
1020 print macro,
1006 print macro,
1021
1007
1022 @magic_arguments.magic_arguments()
1008 @magic_arguments.magic_arguments()
1023 @magic_arguments.argument('output', type=str, default='', nargs='?',
1009 @magic_arguments.argument('output', type=str, default='', nargs='?',
1024 help="""The name of the variable in which to store output.
1010 help="""The name of the variable in which to store output.
1025 This is a utils.io.CapturedIO object with stdout/err attributes
1011 This is a utils.io.CapturedIO object with stdout/err attributes
1026 for the text of the captured output.
1012 for the text of the captured output.
1027
1013
1028 CapturedOutput also has a show() method for displaying the output,
1014 CapturedOutput also has a show() method for displaying the output,
1029 and __call__ as well, so you can use that to quickly display the
1015 and __call__ as well, so you can use that to quickly display the
1030 output.
1016 output.
1031
1017
1032 If unspecified, captured output is discarded.
1018 If unspecified, captured output is discarded.
1033 """
1019 """
1034 )
1020 )
1035 @magic_arguments.argument('--no-stderr', action="store_true",
1021 @magic_arguments.argument('--no-stderr', action="store_true",
1036 help="""Don't capture stderr."""
1022 help="""Don't capture stderr."""
1037 )
1023 )
1038 @magic_arguments.argument('--no-stdout', action="store_true",
1024 @magic_arguments.argument('--no-stdout', action="store_true",
1039 help="""Don't capture stdout."""
1025 help="""Don't capture stdout."""
1040 )
1026 )
1041 @cell_magic
1027 @cell_magic
1042 def capture(self, line, cell):
1028 def capture(self, line, cell):
1043 """run the cell, capturing stdout/err"""
1029 """run the cell, capturing stdout/err"""
1044 args = magic_arguments.parse_argstring(self.capture, line)
1030 args = magic_arguments.parse_argstring(self.capture, line)
1045 out = not args.no_stdout
1031 out = not args.no_stdout
1046 err = not args.no_stderr
1032 err = not args.no_stderr
1047 with capture_output(out, err) as io:
1033 with capture_output(out, err) as io:
1048 self.shell.run_cell(cell)
1034 self.shell.run_cell(cell)
1049 if args.output:
1035 if args.output:
1050 self.shell.user_ns[args.output] = io
1036 self.shell.user_ns[args.output] = io
@@ -1,776 +1,744 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions.
2 """Tests for various magic functions.
3
3
4 Needs to be run by nose (to make ipython session available).
4 Needs to be run by nose (to make ipython session available).
5 """
5 """
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Imports
9 # Imports
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import io
12 import io
13 import os
13 import os
14 import sys
14 import sys
15 from StringIO import StringIO
15 from StringIO import StringIO
16 from unittest import TestCase
16 from unittest import TestCase
17
17
18 try:
18 try:
19 from importlib import invalidate_caches # Required from Python 3.3
19 from importlib import invalidate_caches # Required from Python 3.3
20 except ImportError:
20 except ImportError:
21 def invalidate_caches():
21 def invalidate_caches():
22 pass
22 pass
23
23
24 import nose.tools as nt
24 import nose.tools as nt
25
25
26 from IPython.core import magic
26 from IPython.core import magic
27 from IPython.core.magic import (Magics, magics_class, line_magic,
27 from IPython.core.magic import (Magics, magics_class, line_magic,
28 cell_magic, line_cell_magic,
28 cell_magic, line_cell_magic,
29 register_line_magic, register_cell_magic,
29 register_line_magic, register_cell_magic,
30 register_line_cell_magic)
30 register_line_cell_magic)
31 from IPython.core.magics import execution, script
31 from IPython.core.magics import execution, script
32 from IPython.core.magics.execution import globlist
33 from IPython.nbformat.v3.tests.nbexamples import nb0
32 from IPython.nbformat.v3.tests.nbexamples import nb0
34 from IPython.nbformat import current
33 from IPython.nbformat import current
35 from IPython.testing import decorators as dec
34 from IPython.testing import decorators as dec
36 from IPython.testing import tools as tt
35 from IPython.testing import tools as tt
37 from IPython.utils import py3compat
36 from IPython.utils import py3compat
38 from IPython.utils.tempdir import TemporaryDirectory
37 from IPython.utils.tempdir import TemporaryDirectory
39 from IPython.utils.process import find_cmd
38 from IPython.utils.process import find_cmd
40
39
41 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
42 # Test functions begin
41 # Test functions begin
43 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
44
43
45 @magic.magics_class
44 @magic.magics_class
46 class DummyMagics(magic.Magics): pass
45 class DummyMagics(magic.Magics): pass
47
46
48 def test_rehashx():
47 def test_rehashx():
49 # clear up everything
48 # clear up everything
50 _ip = get_ipython()
49 _ip = get_ipython()
51 _ip.alias_manager.alias_table.clear()
50 _ip.alias_manager.alias_table.clear()
52 del _ip.db['syscmdlist']
51 del _ip.db['syscmdlist']
53
52
54 _ip.magic('rehashx')
53 _ip.magic('rehashx')
55 # Practically ALL ipython development systems will have more than 10 aliases
54 # Practically ALL ipython development systems will have more than 10 aliases
56
55
57 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
56 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
58 for key, val in _ip.alias_manager.alias_table.iteritems():
57 for key, val in _ip.alias_manager.alias_table.iteritems():
59 # we must strip dots from alias names
58 # we must strip dots from alias names
60 nt.assert_true('.' not in key)
59 nt.assert_true('.' not in key)
61
60
62 # rehashx must fill up syscmdlist
61 # rehashx must fill up syscmdlist
63 scoms = _ip.db['syscmdlist']
62 scoms = _ip.db['syscmdlist']
64 yield (nt.assert_true, len(scoms) > 10)
63 yield (nt.assert_true, len(scoms) > 10)
65
64
66
65
67 def test_magic_parse_options():
66 def test_magic_parse_options():
68 """Test that we don't mangle paths when parsing magic options."""
67 """Test that we don't mangle paths when parsing magic options."""
69 ip = get_ipython()
68 ip = get_ipython()
70 path = 'c:\\x'
69 path = 'c:\\x'
71 m = DummyMagics(ip)
70 m = DummyMagics(ip)
72 opts = m.parse_options('-f %s' % path,'f:')[0]
71 opts = m.parse_options('-f %s' % path,'f:')[0]
73 # argv splitting is os-dependent
72 # argv splitting is os-dependent
74 if os.name == 'posix':
73 if os.name == 'posix':
75 expected = 'c:x'
74 expected = 'c:x'
76 else:
75 else:
77 expected = path
76 expected = path
78 nt.assert_equals(opts['f'], expected)
77 nt.assert_equals(opts['f'], expected)
79
78
80 def test_magic_parse_long_options():
79 def test_magic_parse_long_options():
81 """Magic.parse_options can handle --foo=bar long options"""
80 """Magic.parse_options can handle --foo=bar long options"""
82 ip = get_ipython()
81 ip = get_ipython()
83 m = DummyMagics(ip)
82 m = DummyMagics(ip)
84 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
83 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
85 nt.assert_true('foo' in opts)
84 nt.assert_true('foo' in opts)
86 nt.assert_true('bar' in opts)
85 nt.assert_true('bar' in opts)
87 nt.assert_true(opts['bar'], "bubble")
86 nt.assert_true(opts['bar'], "bubble")
88
87
89
88
90 def test_globlist():
91 """Test glob expansion for %run magic."""
92 filenames_start_with_a = map('a{0}'.format, range(3))
93 filenames_end_with_b = map('{0}b'.format, range(3))
94 filenames = filenames_start_with_a + filenames_end_with_b
95
96 with TemporaryDirectory() as td:
97 save = os.getcwdu()
98 try:
99 os.chdir(td)
100
101 # Create empty files
102 for fname in filenames:
103 open(os.path.join(td, fname), 'w').close()
104
105 def assert_match(patterns, matches):
106 # glob returns unordered list. that's why sorted is required.
107 nt.assert_equals(sorted(globlist(patterns)), sorted(matches))
108
109 assert_match(['*'], filenames)
110 assert_match(['a*'], filenames_start_with_a)
111 assert_match(['*c'], ['*c'])
112 assert_match(['*', 'a*', '*b', '*c'],
113 filenames
114 + filenames_start_with_a
115 + filenames_end_with_b
116 + ['*c'])
117 finally:
118 os.chdir(save)
119
120
121 @dec.skip_without('sqlite3')
89 @dec.skip_without('sqlite3')
122 def doctest_hist_f():
90 def doctest_hist_f():
123 """Test %hist -f with temporary filename.
91 """Test %hist -f with temporary filename.
124
92
125 In [9]: import tempfile
93 In [9]: import tempfile
126
94
127 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
95 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
128
96
129 In [11]: %hist -nl -f $tfile 3
97 In [11]: %hist -nl -f $tfile 3
130
98
131 In [13]: import os; os.unlink(tfile)
99 In [13]: import os; os.unlink(tfile)
132 """
100 """
133
101
134
102
135 @dec.skip_without('sqlite3')
103 @dec.skip_without('sqlite3')
136 def doctest_hist_r():
104 def doctest_hist_r():
137 """Test %hist -r
105 """Test %hist -r
138
106
139 XXX - This test is not recording the output correctly. For some reason, in
107 XXX - This test is not recording the output correctly. For some reason, in
140 testing mode the raw history isn't getting populated. No idea why.
108 testing mode the raw history isn't getting populated. No idea why.
141 Disabling the output checking for now, though at least we do run it.
109 Disabling the output checking for now, though at least we do run it.
142
110
143 In [1]: 'hist' in _ip.lsmagic()
111 In [1]: 'hist' in _ip.lsmagic()
144 Out[1]: True
112 Out[1]: True
145
113
146 In [2]: x=1
114 In [2]: x=1
147
115
148 In [3]: %hist -rl 2
116 In [3]: %hist -rl 2
149 x=1 # random
117 x=1 # random
150 %hist -r 2
118 %hist -r 2
151 """
119 """
152
120
153
121
154 @dec.skip_without('sqlite3')
122 @dec.skip_without('sqlite3')
155 def doctest_hist_op():
123 def doctest_hist_op():
156 """Test %hist -op
124 """Test %hist -op
157
125
158 In [1]: class b(float):
126 In [1]: class b(float):
159 ...: pass
127 ...: pass
160 ...:
128 ...:
161
129
162 In [2]: class s(object):
130 In [2]: class s(object):
163 ...: def __str__(self):
131 ...: def __str__(self):
164 ...: return 's'
132 ...: return 's'
165 ...:
133 ...:
166
134
167 In [3]:
135 In [3]:
168
136
169 In [4]: class r(b):
137 In [4]: class r(b):
170 ...: def __repr__(self):
138 ...: def __repr__(self):
171 ...: return 'r'
139 ...: return 'r'
172 ...:
140 ...:
173
141
174 In [5]: class sr(s,r): pass
142 In [5]: class sr(s,r): pass
175 ...:
143 ...:
176
144
177 In [6]:
145 In [6]:
178
146
179 In [7]: bb=b()
147 In [7]: bb=b()
180
148
181 In [8]: ss=s()
149 In [8]: ss=s()
182
150
183 In [9]: rr=r()
151 In [9]: rr=r()
184
152
185 In [10]: ssrr=sr()
153 In [10]: ssrr=sr()
186
154
187 In [11]: 4.5
155 In [11]: 4.5
188 Out[11]: 4.5
156 Out[11]: 4.5
189
157
190 In [12]: str(ss)
158 In [12]: str(ss)
191 Out[12]: 's'
159 Out[12]: 's'
192
160
193 In [13]:
161 In [13]:
194
162
195 In [14]: %hist -op
163 In [14]: %hist -op
196 >>> class b:
164 >>> class b:
197 ... pass
165 ... pass
198 ...
166 ...
199 >>> class s(b):
167 >>> class s(b):
200 ... def __str__(self):
168 ... def __str__(self):
201 ... return 's'
169 ... return 's'
202 ...
170 ...
203 >>>
171 >>>
204 >>> class r(b):
172 >>> class r(b):
205 ... def __repr__(self):
173 ... def __repr__(self):
206 ... return 'r'
174 ... return 'r'
207 ...
175 ...
208 >>> class sr(s,r): pass
176 >>> class sr(s,r): pass
209 >>>
177 >>>
210 >>> bb=b()
178 >>> bb=b()
211 >>> ss=s()
179 >>> ss=s()
212 >>> rr=r()
180 >>> rr=r()
213 >>> ssrr=sr()
181 >>> ssrr=sr()
214 >>> 4.5
182 >>> 4.5
215 4.5
183 4.5
216 >>> str(ss)
184 >>> str(ss)
217 's'
185 's'
218 >>>
186 >>>
219 """
187 """
220
188
221
189
222 @dec.skip_without('sqlite3')
190 @dec.skip_without('sqlite3')
223 def test_macro():
191 def test_macro():
224 ip = get_ipython()
192 ip = get_ipython()
225 ip.history_manager.reset() # Clear any existing history.
193 ip.history_manager.reset() # Clear any existing history.
226 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
194 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
227 for i, cmd in enumerate(cmds, start=1):
195 for i, cmd in enumerate(cmds, start=1):
228 ip.history_manager.store_inputs(i, cmd)
196 ip.history_manager.store_inputs(i, cmd)
229 ip.magic("macro test 1-3")
197 ip.magic("macro test 1-3")
230 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
198 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
231
199
232 # List macros.
200 # List macros.
233 assert "test" in ip.magic("macro")
201 assert "test" in ip.magic("macro")
234
202
235
203
236 @dec.skip_without('sqlite3')
204 @dec.skip_without('sqlite3')
237 def test_macro_run():
205 def test_macro_run():
238 """Test that we can run a multi-line macro successfully."""
206 """Test that we can run a multi-line macro successfully."""
239 ip = get_ipython()
207 ip = get_ipython()
240 ip.history_manager.reset()
208 ip.history_manager.reset()
241 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
209 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
242 "%macro test 2-3"]
210 "%macro test 2-3"]
243 for cmd in cmds:
211 for cmd in cmds:
244 ip.run_cell(cmd, store_history=True)
212 ip.run_cell(cmd, store_history=True)
245 nt.assert_equal(ip.user_ns["test"].value,
213 nt.assert_equal(ip.user_ns["test"].value,
246 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
214 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
247 with tt.AssertPrints("12"):
215 with tt.AssertPrints("12"):
248 ip.run_cell("test")
216 ip.run_cell("test")
249 with tt.AssertPrints("13"):
217 with tt.AssertPrints("13"):
250 ip.run_cell("test")
218 ip.run_cell("test")
251
219
252
220
253 @dec.skipif_not_numpy
221 @dec.skipif_not_numpy
254 def test_numpy_reset_array_undec():
222 def test_numpy_reset_array_undec():
255 "Test '%reset array' functionality"
223 "Test '%reset array' functionality"
256 _ip.ex('import numpy as np')
224 _ip.ex('import numpy as np')
257 _ip.ex('a = np.empty(2)')
225 _ip.ex('a = np.empty(2)')
258 yield (nt.assert_true, 'a' in _ip.user_ns)
226 yield (nt.assert_true, 'a' in _ip.user_ns)
259 _ip.magic('reset -f array')
227 _ip.magic('reset -f array')
260 yield (nt.assert_false, 'a' in _ip.user_ns)
228 yield (nt.assert_false, 'a' in _ip.user_ns)
261
229
262 def test_reset_out():
230 def test_reset_out():
263 "Test '%reset out' magic"
231 "Test '%reset out' magic"
264 _ip.run_cell("parrot = 'dead'", store_history=True)
232 _ip.run_cell("parrot = 'dead'", store_history=True)
265 # test '%reset -f out', make an Out prompt
233 # test '%reset -f out', make an Out prompt
266 _ip.run_cell("parrot", store_history=True)
234 _ip.run_cell("parrot", store_history=True)
267 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
235 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
268 _ip.magic('reset -f out')
236 _ip.magic('reset -f out')
269 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
237 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
270 nt.assert_true(len(_ip.user_ns['Out']) == 0)
238 nt.assert_true(len(_ip.user_ns['Out']) == 0)
271
239
272 def test_reset_in():
240 def test_reset_in():
273 "Test '%reset in' magic"
241 "Test '%reset in' magic"
274 # test '%reset -f in'
242 # test '%reset -f in'
275 _ip.run_cell("parrot", store_history=True)
243 _ip.run_cell("parrot", store_history=True)
276 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
244 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
277 _ip.magic('%reset -f in')
245 _ip.magic('%reset -f in')
278 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
246 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
279 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
247 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
280
248
281 def test_reset_dhist():
249 def test_reset_dhist():
282 "Test '%reset dhist' magic"
250 "Test '%reset dhist' magic"
283 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
251 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
284 _ip.magic('cd ' + os.path.dirname(nt.__file__))
252 _ip.magic('cd ' + os.path.dirname(nt.__file__))
285 _ip.magic('cd -')
253 _ip.magic('cd -')
286 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
254 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
287 _ip.magic('reset -f dhist')
255 _ip.magic('reset -f dhist')
288 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
256 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
289 _ip.run_cell("_dh = [d for d in tmp]") #restore
257 _ip.run_cell("_dh = [d for d in tmp]") #restore
290
258
291 def test_reset_in_length():
259 def test_reset_in_length():
292 "Test that '%reset in' preserves In[] length"
260 "Test that '%reset in' preserves In[] length"
293 _ip.run_cell("print 'foo'")
261 _ip.run_cell("print 'foo'")
294 _ip.run_cell("reset -f in")
262 _ip.run_cell("reset -f in")
295 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
263 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
296
264
297 def test_time():
265 def test_time():
298 _ip.magic('time None')
266 _ip.magic('time None')
299
267
300 def test_tb_syntaxerror():
268 def test_tb_syntaxerror():
301 """test %tb after a SyntaxError"""
269 """test %tb after a SyntaxError"""
302 ip = get_ipython()
270 ip = get_ipython()
303 ip.run_cell("for")
271 ip.run_cell("for")
304
272
305 # trap and validate stdout
273 # trap and validate stdout
306 save_stdout = sys.stdout
274 save_stdout = sys.stdout
307 try:
275 try:
308 sys.stdout = StringIO()
276 sys.stdout = StringIO()
309 ip.run_cell("%tb")
277 ip.run_cell("%tb")
310 out = sys.stdout.getvalue()
278 out = sys.stdout.getvalue()
311 finally:
279 finally:
312 sys.stdout = save_stdout
280 sys.stdout = save_stdout
313 # trim output, and only check the last line
281 # trim output, and only check the last line
314 last_line = out.rstrip().splitlines()[-1].strip()
282 last_line = out.rstrip().splitlines()[-1].strip()
315 nt.assert_equals(last_line, "SyntaxError: invalid syntax")
283 nt.assert_equals(last_line, "SyntaxError: invalid syntax")
316
284
317
285
318 @py3compat.doctest_refactor_print
286 @py3compat.doctest_refactor_print
319 def doctest_time():
287 def doctest_time():
320 """
288 """
321 In [10]: %time None
289 In [10]: %time None
322 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
290 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
323 Wall time: 0.00 s
291 Wall time: 0.00 s
324
292
325 In [11]: def f(kmjy):
293 In [11]: def f(kmjy):
326 ....: %time print 2*kmjy
294 ....: %time print 2*kmjy
327
295
328 In [12]: f(3)
296 In [12]: f(3)
329 6
297 6
330 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
298 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
331 Wall time: 0.00 s
299 Wall time: 0.00 s
332 """
300 """
333
301
334
302
335 def test_doctest_mode():
303 def test_doctest_mode():
336 "Toggle doctest_mode twice, it should be a no-op and run without error"
304 "Toggle doctest_mode twice, it should be a no-op and run without error"
337 _ip.magic('doctest_mode')
305 _ip.magic('doctest_mode')
338 _ip.magic('doctest_mode')
306 _ip.magic('doctest_mode')
339
307
340
308
341 def test_parse_options():
309 def test_parse_options():
342 """Tests for basic options parsing in magics."""
310 """Tests for basic options parsing in magics."""
343 # These are only the most minimal of tests, more should be added later. At
311 # These are only the most minimal of tests, more should be added later. At
344 # the very least we check that basic text/unicode calls work OK.
312 # the very least we check that basic text/unicode calls work OK.
345 m = DummyMagics(_ip)
313 m = DummyMagics(_ip)
346 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
314 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
347 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
315 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
348
316
349
317
350 def test_dirops():
318 def test_dirops():
351 """Test various directory handling operations."""
319 """Test various directory handling operations."""
352 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
320 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
353 curpath = os.getcwdu
321 curpath = os.getcwdu
354 startdir = os.getcwdu()
322 startdir = os.getcwdu()
355 ipdir = os.path.realpath(_ip.ipython_dir)
323 ipdir = os.path.realpath(_ip.ipython_dir)
356 try:
324 try:
357 _ip.magic('cd "%s"' % ipdir)
325 _ip.magic('cd "%s"' % ipdir)
358 nt.assert_equal(curpath(), ipdir)
326 nt.assert_equal(curpath(), ipdir)
359 _ip.magic('cd -')
327 _ip.magic('cd -')
360 nt.assert_equal(curpath(), startdir)
328 nt.assert_equal(curpath(), startdir)
361 _ip.magic('pushd "%s"' % ipdir)
329 _ip.magic('pushd "%s"' % ipdir)
362 nt.assert_equal(curpath(), ipdir)
330 nt.assert_equal(curpath(), ipdir)
363 _ip.magic('popd')
331 _ip.magic('popd')
364 nt.assert_equal(curpath(), startdir)
332 nt.assert_equal(curpath(), startdir)
365 finally:
333 finally:
366 os.chdir(startdir)
334 os.chdir(startdir)
367
335
368
336
369 def test_xmode():
337 def test_xmode():
370 # Calling xmode three times should be a no-op
338 # Calling xmode three times should be a no-op
371 xmode = _ip.InteractiveTB.mode
339 xmode = _ip.InteractiveTB.mode
372 for i in range(3):
340 for i in range(3):
373 _ip.magic("xmode")
341 _ip.magic("xmode")
374 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
342 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
375
343
376 def test_reset_hard():
344 def test_reset_hard():
377 monitor = []
345 monitor = []
378 class A(object):
346 class A(object):
379 def __del__(self):
347 def __del__(self):
380 monitor.append(1)
348 monitor.append(1)
381 def __repr__(self):
349 def __repr__(self):
382 return "<A instance>"
350 return "<A instance>"
383
351
384 _ip.user_ns["a"] = A()
352 _ip.user_ns["a"] = A()
385 _ip.run_cell("a")
353 _ip.run_cell("a")
386
354
387 nt.assert_equal(monitor, [])
355 nt.assert_equal(monitor, [])
388 _ip.magic("reset -f")
356 _ip.magic("reset -f")
389 nt.assert_equal(monitor, [1])
357 nt.assert_equal(monitor, [1])
390
358
391 class TestXdel(tt.TempFileMixin):
359 class TestXdel(tt.TempFileMixin):
392 def test_xdel(self):
360 def test_xdel(self):
393 """Test that references from %run are cleared by xdel."""
361 """Test that references from %run are cleared by xdel."""
394 src = ("class A(object):\n"
362 src = ("class A(object):\n"
395 " monitor = []\n"
363 " monitor = []\n"
396 " def __del__(self):\n"
364 " def __del__(self):\n"
397 " self.monitor.append(1)\n"
365 " self.monitor.append(1)\n"
398 "a = A()\n")
366 "a = A()\n")
399 self.mktmp(src)
367 self.mktmp(src)
400 # %run creates some hidden references...
368 # %run creates some hidden references...
401 _ip.magic("run %s" % self.fname)
369 _ip.magic("run %s" % self.fname)
402 # ... as does the displayhook.
370 # ... as does the displayhook.
403 _ip.run_cell("a")
371 _ip.run_cell("a")
404
372
405 monitor = _ip.user_ns["A"].monitor
373 monitor = _ip.user_ns["A"].monitor
406 nt.assert_equal(monitor, [])
374 nt.assert_equal(monitor, [])
407
375
408 _ip.magic("xdel a")
376 _ip.magic("xdel a")
409
377
410 # Check that a's __del__ method has been called.
378 # Check that a's __del__ method has been called.
411 nt.assert_equal(monitor, [1])
379 nt.assert_equal(monitor, [1])
412
380
413 def doctest_who():
381 def doctest_who():
414 """doctest for %who
382 """doctest for %who
415
383
416 In [1]: %reset -f
384 In [1]: %reset -f
417
385
418 In [2]: alpha = 123
386 In [2]: alpha = 123
419
387
420 In [3]: beta = 'beta'
388 In [3]: beta = 'beta'
421
389
422 In [4]: %who int
390 In [4]: %who int
423 alpha
391 alpha
424
392
425 In [5]: %who str
393 In [5]: %who str
426 beta
394 beta
427
395
428 In [6]: %whos
396 In [6]: %whos
429 Variable Type Data/Info
397 Variable Type Data/Info
430 ----------------------------
398 ----------------------------
431 alpha int 123
399 alpha int 123
432 beta str beta
400 beta str beta
433
401
434 In [7]: %who_ls
402 In [7]: %who_ls
435 Out[7]: ['alpha', 'beta']
403 Out[7]: ['alpha', 'beta']
436 """
404 """
437
405
438 def test_whos():
406 def test_whos():
439 """Check that whos is protected against objects where repr() fails."""
407 """Check that whos is protected against objects where repr() fails."""
440 class A(object):
408 class A(object):
441 def __repr__(self):
409 def __repr__(self):
442 raise Exception()
410 raise Exception()
443 _ip.user_ns['a'] = A()
411 _ip.user_ns['a'] = A()
444 _ip.magic("whos")
412 _ip.magic("whos")
445
413
446 @py3compat.u_format
414 @py3compat.u_format
447 def doctest_precision():
415 def doctest_precision():
448 """doctest for %precision
416 """doctest for %precision
449
417
450 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
418 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
451
419
452 In [2]: %precision 5
420 In [2]: %precision 5
453 Out[2]: {u}'%.5f'
421 Out[2]: {u}'%.5f'
454
422
455 In [3]: f.float_format
423 In [3]: f.float_format
456 Out[3]: {u}'%.5f'
424 Out[3]: {u}'%.5f'
457
425
458 In [4]: %precision %e
426 In [4]: %precision %e
459 Out[4]: {u}'%e'
427 Out[4]: {u}'%e'
460
428
461 In [5]: f(3.1415927)
429 In [5]: f(3.1415927)
462 Out[5]: {u}'3.141593e+00'
430 Out[5]: {u}'3.141593e+00'
463 """
431 """
464
432
465 def test_psearch():
433 def test_psearch():
466 with tt.AssertPrints("dict.fromkeys"):
434 with tt.AssertPrints("dict.fromkeys"):
467 _ip.run_cell("dict.fr*?")
435 _ip.run_cell("dict.fr*?")
468
436
469 def test_timeit_shlex():
437 def test_timeit_shlex():
470 """test shlex issues with timeit (#1109)"""
438 """test shlex issues with timeit (#1109)"""
471 _ip.ex("def f(*a,**kw): pass")
439 _ip.ex("def f(*a,**kw): pass")
472 _ip.magic('timeit -n1 "this is a bug".count(" ")')
440 _ip.magic('timeit -n1 "this is a bug".count(" ")')
473 _ip.magic('timeit -r1 -n1 f(" ", 1)')
441 _ip.magic('timeit -r1 -n1 f(" ", 1)')
474 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
442 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
475 _ip.magic('timeit -r1 -n1 ("a " + "b")')
443 _ip.magic('timeit -r1 -n1 ("a " + "b")')
476 _ip.magic('timeit -r1 -n1 f("a " + "b")')
444 _ip.magic('timeit -r1 -n1 f("a " + "b")')
477 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
445 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
478
446
479
447
480 def test_timeit_arguments():
448 def test_timeit_arguments():
481 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
449 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
482 _ip.magic("timeit ('#')")
450 _ip.magic("timeit ('#')")
483
451
484
452
485 def test_timeit_special_syntax():
453 def test_timeit_special_syntax():
486 "Test %%timeit with IPython special syntax"
454 "Test %%timeit with IPython special syntax"
487 from IPython.core.magic import register_line_magic
455 from IPython.core.magic import register_line_magic
488
456
489 @register_line_magic
457 @register_line_magic
490 def lmagic(line):
458 def lmagic(line):
491 ip = get_ipython()
459 ip = get_ipython()
492 ip.user_ns['lmagic_out'] = line
460 ip.user_ns['lmagic_out'] = line
493
461
494 # line mode test
462 # line mode test
495 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
463 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
496 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
464 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
497 # cell mode test
465 # cell mode test
498 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
466 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
499 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
467 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
500
468
501
469
502 @dec.skipif(execution.profile is None)
470 @dec.skipif(execution.profile is None)
503 def test_prun_quotes():
471 def test_prun_quotes():
504 "Test that prun does not clobber string escapes (GH #1302)"
472 "Test that prun does not clobber string escapes (GH #1302)"
505 _ip.magic(r"prun -q x = '\t'")
473 _ip.magic(r"prun -q x = '\t'")
506 nt.assert_equal(_ip.user_ns['x'], '\t')
474 nt.assert_equal(_ip.user_ns['x'], '\t')
507
475
508 def test_extension():
476 def test_extension():
509 tmpdir = TemporaryDirectory()
477 tmpdir = TemporaryDirectory()
510 orig_ipython_dir = _ip.ipython_dir
478 orig_ipython_dir = _ip.ipython_dir
511 try:
479 try:
512 _ip.ipython_dir = tmpdir.name
480 _ip.ipython_dir = tmpdir.name
513 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
481 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
514 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
482 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
515 _ip.magic("install_ext %s" % url)
483 _ip.magic("install_ext %s" % url)
516 _ip.user_ns.pop('arq', None)
484 _ip.user_ns.pop('arq', None)
517 invalidate_caches() # Clear import caches
485 invalidate_caches() # Clear import caches
518 _ip.magic("load_ext daft_extension")
486 _ip.magic("load_ext daft_extension")
519 tt.assert_equal(_ip.user_ns['arq'], 185)
487 tt.assert_equal(_ip.user_ns['arq'], 185)
520 _ip.magic("unload_ext daft_extension")
488 _ip.magic("unload_ext daft_extension")
521 assert 'arq' not in _ip.user_ns
489 assert 'arq' not in _ip.user_ns
522 finally:
490 finally:
523 _ip.ipython_dir = orig_ipython_dir
491 _ip.ipython_dir = orig_ipython_dir
524 tmpdir.cleanup()
492 tmpdir.cleanup()
525
493
526 def test_notebook_export_json():
494 def test_notebook_export_json():
527 with TemporaryDirectory() as td:
495 with TemporaryDirectory() as td:
528 outfile = os.path.join(td, "nb.ipynb")
496 outfile = os.path.join(td, "nb.ipynb")
529 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
497 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
530 _ip.magic("notebook -e %s" % outfile)
498 _ip.magic("notebook -e %s" % outfile)
531
499
532 def test_notebook_export_py():
500 def test_notebook_export_py():
533 with TemporaryDirectory() as td:
501 with TemporaryDirectory() as td:
534 outfile = os.path.join(td, "nb.py")
502 outfile = os.path.join(td, "nb.py")
535 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
503 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
536 _ip.magic("notebook -e %s" % outfile)
504 _ip.magic("notebook -e %s" % outfile)
537
505
538 def test_notebook_reformat_py():
506 def test_notebook_reformat_py():
539 with TemporaryDirectory() as td:
507 with TemporaryDirectory() as td:
540 infile = os.path.join(td, "nb.ipynb")
508 infile = os.path.join(td, "nb.ipynb")
541 with io.open(infile, 'w', encoding='utf-8') as f:
509 with io.open(infile, 'w', encoding='utf-8') as f:
542 current.write(nb0, f, 'json')
510 current.write(nb0, f, 'json')
543
511
544 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
512 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
545 _ip.magic("notebook -f py %s" % infile)
513 _ip.magic("notebook -f py %s" % infile)
546
514
547 def test_notebook_reformat_json():
515 def test_notebook_reformat_json():
548 with TemporaryDirectory() as td:
516 with TemporaryDirectory() as td:
549 infile = os.path.join(td, "nb.py")
517 infile = os.path.join(td, "nb.py")
550 with io.open(infile, 'w', encoding='utf-8') as f:
518 with io.open(infile, 'w', encoding='utf-8') as f:
551 current.write(nb0, f, 'py')
519 current.write(nb0, f, 'py')
552
520
553 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
521 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
554 _ip.magic("notebook -f ipynb %s" % infile)
522 _ip.magic("notebook -f ipynb %s" % infile)
555 _ip.magic("notebook -f json %s" % infile)
523 _ip.magic("notebook -f json %s" % infile)
556
524
557 def test_env():
525 def test_env():
558 env = _ip.magic("env")
526 env = _ip.magic("env")
559 assert isinstance(env, dict), type(env)
527 assert isinstance(env, dict), type(env)
560
528
561
529
562 class CellMagicTestCase(TestCase):
530 class CellMagicTestCase(TestCase):
563
531
564 def check_ident(self, magic):
532 def check_ident(self, magic):
565 # Manually called, we get the result
533 # Manually called, we get the result
566 out = _ip.run_cell_magic(magic, 'a', 'b')
534 out = _ip.run_cell_magic(magic, 'a', 'b')
567 nt.assert_equals(out, ('a','b'))
535 nt.assert_equals(out, ('a','b'))
568 # Via run_cell, it goes into the user's namespace via displayhook
536 # Via run_cell, it goes into the user's namespace via displayhook
569 _ip.run_cell('%%' + magic +' c\nd')
537 _ip.run_cell('%%' + magic +' c\nd')
570 nt.assert_equals(_ip.user_ns['_'], ('c','d'))
538 nt.assert_equals(_ip.user_ns['_'], ('c','d'))
571
539
572 def test_cell_magic_func_deco(self):
540 def test_cell_magic_func_deco(self):
573 "Cell magic using simple decorator"
541 "Cell magic using simple decorator"
574 @register_cell_magic
542 @register_cell_magic
575 def cellm(line, cell):
543 def cellm(line, cell):
576 return line, cell
544 return line, cell
577
545
578 self.check_ident('cellm')
546 self.check_ident('cellm')
579
547
580 def test_cell_magic_reg(self):
548 def test_cell_magic_reg(self):
581 "Cell magic manually registered"
549 "Cell magic manually registered"
582 def cellm(line, cell):
550 def cellm(line, cell):
583 return line, cell
551 return line, cell
584
552
585 _ip.register_magic_function(cellm, 'cell', 'cellm2')
553 _ip.register_magic_function(cellm, 'cell', 'cellm2')
586 self.check_ident('cellm2')
554 self.check_ident('cellm2')
587
555
588 def test_cell_magic_class(self):
556 def test_cell_magic_class(self):
589 "Cell magics declared via a class"
557 "Cell magics declared via a class"
590 @magics_class
558 @magics_class
591 class MyMagics(Magics):
559 class MyMagics(Magics):
592
560
593 @cell_magic
561 @cell_magic
594 def cellm3(self, line, cell):
562 def cellm3(self, line, cell):
595 return line, cell
563 return line, cell
596
564
597 _ip.register_magics(MyMagics)
565 _ip.register_magics(MyMagics)
598 self.check_ident('cellm3')
566 self.check_ident('cellm3')
599
567
600 def test_cell_magic_class2(self):
568 def test_cell_magic_class2(self):
601 "Cell magics declared via a class, #2"
569 "Cell magics declared via a class, #2"
602 @magics_class
570 @magics_class
603 class MyMagics2(Magics):
571 class MyMagics2(Magics):
604
572
605 @cell_magic('cellm4')
573 @cell_magic('cellm4')
606 def cellm33(self, line, cell):
574 def cellm33(self, line, cell):
607 return line, cell
575 return line, cell
608
576
609 _ip.register_magics(MyMagics2)
577 _ip.register_magics(MyMagics2)
610 self.check_ident('cellm4')
578 self.check_ident('cellm4')
611 # Check that nothing is registered as 'cellm33'
579 # Check that nothing is registered as 'cellm33'
612 c33 = _ip.find_cell_magic('cellm33')
580 c33 = _ip.find_cell_magic('cellm33')
613 nt.assert_equals(c33, None)
581 nt.assert_equals(c33, None)
614
582
615 def test_file():
583 def test_file():
616 """Basic %%file"""
584 """Basic %%file"""
617 ip = get_ipython()
585 ip = get_ipython()
618 with TemporaryDirectory() as td:
586 with TemporaryDirectory() as td:
619 fname = os.path.join(td, 'file1')
587 fname = os.path.join(td, 'file1')
620 ip.run_cell_magic("file", fname, u'\n'.join([
588 ip.run_cell_magic("file", fname, u'\n'.join([
621 'line1',
589 'line1',
622 'line2',
590 'line2',
623 ]))
591 ]))
624 with open(fname) as f:
592 with open(fname) as f:
625 s = f.read()
593 s = f.read()
626 nt.assert_in('line1\n', s)
594 nt.assert_in('line1\n', s)
627 nt.assert_in('line2', s)
595 nt.assert_in('line2', s)
628
596
629 def test_file_unicode():
597 def test_file_unicode():
630 """%%file with unicode cell"""
598 """%%file with unicode cell"""
631 ip = get_ipython()
599 ip = get_ipython()
632 with TemporaryDirectory() as td:
600 with TemporaryDirectory() as td:
633 fname = os.path.join(td, 'file1')
601 fname = os.path.join(td, 'file1')
634 ip.run_cell_magic("file", fname, u'\n'.join([
602 ip.run_cell_magic("file", fname, u'\n'.join([
635 u'linΓ©1',
603 u'linΓ©1',
636 u'linΓ©2',
604 u'linΓ©2',
637 ]))
605 ]))
638 with io.open(fname, encoding='utf-8') as f:
606 with io.open(fname, encoding='utf-8') as f:
639 s = f.read()
607 s = f.read()
640 nt.assert_in(u'linΓ©1\n', s)
608 nt.assert_in(u'linΓ©1\n', s)
641 nt.assert_in(u'linΓ©2', s)
609 nt.assert_in(u'linΓ©2', s)
642
610
643 def test_file_amend():
611 def test_file_amend():
644 """%%file -a amends files"""
612 """%%file -a amends files"""
645 ip = get_ipython()
613 ip = get_ipython()
646 with TemporaryDirectory() as td:
614 with TemporaryDirectory() as td:
647 fname = os.path.join(td, 'file2')
615 fname = os.path.join(td, 'file2')
648 ip.run_cell_magic("file", fname, u'\n'.join([
616 ip.run_cell_magic("file", fname, u'\n'.join([
649 'line1',
617 'line1',
650 'line2',
618 'line2',
651 ]))
619 ]))
652 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
620 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
653 'line3',
621 'line3',
654 'line4',
622 'line4',
655 ]))
623 ]))
656 with open(fname) as f:
624 with open(fname) as f:
657 s = f.read()
625 s = f.read()
658 nt.assert_in('line1\n', s)
626 nt.assert_in('line1\n', s)
659 nt.assert_in('line3\n', s)
627 nt.assert_in('line3\n', s)
660
628
661
629
662 def test_script_config():
630 def test_script_config():
663 ip = get_ipython()
631 ip = get_ipython()
664 ip.config.ScriptMagics.script_magics = ['whoda']
632 ip.config.ScriptMagics.script_magics = ['whoda']
665 sm = script.ScriptMagics(shell=ip)
633 sm = script.ScriptMagics(shell=ip)
666 nt.assert_in('whoda', sm.magics['cell'])
634 nt.assert_in('whoda', sm.magics['cell'])
667
635
668 @dec.skip_win32
636 @dec.skip_win32
669 def test_script_out():
637 def test_script_out():
670 ip = get_ipython()
638 ip = get_ipython()
671 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
639 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
672 nt.assert_equals(ip.user_ns['output'], 'hi\n')
640 nt.assert_equals(ip.user_ns['output'], 'hi\n')
673
641
674 @dec.skip_win32
642 @dec.skip_win32
675 def test_script_err():
643 def test_script_err():
676 ip = get_ipython()
644 ip = get_ipython()
677 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
645 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
678 nt.assert_equals(ip.user_ns['error'], 'hello\n')
646 nt.assert_equals(ip.user_ns['error'], 'hello\n')
679
647
680 @dec.skip_win32
648 @dec.skip_win32
681 def test_script_out_err():
649 def test_script_out_err():
682 ip = get_ipython()
650 ip = get_ipython()
683 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
651 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
684 nt.assert_equals(ip.user_ns['output'], 'hi\n')
652 nt.assert_equals(ip.user_ns['output'], 'hi\n')
685 nt.assert_equals(ip.user_ns['error'], 'hello\n')
653 nt.assert_equals(ip.user_ns['error'], 'hello\n')
686
654
687 @dec.skip_win32
655 @dec.skip_win32
688 def test_script_bg_out():
656 def test_script_bg_out():
689 ip = get_ipython()
657 ip = get_ipython()
690 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
658 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
691 nt.assert_equals(ip.user_ns['output'].read(), b'hi\n')
659 nt.assert_equals(ip.user_ns['output'].read(), b'hi\n')
692
660
693 @dec.skip_win32
661 @dec.skip_win32
694 def test_script_bg_err():
662 def test_script_bg_err():
695 ip = get_ipython()
663 ip = get_ipython()
696 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
664 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
697 nt.assert_equals(ip.user_ns['error'].read(), b'hello\n')
665 nt.assert_equals(ip.user_ns['error'].read(), b'hello\n')
698
666
699 @dec.skip_win32
667 @dec.skip_win32
700 def test_script_bg_out_err():
668 def test_script_bg_out_err():
701 ip = get_ipython()
669 ip = get_ipython()
702 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
670 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
703 nt.assert_equals(ip.user_ns['output'].read(), b'hi\n')
671 nt.assert_equals(ip.user_ns['output'].read(), b'hi\n')
704 nt.assert_equals(ip.user_ns['error'].read(), b'hello\n')
672 nt.assert_equals(ip.user_ns['error'].read(), b'hello\n')
705
673
706 def test_script_defaults():
674 def test_script_defaults():
707 ip = get_ipython()
675 ip = get_ipython()
708 for cmd in ['sh', 'bash', 'perl', 'ruby']:
676 for cmd in ['sh', 'bash', 'perl', 'ruby']:
709 try:
677 try:
710 find_cmd(cmd)
678 find_cmd(cmd)
711 except Exception:
679 except Exception:
712 pass
680 pass
713 else:
681 else:
714 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
682 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
715
683
716
684
717 @magics_class
685 @magics_class
718 class FooFoo(Magics):
686 class FooFoo(Magics):
719 """class with both %foo and %%foo magics"""
687 """class with both %foo and %%foo magics"""
720 @line_magic('foo')
688 @line_magic('foo')
721 def line_foo(self, line):
689 def line_foo(self, line):
722 "I am line foo"
690 "I am line foo"
723 pass
691 pass
724
692
725 @cell_magic("foo")
693 @cell_magic("foo")
726 def cell_foo(self, line, cell):
694 def cell_foo(self, line, cell):
727 "I am cell foo, not line foo"
695 "I am cell foo, not line foo"
728 pass
696 pass
729
697
730 def test_line_cell_info():
698 def test_line_cell_info():
731 """%%foo and %foo magics are distinguishable to inspect"""
699 """%%foo and %foo magics are distinguishable to inspect"""
732 ip = get_ipython()
700 ip = get_ipython()
733 ip.magics_manager.register(FooFoo)
701 ip.magics_manager.register(FooFoo)
734 oinfo = ip.object_inspect('foo')
702 oinfo = ip.object_inspect('foo')
735 nt.assert_true(oinfo['found'])
703 nt.assert_true(oinfo['found'])
736 nt.assert_true(oinfo['ismagic'])
704 nt.assert_true(oinfo['ismagic'])
737
705
738 oinfo = ip.object_inspect('%%foo')
706 oinfo = ip.object_inspect('%%foo')
739 nt.assert_true(oinfo['found'])
707 nt.assert_true(oinfo['found'])
740 nt.assert_true(oinfo['ismagic'])
708 nt.assert_true(oinfo['ismagic'])
741 nt.assert_equals(oinfo['docstring'], FooFoo.cell_foo.__doc__)
709 nt.assert_equals(oinfo['docstring'], FooFoo.cell_foo.__doc__)
742
710
743 oinfo = ip.object_inspect('%foo')
711 oinfo = ip.object_inspect('%foo')
744 nt.assert_true(oinfo['found'])
712 nt.assert_true(oinfo['found'])
745 nt.assert_true(oinfo['ismagic'])
713 nt.assert_true(oinfo['ismagic'])
746 nt.assert_equals(oinfo['docstring'], FooFoo.line_foo.__doc__)
714 nt.assert_equals(oinfo['docstring'], FooFoo.line_foo.__doc__)
747
715
748 def test_multiple_magics():
716 def test_multiple_magics():
749 ip = get_ipython()
717 ip = get_ipython()
750 foo1 = FooFoo(ip)
718 foo1 = FooFoo(ip)
751 foo2 = FooFoo(ip)
719 foo2 = FooFoo(ip)
752 mm = ip.magics_manager
720 mm = ip.magics_manager
753 mm.register(foo1)
721 mm.register(foo1)
754 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
722 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
755 mm.register(foo2)
723 mm.register(foo2)
756 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
724 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
757
725
758 def test_alias_magic():
726 def test_alias_magic():
759 """Test %alias_magic."""
727 """Test %alias_magic."""
760 ip = get_ipython()
728 ip = get_ipython()
761 mm = ip.magics_manager
729 mm = ip.magics_manager
762
730
763 # Basic operation: both cell and line magics are created, if possible.
731 # Basic operation: both cell and line magics are created, if possible.
764 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
732 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
765 nt.assert_true('timeit_alias' in mm.magics['line'])
733 nt.assert_true('timeit_alias' in mm.magics['line'])
766 nt.assert_true('timeit_alias' in mm.magics['cell'])
734 nt.assert_true('timeit_alias' in mm.magics['cell'])
767
735
768 # --cell is specified, line magic not created.
736 # --cell is specified, line magic not created.
769 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
737 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
770 nt.assert_false('timeit_cell_alias' in mm.magics['line'])
738 nt.assert_false('timeit_cell_alias' in mm.magics['line'])
771 nt.assert_true('timeit_cell_alias' in mm.magics['cell'])
739 nt.assert_true('timeit_cell_alias' in mm.magics['cell'])
772
740
773 # Test that line alias is created successfully.
741 # Test that line alias is created successfully.
774 ip.run_line_magic('alias_magic', '--line env_alias env')
742 ip.run_line_magic('alias_magic', '--line env_alias env')
775 nt.assert_equal(ip.run_line_magic('env', ''),
743 nt.assert_equal(ip.run_line_magic('env', ''),
776 ip.run_line_magic('env_alias', ''))
744 ip.run_line_magic('env_alias', ''))
@@ -1,468 +1,482 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for path handling.
3 Utilities for path handling.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 import os
17 import os
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 import warnings
20 import warnings
21 from hashlib import md5
21 from hashlib import md5
22 from glob import glob
22
23
23 import IPython
24 import IPython
24 from IPython.testing.skipdoctest import skip_doctest
25 from IPython.testing.skipdoctest import skip_doctest
25 from IPython.utils.process import system
26 from IPython.utils.process import system
26 from IPython.utils.importstring import import_item
27 from IPython.utils.importstring import import_item
27 from IPython.utils import py3compat
28 from IPython.utils import py3compat
28 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
29 # Code
30 # Code
30 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
31
32
32 fs_encoding = sys.getfilesystemencoding()
33 fs_encoding = sys.getfilesystemencoding()
33
34
34 def _get_long_path_name(path):
35 def _get_long_path_name(path):
35 """Dummy no-op."""
36 """Dummy no-op."""
36 return path
37 return path
37
38
38 def _writable_dir(path):
39 def _writable_dir(path):
39 """Whether `path` is a directory, to which the user has write access."""
40 """Whether `path` is a directory, to which the user has write access."""
40 return os.path.isdir(path) and os.access(path, os.W_OK)
41 return os.path.isdir(path) and os.access(path, os.W_OK)
41
42
42 if sys.platform == 'win32':
43 if sys.platform == 'win32':
43 @skip_doctest
44 @skip_doctest
44 def _get_long_path_name(path):
45 def _get_long_path_name(path):
45 """Get a long path name (expand ~) on Windows using ctypes.
46 """Get a long path name (expand ~) on Windows using ctypes.
46
47
47 Examples
48 Examples
48 --------
49 --------
49
50
50 >>> get_long_path_name('c:\\docume~1')
51 >>> get_long_path_name('c:\\docume~1')
51 u'c:\\\\Documents and Settings'
52 u'c:\\\\Documents and Settings'
52
53
53 """
54 """
54 try:
55 try:
55 import ctypes
56 import ctypes
56 except ImportError:
57 except ImportError:
57 raise ImportError('you need to have ctypes installed for this to work')
58 raise ImportError('you need to have ctypes installed for this to work')
58 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
59 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
59 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
60 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
60 ctypes.c_uint ]
61 ctypes.c_uint ]
61
62
62 buf = ctypes.create_unicode_buffer(260)
63 buf = ctypes.create_unicode_buffer(260)
63 rv = _GetLongPathName(path, buf, 260)
64 rv = _GetLongPathName(path, buf, 260)
64 if rv == 0 or rv > 260:
65 if rv == 0 or rv > 260:
65 return path
66 return path
66 else:
67 else:
67 return buf.value
68 return buf.value
68
69
69
70
70 def get_long_path_name(path):
71 def get_long_path_name(path):
71 """Expand a path into its long form.
72 """Expand a path into its long form.
72
73
73 On Windows this expands any ~ in the paths. On other platforms, it is
74 On Windows this expands any ~ in the paths. On other platforms, it is
74 a null operation.
75 a null operation.
75 """
76 """
76 return _get_long_path_name(path)
77 return _get_long_path_name(path)
77
78
78
79
79 def unquote_filename(name, win32=(sys.platform=='win32')):
80 def unquote_filename(name, win32=(sys.platform=='win32')):
80 """ On Windows, remove leading and trailing quotes from filenames.
81 """ On Windows, remove leading and trailing quotes from filenames.
81 """
82 """
82 if win32:
83 if win32:
83 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
84 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
84 name = name[1:-1]
85 name = name[1:-1]
85 return name
86 return name
86
87
87
88
88 def get_py_filename(name, force_win32=None):
89 def get_py_filename(name, force_win32=None):
89 """Return a valid python filename in the current directory.
90 """Return a valid python filename in the current directory.
90
91
91 If the given name is not a file, it adds '.py' and searches again.
92 If the given name is not a file, it adds '.py' and searches again.
92 Raises IOError with an informative message if the file isn't found.
93 Raises IOError with an informative message if the file isn't found.
93
94
94 On Windows, apply Windows semantics to the filename. In particular, remove
95 On Windows, apply Windows semantics to the filename. In particular, remove
95 any quoting that has been applied to it. This option can be forced for
96 any quoting that has been applied to it. This option can be forced for
96 testing purposes.
97 testing purposes.
97 """
98 """
98
99
99 name = os.path.expanduser(name)
100 name = os.path.expanduser(name)
100 if force_win32 is None:
101 if force_win32 is None:
101 win32 = (sys.platform == 'win32')
102 win32 = (sys.platform == 'win32')
102 else:
103 else:
103 win32 = force_win32
104 win32 = force_win32
104 name = unquote_filename(name, win32=win32)
105 name = unquote_filename(name, win32=win32)
105 if not os.path.isfile(name) and not name.endswith('.py'):
106 if not os.path.isfile(name) and not name.endswith('.py'):
106 name += '.py'
107 name += '.py'
107 if os.path.isfile(name):
108 if os.path.isfile(name):
108 return name
109 return name
109 else:
110 else:
110 raise IOError('File `%r` not found.' % name)
111 raise IOError('File `%r` not found.' % name)
111
112
112
113
113 def filefind(filename, path_dirs=None):
114 def filefind(filename, path_dirs=None):
114 """Find a file by looking through a sequence of paths.
115 """Find a file by looking through a sequence of paths.
115
116
116 This iterates through a sequence of paths looking for a file and returns
117 This iterates through a sequence of paths looking for a file and returns
117 the full, absolute path of the first occurence of the file. If no set of
118 the full, absolute path of the first occurence of the file. If no set of
118 path dirs is given, the filename is tested as is, after running through
119 path dirs is given, the filename is tested as is, after running through
119 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
120 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
120
121
121 filefind('myfile.txt')
122 filefind('myfile.txt')
122
123
123 will find the file in the current working dir, but::
124 will find the file in the current working dir, but::
124
125
125 filefind('~/myfile.txt')
126 filefind('~/myfile.txt')
126
127
127 Will find the file in the users home directory. This function does not
128 Will find the file in the users home directory. This function does not
128 automatically try any paths, such as the cwd or the user's home directory.
129 automatically try any paths, such as the cwd or the user's home directory.
129
130
130 Parameters
131 Parameters
131 ----------
132 ----------
132 filename : str
133 filename : str
133 The filename to look for.
134 The filename to look for.
134 path_dirs : str, None or sequence of str
135 path_dirs : str, None or sequence of str
135 The sequence of paths to look for the file in. If None, the filename
136 The sequence of paths to look for the file in. If None, the filename
136 need to be absolute or be in the cwd. If a string, the string is
137 need to be absolute or be in the cwd. If a string, the string is
137 put into a sequence and the searched. If a sequence, walk through
138 put into a sequence and the searched. If a sequence, walk through
138 each element and join with ``filename``, calling :func:`expandvars`
139 each element and join with ``filename``, calling :func:`expandvars`
139 and :func:`expanduser` before testing for existence.
140 and :func:`expanduser` before testing for existence.
140
141
141 Returns
142 Returns
142 -------
143 -------
143 Raises :exc:`IOError` or returns absolute path to file.
144 Raises :exc:`IOError` or returns absolute path to file.
144 """
145 """
145
146
146 # If paths are quoted, abspath gets confused, strip them...
147 # If paths are quoted, abspath gets confused, strip them...
147 filename = filename.strip('"').strip("'")
148 filename = filename.strip('"').strip("'")
148 # If the input is an absolute path, just check it exists
149 # If the input is an absolute path, just check it exists
149 if os.path.isabs(filename) and os.path.isfile(filename):
150 if os.path.isabs(filename) and os.path.isfile(filename):
150 return filename
151 return filename
151
152
152 if path_dirs is None:
153 if path_dirs is None:
153 path_dirs = ("",)
154 path_dirs = ("",)
154 elif isinstance(path_dirs, basestring):
155 elif isinstance(path_dirs, basestring):
155 path_dirs = (path_dirs,)
156 path_dirs = (path_dirs,)
156
157
157 for path in path_dirs:
158 for path in path_dirs:
158 if path == '.': path = os.getcwdu()
159 if path == '.': path = os.getcwdu()
159 testname = expand_path(os.path.join(path, filename))
160 testname = expand_path(os.path.join(path, filename))
160 if os.path.isfile(testname):
161 if os.path.isfile(testname):
161 return os.path.abspath(testname)
162 return os.path.abspath(testname)
162
163
163 raise IOError("File %r does not exist in any of the search paths: %r" %
164 raise IOError("File %r does not exist in any of the search paths: %r" %
164 (filename, path_dirs) )
165 (filename, path_dirs) )
165
166
166
167
167 class HomeDirError(Exception):
168 class HomeDirError(Exception):
168 pass
169 pass
169
170
170
171
171 def get_home_dir(require_writable=False):
172 def get_home_dir(require_writable=False):
172 """Return the 'home' directory, as a unicode string.
173 """Return the 'home' directory, as a unicode string.
173
174
174 * First, check for frozen env in case of py2exe
175 * First, check for frozen env in case of py2exe
175 * Otherwise, defer to os.path.expanduser('~')
176 * Otherwise, defer to os.path.expanduser('~')
176
177
177 See stdlib docs for how this is determined.
178 See stdlib docs for how this is determined.
178 $HOME is first priority on *ALL* platforms.
179 $HOME is first priority on *ALL* platforms.
179
180
180 Parameters
181 Parameters
181 ----------
182 ----------
182
183
183 require_writable : bool [default: False]
184 require_writable : bool [default: False]
184 if True:
185 if True:
185 guarantees the return value is a writable directory, otherwise
186 guarantees the return value is a writable directory, otherwise
186 raises HomeDirError
187 raises HomeDirError
187 if False:
188 if False:
188 The path is resolved, but it is not guaranteed to exist or be writable.
189 The path is resolved, but it is not guaranteed to exist or be writable.
189 """
190 """
190
191
191 # first, check py2exe distribution root directory for _ipython.
192 # first, check py2exe distribution root directory for _ipython.
192 # This overrides all. Normally does not exist.
193 # This overrides all. Normally does not exist.
193
194
194 if hasattr(sys, "frozen"): #Is frozen by py2exe
195 if hasattr(sys, "frozen"): #Is frozen by py2exe
195 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
196 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
196 root, rest = IPython.__file__.lower().split('library.zip')
197 root, rest = IPython.__file__.lower().split('library.zip')
197 else:
198 else:
198 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
199 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
199 root=os.path.abspath(root).rstrip('\\')
200 root=os.path.abspath(root).rstrip('\\')
200 if _writable_dir(os.path.join(root, '_ipython')):
201 if _writable_dir(os.path.join(root, '_ipython')):
201 os.environ["IPYKITROOT"] = root
202 os.environ["IPYKITROOT"] = root
202 return py3compat.cast_unicode(root, fs_encoding)
203 return py3compat.cast_unicode(root, fs_encoding)
203
204
204 homedir = os.path.expanduser('~')
205 homedir = os.path.expanduser('~')
205 # Next line will make things work even when /home/ is a symlink to
206 # Next line will make things work even when /home/ is a symlink to
206 # /usr/home as it is on FreeBSD, for example
207 # /usr/home as it is on FreeBSD, for example
207 homedir = os.path.realpath(homedir)
208 homedir = os.path.realpath(homedir)
208
209
209 if not _writable_dir(homedir) and os.name == 'nt':
210 if not _writable_dir(homedir) and os.name == 'nt':
210 # expanduser failed, use the registry to get the 'My Documents' folder.
211 # expanduser failed, use the registry to get the 'My Documents' folder.
211 try:
212 try:
212 import _winreg as wreg
213 import _winreg as wreg
213 key = wreg.OpenKey(
214 key = wreg.OpenKey(
214 wreg.HKEY_CURRENT_USER,
215 wreg.HKEY_CURRENT_USER,
215 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
216 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
216 )
217 )
217 homedir = wreg.QueryValueEx(key,'Personal')[0]
218 homedir = wreg.QueryValueEx(key,'Personal')[0]
218 key.Close()
219 key.Close()
219 except:
220 except:
220 pass
221 pass
221
222
222 if (not require_writable) or _writable_dir(homedir):
223 if (not require_writable) or _writable_dir(homedir):
223 return py3compat.cast_unicode(homedir, fs_encoding)
224 return py3compat.cast_unicode(homedir, fs_encoding)
224 else:
225 else:
225 raise HomeDirError('%s is not a writable dir, '
226 raise HomeDirError('%s is not a writable dir, '
226 'set $HOME environment variable to override' % homedir)
227 'set $HOME environment variable to override' % homedir)
227
228
228 def get_xdg_dir():
229 def get_xdg_dir():
229 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
230 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
230
231
231 This is only for non-OS X posix (Linux,Unix,etc.) systems.
232 This is only for non-OS X posix (Linux,Unix,etc.) systems.
232 """
233 """
233
234
234 env = os.environ
235 env = os.environ
235
236
236 if os.name == 'posix' and sys.platform != 'darwin':
237 if os.name == 'posix' and sys.platform != 'darwin':
237 # Linux, Unix, AIX, etc.
238 # Linux, Unix, AIX, etc.
238 # use ~/.config if empty OR not set
239 # use ~/.config if empty OR not set
239 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
240 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
240 if xdg and _writable_dir(xdg):
241 if xdg and _writable_dir(xdg):
241 return py3compat.cast_unicode(xdg, fs_encoding)
242 return py3compat.cast_unicode(xdg, fs_encoding)
242
243
243 return None
244 return None
244
245
245
246
246 def get_ipython_dir():
247 def get_ipython_dir():
247 """Get the IPython directory for this platform and user.
248 """Get the IPython directory for this platform and user.
248
249
249 This uses the logic in `get_home_dir` to find the home directory
250 This uses the logic in `get_home_dir` to find the home directory
250 and then adds .ipython to the end of the path.
251 and then adds .ipython to the end of the path.
251 """
252 """
252
253
253 env = os.environ
254 env = os.environ
254 pjoin = os.path.join
255 pjoin = os.path.join
255
256
256
257
257 ipdir_def = '.ipython'
258 ipdir_def = '.ipython'
258 xdg_def = 'ipython'
259 xdg_def = 'ipython'
259
260
260 home_dir = get_home_dir()
261 home_dir = get_home_dir()
261 xdg_dir = get_xdg_dir()
262 xdg_dir = get_xdg_dir()
262
263
263 # import pdb; pdb.set_trace() # dbg
264 # import pdb; pdb.set_trace() # dbg
264 if 'IPYTHON_DIR' in env:
265 if 'IPYTHON_DIR' in env:
265 warnings.warn('The environment variable IPYTHON_DIR is deprecated. '
266 warnings.warn('The environment variable IPYTHON_DIR is deprecated. '
266 'Please use IPYTHONDIR instead.')
267 'Please use IPYTHONDIR instead.')
267 ipdir = env.get('IPYTHONDIR', env.get('IPYTHON_DIR', None))
268 ipdir = env.get('IPYTHONDIR', env.get('IPYTHON_DIR', None))
268 if ipdir is None:
269 if ipdir is None:
269 # not set explicitly, use XDG_CONFIG_HOME or HOME
270 # not set explicitly, use XDG_CONFIG_HOME or HOME
270 home_ipdir = pjoin(home_dir, ipdir_def)
271 home_ipdir = pjoin(home_dir, ipdir_def)
271 if xdg_dir:
272 if xdg_dir:
272 # use XDG, as long as the user isn't already
273 # use XDG, as long as the user isn't already
273 # using $HOME/.ipython and *not* XDG/ipython
274 # using $HOME/.ipython and *not* XDG/ipython
274
275
275 xdg_ipdir = pjoin(xdg_dir, xdg_def)
276 xdg_ipdir = pjoin(xdg_dir, xdg_def)
276
277
277 if _writable_dir(xdg_ipdir) or not _writable_dir(home_ipdir):
278 if _writable_dir(xdg_ipdir) or not _writable_dir(home_ipdir):
278 ipdir = xdg_ipdir
279 ipdir = xdg_ipdir
279
280
280 if ipdir is None:
281 if ipdir is None:
281 # not using XDG
282 # not using XDG
282 ipdir = home_ipdir
283 ipdir = home_ipdir
283
284
284 ipdir = os.path.normpath(os.path.expanduser(ipdir))
285 ipdir = os.path.normpath(os.path.expanduser(ipdir))
285
286
286 if os.path.exists(ipdir) and not _writable_dir(ipdir):
287 if os.path.exists(ipdir) and not _writable_dir(ipdir):
287 # ipdir exists, but is not writable
288 # ipdir exists, but is not writable
288 warnings.warn("IPython dir '%s' is not a writable location,"
289 warnings.warn("IPython dir '%s' is not a writable location,"
289 " using a temp directory."%ipdir)
290 " using a temp directory."%ipdir)
290 ipdir = tempfile.mkdtemp()
291 ipdir = tempfile.mkdtemp()
291 elif not os.path.exists(ipdir):
292 elif not os.path.exists(ipdir):
292 parent = ipdir.rsplit(os.path.sep, 1)[0]
293 parent = ipdir.rsplit(os.path.sep, 1)[0]
293 if not _writable_dir(parent):
294 if not _writable_dir(parent):
294 # ipdir does not exist and parent isn't writable
295 # ipdir does not exist and parent isn't writable
295 warnings.warn("IPython parent '%s' is not a writable location,"
296 warnings.warn("IPython parent '%s' is not a writable location,"
296 " using a temp directory."%parent)
297 " using a temp directory."%parent)
297 ipdir = tempfile.mkdtemp()
298 ipdir = tempfile.mkdtemp()
298
299
299 return py3compat.cast_unicode(ipdir, fs_encoding)
300 return py3compat.cast_unicode(ipdir, fs_encoding)
300
301
301
302
302 def get_ipython_package_dir():
303 def get_ipython_package_dir():
303 """Get the base directory where IPython itself is installed."""
304 """Get the base directory where IPython itself is installed."""
304 ipdir = os.path.dirname(IPython.__file__)
305 ipdir = os.path.dirname(IPython.__file__)
305 return py3compat.cast_unicode(ipdir, fs_encoding)
306 return py3compat.cast_unicode(ipdir, fs_encoding)
306
307
307
308
308 def get_ipython_module_path(module_str):
309 def get_ipython_module_path(module_str):
309 """Find the path to an IPython module in this version of IPython.
310 """Find the path to an IPython module in this version of IPython.
310
311
311 This will always find the version of the module that is in this importable
312 This will always find the version of the module that is in this importable
312 IPython package. This will always return the path to the ``.py``
313 IPython package. This will always return the path to the ``.py``
313 version of the module.
314 version of the module.
314 """
315 """
315 if module_str == 'IPython':
316 if module_str == 'IPython':
316 return os.path.join(get_ipython_package_dir(), '__init__.py')
317 return os.path.join(get_ipython_package_dir(), '__init__.py')
317 mod = import_item(module_str)
318 mod = import_item(module_str)
318 the_path = mod.__file__.replace('.pyc', '.py')
319 the_path = mod.__file__.replace('.pyc', '.py')
319 the_path = the_path.replace('.pyo', '.py')
320 the_path = the_path.replace('.pyo', '.py')
320 return py3compat.cast_unicode(the_path, fs_encoding)
321 return py3compat.cast_unicode(the_path, fs_encoding)
321
322
322 def locate_profile(profile='default'):
323 def locate_profile(profile='default'):
323 """Find the path to the folder associated with a given profile.
324 """Find the path to the folder associated with a given profile.
324
325
325 I.e. find $IPYTHONDIR/profile_whatever.
326 I.e. find $IPYTHONDIR/profile_whatever.
326 """
327 """
327 from IPython.core.profiledir import ProfileDir, ProfileDirError
328 from IPython.core.profiledir import ProfileDir, ProfileDirError
328 try:
329 try:
329 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
330 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
330 except ProfileDirError:
331 except ProfileDirError:
331 # IOError makes more sense when people are expecting a path
332 # IOError makes more sense when people are expecting a path
332 raise IOError("Couldn't find profile %r" % profile)
333 raise IOError("Couldn't find profile %r" % profile)
333 return pd.location
334 return pd.location
334
335
335 def expand_path(s):
336 def expand_path(s):
336 """Expand $VARS and ~names in a string, like a shell
337 """Expand $VARS and ~names in a string, like a shell
337
338
338 :Examples:
339 :Examples:
339
340
340 In [2]: os.environ['FOO']='test'
341 In [2]: os.environ['FOO']='test'
341
342
342 In [3]: expand_path('variable FOO is $FOO')
343 In [3]: expand_path('variable FOO is $FOO')
343 Out[3]: 'variable FOO is test'
344 Out[3]: 'variable FOO is test'
344 """
345 """
345 # This is a pretty subtle hack. When expand user is given a UNC path
346 # This is a pretty subtle hack. When expand user is given a UNC path
346 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
347 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
347 # the $ to get (\\server\share\%username%). I think it considered $
348 # the $ to get (\\server\share\%username%). I think it considered $
348 # alone an empty var. But, we need the $ to remains there (it indicates
349 # alone an empty var. But, we need the $ to remains there (it indicates
349 # a hidden share).
350 # a hidden share).
350 if os.name=='nt':
351 if os.name=='nt':
351 s = s.replace('$\\', 'IPYTHON_TEMP')
352 s = s.replace('$\\', 'IPYTHON_TEMP')
352 s = os.path.expandvars(os.path.expanduser(s))
353 s = os.path.expandvars(os.path.expanduser(s))
353 if os.name=='nt':
354 if os.name=='nt':
354 s = s.replace('IPYTHON_TEMP', '$\\')
355 s = s.replace('IPYTHON_TEMP', '$\\')
355 return s
356 return s
356
357
357
358
359 def globlist(args):
360 """
361 Do glob expansion for each element in `args` and return a flattened list.
362
363 Unmatched glob pattern will remain as-is in the returned list.
364
365 """
366 expanded = []
367 for a in args:
368 expanded.extend(glob(a) or [a])
369 return expanded
370
371
358 def target_outdated(target,deps):
372 def target_outdated(target,deps):
359 """Determine whether a target is out of date.
373 """Determine whether a target is out of date.
360
374
361 target_outdated(target,deps) -> 1/0
375 target_outdated(target,deps) -> 1/0
362
376
363 deps: list of filenames which MUST exist.
377 deps: list of filenames which MUST exist.
364 target: single filename which may or may not exist.
378 target: single filename which may or may not exist.
365
379
366 If target doesn't exist or is older than any file listed in deps, return
380 If target doesn't exist or is older than any file listed in deps, return
367 true, otherwise return false.
381 true, otherwise return false.
368 """
382 """
369 try:
383 try:
370 target_time = os.path.getmtime(target)
384 target_time = os.path.getmtime(target)
371 except os.error:
385 except os.error:
372 return 1
386 return 1
373 for dep in deps:
387 for dep in deps:
374 dep_time = os.path.getmtime(dep)
388 dep_time = os.path.getmtime(dep)
375 if dep_time > target_time:
389 if dep_time > target_time:
376 #print "For target",target,"Dep failed:",dep # dbg
390 #print "For target",target,"Dep failed:",dep # dbg
377 #print "times (dep,tar):",dep_time,target_time # dbg
391 #print "times (dep,tar):",dep_time,target_time # dbg
378 return 1
392 return 1
379 return 0
393 return 0
380
394
381
395
382 def target_update(target,deps,cmd):
396 def target_update(target,deps,cmd):
383 """Update a target with a given command given a list of dependencies.
397 """Update a target with a given command given a list of dependencies.
384
398
385 target_update(target,deps,cmd) -> runs cmd if target is outdated.
399 target_update(target,deps,cmd) -> runs cmd if target is outdated.
386
400
387 This is just a wrapper around target_outdated() which calls the given
401 This is just a wrapper around target_outdated() which calls the given
388 command if target is outdated."""
402 command if target is outdated."""
389
403
390 if target_outdated(target,deps):
404 if target_outdated(target,deps):
391 system(cmd)
405 system(cmd)
392
406
393 def filehash(path):
407 def filehash(path):
394 """Make an MD5 hash of a file, ignoring any differences in line
408 """Make an MD5 hash of a file, ignoring any differences in line
395 ending characters."""
409 ending characters."""
396 with open(path, "rU") as f:
410 with open(path, "rU") as f:
397 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
411 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
398
412
399 # If the config is unmodified from the default, we'll just delete it.
413 # If the config is unmodified from the default, we'll just delete it.
400 # These are consistent for 0.10.x, thankfully. We're not going to worry about
414 # These are consistent for 0.10.x, thankfully. We're not going to worry about
401 # older versions.
415 # older versions.
402 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
416 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
403 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
417 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
404
418
405 def check_for_old_config(ipython_dir=None):
419 def check_for_old_config(ipython_dir=None):
406 """Check for old config files, and present a warning if they exist.
420 """Check for old config files, and present a warning if they exist.
407
421
408 A link to the docs of the new config is included in the message.
422 A link to the docs of the new config is included in the message.
409
423
410 This should mitigate confusion with the transition to the new
424 This should mitigate confusion with the transition to the new
411 config system in 0.11.
425 config system in 0.11.
412 """
426 """
413 if ipython_dir is None:
427 if ipython_dir is None:
414 ipython_dir = get_ipython_dir()
428 ipython_dir = get_ipython_dir()
415
429
416 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
430 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
417 warned = False
431 warned = False
418 for cfg in old_configs:
432 for cfg in old_configs:
419 f = os.path.join(ipython_dir, cfg)
433 f = os.path.join(ipython_dir, cfg)
420 if os.path.exists(f):
434 if os.path.exists(f):
421 if filehash(f) == old_config_md5.get(cfg, ''):
435 if filehash(f) == old_config_md5.get(cfg, ''):
422 os.unlink(f)
436 os.unlink(f)
423 else:
437 else:
424 warnings.warn("Found old IPython config file %r (modified by user)"%f)
438 warnings.warn("Found old IPython config file %r (modified by user)"%f)
425 warned = True
439 warned = True
426
440
427 if warned:
441 if warned:
428 warnings.warn("""
442 warnings.warn("""
429 The IPython configuration system has changed as of 0.11, and these files will
443 The IPython configuration system has changed as of 0.11, and these files will
430 be ignored. See http://ipython.github.com/ipython-doc/dev/config for details
444 be ignored. See http://ipython.github.com/ipython-doc/dev/config for details
431 of the new config system.
445 of the new config system.
432 To start configuring IPython, do `ipython profile create`, and edit
446 To start configuring IPython, do `ipython profile create`, and edit
433 `ipython_config.py` in <ipython_dir>/profile_default.
447 `ipython_config.py` in <ipython_dir>/profile_default.
434 If you need to leave the old config files in place for an older version of
448 If you need to leave the old config files in place for an older version of
435 IPython and want to suppress this warning message, set
449 IPython and want to suppress this warning message, set
436 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
450 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
437
451
438 def get_security_file(filename, profile='default'):
452 def get_security_file(filename, profile='default'):
439 """Return the absolute path of a security file given by filename and profile
453 """Return the absolute path of a security file given by filename and profile
440
454
441 This allows users and developers to find security files without
455 This allows users and developers to find security files without
442 knowledge of the IPython directory structure. The search path
456 knowledge of the IPython directory structure. The search path
443 will be ['.', profile.security_dir]
457 will be ['.', profile.security_dir]
444
458
445 Parameters
459 Parameters
446 ----------
460 ----------
447
461
448 filename : str
462 filename : str
449 The file to be found. If it is passed as an absolute path, it will
463 The file to be found. If it is passed as an absolute path, it will
450 simply be returned.
464 simply be returned.
451 profile : str [default: 'default']
465 profile : str [default: 'default']
452 The name of the profile to search. Leaving this unspecified
466 The name of the profile to search. Leaving this unspecified
453 The file to be found. If it is passed as an absolute path, fname will
467 The file to be found. If it is passed as an absolute path, fname will
454 simply be returned.
468 simply be returned.
455
469
456 Returns
470 Returns
457 -------
471 -------
458 Raises :exc:`IOError` if file not found or returns absolute path to file.
472 Raises :exc:`IOError` if file not found or returns absolute path to file.
459 """
473 """
460 # import here, because profiledir also imports from utils.path
474 # import here, because profiledir also imports from utils.path
461 from IPython.core.profiledir import ProfileDir
475 from IPython.core.profiledir import ProfileDir
462 try:
476 try:
463 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
477 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
464 except Exception:
478 except Exception:
465 # will raise ProfileDirError if no such profile
479 # will raise ProfileDirError if no such profile
466 raise IOError("Profile %r not found")
480 raise IOError("Profile %r not found")
467 return filefind(filename, ['.', pd.security_dir])
481 return filefind(filename, ['.', pd.security_dir])
468
482
@@ -1,446 +1,479 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.utils.path.py"""
2 """Tests for IPython.utils.path.py"""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2008-2011 The IPython Development Team
5 # Copyright (C) 2008-2011 The IPython Development Team
6 #
6 #
7 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from __future__ import with_statement
15 from __future__ import with_statement
16
16
17 import os
17 import os
18 import shutil
18 import shutil
19 import sys
19 import sys
20 import tempfile
20 import tempfile
21 from io import StringIO
21 from io import StringIO
22
22
23 from os.path import join, abspath, split
23 from os.path import join, abspath, split
24
24
25 import nose.tools as nt
25 import nose.tools as nt
26
26
27 from nose import with_setup
27 from nose import with_setup
28
28
29 import IPython
29 import IPython
30 from IPython.testing import decorators as dec
30 from IPython.testing import decorators as dec
31 from IPython.testing.decorators import skip_if_not_win32, skip_win32
31 from IPython.testing.decorators import skip_if_not_win32, skip_win32
32 from IPython.testing.tools import make_tempfile, AssertPrints
32 from IPython.testing.tools import make_tempfile, AssertPrints
33 from IPython.utils import path, io
33 from IPython.utils import path, io
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.tempdir import TemporaryDirectory
35
36
36 # Platform-dependent imports
37 # Platform-dependent imports
37 try:
38 try:
38 import _winreg as wreg
39 import _winreg as wreg
39 except ImportError:
40 except ImportError:
40 #Fake _winreg module on none windows platforms
41 #Fake _winreg module on none windows platforms
41 import types
42 import types
42 wr_name = "winreg" if py3compat.PY3 else "_winreg"
43 wr_name = "winreg" if py3compat.PY3 else "_winreg"
43 sys.modules[wr_name] = types.ModuleType(wr_name)
44 sys.modules[wr_name] = types.ModuleType(wr_name)
44 import _winreg as wreg
45 import _winreg as wreg
45 #Add entries that needs to be stubbed by the testing code
46 #Add entries that needs to be stubbed by the testing code
46 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
47 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
47
48
48 try:
49 try:
49 reload
50 reload
50 except NameError: # Python 3
51 except NameError: # Python 3
51 from imp import reload
52 from imp import reload
52
53
53 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
54 # Globals
55 # Globals
55 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
56 env = os.environ
57 env = os.environ
57 TEST_FILE_PATH = split(abspath(__file__))[0]
58 TEST_FILE_PATH = split(abspath(__file__))[0]
58 TMP_TEST_DIR = tempfile.mkdtemp()
59 TMP_TEST_DIR = tempfile.mkdtemp()
59 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
60 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
60 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
61 XDG_TEST_DIR = join(HOME_TEST_DIR, "xdg_test_dir")
61 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
62 IP_TEST_DIR = join(HOME_TEST_DIR,'.ipython')
62 #
63 #
63 # Setup/teardown functions/decorators
64 # Setup/teardown functions/decorators
64 #
65 #
65
66
66 def setup():
67 def setup():
67 """Setup testenvironment for the module:
68 """Setup testenvironment for the module:
68
69
69 - Adds dummy home dir tree
70 - Adds dummy home dir tree
70 """
71 """
71 # Do not mask exceptions here. In particular, catching WindowsError is a
72 # Do not mask exceptions here. In particular, catching WindowsError is a
72 # problem because that exception is only defined on Windows...
73 # problem because that exception is only defined on Windows...
73 os.makedirs(IP_TEST_DIR)
74 os.makedirs(IP_TEST_DIR)
74 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
75 os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
75
76
76
77
77 def teardown():
78 def teardown():
78 """Teardown testenvironment for the module:
79 """Teardown testenvironment for the module:
79
80
80 - Remove dummy home dir tree
81 - Remove dummy home dir tree
81 """
82 """
82 # Note: we remove the parent test dir, which is the root of all test
83 # Note: we remove the parent test dir, which is the root of all test
83 # subdirs we may have created. Use shutil instead of os.removedirs, so
84 # subdirs we may have created. Use shutil instead of os.removedirs, so
84 # that non-empty directories are all recursively removed.
85 # that non-empty directories are all recursively removed.
85 shutil.rmtree(TMP_TEST_DIR)
86 shutil.rmtree(TMP_TEST_DIR)
86
87
87
88
88 def setup_environment():
89 def setup_environment():
89 """Setup testenvironment for some functions that are tested
90 """Setup testenvironment for some functions that are tested
90 in this module. In particular this functions stores attributes
91 in this module. In particular this functions stores attributes
91 and other things that we need to stub in some test functions.
92 and other things that we need to stub in some test functions.
92 This needs to be done on a function level and not module level because
93 This needs to be done on a function level and not module level because
93 each testfunction needs a pristine environment.
94 each testfunction needs a pristine environment.
94 """
95 """
95 global oldstuff, platformstuff
96 global oldstuff, platformstuff
96 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
97 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
97
98
98 if os.name == 'nt':
99 if os.name == 'nt':
99 platformstuff = (wreg.OpenKey, wreg.QueryValueEx,)
100 platformstuff = (wreg.OpenKey, wreg.QueryValueEx,)
100
101
101
102
102 def teardown_environment():
103 def teardown_environment():
103 """Restore things that were remebered by the setup_environment function
104 """Restore things that were remebered by the setup_environment function
104 """
105 """
105 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
106 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
106 os.chdir(old_wd)
107 os.chdir(old_wd)
107 reload(path)
108 reload(path)
108
109
109 for key in env.keys():
110 for key in env.keys():
110 if key not in oldenv:
111 if key not in oldenv:
111 del env[key]
112 del env[key]
112 env.update(oldenv)
113 env.update(oldenv)
113 if hasattr(sys, 'frozen'):
114 if hasattr(sys, 'frozen'):
114 del sys.frozen
115 del sys.frozen
115 if os.name == 'nt':
116 if os.name == 'nt':
116 (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff
117 (wreg.OpenKey, wreg.QueryValueEx,) = platformstuff
117
118
118 # Build decorator that uses the setup_environment/setup_environment
119 # Build decorator that uses the setup_environment/setup_environment
119 with_environment = with_setup(setup_environment, teardown_environment)
120 with_environment = with_setup(setup_environment, teardown_environment)
120
121
121 @skip_if_not_win32
122 @skip_if_not_win32
122 @with_environment
123 @with_environment
123 def test_get_home_dir_1():
124 def test_get_home_dir_1():
124 """Testcase for py2exe logic, un-compressed lib
125 """Testcase for py2exe logic, un-compressed lib
125 """
126 """
126 sys.frozen = True
127 sys.frozen = True
127
128
128 #fake filename for IPython.__init__
129 #fake filename for IPython.__init__
129 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
130 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
130
131
131 home_dir = path.get_home_dir()
132 home_dir = path.get_home_dir()
132 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
133 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
133
134
134
135
135 @skip_if_not_win32
136 @skip_if_not_win32
136 @with_environment
137 @with_environment
137 def test_get_home_dir_2():
138 def test_get_home_dir_2():
138 """Testcase for py2exe logic, compressed lib
139 """Testcase for py2exe logic, compressed lib
139 """
140 """
140 sys.frozen = True
141 sys.frozen = True
141 #fake filename for IPython.__init__
142 #fake filename for IPython.__init__
142 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
143 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
143
144
144 home_dir = path.get_home_dir(True)
145 home_dir = path.get_home_dir(True)
145 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower())
146 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR).lower())
146
147
147
148
148 @with_environment
149 @with_environment
149 def test_get_home_dir_3():
150 def test_get_home_dir_3():
150 """get_home_dir() uses $HOME if set"""
151 """get_home_dir() uses $HOME if set"""
151 env["HOME"] = HOME_TEST_DIR
152 env["HOME"] = HOME_TEST_DIR
152 home_dir = path.get_home_dir(True)
153 home_dir = path.get_home_dir(True)
153 # get_home_dir expands symlinks
154 # get_home_dir expands symlinks
154 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
155 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
155
156
156
157
157 @with_environment
158 @with_environment
158 def test_get_home_dir_4():
159 def test_get_home_dir_4():
159 """get_home_dir() still works if $HOME is not set"""
160 """get_home_dir() still works if $HOME is not set"""
160
161
161 if 'HOME' in env: del env['HOME']
162 if 'HOME' in env: del env['HOME']
162 # this should still succeed, but we don't care what the answer is
163 # this should still succeed, but we don't care what the answer is
163 home = path.get_home_dir(False)
164 home = path.get_home_dir(False)
164
165
165 @with_environment
166 @with_environment
166 def test_get_home_dir_5():
167 def test_get_home_dir_5():
167 """raise HomeDirError if $HOME is specified, but not a writable dir"""
168 """raise HomeDirError if $HOME is specified, but not a writable dir"""
168 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
169 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
169 # set os.name = posix, to prevent My Documents fallback on Windows
170 # set os.name = posix, to prevent My Documents fallback on Windows
170 os.name = 'posix'
171 os.name = 'posix'
171 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
172 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
172
173
173
174
174 # Should we stub wreg fully so we can run the test on all platforms?
175 # Should we stub wreg fully so we can run the test on all platforms?
175 @skip_if_not_win32
176 @skip_if_not_win32
176 @with_environment
177 @with_environment
177 def test_get_home_dir_8():
178 def test_get_home_dir_8():
178 """Using registry hack for 'My Documents', os=='nt'
179 """Using registry hack for 'My Documents', os=='nt'
179
180
180 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
181 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
181 """
182 """
182 os.name = 'nt'
183 os.name = 'nt'
183 # Remove from stub environment all keys that may be set
184 # Remove from stub environment all keys that may be set
184 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
185 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
185 env.pop(key, None)
186 env.pop(key, None)
186
187
187 #Stub windows registry functions
188 #Stub windows registry functions
188 def OpenKey(x, y):
189 def OpenKey(x, y):
189 class key:
190 class key:
190 def Close(self):
191 def Close(self):
191 pass
192 pass
192 return key()
193 return key()
193 def QueryValueEx(x, y):
194 def QueryValueEx(x, y):
194 return [abspath(HOME_TEST_DIR)]
195 return [abspath(HOME_TEST_DIR)]
195
196
196 wreg.OpenKey = OpenKey
197 wreg.OpenKey = OpenKey
197 wreg.QueryValueEx = QueryValueEx
198 wreg.QueryValueEx = QueryValueEx
198
199
199 home_dir = path.get_home_dir()
200 home_dir = path.get_home_dir()
200 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
201 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
201
202
202
203
203 @with_environment
204 @with_environment
204 def test_get_ipython_dir_1():
205 def test_get_ipython_dir_1():
205 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
206 """test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
206 env_ipdir = os.path.join("someplace", ".ipython")
207 env_ipdir = os.path.join("someplace", ".ipython")
207 path._writable_dir = lambda path: True
208 path._writable_dir = lambda path: True
208 env['IPYTHONDIR'] = env_ipdir
209 env['IPYTHONDIR'] = env_ipdir
209 ipdir = path.get_ipython_dir()
210 ipdir = path.get_ipython_dir()
210 nt.assert_equal(ipdir, env_ipdir)
211 nt.assert_equal(ipdir, env_ipdir)
211
212
212
213
213 @with_environment
214 @with_environment
214 def test_get_ipython_dir_2():
215 def test_get_ipython_dir_2():
215 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
216 """test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
216 path.get_home_dir = lambda : "someplace"
217 path.get_home_dir = lambda : "someplace"
217 path.get_xdg_dir = lambda : None
218 path.get_xdg_dir = lambda : None
218 path._writable_dir = lambda path: True
219 path._writable_dir = lambda path: True
219 os.name = "posix"
220 os.name = "posix"
220 env.pop('IPYTHON_DIR', None)
221 env.pop('IPYTHON_DIR', None)
221 env.pop('IPYTHONDIR', None)
222 env.pop('IPYTHONDIR', None)
222 env.pop('XDG_CONFIG_HOME', None)
223 env.pop('XDG_CONFIG_HOME', None)
223 ipdir = path.get_ipython_dir()
224 ipdir = path.get_ipython_dir()
224 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
225 nt.assert_equal(ipdir, os.path.join("someplace", ".ipython"))
225
226
226 @with_environment
227 @with_environment
227 def test_get_ipython_dir_3():
228 def test_get_ipython_dir_3():
228 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
229 """test_get_ipython_dir_3, use XDG if defined, and .ipython doesn't exist."""
229 path.get_home_dir = lambda : "someplace"
230 path.get_home_dir = lambda : "someplace"
230 path._writable_dir = lambda path: True
231 path._writable_dir = lambda path: True
231 os.name = "posix"
232 os.name = "posix"
232 env.pop('IPYTHON_DIR', None)
233 env.pop('IPYTHON_DIR', None)
233 env.pop('IPYTHONDIR', None)
234 env.pop('IPYTHONDIR', None)
234 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
235 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
235 ipdir = path.get_ipython_dir()
236 ipdir = path.get_ipython_dir()
236 if sys.platform == "darwin":
237 if sys.platform == "darwin":
237 expected = os.path.join("someplace", ".ipython")
238 expected = os.path.join("someplace", ".ipython")
238 else:
239 else:
239 expected = os.path.join(XDG_TEST_DIR, "ipython")
240 expected = os.path.join(XDG_TEST_DIR, "ipython")
240 nt.assert_equal(ipdir, expected)
241 nt.assert_equal(ipdir, expected)
241
242
242 @with_environment
243 @with_environment
243 def test_get_ipython_dir_4():
244 def test_get_ipython_dir_4():
244 """test_get_ipython_dir_4, use XDG if both exist."""
245 """test_get_ipython_dir_4, use XDG if both exist."""
245 path.get_home_dir = lambda : HOME_TEST_DIR
246 path.get_home_dir = lambda : HOME_TEST_DIR
246 os.name = "posix"
247 os.name = "posix"
247 env.pop('IPYTHON_DIR', None)
248 env.pop('IPYTHON_DIR', None)
248 env.pop('IPYTHONDIR', None)
249 env.pop('IPYTHONDIR', None)
249 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
250 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
250 ipdir = path.get_ipython_dir()
251 ipdir = path.get_ipython_dir()
251 if sys.platform == "darwin":
252 if sys.platform == "darwin":
252 expected = os.path.join(HOME_TEST_DIR, ".ipython")
253 expected = os.path.join(HOME_TEST_DIR, ".ipython")
253 else:
254 else:
254 expected = os.path.join(XDG_TEST_DIR, "ipython")
255 expected = os.path.join(XDG_TEST_DIR, "ipython")
255 nt.assert_equal(ipdir, expected)
256 nt.assert_equal(ipdir, expected)
256
257
257 @with_environment
258 @with_environment
258 def test_get_ipython_dir_5():
259 def test_get_ipython_dir_5():
259 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
260 """test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
260 path.get_home_dir = lambda : HOME_TEST_DIR
261 path.get_home_dir = lambda : HOME_TEST_DIR
261 os.name = "posix"
262 os.name = "posix"
262 env.pop('IPYTHON_DIR', None)
263 env.pop('IPYTHON_DIR', None)
263 env.pop('IPYTHONDIR', None)
264 env.pop('IPYTHONDIR', None)
264 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
265 env['XDG_CONFIG_HOME'] = XDG_TEST_DIR
265 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
266 os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
266 ipdir = path.get_ipython_dir()
267 ipdir = path.get_ipython_dir()
267 nt.assert_equal(ipdir, IP_TEST_DIR)
268 nt.assert_equal(ipdir, IP_TEST_DIR)
268
269
269 @with_environment
270 @with_environment
270 def test_get_ipython_dir_6():
271 def test_get_ipython_dir_6():
271 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
272 """test_get_ipython_dir_6, use XDG if defined and neither exist."""
272 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
273 xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
273 os.mkdir(xdg)
274 os.mkdir(xdg)
274 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
275 shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
275 path.get_home_dir = lambda : HOME_TEST_DIR
276 path.get_home_dir = lambda : HOME_TEST_DIR
276 path.get_xdg_dir = lambda : xdg
277 path.get_xdg_dir = lambda : xdg
277 os.name = "posix"
278 os.name = "posix"
278 env.pop('IPYTHON_DIR', None)
279 env.pop('IPYTHON_DIR', None)
279 env.pop('IPYTHONDIR', None)
280 env.pop('IPYTHONDIR', None)
280 env.pop('XDG_CONFIG_HOME', None)
281 env.pop('XDG_CONFIG_HOME', None)
281 xdg_ipdir = os.path.join(xdg, "ipython")
282 xdg_ipdir = os.path.join(xdg, "ipython")
282 ipdir = path.get_ipython_dir()
283 ipdir = path.get_ipython_dir()
283 nt.assert_equal(ipdir, xdg_ipdir)
284 nt.assert_equal(ipdir, xdg_ipdir)
284
285
285 @with_environment
286 @with_environment
286 def test_get_ipython_dir_7():
287 def test_get_ipython_dir_7():
287 """test_get_ipython_dir_7, test home directory expansion on IPYTHONDIR"""
288 """test_get_ipython_dir_7, test home directory expansion on IPYTHONDIR"""
288 path._writable_dir = lambda path: True
289 path._writable_dir = lambda path: True
289 home_dir = os.path.normpath(os.path.expanduser('~'))
290 home_dir = os.path.normpath(os.path.expanduser('~'))
290 env['IPYTHONDIR'] = os.path.join('~', 'somewhere')
291 env['IPYTHONDIR'] = os.path.join('~', 'somewhere')
291 ipdir = path.get_ipython_dir()
292 ipdir = path.get_ipython_dir()
292 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
293 nt.assert_equal(ipdir, os.path.join(home_dir, 'somewhere'))
293
294
294
295
295 @with_environment
296 @with_environment
296 def test_get_xdg_dir_0():
297 def test_get_xdg_dir_0():
297 """test_get_xdg_dir_0, check xdg_dir"""
298 """test_get_xdg_dir_0, check xdg_dir"""
298 reload(path)
299 reload(path)
299 path._writable_dir = lambda path: True
300 path._writable_dir = lambda path: True
300 path.get_home_dir = lambda : 'somewhere'
301 path.get_home_dir = lambda : 'somewhere'
301 os.name = "posix"
302 os.name = "posix"
302 sys.platform = "linux2"
303 sys.platform = "linux2"
303 env.pop('IPYTHON_DIR', None)
304 env.pop('IPYTHON_DIR', None)
304 env.pop('IPYTHONDIR', None)
305 env.pop('IPYTHONDIR', None)
305 env.pop('XDG_CONFIG_HOME', None)
306 env.pop('XDG_CONFIG_HOME', None)
306
307
307 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
308 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
308
309
309
310
310 @with_environment
311 @with_environment
311 def test_get_xdg_dir_1():
312 def test_get_xdg_dir_1():
312 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
313 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
313 reload(path)
314 reload(path)
314 path.get_home_dir = lambda : HOME_TEST_DIR
315 path.get_home_dir = lambda : HOME_TEST_DIR
315 os.name = "posix"
316 os.name = "posix"
316 sys.platform = "linux2"
317 sys.platform = "linux2"
317 env.pop('IPYTHON_DIR', None)
318 env.pop('IPYTHON_DIR', None)
318 env.pop('IPYTHONDIR', None)
319 env.pop('IPYTHONDIR', None)
319 env.pop('XDG_CONFIG_HOME', None)
320 env.pop('XDG_CONFIG_HOME', None)
320 nt.assert_equal(path.get_xdg_dir(), None)
321 nt.assert_equal(path.get_xdg_dir(), None)
321
322
322 @with_environment
323 @with_environment
323 def test_get_xdg_dir_2():
324 def test_get_xdg_dir_2():
324 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
325 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
325 reload(path)
326 reload(path)
326 path.get_home_dir = lambda : HOME_TEST_DIR
327 path.get_home_dir = lambda : HOME_TEST_DIR
327 os.name = "posix"
328 os.name = "posix"
328 sys.platform = "linux2"
329 sys.platform = "linux2"
329 env.pop('IPYTHON_DIR', None)
330 env.pop('IPYTHON_DIR', None)
330 env.pop('IPYTHONDIR', None)
331 env.pop('IPYTHONDIR', None)
331 env.pop('XDG_CONFIG_HOME', None)
332 env.pop('XDG_CONFIG_HOME', None)
332 cfgdir=os.path.join(path.get_home_dir(), '.config')
333 cfgdir=os.path.join(path.get_home_dir(), '.config')
333 if not os.path.exists(cfgdir):
334 if not os.path.exists(cfgdir):
334 os.makedirs(cfgdir)
335 os.makedirs(cfgdir)
335
336
336 nt.assert_equal(path.get_xdg_dir(), cfgdir)
337 nt.assert_equal(path.get_xdg_dir(), cfgdir)
337
338
338 @with_environment
339 @with_environment
339 def test_get_xdg_dir_3():
340 def test_get_xdg_dir_3():
340 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
341 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
341 reload(path)
342 reload(path)
342 path.get_home_dir = lambda : HOME_TEST_DIR
343 path.get_home_dir = lambda : HOME_TEST_DIR
343 os.name = "posix"
344 os.name = "posix"
344 sys.platform = "darwin"
345 sys.platform = "darwin"
345 env.pop('IPYTHON_DIR', None)
346 env.pop('IPYTHON_DIR', None)
346 env.pop('IPYTHONDIR', None)
347 env.pop('IPYTHONDIR', None)
347 env.pop('XDG_CONFIG_HOME', None)
348 env.pop('XDG_CONFIG_HOME', None)
348 cfgdir=os.path.join(path.get_home_dir(), '.config')
349 cfgdir=os.path.join(path.get_home_dir(), '.config')
349 if not os.path.exists(cfgdir):
350 if not os.path.exists(cfgdir):
350 os.makedirs(cfgdir)
351 os.makedirs(cfgdir)
351
352
352 nt.assert_equal(path.get_xdg_dir(), None)
353 nt.assert_equal(path.get_xdg_dir(), None)
353
354
354 def test_filefind():
355 def test_filefind():
355 """Various tests for filefind"""
356 """Various tests for filefind"""
356 f = tempfile.NamedTemporaryFile()
357 f = tempfile.NamedTemporaryFile()
357 # print 'fname:',f.name
358 # print 'fname:',f.name
358 alt_dirs = path.get_ipython_dir()
359 alt_dirs = path.get_ipython_dir()
359 t = path.filefind(f.name, alt_dirs)
360 t = path.filefind(f.name, alt_dirs)
360 # print 'found:',t
361 # print 'found:',t
361
362
362
363
363 def test_get_ipython_package_dir():
364 def test_get_ipython_package_dir():
364 ipdir = path.get_ipython_package_dir()
365 ipdir = path.get_ipython_package_dir()
365 nt.assert_true(os.path.isdir(ipdir))
366 nt.assert_true(os.path.isdir(ipdir))
366
367
367
368
368 def test_get_ipython_module_path():
369 def test_get_ipython_module_path():
369 ipapp_path = path.get_ipython_module_path('IPython.frontend.terminal.ipapp')
370 ipapp_path = path.get_ipython_module_path('IPython.frontend.terminal.ipapp')
370 nt.assert_true(os.path.isfile(ipapp_path))
371 nt.assert_true(os.path.isfile(ipapp_path))
371
372
372
373
373 @dec.skip_if_not_win32
374 @dec.skip_if_not_win32
374 def test_get_long_path_name_win32():
375 def test_get_long_path_name_win32():
375 p = path.get_long_path_name('c:\\docume~1')
376 p = path.get_long_path_name('c:\\docume~1')
376 nt.assert_equals(p,u'c:\\Documents and Settings')
377 nt.assert_equals(p,u'c:\\Documents and Settings')
377
378
378
379
379 @dec.skip_win32
380 @dec.skip_win32
380 def test_get_long_path_name():
381 def test_get_long_path_name():
381 p = path.get_long_path_name('/usr/local')
382 p = path.get_long_path_name('/usr/local')
382 nt.assert_equals(p,'/usr/local')
383 nt.assert_equals(p,'/usr/local')
383
384
384 @dec.skip_win32 # can't create not-user-writable dir on win
385 @dec.skip_win32 # can't create not-user-writable dir on win
385 @with_environment
386 @with_environment
386 def test_not_writable_ipdir():
387 def test_not_writable_ipdir():
387 tmpdir = tempfile.mkdtemp()
388 tmpdir = tempfile.mkdtemp()
388 os.name = "posix"
389 os.name = "posix"
389 env.pop('IPYTHON_DIR', None)
390 env.pop('IPYTHON_DIR', None)
390 env.pop('IPYTHONDIR', None)
391 env.pop('IPYTHONDIR', None)
391 env.pop('XDG_CONFIG_HOME', None)
392 env.pop('XDG_CONFIG_HOME', None)
392 env['HOME'] = tmpdir
393 env['HOME'] = tmpdir
393 ipdir = os.path.join(tmpdir, '.ipython')
394 ipdir = os.path.join(tmpdir, '.ipython')
394 os.mkdir(ipdir)
395 os.mkdir(ipdir)
395 os.chmod(ipdir, 600)
396 os.chmod(ipdir, 600)
396 with AssertPrints('is not a writable location', channel='stderr'):
397 with AssertPrints('is not a writable location', channel='stderr'):
397 ipdir = path.get_ipython_dir()
398 ipdir = path.get_ipython_dir()
398 env.pop('IPYTHON_DIR', None)
399 env.pop('IPYTHON_DIR', None)
399
400
400 def test_unquote_filename():
401 def test_unquote_filename():
401 for win32 in (True, False):
402 for win32 in (True, False):
402 nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py')
403 nt.assert_equals(path.unquote_filename('foo.py', win32=win32), 'foo.py')
403 nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
404 nt.assert_equals(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
404 nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
405 nt.assert_equals(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
405 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
406 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
406 nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
407 nt.assert_equals(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
407 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
408 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
408 nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
409 nt.assert_equals(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
409 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
410 nt.assert_equals(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
410 nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
411 nt.assert_equals(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
411 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
412 nt.assert_equals(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
412
413
413 @with_environment
414 @with_environment
414 def test_get_py_filename():
415 def test_get_py_filename():
415 os.chdir(TMP_TEST_DIR)
416 os.chdir(TMP_TEST_DIR)
416 for win32 in (True, False):
417 for win32 in (True, False):
417 with make_tempfile('foo.py'):
418 with make_tempfile('foo.py'):
418 nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
419 nt.assert_equals(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
419 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py')
420 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo.py')
420 with make_tempfile('foo'):
421 with make_tempfile('foo'):
421 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo')
422 nt.assert_equals(path.get_py_filename('foo', force_win32=win32), 'foo')
422 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
423 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
423 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
424 nt.assert_raises(IOError, path.get_py_filename, 'foo', force_win32=win32)
424 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
425 nt.assert_raises(IOError, path.get_py_filename, 'foo.py', force_win32=win32)
425 true_fn = 'foo with spaces.py'
426 true_fn = 'foo with spaces.py'
426 with make_tempfile(true_fn):
427 with make_tempfile(true_fn):
427 nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
428 nt.assert_equals(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
428 nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
429 nt.assert_equals(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
429 if win32:
430 if win32:
430 nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
431 nt.assert_equals(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
431 nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
432 nt.assert_equals(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
432 else:
433 else:
433 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
434 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"', force_win32=False)
434 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
435 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'", force_win32=False)
435
436
436 def test_unicode_in_filename():
437 def test_unicode_in_filename():
437 """When a file doesn't exist, the exception raised should be safe to call
438 """When a file doesn't exist, the exception raised should be safe to call
438 str() on - i.e. in Python 2 it must only have ASCII characters.
439 str() on - i.e. in Python 2 it must only have ASCII characters.
439
440
440 https://github.com/ipython/ipython/issues/875
441 https://github.com/ipython/ipython/issues/875
441 """
442 """
442 try:
443 try:
443 # these calls should not throw unicode encode exceptions
444 # these calls should not throw unicode encode exceptions
444 path.get_py_filename(u'fooéè.py', force_win32=False)
445 path.get_py_filename(u'fooéè.py', force_win32=False)
445 except IOError as ex:
446 except IOError as ex:
446 str(ex)
447 str(ex)
448
449
450 def test_globlist():
451 """Test glob expansion for %run magic."""
452 filenames_start_with_a = map('a{0}'.format, range(3))
453 filenames_end_with_b = map('{0}b'.format, range(3))
454 filenames = filenames_start_with_a + filenames_end_with_b
455
456 with TemporaryDirectory() as td:
457 save = os.getcwdu()
458 try:
459 os.chdir(td)
460
461 # Create empty files
462 for fname in filenames:
463 open(os.path.join(td, fname), 'w').close()
464
465 def assert_match(patterns, matches):
466 # glob returns unordered list. that's why sorted is required.
467 nt.assert_equals(sorted(path.globlist(patterns)),
468 sorted(matches))
469
470 assert_match(['*'], filenames)
471 assert_match(['a*'], filenames_start_with_a)
472 assert_match(['*c'], ['*c'])
473 assert_match(['*', 'a*', '*b', '*c'],
474 filenames
475 + filenames_start_with_a
476 + filenames_end_with_b
477 + ['*c'])
478 finally:
479 os.chdir(save)
General Comments 0
You need to be logged in to leave comments. Login now