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