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