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