##// END OF EJS Templates
SList.sort() - remove an accidental debug print
Ville M. Vainio -
Show More
@@ -1,2125 +1,2124
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 And used as:
482 482 >>> sysexec.xsys('pwd')
483 483 >>> dirlist = sysexec.bq('ls -l')
484 484 """
485 485
486 486 def __init__(self,verbose=0,debug=0,header='',split=0):
487 487 """Specify the instance's values for verbose, debug and header."""
488 488 setattr_list(self,'verbose debug header split')
489 489
490 490 def system(self,cmd):
491 491 """Stateful interface to system(), with the same keyword parameters."""
492 492
493 493 system(cmd,self.verbose,self.debug,self.header)
494 494
495 495 def shell(self,cmd):
496 496 """Stateful interface to shell(), with the same keyword parameters."""
497 497
498 498 shell(cmd,self.verbose,self.debug,self.header)
499 499
500 500 xsys = system # alias
501 501
502 502 def getoutput(self,cmd):
503 503 """Stateful interface to getoutput()."""
504 504
505 505 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
506 506
507 507 def getoutputerror(self,cmd):
508 508 """Stateful interface to getoutputerror()."""
509 509
510 510 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
511 511
512 512 bq = getoutput # alias
513 513
514 514 #-----------------------------------------------------------------------------
515 515 def mutex_opts(dict,ex_op):
516 516 """Check for presence of mutually exclusive keys in a dict.
517 517
518 518 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
519 519 for op1,op2 in ex_op:
520 520 if op1 in dict and op2 in dict:
521 521 raise ValueError,'\n*** ERROR in Arguments *** '\
522 522 'Options '+op1+' and '+op2+' are mutually exclusive.'
523 523
524 524 #-----------------------------------------------------------------------------
525 525 def get_py_filename(name):
526 526 """Return a valid python filename in the current directory.
527 527
528 528 If the given name is not a file, it adds '.py' and searches again.
529 529 Raises IOError with an informative message if the file isn't found."""
530 530
531 531 name = os.path.expanduser(name)
532 532 if not os.path.isfile(name) and not name.endswith('.py'):
533 533 name += '.py'
534 534 if os.path.isfile(name):
535 535 return name
536 536 else:
537 537 raise IOError,'File `%s` not found.' % name
538 538
539 539 #-----------------------------------------------------------------------------
540 540 def filefind(fname,alt_dirs = None):
541 541 """Return the given filename either in the current directory, if it
542 542 exists, or in a specified list of directories.
543 543
544 544 ~ expansion is done on all file and directory names.
545 545
546 546 Upon an unsuccessful search, raise an IOError exception."""
547 547
548 548 if alt_dirs is None:
549 549 try:
550 550 alt_dirs = get_home_dir()
551 551 except HomeDirError:
552 552 alt_dirs = os.getcwd()
553 553 search = [fname] + list_strings(alt_dirs)
554 554 search = map(os.path.expanduser,search)
555 555 #print 'search list for',fname,'list:',search # dbg
556 556 fname = search[0]
557 557 if os.path.isfile(fname):
558 558 return fname
559 559 for direc in search[1:]:
560 560 testname = os.path.join(direc,fname)
561 561 #print 'testname',testname # dbg
562 562 if os.path.isfile(testname):
563 563 return testname
564 564 raise IOError,'File' + `fname` + \
565 565 ' not found in current or supplied directories:' + `alt_dirs`
566 566
567 567 #----------------------------------------------------------------------------
568 568 def file_read(filename):
569 569 """Read a file and close it. Returns the file source."""
570 570 fobj = open(filename,'r');
571 571 source = fobj.read();
572 572 fobj.close()
573 573 return source
574 574
575 575 def file_readlines(filename):
576 576 """Read a file and close it. Returns the file source using readlines()."""
577 577 fobj = open(filename,'r');
578 578 lines = fobj.readlines();
579 579 fobj.close()
580 580 return lines
581 581
582 582 #----------------------------------------------------------------------------
583 583 def target_outdated(target,deps):
584 584 """Determine whether a target is out of date.
585 585
586 586 target_outdated(target,deps) -> 1/0
587 587
588 588 deps: list of filenames which MUST exist.
589 589 target: single filename which may or may not exist.
590 590
591 591 If target doesn't exist or is older than any file listed in deps, return
592 592 true, otherwise return false.
593 593 """
594 594 try:
595 595 target_time = os.path.getmtime(target)
596 596 except os.error:
597 597 return 1
598 598 for dep in deps:
599 599 dep_time = os.path.getmtime(dep)
600 600 if dep_time > target_time:
601 601 #print "For target",target,"Dep failed:",dep # dbg
602 602 #print "times (dep,tar):",dep_time,target_time # dbg
603 603 return 1
604 604 return 0
605 605
606 606 #-----------------------------------------------------------------------------
607 607 def target_update(target,deps,cmd):
608 608 """Update a target with a given command given a list of dependencies.
609 609
610 610 target_update(target,deps,cmd) -> runs cmd if target is outdated.
611 611
612 612 This is just a wrapper around target_outdated() which calls the given
613 613 command if target is outdated."""
614 614
615 615 if target_outdated(target,deps):
616 616 xsys(cmd)
617 617
618 618 #----------------------------------------------------------------------------
619 619 def unquote_ends(istr):
620 620 """Remove a single pair of quotes from the endpoints of a string."""
621 621
622 622 if not istr:
623 623 return istr
624 624 if (istr[0]=="'" and istr[-1]=="'") or \
625 625 (istr[0]=='"' and istr[-1]=='"'):
626 626 return istr[1:-1]
627 627 else:
628 628 return istr
629 629
630 630 #----------------------------------------------------------------------------
631 631 def process_cmdline(argv,names=[],defaults={},usage=''):
632 632 """ Process command-line options and arguments.
633 633
634 634 Arguments:
635 635
636 636 - argv: list of arguments, typically sys.argv.
637 637
638 638 - names: list of option names. See DPyGetOpt docs for details on options
639 639 syntax.
640 640
641 641 - defaults: dict of default values.
642 642
643 643 - usage: optional usage notice to print if a wrong argument is passed.
644 644
645 645 Return a dict of options and a list of free arguments."""
646 646
647 647 getopt = DPyGetOpt.DPyGetOpt()
648 648 getopt.setIgnoreCase(0)
649 649 getopt.parseConfiguration(names)
650 650
651 651 try:
652 652 getopt.processArguments(argv)
653 653 except DPyGetOpt.ArgumentError, exc:
654 654 print usage
655 655 warn('"%s"' % exc,level=4)
656 656
657 657 defaults.update(getopt.optionValues)
658 658 args = getopt.freeValues
659 659
660 660 return defaults,args
661 661
662 662 #----------------------------------------------------------------------------
663 663 def optstr2types(ostr):
664 664 """Convert a string of option names to a dict of type mappings.
665 665
666 666 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
667 667
668 668 This is used to get the types of all the options in a string formatted
669 669 with the conventions of DPyGetOpt. The 'type' None is used for options
670 670 which are strings (they need no further conversion). This function's main
671 671 use is to get a typemap for use with read_dict().
672 672 """
673 673
674 674 typeconv = {None:'',int:'',float:''}
675 675 typemap = {'s':None,'i':int,'f':float}
676 676 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
677 677
678 678 for w in ostr.split():
679 679 oname,alias,otype = opt_re.match(w).groups()
680 680 if otype == '' or alias == '!': # simple switches are integers too
681 681 otype = 'i'
682 682 typeconv[typemap[otype]] += oname + ' '
683 683 return typeconv
684 684
685 685 #----------------------------------------------------------------------------
686 686 def read_dict(filename,type_conv=None,**opt):
687 687
688 688 """Read a dictionary of key=value pairs from an input file, optionally
689 689 performing conversions on the resulting values.
690 690
691 691 read_dict(filename,type_conv,**opt) -> dict
692 692
693 693 Only one value per line is accepted, the format should be
694 694 # optional comments are ignored
695 695 key value\n
696 696
697 697 Args:
698 698
699 699 - type_conv: A dictionary specifying which keys need to be converted to
700 700 which types. By default all keys are read as strings. This dictionary
701 701 should have as its keys valid conversion functions for strings
702 702 (int,long,float,complex, or your own). The value for each key
703 703 (converter) should be a whitespace separated string containing the names
704 704 of all the entries in the file to be converted using that function. For
705 705 keys to be left alone, use None as the conversion function (only needed
706 706 with purge=1, see below).
707 707
708 708 - opt: dictionary with extra options as below (default in parens)
709 709
710 710 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
711 711 of the dictionary to be returned. If purge is going to be used, the
712 712 set of keys to be left as strings also has to be explicitly specified
713 713 using the (non-existent) conversion function None.
714 714
715 715 fs(None): field separator. This is the key/value separator to be used
716 716 when parsing the file. The None default means any whitespace [behavior
717 717 of string.split()].
718 718
719 719 strip(0): if 1, strip string values of leading/trailinig whitespace.
720 720
721 721 warn(1): warning level if requested keys are not found in file.
722 722 - 0: silently ignore.
723 723 - 1: inform but proceed.
724 724 - 2: raise KeyError exception.
725 725
726 726 no_empty(0): if 1, remove keys with whitespace strings as a value.
727 727
728 728 unique([]): list of keys (or space separated string) which can't be
729 729 repeated. If one such key is found in the file, each new instance
730 730 overwrites the previous one. For keys not listed here, the behavior is
731 731 to make a list of all appearances.
732 732
733 733 Example:
734 734 If the input file test.ini has:
735 735 i 3
736 736 x 4.5
737 737 y 5.5
738 738 s hi ho
739 739 Then:
740 740
741 741 >>> type_conv={int:'i',float:'x',None:'s'}
742 742 >>> read_dict('test.ini')
743 743 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
744 744 >>> read_dict('test.ini',type_conv)
745 745 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
746 746 >>> read_dict('test.ini',type_conv,purge=1)
747 747 {'i': 3, 's': 'hi ho', 'x': 4.5}
748 748 """
749 749
750 750 # starting config
751 751 opt.setdefault('purge',0)
752 752 opt.setdefault('fs',None) # field sep defaults to any whitespace
753 753 opt.setdefault('strip',0)
754 754 opt.setdefault('warn',1)
755 755 opt.setdefault('no_empty',0)
756 756 opt.setdefault('unique','')
757 757 if type(opt['unique']) in StringTypes:
758 758 unique_keys = qw(opt['unique'])
759 759 elif type(opt['unique']) in (types.TupleType,types.ListType):
760 760 unique_keys = opt['unique']
761 761 else:
762 762 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
763 763
764 764 dict = {}
765 765 # first read in table of values as strings
766 766 file = open(filename,'r')
767 767 for line in file.readlines():
768 768 line = line.strip()
769 769 if len(line) and line[0]=='#': continue
770 770 if len(line)>0:
771 771 lsplit = line.split(opt['fs'],1)
772 772 try:
773 773 key,val = lsplit
774 774 except ValueError:
775 775 key,val = lsplit[0],''
776 776 key = key.strip()
777 777 if opt['strip']: val = val.strip()
778 778 if val == "''" or val == '""': val = ''
779 779 if opt['no_empty'] and (val=='' or val.isspace()):
780 780 continue
781 781 # if a key is found more than once in the file, build a list
782 782 # unless it's in the 'unique' list. In that case, last found in file
783 783 # takes precedence. User beware.
784 784 try:
785 785 if dict[key] and key in unique_keys:
786 786 dict[key] = val
787 787 elif type(dict[key]) is types.ListType:
788 788 dict[key].append(val)
789 789 else:
790 790 dict[key] = [dict[key],val]
791 791 except KeyError:
792 792 dict[key] = val
793 793 # purge if requested
794 794 if opt['purge']:
795 795 accepted_keys = qwflat(type_conv.values())
796 796 for key in dict.keys():
797 797 if key in accepted_keys: continue
798 798 del(dict[key])
799 799 # now convert if requested
800 800 if type_conv==None: return dict
801 801 conversions = type_conv.keys()
802 802 try: conversions.remove(None)
803 803 except: pass
804 804 for convert in conversions:
805 805 for val in qw(type_conv[convert]):
806 806 try:
807 807 dict[val] = convert(dict[val])
808 808 except KeyError,e:
809 809 if opt['warn'] == 0:
810 810 pass
811 811 elif opt['warn'] == 1:
812 812 print >>sys.stderr, 'Warning: key',val,\
813 813 'not found in file',filename
814 814 elif opt['warn'] == 2:
815 815 raise KeyError,e
816 816 else:
817 817 raise ValueError,'Warning level must be 0,1 or 2'
818 818
819 819 return dict
820 820
821 821 #----------------------------------------------------------------------------
822 822 def flag_calls(func):
823 823 """Wrap a function to detect and flag when it gets called.
824 824
825 825 This is a decorator which takes a function and wraps it in a function with
826 826 a 'called' attribute. wrapper.called is initialized to False.
827 827
828 828 The wrapper.called attribute is set to False right before each call to the
829 829 wrapped function, so if the call fails it remains False. After the call
830 830 completes, wrapper.called is set to True and the output is returned.
831 831
832 832 Testing for truth in wrapper.called allows you to determine if a call to
833 833 func() was attempted and succeeded."""
834 834
835 835 def wrapper(*args,**kw):
836 836 wrapper.called = False
837 837 out = func(*args,**kw)
838 838 wrapper.called = True
839 839 return out
840 840
841 841 wrapper.called = False
842 842 wrapper.__doc__ = func.__doc__
843 843 return wrapper
844 844
845 845 #----------------------------------------------------------------------------
846 846 def dhook_wrap(func,*a,**k):
847 847 """Wrap a function call in a sys.displayhook controller.
848 848
849 849 Returns a wrapper around func which calls func, with all its arguments and
850 850 keywords unmodified, using the default sys.displayhook. Since IPython
851 851 modifies sys.displayhook, it breaks the behavior of certain systems that
852 852 rely on the default behavior, notably doctest.
853 853 """
854 854
855 855 def f(*a,**k):
856 856
857 857 dhook_s = sys.displayhook
858 858 sys.displayhook = sys.__displayhook__
859 859 try:
860 860 out = func(*a,**k)
861 861 finally:
862 862 sys.displayhook = dhook_s
863 863
864 864 return out
865 865
866 866 f.__doc__ = func.__doc__
867 867 return f
868 868
869 869 #----------------------------------------------------------------------------
870 870 def doctest_reload():
871 871 """Properly reload doctest to reuse it interactively.
872 872
873 873 This routine:
874 874
875 875 - reloads doctest
876 876
877 877 - resets its global 'master' attribute to None, so that multiple uses of
878 878 the module interactively don't produce cumulative reports.
879 879
880 880 - Monkeypatches its core test runner method to protect it from IPython's
881 881 modified displayhook. Doctest expects the default displayhook behavior
882 882 deep down, so our modification breaks it completely. For this reason, a
883 883 hard monkeypatch seems like a reasonable solution rather than asking
884 884 users to manually use a different doctest runner when under IPython."""
885 885
886 886 import doctest
887 887 reload(doctest)
888 888 doctest.master=None
889 889
890 890 try:
891 891 doctest.DocTestRunner
892 892 except AttributeError:
893 893 # This is only for python 2.3 compatibility, remove once we move to
894 894 # 2.4 only.
895 895 pass
896 896 else:
897 897 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
898 898
899 899 #----------------------------------------------------------------------------
900 900 class HomeDirError(Error):
901 901 pass
902 902
903 903 def get_home_dir():
904 904 """Return the closest possible equivalent to a 'home' directory.
905 905
906 906 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
907 907
908 908 Currently only Posix and NT are implemented, a HomeDirError exception is
909 909 raised for all other OSes. """
910 910
911 911 isdir = os.path.isdir
912 912 env = os.environ
913 913
914 914 # first, check py2exe distribution root directory for _ipython.
915 915 # This overrides all. Normally does not exist.
916 916
917 917 if '\\library.zip\\' in IPython.__file__.lower():
918 918 root, rest = IPython.__file__.lower().split('library.zip')
919 919 if isdir(root + '_ipython'):
920 920 os.environ["IPYKITROOT"] = root.rstrip('\\')
921 921 return root
922 922
923 923 try:
924 924 homedir = env['HOME']
925 925 if not isdir(homedir):
926 926 # in case a user stuck some string which does NOT resolve to a
927 927 # valid path, it's as good as if we hadn't foud it
928 928 raise KeyError
929 929 return homedir
930 930 except KeyError:
931 931 if os.name == 'posix':
932 932 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
933 933 elif os.name == 'nt':
934 934 # For some strange reason, win9x returns 'nt' for os.name.
935 935 try:
936 936 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
937 937 if not isdir(homedir):
938 938 homedir = os.path.join(env['USERPROFILE'])
939 939 if not isdir(homedir):
940 940 raise HomeDirError
941 941 return homedir
942 942 except:
943 943 try:
944 944 # Use the registry to get the 'My Documents' folder.
945 945 import _winreg as wreg
946 946 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
947 947 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
948 948 homedir = wreg.QueryValueEx(key,'Personal')[0]
949 949 key.Close()
950 950 if not isdir(homedir):
951 951 e = ('Invalid "Personal" folder registry key '
952 952 'typically "My Documents".\n'
953 953 'Value: %s\n'
954 954 'This is not a valid directory on your system.' %
955 955 homedir)
956 956 raise HomeDirError(e)
957 957 return homedir
958 958 except HomeDirError:
959 959 raise
960 960 except:
961 961 return 'C:\\'
962 962 elif os.name == 'dos':
963 963 # Desperate, may do absurd things in classic MacOS. May work under DOS.
964 964 return 'C:\\'
965 965 else:
966 966 raise HomeDirError,'support for your operating system not implemented.'
967 967
968 968 #****************************************************************************
969 969 # strings and text
970 970
971 971 class LSString(str):
972 972 """String derivative with a special access attributes.
973 973
974 974 These are normal strings, but with the special attributes:
975 975
976 976 .l (or .list) : value as list (split on newlines).
977 977 .n (or .nlstr): original value (the string itself).
978 978 .s (or .spstr): value as whitespace-separated string.
979 979 .p (or .paths): list of path objects
980 980
981 981 Any values which require transformations are computed only once and
982 982 cached.
983 983
984 984 Such strings are very useful to efficiently interact with the shell, which
985 985 typically only understands whitespace-separated options for commands."""
986 986
987 987 def get_list(self):
988 988 try:
989 989 return self.__list
990 990 except AttributeError:
991 991 self.__list = self.split('\n')
992 992 return self.__list
993 993
994 994 l = list = property(get_list)
995 995
996 996 def get_spstr(self):
997 997 try:
998 998 return self.__spstr
999 999 except AttributeError:
1000 1000 self.__spstr = self.replace('\n',' ')
1001 1001 return self.__spstr
1002 1002
1003 1003 s = spstr = property(get_spstr)
1004 1004
1005 1005 def get_nlstr(self):
1006 1006 return self
1007 1007
1008 1008 n = nlstr = property(get_nlstr)
1009 1009
1010 1010 def get_paths(self):
1011 1011 try:
1012 1012 return self.__paths
1013 1013 except AttributeError:
1014 1014 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1015 1015 return self.__paths
1016 1016
1017 1017 p = paths = property(get_paths)
1018 1018
1019 1019 def print_lsstring(arg):
1020 1020 """ Prettier (non-repr-like) and more informative printer for LSString """
1021 1021 print "LSString (.p, .n, .l, .s available). Value:"
1022 1022 print arg
1023 1023
1024 1024 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1025 1025
1026 1026 #----------------------------------------------------------------------------
1027 1027 class SList(list):
1028 1028 """List derivative with a special access attributes.
1029 1029
1030 1030 These are normal lists, but with the special attributes:
1031 1031
1032 1032 .l (or .list) : value as list (the list itself).
1033 1033 .n (or .nlstr): value as a string, joined on newlines.
1034 1034 .s (or .spstr): value as a string, joined on spaces.
1035 1035 .p (or .paths): list of path objects
1036 1036
1037 1037 Any values which require transformations are computed only once and
1038 1038 cached."""
1039 1039
1040 1040 def get_list(self):
1041 1041 return self
1042 1042
1043 1043 l = list = property(get_list)
1044 1044
1045 1045 def get_spstr(self):
1046 1046 try:
1047 1047 return self.__spstr
1048 1048 except AttributeError:
1049 1049 self.__spstr = ' '.join(self)
1050 1050 return self.__spstr
1051 1051
1052 1052 s = spstr = property(get_spstr)
1053 1053
1054 1054 def get_nlstr(self):
1055 1055 try:
1056 1056 return self.__nlstr
1057 1057 except AttributeError:
1058 1058 self.__nlstr = '\n'.join(self)
1059 1059 return self.__nlstr
1060 1060
1061 1061 n = nlstr = property(get_nlstr)
1062 1062
1063 1063 def get_paths(self):
1064 1064 try:
1065 1065 return self.__paths
1066 1066 except AttributeError:
1067 1067 self.__paths = [path(p) for p in self if os.path.exists(p)]
1068 1068 return self.__paths
1069 1069
1070 1070 p = paths = property(get_paths)
1071 1071
1072 1072 def grep(self, pattern, prune = False, field = None):
1073 1073 """ Return all strings matching 'pattern' (a regex or callable)
1074 1074
1075 1075 This is case-insensitive. If prune is true, return all items
1076 1076 NOT matching the pattern.
1077 1077
1078 1078 If field is specified, the match must occur in the specified
1079 1079 whitespace-separated field.
1080 1080
1081 1081 Examples::
1082 1082
1083 1083 a.grep( lambda x: x.startswith('C') )
1084 1084 a.grep('Cha.*log', prune=1)
1085 1085 a.grep('chm', field=-1)
1086 1086 """
1087 1087
1088 1088 def match_target(s):
1089 1089 if field is None:
1090 1090 return s
1091 1091 parts = s.split()
1092 1092 try:
1093 1093 tgt = parts[field]
1094 1094 return tgt
1095 1095 except IndexError:
1096 1096 return ""
1097 1097
1098 1098 if isinstance(pattern, basestring):
1099 1099 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1100 1100 else:
1101 1101 pred = pattern
1102 1102 if not prune:
1103 1103 return SList([el for el in self if pred(match_target(el))])
1104 1104 else:
1105 1105 return SList([el for el in self if not pred(match_target(el))])
1106 1106 def fields(self, *fields):
1107 1107 """ Collect whitespace-separated fields from string list
1108 1108
1109 1109 Allows quick awk-like usage of string lists.
1110 1110
1111 1111 Example data (in var a, created by 'a = !ls -l')::
1112 1112 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1113 1113 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1114 1114
1115 1115 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1116 1116 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1117 1117 (note the joining by space).
1118 1118 a.fields(-1) is ['ChangeLog', 'IPython']
1119 1119
1120 1120 IndexErrors are ignored.
1121 1121
1122 1122 Without args, fields() just split()'s the strings.
1123 1123 """
1124 1124 if len(fields) == 0:
1125 1125 return [el.split() for el in self]
1126 1126
1127 1127 res = SList()
1128 1128 for el in [f.split() for f in self]:
1129 1129 lineparts = []
1130 1130
1131 1131 for fd in fields:
1132 1132 try:
1133 1133 lineparts.append(el[fd])
1134 1134 except IndexError:
1135 1135 pass
1136 1136 if lineparts:
1137 1137 res.append(" ".join(lineparts))
1138 1138
1139 1139 return res
1140 1140 def sort(self,field= None, nums = False):
1141 1141 """ sort by specified fields (see fields())
1142 1142
1143 1143 Example::
1144 1144 a.sort(1, nums = True)
1145 1145
1146 1146 Sorts a by second field, in numerical order (so that 21 > 3)
1147 1147
1148 1148 """
1149 1149
1150 1150 #decorate, sort, undecorate
1151 1151 if field is not None:
1152 1152 dsu = [[SList([line]).fields(field), line] for line in self]
1153 1153 else:
1154 1154 dsu = [[line, line] for line in self]
1155 1155 if nums:
1156 1156 for i in range(len(dsu)):
1157 1157 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1158 print numstr
1159 1158 try:
1160 1159 n = int(numstr)
1161 1160 except ValueError:
1162 1161 n = 0;
1163 1162 dsu[i][0] = n
1164 1163
1165 1164
1166 1165 dsu.sort()
1167 1166 return SList([t[1] for t in dsu])
1168 1167
1169 1168 def print_slist(arg):
1170 1169 """ Prettier (non-repr-like) and more informative printer for SList """
1171 1170 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1172 1171 if hasattr(arg, 'hideonce') and arg.hideonce:
1173 1172 arg.hideonce = False
1174 1173 return
1175 1174
1176 1175 nlprint(arg)
1177 1176
1178 1177 print_slist = result_display.when_type(SList)(print_slist)
1179 1178
1180 1179
1181 1180
1182 1181 #----------------------------------------------------------------------------
1183 1182 def esc_quotes(strng):
1184 1183 """Return the input string with single and double quotes escaped out"""
1185 1184
1186 1185 return strng.replace('"','\\"').replace("'","\\'")
1187 1186
1188 1187 #----------------------------------------------------------------------------
1189 1188 def make_quoted_expr(s):
1190 1189 """Return string s in appropriate quotes, using raw string if possible.
1191 1190
1192 1191 Effectively this turns string: cd \ao\ao\
1193 1192 to: r"cd \ao\ao\_"[:-1]
1194 1193
1195 1194 Note the use of raw string and padding at the end to allow trailing backslash.
1196 1195
1197 1196 """
1198 1197
1199 1198 tail = ''
1200 1199 tailpadding = ''
1201 1200 raw = ''
1202 1201 if "\\" in s:
1203 1202 raw = 'r'
1204 1203 if s.endswith('\\'):
1205 1204 tail = '[:-1]'
1206 1205 tailpadding = '_'
1207 1206 if '"' not in s:
1208 1207 quote = '"'
1209 1208 elif "'" not in s:
1210 1209 quote = "'"
1211 1210 elif '"""' not in s and not s.endswith('"'):
1212 1211 quote = '"""'
1213 1212 elif "'''" not in s and not s.endswith("'"):
1214 1213 quote = "'''"
1215 1214 else:
1216 1215 # give up, backslash-escaped string will do
1217 1216 return '"%s"' % esc_quotes(s)
1218 1217 res = raw + quote + s + tailpadding + quote + tail
1219 1218 return res
1220 1219
1221 1220
1222 1221 #----------------------------------------------------------------------------
1223 1222 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1224 1223 """Take multiple lines of input.
1225 1224
1226 1225 A list with each line of input as a separate element is returned when a
1227 1226 termination string is entered (defaults to a single '.'). Input can also
1228 1227 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1229 1228
1230 1229 Lines of input which end in \\ are joined into single entries (and a
1231 1230 secondary continuation prompt is issued as long as the user terminates
1232 1231 lines with \\). This allows entering very long strings which are still
1233 1232 meant to be treated as single entities.
1234 1233 """
1235 1234
1236 1235 try:
1237 1236 if header:
1238 1237 header += '\n'
1239 1238 lines = [raw_input(header + ps1)]
1240 1239 except EOFError:
1241 1240 return []
1242 1241 terminate = [terminate_str]
1243 1242 try:
1244 1243 while lines[-1:] != terminate:
1245 1244 new_line = raw_input(ps1)
1246 1245 while new_line.endswith('\\'):
1247 1246 new_line = new_line[:-1] + raw_input(ps2)
1248 1247 lines.append(new_line)
1249 1248
1250 1249 return lines[:-1] # don't return the termination command
1251 1250 except EOFError:
1252 1251 print
1253 1252 return lines
1254 1253
1255 1254 #----------------------------------------------------------------------------
1256 1255 def raw_input_ext(prompt='', ps2='... '):
1257 1256 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1258 1257
1259 1258 line = raw_input(prompt)
1260 1259 while line.endswith('\\'):
1261 1260 line = line[:-1] + raw_input(ps2)
1262 1261 return line
1263 1262
1264 1263 #----------------------------------------------------------------------------
1265 1264 def ask_yes_no(prompt,default=None):
1266 1265 """Asks a question and returns a boolean (y/n) answer.
1267 1266
1268 1267 If default is given (one of 'y','n'), it is used if the user input is
1269 1268 empty. Otherwise the question is repeated until an answer is given.
1270 1269
1271 1270 An EOF is treated as the default answer. If there is no default, an
1272 1271 exception is raised to prevent infinite loops.
1273 1272
1274 1273 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1275 1274
1276 1275 answers = {'y':True,'n':False,'yes':True,'no':False}
1277 1276 ans = None
1278 1277 while ans not in answers.keys():
1279 1278 try:
1280 1279 ans = raw_input(prompt+' ').lower()
1281 1280 if not ans: # response was an empty string
1282 1281 ans = default
1283 1282 except KeyboardInterrupt:
1284 1283 pass
1285 1284 except EOFError:
1286 1285 if default in answers.keys():
1287 1286 ans = default
1288 1287 print
1289 1288 else:
1290 1289 raise
1291 1290
1292 1291 return answers[ans]
1293 1292
1294 1293 #----------------------------------------------------------------------------
1295 1294 def marquee(txt='',width=78,mark='*'):
1296 1295 """Return the input string centered in a 'marquee'."""
1297 1296 if not txt:
1298 1297 return (mark*width)[:width]
1299 1298 nmark = (width-len(txt)-2)/len(mark)/2
1300 1299 if nmark < 0: nmark =0
1301 1300 marks = mark*nmark
1302 1301 return '%s %s %s' % (marks,txt,marks)
1303 1302
1304 1303 #----------------------------------------------------------------------------
1305 1304 class EvalDict:
1306 1305 """
1307 1306 Emulate a dict which evaluates its contents in the caller's frame.
1308 1307
1309 1308 Usage:
1310 1309 >>>number = 19
1311 1310 >>>text = "python"
1312 1311 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1313 1312 """
1314 1313
1315 1314 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1316 1315 # modified (shorter) version of:
1317 1316 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1318 1317 # Skip Montanaro (skip@pobox.com).
1319 1318
1320 1319 def __getitem__(self, name):
1321 1320 frame = sys._getframe(1)
1322 1321 return eval(name, frame.f_globals, frame.f_locals)
1323 1322
1324 1323 EvalString = EvalDict # for backwards compatibility
1325 1324 #----------------------------------------------------------------------------
1326 1325 def qw(words,flat=0,sep=None,maxsplit=-1):
1327 1326 """Similar to Perl's qw() operator, but with some more options.
1328 1327
1329 1328 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1330 1329
1331 1330 words can also be a list itself, and with flat=1, the output will be
1332 1331 recursively flattened. Examples:
1333 1332
1334 1333 >>> qw('1 2')
1335 1334 ['1', '2']
1336 1335 >>> qw(['a b','1 2',['m n','p q']])
1337 1336 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1338 1337 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1339 1338 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1340 1339
1341 1340 if type(words) in StringTypes:
1342 1341 return [word.strip() for word in words.split(sep,maxsplit)
1343 1342 if word and not word.isspace() ]
1344 1343 if flat:
1345 1344 return flatten(map(qw,words,[1]*len(words)))
1346 1345 return map(qw,words)
1347 1346
1348 1347 #----------------------------------------------------------------------------
1349 1348 def qwflat(words,sep=None,maxsplit=-1):
1350 1349 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1351 1350 return qw(words,1,sep,maxsplit)
1352 1351
1353 1352 #----------------------------------------------------------------------------
1354 1353 def qw_lol(indata):
1355 1354 """qw_lol('a b') -> [['a','b']],
1356 1355 otherwise it's just a call to qw().
1357 1356
1358 1357 We need this to make sure the modules_some keys *always* end up as a
1359 1358 list of lists."""
1360 1359
1361 1360 if type(indata) in StringTypes:
1362 1361 return [qw(indata)]
1363 1362 else:
1364 1363 return qw(indata)
1365 1364
1366 1365 #-----------------------------------------------------------------------------
1367 1366 def list_strings(arg):
1368 1367 """Always return a list of strings, given a string or list of strings
1369 1368 as input."""
1370 1369
1371 1370 if type(arg) in StringTypes: return [arg]
1372 1371 else: return arg
1373 1372
1374 1373 #----------------------------------------------------------------------------
1375 1374 def grep(pat,list,case=1):
1376 1375 """Simple minded grep-like function.
1377 1376 grep(pat,list) returns occurrences of pat in list, None on failure.
1378 1377
1379 1378 It only does simple string matching, with no support for regexps. Use the
1380 1379 option case=0 for case-insensitive matching."""
1381 1380
1382 1381 # This is pretty crude. At least it should implement copying only references
1383 1382 # to the original data in case it's big. Now it copies the data for output.
1384 1383 out=[]
1385 1384 if case:
1386 1385 for term in list:
1387 1386 if term.find(pat)>-1: out.append(term)
1388 1387 else:
1389 1388 lpat=pat.lower()
1390 1389 for term in list:
1391 1390 if term.lower().find(lpat)>-1: out.append(term)
1392 1391
1393 1392 if len(out): return out
1394 1393 else: return None
1395 1394
1396 1395 #----------------------------------------------------------------------------
1397 1396 def dgrep(pat,*opts):
1398 1397 """Return grep() on dir()+dir(__builtins__).
1399 1398
1400 1399 A very common use of grep() when working interactively."""
1401 1400
1402 1401 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1403 1402
1404 1403 #----------------------------------------------------------------------------
1405 1404 def idgrep(pat):
1406 1405 """Case-insensitive dgrep()"""
1407 1406
1408 1407 return dgrep(pat,0)
1409 1408
1410 1409 #----------------------------------------------------------------------------
1411 1410 def igrep(pat,list):
1412 1411 """Synonym for case-insensitive grep."""
1413 1412
1414 1413 return grep(pat,list,case=0)
1415 1414
1416 1415 #----------------------------------------------------------------------------
1417 1416 def indent(str,nspaces=4,ntabs=0):
1418 1417 """Indent a string a given number of spaces or tabstops.
1419 1418
1420 1419 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1421 1420 """
1422 1421 if str is None:
1423 1422 return
1424 1423 ind = '\t'*ntabs+' '*nspaces
1425 1424 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1426 1425 if outstr.endswith(os.linesep+ind):
1427 1426 return outstr[:-len(ind)]
1428 1427 else:
1429 1428 return outstr
1430 1429
1431 1430 #-----------------------------------------------------------------------------
1432 1431 def native_line_ends(filename,backup=1):
1433 1432 """Convert (in-place) a file to line-ends native to the current OS.
1434 1433
1435 1434 If the optional backup argument is given as false, no backup of the
1436 1435 original file is left. """
1437 1436
1438 1437 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1439 1438
1440 1439 bak_filename = filename + backup_suffixes[os.name]
1441 1440
1442 1441 original = open(filename).read()
1443 1442 shutil.copy2(filename,bak_filename)
1444 1443 try:
1445 1444 new = open(filename,'wb')
1446 1445 new.write(os.linesep.join(original.splitlines()))
1447 1446 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1448 1447 new.close()
1449 1448 except:
1450 1449 os.rename(bak_filename,filename)
1451 1450 if not backup:
1452 1451 try:
1453 1452 os.remove(bak_filename)
1454 1453 except:
1455 1454 pass
1456 1455
1457 1456 #----------------------------------------------------------------------------
1458 1457 def get_pager_cmd(pager_cmd = None):
1459 1458 """Return a pager command.
1460 1459
1461 1460 Makes some attempts at finding an OS-correct one."""
1462 1461
1463 1462 if os.name == 'posix':
1464 1463 default_pager_cmd = 'less -r' # -r for color control sequences
1465 1464 elif os.name in ['nt','dos']:
1466 1465 default_pager_cmd = 'type'
1467 1466
1468 1467 if pager_cmd is None:
1469 1468 try:
1470 1469 pager_cmd = os.environ['PAGER']
1471 1470 except:
1472 1471 pager_cmd = default_pager_cmd
1473 1472 return pager_cmd
1474 1473
1475 1474 #-----------------------------------------------------------------------------
1476 1475 def get_pager_start(pager,start):
1477 1476 """Return the string for paging files with an offset.
1478 1477
1479 1478 This is the '+N' argument which less and more (under Unix) accept.
1480 1479 """
1481 1480
1482 1481 if pager in ['less','more']:
1483 1482 if start:
1484 1483 start_string = '+' + str(start)
1485 1484 else:
1486 1485 start_string = ''
1487 1486 else:
1488 1487 start_string = ''
1489 1488 return start_string
1490 1489
1491 1490 #----------------------------------------------------------------------------
1492 1491 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1493 1492 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1494 1493 import msvcrt
1495 1494 def page_more():
1496 1495 """ Smart pausing between pages
1497 1496
1498 1497 @return: True if need print more lines, False if quit
1499 1498 """
1500 1499 Term.cout.write('---Return to continue, q to quit--- ')
1501 1500 ans = msvcrt.getch()
1502 1501 if ans in ("q", "Q"):
1503 1502 result = False
1504 1503 else:
1505 1504 result = True
1506 1505 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1507 1506 return result
1508 1507 else:
1509 1508 def page_more():
1510 1509 ans = raw_input('---Return to continue, q to quit--- ')
1511 1510 if ans.lower().startswith('q'):
1512 1511 return False
1513 1512 else:
1514 1513 return True
1515 1514
1516 1515 esc_re = re.compile(r"(\x1b[^m]+m)")
1517 1516
1518 1517 def page_dumb(strng,start=0,screen_lines=25):
1519 1518 """Very dumb 'pager' in Python, for when nothing else works.
1520 1519
1521 1520 Only moves forward, same interface as page(), except for pager_cmd and
1522 1521 mode."""
1523 1522
1524 1523 out_ln = strng.splitlines()[start:]
1525 1524 screens = chop(out_ln,screen_lines-1)
1526 1525 if len(screens) == 1:
1527 1526 print >>Term.cout, os.linesep.join(screens[0])
1528 1527 else:
1529 1528 last_escape = ""
1530 1529 for scr in screens[0:-1]:
1531 1530 hunk = os.linesep.join(scr)
1532 1531 print >>Term.cout, last_escape + hunk
1533 1532 if not page_more():
1534 1533 return
1535 1534 esc_list = esc_re.findall(hunk)
1536 1535 if len(esc_list) > 0:
1537 1536 last_escape = esc_list[-1]
1538 1537 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1539 1538
1540 1539 #----------------------------------------------------------------------------
1541 1540 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1542 1541 """Print a string, piping through a pager after a certain length.
1543 1542
1544 1543 The screen_lines parameter specifies the number of *usable* lines of your
1545 1544 terminal screen (total lines minus lines you need to reserve to show other
1546 1545 information).
1547 1546
1548 1547 If you set screen_lines to a number <=0, page() will try to auto-determine
1549 1548 your screen size and will only use up to (screen_size+screen_lines) for
1550 1549 printing, paging after that. That is, if you want auto-detection but need
1551 1550 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1552 1551 auto-detection without any lines reserved simply use screen_lines = 0.
1553 1552
1554 1553 If a string won't fit in the allowed lines, it is sent through the
1555 1554 specified pager command. If none given, look for PAGER in the environment,
1556 1555 and ultimately default to less.
1557 1556
1558 1557 If no system pager works, the string is sent through a 'dumb pager'
1559 1558 written in python, very simplistic.
1560 1559 """
1561 1560
1562 1561 # Some routines may auto-compute start offsets incorrectly and pass a
1563 1562 # negative value. Offset to 0 for robustness.
1564 1563 start = max(0,start)
1565 1564
1566 1565 # first, try the hook
1567 1566 ip = IPython.ipapi.get()
1568 1567 if ip:
1569 1568 try:
1570 1569 ip.IP.hooks.show_in_pager(strng)
1571 1570 return
1572 1571 except IPython.ipapi.TryNext:
1573 1572 pass
1574 1573
1575 1574 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1576 1575 TERM = os.environ.get('TERM','dumb')
1577 1576 if TERM in ['dumb','emacs'] and os.name != 'nt':
1578 1577 print strng
1579 1578 return
1580 1579 # chop off the topmost part of the string we don't want to see
1581 1580 str_lines = strng.split(os.linesep)[start:]
1582 1581 str_toprint = os.linesep.join(str_lines)
1583 1582 num_newlines = len(str_lines)
1584 1583 len_str = len(str_toprint)
1585 1584
1586 1585 # Dumb heuristics to guesstimate number of on-screen lines the string
1587 1586 # takes. Very basic, but good enough for docstrings in reasonable
1588 1587 # terminals. If someone later feels like refining it, it's not hard.
1589 1588 numlines = max(num_newlines,int(len_str/80)+1)
1590 1589
1591 1590 if os.name == "nt":
1592 1591 screen_lines_def = get_console_size(defaulty=25)[1]
1593 1592 else:
1594 1593 screen_lines_def = 25 # default value if we can't auto-determine
1595 1594
1596 1595 # auto-determine screen size
1597 1596 if screen_lines <= 0:
1598 1597 if TERM=='xterm':
1599 1598 use_curses = USE_CURSES
1600 1599 else:
1601 1600 # curses causes problems on many terminals other than xterm.
1602 1601 use_curses = False
1603 1602 if use_curses:
1604 1603 # There is a bug in curses, where *sometimes* it fails to properly
1605 1604 # initialize, and then after the endwin() call is made, the
1606 1605 # terminal is left in an unusable state. Rather than trying to
1607 1606 # check everytime for this (by requesting and comparing termios
1608 1607 # flags each time), we just save the initial terminal state and
1609 1608 # unconditionally reset it every time. It's cheaper than making
1610 1609 # the checks.
1611 1610 term_flags = termios.tcgetattr(sys.stdout)
1612 1611 scr = curses.initscr()
1613 1612 screen_lines_real,screen_cols = scr.getmaxyx()
1614 1613 curses.endwin()
1615 1614 # Restore terminal state in case endwin() didn't.
1616 1615 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1617 1616 # Now we have what we needed: the screen size in rows/columns
1618 1617 screen_lines += screen_lines_real
1619 1618 #print '***Screen size:',screen_lines_real,'lines x',\
1620 1619 #screen_cols,'columns.' # dbg
1621 1620 else:
1622 1621 screen_lines += screen_lines_def
1623 1622
1624 1623 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1625 1624 if numlines <= screen_lines :
1626 1625 #print '*** normal print' # dbg
1627 1626 print >>Term.cout, str_toprint
1628 1627 else:
1629 1628 # Try to open pager and default to internal one if that fails.
1630 1629 # All failure modes are tagged as 'retval=1', to match the return
1631 1630 # value of a failed system command. If any intermediate attempt
1632 1631 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1633 1632 pager_cmd = get_pager_cmd(pager_cmd)
1634 1633 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1635 1634 if os.name == 'nt':
1636 1635 if pager_cmd.startswith('type'):
1637 1636 # The default WinXP 'type' command is failing on complex strings.
1638 1637 retval = 1
1639 1638 else:
1640 1639 tmpname = tempfile.mktemp('.txt')
1641 1640 tmpfile = file(tmpname,'wt')
1642 1641 tmpfile.write(strng)
1643 1642 tmpfile.close()
1644 1643 cmd = "%s < %s" % (pager_cmd,tmpname)
1645 1644 if os.system(cmd):
1646 1645 retval = 1
1647 1646 else:
1648 1647 retval = None
1649 1648 os.remove(tmpname)
1650 1649 else:
1651 1650 try:
1652 1651 retval = None
1653 1652 # if I use popen4, things hang. No idea why.
1654 1653 #pager,shell_out = os.popen4(pager_cmd)
1655 1654 pager = os.popen(pager_cmd,'w')
1656 1655 pager.write(strng)
1657 1656 pager.close()
1658 1657 retval = pager.close() # success returns None
1659 1658 except IOError,msg: # broken pipe when user quits
1660 1659 if msg.args == (32,'Broken pipe'):
1661 1660 retval = None
1662 1661 else:
1663 1662 retval = 1
1664 1663 except OSError:
1665 1664 # Other strange problems, sometimes seen in Win2k/cygwin
1666 1665 retval = 1
1667 1666 if retval is not None:
1668 1667 page_dumb(strng,screen_lines=screen_lines)
1669 1668
1670 1669 #----------------------------------------------------------------------------
1671 1670 def page_file(fname,start = 0, pager_cmd = None):
1672 1671 """Page a file, using an optional pager command and starting line.
1673 1672 """
1674 1673
1675 1674 pager_cmd = get_pager_cmd(pager_cmd)
1676 1675 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1677 1676
1678 1677 try:
1679 1678 if os.environ['TERM'] in ['emacs','dumb']:
1680 1679 raise EnvironmentError
1681 1680 xsys(pager_cmd + ' ' + fname)
1682 1681 except:
1683 1682 try:
1684 1683 if start > 0:
1685 1684 start -= 1
1686 1685 page(open(fname).read(),start)
1687 1686 except:
1688 1687 print 'Unable to show file',`fname`
1689 1688
1690 1689
1691 1690 #----------------------------------------------------------------------------
1692 1691 def snip_print(str,width = 75,print_full = 0,header = ''):
1693 1692 """Print a string snipping the midsection to fit in width.
1694 1693
1695 1694 print_full: mode control:
1696 1695 - 0: only snip long strings
1697 1696 - 1: send to page() directly.
1698 1697 - 2: snip long strings and ask for full length viewing with page()
1699 1698 Return 1 if snipping was necessary, 0 otherwise."""
1700 1699
1701 1700 if print_full == 1:
1702 1701 page(header+str)
1703 1702 return 0
1704 1703
1705 1704 print header,
1706 1705 if len(str) < width:
1707 1706 print str
1708 1707 snip = 0
1709 1708 else:
1710 1709 whalf = int((width -5)/2)
1711 1710 print str[:whalf] + ' <...> ' + str[-whalf:]
1712 1711 snip = 1
1713 1712 if snip and print_full == 2:
1714 1713 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1715 1714 page(str)
1716 1715 return snip
1717 1716
1718 1717 #****************************************************************************
1719 1718 # lists, dicts and structures
1720 1719
1721 1720 def belong(candidates,checklist):
1722 1721 """Check whether a list of items appear in a given list of options.
1723 1722
1724 1723 Returns a list of 1 and 0, one for each candidate given."""
1725 1724
1726 1725 return [x in checklist for x in candidates]
1727 1726
1728 1727 #----------------------------------------------------------------------------
1729 1728 def uniq_stable(elems):
1730 1729 """uniq_stable(elems) -> list
1731 1730
1732 1731 Return from an iterable, a list of all the unique elements in the input,
1733 1732 but maintaining the order in which they first appear.
1734 1733
1735 1734 A naive solution to this problem which just makes a dictionary with the
1736 1735 elements as keys fails to respect the stability condition, since
1737 1736 dictionaries are unsorted by nature.
1738 1737
1739 1738 Note: All elements in the input must be valid dictionary keys for this
1740 1739 routine to work, as it internally uses a dictionary for efficiency
1741 1740 reasons."""
1742 1741
1743 1742 unique = []
1744 1743 unique_dict = {}
1745 1744 for nn in elems:
1746 1745 if nn not in unique_dict:
1747 1746 unique.append(nn)
1748 1747 unique_dict[nn] = None
1749 1748 return unique
1750 1749
1751 1750 #----------------------------------------------------------------------------
1752 1751 class NLprinter:
1753 1752 """Print an arbitrarily nested list, indicating index numbers.
1754 1753
1755 1754 An instance of this class called nlprint is available and callable as a
1756 1755 function.
1757 1756
1758 1757 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1759 1758 and using 'sep' to separate the index from the value. """
1760 1759
1761 1760 def __init__(self):
1762 1761 self.depth = 0
1763 1762
1764 1763 def __call__(self,lst,pos='',**kw):
1765 1764 """Prints the nested list numbering levels."""
1766 1765 kw.setdefault('indent',' ')
1767 1766 kw.setdefault('sep',': ')
1768 1767 kw.setdefault('start',0)
1769 1768 kw.setdefault('stop',len(lst))
1770 1769 # we need to remove start and stop from kw so they don't propagate
1771 1770 # into a recursive call for a nested list.
1772 1771 start = kw['start']; del kw['start']
1773 1772 stop = kw['stop']; del kw['stop']
1774 1773 if self.depth == 0 and 'header' in kw.keys():
1775 1774 print kw['header']
1776 1775
1777 1776 for idx in range(start,stop):
1778 1777 elem = lst[idx]
1779 1778 if type(elem)==type([]):
1780 1779 self.depth += 1
1781 1780 self.__call__(elem,itpl('$pos$idx,'),**kw)
1782 1781 self.depth -= 1
1783 1782 else:
1784 1783 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1785 1784
1786 1785 nlprint = NLprinter()
1787 1786 #----------------------------------------------------------------------------
1788 1787 def all_belong(candidates,checklist):
1789 1788 """Check whether a list of items ALL appear in a given list of options.
1790 1789
1791 1790 Returns a single 1 or 0 value."""
1792 1791
1793 1792 return 1-(0 in [x in checklist for x in candidates])
1794 1793
1795 1794 #----------------------------------------------------------------------------
1796 1795 def sort_compare(lst1,lst2,inplace = 1):
1797 1796 """Sort and compare two lists.
1798 1797
1799 1798 By default it does it in place, thus modifying the lists. Use inplace = 0
1800 1799 to avoid that (at the cost of temporary copy creation)."""
1801 1800 if not inplace:
1802 1801 lst1 = lst1[:]
1803 1802 lst2 = lst2[:]
1804 1803 lst1.sort(); lst2.sort()
1805 1804 return lst1 == lst2
1806 1805
1807 1806 #----------------------------------------------------------------------------
1808 1807 def mkdict(**kwargs):
1809 1808 """Return a dict from a keyword list.
1810 1809
1811 1810 It's just syntactic sugar for making ditcionary creation more convenient:
1812 1811 # the standard way
1813 1812 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1814 1813 # a cleaner way
1815 1814 >>>data = dict(red=1, green=2, blue=3)
1816 1815
1817 1816 If you need more than this, look at the Struct() class."""
1818 1817
1819 1818 return kwargs
1820 1819
1821 1820 #----------------------------------------------------------------------------
1822 1821 def list2dict(lst):
1823 1822 """Takes a list of (key,value) pairs and turns it into a dict."""
1824 1823
1825 1824 dic = {}
1826 1825 for k,v in lst: dic[k] = v
1827 1826 return dic
1828 1827
1829 1828 #----------------------------------------------------------------------------
1830 1829 def list2dict2(lst,default=''):
1831 1830 """Takes a list and turns it into a dict.
1832 1831 Much slower than list2dict, but more versatile. This version can take
1833 1832 lists with sublists of arbitrary length (including sclars)."""
1834 1833
1835 1834 dic = {}
1836 1835 for elem in lst:
1837 1836 if type(elem) in (types.ListType,types.TupleType):
1838 1837 size = len(elem)
1839 1838 if size == 0:
1840 1839 pass
1841 1840 elif size == 1:
1842 1841 dic[elem] = default
1843 1842 else:
1844 1843 k,v = elem[0], elem[1:]
1845 1844 if len(v) == 1: v = v[0]
1846 1845 dic[k] = v
1847 1846 else:
1848 1847 dic[elem] = default
1849 1848 return dic
1850 1849
1851 1850 #----------------------------------------------------------------------------
1852 1851 def flatten(seq):
1853 1852 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1854 1853
1855 1854 return [x for subseq in seq for x in subseq]
1856 1855
1857 1856 #----------------------------------------------------------------------------
1858 1857 def get_slice(seq,start=0,stop=None,step=1):
1859 1858 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1860 1859 if stop == None:
1861 1860 stop = len(seq)
1862 1861 item = lambda i: seq[i]
1863 1862 return map(item,xrange(start,stop,step))
1864 1863
1865 1864 #----------------------------------------------------------------------------
1866 1865 def chop(seq,size):
1867 1866 """Chop a sequence into chunks of the given size."""
1868 1867 chunk = lambda i: seq[i:i+size]
1869 1868 return map(chunk,xrange(0,len(seq),size))
1870 1869
1871 1870 #----------------------------------------------------------------------------
1872 1871 # with is a keyword as of python 2.5, so this function is renamed to withobj
1873 1872 # from its old 'with' name.
1874 1873 def with_obj(object, **args):
1875 1874 """Set multiple attributes for an object, similar to Pascal's with.
1876 1875
1877 1876 Example:
1878 1877 with_obj(jim,
1879 1878 born = 1960,
1880 1879 haircolour = 'Brown',
1881 1880 eyecolour = 'Green')
1882 1881
1883 1882 Credit: Greg Ewing, in
1884 1883 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1885 1884
1886 1885 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1887 1886 has become a keyword for Python 2.5, so we had to rename it."""
1888 1887
1889 1888 object.__dict__.update(args)
1890 1889
1891 1890 #----------------------------------------------------------------------------
1892 1891 def setattr_list(obj,alist,nspace = None):
1893 1892 """Set a list of attributes for an object taken from a namespace.
1894 1893
1895 1894 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1896 1895 alist with their values taken from nspace, which must be a dict (something
1897 1896 like locals() will often do) If nspace isn't given, locals() of the
1898 1897 *caller* is used, so in most cases you can omit it.
1899 1898
1900 1899 Note that alist can be given as a string, which will be automatically
1901 1900 split into a list on whitespace. If given as a list, it must be a list of
1902 1901 *strings* (the variable names themselves), not of variables."""
1903 1902
1904 1903 # this grabs the local variables from the *previous* call frame -- that is
1905 1904 # the locals from the function that called setattr_list().
1906 1905 # - snipped from weave.inline()
1907 1906 if nspace is None:
1908 1907 call_frame = sys._getframe().f_back
1909 1908 nspace = call_frame.f_locals
1910 1909
1911 1910 if type(alist) in StringTypes:
1912 1911 alist = alist.split()
1913 1912 for attr in alist:
1914 1913 val = eval(attr,nspace)
1915 1914 setattr(obj,attr,val)
1916 1915
1917 1916 #----------------------------------------------------------------------------
1918 1917 def getattr_list(obj,alist,*args):
1919 1918 """getattr_list(obj,alist[, default]) -> attribute list.
1920 1919
1921 1920 Get a list of named attributes for an object. When a default argument is
1922 1921 given, it is returned when the attribute doesn't exist; without it, an
1923 1922 exception is raised in that case.
1924 1923
1925 1924 Note that alist can be given as a string, which will be automatically
1926 1925 split into a list on whitespace. If given as a list, it must be a list of
1927 1926 *strings* (the variable names themselves), not of variables."""
1928 1927
1929 1928 if type(alist) in StringTypes:
1930 1929 alist = alist.split()
1931 1930 if args:
1932 1931 if len(args)==1:
1933 1932 default = args[0]
1934 1933 return map(lambda attr: getattr(obj,attr,default),alist)
1935 1934 else:
1936 1935 raise ValueError,'getattr_list() takes only one optional argument'
1937 1936 else:
1938 1937 return map(lambda attr: getattr(obj,attr),alist)
1939 1938
1940 1939 #----------------------------------------------------------------------------
1941 1940 def map_method(method,object_list,*argseq,**kw):
1942 1941 """map_method(method,object_list,*args,**kw) -> list
1943 1942
1944 1943 Return a list of the results of applying the methods to the items of the
1945 1944 argument sequence(s). If more than one sequence is given, the method is
1946 1945 called with an argument list consisting of the corresponding item of each
1947 1946 sequence. All sequences must be of the same length.
1948 1947
1949 1948 Keyword arguments are passed verbatim to all objects called.
1950 1949
1951 1950 This is Python code, so it's not nearly as fast as the builtin map()."""
1952 1951
1953 1952 out_list = []
1954 1953 idx = 0
1955 1954 for object in object_list:
1956 1955 try:
1957 1956 handler = getattr(object, method)
1958 1957 except AttributeError:
1959 1958 out_list.append(None)
1960 1959 else:
1961 1960 if argseq:
1962 1961 args = map(lambda lst:lst[idx],argseq)
1963 1962 #print 'ob',object,'hand',handler,'ar',args # dbg
1964 1963 out_list.append(handler(args,**kw))
1965 1964 else:
1966 1965 out_list.append(handler(**kw))
1967 1966 idx += 1
1968 1967 return out_list
1969 1968
1970 1969 #----------------------------------------------------------------------------
1971 1970 def get_class_members(cls):
1972 1971 ret = dir(cls)
1973 1972 if hasattr(cls,'__bases__'):
1974 1973 for base in cls.__bases__:
1975 1974 ret.extend(get_class_members(base))
1976 1975 return ret
1977 1976
1978 1977 #----------------------------------------------------------------------------
1979 1978 def dir2(obj):
1980 1979 """dir2(obj) -> list of strings
1981 1980
1982 1981 Extended version of the Python builtin dir(), which does a few extra
1983 1982 checks, and supports common objects with unusual internals that confuse
1984 1983 dir(), such as Traits and PyCrust.
1985 1984
1986 1985 This version is guaranteed to return only a list of true strings, whereas
1987 1986 dir() returns anything that objects inject into themselves, even if they
1988 1987 are later not really valid for attribute access (many extension libraries
1989 1988 have such bugs).
1990 1989 """
1991 1990
1992 1991 # Start building the attribute list via dir(), and then complete it
1993 1992 # with a few extra special-purpose calls.
1994 1993 words = dir(obj)
1995 1994
1996 1995 if hasattr(obj,'__class__'):
1997 1996 words.append('__class__')
1998 1997 words.extend(get_class_members(obj.__class__))
1999 1998 #if '__base__' in words: 1/0
2000 1999
2001 2000 # Some libraries (such as traits) may introduce duplicates, we want to
2002 2001 # track and clean this up if it happens
2003 2002 may_have_dupes = False
2004 2003
2005 2004 # this is the 'dir' function for objects with Enthought's traits
2006 2005 if hasattr(obj, 'trait_names'):
2007 2006 try:
2008 2007 words.extend(obj.trait_names())
2009 2008 may_have_dupes = True
2010 2009 except TypeError:
2011 2010 # This will happen if `obj` is a class and not an instance.
2012 2011 pass
2013 2012
2014 2013 # Support for PyCrust-style _getAttributeNames magic method.
2015 2014 if hasattr(obj, '_getAttributeNames'):
2016 2015 try:
2017 2016 words.extend(obj._getAttributeNames())
2018 2017 may_have_dupes = True
2019 2018 except TypeError:
2020 2019 # `obj` is a class and not an instance. Ignore
2021 2020 # this error.
2022 2021 pass
2023 2022
2024 2023 if may_have_dupes:
2025 2024 # eliminate possible duplicates, as some traits may also
2026 2025 # appear as normal attributes in the dir() call.
2027 2026 words = list(set(words))
2028 2027 words.sort()
2029 2028
2030 2029 # filter out non-string attributes which may be stuffed by dir() calls
2031 2030 # and poor coding in third-party modules
2032 2031 return [w for w in words if isinstance(w, basestring)]
2033 2032
2034 2033 #----------------------------------------------------------------------------
2035 2034 def import_fail_info(mod_name,fns=None):
2036 2035 """Inform load failure for a module."""
2037 2036
2038 2037 if fns == None:
2039 2038 warn("Loading of %s failed.\n" % (mod_name,))
2040 2039 else:
2041 2040 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2042 2041
2043 2042 #----------------------------------------------------------------------------
2044 2043 # Proposed popitem() extension, written as a method
2045 2044
2046 2045
2047 2046 class NotGiven: pass
2048 2047
2049 2048 def popkey(dct,key,default=NotGiven):
2050 2049 """Return dct[key] and delete dct[key].
2051 2050
2052 2051 If default is given, return it if dct[key] doesn't exist, otherwise raise
2053 2052 KeyError. """
2054 2053
2055 2054 try:
2056 2055 val = dct[key]
2057 2056 except KeyError:
2058 2057 if default is NotGiven:
2059 2058 raise
2060 2059 else:
2061 2060 return default
2062 2061 else:
2063 2062 del dct[key]
2064 2063 return val
2065 2064
2066 2065 def wrap_deprecated(func, suggest = '<nothing>'):
2067 2066 def newFunc(*args, **kwargs):
2068 2067 warnings.warn("Call to deprecated function %s, use %s instead" %
2069 2068 ( func.__name__, suggest),
2070 2069 category=DeprecationWarning,
2071 2070 stacklevel = 2)
2072 2071 return func(*args, **kwargs)
2073 2072 return newFunc
2074 2073
2075 2074
2076 2075 def _num_cpus_unix():
2077 2076 """Return the number of active CPUs on a Unix system."""
2078 2077 return os.sysconf("SC_NPROCESSORS_ONLN")
2079 2078
2080 2079
2081 2080 def _num_cpus_darwin():
2082 2081 """Return the number of active CPUs on a Darwin system."""
2083 2082 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
2084 2083 return p.stdout.read()
2085 2084
2086 2085
2087 2086 def _num_cpus_windows():
2088 2087 """Return the number of active CPUs on a Windows system."""
2089 2088 return os.environ.get("NUMBER_OF_PROCESSORS")
2090 2089
2091 2090
2092 2091 def num_cpus():
2093 2092 """Return the effective number of CPUs in the system as an integer.
2094 2093
2095 2094 This cross-platform function makes an attempt at finding the total number of
2096 2095 available CPUs in the system, as returned by various underlying system and
2097 2096 python calls.
2098 2097
2099 2098 If it can't find a sensible answer, it returns 1 (though an error *may* make
2100 2099 it return a large positive number that's actually incorrect).
2101 2100 """
2102 2101
2103 2102 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
2104 2103 # for the names of the keys we needed to look up for this function. This
2105 2104 # code was inspired by their equivalent function.
2106 2105
2107 2106 ncpufuncs = {'Linux':_num_cpus_unix,
2108 2107 'Darwin':_num_cpus_darwin,
2109 2108 'Windows':_num_cpus_windows,
2110 2109 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
2111 2110 # See http://bugs.python.org/issue1082 for details.
2112 2111 'Microsoft':_num_cpus_windows,
2113 2112 }
2114 2113
2115 2114 ncpufunc = ncpufuncs.get(platform.system(),
2116 2115 # default to unix version (Solaris, AIX, etc)
2117 2116 _num_cpus_unix)
2118 2117
2119 2118 try:
2120 2119 ncpus = max(1,int(ncpufunc()))
2121 2120 except:
2122 2121 ncpus = 1
2123 2122 return ncpus
2124 2123
2125 2124 #*************************** end of file <genutils.py> **********************
General Comments 0
You need to be logged in to leave comments. Login now