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