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