##// END OF EJS Templates
add examples to SList.grep doc
vivainio -
Show More
@@ -1,1911 +1,1916 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 2726 2007-09-07 15:07:17Z vivainio $"""
8 $Id: genutils.py 2727 2007-09-07 15:32:08Z 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 1011 def grep(self, pattern, prune = False):
1012 1012 """ Return all strings matching 'pattern' (a regex or callable)
1013 1013
1014 1014 This is case-insensitive. If prune is true, return all items
1015 1015 NOT matching the pattern.
1016
1017 Examples::
1018
1019 a.grep( lambda x: x.startswith('C') )
1020 a.grep('Cha.*log', prune=1)
1016 1021 """
1017 1022 if isinstance(pattern, basestring):
1018 1023 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1019 1024 else:
1020 1025 pred = pattern
1021 1026 if not prune:
1022 1027 return SList([el for el in self if pred(el)])
1023 1028 else:
1024 1029 return SList([el for el in self if not pred(el)])
1025 1030
1026 1031 def print_slist(arg):
1027 1032 """ Prettier (non-repr-like) and more informative printer for SList """
1028 1033 print "SList (.p, .n, .l, .s, .grep() available). Value:"
1029 1034 nlprint(arg)
1030 1035
1031 1036 print_slist = result_display.when_type(SList)(print_slist)
1032 1037
1033 1038
1034 1039
1035 1040 #----------------------------------------------------------------------------
1036 1041 def esc_quotes(strng):
1037 1042 """Return the input string with single and double quotes escaped out"""
1038 1043
1039 1044 return strng.replace('"','\\"').replace("'","\\'")
1040 1045
1041 1046 #----------------------------------------------------------------------------
1042 1047 def make_quoted_expr(s):
1043 1048 """Return string s in appropriate quotes, using raw string if possible.
1044 1049
1045 1050 Effectively this turns string: cd \ao\ao\
1046 1051 to: r"cd \ao\ao\_"[:-1]
1047 1052
1048 1053 Note the use of raw string and padding at the end to allow trailing backslash.
1049 1054
1050 1055 """
1051 1056
1052 1057 tail = ''
1053 1058 tailpadding = ''
1054 1059 raw = ''
1055 1060 if "\\" in s:
1056 1061 raw = 'r'
1057 1062 if s.endswith('\\'):
1058 1063 tail = '[:-1]'
1059 1064 tailpadding = '_'
1060 1065 if '"' not in s:
1061 1066 quote = '"'
1062 1067 elif "'" not in s:
1063 1068 quote = "'"
1064 1069 elif '"""' not in s and not s.endswith('"'):
1065 1070 quote = '"""'
1066 1071 elif "'''" not in s and not s.endswith("'"):
1067 1072 quote = "'''"
1068 1073 else:
1069 1074 # give up, backslash-escaped string will do
1070 1075 return '"%s"' % esc_quotes(s)
1071 1076 res = itpl("$raw$quote$s$tailpadding$quote$tail")
1072 1077 return res
1073 1078
1074 1079
1075 1080 #----------------------------------------------------------------------------
1076 1081 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1077 1082 """Take multiple lines of input.
1078 1083
1079 1084 A list with each line of input as a separate element is returned when a
1080 1085 termination string is entered (defaults to a single '.'). Input can also
1081 1086 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1082 1087
1083 1088 Lines of input which end in \\ are joined into single entries (and a
1084 1089 secondary continuation prompt is issued as long as the user terminates
1085 1090 lines with \\). This allows entering very long strings which are still
1086 1091 meant to be treated as single entities.
1087 1092 """
1088 1093
1089 1094 try:
1090 1095 if header:
1091 1096 header += '\n'
1092 1097 lines = [raw_input(header + ps1)]
1093 1098 except EOFError:
1094 1099 return []
1095 1100 terminate = [terminate_str]
1096 1101 try:
1097 1102 while lines[-1:] != terminate:
1098 1103 new_line = raw_input(ps1)
1099 1104 while new_line.endswith('\\'):
1100 1105 new_line = new_line[:-1] + raw_input(ps2)
1101 1106 lines.append(new_line)
1102 1107
1103 1108 return lines[:-1] # don't return the termination command
1104 1109 except EOFError:
1105 1110 print
1106 1111 return lines
1107 1112
1108 1113 #----------------------------------------------------------------------------
1109 1114 def raw_input_ext(prompt='', ps2='... '):
1110 1115 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1111 1116
1112 1117 line = raw_input(prompt)
1113 1118 while line.endswith('\\'):
1114 1119 line = line[:-1] + raw_input(ps2)
1115 1120 return line
1116 1121
1117 1122 #----------------------------------------------------------------------------
1118 1123 def ask_yes_no(prompt,default=None):
1119 1124 """Asks a question and returns a boolean (y/n) answer.
1120 1125
1121 1126 If default is given (one of 'y','n'), it is used if the user input is
1122 1127 empty. Otherwise the question is repeated until an answer is given.
1123 1128
1124 1129 An EOF is treated as the default answer. If there is no default, an
1125 1130 exception is raised to prevent infinite loops.
1126 1131
1127 1132 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1128 1133
1129 1134 answers = {'y':True,'n':False,'yes':True,'no':False}
1130 1135 ans = None
1131 1136 while ans not in answers.keys():
1132 1137 try:
1133 1138 ans = raw_input(prompt+' ').lower()
1134 1139 if not ans: # response was an empty string
1135 1140 ans = default
1136 1141 except KeyboardInterrupt:
1137 1142 pass
1138 1143 except EOFError:
1139 1144 if default in answers.keys():
1140 1145 ans = default
1141 1146 print
1142 1147 else:
1143 1148 raise
1144 1149
1145 1150 return answers[ans]
1146 1151
1147 1152 #----------------------------------------------------------------------------
1148 1153 def marquee(txt='',width=78,mark='*'):
1149 1154 """Return the input string centered in a 'marquee'."""
1150 1155 if not txt:
1151 1156 return (mark*width)[:width]
1152 1157 nmark = (width-len(txt)-2)/len(mark)/2
1153 1158 if nmark < 0: nmark =0
1154 1159 marks = mark*nmark
1155 1160 return '%s %s %s' % (marks,txt,marks)
1156 1161
1157 1162 #----------------------------------------------------------------------------
1158 1163 class EvalDict:
1159 1164 """
1160 1165 Emulate a dict which evaluates its contents in the caller's frame.
1161 1166
1162 1167 Usage:
1163 1168 >>>number = 19
1164 1169 >>>text = "python"
1165 1170 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1166 1171 """
1167 1172
1168 1173 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1169 1174 # modified (shorter) version of:
1170 1175 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1171 1176 # Skip Montanaro (skip@pobox.com).
1172 1177
1173 1178 def __getitem__(self, name):
1174 1179 frame = sys._getframe(1)
1175 1180 return eval(name, frame.f_globals, frame.f_locals)
1176 1181
1177 1182 EvalString = EvalDict # for backwards compatibility
1178 1183 #----------------------------------------------------------------------------
1179 1184 def qw(words,flat=0,sep=None,maxsplit=-1):
1180 1185 """Similar to Perl's qw() operator, but with some more options.
1181 1186
1182 1187 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1183 1188
1184 1189 words can also be a list itself, and with flat=1, the output will be
1185 1190 recursively flattened. Examples:
1186 1191
1187 1192 >>> qw('1 2')
1188 1193 ['1', '2']
1189 1194 >>> qw(['a b','1 2',['m n','p q']])
1190 1195 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1191 1196 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1192 1197 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1193 1198
1194 1199 if type(words) in StringTypes:
1195 1200 return [word.strip() for word in words.split(sep,maxsplit)
1196 1201 if word and not word.isspace() ]
1197 1202 if flat:
1198 1203 return flatten(map(qw,words,[1]*len(words)))
1199 1204 return map(qw,words)
1200 1205
1201 1206 #----------------------------------------------------------------------------
1202 1207 def qwflat(words,sep=None,maxsplit=-1):
1203 1208 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1204 1209 return qw(words,1,sep,maxsplit)
1205 1210
1206 1211 #----------------------------------------------------------------------------
1207 1212 def qw_lol(indata):
1208 1213 """qw_lol('a b') -> [['a','b']],
1209 1214 otherwise it's just a call to qw().
1210 1215
1211 1216 We need this to make sure the modules_some keys *always* end up as a
1212 1217 list of lists."""
1213 1218
1214 1219 if type(indata) in StringTypes:
1215 1220 return [qw(indata)]
1216 1221 else:
1217 1222 return qw(indata)
1218 1223
1219 1224 #-----------------------------------------------------------------------------
1220 1225 def list_strings(arg):
1221 1226 """Always return a list of strings, given a string or list of strings
1222 1227 as input."""
1223 1228
1224 1229 if type(arg) in StringTypes: return [arg]
1225 1230 else: return arg
1226 1231
1227 1232 #----------------------------------------------------------------------------
1228 1233 def grep(pat,list,case=1):
1229 1234 """Simple minded grep-like function.
1230 1235 grep(pat,list) returns occurrences of pat in list, None on failure.
1231 1236
1232 1237 It only does simple string matching, with no support for regexps. Use the
1233 1238 option case=0 for case-insensitive matching."""
1234 1239
1235 1240 # This is pretty crude. At least it should implement copying only references
1236 1241 # to the original data in case it's big. Now it copies the data for output.
1237 1242 out=[]
1238 1243 if case:
1239 1244 for term in list:
1240 1245 if term.find(pat)>-1: out.append(term)
1241 1246 else:
1242 1247 lpat=pat.lower()
1243 1248 for term in list:
1244 1249 if term.lower().find(lpat)>-1: out.append(term)
1245 1250
1246 1251 if len(out): return out
1247 1252 else: return None
1248 1253
1249 1254 #----------------------------------------------------------------------------
1250 1255 def dgrep(pat,*opts):
1251 1256 """Return grep() on dir()+dir(__builtins__).
1252 1257
1253 1258 A very common use of grep() when working interactively."""
1254 1259
1255 1260 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1256 1261
1257 1262 #----------------------------------------------------------------------------
1258 1263 def idgrep(pat):
1259 1264 """Case-insensitive dgrep()"""
1260 1265
1261 1266 return dgrep(pat,0)
1262 1267
1263 1268 #----------------------------------------------------------------------------
1264 1269 def igrep(pat,list):
1265 1270 """Synonym for case-insensitive grep."""
1266 1271
1267 1272 return grep(pat,list,case=0)
1268 1273
1269 1274 #----------------------------------------------------------------------------
1270 1275 def indent(str,nspaces=4,ntabs=0):
1271 1276 """Indent a string a given number of spaces or tabstops.
1272 1277
1273 1278 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1274 1279 """
1275 1280 if str is None:
1276 1281 return
1277 1282 ind = '\t'*ntabs+' '*nspaces
1278 1283 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1279 1284 if outstr.endswith(os.linesep+ind):
1280 1285 return outstr[:-len(ind)]
1281 1286 else:
1282 1287 return outstr
1283 1288
1284 1289 #-----------------------------------------------------------------------------
1285 1290 def native_line_ends(filename,backup=1):
1286 1291 """Convert (in-place) a file to line-ends native to the current OS.
1287 1292
1288 1293 If the optional backup argument is given as false, no backup of the
1289 1294 original file is left. """
1290 1295
1291 1296 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1292 1297
1293 1298 bak_filename = filename + backup_suffixes[os.name]
1294 1299
1295 1300 original = open(filename).read()
1296 1301 shutil.copy2(filename,bak_filename)
1297 1302 try:
1298 1303 new = open(filename,'wb')
1299 1304 new.write(os.linesep.join(original.splitlines()))
1300 1305 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1301 1306 new.close()
1302 1307 except:
1303 1308 os.rename(bak_filename,filename)
1304 1309 if not backup:
1305 1310 try:
1306 1311 os.remove(bak_filename)
1307 1312 except:
1308 1313 pass
1309 1314
1310 1315 #----------------------------------------------------------------------------
1311 1316 def get_pager_cmd(pager_cmd = None):
1312 1317 """Return a pager command.
1313 1318
1314 1319 Makes some attempts at finding an OS-correct one."""
1315 1320
1316 1321 if os.name == 'posix':
1317 1322 default_pager_cmd = 'less -r' # -r for color control sequences
1318 1323 elif os.name in ['nt','dos']:
1319 1324 default_pager_cmd = 'type'
1320 1325
1321 1326 if pager_cmd is None:
1322 1327 try:
1323 1328 pager_cmd = os.environ['PAGER']
1324 1329 except:
1325 1330 pager_cmd = default_pager_cmd
1326 1331 return pager_cmd
1327 1332
1328 1333 #-----------------------------------------------------------------------------
1329 1334 def get_pager_start(pager,start):
1330 1335 """Return the string for paging files with an offset.
1331 1336
1332 1337 This is the '+N' argument which less and more (under Unix) accept.
1333 1338 """
1334 1339
1335 1340 if pager in ['less','more']:
1336 1341 if start:
1337 1342 start_string = '+' + str(start)
1338 1343 else:
1339 1344 start_string = ''
1340 1345 else:
1341 1346 start_string = ''
1342 1347 return start_string
1343 1348
1344 1349 #----------------------------------------------------------------------------
1345 1350 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1346 1351 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1347 1352 import msvcrt
1348 1353 def page_more():
1349 1354 """ Smart pausing between pages
1350 1355
1351 1356 @return: True if need print more lines, False if quit
1352 1357 """
1353 1358 Term.cout.write('---Return to continue, q to quit--- ')
1354 1359 ans = msvcrt.getch()
1355 1360 if ans in ("q", "Q"):
1356 1361 result = False
1357 1362 else:
1358 1363 result = True
1359 1364 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1360 1365 return result
1361 1366 else:
1362 1367 def page_more():
1363 1368 ans = raw_input('---Return to continue, q to quit--- ')
1364 1369 if ans.lower().startswith('q'):
1365 1370 return False
1366 1371 else:
1367 1372 return True
1368 1373
1369 1374 esc_re = re.compile(r"(\x1b[^m]+m)")
1370 1375
1371 1376 def page_dumb(strng,start=0,screen_lines=25):
1372 1377 """Very dumb 'pager' in Python, for when nothing else works.
1373 1378
1374 1379 Only moves forward, same interface as page(), except for pager_cmd and
1375 1380 mode."""
1376 1381
1377 1382 out_ln = strng.splitlines()[start:]
1378 1383 screens = chop(out_ln,screen_lines-1)
1379 1384 if len(screens) == 1:
1380 1385 print >>Term.cout, os.linesep.join(screens[0])
1381 1386 else:
1382 1387 last_escape = ""
1383 1388 for scr in screens[0:-1]:
1384 1389 hunk = os.linesep.join(scr)
1385 1390 print >>Term.cout, last_escape + hunk
1386 1391 if not page_more():
1387 1392 return
1388 1393 esc_list = esc_re.findall(hunk)
1389 1394 if len(esc_list) > 0:
1390 1395 last_escape = esc_list[-1]
1391 1396 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1392 1397
1393 1398 #----------------------------------------------------------------------------
1394 1399 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1395 1400 """Print a string, piping through a pager after a certain length.
1396 1401
1397 1402 The screen_lines parameter specifies the number of *usable* lines of your
1398 1403 terminal screen (total lines minus lines you need to reserve to show other
1399 1404 information).
1400 1405
1401 1406 If you set screen_lines to a number <=0, page() will try to auto-determine
1402 1407 your screen size and will only use up to (screen_size+screen_lines) for
1403 1408 printing, paging after that. That is, if you want auto-detection but need
1404 1409 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1405 1410 auto-detection without any lines reserved simply use screen_lines = 0.
1406 1411
1407 1412 If a string won't fit in the allowed lines, it is sent through the
1408 1413 specified pager command. If none given, look for PAGER in the environment,
1409 1414 and ultimately default to less.
1410 1415
1411 1416 If no system pager works, the string is sent through a 'dumb pager'
1412 1417 written in python, very simplistic.
1413 1418 """
1414 1419
1415 1420 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1416 1421 TERM = os.environ.get('TERM','dumb')
1417 1422 if TERM in ['dumb','emacs'] and os.name != 'nt':
1418 1423 print strng
1419 1424 return
1420 1425 # chop off the topmost part of the string we don't want to see
1421 1426 str_lines = strng.split(os.linesep)[start:]
1422 1427 str_toprint = os.linesep.join(str_lines)
1423 1428 num_newlines = len(str_lines)
1424 1429 len_str = len(str_toprint)
1425 1430
1426 1431 # Dumb heuristics to guesstimate number of on-screen lines the string
1427 1432 # takes. Very basic, but good enough for docstrings in reasonable
1428 1433 # terminals. If someone later feels like refining it, it's not hard.
1429 1434 numlines = max(num_newlines,int(len_str/80)+1)
1430 1435
1431 1436 if os.name == "nt":
1432 1437 screen_lines_def = get_console_size(defaulty=25)[1]
1433 1438 else:
1434 1439 screen_lines_def = 25 # default value if we can't auto-determine
1435 1440
1436 1441 # auto-determine screen size
1437 1442 if screen_lines <= 0:
1438 1443 if TERM=='xterm':
1439 1444 try:
1440 1445 import curses
1441 1446 if hasattr(curses,'initscr'):
1442 1447 use_curses = 1
1443 1448 else:
1444 1449 use_curses = 0
1445 1450 except ImportError:
1446 1451 use_curses = 0
1447 1452 else:
1448 1453 # curses causes problems on many terminals other than xterm.
1449 1454 use_curses = 0
1450 1455 if use_curses:
1451 1456 scr = curses.initscr()
1452 1457 screen_lines_real,screen_cols = scr.getmaxyx()
1453 1458 curses.endwin()
1454 1459 screen_lines += screen_lines_real
1455 1460 #print '***Screen size:',screen_lines_real,'lines x',\
1456 1461 #screen_cols,'columns.' # dbg
1457 1462 else:
1458 1463 screen_lines += screen_lines_def
1459 1464
1460 1465 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1461 1466 if numlines <= screen_lines :
1462 1467 #print '*** normal print' # dbg
1463 1468 print >>Term.cout, str_toprint
1464 1469 else:
1465 1470 # Try to open pager and default to internal one if that fails.
1466 1471 # All failure modes are tagged as 'retval=1', to match the return
1467 1472 # value of a failed system command. If any intermediate attempt
1468 1473 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1469 1474 pager_cmd = get_pager_cmd(pager_cmd)
1470 1475 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1471 1476 if os.name == 'nt':
1472 1477 if pager_cmd.startswith('type'):
1473 1478 # The default WinXP 'type' command is failing on complex strings.
1474 1479 retval = 1
1475 1480 else:
1476 1481 tmpname = tempfile.mktemp('.txt')
1477 1482 tmpfile = file(tmpname,'wt')
1478 1483 tmpfile.write(strng)
1479 1484 tmpfile.close()
1480 1485 cmd = "%s < %s" % (pager_cmd,tmpname)
1481 1486 if os.system(cmd):
1482 1487 retval = 1
1483 1488 else:
1484 1489 retval = None
1485 1490 os.remove(tmpname)
1486 1491 else:
1487 1492 try:
1488 1493 retval = None
1489 1494 # if I use popen4, things hang. No idea why.
1490 1495 #pager,shell_out = os.popen4(pager_cmd)
1491 1496 pager = os.popen(pager_cmd,'w')
1492 1497 pager.write(strng)
1493 1498 pager.close()
1494 1499 retval = pager.close() # success returns None
1495 1500 except IOError,msg: # broken pipe when user quits
1496 1501 if msg.args == (32,'Broken pipe'):
1497 1502 retval = None
1498 1503 else:
1499 1504 retval = 1
1500 1505 except OSError:
1501 1506 # Other strange problems, sometimes seen in Win2k/cygwin
1502 1507 retval = 1
1503 1508 if retval is not None:
1504 1509 page_dumb(strng,screen_lines=screen_lines)
1505 1510
1506 1511 #----------------------------------------------------------------------------
1507 1512 def page_file(fname,start = 0, pager_cmd = None):
1508 1513 """Page a file, using an optional pager command and starting line.
1509 1514 """
1510 1515
1511 1516 pager_cmd = get_pager_cmd(pager_cmd)
1512 1517 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1513 1518
1514 1519 try:
1515 1520 if os.environ['TERM'] in ['emacs','dumb']:
1516 1521 raise EnvironmentError
1517 1522 xsys(pager_cmd + ' ' + fname)
1518 1523 except:
1519 1524 try:
1520 1525 if start > 0:
1521 1526 start -= 1
1522 1527 page(open(fname).read(),start)
1523 1528 except:
1524 1529 print 'Unable to show file',`fname`
1525 1530
1526 1531 #----------------------------------------------------------------------------
1527 1532 def snip_print(str,width = 75,print_full = 0,header = ''):
1528 1533 """Print a string snipping the midsection to fit in width.
1529 1534
1530 1535 print_full: mode control:
1531 1536 - 0: only snip long strings
1532 1537 - 1: send to page() directly.
1533 1538 - 2: snip long strings and ask for full length viewing with page()
1534 1539 Return 1 if snipping was necessary, 0 otherwise."""
1535 1540
1536 1541 if print_full == 1:
1537 1542 page(header+str)
1538 1543 return 0
1539 1544
1540 1545 print header,
1541 1546 if len(str) < width:
1542 1547 print str
1543 1548 snip = 0
1544 1549 else:
1545 1550 whalf = int((width -5)/2)
1546 1551 print str[:whalf] + ' <...> ' + str[-whalf:]
1547 1552 snip = 1
1548 1553 if snip and print_full == 2:
1549 1554 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1550 1555 page(str)
1551 1556 return snip
1552 1557
1553 1558 #****************************************************************************
1554 1559 # lists, dicts and structures
1555 1560
1556 1561 def belong(candidates,checklist):
1557 1562 """Check whether a list of items appear in a given list of options.
1558 1563
1559 1564 Returns a list of 1 and 0, one for each candidate given."""
1560 1565
1561 1566 return [x in checklist for x in candidates]
1562 1567
1563 1568 #----------------------------------------------------------------------------
1564 1569 def uniq_stable(elems):
1565 1570 """uniq_stable(elems) -> list
1566 1571
1567 1572 Return from an iterable, a list of all the unique elements in the input,
1568 1573 but maintaining the order in which they first appear.
1569 1574
1570 1575 A naive solution to this problem which just makes a dictionary with the
1571 1576 elements as keys fails to respect the stability condition, since
1572 1577 dictionaries are unsorted by nature.
1573 1578
1574 1579 Note: All elements in the input must be valid dictionary keys for this
1575 1580 routine to work, as it internally uses a dictionary for efficiency
1576 1581 reasons."""
1577 1582
1578 1583 unique = []
1579 1584 unique_dict = {}
1580 1585 for nn in elems:
1581 1586 if nn not in unique_dict:
1582 1587 unique.append(nn)
1583 1588 unique_dict[nn] = None
1584 1589 return unique
1585 1590
1586 1591 #----------------------------------------------------------------------------
1587 1592 class NLprinter:
1588 1593 """Print an arbitrarily nested list, indicating index numbers.
1589 1594
1590 1595 An instance of this class called nlprint is available and callable as a
1591 1596 function.
1592 1597
1593 1598 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1594 1599 and using 'sep' to separate the index from the value. """
1595 1600
1596 1601 def __init__(self):
1597 1602 self.depth = 0
1598 1603
1599 1604 def __call__(self,lst,pos='',**kw):
1600 1605 """Prints the nested list numbering levels."""
1601 1606 kw.setdefault('indent',' ')
1602 1607 kw.setdefault('sep',': ')
1603 1608 kw.setdefault('start',0)
1604 1609 kw.setdefault('stop',len(lst))
1605 1610 # we need to remove start and stop from kw so they don't propagate
1606 1611 # into a recursive call for a nested list.
1607 1612 start = kw['start']; del kw['start']
1608 1613 stop = kw['stop']; del kw['stop']
1609 1614 if self.depth == 0 and 'header' in kw.keys():
1610 1615 print kw['header']
1611 1616
1612 1617 for idx in range(start,stop):
1613 1618 elem = lst[idx]
1614 1619 if type(elem)==type([]):
1615 1620 self.depth += 1
1616 1621 self.__call__(elem,itpl('$pos$idx,'),**kw)
1617 1622 self.depth -= 1
1618 1623 else:
1619 1624 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1620 1625
1621 1626 nlprint = NLprinter()
1622 1627 #----------------------------------------------------------------------------
1623 1628 def all_belong(candidates,checklist):
1624 1629 """Check whether a list of items ALL appear in a given list of options.
1625 1630
1626 1631 Returns a single 1 or 0 value."""
1627 1632
1628 1633 return 1-(0 in [x in checklist for x in candidates])
1629 1634
1630 1635 #----------------------------------------------------------------------------
1631 1636 def sort_compare(lst1,lst2,inplace = 1):
1632 1637 """Sort and compare two lists.
1633 1638
1634 1639 By default it does it in place, thus modifying the lists. Use inplace = 0
1635 1640 to avoid that (at the cost of temporary copy creation)."""
1636 1641 if not inplace:
1637 1642 lst1 = lst1[:]
1638 1643 lst2 = lst2[:]
1639 1644 lst1.sort(); lst2.sort()
1640 1645 return lst1 == lst2
1641 1646
1642 1647 #----------------------------------------------------------------------------
1643 1648 def mkdict(**kwargs):
1644 1649 """Return a dict from a keyword list.
1645 1650
1646 1651 It's just syntactic sugar for making ditcionary creation more convenient:
1647 1652 # the standard way
1648 1653 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1649 1654 # a cleaner way
1650 1655 >>>data = dict(red=1, green=2, blue=3)
1651 1656
1652 1657 If you need more than this, look at the Struct() class."""
1653 1658
1654 1659 return kwargs
1655 1660
1656 1661 #----------------------------------------------------------------------------
1657 1662 def list2dict(lst):
1658 1663 """Takes a list of (key,value) pairs and turns it into a dict."""
1659 1664
1660 1665 dic = {}
1661 1666 for k,v in lst: dic[k] = v
1662 1667 return dic
1663 1668
1664 1669 #----------------------------------------------------------------------------
1665 1670 def list2dict2(lst,default=''):
1666 1671 """Takes a list and turns it into a dict.
1667 1672 Much slower than list2dict, but more versatile. This version can take
1668 1673 lists with sublists of arbitrary length (including sclars)."""
1669 1674
1670 1675 dic = {}
1671 1676 for elem in lst:
1672 1677 if type(elem) in (types.ListType,types.TupleType):
1673 1678 size = len(elem)
1674 1679 if size == 0:
1675 1680 pass
1676 1681 elif size == 1:
1677 1682 dic[elem] = default
1678 1683 else:
1679 1684 k,v = elem[0], elem[1:]
1680 1685 if len(v) == 1: v = v[0]
1681 1686 dic[k] = v
1682 1687 else:
1683 1688 dic[elem] = default
1684 1689 return dic
1685 1690
1686 1691 #----------------------------------------------------------------------------
1687 1692 def flatten(seq):
1688 1693 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1689 1694
1690 1695 return [x for subseq in seq for x in subseq]
1691 1696
1692 1697 #----------------------------------------------------------------------------
1693 1698 def get_slice(seq,start=0,stop=None,step=1):
1694 1699 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1695 1700 if stop == None:
1696 1701 stop = len(seq)
1697 1702 item = lambda i: seq[i]
1698 1703 return map(item,xrange(start,stop,step))
1699 1704
1700 1705 #----------------------------------------------------------------------------
1701 1706 def chop(seq,size):
1702 1707 """Chop a sequence into chunks of the given size."""
1703 1708 chunk = lambda i: seq[i:i+size]
1704 1709 return map(chunk,xrange(0,len(seq),size))
1705 1710
1706 1711 #----------------------------------------------------------------------------
1707 1712 # with is a keyword as of python 2.5, so this function is renamed to withobj
1708 1713 # from its old 'with' name.
1709 1714 def with_obj(object, **args):
1710 1715 """Set multiple attributes for an object, similar to Pascal's with.
1711 1716
1712 1717 Example:
1713 1718 with_obj(jim,
1714 1719 born = 1960,
1715 1720 haircolour = 'Brown',
1716 1721 eyecolour = 'Green')
1717 1722
1718 1723 Credit: Greg Ewing, in
1719 1724 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1720 1725
1721 1726 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1722 1727 has become a keyword for Python 2.5, so we had to rename it."""
1723 1728
1724 1729 object.__dict__.update(args)
1725 1730
1726 1731 #----------------------------------------------------------------------------
1727 1732 def setattr_list(obj,alist,nspace = None):
1728 1733 """Set a list of attributes for an object taken from a namespace.
1729 1734
1730 1735 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1731 1736 alist with their values taken from nspace, which must be a dict (something
1732 1737 like locals() will often do) If nspace isn't given, locals() of the
1733 1738 *caller* is used, so in most cases you can omit it.
1734 1739
1735 1740 Note that alist can be given as a string, which will be automatically
1736 1741 split into a list on whitespace. If given as a list, it must be a list of
1737 1742 *strings* (the variable names themselves), not of variables."""
1738 1743
1739 1744 # this grabs the local variables from the *previous* call frame -- that is
1740 1745 # the locals from the function that called setattr_list().
1741 1746 # - snipped from weave.inline()
1742 1747 if nspace is None:
1743 1748 call_frame = sys._getframe().f_back
1744 1749 nspace = call_frame.f_locals
1745 1750
1746 1751 if type(alist) in StringTypes:
1747 1752 alist = alist.split()
1748 1753 for attr in alist:
1749 1754 val = eval(attr,nspace)
1750 1755 setattr(obj,attr,val)
1751 1756
1752 1757 #----------------------------------------------------------------------------
1753 1758 def getattr_list(obj,alist,*args):
1754 1759 """getattr_list(obj,alist[, default]) -> attribute list.
1755 1760
1756 1761 Get a list of named attributes for an object. When a default argument is
1757 1762 given, it is returned when the attribute doesn't exist; without it, an
1758 1763 exception is raised in that case.
1759 1764
1760 1765 Note that alist can be given as a string, which will be automatically
1761 1766 split into a list on whitespace. If given as a list, it must be a list of
1762 1767 *strings* (the variable names themselves), not of variables."""
1763 1768
1764 1769 if type(alist) in StringTypes:
1765 1770 alist = alist.split()
1766 1771 if args:
1767 1772 if len(args)==1:
1768 1773 default = args[0]
1769 1774 return map(lambda attr: getattr(obj,attr,default),alist)
1770 1775 else:
1771 1776 raise ValueError,'getattr_list() takes only one optional argument'
1772 1777 else:
1773 1778 return map(lambda attr: getattr(obj,attr),alist)
1774 1779
1775 1780 #----------------------------------------------------------------------------
1776 1781 def map_method(method,object_list,*argseq,**kw):
1777 1782 """map_method(method,object_list,*args,**kw) -> list
1778 1783
1779 1784 Return a list of the results of applying the methods to the items of the
1780 1785 argument sequence(s). If more than one sequence is given, the method is
1781 1786 called with an argument list consisting of the corresponding item of each
1782 1787 sequence. All sequences must be of the same length.
1783 1788
1784 1789 Keyword arguments are passed verbatim to all objects called.
1785 1790
1786 1791 This is Python code, so it's not nearly as fast as the builtin map()."""
1787 1792
1788 1793 out_list = []
1789 1794 idx = 0
1790 1795 for object in object_list:
1791 1796 try:
1792 1797 handler = getattr(object, method)
1793 1798 except AttributeError:
1794 1799 out_list.append(None)
1795 1800 else:
1796 1801 if argseq:
1797 1802 args = map(lambda lst:lst[idx],argseq)
1798 1803 #print 'ob',object,'hand',handler,'ar',args # dbg
1799 1804 out_list.append(handler(args,**kw))
1800 1805 else:
1801 1806 out_list.append(handler(**kw))
1802 1807 idx += 1
1803 1808 return out_list
1804 1809
1805 1810 #----------------------------------------------------------------------------
1806 1811 def get_class_members(cls):
1807 1812 ret = dir(cls)
1808 1813 if hasattr(cls,'__bases__'):
1809 1814 for base in cls.__bases__:
1810 1815 ret.extend(get_class_members(base))
1811 1816 return ret
1812 1817
1813 1818 #----------------------------------------------------------------------------
1814 1819 def dir2(obj):
1815 1820 """dir2(obj) -> list of strings
1816 1821
1817 1822 Extended version of the Python builtin dir(), which does a few extra
1818 1823 checks, and supports common objects with unusual internals that confuse
1819 1824 dir(), such as Traits and PyCrust.
1820 1825
1821 1826 This version is guaranteed to return only a list of true strings, whereas
1822 1827 dir() returns anything that objects inject into themselves, even if they
1823 1828 are later not really valid for attribute access (many extension libraries
1824 1829 have such bugs).
1825 1830 """
1826 1831
1827 1832 # Start building the attribute list via dir(), and then complete it
1828 1833 # with a few extra special-purpose calls.
1829 1834 words = dir(obj)
1830 1835
1831 1836 if hasattr(obj,'__class__'):
1832 1837 words.append('__class__')
1833 1838 words.extend(get_class_members(obj.__class__))
1834 1839 #if '__base__' in words: 1/0
1835 1840
1836 1841 # Some libraries (such as traits) may introduce duplicates, we want to
1837 1842 # track and clean this up if it happens
1838 1843 may_have_dupes = False
1839 1844
1840 1845 # this is the 'dir' function for objects with Enthought's traits
1841 1846 if hasattr(obj, 'trait_names'):
1842 1847 try:
1843 1848 words.extend(obj.trait_names())
1844 1849 may_have_dupes = True
1845 1850 except TypeError:
1846 1851 # This will happen if `obj` is a class and not an instance.
1847 1852 pass
1848 1853
1849 1854 # Support for PyCrust-style _getAttributeNames magic method.
1850 1855 if hasattr(obj, '_getAttributeNames'):
1851 1856 try:
1852 1857 words.extend(obj._getAttributeNames())
1853 1858 may_have_dupes = True
1854 1859 except TypeError:
1855 1860 # `obj` is a class and not an instance. Ignore
1856 1861 # this error.
1857 1862 pass
1858 1863
1859 1864 if may_have_dupes:
1860 1865 # eliminate possible duplicates, as some traits may also
1861 1866 # appear as normal attributes in the dir() call.
1862 1867 words = list(set(words))
1863 1868 words.sort()
1864 1869
1865 1870 # filter out non-string attributes which may be stuffed by dir() calls
1866 1871 # and poor coding in third-party modules
1867 1872 return [w for w in words if isinstance(w, basestring)]
1868 1873
1869 1874 #----------------------------------------------------------------------------
1870 1875 def import_fail_info(mod_name,fns=None):
1871 1876 """Inform load failure for a module."""
1872 1877
1873 1878 if fns == None:
1874 1879 warn("Loading of %s failed.\n" % (mod_name,))
1875 1880 else:
1876 1881 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1877 1882
1878 1883 #----------------------------------------------------------------------------
1879 1884 # Proposed popitem() extension, written as a method
1880 1885
1881 1886
1882 1887 class NotGiven: pass
1883 1888
1884 1889 def popkey(dct,key,default=NotGiven):
1885 1890 """Return dct[key] and delete dct[key].
1886 1891
1887 1892 If default is given, return it if dct[key] doesn't exist, otherwise raise
1888 1893 KeyError. """
1889 1894
1890 1895 try:
1891 1896 val = dct[key]
1892 1897 except KeyError:
1893 1898 if default is NotGiven:
1894 1899 raise
1895 1900 else:
1896 1901 return default
1897 1902 else:
1898 1903 del dct[key]
1899 1904 return val
1900 1905
1901 1906 def wrap_deprecated(func, suggest = '<nothing>'):
1902 1907 def newFunc(*args, **kwargs):
1903 1908 warnings.warn("Call to deprecated function %s, use %s instead" %
1904 1909 ( func.__name__, suggest),
1905 1910 category=DeprecationWarning,
1906 1911 stacklevel = 2)
1907 1912 return func(*args, **kwargs)
1908 1913 return newFunc
1909 1914
1910 1915 #*************************** end of file <genutils.py> **********************
1911 1916
General Comments 0
You need to be logged in to leave comments. Login now