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