##// END OF EJS Templates
Fix for py2exe when using uncompressed lib/
Jorgen Stenarson -
Show More
@@ -1,2164 +1,2169 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 General purpose utilities.
4 4
5 5 This is a grab-bag of stuff I find useful in most programs I write. Some of
6 6 these things are also convenient when working at the command line.
7 7
8 8 $Id: genutils.py 2998 2008-01-31 10:06:04Z vivainio $"""
9 9
10 10 #*****************************************************************************
11 11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #*****************************************************************************
16 16
17 17 from IPython import Release
18 18 __author__ = '%s <%s>' % Release.authors['Fernando']
19 19 __license__ = Release.license
20 20
21 21 #****************************************************************************
22 22 # required modules from the Python standard library
23 23 import __main__
24 24 import commands
25 25 try:
26 26 import doctest
27 27 except ImportError:
28 28 pass
29 29 import os
30 30 import platform
31 31 import re
32 32 import shlex
33 33 import shutil
34 34 import subprocess
35 35 import sys
36 36 import tempfile
37 37 import time
38 38 import types
39 39 import warnings
40 40
41 41 # Curses and termios are Unix-only modules
42 42 try:
43 43 import curses
44 44 # We need termios as well, so if its import happens to raise, we bail on
45 45 # using curses altogether.
46 46 import termios
47 47 except ImportError:
48 48 USE_CURSES = False
49 49 else:
50 50 # Curses on Solaris may not be complete, so we can't use it there
51 51 USE_CURSES = hasattr(curses,'initscr')
52 52
53 53 # Other IPython utilities
54 54 import IPython
55 55 from IPython.Itpl import Itpl,itpl,printpl
56 56 from IPython import DPyGetOpt, platutils
57 57 from IPython.generics import result_display
58 58 import IPython.ipapi
59 59 from IPython.external.path import path
60 60 if os.name == "nt":
61 61 from IPython.winconsole import get_console_size
62 62
63 63 try:
64 64 set
65 65 except:
66 66 from sets import Set as set
67 67
68 68
69 69 #****************************************************************************
70 70 # Exceptions
71 71 class Error(Exception):
72 72 """Base class for exceptions in this module."""
73 73 pass
74 74
75 75 #----------------------------------------------------------------------------
76 76 class IOStream:
77 77 def __init__(self,stream,fallback):
78 78 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
79 79 stream = fallback
80 80 self.stream = stream
81 81 self._swrite = stream.write
82 82 self.flush = stream.flush
83 83
84 84 def write(self,data):
85 85 try:
86 86 self._swrite(data)
87 87 except:
88 88 try:
89 89 # print handles some unicode issues which may trip a plain
90 90 # write() call. Attempt to emulate write() by using a
91 91 # trailing comma
92 92 print >> self.stream, data,
93 93 except:
94 94 # if we get here, something is seriously broken.
95 95 print >> sys.stderr, \
96 96 'ERROR - failed to write data to stream:', self.stream
97 97
98 98 def close(self):
99 99 pass
100 100
101 101
102 102 class IOTerm:
103 103 """ Term holds the file or file-like objects for handling I/O operations.
104 104
105 105 These are normally just sys.stdin, sys.stdout and sys.stderr but for
106 106 Windows they can can replaced to allow editing the strings before they are
107 107 displayed."""
108 108
109 109 # In the future, having IPython channel all its I/O operations through
110 110 # this class will make it easier to embed it into other environments which
111 111 # are not a normal terminal (such as a GUI-based shell)
112 112 def __init__(self,cin=None,cout=None,cerr=None):
113 113 self.cin = IOStream(cin,sys.stdin)
114 114 self.cout = IOStream(cout,sys.stdout)
115 115 self.cerr = IOStream(cerr,sys.stderr)
116 116
117 117 # Global variable to be used for all I/O
118 118 Term = IOTerm()
119 119
120 120 import IPython.rlineimpl as readline
121 121 # Remake Term to use the readline i/o facilities
122 122 if sys.platform == 'win32' and readline.have_readline:
123 123
124 124 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
125 125
126 126
127 127 #****************************************************************************
128 128 # Generic warning/error printer, used by everything else
129 129 def warn(msg,level=2,exit_val=1):
130 130 """Standard warning printer. Gives formatting consistency.
131 131
132 132 Output is sent to Term.cerr (sys.stderr by default).
133 133
134 134 Options:
135 135
136 136 -level(2): allows finer control:
137 137 0 -> Do nothing, dummy function.
138 138 1 -> Print message.
139 139 2 -> Print 'WARNING:' + message. (Default level).
140 140 3 -> Print 'ERROR:' + message.
141 141 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
142 142
143 143 -exit_val (1): exit value returned by sys.exit() for a level 4
144 144 warning. Ignored for all other levels."""
145 145
146 146 if level>0:
147 147 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
148 148 print >> Term.cerr, '%s%s' % (header[level],msg)
149 149 if level == 4:
150 150 print >> Term.cerr,'Exiting.\n'
151 151 sys.exit(exit_val)
152 152
153 153 def info(msg):
154 154 """Equivalent to warn(msg,level=1)."""
155 155
156 156 warn(msg,level=1)
157 157
158 158 def error(msg):
159 159 """Equivalent to warn(msg,level=3)."""
160 160
161 161 warn(msg,level=3)
162 162
163 163 def fatal(msg,exit_val=1):
164 164 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
165 165
166 166 warn(msg,exit_val=exit_val,level=4)
167 167
168 168 #---------------------------------------------------------------------------
169 169 # Debugging routines
170 170 #
171 171 def debugx(expr,pre_msg=''):
172 172 """Print the value of an expression from the caller's frame.
173 173
174 174 Takes an expression, evaluates it in the caller's frame and prints both
175 175 the given expression and the resulting value (as well as a debug mark
176 176 indicating the name of the calling function. The input must be of a form
177 177 suitable for eval().
178 178
179 179 An optional message can be passed, which will be prepended to the printed
180 180 expr->value pair."""
181 181
182 182 cf = sys._getframe(1)
183 183 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
184 184 eval(expr,cf.f_globals,cf.f_locals))
185 185
186 186 # deactivate it by uncommenting the following line, which makes it a no-op
187 187 #def debugx(expr,pre_msg=''): pass
188 188
189 189 #----------------------------------------------------------------------------
190 190 StringTypes = types.StringTypes
191 191
192 192 # Basic timing functionality
193 193
194 194 # If possible (Unix), use the resource module instead of time.clock()
195 195 try:
196 196 import resource
197 197 def clocku():
198 198 """clocku() -> floating point number
199 199
200 200 Return the *USER* CPU time in seconds since the start of the process.
201 201 This is done via a call to resource.getrusage, so it avoids the
202 202 wraparound problems in time.clock()."""
203 203
204 204 return resource.getrusage(resource.RUSAGE_SELF)[0]
205 205
206 206 def clocks():
207 207 """clocks() -> floating point number
208 208
209 209 Return the *SYSTEM* CPU time in seconds since the start of the process.
210 210 This is done via a call to resource.getrusage, so it avoids the
211 211 wraparound problems in time.clock()."""
212 212
213 213 return resource.getrusage(resource.RUSAGE_SELF)[1]
214 214
215 215 def clock():
216 216 """clock() -> floating point number
217 217
218 218 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
219 219 the process. This is done via a call to resource.getrusage, so it
220 220 avoids the wraparound problems in time.clock()."""
221 221
222 222 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
223 223 return u+s
224 224
225 225 def clock2():
226 226 """clock2() -> (t_user,t_system)
227 227
228 228 Similar to clock(), but return a tuple of user/system times."""
229 229 return resource.getrusage(resource.RUSAGE_SELF)[:2]
230 230
231 231 except ImportError:
232 232 # There is no distinction of user/system time under windows, so we just use
233 233 # time.clock() for everything...
234 234 clocku = clocks = clock = time.clock
235 235 def clock2():
236 236 """Under windows, system CPU time can't be measured.
237 237
238 238 This just returns clock() and zero."""
239 239 return time.clock(),0.0
240 240
241 241 def timings_out(reps,func,*args,**kw):
242 242 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
243 243
244 244 Execute a function reps times, return a tuple with the elapsed total
245 245 CPU time in seconds, the time per call and the function's output.
246 246
247 247 Under Unix, the return value is the sum of user+system time consumed by
248 248 the process, computed via the resource module. This prevents problems
249 249 related to the wraparound effect which the time.clock() function has.
250 250
251 251 Under Windows the return value is in wall clock seconds. See the
252 252 documentation for the time module for more details."""
253 253
254 254 reps = int(reps)
255 255 assert reps >=1, 'reps must be >= 1'
256 256 if reps==1:
257 257 start = clock()
258 258 out = func(*args,**kw)
259 259 tot_time = clock()-start
260 260 else:
261 261 rng = xrange(reps-1) # the last time is executed separately to store output
262 262 start = clock()
263 263 for dummy in rng: func(*args,**kw)
264 264 out = func(*args,**kw) # one last time
265 265 tot_time = clock()-start
266 266 av_time = tot_time / reps
267 267 return tot_time,av_time,out
268 268
269 269 def timings(reps,func,*args,**kw):
270 270 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
271 271
272 272 Execute a function reps times, return a tuple with the elapsed total CPU
273 273 time in seconds and the time per call. These are just the first two values
274 274 in timings_out()."""
275 275
276 276 return timings_out(reps,func,*args,**kw)[0:2]
277 277
278 278 def timing(func,*args,**kw):
279 279 """timing(func,*args,**kw) -> t_total
280 280
281 281 Execute a function once, return the elapsed total CPU time in
282 282 seconds. This is just the first value in timings_out()."""
283 283
284 284 return timings_out(1,func,*args,**kw)[0]
285 285
286 286 #****************************************************************************
287 287 # file and system
288 288
289 289 def arg_split(s,posix=False):
290 290 """Split a command line's arguments in a shell-like manner.
291 291
292 292 This is a modified version of the standard library's shlex.split()
293 293 function, but with a default of posix=False for splitting, so that quotes
294 294 in inputs are respected."""
295 295
296 296 # XXX - there may be unicode-related problems here!!! I'm not sure that
297 297 # shlex is truly unicode-safe, so it might be necessary to do
298 298 #
299 299 # s = s.encode(sys.stdin.encoding)
300 300 #
301 301 # first, to ensure that shlex gets a normal string. Input from anyone who
302 302 # knows more about unicode and shlex than I would be good to have here...
303 303 lex = shlex.shlex(s, posix=posix)
304 304 lex.whitespace_split = True
305 305 return list(lex)
306 306
307 307 def system(cmd,verbose=0,debug=0,header=''):
308 308 """Execute a system command, return its exit status.
309 309
310 310 Options:
311 311
312 312 - verbose (0): print the command to be executed.
313 313
314 314 - debug (0): only print, do not actually execute.
315 315
316 316 - header (''): Header to print on screen prior to the executed command (it
317 317 is only prepended to the command, no newlines are added).
318 318
319 319 Note: a stateful version of this function is available through the
320 320 SystemExec class."""
321 321
322 322 stat = 0
323 323 if verbose or debug: print header+cmd
324 324 sys.stdout.flush()
325 325 if not debug: stat = os.system(cmd)
326 326 return stat
327 327
328 328 def abbrev_cwd():
329 329 """ Return abbreviated version of cwd, e.g. d:mydir """
330 330 cwd = os.getcwd().replace('\\','/')
331 331 drivepart = ''
332 332 tail = cwd
333 333 if sys.platform == 'win32':
334 334 if len(cwd) < 4:
335 335 return cwd
336 336 drivepart,tail = os.path.splitdrive(cwd)
337 337
338 338
339 339 parts = tail.split('/')
340 340 if len(parts) > 2:
341 341 tail = '/'.join(parts[-2:])
342 342
343 343 return (drivepart + (
344 344 cwd == '/' and '/' or tail))
345 345
346 346
347 347 # This function is used by ipython in a lot of places to make system calls.
348 348 # We need it to be slightly different under win32, due to the vagaries of
349 349 # 'network shares'. A win32 override is below.
350 350
351 351 def shell(cmd,verbose=0,debug=0,header=''):
352 352 """Execute a command in the system shell, always return None.
353 353
354 354 Options:
355 355
356 356 - verbose (0): print the command to be executed.
357 357
358 358 - debug (0): only print, do not actually execute.
359 359
360 360 - header (''): Header to print on screen prior to the executed command (it
361 361 is only prepended to the command, no newlines are added).
362 362
363 363 Note: this is similar to genutils.system(), but it returns None so it can
364 364 be conveniently used in interactive loops without getting the return value
365 365 (typically 0) printed many times."""
366 366
367 367 stat = 0
368 368 if verbose or debug: print header+cmd
369 369 # flush stdout so we don't mangle python's buffering
370 370 sys.stdout.flush()
371 371
372 372 if not debug:
373 373 platutils.set_term_title("IPy " + cmd)
374 374 os.system(cmd)
375 375 platutils.set_term_title("IPy " + abbrev_cwd())
376 376
377 377 # override shell() for win32 to deal with network shares
378 378 if os.name in ('nt','dos'):
379 379
380 380 shell_ori = shell
381 381
382 382 def shell(cmd,verbose=0,debug=0,header=''):
383 383 if os.getcwd().startswith(r"\\"):
384 384 path = os.getcwd()
385 385 # change to c drive (cannot be on UNC-share when issuing os.system,
386 386 # as cmd.exe cannot handle UNC addresses)
387 387 os.chdir("c:")
388 388 # issue pushd to the UNC-share and then run the command
389 389 try:
390 390 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
391 391 finally:
392 392 os.chdir(path)
393 393 else:
394 394 shell_ori(cmd,verbose,debug,header)
395 395
396 396 shell.__doc__ = shell_ori.__doc__
397 397
398 398 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
399 399 """Dummy substitute for perl's backquotes.
400 400
401 401 Executes a command and returns the output.
402 402
403 403 Accepts the same arguments as system(), plus:
404 404
405 405 - split(0): if true, the output is returned as a list split on newlines.
406 406
407 407 Note: a stateful version of this function is available through the
408 408 SystemExec class.
409 409
410 410 This is pretty much deprecated and rarely used,
411 411 genutils.getoutputerror may be what you need.
412 412
413 413 """
414 414
415 415 if verbose or debug: print header+cmd
416 416 if not debug:
417 417 output = os.popen(cmd).read()
418 418 # stipping last \n is here for backwards compat.
419 419 if output.endswith('\n'):
420 420 output = output[:-1]
421 421 if split:
422 422 return output.split('\n')
423 423 else:
424 424 return output
425 425
426 426 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
427 427 """Return (standard output,standard error) of executing cmd in a shell.
428 428
429 429 Accepts the same arguments as system(), plus:
430 430
431 431 - split(0): if true, each of stdout/err is returned as a list split on
432 432 newlines.
433 433
434 434 Note: a stateful version of this function is available through the
435 435 SystemExec class."""
436 436
437 437 if verbose or debug: print header+cmd
438 438 if not cmd:
439 439 if split:
440 440 return [],[]
441 441 else:
442 442 return '',''
443 443 if not debug:
444 444 pin,pout,perr = os.popen3(cmd)
445 445 tout = pout.read().rstrip()
446 446 terr = perr.read().rstrip()
447 447 pin.close()
448 448 pout.close()
449 449 perr.close()
450 450 if split:
451 451 return tout.split('\n'),terr.split('\n')
452 452 else:
453 453 return tout,terr
454 454
455 455 # for compatibility with older naming conventions
456 456 xsys = system
457 457 bq = getoutput
458 458
459 459 class SystemExec:
460 460 """Access the system and getoutput functions through a stateful interface.
461 461
462 462 Note: here we refer to the system and getoutput functions from this
463 463 library, not the ones from the standard python library.
464 464
465 465 This class offers the system and getoutput functions as methods, but the
466 466 verbose, debug and header parameters can be set for the instance (at
467 467 creation time or later) so that they don't need to be specified on each
468 468 call.
469 469
470 470 For efficiency reasons, there's no way to override the parameters on a
471 471 per-call basis other than by setting instance attributes. If you need
472 472 local overrides, it's best to directly call system() or getoutput().
473 473
474 474 The following names are provided as alternate options:
475 475 - xsys: alias to system
476 476 - bq: alias to getoutput
477 477
478 478 An instance can then be created as:
479 479 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
480 480 """
481 481
482 482 def __init__(self,verbose=0,debug=0,header='',split=0):
483 483 """Specify the instance's values for verbose, debug and header."""
484 484 setattr_list(self,'verbose debug header split')
485 485
486 486 def system(self,cmd):
487 487 """Stateful interface to system(), with the same keyword parameters."""
488 488
489 489 system(cmd,self.verbose,self.debug,self.header)
490 490
491 491 def shell(self,cmd):
492 492 """Stateful interface to shell(), with the same keyword parameters."""
493 493
494 494 shell(cmd,self.verbose,self.debug,self.header)
495 495
496 496 xsys = system # alias
497 497
498 498 def getoutput(self,cmd):
499 499 """Stateful interface to getoutput()."""
500 500
501 501 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
502 502
503 503 def getoutputerror(self,cmd):
504 504 """Stateful interface to getoutputerror()."""
505 505
506 506 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
507 507
508 508 bq = getoutput # alias
509 509
510 510 #-----------------------------------------------------------------------------
511 511 def mutex_opts(dict,ex_op):
512 512 """Check for presence of mutually exclusive keys in a dict.
513 513
514 514 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
515 515 for op1,op2 in ex_op:
516 516 if op1 in dict and op2 in dict:
517 517 raise ValueError,'\n*** ERROR in Arguments *** '\
518 518 'Options '+op1+' and '+op2+' are mutually exclusive.'
519 519
520 520 #-----------------------------------------------------------------------------
521 521 def get_py_filename(name):
522 522 """Return a valid python filename in the current directory.
523 523
524 524 If the given name is not a file, it adds '.py' and searches again.
525 525 Raises IOError with an informative message if the file isn't found."""
526 526
527 527 name = os.path.expanduser(name)
528 528 if not os.path.isfile(name) and not name.endswith('.py'):
529 529 name += '.py'
530 530 if os.path.isfile(name):
531 531 return name
532 532 else:
533 533 raise IOError,'File `%s` not found.' % name
534 534
535 535 #-----------------------------------------------------------------------------
536 536 def filefind(fname,alt_dirs = None):
537 537 """Return the given filename either in the current directory, if it
538 538 exists, or in a specified list of directories.
539 539
540 540 ~ expansion is done on all file and directory names.
541 541
542 542 Upon an unsuccessful search, raise an IOError exception."""
543 543
544 544 if alt_dirs is None:
545 545 try:
546 546 alt_dirs = get_home_dir()
547 547 except HomeDirError:
548 548 alt_dirs = os.getcwd()
549 549 search = [fname] + list_strings(alt_dirs)
550 550 search = map(os.path.expanduser,search)
551 551 #print 'search list for',fname,'list:',search # dbg
552 552 fname = search[0]
553 553 if os.path.isfile(fname):
554 554 return fname
555 555 for direc in search[1:]:
556 556 testname = os.path.join(direc,fname)
557 557 #print 'testname',testname # dbg
558 558 if os.path.isfile(testname):
559 559 return testname
560 560 raise IOError,'File' + `fname` + \
561 561 ' not found in current or supplied directories:' + `alt_dirs`
562 562
563 563 #----------------------------------------------------------------------------
564 564 def file_read(filename):
565 565 """Read a file and close it. Returns the file source."""
566 566 fobj = open(filename,'r');
567 567 source = fobj.read();
568 568 fobj.close()
569 569 return source
570 570
571 571 def file_readlines(filename):
572 572 """Read a file and close it. Returns the file source using readlines()."""
573 573 fobj = open(filename,'r');
574 574 lines = fobj.readlines();
575 575 fobj.close()
576 576 return lines
577 577
578 578 #----------------------------------------------------------------------------
579 579 def target_outdated(target,deps):
580 580 """Determine whether a target is out of date.
581 581
582 582 target_outdated(target,deps) -> 1/0
583 583
584 584 deps: list of filenames which MUST exist.
585 585 target: single filename which may or may not exist.
586 586
587 587 If target doesn't exist or is older than any file listed in deps, return
588 588 true, otherwise return false.
589 589 """
590 590 try:
591 591 target_time = os.path.getmtime(target)
592 592 except os.error:
593 593 return 1
594 594 for dep in deps:
595 595 dep_time = os.path.getmtime(dep)
596 596 if dep_time > target_time:
597 597 #print "For target",target,"Dep failed:",dep # dbg
598 598 #print "times (dep,tar):",dep_time,target_time # dbg
599 599 return 1
600 600 return 0
601 601
602 602 #-----------------------------------------------------------------------------
603 603 def target_update(target,deps,cmd):
604 604 """Update a target with a given command given a list of dependencies.
605 605
606 606 target_update(target,deps,cmd) -> runs cmd if target is outdated.
607 607
608 608 This is just a wrapper around target_outdated() which calls the given
609 609 command if target is outdated."""
610 610
611 611 if target_outdated(target,deps):
612 612 xsys(cmd)
613 613
614 614 #----------------------------------------------------------------------------
615 615 def unquote_ends(istr):
616 616 """Remove a single pair of quotes from the endpoints of a string."""
617 617
618 618 if not istr:
619 619 return istr
620 620 if (istr[0]=="'" and istr[-1]=="'") or \
621 621 (istr[0]=='"' and istr[-1]=='"'):
622 622 return istr[1:-1]
623 623 else:
624 624 return istr
625 625
626 626 #----------------------------------------------------------------------------
627 627 def process_cmdline(argv,names=[],defaults={},usage=''):
628 628 """ Process command-line options and arguments.
629 629
630 630 Arguments:
631 631
632 632 - argv: list of arguments, typically sys.argv.
633 633
634 634 - names: list of option names. See DPyGetOpt docs for details on options
635 635 syntax.
636 636
637 637 - defaults: dict of default values.
638 638
639 639 - usage: optional usage notice to print if a wrong argument is passed.
640 640
641 641 Return a dict of options and a list of free arguments."""
642 642
643 643 getopt = DPyGetOpt.DPyGetOpt()
644 644 getopt.setIgnoreCase(0)
645 645 getopt.parseConfiguration(names)
646 646
647 647 try:
648 648 getopt.processArguments(argv)
649 649 except DPyGetOpt.ArgumentError, exc:
650 650 print usage
651 651 warn('"%s"' % exc,level=4)
652 652
653 653 defaults.update(getopt.optionValues)
654 654 args = getopt.freeValues
655 655
656 656 return defaults,args
657 657
658 658 #----------------------------------------------------------------------------
659 659 def optstr2types(ostr):
660 660 """Convert a string of option names to a dict of type mappings.
661 661
662 662 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
663 663
664 664 This is used to get the types of all the options in a string formatted
665 665 with the conventions of DPyGetOpt. The 'type' None is used for options
666 666 which are strings (they need no further conversion). This function's main
667 667 use is to get a typemap for use with read_dict().
668 668 """
669 669
670 670 typeconv = {None:'',int:'',float:''}
671 671 typemap = {'s':None,'i':int,'f':float}
672 672 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
673 673
674 674 for w in ostr.split():
675 675 oname,alias,otype = opt_re.match(w).groups()
676 676 if otype == '' or alias == '!': # simple switches are integers too
677 677 otype = 'i'
678 678 typeconv[typemap[otype]] += oname + ' '
679 679 return typeconv
680 680
681 681 #----------------------------------------------------------------------------
682 682 def read_dict(filename,type_conv=None,**opt):
683 683 r"""Read a dictionary of key=value pairs from an input file, optionally
684 684 performing conversions on the resulting values.
685 685
686 686 read_dict(filename,type_conv,**opt) -> dict
687 687
688 688 Only one value per line is accepted, the format should be
689 689 # optional comments are ignored
690 690 key value\n
691 691
692 692 Args:
693 693
694 694 - type_conv: A dictionary specifying which keys need to be converted to
695 695 which types. By default all keys are read as strings. This dictionary
696 696 should have as its keys valid conversion functions for strings
697 697 (int,long,float,complex, or your own). The value for each key
698 698 (converter) should be a whitespace separated string containing the names
699 699 of all the entries in the file to be converted using that function. For
700 700 keys to be left alone, use None as the conversion function (only needed
701 701 with purge=1, see below).
702 702
703 703 - opt: dictionary with extra options as below (default in parens)
704 704
705 705 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
706 706 of the dictionary to be returned. If purge is going to be used, the
707 707 set of keys to be left as strings also has to be explicitly specified
708 708 using the (non-existent) conversion function None.
709 709
710 710 fs(None): field separator. This is the key/value separator to be used
711 711 when parsing the file. The None default means any whitespace [behavior
712 712 of string.split()].
713 713
714 714 strip(0): if 1, strip string values of leading/trailinig whitespace.
715 715
716 716 warn(1): warning level if requested keys are not found in file.
717 717 - 0: silently ignore.
718 718 - 1: inform but proceed.
719 719 - 2: raise KeyError exception.
720 720
721 721 no_empty(0): if 1, remove keys with whitespace strings as a value.
722 722
723 723 unique([]): list of keys (or space separated string) which can't be
724 724 repeated. If one such key is found in the file, each new instance
725 725 overwrites the previous one. For keys not listed here, the behavior is
726 726 to make a list of all appearances.
727 727
728 728 Example:
729 729
730 730 If the input file test.ini contains (we put it in a string to keep the test
731 731 self-contained):
732 732
733 733 >>> test_ini = '''\
734 734 ... i 3
735 735 ... x 4.5
736 736 ... y 5.5
737 737 ... s hi ho'''
738 738
739 739 Then we can use it as follows:
740 740 >>> type_conv={int:'i',float:'x',None:'s'}
741 741
742 742 >>> d = read_dict(test_ini)
743 743
744 744 >>> sorted(d.items())
745 745 [('i', '3'), ('s', 'hi ho'), ('x', '4.5'), ('y', '5.5')]
746 746
747 747 >>> d = read_dict(test_ini,type_conv)
748 748
749 749 >>> sorted(d.items())
750 750 [('i', 3), ('s', 'hi ho'), ('x', 4.5), ('y', '5.5')]
751 751
752 752 >>> d = read_dict(test_ini,type_conv,purge=True)
753 753
754 754 >>> sorted(d.items())
755 755 [('i', 3), ('s', 'hi ho'), ('x', 4.5)]
756 756 """
757 757
758 758 # starting config
759 759 opt.setdefault('purge',0)
760 760 opt.setdefault('fs',None) # field sep defaults to any whitespace
761 761 opt.setdefault('strip',0)
762 762 opt.setdefault('warn',1)
763 763 opt.setdefault('no_empty',0)
764 764 opt.setdefault('unique','')
765 765 if type(opt['unique']) in StringTypes:
766 766 unique_keys = qw(opt['unique'])
767 767 elif type(opt['unique']) in (types.TupleType,types.ListType):
768 768 unique_keys = opt['unique']
769 769 else:
770 770 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
771 771
772 772 dict = {}
773 773
774 774 # first read in table of values as strings
775 775 if '\n' in filename:
776 776 lines = filename.splitlines()
777 777 file = None
778 778 else:
779 779 file = open(filename,'r')
780 780 lines = file.readlines()
781 781 for line in lines:
782 782 line = line.strip()
783 783 if len(line) and line[0]=='#': continue
784 784 if len(line)>0:
785 785 lsplit = line.split(opt['fs'],1)
786 786 try:
787 787 key,val = lsplit
788 788 except ValueError:
789 789 key,val = lsplit[0],''
790 790 key = key.strip()
791 791 if opt['strip']: val = val.strip()
792 792 if val == "''" or val == '""': val = ''
793 793 if opt['no_empty'] and (val=='' or val.isspace()):
794 794 continue
795 795 # if a key is found more than once in the file, build a list
796 796 # unless it's in the 'unique' list. In that case, last found in file
797 797 # takes precedence. User beware.
798 798 try:
799 799 if dict[key] and key in unique_keys:
800 800 dict[key] = val
801 801 elif type(dict[key]) is types.ListType:
802 802 dict[key].append(val)
803 803 else:
804 804 dict[key] = [dict[key],val]
805 805 except KeyError:
806 806 dict[key] = val
807 807 # purge if requested
808 808 if opt['purge']:
809 809 accepted_keys = qwflat(type_conv.values())
810 810 for key in dict.keys():
811 811 if key in accepted_keys: continue
812 812 del(dict[key])
813 813 # now convert if requested
814 814 if type_conv==None: return dict
815 815 conversions = type_conv.keys()
816 816 try: conversions.remove(None)
817 817 except: pass
818 818 for convert in conversions:
819 819 for val in qw(type_conv[convert]):
820 820 try:
821 821 dict[val] = convert(dict[val])
822 822 except KeyError,e:
823 823 if opt['warn'] == 0:
824 824 pass
825 825 elif opt['warn'] == 1:
826 826 print >>sys.stderr, 'Warning: key',val,\
827 827 'not found in file',filename
828 828 elif opt['warn'] == 2:
829 829 raise KeyError,e
830 830 else:
831 831 raise ValueError,'Warning level must be 0,1 or 2'
832 832
833 833 return dict
834 834
835 835 #----------------------------------------------------------------------------
836 836 def flag_calls(func):
837 837 """Wrap a function to detect and flag when it gets called.
838 838
839 839 This is a decorator which takes a function and wraps it in a function with
840 840 a 'called' attribute. wrapper.called is initialized to False.
841 841
842 842 The wrapper.called attribute is set to False right before each call to the
843 843 wrapped function, so if the call fails it remains False. After the call
844 844 completes, wrapper.called is set to True and the output is returned.
845 845
846 846 Testing for truth in wrapper.called allows you to determine if a call to
847 847 func() was attempted and succeeded."""
848 848
849 849 def wrapper(*args,**kw):
850 850 wrapper.called = False
851 851 out = func(*args,**kw)
852 852 wrapper.called = True
853 853 return out
854 854
855 855 wrapper.called = False
856 856 wrapper.__doc__ = func.__doc__
857 857 return wrapper
858 858
859 859 #----------------------------------------------------------------------------
860 860 def dhook_wrap(func,*a,**k):
861 861 """Wrap a function call in a sys.displayhook controller.
862 862
863 863 Returns a wrapper around func which calls func, with all its arguments and
864 864 keywords unmodified, using the default sys.displayhook. Since IPython
865 865 modifies sys.displayhook, it breaks the behavior of certain systems that
866 866 rely on the default behavior, notably doctest.
867 867 """
868 868
869 869 def f(*a,**k):
870 870
871 871 dhook_s = sys.displayhook
872 872 sys.displayhook = sys.__displayhook__
873 873 try:
874 874 out = func(*a,**k)
875 875 finally:
876 876 sys.displayhook = dhook_s
877 877
878 878 return out
879 879
880 880 f.__doc__ = func.__doc__
881 881 return f
882 882
883 883 #----------------------------------------------------------------------------
884 884 def doctest_reload():
885 885 """Properly reload doctest to reuse it interactively.
886 886
887 887 This routine:
888 888
889 889 - reloads doctest
890 890
891 891 - resets its global 'master' attribute to None, so that multiple uses of
892 892 the module interactively don't produce cumulative reports.
893 893
894 894 - Monkeypatches its core test runner method to protect it from IPython's
895 895 modified displayhook. Doctest expects the default displayhook behavior
896 896 deep down, so our modification breaks it completely. For this reason, a
897 897 hard monkeypatch seems like a reasonable solution rather than asking
898 898 users to manually use a different doctest runner when under IPython."""
899 899
900 900 import doctest
901 901 reload(doctest)
902 902 doctest.master=None
903 903
904 904 try:
905 905 doctest.DocTestRunner
906 906 except AttributeError:
907 907 # This is only for python 2.3 compatibility, remove once we move to
908 908 # 2.4 only.
909 909 pass
910 910 else:
911 911 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
912 912
913 913 #----------------------------------------------------------------------------
914 914 class HomeDirError(Error):
915 915 pass
916 916
917 917 def get_home_dir():
918 918 """Return the closest possible equivalent to a 'home' directory.
919 919
920 920 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
921 921
922 922 Currently only Posix and NT are implemented, a HomeDirError exception is
923 923 raised for all other OSes. """
924 924
925 925 isdir = os.path.isdir
926 926 env = os.environ
927 927
928 928 # first, check py2exe distribution root directory for _ipython.
929 929 # This overrides all. Normally does not exist.
930 930
931 if '\\library.zip\\' in IPython.__file__.lower():
932 root, rest = IPython.__file__.lower().split('library.zip')
933 if isdir(root + '_ipython'):
931 if hasattr(sys, "frozen"): #Is frozen by py2exe
932 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
933 root, rest = IPython.__file__.lower().split('library.zip')
934 if isdir(root + '_ipython'):
935 os.environ["IPYKITROOT"] = root.rstrip('\\')
936 return root
937 else:
938 root=os.path.abspath(os.path.join(os.path.split(IPython.__file__)[0],"../../"))
939 if isdir(os.path.join(root, '_ipython')):
934 940 os.environ["IPYKITROOT"] = root.rstrip('\\')
935 941 return root
936
937 942 try:
938 943 homedir = env['HOME']
939 944 if not isdir(homedir):
940 945 # in case a user stuck some string which does NOT resolve to a
941 946 # valid path, it's as good as if we hadn't foud it
942 947 raise KeyError
943 948 return homedir
944 949 except KeyError:
945 950 if os.name == 'posix':
946 951 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
947 952 elif os.name == 'nt':
948 953 # For some strange reason, win9x returns 'nt' for os.name.
949 954 try:
950 955 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
951 956 if not isdir(homedir):
952 957 homedir = os.path.join(env['USERPROFILE'])
953 958 if not isdir(homedir):
954 959 raise HomeDirError
955 960 return homedir
956 961 except:
957 962 try:
958 963 # Use the registry to get the 'My Documents' folder.
959 964 import _winreg as wreg
960 965 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
961 966 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
962 967 homedir = wreg.QueryValueEx(key,'Personal')[0]
963 968 key.Close()
964 969 if not isdir(homedir):
965 970 e = ('Invalid "Personal" folder registry key '
966 971 'typically "My Documents".\n'
967 972 'Value: %s\n'
968 973 'This is not a valid directory on your system.' %
969 974 homedir)
970 975 raise HomeDirError(e)
971 976 return homedir
972 977 except HomeDirError:
973 978 raise
974 979 except:
975 980 return 'C:\\'
976 981 elif os.name == 'dos':
977 982 # Desperate, may do absurd things in classic MacOS. May work under DOS.
978 983 return 'C:\\'
979 984 else:
980 985 raise HomeDirError,'support for your operating system not implemented.'
981 986
982 987
983 988 def get_ipython_dir():
984 989 """Get the IPython directory for this platform and user.
985 990
986 991 This uses the logic in `get_home_dir` to find the home directory
987 992 and the adds either .ipython or _ipython to the end of the path.
988 993 """
989 994 if os.name == 'posix':
990 995 ipdir_def = '.ipython'
991 996 else:
992 997 ipdir_def = '_ipython'
993 998 home_dir = get_home_dir()
994 999 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
995 1000 os.path.join(home_dir,ipdir_def)))
996 1001 return ipdir
997 1002
998 1003 def get_security_dir():
999 1004 """Get the IPython security directory.
1000 1005
1001 1006 This directory is the default location for all security related files,
1002 1007 including SSL/TLS certificates and FURL files.
1003 1008
1004 1009 If the directory does not exist, it is created with 0700 permissions.
1005 1010 If it exists, permissions are set to 0700.
1006 1011 """
1007 1012 security_dir = os.path.join(get_ipython_dir(), 'security')
1008 1013 if not os.path.isdir(security_dir):
1009 1014 os.mkdir(security_dir, 0700)
1010 1015 else:
1011 1016 os.chmod(security_dir, 0700)
1012 1017 return security_dir
1013 1018
1014 1019 #****************************************************************************
1015 1020 # strings and text
1016 1021
1017 1022 class LSString(str):
1018 1023 """String derivative with a special access attributes.
1019 1024
1020 1025 These are normal strings, but with the special attributes:
1021 1026
1022 1027 .l (or .list) : value as list (split on newlines).
1023 1028 .n (or .nlstr): original value (the string itself).
1024 1029 .s (or .spstr): value as whitespace-separated string.
1025 1030 .p (or .paths): list of path objects
1026 1031
1027 1032 Any values which require transformations are computed only once and
1028 1033 cached.
1029 1034
1030 1035 Such strings are very useful to efficiently interact with the shell, which
1031 1036 typically only understands whitespace-separated options for commands."""
1032 1037
1033 1038 def get_list(self):
1034 1039 try:
1035 1040 return self.__list
1036 1041 except AttributeError:
1037 1042 self.__list = self.split('\n')
1038 1043 return self.__list
1039 1044
1040 1045 l = list = property(get_list)
1041 1046
1042 1047 def get_spstr(self):
1043 1048 try:
1044 1049 return self.__spstr
1045 1050 except AttributeError:
1046 1051 self.__spstr = self.replace('\n',' ')
1047 1052 return self.__spstr
1048 1053
1049 1054 s = spstr = property(get_spstr)
1050 1055
1051 1056 def get_nlstr(self):
1052 1057 return self
1053 1058
1054 1059 n = nlstr = property(get_nlstr)
1055 1060
1056 1061 def get_paths(self):
1057 1062 try:
1058 1063 return self.__paths
1059 1064 except AttributeError:
1060 1065 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1061 1066 return self.__paths
1062 1067
1063 1068 p = paths = property(get_paths)
1064 1069
1065 1070 def print_lsstring(arg):
1066 1071 """ Prettier (non-repr-like) and more informative printer for LSString """
1067 1072 print "LSString (.p, .n, .l, .s available). Value:"
1068 1073 print arg
1069 1074
1070 1075 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1071 1076
1072 1077 #----------------------------------------------------------------------------
1073 1078 class SList(list):
1074 1079 """List derivative with a special access attributes.
1075 1080
1076 1081 These are normal lists, but with the special attributes:
1077 1082
1078 1083 .l (or .list) : value as list (the list itself).
1079 1084 .n (or .nlstr): value as a string, joined on newlines.
1080 1085 .s (or .spstr): value as a string, joined on spaces.
1081 1086 .p (or .paths): list of path objects
1082 1087
1083 1088 Any values which require transformations are computed only once and
1084 1089 cached."""
1085 1090
1086 1091 def get_list(self):
1087 1092 return self
1088 1093
1089 1094 l = list = property(get_list)
1090 1095
1091 1096 def get_spstr(self):
1092 1097 try:
1093 1098 return self.__spstr
1094 1099 except AttributeError:
1095 1100 self.__spstr = ' '.join(self)
1096 1101 return self.__spstr
1097 1102
1098 1103 s = spstr = property(get_spstr)
1099 1104
1100 1105 def get_nlstr(self):
1101 1106 try:
1102 1107 return self.__nlstr
1103 1108 except AttributeError:
1104 1109 self.__nlstr = '\n'.join(self)
1105 1110 return self.__nlstr
1106 1111
1107 1112 n = nlstr = property(get_nlstr)
1108 1113
1109 1114 def get_paths(self):
1110 1115 try:
1111 1116 return self.__paths
1112 1117 except AttributeError:
1113 1118 self.__paths = [path(p) for p in self if os.path.exists(p)]
1114 1119 return self.__paths
1115 1120
1116 1121 p = paths = property(get_paths)
1117 1122
1118 1123 def grep(self, pattern, prune = False, field = None):
1119 1124 """ Return all strings matching 'pattern' (a regex or callable)
1120 1125
1121 1126 This is case-insensitive. If prune is true, return all items
1122 1127 NOT matching the pattern.
1123 1128
1124 1129 If field is specified, the match must occur in the specified
1125 1130 whitespace-separated field.
1126 1131
1127 1132 Examples::
1128 1133
1129 1134 a.grep( lambda x: x.startswith('C') )
1130 1135 a.grep('Cha.*log', prune=1)
1131 1136 a.grep('chm', field=-1)
1132 1137 """
1133 1138
1134 1139 def match_target(s):
1135 1140 if field is None:
1136 1141 return s
1137 1142 parts = s.split()
1138 1143 try:
1139 1144 tgt = parts[field]
1140 1145 return tgt
1141 1146 except IndexError:
1142 1147 return ""
1143 1148
1144 1149 if isinstance(pattern, basestring):
1145 1150 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1146 1151 else:
1147 1152 pred = pattern
1148 1153 if not prune:
1149 1154 return SList([el for el in self if pred(match_target(el))])
1150 1155 else:
1151 1156 return SList([el for el in self if not pred(match_target(el))])
1152 1157 def fields(self, *fields):
1153 1158 """ Collect whitespace-separated fields from string list
1154 1159
1155 1160 Allows quick awk-like usage of string lists.
1156 1161
1157 1162 Example data (in var a, created by 'a = !ls -l')::
1158 1163 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1159 1164 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1160 1165
1161 1166 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1162 1167 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1163 1168 (note the joining by space).
1164 1169 a.fields(-1) is ['ChangeLog', 'IPython']
1165 1170
1166 1171 IndexErrors are ignored.
1167 1172
1168 1173 Without args, fields() just split()'s the strings.
1169 1174 """
1170 1175 if len(fields) == 0:
1171 1176 return [el.split() for el in self]
1172 1177
1173 1178 res = SList()
1174 1179 for el in [f.split() for f in self]:
1175 1180 lineparts = []
1176 1181
1177 1182 for fd in fields:
1178 1183 try:
1179 1184 lineparts.append(el[fd])
1180 1185 except IndexError:
1181 1186 pass
1182 1187 if lineparts:
1183 1188 res.append(" ".join(lineparts))
1184 1189
1185 1190 return res
1186 1191 def sort(self,field= None, nums = False):
1187 1192 """ sort by specified fields (see fields())
1188 1193
1189 1194 Example::
1190 1195 a.sort(1, nums = True)
1191 1196
1192 1197 Sorts a by second field, in numerical order (so that 21 > 3)
1193 1198
1194 1199 """
1195 1200
1196 1201 #decorate, sort, undecorate
1197 1202 if field is not None:
1198 1203 dsu = [[SList([line]).fields(field), line] for line in self]
1199 1204 else:
1200 1205 dsu = [[line, line] for line in self]
1201 1206 if nums:
1202 1207 for i in range(len(dsu)):
1203 1208 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1204 1209 try:
1205 1210 n = int(numstr)
1206 1211 except ValueError:
1207 1212 n = 0;
1208 1213 dsu[i][0] = n
1209 1214
1210 1215
1211 1216 dsu.sort()
1212 1217 return SList([t[1] for t in dsu])
1213 1218
1214 1219 def print_slist(arg):
1215 1220 """ Prettier (non-repr-like) and more informative printer for SList """
1216 1221 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1217 1222 if hasattr(arg, 'hideonce') and arg.hideonce:
1218 1223 arg.hideonce = False
1219 1224 return
1220 1225
1221 1226 nlprint(arg)
1222 1227
1223 1228 print_slist = result_display.when_type(SList)(print_slist)
1224 1229
1225 1230
1226 1231
1227 1232 #----------------------------------------------------------------------------
1228 1233 def esc_quotes(strng):
1229 1234 """Return the input string with single and double quotes escaped out"""
1230 1235
1231 1236 return strng.replace('"','\\"').replace("'","\\'")
1232 1237
1233 1238 #----------------------------------------------------------------------------
1234 1239 def make_quoted_expr(s):
1235 1240 """Return string s in appropriate quotes, using raw string if possible.
1236 1241
1237 1242 Effectively this turns string: cd \ao\ao\
1238 1243 to: r"cd \ao\ao\_"[:-1]
1239 1244
1240 1245 Note the use of raw string and padding at the end to allow trailing backslash.
1241 1246
1242 1247 """
1243 1248
1244 1249 tail = ''
1245 1250 tailpadding = ''
1246 1251 raw = ''
1247 1252 if "\\" in s:
1248 1253 raw = 'r'
1249 1254 if s.endswith('\\'):
1250 1255 tail = '[:-1]'
1251 1256 tailpadding = '_'
1252 1257 if '"' not in s:
1253 1258 quote = '"'
1254 1259 elif "'" not in s:
1255 1260 quote = "'"
1256 1261 elif '"""' not in s and not s.endswith('"'):
1257 1262 quote = '"""'
1258 1263 elif "'''" not in s and not s.endswith("'"):
1259 1264 quote = "'''"
1260 1265 else:
1261 1266 # give up, backslash-escaped string will do
1262 1267 return '"%s"' % esc_quotes(s)
1263 1268 res = raw + quote + s + tailpadding + quote + tail
1264 1269 return res
1265 1270
1266 1271
1267 1272 #----------------------------------------------------------------------------
1268 1273 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1269 1274 """Take multiple lines of input.
1270 1275
1271 1276 A list with each line of input as a separate element is returned when a
1272 1277 termination string is entered (defaults to a single '.'). Input can also
1273 1278 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1274 1279
1275 1280 Lines of input which end in \\ are joined into single entries (and a
1276 1281 secondary continuation prompt is issued as long as the user terminates
1277 1282 lines with \\). This allows entering very long strings which are still
1278 1283 meant to be treated as single entities.
1279 1284 """
1280 1285
1281 1286 try:
1282 1287 if header:
1283 1288 header += '\n'
1284 1289 lines = [raw_input(header + ps1)]
1285 1290 except EOFError:
1286 1291 return []
1287 1292 terminate = [terminate_str]
1288 1293 try:
1289 1294 while lines[-1:] != terminate:
1290 1295 new_line = raw_input(ps1)
1291 1296 while new_line.endswith('\\'):
1292 1297 new_line = new_line[:-1] + raw_input(ps2)
1293 1298 lines.append(new_line)
1294 1299
1295 1300 return lines[:-1] # don't return the termination command
1296 1301 except EOFError:
1297 1302 print
1298 1303 return lines
1299 1304
1300 1305 #----------------------------------------------------------------------------
1301 1306 def raw_input_ext(prompt='', ps2='... '):
1302 1307 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1303 1308
1304 1309 line = raw_input(prompt)
1305 1310 while line.endswith('\\'):
1306 1311 line = line[:-1] + raw_input(ps2)
1307 1312 return line
1308 1313
1309 1314 #----------------------------------------------------------------------------
1310 1315 def ask_yes_no(prompt,default=None):
1311 1316 """Asks a question and returns a boolean (y/n) answer.
1312 1317
1313 1318 If default is given (one of 'y','n'), it is used if the user input is
1314 1319 empty. Otherwise the question is repeated until an answer is given.
1315 1320
1316 1321 An EOF is treated as the default answer. If there is no default, an
1317 1322 exception is raised to prevent infinite loops.
1318 1323
1319 1324 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1320 1325
1321 1326 answers = {'y':True,'n':False,'yes':True,'no':False}
1322 1327 ans = None
1323 1328 while ans not in answers.keys():
1324 1329 try:
1325 1330 ans = raw_input(prompt+' ').lower()
1326 1331 if not ans: # response was an empty string
1327 1332 ans = default
1328 1333 except KeyboardInterrupt:
1329 1334 pass
1330 1335 except EOFError:
1331 1336 if default in answers.keys():
1332 1337 ans = default
1333 1338 print
1334 1339 else:
1335 1340 raise
1336 1341
1337 1342 return answers[ans]
1338 1343
1339 1344 #----------------------------------------------------------------------------
1340 1345 def marquee(txt='',width=78,mark='*'):
1341 1346 """Return the input string centered in a 'marquee'."""
1342 1347 if not txt:
1343 1348 return (mark*width)[:width]
1344 1349 nmark = (width-len(txt)-2)/len(mark)/2
1345 1350 if nmark < 0: nmark =0
1346 1351 marks = mark*nmark
1347 1352 return '%s %s %s' % (marks,txt,marks)
1348 1353
1349 1354 #----------------------------------------------------------------------------
1350 1355 class EvalDict:
1351 1356 """
1352 1357 Emulate a dict which evaluates its contents in the caller's frame.
1353 1358
1354 1359 Usage:
1355 1360 >>> number = 19
1356 1361
1357 1362 >>> text = "python"
1358 1363
1359 1364 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1360 1365 Python 2.1 rules!
1361 1366 """
1362 1367
1363 1368 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1364 1369 # modified (shorter) version of:
1365 1370 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1366 1371 # Skip Montanaro (skip@pobox.com).
1367 1372
1368 1373 def __getitem__(self, name):
1369 1374 frame = sys._getframe(1)
1370 1375 return eval(name, frame.f_globals, frame.f_locals)
1371 1376
1372 1377 EvalString = EvalDict # for backwards compatibility
1373 1378 #----------------------------------------------------------------------------
1374 1379 def qw(words,flat=0,sep=None,maxsplit=-1):
1375 1380 """Similar to Perl's qw() operator, but with some more options.
1376 1381
1377 1382 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1378 1383
1379 1384 words can also be a list itself, and with flat=1, the output will be
1380 1385 recursively flattened.
1381 1386
1382 1387 Examples:
1383 1388
1384 1389 >>> qw('1 2')
1385 1390 ['1', '2']
1386 1391
1387 1392 >>> qw(['a b','1 2',['m n','p q']])
1388 1393 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1389 1394
1390 1395 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1391 1396 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1392 1397 """
1393 1398
1394 1399 if type(words) in StringTypes:
1395 1400 return [word.strip() for word in words.split(sep,maxsplit)
1396 1401 if word and not word.isspace() ]
1397 1402 if flat:
1398 1403 return flatten(map(qw,words,[1]*len(words)))
1399 1404 return map(qw,words)
1400 1405
1401 1406 #----------------------------------------------------------------------------
1402 1407 def qwflat(words,sep=None,maxsplit=-1):
1403 1408 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1404 1409 return qw(words,1,sep,maxsplit)
1405 1410
1406 1411 #----------------------------------------------------------------------------
1407 1412 def qw_lol(indata):
1408 1413 """qw_lol('a b') -> [['a','b']],
1409 1414 otherwise it's just a call to qw().
1410 1415
1411 1416 We need this to make sure the modules_some keys *always* end up as a
1412 1417 list of lists."""
1413 1418
1414 1419 if type(indata) in StringTypes:
1415 1420 return [qw(indata)]
1416 1421 else:
1417 1422 return qw(indata)
1418 1423
1419 1424 #-----------------------------------------------------------------------------
1420 1425 def list_strings(arg):
1421 1426 """Always return a list of strings, given a string or list of strings
1422 1427 as input."""
1423 1428
1424 1429 if type(arg) in StringTypes: return [arg]
1425 1430 else: return arg
1426 1431
1427 1432 #----------------------------------------------------------------------------
1428 1433 def grep(pat,list,case=1):
1429 1434 """Simple minded grep-like function.
1430 1435 grep(pat,list) returns occurrences of pat in list, None on failure.
1431 1436
1432 1437 It only does simple string matching, with no support for regexps. Use the
1433 1438 option case=0 for case-insensitive matching."""
1434 1439
1435 1440 # This is pretty crude. At least it should implement copying only references
1436 1441 # to the original data in case it's big. Now it copies the data for output.
1437 1442 out=[]
1438 1443 if case:
1439 1444 for term in list:
1440 1445 if term.find(pat)>-1: out.append(term)
1441 1446 else:
1442 1447 lpat=pat.lower()
1443 1448 for term in list:
1444 1449 if term.lower().find(lpat)>-1: out.append(term)
1445 1450
1446 1451 if len(out): return out
1447 1452 else: return None
1448 1453
1449 1454 #----------------------------------------------------------------------------
1450 1455 def dgrep(pat,*opts):
1451 1456 """Return grep() on dir()+dir(__builtins__).
1452 1457
1453 1458 A very common use of grep() when working interactively."""
1454 1459
1455 1460 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1456 1461
1457 1462 #----------------------------------------------------------------------------
1458 1463 def idgrep(pat):
1459 1464 """Case-insensitive dgrep()"""
1460 1465
1461 1466 return dgrep(pat,0)
1462 1467
1463 1468 #----------------------------------------------------------------------------
1464 1469 def igrep(pat,list):
1465 1470 """Synonym for case-insensitive grep."""
1466 1471
1467 1472 return grep(pat,list,case=0)
1468 1473
1469 1474 #----------------------------------------------------------------------------
1470 1475 def indent(str,nspaces=4,ntabs=0):
1471 1476 """Indent a string a given number of spaces or tabstops.
1472 1477
1473 1478 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1474 1479 """
1475 1480 if str is None:
1476 1481 return
1477 1482 ind = '\t'*ntabs+' '*nspaces
1478 1483 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1479 1484 if outstr.endswith(os.linesep+ind):
1480 1485 return outstr[:-len(ind)]
1481 1486 else:
1482 1487 return outstr
1483 1488
1484 1489 #-----------------------------------------------------------------------------
1485 1490 def native_line_ends(filename,backup=1):
1486 1491 """Convert (in-place) a file to line-ends native to the current OS.
1487 1492
1488 1493 If the optional backup argument is given as false, no backup of the
1489 1494 original file is left. """
1490 1495
1491 1496 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1492 1497
1493 1498 bak_filename = filename + backup_suffixes[os.name]
1494 1499
1495 1500 original = open(filename).read()
1496 1501 shutil.copy2(filename,bak_filename)
1497 1502 try:
1498 1503 new = open(filename,'wb')
1499 1504 new.write(os.linesep.join(original.splitlines()))
1500 1505 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1501 1506 new.close()
1502 1507 except:
1503 1508 os.rename(bak_filename,filename)
1504 1509 if not backup:
1505 1510 try:
1506 1511 os.remove(bak_filename)
1507 1512 except:
1508 1513 pass
1509 1514
1510 1515 #----------------------------------------------------------------------------
1511 1516 def get_pager_cmd(pager_cmd = None):
1512 1517 """Return a pager command.
1513 1518
1514 1519 Makes some attempts at finding an OS-correct one."""
1515 1520
1516 1521 if os.name == 'posix':
1517 1522 default_pager_cmd = 'less -r' # -r for color control sequences
1518 1523 elif os.name in ['nt','dos']:
1519 1524 default_pager_cmd = 'type'
1520 1525
1521 1526 if pager_cmd is None:
1522 1527 try:
1523 1528 pager_cmd = os.environ['PAGER']
1524 1529 except:
1525 1530 pager_cmd = default_pager_cmd
1526 1531 return pager_cmd
1527 1532
1528 1533 #-----------------------------------------------------------------------------
1529 1534 def get_pager_start(pager,start):
1530 1535 """Return the string for paging files with an offset.
1531 1536
1532 1537 This is the '+N' argument which less and more (under Unix) accept.
1533 1538 """
1534 1539
1535 1540 if pager in ['less','more']:
1536 1541 if start:
1537 1542 start_string = '+' + str(start)
1538 1543 else:
1539 1544 start_string = ''
1540 1545 else:
1541 1546 start_string = ''
1542 1547 return start_string
1543 1548
1544 1549 #----------------------------------------------------------------------------
1545 1550 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1546 1551 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1547 1552 import msvcrt
1548 1553 def page_more():
1549 1554 """ Smart pausing between pages
1550 1555
1551 1556 @return: True if need print more lines, False if quit
1552 1557 """
1553 1558 Term.cout.write('---Return to continue, q to quit--- ')
1554 1559 ans = msvcrt.getch()
1555 1560 if ans in ("q", "Q"):
1556 1561 result = False
1557 1562 else:
1558 1563 result = True
1559 1564 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1560 1565 return result
1561 1566 else:
1562 1567 def page_more():
1563 1568 ans = raw_input('---Return to continue, q to quit--- ')
1564 1569 if ans.lower().startswith('q'):
1565 1570 return False
1566 1571 else:
1567 1572 return True
1568 1573
1569 1574 esc_re = re.compile(r"(\x1b[^m]+m)")
1570 1575
1571 1576 def page_dumb(strng,start=0,screen_lines=25):
1572 1577 """Very dumb 'pager' in Python, for when nothing else works.
1573 1578
1574 1579 Only moves forward, same interface as page(), except for pager_cmd and
1575 1580 mode."""
1576 1581
1577 1582 out_ln = strng.splitlines()[start:]
1578 1583 screens = chop(out_ln,screen_lines-1)
1579 1584 if len(screens) == 1:
1580 1585 print >>Term.cout, os.linesep.join(screens[0])
1581 1586 else:
1582 1587 last_escape = ""
1583 1588 for scr in screens[0:-1]:
1584 1589 hunk = os.linesep.join(scr)
1585 1590 print >>Term.cout, last_escape + hunk
1586 1591 if not page_more():
1587 1592 return
1588 1593 esc_list = esc_re.findall(hunk)
1589 1594 if len(esc_list) > 0:
1590 1595 last_escape = esc_list[-1]
1591 1596 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1592 1597
1593 1598 #----------------------------------------------------------------------------
1594 1599 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1595 1600 """Print a string, piping through a pager after a certain length.
1596 1601
1597 1602 The screen_lines parameter specifies the number of *usable* lines of your
1598 1603 terminal screen (total lines minus lines you need to reserve to show other
1599 1604 information).
1600 1605
1601 1606 If you set screen_lines to a number <=0, page() will try to auto-determine
1602 1607 your screen size and will only use up to (screen_size+screen_lines) for
1603 1608 printing, paging after that. That is, if you want auto-detection but need
1604 1609 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1605 1610 auto-detection without any lines reserved simply use screen_lines = 0.
1606 1611
1607 1612 If a string won't fit in the allowed lines, it is sent through the
1608 1613 specified pager command. If none given, look for PAGER in the environment,
1609 1614 and ultimately default to less.
1610 1615
1611 1616 If no system pager works, the string is sent through a 'dumb pager'
1612 1617 written in python, very simplistic.
1613 1618 """
1614 1619
1615 1620 # Some routines may auto-compute start offsets incorrectly and pass a
1616 1621 # negative value. Offset to 0 for robustness.
1617 1622 start = max(0,start)
1618 1623
1619 1624 # first, try the hook
1620 1625 ip = IPython.ipapi.get()
1621 1626 if ip:
1622 1627 try:
1623 1628 ip.IP.hooks.show_in_pager(strng)
1624 1629 return
1625 1630 except IPython.ipapi.TryNext:
1626 1631 pass
1627 1632
1628 1633 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1629 1634 TERM = os.environ.get('TERM','dumb')
1630 1635 if TERM in ['dumb','emacs'] and os.name != 'nt':
1631 1636 print strng
1632 1637 return
1633 1638 # chop off the topmost part of the string we don't want to see
1634 1639 str_lines = strng.split(os.linesep)[start:]
1635 1640 str_toprint = os.linesep.join(str_lines)
1636 1641 num_newlines = len(str_lines)
1637 1642 len_str = len(str_toprint)
1638 1643
1639 1644 # Dumb heuristics to guesstimate number of on-screen lines the string
1640 1645 # takes. Very basic, but good enough for docstrings in reasonable
1641 1646 # terminals. If someone later feels like refining it, it's not hard.
1642 1647 numlines = max(num_newlines,int(len_str/80)+1)
1643 1648
1644 1649 if os.name == "nt":
1645 1650 screen_lines_def = get_console_size(defaulty=25)[1]
1646 1651 else:
1647 1652 screen_lines_def = 25 # default value if we can't auto-determine
1648 1653
1649 1654 # auto-determine screen size
1650 1655 if screen_lines <= 0:
1651 1656 if TERM=='xterm':
1652 1657 use_curses = USE_CURSES
1653 1658 else:
1654 1659 # curses causes problems on many terminals other than xterm.
1655 1660 use_curses = False
1656 1661 if use_curses:
1657 1662 # There is a bug in curses, where *sometimes* it fails to properly
1658 1663 # initialize, and then after the endwin() call is made, the
1659 1664 # terminal is left in an unusable state. Rather than trying to
1660 1665 # check everytime for this (by requesting and comparing termios
1661 1666 # flags each time), we just save the initial terminal state and
1662 1667 # unconditionally reset it every time. It's cheaper than making
1663 1668 # the checks.
1664 1669 term_flags = termios.tcgetattr(sys.stdout)
1665 1670 scr = curses.initscr()
1666 1671 screen_lines_real,screen_cols = scr.getmaxyx()
1667 1672 curses.endwin()
1668 1673 # Restore terminal state in case endwin() didn't.
1669 1674 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1670 1675 # Now we have what we needed: the screen size in rows/columns
1671 1676 screen_lines += screen_lines_real
1672 1677 #print '***Screen size:',screen_lines_real,'lines x',\
1673 1678 #screen_cols,'columns.' # dbg
1674 1679 else:
1675 1680 screen_lines += screen_lines_def
1676 1681
1677 1682 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1678 1683 if numlines <= screen_lines :
1679 1684 #print '*** normal print' # dbg
1680 1685 print >>Term.cout, str_toprint
1681 1686 else:
1682 1687 # Try to open pager and default to internal one if that fails.
1683 1688 # All failure modes are tagged as 'retval=1', to match the return
1684 1689 # value of a failed system command. If any intermediate attempt
1685 1690 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1686 1691 pager_cmd = get_pager_cmd(pager_cmd)
1687 1692 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1688 1693 if os.name == 'nt':
1689 1694 if pager_cmd.startswith('type'):
1690 1695 # The default WinXP 'type' command is failing on complex strings.
1691 1696 retval = 1
1692 1697 else:
1693 1698 tmpname = tempfile.mktemp('.txt')
1694 1699 tmpfile = file(tmpname,'wt')
1695 1700 tmpfile.write(strng)
1696 1701 tmpfile.close()
1697 1702 cmd = "%s < %s" % (pager_cmd,tmpname)
1698 1703 if os.system(cmd):
1699 1704 retval = 1
1700 1705 else:
1701 1706 retval = None
1702 1707 os.remove(tmpname)
1703 1708 else:
1704 1709 try:
1705 1710 retval = None
1706 1711 # if I use popen4, things hang. No idea why.
1707 1712 #pager,shell_out = os.popen4(pager_cmd)
1708 1713 pager = os.popen(pager_cmd,'w')
1709 1714 pager.write(strng)
1710 1715 pager.close()
1711 1716 retval = pager.close() # success returns None
1712 1717 except IOError,msg: # broken pipe when user quits
1713 1718 if msg.args == (32,'Broken pipe'):
1714 1719 retval = None
1715 1720 else:
1716 1721 retval = 1
1717 1722 except OSError:
1718 1723 # Other strange problems, sometimes seen in Win2k/cygwin
1719 1724 retval = 1
1720 1725 if retval is not None:
1721 1726 page_dumb(strng,screen_lines=screen_lines)
1722 1727
1723 1728 #----------------------------------------------------------------------------
1724 1729 def page_file(fname,start = 0, pager_cmd = None):
1725 1730 """Page a file, using an optional pager command and starting line.
1726 1731 """
1727 1732
1728 1733 pager_cmd = get_pager_cmd(pager_cmd)
1729 1734 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1730 1735
1731 1736 try:
1732 1737 if os.environ['TERM'] in ['emacs','dumb']:
1733 1738 raise EnvironmentError
1734 1739 xsys(pager_cmd + ' ' + fname)
1735 1740 except:
1736 1741 try:
1737 1742 if start > 0:
1738 1743 start -= 1
1739 1744 page(open(fname).read(),start)
1740 1745 except:
1741 1746 print 'Unable to show file',`fname`
1742 1747
1743 1748
1744 1749 #----------------------------------------------------------------------------
1745 1750 def snip_print(str,width = 75,print_full = 0,header = ''):
1746 1751 """Print a string snipping the midsection to fit in width.
1747 1752
1748 1753 print_full: mode control:
1749 1754 - 0: only snip long strings
1750 1755 - 1: send to page() directly.
1751 1756 - 2: snip long strings and ask for full length viewing with page()
1752 1757 Return 1 if snipping was necessary, 0 otherwise."""
1753 1758
1754 1759 if print_full == 1:
1755 1760 page(header+str)
1756 1761 return 0
1757 1762
1758 1763 print header,
1759 1764 if len(str) < width:
1760 1765 print str
1761 1766 snip = 0
1762 1767 else:
1763 1768 whalf = int((width -5)/2)
1764 1769 print str[:whalf] + ' <...> ' + str[-whalf:]
1765 1770 snip = 1
1766 1771 if snip and print_full == 2:
1767 1772 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1768 1773 page(str)
1769 1774 return snip
1770 1775
1771 1776 #****************************************************************************
1772 1777 # lists, dicts and structures
1773 1778
1774 1779 def belong(candidates,checklist):
1775 1780 """Check whether a list of items appear in a given list of options.
1776 1781
1777 1782 Returns a list of 1 and 0, one for each candidate given."""
1778 1783
1779 1784 return [x in checklist for x in candidates]
1780 1785
1781 1786 #----------------------------------------------------------------------------
1782 1787 def uniq_stable(elems):
1783 1788 """uniq_stable(elems) -> list
1784 1789
1785 1790 Return from an iterable, a list of all the unique elements in the input,
1786 1791 but maintaining the order in which they first appear.
1787 1792
1788 1793 A naive solution to this problem which just makes a dictionary with the
1789 1794 elements as keys fails to respect the stability condition, since
1790 1795 dictionaries are unsorted by nature.
1791 1796
1792 1797 Note: All elements in the input must be valid dictionary keys for this
1793 1798 routine to work, as it internally uses a dictionary for efficiency
1794 1799 reasons."""
1795 1800
1796 1801 unique = []
1797 1802 unique_dict = {}
1798 1803 for nn in elems:
1799 1804 if nn not in unique_dict:
1800 1805 unique.append(nn)
1801 1806 unique_dict[nn] = None
1802 1807 return unique
1803 1808
1804 1809 #----------------------------------------------------------------------------
1805 1810 class NLprinter:
1806 1811 """Print an arbitrarily nested list, indicating index numbers.
1807 1812
1808 1813 An instance of this class called nlprint is available and callable as a
1809 1814 function.
1810 1815
1811 1816 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1812 1817 and using 'sep' to separate the index from the value. """
1813 1818
1814 1819 def __init__(self):
1815 1820 self.depth = 0
1816 1821
1817 1822 def __call__(self,lst,pos='',**kw):
1818 1823 """Prints the nested list numbering levels."""
1819 1824 kw.setdefault('indent',' ')
1820 1825 kw.setdefault('sep',': ')
1821 1826 kw.setdefault('start',0)
1822 1827 kw.setdefault('stop',len(lst))
1823 1828 # we need to remove start and stop from kw so they don't propagate
1824 1829 # into a recursive call for a nested list.
1825 1830 start = kw['start']; del kw['start']
1826 1831 stop = kw['stop']; del kw['stop']
1827 1832 if self.depth == 0 and 'header' in kw.keys():
1828 1833 print kw['header']
1829 1834
1830 1835 for idx in range(start,stop):
1831 1836 elem = lst[idx]
1832 1837 if type(elem)==type([]):
1833 1838 self.depth += 1
1834 1839 self.__call__(elem,itpl('$pos$idx,'),**kw)
1835 1840 self.depth -= 1
1836 1841 else:
1837 1842 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1838 1843
1839 1844 nlprint = NLprinter()
1840 1845 #----------------------------------------------------------------------------
1841 1846 def all_belong(candidates,checklist):
1842 1847 """Check whether a list of items ALL appear in a given list of options.
1843 1848
1844 1849 Returns a single 1 or 0 value."""
1845 1850
1846 1851 return 1-(0 in [x in checklist for x in candidates])
1847 1852
1848 1853 #----------------------------------------------------------------------------
1849 1854 def sort_compare(lst1,lst2,inplace = 1):
1850 1855 """Sort and compare two lists.
1851 1856
1852 1857 By default it does it in place, thus modifying the lists. Use inplace = 0
1853 1858 to avoid that (at the cost of temporary copy creation)."""
1854 1859 if not inplace:
1855 1860 lst1 = lst1[:]
1856 1861 lst2 = lst2[:]
1857 1862 lst1.sort(); lst2.sort()
1858 1863 return lst1 == lst2
1859 1864
1860 1865 #----------------------------------------------------------------------------
1861 1866 def list2dict(lst):
1862 1867 """Takes a list of (key,value) pairs and turns it into a dict."""
1863 1868
1864 1869 dic = {}
1865 1870 for k,v in lst: dic[k] = v
1866 1871 return dic
1867 1872
1868 1873 #----------------------------------------------------------------------------
1869 1874 def list2dict2(lst,default=''):
1870 1875 """Takes a list and turns it into a dict.
1871 1876 Much slower than list2dict, but more versatile. This version can take
1872 1877 lists with sublists of arbitrary length (including sclars)."""
1873 1878
1874 1879 dic = {}
1875 1880 for elem in lst:
1876 1881 if type(elem) in (types.ListType,types.TupleType):
1877 1882 size = len(elem)
1878 1883 if size == 0:
1879 1884 pass
1880 1885 elif size == 1:
1881 1886 dic[elem] = default
1882 1887 else:
1883 1888 k,v = elem[0], elem[1:]
1884 1889 if len(v) == 1: v = v[0]
1885 1890 dic[k] = v
1886 1891 else:
1887 1892 dic[elem] = default
1888 1893 return dic
1889 1894
1890 1895 #----------------------------------------------------------------------------
1891 1896 def flatten(seq):
1892 1897 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1893 1898
1894 1899 return [x for subseq in seq for x in subseq]
1895 1900
1896 1901 #----------------------------------------------------------------------------
1897 1902 def get_slice(seq,start=0,stop=None,step=1):
1898 1903 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1899 1904 if stop == None:
1900 1905 stop = len(seq)
1901 1906 item = lambda i: seq[i]
1902 1907 return map(item,xrange(start,stop,step))
1903 1908
1904 1909 #----------------------------------------------------------------------------
1905 1910 def chop(seq,size):
1906 1911 """Chop a sequence into chunks of the given size."""
1907 1912 chunk = lambda i: seq[i:i+size]
1908 1913 return map(chunk,xrange(0,len(seq),size))
1909 1914
1910 1915 #----------------------------------------------------------------------------
1911 1916 # with is a keyword as of python 2.5, so this function is renamed to withobj
1912 1917 # from its old 'with' name.
1913 1918 def with_obj(object, **args):
1914 1919 """Set multiple attributes for an object, similar to Pascal's with.
1915 1920
1916 1921 Example:
1917 1922 with_obj(jim,
1918 1923 born = 1960,
1919 1924 haircolour = 'Brown',
1920 1925 eyecolour = 'Green')
1921 1926
1922 1927 Credit: Greg Ewing, in
1923 1928 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1924 1929
1925 1930 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1926 1931 has become a keyword for Python 2.5, so we had to rename it."""
1927 1932
1928 1933 object.__dict__.update(args)
1929 1934
1930 1935 #----------------------------------------------------------------------------
1931 1936 def setattr_list(obj,alist,nspace = None):
1932 1937 """Set a list of attributes for an object taken from a namespace.
1933 1938
1934 1939 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1935 1940 alist with their values taken from nspace, which must be a dict (something
1936 1941 like locals() will often do) If nspace isn't given, locals() of the
1937 1942 *caller* is used, so in most cases you can omit it.
1938 1943
1939 1944 Note that alist can be given as a string, which will be automatically
1940 1945 split into a list on whitespace. If given as a list, it must be a list of
1941 1946 *strings* (the variable names themselves), not of variables."""
1942 1947
1943 1948 # this grabs the local variables from the *previous* call frame -- that is
1944 1949 # the locals from the function that called setattr_list().
1945 1950 # - snipped from weave.inline()
1946 1951 if nspace is None:
1947 1952 call_frame = sys._getframe().f_back
1948 1953 nspace = call_frame.f_locals
1949 1954
1950 1955 if type(alist) in StringTypes:
1951 1956 alist = alist.split()
1952 1957 for attr in alist:
1953 1958 val = eval(attr,nspace)
1954 1959 setattr(obj,attr,val)
1955 1960
1956 1961 #----------------------------------------------------------------------------
1957 1962 def getattr_list(obj,alist,*args):
1958 1963 """getattr_list(obj,alist[, default]) -> attribute list.
1959 1964
1960 1965 Get a list of named attributes for an object. When a default argument is
1961 1966 given, it is returned when the attribute doesn't exist; without it, an
1962 1967 exception is raised in that case.
1963 1968
1964 1969 Note that alist can be given as a string, which will be automatically
1965 1970 split into a list on whitespace. If given as a list, it must be a list of
1966 1971 *strings* (the variable names themselves), not of variables."""
1967 1972
1968 1973 if type(alist) in StringTypes:
1969 1974 alist = alist.split()
1970 1975 if args:
1971 1976 if len(args)==1:
1972 1977 default = args[0]
1973 1978 return map(lambda attr: getattr(obj,attr,default),alist)
1974 1979 else:
1975 1980 raise ValueError,'getattr_list() takes only one optional argument'
1976 1981 else:
1977 1982 return map(lambda attr: getattr(obj,attr),alist)
1978 1983
1979 1984 #----------------------------------------------------------------------------
1980 1985 def map_method(method,object_list,*argseq,**kw):
1981 1986 """map_method(method,object_list,*args,**kw) -> list
1982 1987
1983 1988 Return a list of the results of applying the methods to the items of the
1984 1989 argument sequence(s). If more than one sequence is given, the method is
1985 1990 called with an argument list consisting of the corresponding item of each
1986 1991 sequence. All sequences must be of the same length.
1987 1992
1988 1993 Keyword arguments are passed verbatim to all objects called.
1989 1994
1990 1995 This is Python code, so it's not nearly as fast as the builtin map()."""
1991 1996
1992 1997 out_list = []
1993 1998 idx = 0
1994 1999 for object in object_list:
1995 2000 try:
1996 2001 handler = getattr(object, method)
1997 2002 except AttributeError:
1998 2003 out_list.append(None)
1999 2004 else:
2000 2005 if argseq:
2001 2006 args = map(lambda lst:lst[idx],argseq)
2002 2007 #print 'ob',object,'hand',handler,'ar',args # dbg
2003 2008 out_list.append(handler(args,**kw))
2004 2009 else:
2005 2010 out_list.append(handler(**kw))
2006 2011 idx += 1
2007 2012 return out_list
2008 2013
2009 2014 #----------------------------------------------------------------------------
2010 2015 def get_class_members(cls):
2011 2016 ret = dir(cls)
2012 2017 if hasattr(cls,'__bases__'):
2013 2018 for base in cls.__bases__:
2014 2019 ret.extend(get_class_members(base))
2015 2020 return ret
2016 2021
2017 2022 #----------------------------------------------------------------------------
2018 2023 def dir2(obj):
2019 2024 """dir2(obj) -> list of strings
2020 2025
2021 2026 Extended version of the Python builtin dir(), which does a few extra
2022 2027 checks, and supports common objects with unusual internals that confuse
2023 2028 dir(), such as Traits and PyCrust.
2024 2029
2025 2030 This version is guaranteed to return only a list of true strings, whereas
2026 2031 dir() returns anything that objects inject into themselves, even if they
2027 2032 are later not really valid for attribute access (many extension libraries
2028 2033 have such bugs).
2029 2034 """
2030 2035
2031 2036 # Start building the attribute list via dir(), and then complete it
2032 2037 # with a few extra special-purpose calls.
2033 2038 words = dir(obj)
2034 2039
2035 2040 if hasattr(obj,'__class__'):
2036 2041 words.append('__class__')
2037 2042 words.extend(get_class_members(obj.__class__))
2038 2043 #if '__base__' in words: 1/0
2039 2044
2040 2045 # Some libraries (such as traits) may introduce duplicates, we want to
2041 2046 # track and clean this up if it happens
2042 2047 may_have_dupes = False
2043 2048
2044 2049 # this is the 'dir' function for objects with Enthought's traits
2045 2050 if hasattr(obj, 'trait_names'):
2046 2051 try:
2047 2052 words.extend(obj.trait_names())
2048 2053 may_have_dupes = True
2049 2054 except TypeError:
2050 2055 # This will happen if `obj` is a class and not an instance.
2051 2056 pass
2052 2057
2053 2058 # Support for PyCrust-style _getAttributeNames magic method.
2054 2059 if hasattr(obj, '_getAttributeNames'):
2055 2060 try:
2056 2061 words.extend(obj._getAttributeNames())
2057 2062 may_have_dupes = True
2058 2063 except TypeError:
2059 2064 # `obj` is a class and not an instance. Ignore
2060 2065 # this error.
2061 2066 pass
2062 2067
2063 2068 if may_have_dupes:
2064 2069 # eliminate possible duplicates, as some traits may also
2065 2070 # appear as normal attributes in the dir() call.
2066 2071 words = list(set(words))
2067 2072 words.sort()
2068 2073
2069 2074 # filter out non-string attributes which may be stuffed by dir() calls
2070 2075 # and poor coding in third-party modules
2071 2076 return [w for w in words if isinstance(w, basestring)]
2072 2077
2073 2078 #----------------------------------------------------------------------------
2074 2079 def import_fail_info(mod_name,fns=None):
2075 2080 """Inform load failure for a module."""
2076 2081
2077 2082 if fns == None:
2078 2083 warn("Loading of %s failed.\n" % (mod_name,))
2079 2084 else:
2080 2085 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2081 2086
2082 2087 #----------------------------------------------------------------------------
2083 2088 # Proposed popitem() extension, written as a method
2084 2089
2085 2090
2086 2091 class NotGiven: pass
2087 2092
2088 2093 def popkey(dct,key,default=NotGiven):
2089 2094 """Return dct[key] and delete dct[key].
2090 2095
2091 2096 If default is given, return it if dct[key] doesn't exist, otherwise raise
2092 2097 KeyError. """
2093 2098
2094 2099 try:
2095 2100 val = dct[key]
2096 2101 except KeyError:
2097 2102 if default is NotGiven:
2098 2103 raise
2099 2104 else:
2100 2105 return default
2101 2106 else:
2102 2107 del dct[key]
2103 2108 return val
2104 2109
2105 2110 def wrap_deprecated(func, suggest = '<nothing>'):
2106 2111 def newFunc(*args, **kwargs):
2107 2112 warnings.warn("Call to deprecated function %s, use %s instead" %
2108 2113 ( func.__name__, suggest),
2109 2114 category=DeprecationWarning,
2110 2115 stacklevel = 2)
2111 2116 return func(*args, **kwargs)
2112 2117 return newFunc
2113 2118
2114 2119
2115 2120 def _num_cpus_unix():
2116 2121 """Return the number of active CPUs on a Unix system."""
2117 2122 return os.sysconf("SC_NPROCESSORS_ONLN")
2118 2123
2119 2124
2120 2125 def _num_cpus_darwin():
2121 2126 """Return the number of active CPUs on a Darwin system."""
2122 2127 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
2123 2128 return p.stdout.read()
2124 2129
2125 2130
2126 2131 def _num_cpus_windows():
2127 2132 """Return the number of active CPUs on a Windows system."""
2128 2133 return os.environ.get("NUMBER_OF_PROCESSORS")
2129 2134
2130 2135
2131 2136 def num_cpus():
2132 2137 """Return the effective number of CPUs in the system as an integer.
2133 2138
2134 2139 This cross-platform function makes an attempt at finding the total number of
2135 2140 available CPUs in the system, as returned by various underlying system and
2136 2141 python calls.
2137 2142
2138 2143 If it can't find a sensible answer, it returns 1 (though an error *may* make
2139 2144 it return a large positive number that's actually incorrect).
2140 2145 """
2141 2146
2142 2147 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
2143 2148 # for the names of the keys we needed to look up for this function. This
2144 2149 # code was inspired by their equivalent function.
2145 2150
2146 2151 ncpufuncs = {'Linux':_num_cpus_unix,
2147 2152 'Darwin':_num_cpus_darwin,
2148 2153 'Windows':_num_cpus_windows,
2149 2154 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
2150 2155 # See http://bugs.python.org/issue1082 for details.
2151 2156 'Microsoft':_num_cpus_windows,
2152 2157 }
2153 2158
2154 2159 ncpufunc = ncpufuncs.get(platform.system(),
2155 2160 # default to unix version (Solaris, AIX, etc)
2156 2161 _num_cpus_unix)
2157 2162
2158 2163 try:
2159 2164 ncpus = max(1,int(ncpufunc()))
2160 2165 except:
2161 2166 ncpus = 1
2162 2167 return ncpus
2163 2168
2164 2169 #*************************** end of file <genutils.py> **********************
@@ -1,32 +1,46 b''
1 1 # encoding: utf-8
2 2
3 3 """Tests for genutils.py"""
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 from IPython import genutils
19 import os
20 env = os.environ
19 21
20 22
21 def test_get_home_dir():
23 def test_get_home_dir_1():
22 24 """Make sure we can get the home directory."""
23 25 home_dir = genutils.get_home_dir()
24 26
27 def test_get_home_dir_2():
28 """Make sure we can get the home directory."""
29 old=env["HOME"]
30 env["HOME"]=os.path.join(".","home_test_dir")
31 home_dir = genutils.get_home_dir()
32 assert home_dir==env["HOME"]
33 env["HOME"]=old
34
35
36
37
38
25 39 def test_get_ipython_dir():
26 40 """Make sure we can get the ipython directory."""
27 41 ipdir = genutils.get_ipython_dir()
28 42
29 43 def test_get_security_dir():
30 44 """Make sure we can get the ipython/security directory."""
31 45 sdir = genutils.get_security_dir()
32 46 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now