##// END OF EJS Templates
- Modified clock() to return total (user+system) time. Introduced...
fperez -
Show More

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

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