##// END OF EJS Templates
revert accidental checkin of ipipe
vivainio -
Show More
@@ -1,2260 +1,2250 b''
1 1 # -*- coding: iso-8859-1 -*-
2 2
3 3 """
4 4 ``ipipe`` provides classes to be used in an interactive Python session. Doing a
5 5 ``from ipipe import *`` is the preferred way to do this. The name of all
6 6 objects imported this way starts with ``i`` to minimize collisions.
7 7
8 8 ``ipipe`` supports "pipeline expressions", which is something resembling Unix
9 9 pipes. An example is:
10 10
11 11 >>> ienv | isort("key.lower()")
12 12
13 13 This gives a listing of all environment variables sorted by name.
14 14
15 15
16 16 There are three types of objects in a pipeline expression:
17 17
18 18 * ``Table``s: These objects produce items. Examples are ``ils`` (listing the
19 19 current directory, ``ienv`` (listing environment variables), ``ipwd`` (listing
20 20 user accounts) and ``igrp`` (listing user groups). A ``Table`` must be the
21 21 first object in a pipe expression.
22 22
23 23 * ``Pipe``s: These objects sit in the middle of a pipe expression. They
24 24 transform the input in some way (e.g. filtering or sorting it). Examples are:
25 25 ``ifilter`` (which filters the input pipe), ``isort`` (which sorts the input
26 26 pipe) and ``ieval`` (which evaluates a function or expression for each object
27 27 in the input pipe).
28 28
29 29 * ``Display``s: These objects can be put as the last object in a pipeline
30 30 expression. There are responsible for displaying the result of the pipeline
31 31 expression. If a pipeline expression doesn't end in a display object a default
32 32 display objects will be used. One example is ``ibrowse`` which is a ``curses``
33 33 based browser.
34 34
35 35
36 36 Adding support for pipeline expressions to your own objects can be done through
37 37 three extensions points (all of them optional):
38 38
39 39 * An object that will be displayed as a row by a ``Display`` object should
40 40 implement the method ``__xattrs__(self, mode)`` method or register an
41 41 implementation of the generic function ``xattrs``. For more info see ``xattrs``.
42 42
43 43 * When an object ``foo`` is displayed by a ``Display`` object, the generic
44 44 function ``xrepr`` is used.
45 45
46 46 * Objects that can be iterated by ``Pipe``s must iterable. For special cases,
47 47 where iteration for display is different than the normal iteration a special
48 48 implementation can be registered with the generic function ``xiter``. This makes
49 49 it possible to use dictionaries and modules in pipeline expressions, for example:
50 50
51 51 >>> import sys
52 52 >>> sys | ifilter("isinstance(value, int)") | idump
53 53 key |value
54 54 api_version| 1012
55 55 dllhandle | 503316480
56 56 hexversion | 33817328
57 57 maxint |2147483647
58 58 maxunicode | 65535
59 59 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
60 60 ...
61 61
62 62 Note: The expression strings passed to ``ifilter()`` and ``isort()`` can
63 63 refer to the object to be filtered or sorted via the variable ``_`` and to any
64 64 of the attributes of the object, i.e.:
65 65
66 66 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
67 67
68 68 does the same as
69 69
70 70 >>> sys.modules | ifilter("value is not None") | isort("key.lower()")
71 71
72 72 In addition to expression strings, it's possible to pass callables (taking
73 73 the object as an argument) to ``ifilter()``, ``isort()`` and ``ieval()``:
74 74
75 75 >>> sys | ifilter(lambda _:isinstance(_.value, int)) \
76 76 ... | ieval(lambda _: (_.key, hex(_.value))) | idump
77 77 0 |1
78 78 api_version|0x3f4
79 79 dllhandle |0x1e000000
80 80 hexversion |0x20402f0
81 81 maxint |0x7fffffff
82 82 maxunicode |0xffff
83 83 """
84 84
85 85 import sys, os, os.path, stat, glob, new, csv, datetime, types
86 86 import itertools, mimetypes, StringIO
87 87
88 88 try: # Python 2.3 compatibility
89 89 import collections
90 90 except ImportError:
91 91 deque = list
92 92 else:
93 93 deque = collections.deque
94 94
95 95 try: # Python 2.3 compatibility
96 96 set
97 97 except NameError:
98 98 import sets
99 99 set = sets.Set
100 100
101 101 try: # Python 2.3 compatibility
102 102 sorted
103 103 except NameError:
104 104 def sorted(iterator, key=None, reverse=False):
105 105 items = list(iterator)
106 106 if key is not None:
107 107 items.sort(lambda i1, i2: cmp(key(i1), key(i2)))
108 108 else:
109 109 items.sort()
110 110 if reverse:
111 111 items.reverse()
112 112 return items
113 113
114 114 try:
115 115 import pwd
116 116 except ImportError:
117 117 pwd = None
118 118
119 119 try:
120 120 import grp
121 121 except ImportError:
122 122 grp = None
123 123
124 124 from IPython.external import simplegeneric
125 125
126 126 import path
127 127 try:
128 128 from IPython import genutils, ipapi
129 129 except ImportError:
130 130 genutils = None
131 131 ipapi = None
132 132
133 133 import astyle
134 134
135 135
136 136 __all__ = [
137 137 "ifile", "ils", "iglob", "iwalk", "ipwdentry", "ipwd", "igrpentry", "igrp",
138 138 "icsv", "ix", "ichain", "isort", "ifilter", "ieval", "ienum",
139 "ienv", "ihist", "icap", "idump", "iless", "igrep"
139 "ienv", "ihist", "icap", "idump", "iless"
140 140 ]
141 141
142 142
143 143 os.stat_float_times(True) # enable microseconds
144 144
145 145
146 146 class AttrNamespace(object):
147 147 """
148 148 Helper class that is used for providing a namespace for evaluating
149 149 expressions containing attribute names of an object.
150 150 """
151 151 def __init__(self, wrapped):
152 152 self.wrapped = wrapped
153 153
154 154 def __getitem__(self, name):
155 155 if name == "_":
156 156 return self.wrapped
157 157 try:
158 158 return getattr(self.wrapped, name)
159 159 except AttributeError:
160 160 raise KeyError(name)
161 161
162 162 # Python 2.3 compatibility
163 163 # use eval workaround to find out which names are used in the
164 164 # eval string and put them into the locals. This works for most
165 165 # normal uses case, bizarre ones like accessing the locals()
166 166 # will fail
167 167 try:
168 168 eval("_", None, AttrNamespace(None))
169 169 except TypeError:
170 170 real_eval = eval
171 171 def eval(codestring, _globals, _locals):
172 172 """
173 173 eval(source[, globals[, locals]]) -> value
174 174
175 175 Evaluate the source in the context of globals and locals.
176 176 The source may be a string representing a Python expression
177 177 or a code object as returned by compile().
178 178 The globals must be a dictionary and locals can be any mappping.
179 179
180 180 This function is a workaround for the shortcomings of
181 181 Python 2.3's eval.
182 182 """
183 183
184 184 if isinstance(codestring, basestring):
185 185 code = compile(codestring, "_eval", "eval")
186 186 else:
187 187 code = codestring
188 188 newlocals = {}
189 189 for name in code.co_names:
190 190 try:
191 191 newlocals[name] = _locals[name]
192 192 except KeyError:
193 193 pass
194 194 return real_eval(code, _globals, newlocals)
195 195
196 196
197 197 noitem = object()
198 198
199 199
200 200 def item(iterator, index, default=noitem):
201 201 """
202 202 Return the ``index``th item from the iterator ``iterator``.
203 203 ``index`` must be an integer (negative integers are relative to the
204 204 end (i.e. the last items produced by the iterator)).
205 205
206 206 If ``default`` is given, this will be the default value when
207 207 the iterator doesn't contain an item at this position. Otherwise an
208 208 ``IndexError`` will be raised.
209 209
210 210 Note that using this function will partially or totally exhaust the
211 211 iterator.
212 212 """
213 213 i = index
214 214 if i>=0:
215 215 for item in iterator:
216 216 if not i:
217 217 return item
218 218 i -= 1
219 219 else:
220 220 i = -index
221 221 cache = deque()
222 222 for item in iterator:
223 223 cache.append(item)
224 224 if len(cache)>i:
225 225 cache.popleft()
226 226 if len(cache)==i:
227 227 return cache.popleft()
228 228 if default is noitem:
229 229 raise IndexError(index)
230 230 else:
231 231 return default
232 232
233 233
234 234 def getglobals(g):
235 235 """
236 236 Return the global namespace that is used for expression strings in
237 237 ``ifilter`` and others. This is ``g`` or (if ``g`` is ``None``) IPython's
238 238 user namespace.
239 239 """
240 240 if g is None:
241 241 if ipapi is not None:
242 242 api = ipapi.get()
243 243 if api is not None:
244 244 return api.user_ns
245 245 return globals()
246 246 return g
247 247
248 248
249 249 class Descriptor(object):
250 250 """
251 251 A ``Descriptor`` object is used for describing the attributes of objects.
252 252 """
253 253 def __hash__(self):
254 254 return hash(self.__class__) ^ hash(self.key())
255 255
256 256 def __eq__(self, other):
257 257 return self.__class__ is other.__class__ and self.key() == other.key()
258 258
259 259 def __ne__(self, other):
260 260 return self.__class__ is not other.__class__ or self.key() != other.key()
261 261
262 262 def key(self):
263 263 pass
264 264
265 265 def name(self):
266 266 """
267 267 Return the name of this attribute for display by a ``Display`` object
268 268 (e.g. as a column title).
269 269 """
270 270 key = self.key()
271 271 if key is None:
272 272 return "_"
273 273 return str(key)
274 274
275 275 def attrtype(self, obj):
276 276 """
277 277 Return the type of this attribute (i.e. something like "attribute" or
278 278 "method").
279 279 """
280 280
281 281 def valuetype(self, obj):
282 282 """
283 283 Return the type of this attribute value of the object ``obj``.
284 284 """
285 285
286 286 def value(self, obj):
287 287 """
288 288 Return the value of this attribute of the object ``obj``.
289 289 """
290 290
291 291 def doc(self, obj):
292 292 """
293 293 Return the documentation for this attribute.
294 294 """
295 295
296 296 def shortdoc(self, obj):
297 297 """
298 298 Return a short documentation for this attribute (defaulting to the
299 299 first line).
300 300 """
301 301 doc = self.doc(obj)
302 302 if doc is not None:
303 303 doc = doc.strip().splitlines()[0].strip()
304 304 return doc
305 305
306 306 def iter(self, obj):
307 307 """
308 308 Return an iterator for this attribute of the object ``obj``.
309 309 """
310 310 return xiter(self.value(obj))
311 311
312 312
313 313 class SelfDescriptor(Descriptor):
314 314 """
315 315 A ``SelfDescriptor`` describes the object itself.
316 316 """
317 317 def key(self):
318 318 return None
319 319
320 320 def attrtype(self, obj):
321 321 return "self"
322 322
323 323 def valuetype(self, obj):
324 324 return type(obj)
325 325
326 326 def value(self, obj):
327 327 return obj
328 328
329 329 def __repr__(self):
330 330 return "Self"
331 331
332 332 selfdescriptor = SelfDescriptor() # there's no need for more than one
333 333
334 334
335 335 class AttributeDescriptor(Descriptor):
336 336 """
337 337 An ``AttributeDescriptor`` describes a simple attribute of an object.
338 338 """
339 339 __slots__ = ("_name", "_doc")
340 340
341 341 def __init__(self, name, doc=None):
342 342 self._name = name
343 343 self._doc = doc
344 344
345 345 def key(self):
346 346 return self._name
347 347
348 348 def doc(self, obj):
349 349 return self._doc
350 350
351 351 def attrtype(self, obj):
352 352 return "attr"
353 353
354 354 def valuetype(self, obj):
355 355 return type(getattr(obj, self._name))
356 356
357 357 def value(self, obj):
358 358 return getattr(obj, self._name)
359 359
360 360 def __repr__(self):
361 361 if self._doc is None:
362 362 return "Attribute(%r)" % self._name
363 363 else:
364 364 return "Attribute(%r, %r)" % (self._name, self._doc)
365 365
366 366
367 367 class IndexDescriptor(Descriptor):
368 368 """
369 369 An ``IndexDescriptor`` describes an "attribute" of an object that is fetched
370 370 via ``__getitem__``.
371 371 """
372 372 __slots__ = ("_index",)
373 373
374 374 def __init__(self, index):
375 375 self._index = index
376 376
377 377 def key(self):
378 378 return self._index
379 379
380 380 def attrtype(self, obj):
381 381 return "item"
382 382
383 383 def valuetype(self, obj):
384 384 return type(obj[self._index])
385 385
386 386 def value(self, obj):
387 387 return obj[self._index]
388 388
389 389 def __repr__(self):
390 390 return "Index(%r)" % self._index
391 391
392 392
393 393 class MethodDescriptor(Descriptor):
394 394 """
395 395 A ``MethodDescriptor`` describes a method of an object that can be called
396 396 without argument. Note that this method shouldn't change the object.
397 397 """
398 398 __slots__ = ("_name", "_doc")
399 399
400 400 def __init__(self, name, doc=None):
401 401 self._name = name
402 402 self._doc = doc
403 403
404 404 def key(self):
405 405 return self._name
406 406
407 407 def doc(self, obj):
408 408 if self._doc is None:
409 409 return getattr(obj, self._name).__doc__
410 410 return self._doc
411 411
412 412 def attrtype(self, obj):
413 413 return "method"
414 414
415 415 def valuetype(self, obj):
416 416 return type(self.value(obj))
417 417
418 418 def value(self, obj):
419 419 return getattr(obj, self._name)()
420 420
421 421 def __repr__(self):
422 422 if self._doc is None:
423 423 return "Method(%r)" % self._name
424 424 else:
425 425 return "Method(%r, %r)" % (self._name, self._doc)
426 426
427 427
428 428 class IterAttributeDescriptor(Descriptor):
429 429 """
430 430 An ``IterAttributeDescriptor`` works like an ``AttributeDescriptor`` but
431 431 doesn't return an attribute values (because this value might be e.g. a large
432 432 list).
433 433 """
434 434 __slots__ = ("_name", "_doc")
435 435
436 436 def __init__(self, name, doc=None):
437 437 self._name = name
438 438 self._doc = doc
439 439
440 440 def key(self):
441 441 return self._name
442 442
443 443 def doc(self, obj):
444 444 return self._doc
445 445
446 446 def attrtype(self, obj):
447 447 return "iter"
448 448
449 449 def valuetype(self, obj):
450 450 return noitem
451 451
452 452 def value(self, obj):
453 453 return noitem
454 454
455 455 def iter(self, obj):
456 456 return xiter(getattr(obj, self._name))
457 457
458 458 def __repr__(self):
459 459 if self._doc is None:
460 460 return "IterAttribute(%r)" % self._name
461 461 else:
462 462 return "IterAttribute(%r, %r)" % (self._name, self._doc)
463 463
464 464
465 465 class IterMethodDescriptor(Descriptor):
466 466 """
467 467 An ``IterMethodDescriptor`` works like an ``MethodDescriptor`` but doesn't
468 468 return an attribute values (because this value might be e.g. a large list).
469 469 """
470 470 __slots__ = ("_name", "_doc")
471 471
472 472 def __init__(self, name, doc=None):
473 473 self._name = name
474 474 self._doc = doc
475 475
476 476 def key(self):
477 477 return self._name
478 478
479 479 def doc(self, obj):
480 480 if self._doc is None:
481 481 return getattr(obj, self._name).__doc__
482 482 return self._doc
483 483
484 484 def attrtype(self, obj):
485 485 return "itermethod"
486 486
487 487 def valuetype(self, obj):
488 488 return noitem
489 489
490 490 def value(self, obj):
491 491 return noitem
492 492
493 493 def iter(self, obj):
494 494 return xiter(getattr(obj, self._name)())
495 495
496 496 def __repr__(self):
497 497 if self._doc is None:
498 498 return "IterMethod(%r)" % self._name
499 499 else:
500 500 return "IterMethod(%r, %r)" % (self._name, self._doc)
501 501
502 502
503 503 class FunctionDescriptor(Descriptor):
504 504 """
505 505 A ``FunctionDescriptor`` turns a function into a descriptor. The function
506 506 will be called with the object to get the type and value of the attribute.
507 507 """
508 508 __slots__ = ("_function", "_name", "_doc")
509 509
510 510 def __init__(self, function, name=None, doc=None):
511 511 self._function = function
512 512 self._name = name
513 513 self._doc = doc
514 514
515 515 def key(self):
516 516 return self._function
517 517
518 518 def name(self):
519 519 if self._name is not None:
520 520 return self._name
521 521 return getattr(self._function, "__xname__", self._function.__name__)
522 522
523 523 def doc(self, obj):
524 524 if self._doc is None:
525 525 return self._function.__doc__
526 526 return self._doc
527 527
528 528 def attrtype(self, obj):
529 529 return "function"
530 530
531 531 def valuetype(self, obj):
532 532 return type(self._function(obj))
533 533
534 534 def value(self, obj):
535 535 return self._function(obj)
536 536
537 537 def __repr__(self):
538 538 if self._doc is None:
539 539 return "Function(%r)" % self._name
540 540 else:
541 541 return "Function(%r, %r)" % (self._name, self._doc)
542 542
543 543
544 544 class Table(object):
545 545 """
546 546 A ``Table`` is an object that produces items (just like a normal Python
547 547 iterator/generator does) and can be used as the first object in a pipeline
548 548 expression. The displayhook will open the default browser for such an object
549 549 (instead of simply printing the ``repr()`` result).
550 550 """
551 551
552 552 # We want to support ``foo`` and ``foo()`` in pipeline expression:
553 553 # So we implement the required operators (``|`` and ``+``) in the metaclass,
554 554 # instantiate the class and forward the operator to the instance
555 555 class __metaclass__(type):
556 556 def __iter__(self):
557 557 return iter(self())
558 558
559 559 def __or__(self, other):
560 560 return self() | other
561 561
562 562 def __add__(self, other):
563 563 return self() + other
564 564
565 565 def __radd__(self, other):
566 566 return other + self()
567 567
568 568 def __getitem__(self, index):
569 569 return self()[index]
570 570
571 571 def __getitem__(self, index):
572 572 return item(self, index)
573 573
574 574 def __contains__(self, item):
575 575 for haveitem in self:
576 576 if item == haveitem:
577 577 return True
578 578 return False
579 579
580 580 def __or__(self, other):
581 581 # autoinstantiate right hand side
582 582 if isinstance(other, type) and issubclass(other, (Table, Display)):
583 583 other = other()
584 584 # treat simple strings and functions as ``ieval`` instances
585 585 elif not isinstance(other, Display) and not isinstance(other, Table):
586 586 other = ieval(other)
587 587 # forward operations to the right hand side
588 588 return other.__ror__(self)
589 589
590 590 def __add__(self, other):
591 591 # autoinstantiate right hand side
592 592 if isinstance(other, type) and issubclass(other, Table):
593 593 other = other()
594 594 return ichain(self, other)
595 595
596 596 def __radd__(self, other):
597 597 # autoinstantiate left hand side
598 598 if isinstance(other, type) and issubclass(other, Table):
599 599 other = other()
600 600 return ichain(other, self)
601 601
602 602
603 603 class Pipe(Table):
604 604 """
605 605 A ``Pipe`` is an object that can be used in a pipeline expression. It
606 606 processes the objects it gets from its input ``Table``/``Pipe``. Note that
607 607 a ``Pipe`` object can't be used as the first object in a pipeline
608 608 expression, as it doesn't produces items itself.
609 609 """
610 610 class __metaclass__(Table.__metaclass__):
611 611 def __ror__(self, input):
612 612 return input | self()
613 613
614 614 def __ror__(self, input):
615 615 # autoinstantiate left hand side
616 616 if isinstance(input, type) and issubclass(input, Table):
617 617 input = input()
618 618 self.input = input
619 619 return self
620 620
621 621
622 622 def xrepr(item, mode="default"):
623 623 """
624 624 Generic function that adds color output and different display modes to ``repr``.
625 625
626 626 The result of an ``xrepr`` call is iterable and consists of ``(style, string)``
627 627 tuples. The ``style`` in this tuple must be a ``Style`` object from the
628 628 ``astring`` module. To reconfigure the output the first yielded tuple can be
629 629 a ``(aligment, full)`` tuple instead of a ``(style, string)`` tuple.
630 630 ``alignment`` can be -1 for left aligned, 0 for centered and 1 for right
631 631 aligned (the default is left alignment). ``full`` is a boolean that specifies
632 632 whether the complete output must be displayed or the ``Display`` object is
633 633 allowed to stop output after enough text has been produced (e.g. a syntax
634 634 highlighted text line would use ``True``, but for a large data structure
635 635 (i.e. a nested list, tuple or dictionary) ``False`` would be used).
636 636 The default is full output.
637 637
638 638 There are four different possible values for ``mode`` depending on where
639 639 the ``Display`` object will display ``item``:
640 640
641 641 * ``"header"``: ``item`` will be displayed in a header line (this is used by
642 642 ``ibrowse``).
643 643 * ``"footer"``: ``item`` will be displayed in a footer line (this is used by
644 644 ``ibrowse``).
645 645 * ``"cell"``: ``item`` will be displayed in a table cell/list.
646 646 * ``"default"``: default mode. If an ``xrepr`` implementation recursively
647 647 outputs objects, ``"default"`` must be passed in the recursive calls to
648 648 ``xrepr``.
649 649
650 650 If no implementation is registered for ``item``, ``xrepr`` will try the
651 651 ``__xrepr__`` method on ``item``. If ``item`` doesn't have an ``__xrepr__``
652 652 method it falls back to ``repr``/``__repr__`` for all modes.
653 653 """
654 654 try:
655 655 func = item.__xrepr__
656 656 except AttributeError:
657 657 yield (astyle.style_default, repr(item))
658 658 else:
659 659 try:
660 660 for x in func(mode):
661 661 yield x
662 662 except (KeyboardInterrupt, SystemExit):
663 663 raise
664 664 except Exception:
665 665 yield (astyle.style_default, repr(item))
666 666 xrepr = simplegeneric.generic(xrepr)
667 667
668 668
669 669 def xrepr_none(self, mode="default"):
670 670 yield (astyle.style_type_none, repr(self))
671 671 xrepr.when_object(None)(xrepr_none)
672 672
673 673
674 674 def xrepr_noitem(self, mode="default"):
675 675 yield (2, True)
676 676 yield (astyle.style_nodata, "<?>")
677 677 xrepr.when_object(noitem)(xrepr_noitem)
678 678
679 679
680 680 def xrepr_bool(self, mode="default"):
681 681 yield (astyle.style_type_bool, repr(self))
682 682 xrepr.when_type(bool)(xrepr_bool)
683 683
684 684
685 685 def xrepr_str(self, mode="default"):
686 686 if mode == "cell":
687 687 yield (astyle.style_default, repr(self.expandtabs(tab))[1:-1])
688 688 else:
689 689 yield (astyle.style_default, repr(self))
690 690 xrepr.when_type(str)(xrepr_str)
691 691
692 692
693 693 def xrepr_unicode(self, mode="default"):
694 694 if mode == "cell":
695 695 yield (astyle.style_default, repr(self.expandtabs(tab))[2:-1])
696 696 else:
697 697 yield (astyle.style_default, repr(self))
698 698 xrepr.when_type(unicode)(xrepr_unicode)
699 699
700 700
701 701 def xrepr_number(self, mode="default"):
702 702 yield (1, True)
703 703 yield (astyle.style_type_number, repr(self))
704 704 xrepr.when_type(int)(xrepr_number)
705 705 xrepr.when_type(long)(xrepr_number)
706 706 xrepr.when_type(float)(xrepr_number)
707 707
708 708
709 709 def xrepr_complex(self, mode="default"):
710 710 yield (astyle.style_type_number, repr(self))
711 711 xrepr.when_type(complex)(xrepr_number)
712 712
713 713
714 714 def xrepr_datetime(self, mode="default"):
715 715 if mode == "cell":
716 716 # Don't use strftime() here, as this requires year >= 1900
717 717 yield (astyle.style_type_datetime,
718 718 "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
719 719 (self.year, self.month, self.day,
720 720 self.hour, self.minute, self.second,
721 721 self.microsecond),
722 722 )
723 723 else:
724 724 yield (astyle.style_type_datetime, repr(self))
725 725 xrepr.when_type(datetime.datetime)(xrepr_datetime)
726 726
727 727
728 728 def xrepr_date(self, mode="default"):
729 729 if mode == "cell":
730 730 yield (astyle.style_type_datetime,
731 731 "%04d-%02d-%02d" % (self.year, self.month, self.day))
732 732 else:
733 733 yield (astyle.style_type_datetime, repr(self))
734 734 xrepr.when_type(datetime.date)(xrepr_date)
735 735
736 736
737 737 def xrepr_time(self, mode="default"):
738 738 if mode == "cell":
739 739 yield (astyle.style_type_datetime,
740 740 "%02d:%02d:%02d.%06d" % \
741 741 (self.hour, self.minute, self.second, self.microsecond))
742 742 else:
743 743 yield (astyle.style_type_datetime, repr(self))
744 744 xrepr.when_type(datetime.time)(xrepr_time)
745 745
746 746
747 747 def xrepr_timedelta(self, mode="default"):
748 748 yield (astyle.style_type_datetime, repr(self))
749 749 xrepr.when_type(datetime.timedelta)(xrepr_timedelta)
750 750
751 751
752 752 def xrepr_type(self, mode="default"):
753 753 if self.__module__ == "__builtin__":
754 754 yield (astyle.style_type_type, self.__name__)
755 755 else:
756 756 yield (astyle.style_type_type, "%s.%s" % (self.__module__, self.__name__))
757 757 xrepr.when_type(type)(xrepr_type)
758 758
759 759
760 760 def xrepr_exception(self, mode="default"):
761 761 if self.__class__.__module__ == "exceptions":
762 762 classname = self.__class__.__name__
763 763 else:
764 764 classname = "%s.%s" % \
765 765 (self.__class__.__module__, self.__class__.__name__)
766 766 if mode == "header" or mode == "footer":
767 767 yield (astyle.style_error, "%s: %s" % (classname, self))
768 768 else:
769 769 yield (astyle.style_error, classname)
770 770 xrepr.when_type(Exception)(xrepr_exception)
771 771
772 772
773 773 def xrepr_listtuple(self, mode="default"):
774 774 if mode == "header" or mode == "footer":
775 775 if self.__class__.__module__ == "__builtin__":
776 776 classname = self.__class__.__name__
777 777 else:
778 778 classname = "%s.%s" % \
779 779 (self.__class__.__module__,self.__class__.__name__)
780 780 yield (astyle.style_default,
781 781 "<%s object with %d items at 0x%x>" % \
782 782 (classname, len(self), id(self)))
783 783 else:
784 784 yield (-1, False)
785 785 if isinstance(self, list):
786 786 yield (astyle.style_default, "[")
787 787 end = "]"
788 788 else:
789 789 yield (astyle.style_default, "(")
790 790 end = ")"
791 791 for (i, subself) in enumerate(self):
792 792 if i:
793 793 yield (astyle.style_default, ", ")
794 794 for part in xrepr(subself, "default"):
795 795 yield part
796 796 yield (astyle.style_default, end)
797 797 xrepr.when_type(list)(xrepr_listtuple)
798 798 xrepr.when_type(tuple)(xrepr_listtuple)
799 799
800 800
801 801 def xrepr_dict(self, mode="default"):
802 802 if mode == "header" or mode == "footer":
803 803 if self.__class__.__module__ == "__builtin__":
804 804 classname = self.__class__.__name__
805 805 else:
806 806 classname = "%s.%s" % \
807 807 (self.__class__.__module__,self.__class__.__name__)
808 808 yield (astyle.style_default,
809 809 "<%s object with %d items at 0x%x>" % \
810 810 (classname, len(self), id(self)))
811 811 else:
812 812 yield (-1, False)
813 813 if isinstance(self, dict):
814 814 yield (astyle.style_default, "{")
815 815 end = "}"
816 816 else:
817 817 yield (astyle.style_default, "dictproxy((")
818 818 end = "})"
819 819 for (i, (key, value)) in enumerate(self.iteritems()):
820 820 if i:
821 821 yield (astyle.style_default, ", ")
822 822 for part in xrepr(key, "default"):
823 823 yield part
824 824 yield (astyle.style_default, ": ")
825 825 for part in xrepr(value, "default"):
826 826 yield part
827 827 yield (astyle.style_default, end)
828 828 xrepr.when_type(dict)(xrepr_dict)
829 829 xrepr.when_type(types.DictProxyType)(xrepr_dict)
830 830
831 831
832 832 def upgradexattr(attr):
833 833 """
834 834 Convert an attribute descriptor string to a real descriptor object.
835 835
836 836 If attr already is a descriptor object return if unmodified. A
837 837 ``SelfDescriptor`` will be returned if ``attr`` is ``None``. ``"foo"``
838 838 returns an ``AttributeDescriptor`` for the attribute named ``"foo"``.
839 839 ``"foo()"`` returns a ``MethodDescriptor`` for the method named ``"foo"``.
840 840 ``"-foo"`` will return an ``IterAttributeDescriptor`` for the attribute
841 841 named ``"foo"`` and ``"-foo()"`` will return an ``IterMethodDescriptor``
842 842 for the method named ``"foo"``. Furthermore integer will return the appropriate
843 843 ``IndexDescriptor`` and callables will return a ``FunctionDescriptor``.
844 844 """
845 845 if attr is None:
846 846 return selfdescriptor
847 847 elif isinstance(attr, Descriptor):
848 848 return attr
849 849 elif isinstance(attr, str):
850 850 if attr.endswith("()"):
851 851 if attr.startswith("-"):
852 852 return IterMethodDescriptor(attr[1:-2])
853 853 else:
854 854 return MethodDescriptor(attr[:-2])
855 855 else:
856 856 if attr.startswith("-"):
857 857 return IterAttributeDescriptor(attr[1:])
858 858 else:
859 859 return AttributeDescriptor(attr)
860 860 elif isinstance(attr, (int, long)):
861 861 return IndexDescriptor(attr)
862 862 elif callable(attr):
863 863 return FunctionDescriptor(attr)
864 864 else:
865 865 raise TypeError("can't handle descriptor %r" % attr)
866 866
867 867
868 868 def xattrs(item, mode="default"):
869 869 """
870 870 Generic function that returns an iterable of attribute descriptors
871 871 to be used for displaying the attributes ob the object ``item`` in display
872 872 mode ``mode``.
873 873
874 874 There are two possible modes:
875 875
876 876 * ``"detail"``: The ``Display`` object wants to display a detailed list
877 877 of the object attributes.
878 878 * ``"default"``: The ``Display`` object wants to display the object in a
879 879 list view.
880 880
881 881 If no implementation is registered for the object ``item`` ``xattrs`` falls
882 882 back to trying the ``__xattrs__`` method of the object. If this doesn't
883 883 exist either, ``dir(item)`` is used for ``"detail"`` mode and ``(None,)``
884 884 for ``"default"`` mode.
885 885
886 886 The implementation must yield attribute descriptor (see the class
887 887 ``Descriptor`` for more info). The ``__xattrs__`` method may also return
888 888 attribute descriptor string (and ``None``) which will be converted to real
889 889 descriptors by ``upgradexattr()``.
890 890 """
891 891 try:
892 892 func = item.__xattrs__
893 893 except AttributeError:
894 894 if mode == "detail":
895 895 for attrname in dir(item):
896 896 yield AttributeDescriptor(attrname)
897 897 else:
898 898 yield selfdescriptor
899 899 else:
900 900 for attr in func(mode):
901 901 yield upgradexattr(attr)
902 902 xattrs = simplegeneric.generic(xattrs)
903 903
904 904
905 905 def xattrs_complex(self, mode="default"):
906 906 if mode == "detail":
907 907 return (AttributeDescriptor("real"), AttributeDescriptor("imag"))
908 908 return (selfdescriptor,)
909 909 xattrs.when_type(complex)(xattrs_complex)
910 910
911 911
912 912 def _isdict(item):
913 913 try:
914 914 itermeth = item.__class__.__iter__
915 915 except (AttributeError, TypeError):
916 916 return False
917 917 return itermeth is dict.__iter__ or itermeth is types.DictProxyType.__iter__
918 918
919 919
920 920 def _isstr(item):
921 921 if not isinstance(item, basestring):
922 922 return False
923 923 try:
924 924 itermeth = item.__class__.__iter__
925 925 except AttributeError:
926 926 return True
927 927 return False # ``__iter__`` has been redefined
928 928
929 929
930 930 def xiter(item):
931 931 """
932 932 Generic function that implements iteration for pipeline expression. If no
933 933 implementation is registered for ``item`` ``xiter`` falls back to ``iter``.
934 934 """
935 935 try:
936 936 func = item.__xiter__
937 937 except AttributeError:
938 938 if _isdict(item):
939 939 def items(item):
940 940 fields = ("key", "value")
941 941 for (key, value) in item.iteritems():
942 942 yield Fields(fields, key=key, value=value)
943 943 return items(item)
944 944 elif isinstance(item, new.module):
945 945 def items(item):
946 946 fields = ("key", "value")
947 947 for key in sorted(item.__dict__):
948 948 yield Fields(fields, key=key, value=getattr(item, key))
949 949 return items(item)
950 950 elif _isstr(item):
951 951 if not item:
952 952 raise ValueError("can't enter empty string")
953 953 lines = item.splitlines()
954 954 if len(lines) == 1:
955 955 def iterone(item):
956 956 yield item
957 957 return iterone(item)
958 958 else:
959 959 return iter(lines)
960 960 return iter(item)
961 961 else:
962 962 return iter(func()) # iter() just to be safe
963 963 xiter = simplegeneric.generic(xiter)
964 964
965 965
966 966 class ichain(Pipe):
967 967 """
968 968 Chains multiple ``Table``s into one.
969 969 """
970 970
971 971 def __init__(self, *iters):
972 972 self.iters = iters
973 973
974 974 def __iter__(self):
975 975 return itertools.chain(*self.iters)
976 976
977 977 def __xrepr__(self, mode="default"):
978 978 if mode == "header" or mode == "footer":
979 979 for (i, item) in enumerate(self.iters):
980 980 if i:
981 981 yield (astyle.style_default, "+")
982 982 if isinstance(item, Pipe):
983 983 yield (astyle.style_default, "(")
984 984 for part in xrepr(item, mode):
985 985 yield part
986 986 if isinstance(item, Pipe):
987 987 yield (astyle.style_default, ")")
988 988 else:
989 989 yield (astyle.style_default, repr(self))
990 990
991 991 def __repr__(self):
992 992 args = ", ".join([repr(it) for it in self.iters])
993 993 return "%s.%s(%s)" % \
994 994 (self.__class__.__module__, self.__class__.__name__, args)
995 995
996 996
997 997 class ifile(path.path):
998 998 """
999 999 file (or directory) object.
1000 1000 """
1001 1001
1002 1002 def getmode(self):
1003 1003 return self.stat().st_mode
1004 1004 mode = property(getmode, None, None, "Access mode")
1005 1005
1006 1006 def gettype(self):
1007 1007 data = [
1008 1008 (stat.S_ISREG, "file"),
1009 1009 (stat.S_ISDIR, "dir"),
1010 1010 (stat.S_ISCHR, "chardev"),
1011 1011 (stat.S_ISBLK, "blockdev"),
1012 1012 (stat.S_ISFIFO, "fifo"),
1013 1013 (stat.S_ISLNK, "symlink"),
1014 1014 (stat.S_ISSOCK,"socket"),
1015 1015 ]
1016 1016 lstat = self.lstat()
1017 1017 if lstat is not None:
1018 1018 types = set([text for (func, text) in data if func(lstat.st_mode)])
1019 1019 else:
1020 1020 types = set()
1021 1021 m = self.mode
1022 1022 types.update([text for (func, text) in data if func(m)])
1023 1023 return ", ".join(types)
1024 1024 type = property(gettype, None, None, "file type (file, directory, link, etc.)")
1025 1025
1026 1026 def getmodestr(self):
1027 1027 m = self.mode
1028 1028 data = [
1029 1029 (stat.S_IRUSR, "-r"),
1030 1030 (stat.S_IWUSR, "-w"),
1031 1031 (stat.S_IXUSR, "-x"),
1032 1032 (stat.S_IRGRP, "-r"),
1033 1033 (stat.S_IWGRP, "-w"),
1034 1034 (stat.S_IXGRP, "-x"),
1035 1035 (stat.S_IROTH, "-r"),
1036 1036 (stat.S_IWOTH, "-w"),
1037 1037 (stat.S_IXOTH, "-x"),
1038 1038 ]
1039 1039 return "".join([text[bool(m&bit)] for (bit, text) in data])
1040 1040
1041 1041 modestr = property(getmodestr, None, None, "Access mode as string")
1042 1042
1043 1043 def getblocks(self):
1044 1044 return self.stat().st_blocks
1045 1045 blocks = property(getblocks, None, None, "File size in blocks")
1046 1046
1047 1047 def getblksize(self):
1048 1048 return self.stat().st_blksize
1049 1049 blksize = property(getblksize, None, None, "Filesystem block size")
1050 1050
1051 1051 def getdev(self):
1052 1052 return self.stat().st_dev
1053 1053 dev = property(getdev)
1054 1054
1055 1055 def getnlink(self):
1056 1056 return self.stat().st_nlink
1057 1057 nlink = property(getnlink, None, None, "Number of links")
1058 1058
1059 1059 def getuid(self):
1060 1060 return self.stat().st_uid
1061 1061 uid = property(getuid, None, None, "User id of file owner")
1062 1062
1063 1063 def getgid(self):
1064 1064 return self.stat().st_gid
1065 1065 gid = property(getgid, None, None, "Group id of file owner")
1066 1066
1067 1067 def getowner(self):
1068 1068 stat = self.stat()
1069 1069 try:
1070 1070 return pwd.getpwuid(stat.st_uid).pw_name
1071 1071 except KeyError:
1072 1072 return stat.st_uid
1073 1073 owner = property(getowner, None, None, "Owner name (or id)")
1074 1074
1075 1075 def getgroup(self):
1076 1076 stat = self.stat()
1077 1077 try:
1078 1078 return grp.getgrgid(stat.st_gid).gr_name
1079 1079 except KeyError:
1080 1080 return stat.st_gid
1081 1081 group = property(getgroup, None, None, "Group name (or id)")
1082 1082
1083 1083 def getadate(self):
1084 1084 return datetime.datetime.utcfromtimestamp(self.atime)
1085 1085 adate = property(getadate, None, None, "Access date")
1086 1086
1087 1087 def getcdate(self):
1088 1088 return datetime.datetime.utcfromtimestamp(self.ctime)
1089 1089 cdate = property(getcdate, None, None, "Creation date")
1090 1090
1091 1091 def getmdate(self):
1092 1092 return datetime.datetime.utcfromtimestamp(self.mtime)
1093 1093 mdate = property(getmdate, None, None, "Modification date")
1094 1094
1095 1095 def mimetype(self):
1096 1096 """
1097 1097 Return MIME type guessed from the extension.
1098 1098 """
1099 1099 return mimetypes.guess_type(self.basename())[0]
1100 1100
1101 1101 def encoding(self):
1102 1102 """
1103 1103 Return guessed compression (like "compress" or "gzip").
1104 1104 """
1105 1105 return mimetypes.guess_type(self.basename())[1]
1106 1106
1107 1107 def __repr__(self):
1108 1108 return "ifile(%s)" % path._base.__repr__(self)
1109 1109
1110 1110 if sys.platform == "win32":
1111 1111 defaultattrs = (None, "type", "size", "modestr", "mdate")
1112 1112 else:
1113 1113 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
1114 1114
1115 1115 def __xattrs__(self, mode="default"):
1116 1116 if mode == "detail":
1117 1117 return (
1118 1118 "name",
1119 1119 "basename()",
1120 1120 "abspath()",
1121 1121 "realpath()",
1122 1122 "type",
1123 1123 "mode",
1124 1124 "modestr",
1125 1125 "stat()",
1126 1126 "lstat()",
1127 1127 "uid",
1128 1128 "gid",
1129 1129 "owner",
1130 1130 "group",
1131 1131 "dev",
1132 1132 "nlink",
1133 1133 "ctime",
1134 1134 "mtime",
1135 1135 "atime",
1136 1136 "cdate",
1137 1137 "mdate",
1138 1138 "adate",
1139 1139 "size",
1140 1140 "blocks",
1141 1141 "blksize",
1142 1142 "isdir()",
1143 1143 "islink()",
1144 1144 "mimetype()",
1145 1145 "encoding()",
1146 1146 "-listdir()",
1147 1147 "-dirs()",
1148 1148 "-files()",
1149 1149 "-walk()",
1150 1150 "-walkdirs()",
1151 1151 "-walkfiles()",
1152 1152 )
1153 1153 else:
1154 1154 return self.defaultattrs
1155 1155
1156 1156
1157 1157 def xiter_ifile(self):
1158 1158 if self.isdir():
1159 1159 yield (self / os.pardir).abspath()
1160 1160 for child in sorted(self.listdir()):
1161 1161 yield child
1162 1162 else:
1163 1163 f = self.open("rb")
1164 1164 for line in f:
1165 1165 yield line
1166 1166 f.close()
1167 1167 xiter.when_type(ifile)(xiter_ifile)
1168 1168
1169 1169
1170 1170 # We need to implement ``xrepr`` for ``ifile`` as a generic function, because
1171 1171 # otherwise ``xrepr_str`` would kick in.
1172 1172 def xrepr_ifile(self, mode="default"):
1173 1173 try:
1174 1174 if self.isdir():
1175 1175 name = "idir"
1176 1176 style = astyle.style_dir
1177 1177 else:
1178 1178 name = "ifile"
1179 1179 style = astyle.style_file
1180 1180 except IOError:
1181 1181 name = "ifile"
1182 1182 style = astyle.style_default
1183 1183 if mode in ("cell", "header", "footer"):
1184 1184 abspath = repr(path._base(self.normpath()))
1185 1185 if abspath.startswith("u"):
1186 1186 abspath = abspath[2:-1]
1187 1187 else:
1188 1188 abspath = abspath[1:-1]
1189 1189 if mode == "cell":
1190 1190 yield (style, abspath)
1191 1191 else:
1192 1192 yield (style, "%s(%s)" % (name, abspath))
1193 1193 else:
1194 1194 yield (style, repr(self))
1195 1195 xrepr.when_type(ifile)(xrepr_ifile)
1196 1196
1197 1197
1198 1198 class ils(Table):
1199 1199 """
1200 1200 List the current (or a specified) directory.
1201 1201
1202 1202 Examples:
1203 1203
1204 1204 >>> ils
1205 1205 >>> ils("/usr/local/lib/python2.4")
1206 1206 >>> ils("~")
1207 1207 """
1208 1208 def __init__(self, base=os.curdir, dirs=True, files=True):
1209 1209 self.base = os.path.expanduser(base)
1210 1210 self.dirs = dirs
1211 1211 self.files = files
1212 1212
1213 1213 def __iter__(self):
1214 1214 base = ifile(self.base)
1215 1215 yield (base / os.pardir).abspath()
1216 1216 for child in sorted(base.listdir()):
1217 1217 if self.dirs:
1218 1218 if self.files:
1219 1219 yield child
1220 1220 else:
1221 1221 if child.isdir():
1222 1222 yield child
1223 1223 elif self.files:
1224 1224 if not child.isdir():
1225 1225 yield child
1226 1226
1227 1227 def __xrepr__(self, mode="default"):
1228 1228 return xrepr(ifile(self.base), mode)
1229 1229
1230 1230 def __repr__(self):
1231 1231 return "%s.%s(%r)" % \
1232 1232 (self.__class__.__module__, self.__class__.__name__, self.base)
1233 1233
1234 1234
1235 1235 class iglob(Table):
1236 1236 """
1237 1237 List all files and directories matching a specified pattern.
1238 1238 (See ``glob.glob()`` for more info.).
1239 1239
1240 1240 Examples:
1241 1241
1242 1242 >>> iglob("*.py")
1243 1243 """
1244 1244 def __init__(self, glob):
1245 1245 self.glob = glob
1246 1246
1247 1247 def __iter__(self):
1248 1248 for name in glob.glob(self.glob):
1249 1249 yield ifile(name)
1250 1250
1251 1251 def __xrepr__(self, mode="default"):
1252 1252 if mode == "header" or mode == "footer" or mode == "cell":
1253 1253 yield (astyle.style_default,
1254 1254 "%s(%r)" % (self.__class__.__name__, self.glob))
1255 1255 else:
1256 1256 yield (astyle.style_default, repr(self))
1257 1257
1258 1258 def __repr__(self):
1259 1259 return "%s.%s(%r)" % \
1260 1260 (self.__class__.__module__, self.__class__.__name__, self.glob)
1261 1261
1262 1262
1263 1263 class iwalk(Table):
1264 1264 """
1265 1265 List all files and directories in a directory and it's subdirectory.
1266 1266
1267 1267 >>> iwalk
1268 1268 >>> iwalk("/usr/local/lib/python2.4")
1269 1269 >>> iwalk("~")
1270 1270 """
1271 1271 def __init__(self, base=os.curdir, dirs=True, files=True):
1272 1272 self.base = os.path.expanduser(base)
1273 1273 self.dirs = dirs
1274 1274 self.files = files
1275 1275
1276 1276 def __iter__(self):
1277 1277 for (dirpath, dirnames, filenames) in os.walk(self.base):
1278 1278 if self.dirs:
1279 1279 for name in sorted(dirnames):
1280 1280 yield ifile(os.path.join(dirpath, name))
1281 1281 if self.files:
1282 1282 for name in sorted(filenames):
1283 1283 yield ifile(os.path.join(dirpath, name))
1284 1284
1285 1285 def __xrepr__(self, mode="default"):
1286 1286 if mode == "header" or mode == "footer" or mode == "cell":
1287 1287 yield (astyle.style_default,
1288 1288 "%s(%r)" % (self.__class__.__name__, self.base))
1289 1289 else:
1290 1290 yield (astyle.style_default, repr(self))
1291 1291
1292 1292 def __repr__(self):
1293 1293 return "%s.%s(%r)" % \
1294 1294 (self.__class__.__module__, self.__class__.__name__, self.base)
1295 1295
1296 1296
1297 1297 class ipwdentry(object):
1298 1298 """
1299 1299 ``ipwdentry`` objects encapsulate entries in the Unix user account and
1300 1300 password database.
1301 1301 """
1302 1302 def __init__(self, id):
1303 1303 self._id = id
1304 1304 self._entry = None
1305 1305
1306 1306 def __eq__(self, other):
1307 1307 return self.__class__ is other.__class__ and self._id == other._id
1308 1308
1309 1309 def __ne__(self, other):
1310 1310 return self.__class__ is not other.__class__ or self._id != other._id
1311 1311
1312 1312 def _getentry(self):
1313 1313 if self._entry is None:
1314 1314 if isinstance(self._id, basestring):
1315 1315 self._entry = pwd.getpwnam(self._id)
1316 1316 else:
1317 1317 self._entry = pwd.getpwuid(self._id)
1318 1318 return self._entry
1319 1319
1320 1320 def getname(self):
1321 1321 if isinstance(self._id, basestring):
1322 1322 return self._id
1323 1323 else:
1324 1324 return self._getentry().pw_name
1325 1325 name = property(getname, None, None, "User name")
1326 1326
1327 1327 def getpasswd(self):
1328 1328 return self._getentry().pw_passwd
1329 1329 passwd = property(getpasswd, None, None, "Password")
1330 1330
1331 1331 def getuid(self):
1332 1332 if isinstance(self._id, basestring):
1333 1333 return self._getentry().pw_uid
1334 1334 else:
1335 1335 return self._id
1336 1336 uid = property(getuid, None, None, "User id")
1337 1337
1338 1338 def getgid(self):
1339 1339 return self._getentry().pw_gid
1340 1340 gid = property(getgid, None, None, "Primary group id")
1341 1341
1342 1342 def getgroup(self):
1343 1343 return igrpentry(self.gid)
1344 1344 group = property(getgroup, None, None, "Group")
1345 1345
1346 1346 def getgecos(self):
1347 1347 return self._getentry().pw_gecos
1348 1348 gecos = property(getgecos, None, None, "Information (e.g. full user name)")
1349 1349
1350 1350 def getdir(self):
1351 1351 return self._getentry().pw_dir
1352 1352 dir = property(getdir, None, None, "$HOME directory")
1353 1353
1354 1354 def getshell(self):
1355 1355 return self._getentry().pw_shell
1356 1356 shell = property(getshell, None, None, "Login shell")
1357 1357
1358 1358 def __xattrs__(self, mode="default"):
1359 1359 return ("name", "passwd", "uid", "gid", "gecos", "dir", "shell")
1360 1360
1361 1361 def __repr__(self):
1362 1362 return "%s.%s(%r)" % \
1363 1363 (self.__class__.__module__, self.__class__.__name__, self._id)
1364 1364
1365 1365
1366 1366 class ipwd(Table):
1367 1367 """
1368 1368 List all entries in the Unix user account and password database.
1369 1369
1370 1370 Example:
1371 1371
1372 1372 >>> ipwd | isort("uid")
1373 1373 """
1374 1374 def __iter__(self):
1375 1375 for entry in pwd.getpwall():
1376 1376 yield ipwdentry(entry.pw_name)
1377 1377
1378 1378 def __xrepr__(self, mode="default"):
1379 1379 if mode == "header" or mode == "footer" or mode == "cell":
1380 1380 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1381 1381 else:
1382 1382 yield (astyle.style_default, repr(self))
1383 1383
1384 1384
1385 1385 class igrpentry(object):
1386 1386 """
1387 1387 ``igrpentry`` objects encapsulate entries in the Unix group database.
1388 1388 """
1389 1389 def __init__(self, id):
1390 1390 self._id = id
1391 1391 self._entry = None
1392 1392
1393 1393 def __eq__(self, other):
1394 1394 return self.__class__ is other.__class__ and self._id == other._id
1395 1395
1396 1396 def __ne__(self, other):
1397 1397 return self.__class__ is not other.__class__ or self._id != other._id
1398 1398
1399 1399 def _getentry(self):
1400 1400 if self._entry is None:
1401 1401 if isinstance(self._id, basestring):
1402 1402 self._entry = grp.getgrnam(self._id)
1403 1403 else:
1404 1404 self._entry = grp.getgrgid(self._id)
1405 1405 return self._entry
1406 1406
1407 1407 def getname(self):
1408 1408 if isinstance(self._id, basestring):
1409 1409 return self._id
1410 1410 else:
1411 1411 return self._getentry().gr_name
1412 1412 name = property(getname, None, None, "Group name")
1413 1413
1414 1414 def getpasswd(self):
1415 1415 return self._getentry().gr_passwd
1416 1416 passwd = property(getpasswd, None, None, "Password")
1417 1417
1418 1418 def getgid(self):
1419 1419 if isinstance(self._id, basestring):
1420 1420 return self._getentry().gr_gid
1421 1421 else:
1422 1422 return self._id
1423 1423 gid = property(getgid, None, None, "Group id")
1424 1424
1425 1425 def getmem(self):
1426 1426 return self._getentry().gr_mem
1427 1427 mem = property(getmem, None, None, "Members")
1428 1428
1429 1429 def __xattrs__(self, mode="default"):
1430 1430 return ("name", "passwd", "gid", "mem")
1431 1431
1432 1432 def __xrepr__(self, mode="default"):
1433 1433 if mode == "header" or mode == "footer" or mode == "cell":
1434 1434 yield (astyle.style_default, "group ")
1435 1435 try:
1436 1436 yield (astyle.style_default, self.name)
1437 1437 except KeyError:
1438 1438 if isinstance(self._id, basestring):
1439 1439 yield (astyle.style_default, self.name_id)
1440 1440 else:
1441 1441 yield (astyle.style_type_number, str(self._id))
1442 1442 else:
1443 1443 yield (astyle.style_default, repr(self))
1444 1444
1445 1445 def __iter__(self):
1446 1446 for member in self.mem:
1447 1447 yield ipwdentry(member)
1448 1448
1449 1449 def __repr__(self):
1450 1450 return "%s.%s(%r)" % \
1451 1451 (self.__class__.__module__, self.__class__.__name__, self._id)
1452 1452
1453 1453
1454 1454 class igrp(Table):
1455 1455 """
1456 1456 This ``Table`` lists all entries in the Unix group database.
1457 1457 """
1458 1458 def __iter__(self):
1459 1459 for entry in grp.getgrall():
1460 1460 yield igrpentry(entry.gr_name)
1461 1461
1462 1462 def __xrepr__(self, mode="default"):
1463 1463 if mode == "header" or mode == "footer":
1464 1464 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1465 1465 else:
1466 1466 yield (astyle.style_default, repr(self))
1467 1467
1468 1468
1469 1469 class Fields(object):
1470 1470 def __init__(self, fieldnames, **fields):
1471 1471 self.__fieldnames = [upgradexattr(fieldname) for fieldname in fieldnames]
1472 1472 for (key, value) in fields.iteritems():
1473 1473 setattr(self, key, value)
1474 1474
1475 1475 def __xattrs__(self, mode="default"):
1476 1476 return self.__fieldnames
1477 1477
1478 1478 def __xrepr__(self, mode="default"):
1479 1479 yield (-1, False)
1480 1480 if mode == "header" or mode == "cell":
1481 1481 yield (astyle.style_default, self.__class__.__name__)
1482 1482 yield (astyle.style_default, "(")
1483 1483 for (i, f) in enumerate(self.__fieldnames):
1484 1484 if i:
1485 1485 yield (astyle.style_default, ", ")
1486 1486 yield (astyle.style_default, f.name())
1487 1487 yield (astyle.style_default, "=")
1488 1488 for part in xrepr(getattr(self, f), "default"):
1489 1489 yield part
1490 1490 yield (astyle.style_default, ")")
1491 1491 elif mode == "footer":
1492 1492 yield (astyle.style_default, self.__class__.__name__)
1493 1493 yield (astyle.style_default, "(")
1494 1494 for (i, f) in enumerate(self.__fieldnames):
1495 1495 if i:
1496 1496 yield (astyle.style_default, ", ")
1497 1497 yield (astyle.style_default, f.name())
1498 1498 yield (astyle.style_default, ")")
1499 1499 else:
1500 1500 yield (astyle.style_default, repr(self))
1501 1501
1502 def __str__(self):
1503 return ",".join([getattr(self,f) for f in self.__fieldnames])
1504
1505
1506 1502
1507 1503 class FieldTable(Table, list):
1508 1504 def __init__(self, *fields):
1509 1505 Table.__init__(self)
1510 1506 list.__init__(self)
1511 1507 self.fields = fields
1512 1508
1513 1509 def add(self, **fields):
1514 1510 self.append(Fields(self.fields, **fields))
1515 1511
1516 1512 def __xrepr__(self, mode="default"):
1517 1513 yield (-1, False)
1518 1514 if mode == "header" or mode == "footer":
1519 1515 yield (astyle.style_default, self.__class__.__name__)
1520 1516 yield (astyle.style_default, "(")
1521 1517 for (i, f) in enumerate(self.__fieldnames):
1522 1518 if i:
1523 1519 yield (astyle.style_default, ", ")
1524 1520 yield (astyle.style_default, f)
1525 1521 yield (astyle.style_default, ")")
1526 1522 else:
1527 1523 yield (astyle.style_default, repr(self))
1528 1524
1529 1525 def __repr__(self):
1530 1526 return "<%s.%s object with fields=%r at 0x%x>" % \
1531 1527 (self.__class__.__module__, self.__class__.__name__,
1532 1528 ", ".join(map(repr, self.fields)), id(self))
1533 1529
1534 1530
1535 1531 class List(list):
1536 1532 def __xattrs__(self, mode="default"):
1537 1533 return xrange(len(self))
1538 1534
1539 1535 def __xrepr__(self, mode="default"):
1540 1536 yield (-1, False)
1541 1537 if mode == "header" or mode == "cell" or mode == "footer" or mode == "default":
1542 1538 yield (astyle.style_default, self.__class__.__name__)
1543 1539 yield (astyle.style_default, "(")
1544 1540 for (i, item) in enumerate(self):
1545 1541 if i:
1546 1542 yield (astyle.style_default, ", ")
1547 1543 for part in xrepr(item, "default"):
1548 1544 yield part
1549 1545 yield (astyle.style_default, ")")
1550 1546 else:
1551 1547 yield (astyle.style_default, repr(self))
1552 1548
1553 1549
1554 1550 class ienv(Table):
1555 1551 """
1556 1552 List environment variables.
1557 1553
1558 1554 Example:
1559 1555
1560 1556 >>> ienv
1561 1557 """
1562 1558
1563 1559 def __iter__(self):
1564 1560 fields = ("key", "value")
1565 1561 for (key, value) in os.environ.iteritems():
1566 1562 yield Fields(fields, key=key, value=value)
1567 1563
1568 1564 def __xrepr__(self, mode="default"):
1569 1565 if mode == "header" or mode == "cell":
1570 1566 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1571 1567 else:
1572 1568 yield (astyle.style_default, repr(self))
1573 1569
1574 1570
1575 1571 class ihist(Table):
1576 1572 """
1577 1573 IPython input history
1578 1574
1579 1575 Example:
1580 1576
1581 1577 >>> ihist
1582 1578 >>> ihist(True) (raw mode)
1583 1579 """
1584 1580 def __init__(self, raw=True):
1585 1581 self.raw = raw
1586 1582
1587 1583 def __iter__(self):
1588 1584 api = ipapi.get()
1589 1585 if self.raw:
1590 1586 for line in api.IP.input_hist_raw:
1591 1587 yield line.rstrip("\n")
1592 1588 else:
1593 1589 for line in api.IP.input_hist:
1594 1590 yield line.rstrip("\n")
1595 1591
1596 1592
1597 1593 class icsv(Pipe):
1598 1594 """
1599 1595 This ``Pipe`` lists turn the input (with must be a pipe outputting lines
1600 1596 or an ``ifile``) into lines of CVS columns.
1601 1597 """
1602 1598 def __init__(self, **csvargs):
1603 1599 """
1604 1600 Create an ``icsv`` object. ``cvsargs`` will be passed through as
1605 1601 keyword arguments to ``cvs.reader()``.
1606 1602 """
1607 1603 self.csvargs = csvargs
1608 1604
1609 1605 def __iter__(self):
1610 1606 input = self.input
1611 1607 if isinstance(input, ifile):
1612 1608 input = input.open("rb")
1613 1609 reader = csv.reader(input, **self.csvargs)
1614 1610 for line in reader:
1615 1611 yield List(line)
1616 1612
1617 1613 def __xrepr__(self, mode="default"):
1618 1614 yield (-1, False)
1619 1615 if mode == "header" or mode == "footer":
1620 1616 input = getattr(self, "input", None)
1621 1617 if input is not None:
1622 1618 for part in xrepr(input, mode):
1623 1619 yield part
1624 1620 yield (astyle.style_default, " | ")
1625 1621 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1626 1622 for (i, (name, value)) in enumerate(self.csvargs.iteritems()):
1627 1623 if i:
1628 1624 yield (astyle.style_default, ", ")
1629 1625 yield (astyle.style_default, name)
1630 1626 yield (astyle.style_default, "=")
1631 1627 for part in xrepr(value, "default"):
1632 1628 yield part
1633 1629 yield (astyle.style_default, ")")
1634 1630 else:
1635 1631 yield (astyle.style_default, repr(self))
1636 1632
1637 1633 def __repr__(self):
1638 1634 args = ", ".join(["%s=%r" % item for item in self.csvargs.iteritems()])
1639 1635 return "<%s.%s %s at 0x%x>" % \
1640 1636 (self.__class__.__module__, self.__class__.__name__, args, id(self))
1641 1637
1642 1638
1643 1639 class ix(Table):
1644 1640 """
1645 1641 Execute a system command and list its output as lines
1646 1642 (similar to ``os.popen()``).
1647 1643
1648 1644 Examples:
1649 1645
1650 1646 >>> ix("ps x")
1651 1647 >>> ix("find .") | ifile
1652 1648 """
1653 1649 def __init__(self, cmd):
1654 1650 self.cmd = cmd
1655 1651 self._pipeout = None
1656 1652
1657 1653 def __iter__(self):
1658 1654 (_pipein, self._pipeout) = os.popen4(self.cmd)
1659 1655 _pipein.close()
1660 1656 for l in self._pipeout:
1661 1657 yield l.rstrip("\r\n")
1662 1658 self._pipeout.close()
1663 1659 self._pipeout = None
1664 1660
1665 1661 def __del__(self):
1666 1662 if self._pipeout is not None and not self._pipeout.closed:
1667 1663 self._pipeout.close()
1668 1664 self._pipeout = None
1669 1665
1670 1666 def __xrepr__(self, mode="default"):
1671 1667 if mode == "header" or mode == "footer":
1672 1668 yield (astyle.style_default,
1673 1669 "%s(%r)" % (self.__class__.__name__, self.cmd))
1674 1670 else:
1675 1671 yield (astyle.style_default, repr(self))
1676 1672
1677 1673 def __repr__(self):
1678 1674 return "%s.%s(%r)" % \
1679 1675 (self.__class__.__module__, self.__class__.__name__, self.cmd)
1680 1676
1681 1677
1682 1678 class ifilter(Pipe):
1683 1679 """
1684 1680 Filter an input pipe. Only objects where an expression evaluates to true
1685 1681 (and doesn't raise an exception) are listed.
1686 1682
1687 1683 Examples:
1688 1684
1689 1685 >>> ils | ifilter("_.isfile() and size>1000")
1690 1686 >>> igrp | ifilter("len(mem)")
1691 1687 >>> sys.modules | ifilter(lambda _:_.value is not None)
1692 1688 """
1693 1689
1694 1690 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1695 1691 """
1696 1692 Create an ``ifilter`` object. ``expr`` can be a callable or a string
1697 1693 containing an expression. ``globals`` will be used as the global
1698 1694 namespace for calling string expressions (defaulting to IPython's
1699 1695 user namespace). ``errors`` specifies how exception during evaluation
1700 1696 of ``expr`` are handled:
1701 1697
1702 1698 * ``drop``: drop all items that have errors;
1703 1699
1704 1700 * ``keep``: keep all items that have errors;
1705 1701
1706 1702 * ``keeperror``: keep the exception of all items that have errors;
1707 1703
1708 1704 * ``raise``: raise the exception;
1709 1705
1710 1706 * ``raiseifallfail``: raise the first exception if all items have errors;
1711 1707 otherwise drop those with errors (this is the default).
1712 1708 """
1713 1709 self.expr = expr
1714 1710 self.globals = globals
1715 1711 self.errors = errors
1716 1712
1717 1713 def __iter__(self):
1718 1714 if callable(self.expr):
1719 1715 test = self.expr
1720 1716 else:
1721 1717 g = getglobals(self.globals)
1722 1718 expr = compile(self.expr, "ipipe-expression", "eval")
1723 1719 def test(item):
1724 1720 return eval(expr, g, AttrNamespace(item))
1725 1721
1726 1722 ok = 0
1727 1723 exc_info = None
1728 1724 for item in xiter(self.input):
1729 1725 try:
1730 1726 if test(item):
1731 1727 yield item
1732 1728 ok += 1
1733 1729 except (KeyboardInterrupt, SystemExit):
1734 1730 raise
1735 1731 except Exception, exc:
1736 1732 if self.errors == "drop":
1737 1733 pass # Ignore errors
1738 1734 elif self.errors == "keep":
1739 1735 yield item
1740 1736 elif self.errors == "keeperror":
1741 1737 yield exc
1742 1738 elif self.errors == "raise":
1743 1739 raise
1744 1740 elif self.errors == "raiseifallfail":
1745 1741 if exc_info is None:
1746 1742 exc_info = sys.exc_info()
1747 1743 if not ok and exc_info is not None:
1748 1744 raise exc_info[0], exc_info[1], exc_info[2]
1749 1745
1750 1746 def __xrepr__(self, mode="default"):
1751 1747 if mode == "header" or mode == "footer":
1752 1748 input = getattr(self, "input", None)
1753 1749 if input is not None:
1754 1750 for part in xrepr(input, mode):
1755 1751 yield part
1756 1752 yield (astyle.style_default, " | ")
1757 1753 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1758 1754 for part in xrepr(self.expr, "default"):
1759 1755 yield part
1760 1756 yield (astyle.style_default, ")")
1761 1757 else:
1762 1758 yield (astyle.style_default, repr(self))
1763 1759
1764 1760 def __repr__(self):
1765 1761 return "<%s.%s expr=%r at 0x%x>" % \
1766 1762 (self.__class__.__module__, self.__class__.__name__,
1767 1763 self.expr, id(self))
1768 1764
1769 def igrep(pat):
1770 """ Filter an input pipe. Only yield items that contain the substring pat
1771
1772 This is case insensitive.
1773 """
1774 return ifilter('"""%s""" in str(_).lower()' % pat.lower())
1775 1765
1776 1766 class ieval(Pipe):
1777 1767 """
1778 1768 Evaluate an expression for each object in the input pipe.
1779 1769
1780 1770 Examples:
1781 1771
1782 1772 >>> ils | ieval("_.abspath()")
1783 1773 >>> sys.path | ieval(ifile)
1784 1774 """
1785 1775
1786 1776 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1787 1777 """
1788 1778 Create an ``ieval`` object. ``expr`` can be a callable or a string
1789 1779 containing an expression. For the meaning of ``globals`` and
1790 1780 ``errors`` see ``ifilter``.
1791 1781 """
1792 1782 self.expr = expr
1793 1783 self.globals = globals
1794 1784 self.errors = errors
1795 1785
1796 1786 def __iter__(self):
1797 1787 if callable(self.expr):
1798 1788 do = self.expr
1799 1789 else:
1800 1790 g = getglobals(self.globals)
1801 1791 expr = compile(self.expr, "ipipe-expression", "eval")
1802 1792 def do(item):
1803 1793 return eval(expr, g, AttrNamespace(item))
1804 1794
1805 1795 ok = 0
1806 1796 exc_info = None
1807 1797 for item in xiter(self.input):
1808 1798 try:
1809 1799 yield do(item)
1810 1800 except (KeyboardInterrupt, SystemExit):
1811 1801 raise
1812 1802 except Exception, exc:
1813 1803 if self.errors == "drop":
1814 1804 pass # Ignore errors
1815 1805 elif self.errors == "keep":
1816 1806 yield item
1817 1807 elif self.errors == "keeperror":
1818 1808 yield exc
1819 1809 elif self.errors == "raise":
1820 1810 raise
1821 1811 elif self.errors == "raiseifallfail":
1822 1812 if exc_info is None:
1823 1813 exc_info = sys.exc_info()
1824 1814 if not ok and exc_info is not None:
1825 1815 raise exc_info[0], exc_info[1], exc_info[2]
1826 1816
1827 1817 def __xrepr__(self, mode="default"):
1828 1818 if mode == "header" or mode == "footer":
1829 1819 input = getattr(self, "input", None)
1830 1820 if input is not None:
1831 1821 for part in xrepr(input, mode):
1832 1822 yield part
1833 1823 yield (astyle.style_default, " | ")
1834 1824 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1835 1825 for part in xrepr(self.expr, "default"):
1836 1826 yield part
1837 1827 yield (astyle.style_default, ")")
1838 1828 else:
1839 1829 yield (astyle.style_default, repr(self))
1840 1830
1841 1831 def __repr__(self):
1842 1832 return "<%s.%s expr=%r at 0x%x>" % \
1843 1833 (self.__class__.__module__, self.__class__.__name__,
1844 1834 self.expr, id(self))
1845 1835
1846 1836
1847 1837 class ienum(Pipe):
1848 1838 """
1849 1839 Enumerate the input pipe (i.e. wrap each input object in an object
1850 1840 with ``index`` and ``object`` attributes).
1851 1841
1852 1842 Examples:
1853 1843
1854 1844 >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object")
1855 1845 """
1856 1846 def __iter__(self):
1857 1847 fields = ("index", "object")
1858 1848 for (index, object) in enumerate(xiter(self.input)):
1859 1849 yield Fields(fields, index=index, object=object)
1860 1850
1861 1851
1862 1852 class isort(Pipe):
1863 1853 """
1864 1854 Sorts the input pipe.
1865 1855
1866 1856 Examples:
1867 1857
1868 1858 >>> ils | isort("size")
1869 1859 >>> ils | isort("_.isdir(), _.lower()", reverse=True)
1870 1860 """
1871 1861
1872 1862 def __init__(self, key=None, globals=None, reverse=False):
1873 1863 """
1874 1864 Create an ``isort`` object. ``key`` can be a callable or a string
1875 1865 containing an expression (or ``None`` in which case the items
1876 1866 themselves will be sorted). If ``reverse`` is true the sort order
1877 1867 will be reversed. For the meaning of ``globals`` see ``ifilter``.
1878 1868 """
1879 1869 self.key = key
1880 1870 self.globals = globals
1881 1871 self.reverse = reverse
1882 1872
1883 1873 def __iter__(self):
1884 1874 if self.key is None:
1885 1875 items = sorted(xiter(self.input), reverse=self.reverse)
1886 1876 elif callable(self.key):
1887 1877 items = sorted(xiter(self.input), key=self.key, reverse=self.reverse)
1888 1878 else:
1889 1879 g = getglobals(self.globals)
1890 1880 key = compile(self.key, "ipipe-expression", "eval")
1891 1881 def realkey(item):
1892 1882 return eval(key, g, AttrNamespace(item))
1893 1883 items = sorted(xiter(self.input), key=realkey, reverse=self.reverse)
1894 1884 for item in items:
1895 1885 yield item
1896 1886
1897 1887 def __xrepr__(self, mode="default"):
1898 1888 if mode == "header" or mode == "footer":
1899 1889 input = getattr(self, "input", None)
1900 1890 if input is not None:
1901 1891 for part in xrepr(input, mode):
1902 1892 yield part
1903 1893 yield (astyle.style_default, " | ")
1904 1894 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1905 1895 for part in xrepr(self.key, "default"):
1906 1896 yield part
1907 1897 if self.reverse:
1908 1898 yield (astyle.style_default, ", ")
1909 1899 for part in xrepr(True, "default"):
1910 1900 yield part
1911 1901 yield (astyle.style_default, ")")
1912 1902 else:
1913 1903 yield (astyle.style_default, repr(self))
1914 1904
1915 1905 def __repr__(self):
1916 1906 return "<%s.%s key=%r reverse=%r at 0x%x>" % \
1917 1907 (self.__class__.__module__, self.__class__.__name__,
1918 1908 self.key, self.reverse, id(self))
1919 1909
1920 1910
1921 1911 tab = 3 # for expandtabs()
1922 1912
1923 1913 def _format(field):
1924 1914 if isinstance(field, str):
1925 1915 text = repr(field.expandtabs(tab))[1:-1]
1926 1916 elif isinstance(field, unicode):
1927 1917 text = repr(field.expandtabs(tab))[2:-1]
1928 1918 elif isinstance(field, datetime.datetime):
1929 1919 # Don't use strftime() here, as this requires year >= 1900
1930 1920 text = "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
1931 1921 (field.year, field.month, field.day,
1932 1922 field.hour, field.minute, field.second, field.microsecond)
1933 1923 elif isinstance(field, datetime.date):
1934 1924 text = "%04d-%02d-%02d" % (field.year, field.month, field.day)
1935 1925 else:
1936 1926 text = repr(field)
1937 1927 return text
1938 1928
1939 1929
1940 1930 class Display(object):
1941 1931 class __metaclass__(type):
1942 1932 def __ror__(self, input):
1943 1933 return input | self()
1944 1934
1945 1935 def __ror__(self, input):
1946 1936 self.input = input
1947 1937 return self
1948 1938
1949 1939 def display(self):
1950 1940 pass
1951 1941
1952 1942
1953 1943 class iless(Display):
1954 1944 cmd = "less --quit-if-one-screen --LONG-PROMPT --LINE-NUMBERS --chop-long-lines --shift=8 --RAW-CONTROL-CHARS"
1955 1945
1956 1946 def display(self):
1957 1947 try:
1958 1948 pager = os.popen(self.cmd, "w")
1959 1949 try:
1960 1950 for item in xiter(self.input):
1961 1951 first = False
1962 1952 for attr in xattrs(item, "default"):
1963 1953 if first:
1964 1954 first = False
1965 1955 else:
1966 1956 pager.write(" ")
1967 1957 attr = upgradexattr(attr)
1968 1958 if not isinstance(attr, SelfDescriptor):
1969 1959 pager.write(attr.name())
1970 1960 pager.write("=")
1971 1961 pager.write(str(attr.value(item)))
1972 1962 pager.write("\n")
1973 1963 finally:
1974 1964 pager.close()
1975 1965 except Exception, exc:
1976 1966 print "%s: %s" % (exc.__class__.__name__, str(exc))
1977 1967
1978 1968
1979 1969 class _RedirectIO(object):
1980 1970 def __init__(self,*args,**kwargs):
1981 1971 """
1982 1972 Map the system output streams to self.
1983 1973 """
1984 1974 self.stream = StringIO.StringIO()
1985 1975 self.stdout = sys.stdout
1986 1976 sys.stdout = self
1987 1977 self.stderr = sys.stderr
1988 1978 sys.stderr = self
1989 1979
1990 1980 def write(self, text):
1991 1981 """
1992 1982 Write both to screen and to self.
1993 1983 """
1994 1984 self.stream.write(text)
1995 1985 self.stdout.write(text)
1996 1986 if "\n" in text:
1997 1987 self.stdout.flush()
1998 1988
1999 1989 def writelines(self, lines):
2000 1990 """
2001 1991 Write lines both to screen and to self.
2002 1992 """
2003 1993 self.stream.writelines(lines)
2004 1994 self.stdout.writelines(lines)
2005 1995 self.stdout.flush()
2006 1996
2007 1997 def restore(self):
2008 1998 """
2009 1999 Restore the default system streams.
2010 2000 """
2011 2001 self.stdout.flush()
2012 2002 self.stderr.flush()
2013 2003 sys.stdout = self.stdout
2014 2004 sys.stderr = self.stderr
2015 2005
2016 2006
2017 2007 class icap(Table):
2018 2008 """
2019 2009 Execute a python string and capture any output to stderr/stdout.
2020 2010
2021 2011 Examples:
2022 2012
2023 2013 >>> import time
2024 2014 >>> icap("for i in range(10): print i, time.sleep(0.1)")
2025 2015
2026 2016 """
2027 2017 def __init__(self, expr, globals=None):
2028 2018 self.expr = expr
2029 2019 self.globals = globals
2030 2020 log = _RedirectIO()
2031 2021 try:
2032 2022 exec(expr, getglobals(globals))
2033 2023 finally:
2034 2024 log.restore()
2035 2025 self.stream = log.stream
2036 2026
2037 2027 def __iter__(self):
2038 2028 self.stream.seek(0)
2039 2029 for line in self.stream:
2040 2030 yield line.rstrip("\r\n")
2041 2031
2042 2032 def __xrepr__(self, mode="default"):
2043 2033 if mode == "header" or mode == "footer":
2044 2034 yield (astyle.style_default,
2045 2035 "%s(%r)" % (self.__class__.__name__, self.expr))
2046 2036 else:
2047 2037 yield (astyle.style_default, repr(self))
2048 2038
2049 2039 def __repr__(self):
2050 2040 return "%s.%s(%r)" % \
2051 2041 (self.__class__.__module__, self.__class__.__name__, self.expr)
2052 2042
2053 2043
2054 2044 def xformat(value, mode, maxlength):
2055 2045 align = None
2056 2046 full = True
2057 2047 width = 0
2058 2048 text = astyle.Text()
2059 2049 for (style, part) in xrepr(value, mode):
2060 2050 # only consider the first result
2061 2051 if align is None:
2062 2052 if isinstance(style, int):
2063 2053 # (style, text) really is (alignment, stop)
2064 2054 align = style
2065 2055 full = part
2066 2056 continue
2067 2057 else:
2068 2058 align = -1
2069 2059 full = True
2070 2060 if not isinstance(style, int):
2071 2061 text.append((style, part))
2072 2062 width += len(part)
2073 2063 if width >= maxlength and not full:
2074 2064 text.append((astyle.style_ellisis, "..."))
2075 2065 width += 3
2076 2066 break
2077 2067 if align is None: # default to left alignment
2078 2068 align = -1
2079 2069 return (align, width, text)
2080 2070
2081 2071
2082 2072 class idump(Display):
2083 2073 # The approximate maximum length of a column entry
2084 2074 maxattrlength = 200
2085 2075
2086 2076 # Style for column names
2087 2077 style_header = astyle.Style.fromstr("white:black:bold")
2088 2078
2089 2079 def __init__(self, *attrs):
2090 2080 self.attrs = [upgradexattr(attr) for attr in attrs]
2091 2081 self.headerpadchar = " "
2092 2082 self.headersepchar = "|"
2093 2083 self.datapadchar = " "
2094 2084 self.datasepchar = "|"
2095 2085
2096 2086 def display(self):
2097 2087 stream = genutils.Term.cout
2098 2088 allattrs = []
2099 2089 attrset = set()
2100 2090 colwidths = {}
2101 2091 rows = []
2102 2092 for item in xiter(self.input):
2103 2093 row = {}
2104 2094 attrs = self.attrs
2105 2095 if not attrs:
2106 2096 attrs = xattrs(item, "default")
2107 2097 for attr in attrs:
2108 2098 if attr not in attrset:
2109 2099 allattrs.append(attr)
2110 2100 attrset.add(attr)
2111 2101 colwidths[attr] = len(attr.name())
2112 2102 try:
2113 2103 value = attr.value(item)
2114 2104 except (KeyboardInterrupt, SystemExit):
2115 2105 raise
2116 2106 except Exception, exc:
2117 2107 value = exc
2118 2108 (align, width, text) = xformat(value, "cell", self.maxattrlength)
2119 2109 colwidths[attr] = max(colwidths[attr], width)
2120 2110 # remember alignment, length and colored parts
2121 2111 row[attr] = (align, width, text)
2122 2112 rows.append(row)
2123 2113
2124 2114 stream.write("\n")
2125 2115 for (i, attr) in enumerate(allattrs):
2126 2116 attrname = attr.name()
2127 2117 self.style_header(attrname).write(stream)
2128 2118 spc = colwidths[attr] - len(attrname)
2129 2119 if i < len(colwidths)-1:
2130 2120 stream.write(self.headerpadchar*spc)
2131 2121 stream.write(self.headersepchar)
2132 2122 stream.write("\n")
2133 2123
2134 2124 for row in rows:
2135 2125 for (i, attr) in enumerate(allattrs):
2136 2126 (align, width, text) = row[attr]
2137 2127 spc = colwidths[attr] - width
2138 2128 if align == -1:
2139 2129 text.write(stream)
2140 2130 if i < len(colwidths)-1:
2141 2131 stream.write(self.datapadchar*spc)
2142 2132 elif align == 0:
2143 2133 spc = colwidths[attr] - width
2144 2134 spc1 = spc//2
2145 2135 spc2 = spc-spc1
2146 2136 stream.write(self.datapadchar*spc1)
2147 2137 text.write(stream)
2148 2138 if i < len(colwidths)-1:
2149 2139 stream.write(self.datapadchar*spc2)
2150 2140 else:
2151 2141 stream.write(self.datapadchar*spc)
2152 2142 text.write(stream)
2153 2143 if i < len(colwidths)-1:
2154 2144 stream.write(self.datasepchar)
2155 2145 stream.write("\n")
2156 2146
2157 2147
2158 2148 class AttributeDetail(Table):
2159 2149 """
2160 2150 ``AttributeDetail`` objects are use for displaying a detailed list of object
2161 2151 attributes.
2162 2152 """
2163 2153 def __init__(self, object, descriptor):
2164 2154 self.object = object
2165 2155 self.descriptor = descriptor
2166 2156
2167 2157 def __iter__(self):
2168 2158 return self.descriptor.iter(self.object)
2169 2159
2170 2160 def name(self):
2171 2161 return self.descriptor.name()
2172 2162
2173 2163 def attrtype(self):
2174 2164 return self.descriptor.attrtype(self.object)
2175 2165
2176 2166 def valuetype(self):
2177 2167 return self.descriptor.valuetype(self.object)
2178 2168
2179 2169 def doc(self):
2180 2170 return self.descriptor.doc(self.object)
2181 2171
2182 2172 def shortdoc(self):
2183 2173 return self.descriptor.shortdoc(self.object)
2184 2174
2185 2175 def value(self):
2186 2176 return self.descriptor.value(self.object)
2187 2177
2188 2178 def __xattrs__(self, mode="default"):
2189 2179 attrs = ("name()", "attrtype()", "valuetype()", "value()", "shortdoc()")
2190 2180 if mode == "detail":
2191 2181 attrs += ("doc()",)
2192 2182 return attrs
2193 2183
2194 2184 def __xrepr__(self, mode="default"):
2195 2185 yield (-1, True)
2196 2186 valuetype = self.valuetype()
2197 2187 if valuetype is not noitem:
2198 2188 for part in xrepr(valuetype):
2199 2189 yield part
2200 2190 yield (astyle.style_default, " ")
2201 2191 yield (astyle.style_default, self.attrtype())
2202 2192 yield (astyle.style_default, " ")
2203 2193 yield (astyle.style_default, self.name())
2204 2194 yield (astyle.style_default, " of ")
2205 2195 for part in xrepr(self.object):
2206 2196 yield part
2207 2197
2208 2198
2209 2199 try:
2210 2200 from ibrowse import ibrowse
2211 2201 except ImportError:
2212 2202 # No curses (probably Windows)
2213 2203 try:
2214 2204 from igrid import igrid
2215 2205 except ImportError:
2216 2206 # no wx eithevn do => use ``idump`` as the default display.
2217 2207 defaultdisplay = idump
2218 2208 else:
2219 2209 defaultdisplay = igrid
2220 2210 __all__.append("igrid")
2221 2211 else:
2222 2212 defaultdisplay = ibrowse
2223 2213 __all__.append("ibrowse")
2224 2214
2225 2215
2226 2216 # If we're running under IPython, install an IPython displayhook that
2227 2217 # returns the object from Display.display(), else install a displayhook
2228 2218 # directly as sys.displayhook
2229 2219 api = None
2230 2220 if ipapi is not None:
2231 2221 try:
2232 2222 api = ipapi.get()
2233 2223 except AttributeError:
2234 2224 pass
2235 2225
2236 2226 if api is not None:
2237 2227 def displayhook(self, obj):
2238 2228 if isinstance(obj, type) and issubclass(obj, Table):
2239 2229 obj = obj()
2240 2230 if isinstance(obj, Table):
2241 2231 obj = obj | defaultdisplay
2242 2232 if isinstance(obj, Display):
2243 2233 return obj.display()
2244 2234 else:
2245 2235 raise ipapi.TryNext
2246 2236 api.set_hook("result_display", displayhook)
2247 2237 else:
2248 2238 def installdisplayhook():
2249 2239 _originalhook = sys.displayhook
2250 2240 def displayhook(obj):
2251 2241 if isinstance(obj, type) and issubclass(obj, Table):
2252 2242 obj = obj()
2253 2243 if isinstance(obj, Table):
2254 2244 obj = obj | defaultdisplay
2255 2245 if isinstance(obj, Display):
2256 2246 return obj.display()
2257 2247 else:
2258 2248 _originalhook(obj)
2259 2249 sys.displayhook = displayhook
2260 2250 installdisplayhook()
General Comments 0
You need to be logged in to leave comments. Login now