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