##// END OF EJS Templates
Merge pull request #2165 from tkf/run-glob...
Bradley M. Froehle -
r8544:e54a60bc merge
parent child Browse files
Show More
@@ -0,0 +1,2 b''
1 import sys
2 print sys.argv[1:]
@@ -1,1016 +1,1030 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
22
23 # cProfile was added in Python2.5
23 # cProfile was added in Python2.5
24 try:
24 try:
25 import cProfile as profile
25 import cProfile as profile
26 import pstats
26 import pstats
27 except ImportError:
27 except ImportError:
28 # profile isn't bundled by default in Debian for license reasons
28 # profile isn't bundled by default in Debian for license reasons
29 try:
29 try:
30 import profile, pstats
30 import profile, pstats
31 except ImportError:
31 except ImportError:
32 profile = pstats = None
32 profile = pstats = None
33
33
34 # Our own packages
34 # Our own packages
35 from IPython.core import debugger, oinspect
35 from IPython.core import debugger, oinspect
36 from IPython.core import magic_arguments
36 from IPython.core import magic_arguments
37 from IPython.core import page
37 from IPython.core import page
38 from IPython.core.error import UsageError
38 from IPython.core.error import UsageError
39 from IPython.core.macro import Macro
39 from IPython.core.macro import Macro
40 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,
41 line_cell_magic, on_off, needs_local_scope)
41 line_cell_magic, on_off, needs_local_scope)
42 from IPython.testing.skipdoctest import skip_doctest
42 from IPython.testing.skipdoctest import skip_doctest
43 from IPython.utils import py3compat
43 from IPython.utils import py3compat
44 from IPython.utils.io import capture_output
44 from IPython.utils.io import capture_output
45 from IPython.utils.ipstruct import Struct
45 from IPython.utils.ipstruct import Struct
46 from IPython.utils.module_paths import find_mod
46 from IPython.utils.module_paths import find_mod
47 from IPython.utils.path import get_py_filename, unquote_filename
47 from IPython.utils.path import get_py_filename, unquote_filename, shellglob
48 from IPython.utils.timing import clock, clock2
48 from IPython.utils.timing import clock, clock2
49 from IPython.utils.warn import warn, error
49 from IPython.utils.warn import warn, error
50
50
51
51 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
52 # Magic implementation classes
53 # Magic implementation classes
53 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
54
55
55 @magics_class
56 @magics_class
56 class ExecutionMagics(Magics):
57 class ExecutionMagics(Magics):
57 """Magics related to code execution, debugging, profiling, etc.
58 """Magics related to code execution, debugging, profiling, etc.
58
59
59 """
60 """
60
61
61 def __init__(self, shell):
62 def __init__(self, shell):
62 super(ExecutionMagics, self).__init__(shell)
63 super(ExecutionMagics, self).__init__(shell)
63 if profile is None:
64 if profile is None:
64 self.prun = self.profile_missing_notice
65 self.prun = self.profile_missing_notice
65 # Default execution function used to actually run user code.
66 # Default execution function used to actually run user code.
66 self.default_runner = None
67 self.default_runner = None
67
68
68 def profile_missing_notice(self, *args, **kwargs):
69 def profile_missing_notice(self, *args, **kwargs):
69 error("""\
70 error("""\
70 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
71 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
72 python-profiler package from non-free.""")
73 python-profiler package from non-free.""")
73
74
74 @skip_doctest
75 @skip_doctest
75 @line_cell_magic
76 @line_cell_magic
76 def prun(self, parameter_s='', cell=None, user_mode=True,
77 def prun(self, parameter_s='', cell=None, user_mode=True,
77 opts=None,arg_lst=None,prog_ns=None):
78 opts=None,arg_lst=None,prog_ns=None):
78
79
79 """Run a statement through the python code profiler.
80 """Run a statement through the python code profiler.
80
81
81 Usage, in line mode:
82 Usage, in line mode:
82 %prun [options] statement
83 %prun [options] statement
83
84
84 Usage, in cell mode:
85 Usage, in cell mode:
85 %%prun [options] [statement]
86 %%prun [options] [statement]
86 code...
87 code...
87 code...
88 code...
88
89
89 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
90 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
91 profile multiline blocks without having to put them in a separate
92 profile multiline blocks without having to put them in a separate
92 function.
93 function.
93
94
94 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
95 python profiler in a manner similar to the profile.run() function.
96 python profiler in a manner similar to the profile.run() function.
96 Namespaces are internally managed to work correctly; profile.run
97 Namespaces are internally managed to work correctly; profile.run
97 cannot be used in IPython because it makes certain assumptions about
98 cannot be used in IPython because it makes certain assumptions about
98 namespaces which do not hold under IPython.
99 namespaces which do not hold under IPython.
99
100
100 Options:
101 Options:
101
102
102 -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
103 profile gets printed. The limit value can be:
104 profile gets printed. The limit value can be:
104
105
105 * A string: only information for function names containing this string
106 * A string: only information for function names containing this string
106 is printed.
107 is printed.
107
108
108 * An integer: only these many lines are printed.
109 * An integer: only these many lines are printed.
109
110
110 * 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
111 (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).
112
113
113 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
114 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
115 information about class constructors.
116 information about class constructors.
116
117
117 -r: return the pstats.Stats object generated by the profiling. This
118 -r: return the pstats.Stats object generated by the profiling. This
118 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
119 later use it for further analysis or in other functions.
120 later use it for further analysis or in other functions.
120
121
121 -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
122 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
123 default sorting key is 'time'.
124 default sorting key is 'time'.
124
125
125 The following is copied verbatim from the profile documentation
126 The following is copied verbatim from the profile documentation
126 referenced below:
127 referenced below:
127
128
128 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
129 secondary criteria when the there is equality in all keys selected
130 secondary criteria when the there is equality in all keys selected
130 before them.
131 before them.
131
132
132 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
133 abbreviation is unambiguous. The following are the keys currently
134 abbreviation is unambiguous. The following are the keys currently
134 defined:
135 defined:
135
136
136 Valid Arg Meaning
137 Valid Arg Meaning
137 "calls" call count
138 "calls" call count
138 "cumulative" cumulative time
139 "cumulative" cumulative time
139 "file" file name
140 "file" file name
140 "module" file name
141 "module" file name
141 "pcalls" primitive call count
142 "pcalls" primitive call count
142 "line" line number
143 "line" line number
143 "name" function name
144 "name" function name
144 "nfl" name/file/line
145 "nfl" name/file/line
145 "stdname" standard name
146 "stdname" standard name
146 "time" internal time
147 "time" internal time
147
148
148 Note that all sorts on statistics are in descending order (placing
149 Note that all sorts on statistics are in descending order (placing
149 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
150 searches are in ascending order (i.e., alphabetical). The subtle
151 searches are in ascending order (i.e., alphabetical). The subtle
151 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
152 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
153 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
154 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
155 "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
156 line numbers. In fact, sort_stats("nfl") is the same as
157 line numbers. In fact, sort_stats("nfl") is the same as
157 sort_stats("name", "file", "line").
158 sort_stats("name", "file", "line").
158
159
159 -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
160 file. The profile is still shown on screen.
161 file. The profile is still shown on screen.
161
162
162 -D <filename>: save (via dump_stats) profile statistics to given
163 -D <filename>: save (via dump_stats) profile statistics to given
163 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
164 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
165 objects. The profile is still shown on screen.
166 objects. The profile is still shown on screen.
166
167
167 -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.
168
169
169 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
170 '%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
171 contains profiler specific options as described here.
172 contains profiler specific options as described here.
172
173
173 You can read the complete documentation for the profile module with::
174 You can read the complete documentation for the profile module with::
174
175
175 In [1]: import profile; profile.help()
176 In [1]: import profile; profile.help()
176 """
177 """
177
178
178 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
179 opts_def = Struct(D=[''],l=[],s=['time'],T=[''])
179
180
180 if user_mode: # regular user call
181 if user_mode: # regular user call
181 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',
182 list_all=True, posix=False)
183 list_all=True, posix=False)
183 namespace = self.shell.user_ns
184 namespace = self.shell.user_ns
184 if cell is not None:
185 if cell is not None:
185 arg_str += '\n' + cell
186 arg_str += '\n' + cell
186 else: # called to run a program by %run -p
187 else: # called to run a program by %run -p
187 try:
188 try:
188 filename = get_py_filename(arg_lst[0])
189 filename = get_py_filename(arg_lst[0])
189 except IOError as e:
190 except IOError as e:
190 try:
191 try:
191 msg = str(e)
192 msg = str(e)
192 except UnicodeError:
193 except UnicodeError:
193 msg = e.message
194 msg = e.message
194 error(msg)
195 error(msg)
195 return
196 return
196
197
197 arg_str = 'execfile(filename,prog_ns)'
198 arg_str = 'execfile(filename,prog_ns)'
198 namespace = {
199 namespace = {
199 'execfile': self.shell.safe_execfile,
200 'execfile': self.shell.safe_execfile,
200 'prog_ns': prog_ns,
201 'prog_ns': prog_ns,
201 'filename': filename
202 'filename': filename
202 }
203 }
203
204
204 opts.merge(opts_def)
205 opts.merge(opts_def)
205
206
206 prof = profile.Profile()
207 prof = profile.Profile()
207 try:
208 try:
208 prof = prof.runctx(arg_str,namespace,namespace)
209 prof = prof.runctx(arg_str,namespace,namespace)
209 sys_exit = ''
210 sys_exit = ''
210 except SystemExit:
211 except SystemExit:
211 sys_exit = """*** SystemExit exception caught in code being profiled."""
212 sys_exit = """*** SystemExit exception caught in code being profiled."""
212
213
213 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
214 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
214
215
215 lims = opts.l
216 lims = opts.l
216 if lims:
217 if lims:
217 lims = [] # rebuild lims with ints/floats/strings
218 lims = [] # rebuild lims with ints/floats/strings
218 for lim in opts.l:
219 for lim in opts.l:
219 try:
220 try:
220 lims.append(int(lim))
221 lims.append(int(lim))
221 except ValueError:
222 except ValueError:
222 try:
223 try:
223 lims.append(float(lim))
224 lims.append(float(lim))
224 except ValueError:
225 except ValueError:
225 lims.append(lim)
226 lims.append(lim)
226
227
227 # Trap output.
228 # Trap output.
228 stdout_trap = StringIO()
229 stdout_trap = StringIO()
229 stats_stream = stats.stream
230 stats_stream = stats.stream
230 try:
231 try:
231 stats.stream = stdout_trap
232 stats.stream = stdout_trap
232 stats.print_stats(*lims)
233 stats.print_stats(*lims)
233 finally:
234 finally:
234 stats.stream = stats_stream
235 stats.stream = stats_stream
235
236
236 output = stdout_trap.getvalue()
237 output = stdout_trap.getvalue()
237 output = output.rstrip()
238 output = output.rstrip()
238
239
239 if 'q' not in opts:
240 if 'q' not in opts:
240 page.page(output)
241 page.page(output)
241 print sys_exit,
242 print sys_exit,
242
243
243 dump_file = opts.D[0]
244 dump_file = opts.D[0]
244 text_file = opts.T[0]
245 text_file = opts.T[0]
245 if dump_file:
246 if dump_file:
246 dump_file = unquote_filename(dump_file)
247 dump_file = unquote_filename(dump_file)
247 prof.dump_stats(dump_file)
248 prof.dump_stats(dump_file)
248 print '\n*** Profile stats marshalled to file',\
249 print '\n*** Profile stats marshalled to file',\
249 repr(dump_file)+'.',sys_exit
250 repr(dump_file)+'.',sys_exit
250 if text_file:
251 if text_file:
251 text_file = unquote_filename(text_file)
252 text_file = unquote_filename(text_file)
252 pfile = open(text_file,'w')
253 pfile = open(text_file,'w')
253 pfile.write(output)
254 pfile.write(output)
254 pfile.close()
255 pfile.close()
255 print '\n*** Profile printout saved to text file',\
256 print '\n*** Profile printout saved to text file',\
256 repr(text_file)+'.',sys_exit
257 repr(text_file)+'.',sys_exit
257
258
258 if 'r' in opts:
259 if 'r' in opts:
259 return stats
260 return stats
260 else:
261 else:
261 return None
262 return None
262
263
263 @line_magic
264 @line_magic
264 def pdb(self, parameter_s=''):
265 def pdb(self, parameter_s=''):
265 """Control the automatic calling of the pdb interactive debugger.
266 """Control the automatic calling of the pdb interactive debugger.
266
267
267 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
268 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
268 argument it works as a toggle.
269 argument it works as a toggle.
269
270
270 When an exception is triggered, IPython can optionally call the
271 When an exception is triggered, IPython can optionally call the
271 interactive pdb debugger after the traceback printout. %pdb toggles
272 interactive pdb debugger after the traceback printout. %pdb toggles
272 this feature on and off.
273 this feature on and off.
273
274
274 The initial state of this feature is set in your configuration
275 The initial state of this feature is set in your configuration
275 file (the option is ``InteractiveShell.pdb``).
276 file (the option is ``InteractiveShell.pdb``).
276
277
277 If you want to just activate the debugger AFTER an exception has fired,
278 If you want to just activate the debugger AFTER an exception has fired,
278 without having to type '%pdb on' and rerunning your code, you can use
279 without having to type '%pdb on' and rerunning your code, you can use
279 the %debug magic."""
280 the %debug magic."""
280
281
281 par = parameter_s.strip().lower()
282 par = parameter_s.strip().lower()
282
283
283 if par:
284 if par:
284 try:
285 try:
285 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
286 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
286 except KeyError:
287 except KeyError:
287 print ('Incorrect argument. Use on/1, off/0, '
288 print ('Incorrect argument. Use on/1, off/0, '
288 'or nothing for a toggle.')
289 'or nothing for a toggle.')
289 return
290 return
290 else:
291 else:
291 # toggle
292 # toggle
292 new_pdb = not self.shell.call_pdb
293 new_pdb = not self.shell.call_pdb
293
294
294 # set on the shell
295 # set on the shell
295 self.shell.call_pdb = new_pdb
296 self.shell.call_pdb = new_pdb
296 print 'Automatic pdb calling has been turned',on_off(new_pdb)
297 print 'Automatic pdb calling has been turned',on_off(new_pdb)
297
298
298 @line_magic
299 @line_magic
299 def debug(self, parameter_s=''):
300 def debug(self, parameter_s=''):
300 """Activate the interactive debugger in post-mortem mode.
301 """Activate the interactive debugger in post-mortem mode.
301
302
302 If an exception has just occurred, this lets you inspect its stack
303 If an exception has just occurred, this lets you inspect its stack
303 frames interactively. Note that this will always work only on the last
304 frames interactively. Note that this will always work only on the last
304 traceback that occurred, so you must call this quickly after an
305 traceback that occurred, so you must call this quickly after an
305 exception that you wish to inspect has fired, because if another one
306 exception that you wish to inspect has fired, because if another one
306 occurs, it clobbers the previous one.
307 occurs, it clobbers the previous one.
307
308
308 If you want IPython to automatically do this on every exception, see
309 If you want IPython to automatically do this on every exception, see
309 the %pdb magic for more details.
310 the %pdb magic for more details.
310 """
311 """
311 self.shell.debugger(force=True)
312 self.shell.debugger(force=True)
312
313
313 @line_magic
314 @line_magic
314 def tb(self, s):
315 def tb(self, s):
315 """Print the last traceback with the currently active exception mode.
316 """Print the last traceback with the currently active exception mode.
316
317
317 See %xmode for changing exception reporting modes."""
318 See %xmode for changing exception reporting modes."""
318 self.shell.showtraceback()
319 self.shell.showtraceback()
319
320
320 @skip_doctest
321 @skip_doctest
321 @line_magic
322 @line_magic
322 def run(self, parameter_s='', runner=None,
323 def run(self, parameter_s='', runner=None,
323 file_finder=get_py_filename):
324 file_finder=get_py_filename):
324 """Run the named file inside IPython as a program.
325 """Run the named file inside IPython as a program.
325
326
326 Usage:\\
327 Usage:\\
327 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options]] file [args]
328 %run [-n -i -t [-N<N>] -d [-b<N>] -p [profile options] -G] file [args]
328
329
329 Parameters after the filename are passed as command-line arguments to
330 Parameters after the filename are passed as command-line arguments to
330 the program (put in sys.argv). Then, control returns to IPython's
331 the program (put in sys.argv). Then, control returns to IPython's
331 prompt.
332 prompt.
332
333
333 This is similar to running at a system prompt:\\
334 This is similar to running at a system prompt:\\
334 $ python file args\\
335 $ python file args\\
335 but with the advantage of giving you IPython's tracebacks, and of
336 but with the advantage of giving you IPython's tracebacks, and of
336 loading all variables into your interactive namespace for further use
337 loading all variables into your interactive namespace for further use
337 (unless -p is used, see below).
338 (unless -p is used, see below).
338
339
339 The file is executed in a namespace initially consisting only of
340 The file is executed in a namespace initially consisting only of
340 __name__=='__main__' and sys.argv constructed as indicated. It thus
341 __name__=='__main__' and sys.argv constructed as indicated. It thus
341 sees its environment as if it were being run as a stand-alone program
342 sees its environment as if it were being run as a stand-alone program
342 (except for sharing global objects such as previously imported
343 (except for sharing global objects such as previously imported
343 modules). But after execution, the IPython interactive namespace gets
344 modules). But after execution, the IPython interactive namespace gets
344 updated with all variables defined in the program (except for __name__
345 updated with all variables defined in the program (except for __name__
345 and sys.argv). This allows for very convenient loading of code for
346 and sys.argv). This allows for very convenient loading of code for
346 interactive work, while giving each program a 'clean sheet' to run in.
347 interactive work, while giving each program a 'clean sheet' to run in.
347
348
349 Arguments are expanded using shell-like glob match. Patterns
350 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
351 tilde '~' will be expanded into user's home directory. Unlike
352 real shells, quotation does not suppress expansions. Use
353 *two* back slashes (e.g., '\\\\*') to suppress expansions.
354 To completely disable these expansions, you can use -G flag.
355
348 Options:
356 Options:
349
357
350 -n: __name__ is NOT set to '__main__', but to the running file's name
358 -n: __name__ is NOT set to '__main__', but to the running file's name
351 without extension (as python does under import). This allows running
359 without extension (as python does under import). This allows running
352 scripts and reloading the definitions in them without calling code
360 scripts and reloading the definitions in them without calling code
353 protected by an ' if __name__ == "__main__" ' clause.
361 protected by an ' if __name__ == "__main__" ' clause.
354
362
355 -i: run the file in IPython's namespace instead of an empty one. This
363 -i: run the file in IPython's namespace instead of an empty one. This
356 is useful if you are experimenting with code written in a text editor
364 is useful if you are experimenting with code written in a text editor
357 which depends on variables defined interactively.
365 which depends on variables defined interactively.
358
366
359 -e: ignore sys.exit() calls or SystemExit exceptions in the script
367 -e: ignore sys.exit() calls or SystemExit exceptions in the script
360 being run. This is particularly useful if IPython is being used to
368 being run. This is particularly useful if IPython is being used to
361 run unittests, which always exit with a sys.exit() call. In such
369 run unittests, which always exit with a sys.exit() call. In such
362 cases you are interested in the output of the test results, not in
370 cases you are interested in the output of the test results, not in
363 seeing a traceback of the unittest module.
371 seeing a traceback of the unittest module.
364
372
365 -t: print timing information at the end of the run. IPython will give
373 -t: print timing information at the end of the run. IPython will give
366 you an estimated CPU time consumption for your script, which under
374 you an estimated CPU time consumption for your script, which under
367 Unix uses the resource module to avoid the wraparound problems of
375 Unix uses the resource module to avoid the wraparound problems of
368 time.clock(). Under Unix, an estimate of time spent on system tasks
376 time.clock(). Under Unix, an estimate of time spent on system tasks
369 is also given (for Windows platforms this is reported as 0.0).
377 is also given (for Windows platforms this is reported as 0.0).
370
378
371 If -t is given, an additional -N<N> option can be given, where <N>
379 If -t is given, an additional -N<N> option can be given, where <N>
372 must be an integer indicating how many times you want the script to
380 must be an integer indicating how many times you want the script to
373 run. The final timing report will include total and per run results.
381 run. The final timing report will include total and per run results.
374
382
375 For example (testing the script uniq_stable.py)::
383 For example (testing the script uniq_stable.py)::
376
384
377 In [1]: run -t uniq_stable
385 In [1]: run -t uniq_stable
378
386
379 IPython CPU timings (estimated):\\
387 IPython CPU timings (estimated):\\
380 User : 0.19597 s.\\
388 User : 0.19597 s.\\
381 System: 0.0 s.\\
389 System: 0.0 s.\\
382
390
383 In [2]: run -t -N5 uniq_stable
391 In [2]: run -t -N5 uniq_stable
384
392
385 IPython CPU timings (estimated):\\
393 IPython CPU timings (estimated):\\
386 Total runs performed: 5\\
394 Total runs performed: 5\\
387 Times : Total Per run\\
395 Times : Total Per run\\
388 User : 0.910862 s, 0.1821724 s.\\
396 User : 0.910862 s, 0.1821724 s.\\
389 System: 0.0 s, 0.0 s.
397 System: 0.0 s, 0.0 s.
390
398
391 -d: run your program under the control of pdb, the Python debugger.
399 -d: run your program under the control of pdb, the Python debugger.
392 This allows you to execute your program step by step, watch variables,
400 This allows you to execute your program step by step, watch variables,
393 etc. Internally, what IPython does is similar to calling:
401 etc. Internally, what IPython does is similar to calling:
394
402
395 pdb.run('execfile("YOURFILENAME")')
403 pdb.run('execfile("YOURFILENAME")')
396
404
397 with a breakpoint set on line 1 of your file. You can change the line
405 with a breakpoint set on line 1 of your file. You can change the line
398 number for this automatic breakpoint to be <N> by using the -bN option
406 number for this automatic breakpoint to be <N> by using the -bN option
399 (where N must be an integer). For example::
407 (where N must be an integer). For example::
400
408
401 %run -d -b40 myscript
409 %run -d -b40 myscript
402
410
403 will set the first breakpoint at line 40 in myscript.py. Note that
411 will set the first breakpoint at line 40 in myscript.py. Note that
404 the first breakpoint must be set on a line which actually does
412 the first breakpoint must be set on a line which actually does
405 something (not a comment or docstring) for it to stop execution.
413 something (not a comment or docstring) for it to stop execution.
406
414
407 When the pdb debugger starts, you will see a (Pdb) prompt. You must
415 When the pdb debugger starts, you will see a (Pdb) prompt. You must
408 first enter 'c' (without quotes) to start execution up to the first
416 first enter 'c' (without quotes) to start execution up to the first
409 breakpoint.
417 breakpoint.
410
418
411 Entering 'help' gives information about the use of the debugger. You
419 Entering 'help' gives information about the use of the debugger. You
412 can easily see pdb's full documentation with "import pdb;pdb.help()"
420 can easily see pdb's full documentation with "import pdb;pdb.help()"
413 at a prompt.
421 at a prompt.
414
422
415 -p: run program under the control of the Python profiler module (which
423 -p: run program under the control of the Python profiler module (which
416 prints a detailed report of execution times, function calls, etc).
424 prints a detailed report of execution times, function calls, etc).
417
425
418 You can pass other options after -p which affect the behavior of the
426 You can pass other options after -p which affect the behavior of the
419 profiler itself. See the docs for %prun for details.
427 profiler itself. See the docs for %prun for details.
420
428
421 In this mode, the program's variables do NOT propagate back to the
429 In this mode, the program's variables do NOT propagate back to the
422 IPython interactive namespace (because they remain in the namespace
430 IPython interactive namespace (because they remain in the namespace
423 where the profiler executes them).
431 where the profiler executes them).
424
432
425 Internally this triggers a call to %prun, see its documentation for
433 Internally this triggers a call to %prun, see its documentation for
426 details on the options available specifically for profiling.
434 details on the options available specifically for profiling.
427
435
428 There is one special usage for which the text above doesn't apply:
436 There is one special usage for which the text above doesn't apply:
429 if the filename ends with .ipy, the file is run as ipython script,
437 if the filename ends with .ipy, the file is run as ipython script,
430 just as if the commands were written on IPython prompt.
438 just as if the commands were written on IPython prompt.
431
439
432 -m: specify module name to load instead of script path. Similar to
440 -m: specify module name to load instead of script path. Similar to
433 the -m option for the python interpreter. Use this option last if you
441 the -m option for the python interpreter. Use this option last if you
434 want to combine with other %run options. Unlike the python interpreter
442 want to combine with other %run options. Unlike the python interpreter
435 only source modules are allowed no .pyc or .pyo files.
443 only source modules are allowed no .pyc or .pyo files.
436 For example::
444 For example::
437
445
438 %run -m example
446 %run -m example
439
447
440 will run the example module.
448 will run the example module.
441
449
450 -G: disable shell-like glob expansion of arguments.
451
442 """
452 """
443
453
444 # get arguments and set sys.argv for program to be run.
454 # get arguments and set sys.argv for program to be run.
445 opts, arg_lst = self.parse_options(parameter_s, 'nidtN:b:pD:l:rs:T:em:',
455 opts, arg_lst = self.parse_options(parameter_s,
456 'nidtN:b:pD:l:rs:T:em:G',
446 mode='list', list_all=1)
457 mode='list', list_all=1)
447 if "m" in opts:
458 if "m" in opts:
448 modulename = opts["m"][0]
459 modulename = opts["m"][0]
449 modpath = find_mod(modulename)
460 modpath = find_mod(modulename)
450 if modpath is None:
461 if modpath is None:
451 warn('%r is not a valid modulename on sys.path'%modulename)
462 warn('%r is not a valid modulename on sys.path'%modulename)
452 return
463 return
453 arg_lst = [modpath] + arg_lst
464 arg_lst = [modpath] + arg_lst
454 try:
465 try:
455 filename = file_finder(arg_lst[0])
466 filename = file_finder(arg_lst[0])
456 except IndexError:
467 except IndexError:
457 warn('you must provide at least a filename.')
468 warn('you must provide at least a filename.')
458 print '\n%run:\n', oinspect.getdoc(self.run)
469 print '\n%run:\n', oinspect.getdoc(self.run)
459 return
470 return
460 except IOError as e:
471 except IOError as e:
461 try:
472 try:
462 msg = str(e)
473 msg = str(e)
463 except UnicodeError:
474 except UnicodeError:
464 msg = e.message
475 msg = e.message
465 error(msg)
476 error(msg)
466 return
477 return
467
478
468 if filename.lower().endswith('.ipy'):
479 if filename.lower().endswith('.ipy'):
469 self.shell.safe_execfile_ipy(filename)
480 self.shell.safe_execfile_ipy(filename)
470 return
481 return
471
482
472 # Control the response to exit() calls made by the script being run
483 # Control the response to exit() calls made by the script being run
473 exit_ignore = 'e' in opts
484 exit_ignore = 'e' in opts
474
485
475 # Make sure that the running script gets a proper sys.argv as if it
486 # Make sure that the running script gets a proper sys.argv as if it
476 # were run from a system shell.
487 # were run from a system shell.
477 save_argv = sys.argv # save it for later restoring
488 save_argv = sys.argv # save it for later restoring
478
489
479 # simulate shell expansion on arguments, at least tilde expansion
490 if 'G' in opts:
480 args = [ os.path.expanduser(a) for a in arg_lst[1:] ]
491 args = arg_lst[1:]
492 else:
493 # tilde and glob expansion
494 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
481
495
482 sys.argv = [filename] + args # put in the proper filename
496 sys.argv = [filename] + args # put in the proper filename
483 # protect sys.argv from potential unicode strings on Python 2:
497 # protect sys.argv from potential unicode strings on Python 2:
484 if not py3compat.PY3:
498 if not py3compat.PY3:
485 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
499 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
486
500
487 if 'i' in opts:
501 if 'i' in opts:
488 # Run in user's interactive namespace
502 # Run in user's interactive namespace
489 prog_ns = self.shell.user_ns
503 prog_ns = self.shell.user_ns
490 __name__save = self.shell.user_ns['__name__']
504 __name__save = self.shell.user_ns['__name__']
491 prog_ns['__name__'] = '__main__'
505 prog_ns['__name__'] = '__main__'
492 main_mod = self.shell.new_main_mod(prog_ns)
506 main_mod = self.shell.new_main_mod(prog_ns)
493 else:
507 else:
494 # Run in a fresh, empty namespace
508 # Run in a fresh, empty namespace
495 if 'n' in opts:
509 if 'n' in opts:
496 name = os.path.splitext(os.path.basename(filename))[0]
510 name = os.path.splitext(os.path.basename(filename))[0]
497 else:
511 else:
498 name = '__main__'
512 name = '__main__'
499
513
500 main_mod = self.shell.new_main_mod()
514 main_mod = self.shell.new_main_mod()
501 prog_ns = main_mod.__dict__
515 prog_ns = main_mod.__dict__
502 prog_ns['__name__'] = name
516 prog_ns['__name__'] = name
503
517
504 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
518 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
505 # set the __file__ global in the script's namespace
519 # set the __file__ global in the script's namespace
506 prog_ns['__file__'] = filename
520 prog_ns['__file__'] = filename
507
521
508 # pickle fix. See interactiveshell for an explanation. But we need to
522 # pickle fix. See interactiveshell for an explanation. But we need to
509 # make sure that, if we overwrite __main__, we replace it at the end
523 # make sure that, if we overwrite __main__, we replace it at the end
510 main_mod_name = prog_ns['__name__']
524 main_mod_name = prog_ns['__name__']
511
525
512 if main_mod_name == '__main__':
526 if main_mod_name == '__main__':
513 restore_main = sys.modules['__main__']
527 restore_main = sys.modules['__main__']
514 else:
528 else:
515 restore_main = False
529 restore_main = False
516
530
517 # This needs to be undone at the end to prevent holding references to
531 # This needs to be undone at the end to prevent holding references to
518 # every single object ever created.
532 # every single object ever created.
519 sys.modules[main_mod_name] = main_mod
533 sys.modules[main_mod_name] = main_mod
520
534
521 try:
535 try:
522 stats = None
536 stats = None
523 with self.shell.readline_no_record:
537 with self.shell.readline_no_record:
524 if 'p' in opts:
538 if 'p' in opts:
525 stats = self.prun('', None, False, opts, arg_lst, prog_ns)
539 stats = self.prun('', None, False, opts, arg_lst, prog_ns)
526 else:
540 else:
527 if 'd' in opts:
541 if 'd' in opts:
528 deb = debugger.Pdb(self.shell.colors)
542 deb = debugger.Pdb(self.shell.colors)
529 # reset Breakpoint state, which is moronically kept
543 # reset Breakpoint state, which is moronically kept
530 # in a class
544 # in a class
531 bdb.Breakpoint.next = 1
545 bdb.Breakpoint.next = 1
532 bdb.Breakpoint.bplist = {}
546 bdb.Breakpoint.bplist = {}
533 bdb.Breakpoint.bpbynumber = [None]
547 bdb.Breakpoint.bpbynumber = [None]
534 # Set an initial breakpoint to stop execution
548 # Set an initial breakpoint to stop execution
535 maxtries = 10
549 maxtries = 10
536 bp = int(opts.get('b', [1])[0])
550 bp = int(opts.get('b', [1])[0])
537 checkline = deb.checkline(filename, bp)
551 checkline = deb.checkline(filename, bp)
538 if not checkline:
552 if not checkline:
539 for bp in range(bp + 1, bp + maxtries + 1):
553 for bp in range(bp + 1, bp + maxtries + 1):
540 if deb.checkline(filename, bp):
554 if deb.checkline(filename, bp):
541 break
555 break
542 else:
556 else:
543 msg = ("\nI failed to find a valid line to set "
557 msg = ("\nI failed to find a valid line to set "
544 "a breakpoint\n"
558 "a breakpoint\n"
545 "after trying up to line: %s.\n"
559 "after trying up to line: %s.\n"
546 "Please set a valid breakpoint manually "
560 "Please set a valid breakpoint manually "
547 "with the -b option." % bp)
561 "with the -b option." % bp)
548 error(msg)
562 error(msg)
549 return
563 return
550 # if we find a good linenumber, set the breakpoint
564 # if we find a good linenumber, set the breakpoint
551 deb.do_break('%s:%s' % (filename, bp))
565 deb.do_break('%s:%s' % (filename, bp))
552 # Start file run
566 # Start file run
553 print "NOTE: Enter 'c' at the",
567 print "NOTE: Enter 'c' at the",
554 print "%s prompt to start your script." % deb.prompt
568 print "%s prompt to start your script." % deb.prompt
555 ns = {'execfile': py3compat.execfile, 'prog_ns': prog_ns}
569 ns = {'execfile': py3compat.execfile, 'prog_ns': prog_ns}
556 try:
570 try:
557 #save filename so it can be used by methods on the deb object
571 #save filename so it can be used by methods on the deb object
558 deb._exec_filename = filename
572 deb._exec_filename = filename
559 deb.run('execfile("%s", prog_ns)' % filename, ns)
573 deb.run('execfile("%s", prog_ns)' % filename, ns)
560
574
561 except:
575 except:
562 etype, value, tb = sys.exc_info()
576 etype, value, tb = sys.exc_info()
563 # Skip three frames in the traceback: the %run one,
577 # Skip three frames in the traceback: the %run one,
564 # one inside bdb.py, and the command-line typed by the
578 # one inside bdb.py, and the command-line typed by the
565 # user (run by exec in pdb itself).
579 # user (run by exec in pdb itself).
566 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
580 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
567 else:
581 else:
568 if runner is None:
582 if runner is None:
569 runner = self.default_runner
583 runner = self.default_runner
570 if runner is None:
584 if runner is None:
571 runner = self.shell.safe_execfile
585 runner = self.shell.safe_execfile
572 if 't' in opts:
586 if 't' in opts:
573 # timed execution
587 # timed execution
574 try:
588 try:
575 nruns = int(opts['N'][0])
589 nruns = int(opts['N'][0])
576 if nruns < 1:
590 if nruns < 1:
577 error('Number of runs must be >=1')
591 error('Number of runs must be >=1')
578 return
592 return
579 except (KeyError):
593 except (KeyError):
580 nruns = 1
594 nruns = 1
581 twall0 = time.time()
595 twall0 = time.time()
582 if nruns == 1:
596 if nruns == 1:
583 t0 = clock2()
597 t0 = clock2()
584 runner(filename, prog_ns, prog_ns,
598 runner(filename, prog_ns, prog_ns,
585 exit_ignore=exit_ignore)
599 exit_ignore=exit_ignore)
586 t1 = clock2()
600 t1 = clock2()
587 t_usr = t1[0] - t0[0]
601 t_usr = t1[0] - t0[0]
588 t_sys = t1[1] - t0[1]
602 t_sys = t1[1] - t0[1]
589 print "\nIPython CPU timings (estimated):"
603 print "\nIPython CPU timings (estimated):"
590 print " User : %10.2f s." % t_usr
604 print " User : %10.2f s." % t_usr
591 print " System : %10.2f s." % t_sys
605 print " System : %10.2f s." % t_sys
592 else:
606 else:
593 runs = range(nruns)
607 runs = range(nruns)
594 t0 = clock2()
608 t0 = clock2()
595 for nr in runs:
609 for nr in runs:
596 runner(filename, prog_ns, prog_ns,
610 runner(filename, prog_ns, prog_ns,
597 exit_ignore=exit_ignore)
611 exit_ignore=exit_ignore)
598 t1 = clock2()
612 t1 = clock2()
599 t_usr = t1[0] - t0[0]
613 t_usr = t1[0] - t0[0]
600 t_sys = t1[1] - t0[1]
614 t_sys = t1[1] - t0[1]
601 print "\nIPython CPU timings (estimated):"
615 print "\nIPython CPU timings (estimated):"
602 print "Total runs performed:", nruns
616 print "Total runs performed:", nruns
603 print " Times : %10.2f %10.2f" % ('Total', 'Per run')
617 print " Times : %10.2f %10.2f" % ('Total', 'Per run')
604 print " User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)
618 print " User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)
605 print " System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)
619 print " System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)
606 twall1 = time.time()
620 twall1 = time.time()
607 print "Wall time: %10.2f s." % (twall1 - twall0)
621 print "Wall time: %10.2f s." % (twall1 - twall0)
608
622
609 else:
623 else:
610 # regular execution
624 # regular execution
611 runner(filename, prog_ns, prog_ns, exit_ignore=exit_ignore)
625 runner(filename, prog_ns, prog_ns, exit_ignore=exit_ignore)
612
626
613 if 'i' in opts:
627 if 'i' in opts:
614 self.shell.user_ns['__name__'] = __name__save
628 self.shell.user_ns['__name__'] = __name__save
615 else:
629 else:
616 # The shell MUST hold a reference to prog_ns so after %run
630 # The shell MUST hold a reference to prog_ns so after %run
617 # exits, the python deletion mechanism doesn't zero it out
631 # exits, the python deletion mechanism doesn't zero it out
618 # (leaving dangling references).
632 # (leaving dangling references).
619 self.shell.cache_main_mod(prog_ns, filename)
633 self.shell.cache_main_mod(prog_ns, filename)
620 # update IPython interactive namespace
634 # update IPython interactive namespace
621
635
622 # Some forms of read errors on the file may mean the
636 # Some forms of read errors on the file may mean the
623 # __name__ key was never set; using pop we don't have to
637 # __name__ key was never set; using pop we don't have to
624 # worry about a possible KeyError.
638 # worry about a possible KeyError.
625 prog_ns.pop('__name__', None)
639 prog_ns.pop('__name__', None)
626
640
627 self.shell.user_ns.update(prog_ns)
641 self.shell.user_ns.update(prog_ns)
628 finally:
642 finally:
629 # It's a bit of a mystery why, but __builtins__ can change from
643 # It's a bit of a mystery why, but __builtins__ can change from
630 # being a module to becoming a dict missing some key data after
644 # being a module to becoming a dict missing some key data after
631 # %run. As best I can see, this is NOT something IPython is doing
645 # %run. As best I can see, this is NOT something IPython is doing
632 # at all, and similar problems have been reported before:
646 # at all, and similar problems have been reported before:
633 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
647 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
634 # Since this seems to be done by the interpreter itself, the best
648 # Since this seems to be done by the interpreter itself, the best
635 # we can do is to at least restore __builtins__ for the user on
649 # we can do is to at least restore __builtins__ for the user on
636 # exit.
650 # exit.
637 self.shell.user_ns['__builtins__'] = builtin_mod
651 self.shell.user_ns['__builtins__'] = builtin_mod
638
652
639 # Ensure key global structures are restored
653 # Ensure key global structures are restored
640 sys.argv = save_argv
654 sys.argv = save_argv
641 if restore_main:
655 if restore_main:
642 sys.modules['__main__'] = restore_main
656 sys.modules['__main__'] = restore_main
643 else:
657 else:
644 # Remove from sys.modules the reference to main_mod we'd
658 # Remove from sys.modules the reference to main_mod we'd
645 # added. Otherwise it will trap references to objects
659 # added. Otherwise it will trap references to objects
646 # contained therein.
660 # contained therein.
647 del sys.modules[main_mod_name]
661 del sys.modules[main_mod_name]
648
662
649 return stats
663 return stats
650
664
651 @skip_doctest
665 @skip_doctest
652 @line_cell_magic
666 @line_cell_magic
653 def timeit(self, line='', cell=None):
667 def timeit(self, line='', cell=None):
654 """Time execution of a Python statement or expression
668 """Time execution of a Python statement or expression
655
669
656 Usage, in line mode:
670 Usage, in line mode:
657 %timeit [-n<N> -r<R> [-t|-c]] statement
671 %timeit [-n<N> -r<R> [-t|-c]] statement
658 or in cell mode:
672 or in cell mode:
659 %%timeit [-n<N> -r<R> [-t|-c]] setup_code
673 %%timeit [-n<N> -r<R> [-t|-c]] setup_code
660 code
674 code
661 code...
675 code...
662
676
663 Time execution of a Python statement or expression using the timeit
677 Time execution of a Python statement or expression using the timeit
664 module. This function can be used both as a line and cell magic:
678 module. This function can be used both as a line and cell magic:
665
679
666 - In line mode you can time a single-line statement (though multiple
680 - In line mode you can time a single-line statement (though multiple
667 ones can be chained with using semicolons).
681 ones can be chained with using semicolons).
668
682
669 - In cell mode, the statement in the first line is used as setup code
683 - In cell mode, the statement in the first line is used as setup code
670 (executed but not timed) and the body of the cell is timed. The cell
684 (executed but not timed) and the body of the cell is timed. The cell
671 body has access to any variables created in the setup code.
685 body has access to any variables created in the setup code.
672
686
673 Options:
687 Options:
674 -n<N>: execute the given statement <N> times in a loop. If this value
688 -n<N>: execute the given statement <N> times in a loop. If this value
675 is not given, a fitting value is chosen.
689 is not given, a fitting value is chosen.
676
690
677 -r<R>: repeat the loop iteration <R> times and take the best result.
691 -r<R>: repeat the loop iteration <R> times and take the best result.
678 Default: 3
692 Default: 3
679
693
680 -t: use time.time to measure the time, which is the default on Unix.
694 -t: use time.time to measure the time, which is the default on Unix.
681 This function measures wall time.
695 This function measures wall time.
682
696
683 -c: use time.clock to measure the time, which is the default on
697 -c: use time.clock to measure the time, which is the default on
684 Windows and measures wall time. On Unix, resource.getrusage is used
698 Windows and measures wall time. On Unix, resource.getrusage is used
685 instead and returns the CPU user time.
699 instead and returns the CPU user time.
686
700
687 -p<P>: use a precision of <P> digits to display the timing result.
701 -p<P>: use a precision of <P> digits to display the timing result.
688 Default: 3
702 Default: 3
689
703
690
704
691 Examples
705 Examples
692 --------
706 --------
693 ::
707 ::
694
708
695 In [1]: %timeit pass
709 In [1]: %timeit pass
696 10000000 loops, best of 3: 53.3 ns per loop
710 10000000 loops, best of 3: 53.3 ns per loop
697
711
698 In [2]: u = None
712 In [2]: u = None
699
713
700 In [3]: %timeit u is None
714 In [3]: %timeit u is None
701 10000000 loops, best of 3: 184 ns per loop
715 10000000 loops, best of 3: 184 ns per loop
702
716
703 In [4]: %timeit -r 4 u == None
717 In [4]: %timeit -r 4 u == None
704 1000000 loops, best of 4: 242 ns per loop
718 1000000 loops, best of 4: 242 ns per loop
705
719
706 In [5]: import time
720 In [5]: import time
707
721
708 In [6]: %timeit -n1 time.sleep(2)
722 In [6]: %timeit -n1 time.sleep(2)
709 1 loops, best of 3: 2 s per loop
723 1 loops, best of 3: 2 s per loop
710
724
711
725
712 The times reported by %timeit will be slightly higher than those
726 The times reported by %timeit will be slightly higher than those
713 reported by the timeit.py script when variables are accessed. This is
727 reported by the timeit.py script when variables are accessed. This is
714 due to the fact that %timeit executes the statement in the namespace
728 due to the fact that %timeit executes the statement in the namespace
715 of the shell, compared with timeit.py, which uses a single setup
729 of the shell, compared with timeit.py, which uses a single setup
716 statement to import function or create variables. Generally, the bias
730 statement to import function or create variables. Generally, the bias
717 does not matter as long as results from timeit.py are not mixed with
731 does not matter as long as results from timeit.py are not mixed with
718 those from %timeit."""
732 those from %timeit."""
719
733
720 import timeit
734 import timeit
721 import math
735 import math
722
736
723 # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
737 # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
724 # certain terminals. Until we figure out a robust way of
738 # certain terminals. Until we figure out a robust way of
725 # auto-detecting if the terminal can deal with it, use plain 'us' for
739 # auto-detecting if the terminal can deal with it, use plain 'us' for
726 # microseconds. I am really NOT happy about disabling the proper
740 # microseconds. I am really NOT happy about disabling the proper
727 # 'micro' prefix, but crashing is worse... If anyone knows what the
741 # 'micro' prefix, but crashing is worse... If anyone knows what the
728 # right solution for this is, I'm all ears...
742 # right solution for this is, I'm all ears...
729 #
743 #
730 # Note: using
744 # Note: using
731 #
745 #
732 # s = u'\xb5'
746 # s = u'\xb5'
733 # s.encode(sys.getdefaultencoding())
747 # s.encode(sys.getdefaultencoding())
734 #
748 #
735 # is not sufficient, as I've seen terminals where that fails but
749 # is not sufficient, as I've seen terminals where that fails but
736 # print s
750 # print s
737 #
751 #
738 # succeeds
752 # succeeds
739 #
753 #
740 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
754 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
741
755
742 #units = [u"s", u"ms",u'\xb5',"ns"]
756 #units = [u"s", u"ms",u'\xb5',"ns"]
743 units = [u"s", u"ms",u'us',"ns"]
757 units = [u"s", u"ms",u'us',"ns"]
744
758
745 scaling = [1, 1e3, 1e6, 1e9]
759 scaling = [1, 1e3, 1e6, 1e9]
746
760
747 opts, stmt = self.parse_options(line,'n:r:tcp:',
761 opts, stmt = self.parse_options(line,'n:r:tcp:',
748 posix=False, strict=False)
762 posix=False, strict=False)
749 if stmt == "" and cell is None:
763 if stmt == "" and cell is None:
750 return
764 return
751 timefunc = timeit.default_timer
765 timefunc = timeit.default_timer
752 number = int(getattr(opts, "n", 0))
766 number = int(getattr(opts, "n", 0))
753 repeat = int(getattr(opts, "r", timeit.default_repeat))
767 repeat = int(getattr(opts, "r", timeit.default_repeat))
754 precision = int(getattr(opts, "p", 3))
768 precision = int(getattr(opts, "p", 3))
755 if hasattr(opts, "t"):
769 if hasattr(opts, "t"):
756 timefunc = time.time
770 timefunc = time.time
757 if hasattr(opts, "c"):
771 if hasattr(opts, "c"):
758 timefunc = clock
772 timefunc = clock
759
773
760 timer = timeit.Timer(timer=timefunc)
774 timer = timeit.Timer(timer=timefunc)
761 # this code has tight coupling to the inner workings of timeit.Timer,
775 # this code has tight coupling to the inner workings of timeit.Timer,
762 # but is there a better way to achieve that the code stmt has access
776 # but is there a better way to achieve that the code stmt has access
763 # to the shell namespace?
777 # to the shell namespace?
764 transform = self.shell.input_splitter.transform_cell
778 transform = self.shell.input_splitter.transform_cell
765 if cell is None:
779 if cell is None:
766 # called as line magic
780 # called as line magic
767 setup = 'pass'
781 setup = 'pass'
768 stmt = timeit.reindent(transform(stmt), 8)
782 stmt = timeit.reindent(transform(stmt), 8)
769 else:
783 else:
770 setup = timeit.reindent(transform(stmt), 4)
784 setup = timeit.reindent(transform(stmt), 4)
771 stmt = timeit.reindent(transform(cell), 8)
785 stmt = timeit.reindent(transform(cell), 8)
772
786
773 # From Python 3.3, this template uses new-style string formatting.
787 # From Python 3.3, this template uses new-style string formatting.
774 if sys.version_info >= (3, 3):
788 if sys.version_info >= (3, 3):
775 src = timeit.template.format(stmt=stmt, setup=setup)
789 src = timeit.template.format(stmt=stmt, setup=setup)
776 else:
790 else:
777 src = timeit.template % dict(stmt=stmt, setup=setup)
791 src = timeit.template % dict(stmt=stmt, setup=setup)
778
792
779 # Track compilation time so it can be reported if too long
793 # Track compilation time so it can be reported if too long
780 # Minimum time above which compilation time will be reported
794 # Minimum time above which compilation time will be reported
781 tc_min = 0.1
795 tc_min = 0.1
782
796
783 t0 = clock()
797 t0 = clock()
784 code = compile(src, "<magic-timeit>", "exec")
798 code = compile(src, "<magic-timeit>", "exec")
785 tc = clock()-t0
799 tc = clock()-t0
786
800
787 ns = {}
801 ns = {}
788 exec code in self.shell.user_ns, ns
802 exec code in self.shell.user_ns, ns
789 timer.inner = ns["inner"]
803 timer.inner = ns["inner"]
790
804
791 if number == 0:
805 if number == 0:
792 # determine number so that 0.2 <= total time < 2.0
806 # determine number so that 0.2 <= total time < 2.0
793 number = 1
807 number = 1
794 for i in range(1, 10):
808 for i in range(1, 10):
795 if timer.timeit(number) >= 0.2:
809 if timer.timeit(number) >= 0.2:
796 break
810 break
797 number *= 10
811 number *= 10
798
812
799 best = min(timer.repeat(repeat, number)) / number
813 best = min(timer.repeat(repeat, number)) / number
800
814
801 if best > 0.0 and best < 1000.0:
815 if best > 0.0 and best < 1000.0:
802 order = min(-int(math.floor(math.log10(best)) // 3), 3)
816 order = min(-int(math.floor(math.log10(best)) // 3), 3)
803 elif best >= 1000.0:
817 elif best >= 1000.0:
804 order = 0
818 order = 0
805 else:
819 else:
806 order = 3
820 order = 3
807 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
821 print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
808 precision,
822 precision,
809 best * scaling[order],
823 best * scaling[order],
810 units[order])
824 units[order])
811 if tc > tc_min:
825 if tc > tc_min:
812 print "Compiler time: %.2f s" % tc
826 print "Compiler time: %.2f s" % tc
813
827
814 @skip_doctest
828 @skip_doctest
815 @needs_local_scope
829 @needs_local_scope
816 @line_magic
830 @line_magic
817 def time(self,parameter_s, local_ns=None):
831 def time(self,parameter_s, local_ns=None):
818 """Time execution of a Python statement or expression.
832 """Time execution of a Python statement or expression.
819
833
820 The CPU and wall clock times are printed, and the value of the
834 The CPU and wall clock times are printed, and the value of the
821 expression (if any) is returned. Note that under Win32, system time
835 expression (if any) is returned. Note that under Win32, system time
822 is always reported as 0, since it can not be measured.
836 is always reported as 0, since it can not be measured.
823
837
824 This function provides very basic timing functionality. In Python
838 This function provides very basic timing functionality. In Python
825 2.3, the timeit module offers more control and sophistication, so this
839 2.3, the timeit module offers more control and sophistication, so this
826 could be rewritten to use it (patches welcome).
840 could be rewritten to use it (patches welcome).
827
841
828 Examples
842 Examples
829 --------
843 --------
830 ::
844 ::
831
845
832 In [1]: time 2**128
846 In [1]: time 2**128
833 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
847 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
834 Wall time: 0.00
848 Wall time: 0.00
835 Out[1]: 340282366920938463463374607431768211456L
849 Out[1]: 340282366920938463463374607431768211456L
836
850
837 In [2]: n = 1000000
851 In [2]: n = 1000000
838
852
839 In [3]: time sum(range(n))
853 In [3]: time sum(range(n))
840 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
854 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
841 Wall time: 1.37
855 Wall time: 1.37
842 Out[3]: 499999500000L
856 Out[3]: 499999500000L
843
857
844 In [4]: time print 'hello world'
858 In [4]: time print 'hello world'
845 hello world
859 hello world
846 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
860 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
847 Wall time: 0.00
861 Wall time: 0.00
848
862
849 Note that the time needed by Python to compile the given expression
863 Note that the time needed by Python to compile the given expression
850 will be reported if it is more than 0.1s. In this example, the
864 will be reported if it is more than 0.1s. In this example, the
851 actual exponentiation is done by Python at compilation time, so while
865 actual exponentiation is done by Python at compilation time, so while
852 the expression can take a noticeable amount of time to compute, that
866 the expression can take a noticeable amount of time to compute, that
853 time is purely due to the compilation:
867 time is purely due to the compilation:
854
868
855 In [5]: time 3**9999;
869 In [5]: time 3**9999;
856 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
870 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
857 Wall time: 0.00 s
871 Wall time: 0.00 s
858
872
859 In [6]: time 3**999999;
873 In [6]: time 3**999999;
860 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
874 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
861 Wall time: 0.00 s
875 Wall time: 0.00 s
862 Compiler : 0.78 s
876 Compiler : 0.78 s
863 """
877 """
864
878
865 # fail immediately if the given expression can't be compiled
879 # fail immediately if the given expression can't be compiled
866
880
867 expr = self.shell.prefilter(parameter_s,False)
881 expr = self.shell.prefilter(parameter_s,False)
868
882
869 # Minimum time above which compilation time will be reported
883 # Minimum time above which compilation time will be reported
870 tc_min = 0.1
884 tc_min = 0.1
871
885
872 try:
886 try:
873 mode = 'eval'
887 mode = 'eval'
874 t0 = clock()
888 t0 = clock()
875 code = compile(expr,'<timed eval>',mode)
889 code = compile(expr,'<timed eval>',mode)
876 tc = clock()-t0
890 tc = clock()-t0
877 except SyntaxError:
891 except SyntaxError:
878 mode = 'exec'
892 mode = 'exec'
879 t0 = clock()
893 t0 = clock()
880 code = compile(expr,'<timed exec>',mode)
894 code = compile(expr,'<timed exec>',mode)
881 tc = clock()-t0
895 tc = clock()-t0
882 # skew measurement as little as possible
896 # skew measurement as little as possible
883 glob = self.shell.user_ns
897 glob = self.shell.user_ns
884 wtime = time.time
898 wtime = time.time
885 # time execution
899 # time execution
886 wall_st = wtime()
900 wall_st = wtime()
887 if mode=='eval':
901 if mode=='eval':
888 st = clock2()
902 st = clock2()
889 out = eval(code, glob, local_ns)
903 out = eval(code, glob, local_ns)
890 end = clock2()
904 end = clock2()
891 else:
905 else:
892 st = clock2()
906 st = clock2()
893 exec code in glob, local_ns
907 exec code in glob, local_ns
894 end = clock2()
908 end = clock2()
895 out = None
909 out = None
896 wall_end = wtime()
910 wall_end = wtime()
897 # Compute actual times and report
911 # Compute actual times and report
898 wall_time = wall_end-wall_st
912 wall_time = wall_end-wall_st
899 cpu_user = end[0]-st[0]
913 cpu_user = end[0]-st[0]
900 cpu_sys = end[1]-st[1]
914 cpu_sys = end[1]-st[1]
901 cpu_tot = cpu_user+cpu_sys
915 cpu_tot = cpu_user+cpu_sys
902 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
916 print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
903 (cpu_user,cpu_sys,cpu_tot)
917 (cpu_user,cpu_sys,cpu_tot)
904 print "Wall time: %.2f s" % wall_time
918 print "Wall time: %.2f s" % wall_time
905 if tc > tc_min:
919 if tc > tc_min:
906 print "Compiler : %.2f s" % tc
920 print "Compiler : %.2f s" % tc
907 return out
921 return out
908
922
909 @skip_doctest
923 @skip_doctest
910 @line_magic
924 @line_magic
911 def macro(self, parameter_s=''):
925 def macro(self, parameter_s=''):
912 """Define a macro for future re-execution. It accepts ranges of history,
926 """Define a macro for future re-execution. It accepts ranges of history,
913 filenames or string objects.
927 filenames or string objects.
914
928
915 Usage:\\
929 Usage:\\
916 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
930 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
917
931
918 Options:
932 Options:
919
933
920 -r: use 'raw' input. By default, the 'processed' history is used,
934 -r: use 'raw' input. By default, the 'processed' history is used,
921 so that magics are loaded in their transformed version to valid
935 so that magics are loaded in their transformed version to valid
922 Python. If this option is given, the raw input as typed as the
936 Python. If this option is given, the raw input as typed as the
923 command line is used instead.
937 command line is used instead.
924
938
925 This will define a global variable called `name` which is a string
939 This will define a global variable called `name` which is a string
926 made of joining the slices and lines you specify (n1,n2,... numbers
940 made of joining the slices and lines you specify (n1,n2,... numbers
927 above) from your input history into a single string. This variable
941 above) from your input history into a single string. This variable
928 acts like an automatic function which re-executes those lines as if
942 acts like an automatic function which re-executes those lines as if
929 you had typed them. You just type 'name' at the prompt and the code
943 you had typed them. You just type 'name' at the prompt and the code
930 executes.
944 executes.
931
945
932 The syntax for indicating input ranges is described in %history.
946 The syntax for indicating input ranges is described in %history.
933
947
934 Note: as a 'hidden' feature, you can also use traditional python slice
948 Note: as a 'hidden' feature, you can also use traditional python slice
935 notation, where N:M means numbers N through M-1.
949 notation, where N:M means numbers N through M-1.
936
950
937 For example, if your history contains (%hist prints it)::
951 For example, if your history contains (%hist prints it)::
938
952
939 44: x=1
953 44: x=1
940 45: y=3
954 45: y=3
941 46: z=x+y
955 46: z=x+y
942 47: print x
956 47: print x
943 48: a=5
957 48: a=5
944 49: print 'x',x,'y',y
958 49: print 'x',x,'y',y
945
959
946 you can create a macro with lines 44 through 47 (included) and line 49
960 you can create a macro with lines 44 through 47 (included) and line 49
947 called my_macro with::
961 called my_macro with::
948
962
949 In [55]: %macro my_macro 44-47 49
963 In [55]: %macro my_macro 44-47 49
950
964
951 Now, typing `my_macro` (without quotes) will re-execute all this code
965 Now, typing `my_macro` (without quotes) will re-execute all this code
952 in one pass.
966 in one pass.
953
967
954 You don't need to give the line-numbers in order, and any given line
968 You don't need to give the line-numbers in order, and any given line
955 number can appear multiple times. You can assemble macros with any
969 number can appear multiple times. You can assemble macros with any
956 lines from your input history in any order.
970 lines from your input history in any order.
957
971
958 The macro is a simple object which holds its value in an attribute,
972 The macro is a simple object which holds its value in an attribute,
959 but IPython's display system checks for macros and executes them as
973 but IPython's display system checks for macros and executes them as
960 code instead of printing them when you type their name.
974 code instead of printing them when you type their name.
961
975
962 You can view a macro's contents by explicitly printing it with::
976 You can view a macro's contents by explicitly printing it with::
963
977
964 print macro_name
978 print macro_name
965
979
966 """
980 """
967 opts,args = self.parse_options(parameter_s,'r',mode='list')
981 opts,args = self.parse_options(parameter_s,'r',mode='list')
968 if not args: # List existing macros
982 if not args: # List existing macros
969 return sorted(k for k,v in self.shell.user_ns.iteritems() if\
983 return sorted(k for k,v in self.shell.user_ns.iteritems() if\
970 isinstance(v, Macro))
984 isinstance(v, Macro))
971 if len(args) == 1:
985 if len(args) == 1:
972 raise UsageError(
986 raise UsageError(
973 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
987 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
974 name, codefrom = args[0], " ".join(args[1:])
988 name, codefrom = args[0], " ".join(args[1:])
975
989
976 #print 'rng',ranges # dbg
990 #print 'rng',ranges # dbg
977 try:
991 try:
978 lines = self.shell.find_user_code(codefrom, 'r' in opts)
992 lines = self.shell.find_user_code(codefrom, 'r' in opts)
979 except (ValueError, TypeError) as e:
993 except (ValueError, TypeError) as e:
980 print e.args[0]
994 print e.args[0]
981 return
995 return
982 macro = Macro(lines)
996 macro = Macro(lines)
983 self.shell.define_macro(name, macro)
997 self.shell.define_macro(name, macro)
984 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
998 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
985 print '=== Macro contents: ==='
999 print '=== Macro contents: ==='
986 print macro,
1000 print macro,
987
1001
988 @magic_arguments.magic_arguments()
1002 @magic_arguments.magic_arguments()
989 @magic_arguments.argument('output', type=str, default='', nargs='?',
1003 @magic_arguments.argument('output', type=str, default='', nargs='?',
990 help="""The name of the variable in which to store output.
1004 help="""The name of the variable in which to store output.
991 This is a utils.io.CapturedIO object with stdout/err attributes
1005 This is a utils.io.CapturedIO object with stdout/err attributes
992 for the text of the captured output.
1006 for the text of the captured output.
993
1007
994 CapturedOutput also has a show() method for displaying the output,
1008 CapturedOutput also has a show() method for displaying the output,
995 and __call__ as well, so you can use that to quickly display the
1009 and __call__ as well, so you can use that to quickly display the
996 output.
1010 output.
997
1011
998 If unspecified, captured output is discarded.
1012 If unspecified, captured output is discarded.
999 """
1013 """
1000 )
1014 )
1001 @magic_arguments.argument('--no-stderr', action="store_true",
1015 @magic_arguments.argument('--no-stderr', action="store_true",
1002 help="""Don't capture stderr."""
1016 help="""Don't capture stderr."""
1003 )
1017 )
1004 @magic_arguments.argument('--no-stdout', action="store_true",
1018 @magic_arguments.argument('--no-stdout', action="store_true",
1005 help="""Don't capture stdout."""
1019 help="""Don't capture stdout."""
1006 )
1020 )
1007 @cell_magic
1021 @cell_magic
1008 def capture(self, line, cell):
1022 def capture(self, line, cell):
1009 """run the cell, capturing stdout/err"""
1023 """run the cell, capturing stdout/err"""
1010 args = magic_arguments.parse_argstring(self.capture, line)
1024 args = magic_arguments.parse_argstring(self.capture, line)
1011 out = not args.no_stdout
1025 out = not args.no_stdout
1012 err = not args.no_stderr
1026 err = not args.no_stderr
1013 with capture_output(out, err) as io:
1027 with capture_output(out, err) as io:
1014 self.shell.run_cell(cell)
1028 self.shell.run_cell(cell)
1015 if args.output:
1029 if args.output:
1016 self.shell.user_ns[args.output] = io
1030 self.shell.user_ns[args.output] = io
@@ -1,250 +1,272 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for code execution (%run and related), which is particularly tricky.
2 """Tests for code execution (%run and related), which is particularly tricky.
3
3
4 Because of how %run manages namespaces, and the fact that we are trying here to
4 Because of how %run manages namespaces, and the fact that we are trying here to
5 verify subtle object deletion and reference counting issues, the %run tests
5 verify subtle object deletion and reference counting issues, the %run tests
6 will be kept in this separate file. This makes it easier to aggregate in one
6 will be kept in this separate file. This makes it easier to aggregate in one
7 place the tricks needed to handle it; most other magics are much easier to test
7 place the tricks needed to handle it; most other magics are much easier to test
8 and we do so in a common test_magic file.
8 and we do so in a common test_magic file.
9 """
9 """
10 from __future__ import absolute_import
10 from __future__ import absolute_import
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 import os
16 import os
17 import sys
17 import sys
18 import tempfile
18 import tempfile
19
19
20 import nose.tools as nt
20 import nose.tools as nt
21 from nose import SkipTest
21 from nose import SkipTest
22
22
23 from IPython.testing import decorators as dec
23 from IPython.testing import decorators as dec
24 from IPython.testing import tools as tt
24 from IPython.testing import tools as tt
25 from IPython.utils import py3compat
25 from IPython.utils import py3compat
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Test functions begin
28 # Test functions begin
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 def doctest_refbug():
31 def doctest_refbug():
32 """Very nasty problem with references held by multiple runs of a script.
32 """Very nasty problem with references held by multiple runs of a script.
33 See: https://github.com/ipython/ipython/issues/141
33 See: https://github.com/ipython/ipython/issues/141
34
34
35 In [1]: _ip.clear_main_mod_cache()
35 In [1]: _ip.clear_main_mod_cache()
36 # random
36 # random
37
37
38 In [2]: %run refbug
38 In [2]: %run refbug
39
39
40 In [3]: call_f()
40 In [3]: call_f()
41 lowercased: hello
41 lowercased: hello
42
42
43 In [4]: %run refbug
43 In [4]: %run refbug
44
44
45 In [5]: call_f()
45 In [5]: call_f()
46 lowercased: hello
46 lowercased: hello
47 lowercased: hello
47 lowercased: hello
48 """
48 """
49
49
50
50
51 def doctest_run_builtins():
51 def doctest_run_builtins():
52 r"""Check that %run doesn't damage __builtins__.
52 r"""Check that %run doesn't damage __builtins__.
53
53
54 In [1]: import tempfile
54 In [1]: import tempfile
55
55
56 In [2]: bid1 = id(__builtins__)
56 In [2]: bid1 = id(__builtins__)
57
57
58 In [3]: fname = tempfile.mkstemp('.py')[1]
58 In [3]: fname = tempfile.mkstemp('.py')[1]
59
59
60 In [3]: f = open(fname,'w')
60 In [3]: f = open(fname,'w')
61
61
62 In [4]: dummy= f.write('pass\n')
62 In [4]: dummy= f.write('pass\n')
63
63
64 In [5]: f.flush()
64 In [5]: f.flush()
65
65
66 In [6]: t1 = type(__builtins__)
66 In [6]: t1 = type(__builtins__)
67
67
68 In [7]: %run $fname
68 In [7]: %run $fname
69
69
70 In [7]: f.close()
70 In [7]: f.close()
71
71
72 In [8]: bid2 = id(__builtins__)
72 In [8]: bid2 = id(__builtins__)
73
73
74 In [9]: t2 = type(__builtins__)
74 In [9]: t2 = type(__builtins__)
75
75
76 In [10]: t1 == t2
76 In [10]: t1 == t2
77 Out[10]: True
77 Out[10]: True
78
78
79 In [10]: bid1 == bid2
79 In [10]: bid1 == bid2
80 Out[10]: True
80 Out[10]: True
81
81
82 In [12]: try:
82 In [12]: try:
83 ....: os.unlink(fname)
83 ....: os.unlink(fname)
84 ....: except:
84 ....: except:
85 ....: pass
85 ....: pass
86 ....:
86 ....:
87 """
87 """
88
88
89
90 def doctest_run_option_parser():
91 r"""Test option parser in %run.
92
93 In [1]: %run print_argv.py
94 []
95
96 In [2]: %run print_argv.py print*.py
97 ['print_argv.py']
98
99 In [3]: %run print_argv.py print\\*.py
100 ['print*.py']
101
102 In [4]: %run print_argv.py 'print*.py'
103 ['print_argv.py']
104
105 In [5]: %run -G print_argv.py print*.py
106 ['print*.py']
107
108 """
109
110
89 @py3compat.doctest_refactor_print
111 @py3compat.doctest_refactor_print
90 def doctest_reset_del():
112 def doctest_reset_del():
91 """Test that resetting doesn't cause errors in __del__ methods.
113 """Test that resetting doesn't cause errors in __del__ methods.
92
114
93 In [2]: class A(object):
115 In [2]: class A(object):
94 ...: def __del__(self):
116 ...: def __del__(self):
95 ...: print str("Hi")
117 ...: print str("Hi")
96 ...:
118 ...:
97
119
98 In [3]: a = A()
120 In [3]: a = A()
99
121
100 In [4]: get_ipython().reset()
122 In [4]: get_ipython().reset()
101 Hi
123 Hi
102
124
103 In [5]: 1+1
125 In [5]: 1+1
104 Out[5]: 2
126 Out[5]: 2
105 """
127 """
106
128
107 # For some tests, it will be handy to organize them in a class with a common
129 # For some tests, it will be handy to organize them in a class with a common
108 # setup that makes a temp file
130 # setup that makes a temp file
109
131
110 class TestMagicRunPass(tt.TempFileMixin):
132 class TestMagicRunPass(tt.TempFileMixin):
111
133
112 def setup(self):
134 def setup(self):
113 """Make a valid python temp file."""
135 """Make a valid python temp file."""
114 self.mktmp('pass\n')
136 self.mktmp('pass\n')
115
137
116 def run_tmpfile(self):
138 def run_tmpfile(self):
117 _ip = get_ipython()
139 _ip = get_ipython()
118 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
140 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
119 # See below and ticket https://bugs.launchpad.net/bugs/366353
141 # See below and ticket https://bugs.launchpad.net/bugs/366353
120 _ip.magic('run %s' % self.fname)
142 _ip.magic('run %s' % self.fname)
121
143
122 def run_tmpfile_p(self):
144 def run_tmpfile_p(self):
123 _ip = get_ipython()
145 _ip = get_ipython()
124 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
146 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
125 # See below and ticket https://bugs.launchpad.net/bugs/366353
147 # See below and ticket https://bugs.launchpad.net/bugs/366353
126 _ip.magic('run -p %s' % self.fname)
148 _ip.magic('run -p %s' % self.fname)
127
149
128 def test_builtins_id(self):
150 def test_builtins_id(self):
129 """Check that %run doesn't damage __builtins__ """
151 """Check that %run doesn't damage __builtins__ """
130 _ip = get_ipython()
152 _ip = get_ipython()
131 # Test that the id of __builtins__ is not modified by %run
153 # Test that the id of __builtins__ is not modified by %run
132 bid1 = id(_ip.user_ns['__builtins__'])
154 bid1 = id(_ip.user_ns['__builtins__'])
133 self.run_tmpfile()
155 self.run_tmpfile()
134 bid2 = id(_ip.user_ns['__builtins__'])
156 bid2 = id(_ip.user_ns['__builtins__'])
135 nt.assert_equal(bid1, bid2)
157 nt.assert_equal(bid1, bid2)
136
158
137 def test_builtins_type(self):
159 def test_builtins_type(self):
138 """Check that the type of __builtins__ doesn't change with %run.
160 """Check that the type of __builtins__ doesn't change with %run.
139
161
140 However, the above could pass if __builtins__ was already modified to
162 However, the above could pass if __builtins__ was already modified to
141 be a dict (it should be a module) by a previous use of %run. So we
163 be a dict (it should be a module) by a previous use of %run. So we
142 also check explicitly that it really is a module:
164 also check explicitly that it really is a module:
143 """
165 """
144 _ip = get_ipython()
166 _ip = get_ipython()
145 self.run_tmpfile()
167 self.run_tmpfile()
146 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
168 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
147
169
148 def test_prompts(self):
170 def test_prompts(self):
149 """Test that prompts correctly generate after %run"""
171 """Test that prompts correctly generate after %run"""
150 self.run_tmpfile()
172 self.run_tmpfile()
151 _ip = get_ipython()
173 _ip = get_ipython()
152 p2 = _ip.prompt_manager.render('in2').strip()
174 p2 = _ip.prompt_manager.render('in2').strip()
153 nt.assert_equal(p2[:3], '...')
175 nt.assert_equal(p2[:3], '...')
154
176
155 def test_run_profile( self ):
177 def test_run_profile( self ):
156 """Test that the option -p, which invokes the profiler, do not
178 """Test that the option -p, which invokes the profiler, do not
157 crash by invoking execfile"""
179 crash by invoking execfile"""
158 _ip = get_ipython()
180 _ip = get_ipython()
159 self.run_tmpfile_p()
181 self.run_tmpfile_p()
160
182
161
183
162 class TestMagicRunSimple(tt.TempFileMixin):
184 class TestMagicRunSimple(tt.TempFileMixin):
163
185
164 def test_simpledef(self):
186 def test_simpledef(self):
165 """Test that simple class definitions work."""
187 """Test that simple class definitions work."""
166 src = ("class foo: pass\n"
188 src = ("class foo: pass\n"
167 "def f(): return foo()")
189 "def f(): return foo()")
168 self.mktmp(src)
190 self.mktmp(src)
169 _ip.magic('run %s' % self.fname)
191 _ip.magic('run %s' % self.fname)
170 _ip.run_cell('t = isinstance(f(), foo)')
192 _ip.run_cell('t = isinstance(f(), foo)')
171 nt.assert_true(_ip.user_ns['t'])
193 nt.assert_true(_ip.user_ns['t'])
172
194
173 def test_obj_del(self):
195 def test_obj_del(self):
174 """Test that object's __del__ methods are called on exit."""
196 """Test that object's __del__ methods are called on exit."""
175 if sys.platform == 'win32':
197 if sys.platform == 'win32':
176 try:
198 try:
177 import win32api
199 import win32api
178 except ImportError:
200 except ImportError:
179 raise SkipTest("Test requires pywin32")
201 raise SkipTest("Test requires pywin32")
180 src = ("class A(object):\n"
202 src = ("class A(object):\n"
181 " def __del__(self):\n"
203 " def __del__(self):\n"
182 " print 'object A deleted'\n"
204 " print 'object A deleted'\n"
183 "a = A()\n")
205 "a = A()\n")
184 self.mktmp(py3compat.doctest_refactor_print(src))
206 self.mktmp(py3compat.doctest_refactor_print(src))
185 if dec.module_not_available('sqlite3'):
207 if dec.module_not_available('sqlite3'):
186 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
208 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
187 else:
209 else:
188 err = None
210 err = None
189 tt.ipexec_validate(self.fname, 'object A deleted', err)
211 tt.ipexec_validate(self.fname, 'object A deleted', err)
190
212
191 @dec.skip_known_failure
213 @dec.skip_known_failure
192 def test_aggressive_namespace_cleanup(self):
214 def test_aggressive_namespace_cleanup(self):
193 """Test that namespace cleanup is not too aggressive GH-238
215 """Test that namespace cleanup is not too aggressive GH-238
194
216
195 Returning from another run magic deletes the namespace"""
217 Returning from another run magic deletes the namespace"""
196 # see ticket https://github.com/ipython/ipython/issues/238
218 # see ticket https://github.com/ipython/ipython/issues/238
197 class secondtmp(tt.TempFileMixin): pass
219 class secondtmp(tt.TempFileMixin): pass
198 empty = secondtmp()
220 empty = secondtmp()
199 empty.mktmp('')
221 empty.mktmp('')
200 src = ("ip = get_ipython()\n"
222 src = ("ip = get_ipython()\n"
201 "for i in range(5):\n"
223 "for i in range(5):\n"
202 " try:\n"
224 " try:\n"
203 " ip.magic('run %s')\n"
225 " ip.magic('run %s')\n"
204 " except NameError as e:\n"
226 " except NameError as e:\n"
205 " print i;break\n" % empty.fname)
227 " print i;break\n" % empty.fname)
206 self.mktmp(py3compat.doctest_refactor_print(src))
228 self.mktmp(py3compat.doctest_refactor_print(src))
207 _ip.magic('run %s' % self.fname)
229 _ip.magic('run %s' % self.fname)
208 _ip.run_cell('ip == get_ipython()')
230 _ip.run_cell('ip == get_ipython()')
209 nt.assert_equal(_ip.user_ns['i'], 5)
231 nt.assert_equal(_ip.user_ns['i'], 5)
210
232
211 @dec.skip_win32
233 @dec.skip_win32
212 def test_tclass(self):
234 def test_tclass(self):
213 mydir = os.path.dirname(__file__)
235 mydir = os.path.dirname(__file__)
214 tc = os.path.join(mydir, 'tclass')
236 tc = os.path.join(mydir, 'tclass')
215 src = ("%%run '%s' C-first\n"
237 src = ("%%run '%s' C-first\n"
216 "%%run '%s' C-second\n"
238 "%%run '%s' C-second\n"
217 "%%run '%s' C-third\n") % (tc, tc, tc)
239 "%%run '%s' C-third\n") % (tc, tc, tc)
218 self.mktmp(src, '.ipy')
240 self.mktmp(src, '.ipy')
219 out = """\
241 out = """\
220 ARGV 1-: ['C-first']
242 ARGV 1-: ['C-first']
221 ARGV 1-: ['C-second']
243 ARGV 1-: ['C-second']
222 tclass.py: deleting object: C-first
244 tclass.py: deleting object: C-first
223 ARGV 1-: ['C-third']
245 ARGV 1-: ['C-third']
224 tclass.py: deleting object: C-second
246 tclass.py: deleting object: C-second
225 tclass.py: deleting object: C-third
247 tclass.py: deleting object: C-third
226 """
248 """
227 if dec.module_not_available('sqlite3'):
249 if dec.module_not_available('sqlite3'):
228 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
250 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
229 else:
251 else:
230 err = None
252 err = None
231 tt.ipexec_validate(self.fname, out, err)
253 tt.ipexec_validate(self.fname, out, err)
232
254
233 def test_run_i_after_reset(self):
255 def test_run_i_after_reset(self):
234 """Check that %run -i still works after %reset (gh-693)"""
256 """Check that %run -i still works after %reset (gh-693)"""
235 src = "yy = zz\n"
257 src = "yy = zz\n"
236 self.mktmp(src)
258 self.mktmp(src)
237 _ip.run_cell("zz = 23")
259 _ip.run_cell("zz = 23")
238 _ip.magic('run -i %s' % self.fname)
260 _ip.magic('run -i %s' % self.fname)
239 nt.assert_equal(_ip.user_ns['yy'], 23)
261 nt.assert_equal(_ip.user_ns['yy'], 23)
240 _ip.magic('reset -f')
262 _ip.magic('reset -f')
241 _ip.run_cell("zz = 23")
263 _ip.run_cell("zz = 23")
242 _ip.magic('run -i %s' % self.fname)
264 _ip.magic('run -i %s' % self.fname)
243 nt.assert_equal(_ip.user_ns['yy'], 23)
265 nt.assert_equal(_ip.user_ns['yy'], 23)
244
266
245 def test_unicode(self):
267 def test_unicode(self):
246 """Check that files in odd encodings are accepted."""
268 """Check that files in odd encodings are accepted."""
247 mydir = os.path.dirname(__file__)
269 mydir = os.path.dirname(__file__)
248 na = os.path.join(mydir, 'nonascii.py')
270 na = os.path.join(mydir, 'nonascii.py')
249 _ip.magic('run "%s"' % na)
271 _ip.magic('run "%s"' % na)
250 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
272 nt.assert_equal(_ip.user_ns['u'], u'ΠŽΡ‚β„–Π€')
@@ -1,468 +1,491 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 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 unescape_glob(string):
360 """Unescape glob pattern in `string`."""
361 def unescape(s):
362 for pattern in '*[]!?':
363 s = s.replace(r'\{0}'.format(pattern), pattern)
364 return s
365 return '\\'.join(map(unescape, string.split('\\\\')))
366
367
368 def shellglob(args):
369 """
370 Do glob expansion for each element in `args` and return a flattened list.
371
372 Unmatched glob pattern will remain as-is in the returned list.
373
374 """
375 expanded = []
376 for a in args:
377 expanded.extend(glob.glob(a) or [unescape_glob(a)])
378 return expanded
379
380
358 def target_outdated(target,deps):
381 def target_outdated(target,deps):
359 """Determine whether a target is out of date.
382 """Determine whether a target is out of date.
360
383
361 target_outdated(target,deps) -> 1/0
384 target_outdated(target,deps) -> 1/0
362
385
363 deps: list of filenames which MUST exist.
386 deps: list of filenames which MUST exist.
364 target: single filename which may or may not exist.
387 target: single filename which may or may not exist.
365
388
366 If target doesn't exist or is older than any file listed in deps, return
389 If target doesn't exist or is older than any file listed in deps, return
367 true, otherwise return false.
390 true, otherwise return false.
368 """
391 """
369 try:
392 try:
370 target_time = os.path.getmtime(target)
393 target_time = os.path.getmtime(target)
371 except os.error:
394 except os.error:
372 return 1
395 return 1
373 for dep in deps:
396 for dep in deps:
374 dep_time = os.path.getmtime(dep)
397 dep_time = os.path.getmtime(dep)
375 if dep_time > target_time:
398 if dep_time > target_time:
376 #print "For target",target,"Dep failed:",dep # dbg
399 #print "For target",target,"Dep failed:",dep # dbg
377 #print "times (dep,tar):",dep_time,target_time # dbg
400 #print "times (dep,tar):",dep_time,target_time # dbg
378 return 1
401 return 1
379 return 0
402 return 0
380
403
381
404
382 def target_update(target,deps,cmd):
405 def target_update(target,deps,cmd):
383 """Update a target with a given command given a list of dependencies.
406 """Update a target with a given command given a list of dependencies.
384
407
385 target_update(target,deps,cmd) -> runs cmd if target is outdated.
408 target_update(target,deps,cmd) -> runs cmd if target is outdated.
386
409
387 This is just a wrapper around target_outdated() which calls the given
410 This is just a wrapper around target_outdated() which calls the given
388 command if target is outdated."""
411 command if target is outdated."""
389
412
390 if target_outdated(target,deps):
413 if target_outdated(target,deps):
391 system(cmd)
414 system(cmd)
392
415
393 def filehash(path):
416 def filehash(path):
394 """Make an MD5 hash of a file, ignoring any differences in line
417 """Make an MD5 hash of a file, ignoring any differences in line
395 ending characters."""
418 ending characters."""
396 with open(path, "rU") as f:
419 with open(path, "rU") as f:
397 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
420 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
398
421
399 # If the config is unmodified from the default, we'll just delete it.
422 # 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
423 # These are consistent for 0.10.x, thankfully. We're not going to worry about
401 # older versions.
424 # older versions.
402 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
425 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
403 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
426 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
404
427
405 def check_for_old_config(ipython_dir=None):
428 def check_for_old_config(ipython_dir=None):
406 """Check for old config files, and present a warning if they exist.
429 """Check for old config files, and present a warning if they exist.
407
430
408 A link to the docs of the new config is included in the message.
431 A link to the docs of the new config is included in the message.
409
432
410 This should mitigate confusion with the transition to the new
433 This should mitigate confusion with the transition to the new
411 config system in 0.11.
434 config system in 0.11.
412 """
435 """
413 if ipython_dir is None:
436 if ipython_dir is None:
414 ipython_dir = get_ipython_dir()
437 ipython_dir = get_ipython_dir()
415
438
416 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
439 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
417 warned = False
440 warned = False
418 for cfg in old_configs:
441 for cfg in old_configs:
419 f = os.path.join(ipython_dir, cfg)
442 f = os.path.join(ipython_dir, cfg)
420 if os.path.exists(f):
443 if os.path.exists(f):
421 if filehash(f) == old_config_md5.get(cfg, ''):
444 if filehash(f) == old_config_md5.get(cfg, ''):
422 os.unlink(f)
445 os.unlink(f)
423 else:
446 else:
424 warnings.warn("Found old IPython config file %r (modified by user)"%f)
447 warnings.warn("Found old IPython config file %r (modified by user)"%f)
425 warned = True
448 warned = True
426
449
427 if warned:
450 if warned:
428 warnings.warn("""
451 warnings.warn("""
429 The IPython configuration system has changed as of 0.11, and these files will
452 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
453 be ignored. See http://ipython.github.com/ipython-doc/dev/config for details
431 of the new config system.
454 of the new config system.
432 To start configuring IPython, do `ipython profile create`, and edit
455 To start configuring IPython, do `ipython profile create`, and edit
433 `ipython_config.py` in <ipython_dir>/profile_default.
456 `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
457 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
458 IPython and want to suppress this warning message, set
436 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
459 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
437
460
438 def get_security_file(filename, profile='default'):
461 def get_security_file(filename, profile='default'):
439 """Return the absolute path of a security file given by filename and profile
462 """Return the absolute path of a security file given by filename and profile
440
463
441 This allows users and developers to find security files without
464 This allows users and developers to find security files without
442 knowledge of the IPython directory structure. The search path
465 knowledge of the IPython directory structure. The search path
443 will be ['.', profile.security_dir]
466 will be ['.', profile.security_dir]
444
467
445 Parameters
468 Parameters
446 ----------
469 ----------
447
470
448 filename : str
471 filename : str
449 The file to be found. If it is passed as an absolute path, it will
472 The file to be found. If it is passed as an absolute path, it will
450 simply be returned.
473 simply be returned.
451 profile : str [default: 'default']
474 profile : str [default: 'default']
452 The name of the profile to search. Leaving this unspecified
475 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
476 The file to be found. If it is passed as an absolute path, fname will
454 simply be returned.
477 simply be returned.
455
478
456 Returns
479 Returns
457 -------
480 -------
458 Raises :exc:`IOError` if file not found or returns absolute path to file.
481 Raises :exc:`IOError` if file not found or returns absolute path to file.
459 """
482 """
460 # import here, because profiledir also imports from utils.path
483 # import here, because profiledir also imports from utils.path
461 from IPython.core.profiledir import ProfileDir
484 from IPython.core.profiledir import ProfileDir
462 try:
485 try:
463 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
486 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
464 except Exception:
487 except Exception:
465 # will raise ProfileDirError if no such profile
488 # will raise ProfileDirError if no such profile
466 raise IOError("Profile %r not found")
489 raise IOError("Profile %r not found")
467 return filefind(filename, ['.', pd.security_dir])
490 return filefind(filename, ['.', pd.security_dir])
468
491
@@ -1,446 +1,492 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_equal(p,u'c:\\Documents and Settings')
377 nt.assert_equal(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_equal(p,'/usr/local')
383 nt.assert_equal(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_equal(path.unquote_filename('foo.py', win32=win32), 'foo.py')
403 nt.assert_equal(path.unquote_filename('foo.py', win32=win32), 'foo.py')
403 nt.assert_equal(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
404 nt.assert_equal(path.unquote_filename('foo bar.py', win32=win32), 'foo bar.py')
404 nt.assert_equal(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
405 nt.assert_equal(path.unquote_filename('"foo.py"', win32=True), 'foo.py')
405 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
406 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=True), 'foo bar.py')
406 nt.assert_equal(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
407 nt.assert_equal(path.unquote_filename("'foo.py'", win32=True), 'foo.py')
407 nt.assert_equal(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
408 nt.assert_equal(path.unquote_filename("'foo bar.py'", win32=True), 'foo bar.py')
408 nt.assert_equal(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
409 nt.assert_equal(path.unquote_filename('"foo.py"', win32=False), '"foo.py"')
409 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
410 nt.assert_equal(path.unquote_filename('"foo bar.py"', win32=False), '"foo bar.py"')
410 nt.assert_equal(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
411 nt.assert_equal(path.unquote_filename("'foo.py'", win32=False), "'foo.py'")
411 nt.assert_equal(path.unquote_filename("'foo bar.py'", win32=False), "'foo bar.py'")
412 nt.assert_equal(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_equal(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
419 nt.assert_equal(path.get_py_filename('foo.py', force_win32=win32), 'foo.py')
419 nt.assert_equal(path.get_py_filename('foo', force_win32=win32), 'foo.py')
420 nt.assert_equal(path.get_py_filename('foo', force_win32=win32), 'foo.py')
420 with make_tempfile('foo'):
421 with make_tempfile('foo'):
421 nt.assert_equal(path.get_py_filename('foo', force_win32=win32), 'foo')
422 nt.assert_equal(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_equal(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
428 nt.assert_equal(path.get_py_filename('foo with spaces', force_win32=win32), true_fn)
428 nt.assert_equal(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
429 nt.assert_equal(path.get_py_filename('foo with spaces.py', force_win32=win32), true_fn)
429 if win32:
430 if win32:
430 nt.assert_equal(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
431 nt.assert_equal(path.get_py_filename('"foo with spaces.py"', force_win32=True), true_fn)
431 nt.assert_equal(path.get_py_filename("'foo with spaces.py'", force_win32=True), true_fn)
432 nt.assert_equal(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_shellglob():
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.shellglob(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
479 assert_match([r'\*'], ['*'])
480 assert_match([r'a\*', 'a*'], ['a*'] + filenames_start_with_a)
481 assert_match(['a[012]'], filenames_start_with_a)
482 assert_match([r'a\[012]'], ['a[012]'])
483 finally:
484 os.chdir(save)
485
486
487 def test_unescape_glob():
488 nt.assert_equals(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
489 nt.assert_equals(path.unescape_glob(r'\\*'), r'\*')
490 nt.assert_equals(path.unescape_glob(r'\\\*'), r'\*')
491 nt.assert_equals(path.unescape_glob(r'\\a'), r'\a')
492 nt.assert_equals(path.unescape_glob(r'\a'), r'\a')
General Comments 0
You need to be logged in to leave comments. Login now