##// END OF EJS Templates
Fix long-standing and elusive terminal bug, where sometimes after issuing foo?, the terminal would get badly corrupted
Fernando Perez -
Show More

The requested changes are too big and content was truncated. Show full diff

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