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