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