##// END OF EJS Templates
Make left alignment and full output the default...
walter.doerwald -
Show More
@@ -1,1864 +1,1838 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 ``ls`` (listing the
19 19 current directory, ``ienv`` (listing environment variables), ``ipwd`` (listing
20 20 user account) 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 ``browse`` 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)``. This method must return a
41 41 sequence of attribute names. This sequence may also contain integers, which
42 42 will be treated as sequence indizes. Also supported is ``None``, which uses
43 43 the object itself and callables which will be called with the object as the
44 44 an argument. If ``__xattrs__()`` isn't implemented ``(None,)`` will be used as
45 45 the attribute sequence (i.e. the object itself (it's ``repr()`` format) will
46 46 be being displayed. The global function ``xattrs()`` implements this
47 47 functionality.
48 48
49 49 * When an object ``foo`` is displayed in the header, footer or table cell of the
50 50 browser ``foo.__xrepr__(mode)`` is called. Mode can be ``"header"`` or
51 51 ``"footer"`` for the header or footer line and ``"cell"`` for a table cell.
52 52 ``__xrepr__()```must return an iterable (e.g. by being a generator) which
53 53 produces the following items: The first item should be a tuple containing
54 54 the alignment (-1 left aligned, 0 centered and 1 right aligned) and whether
55 55 the complete output must be displayed or if the browser is allowed to stop
56 56 output after enough text has been produced (e.g. a syntax highlighted text
57 57 line would use ``True``, but for a large data structure (i.e. a nested list,
58 58 tuple or dictionary) ``False`` would be used). The other output ``__xrepr__()``
59 59 may produce is tuples of ``Style```objects and text (which contain the text
60 60 representation of the object; see the ``astyle`` module). If ``__xrepr__()``
61 61 recursively outputs a data structure the function ``xrepr(object, mode)`` can
62 62 be used and ``"default"`` must be passed as the mode in these calls. This in
63 63 turn calls the ``__xrepr__()`` method on ``object`` (or uses ``repr(object)``
64 64 as the string representation if ``__xrepr__()`` doesn't exist).
65 65
66 66 * Objects that can be iterated by ``Pipe``s must implement the method
67 67 ``__xiter__(self, mode)``. ``mode`` can take the following values:
68 68
69 69 - ``"default"``: This is the default value and ist always used by pipeline
70 70 expressions. Other values are only used in the browser.
71 71 - ``None``: This value is passed by the browser. The object must return an
72 72 iterable of ``XMode`` objects describing all modes supported by the object.
73 73 (This should never include ``"default"`` or ``None``).
74 74 - Any other value that the object supports.
75 75
76 76 The global function ``xiter()`` can be called to get such an iterator. If
77 77 the method ``_xiter__`` isn't implemented, ``xiter()`` falls back to
78 78 ``__iter__``. In addition to that, dictionaries and modules receive special
79 79 treatment (returning an iterator over ``(key, value)`` pairs). This makes it
80 80 possible to use dictionaries and modules in pipeline expressions, for example:
81 81
82 82 >>> import sys
83 83 >>> sys | ifilter("isinstance(value, int)") | idump
84 84 key |value
85 85 api_version| 1012
86 86 dllhandle | 503316480
87 87 hexversion | 33817328
88 88 maxint |2147483647
89 89 maxunicode | 65535
90 90 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
91 91 ...
92 92
93 93 Note: The expression strings passed to ``ifilter()`` and ``isort()`` can
94 94 refer to the object to be filtered or sorted via the variable ``_`` and to any
95 95 of the attributes of the object, i.e.:
96 96
97 97 >>> sys.modules | ifilter("_.value is not None") | isort("_.key.lower()")
98 98
99 99 does the same as
100 100
101 101 >>> sys.modules | ifilter("value is not None") | isort("key.lower()")
102 102
103 103 In addition to expression strings, it's possible to pass callables (taking
104 104 the object as an argument) to ``ifilter()``, ``isort()`` and ``ieval()``:
105 105
106 106 >>> sys | ifilter(lambda _:isinstance(_.value, int)) \
107 107 ... | ieval(lambda _: (_.key, hex(_.value))) | idump
108 108 0 |1
109 109 api_version|0x3f4
110 110 dllhandle |0x1e000000
111 111 hexversion |0x20402f0
112 112 maxint |0x7fffffff
113 113 maxunicode |0xffff
114 114 """
115 115
116 116 import sys, os, os.path, stat, glob, new, csv, datetime, types
117 117 import itertools, mimetypes
118 118
119 119 try: # Python 2.3 compatibility
120 120 import collections
121 121 except ImportError:
122 122 deque = list
123 123 else:
124 124 deque = collections.deque
125 125
126 126 try: # Python 2.3 compatibility
127 127 set
128 128 except NameError:
129 129 import sets
130 130 set = sets.Set
131 131
132 132 try: # Python 2.3 compatibility
133 133 sorted
134 134 except NameError:
135 135 def sorted(iterator, key=None, reverse=False):
136 136 items = list(iterator)
137 137 if key is not None:
138 138 items.sort(lambda i1, i2: cmp(key(i1), key(i2)))
139 139 else:
140 140 items.sort()
141 141 if reverse:
142 142 items.reverse()
143 143 return items
144 144
145 145 try:
146 146 import pwd
147 147 except ImportError:
148 148 pwd = None
149 149
150 150 try:
151 151 import grp
152 152 except ImportError:
153 153 grp = None
154 154
155 155 import path
156 156 try:
157 157 from IPython import genutils, ipapi
158 158 except ImportError:
159 159 genutils = None
160 160 ipapi = None
161 161
162 162 import astyle
163 163
164 164
165 165 __all__ = [
166 166 "ifile", "ils", "iglob", "iwalk", "ipwdentry", "ipwd", "igrpentry", "igrp",
167 167 "icsv", "ix", "ichain", "isort", "ifilter", "ieval", "ienum", "ienv",
168 168 "idump", "iless"
169 169 ]
170 170
171 171
172 172 os.stat_float_times(True) # enable microseconds
173 173
174 174
175 175 class AttrNamespace(object):
176 176 """
177 177 Helper class that is used for providing a namespace for evaluating
178 178 expressions containing attribute names of an object.
179 179 """
180 180 def __init__(self, wrapped):
181 181 self.wrapped = wrapped
182 182
183 183 def __getitem__(self, name):
184 184 if name == "_":
185 185 return self.wrapped
186 186 try:
187 187 return getattr(self.wrapped, name)
188 188 except AttributeError:
189 189 raise KeyError(name)
190 190
191 191 # Python 2.3 compatibility
192 192 # use eval workaround to find out which names are used in the
193 193 # eval string and put them into the locals. This works for most
194 194 # normal uses case, bizarre ones like accessing the locals()
195 195 # will fail
196 196 try:
197 197 eval("_", None, AttrNamespace(None))
198 198 except TypeError:
199 199 real_eval = eval
200 200 def eval(codestring, _globals, _locals):
201 201 """
202 202 eval(source[, globals[, locals]]) -> value
203 203
204 204 Evaluate the source in the context of globals and locals.
205 205 The source may be a string representing a Python expression
206 206 or a code object as returned by compile().
207 207 The globals must be a dictionary and locals can be any mappping.
208 208
209 209 This function is a workaround for the shortcomings of
210 210 Python 2.3's eval.
211 211 """
212 212
213 213 code = compile(codestring, "_eval", "eval")
214 214 newlocals = {}
215 215 for name in code.co_names:
216 216 try:
217 217 newlocals[name] = _locals[name]
218 218 except KeyError:
219 219 pass
220 220 return real_eval(code, _globals, newlocals)
221 221
222 222
223 223 noitem = object()
224 224
225 225 def item(iterator, index, default=noitem):
226 226 """
227 227 Return the ``index``th item from the iterator ``iterator``.
228 228 ``index`` must be an integer (negative integers are relative to the
229 229 end (i.e. the last item produced by the iterator)).
230 230
231 231 If ``default`` is given, this will be the default value when
232 232 the iterator doesn't contain an item at this position. Otherwise an
233 233 ``IndexError`` will be raised.
234 234
235 235 Note that using this function will partially or totally exhaust the
236 236 iterator.
237 237 """
238 238 i = index
239 239 if i>=0:
240 240 for item in iterator:
241 241 if not i:
242 242 return item
243 243 i -= 1
244 244 else:
245 245 i = -index
246 246 cache = deque()
247 247 for item in iterator:
248 248 cache.append(item)
249 249 if len(cache)>i:
250 250 cache.popleft()
251 251 if len(cache)==i:
252 252 return cache.popleft()
253 253 if default is noitem:
254 254 raise IndexError(index)
255 255 else:
256 256 return default
257 257
258 258
259 259 def getglobals(g):
260 260 if g is None:
261 261 if ipapi is not None:
262 262 return ipapi.get().user_ns()
263 263 else:
264 264 return globals()
265 265 return g
266 266
267 267
268 268 class Table(object):
269 269 """
270 270 A ``Table`` is an object that produces items (just like a normal Python
271 271 iterator/generator does) and can be used as the first object in a pipeline
272 272 expression. The displayhook will open the default browser for such an object
273 273 (instead of simply printing the ``repr()`` result).
274 274 """
275 275
276 276 # We want to support ``foo`` and ``foo()`` in pipeline expression:
277 277 # So we implement the required operators (``|`` and ``+``) in the metaclass,
278 278 # instantiate the class and forward the operator to the instance
279 279 class __metaclass__(type):
280 280 def __iter__(self):
281 281 return iter(self())
282 282
283 283 def __or__(self, other):
284 284 return self() | other
285 285
286 286 def __add__(self, other):
287 287 return self() + other
288 288
289 289 def __radd__(self, other):
290 290 return other + self()
291 291
292 292 def __getitem__(self, index):
293 293 return self()[index]
294 294
295 295 def __getitem__(self, index):
296 296 return item(self, index)
297 297
298 298 def __contains__(self, item):
299 299 for haveitem in self:
300 300 if item == haveitem:
301 301 return True
302 302 return False
303 303
304 304 def __or__(self, other):
305 305 # autoinstantiate right hand side
306 306 if isinstance(other, type) and issubclass(other, (Table, Display)):
307 307 other = other()
308 308 # treat simple strings and functions as ``ieval`` instances
309 309 elif not isinstance(other, Display) and not isinstance(other, Table):
310 310 other = ieval(other)
311 311 # forward operations to the right hand side
312 312 return other.__ror__(self)
313 313
314 314 def __add__(self, other):
315 315 # autoinstantiate right hand side
316 316 if isinstance(other, type) and issubclass(other, Table):
317 317 other = other()
318 318 return ichain(self, other)
319 319
320 320 def __radd__(self, other):
321 321 # autoinstantiate left hand side
322 322 if isinstance(other, type) and issubclass(other, Table):
323 323 other = other()
324 324 return ichain(other, self)
325 325
326 326 def __iter__(self):
327 327 return xiter(self, "default")
328 328
329 329
330 330 class Pipe(Table):
331 331 """
332 332 A ``Pipe`` is an object that can be used in a pipeline expression. It
333 333 processes the objects it gets from its input ``Table``/``Pipe``. Note that
334 334 a ``Pipe`` object can't be used as the first object in a pipeline
335 335 expression, as it doesn't produces items itself.
336 336 """
337 337 class __metaclass__(Table.__metaclass__):
338 338 def __ror__(self, input):
339 339 return input | self()
340 340
341 341 def __ror__(self, input):
342 342 # autoinstantiate left hand side
343 343 if isinstance(input, type) and issubclass(input, Table):
344 344 input = input()
345 345 self.input = input
346 346 return self
347 347
348 348
349 349 def _getattr(obj, name, default=noitem):
350 350 """
351 351 Internal helper for getting an attribute of an item. If ``name`` is ``None``
352 352 return the object itself. If ``name`` is an integer, use ``__getitem__``
353 353 instead. If the attribute or item does not exist, return ``default``.
354 354 """
355 355 if name is None:
356 356 return obj
357 357 elif isinstance(name, basestring):
358 358 if name.endswith("()"):
359 359 return getattr(obj, name[:-2], default)()
360 360 else:
361 361 return getattr(obj, name, default)
362 362 elif callable(name):
363 363 try:
364 364 return name(obj)
365 365 except AttributeError:
366 366 return default
367 367 else:
368 368 try:
369 369 return obj[name]
370 370 except IndexError:
371 371 return default
372 372
373 373
374 374 def _attrname(name):
375 375 """
376 376 Internal helper that gives a proper name for the attribute ``name``
377 377 (which might be ``None`` or an ``int``).
378 378 """
379 379 if name is None:
380 380 return "_"
381 381 elif isinstance(name, basestring):
382 382 return name
383 383 elif callable(name):
384 384 return getattr(name, "__xname__", name.__name__)
385 385 else:
386 386 return str(name)
387 387
388 388
389 389 def xrepr(item, mode):
390 390 try:
391 391 func = item.__xrepr__
392 392 except AttributeError:
393 393 pass
394 394 else:
395 395 try:
396 396 for x in func(mode):
397 397 yield x
398 398 except (KeyboardInterrupt, SystemExit):
399 399 raise
400 400 except Exception:
401 yield (-1, True)
402 401 yield (astyle.style_default, repr(item))
403 402 return
404 403 if item is None:
405 yield (-1, True)
406 404 yield (astyle.style_type_none, repr(item))
407 405 elif isinstance(item, bool):
408 yield (-1, True)
409 406 yield (astyle.style_type_bool, repr(item))
410 407 elif isinstance(item, str):
411 yield (-1, True)
412 408 if mode == "cell":
413 409 yield (astyle.style_default, repr(item.expandtabs(tab))[1:-1])
414 410 else:
415 411 yield (astyle.style_default, repr(item))
416 412 elif isinstance(item, unicode):
417 yield (-1, True)
418 413 if mode == "cell":
419 414 yield (astyle.style_default, repr(item.expandtabs(tab))[2:-1])
420 415 else:
421 416 yield (astyle.style_default, repr(item))
422 417 elif isinstance(item, (int, long, float)):
423 418 yield (1, True)
424 419 yield (astyle.style_type_number, repr(item))
425 420 elif isinstance(item, complex):
426 yield (-1, True)
427 421 yield (astyle.style_type_number, repr(item))
428 422 elif isinstance(item, datetime.datetime):
429 yield (-1, True)
430 423 if mode == "cell":
431 424 # Don't use strftime() here, as this requires year >= 1900
432 425 yield (astyle.style_type_datetime,
433 426 "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
434 427 (item.year, item.month, item.day,
435 428 item.hour, item.minute, item.second,
436 429 item.microsecond),
437 430 )
438 431 else:
439 432 yield (astyle.style_type_datetime, repr(item))
440 433 elif isinstance(item, datetime.date):
441 yield (-1, True)
442 434 if mode == "cell":
443 435 yield (astyle.style_type_datetime,
444 436 "%04d-%02d-%02d" % (item.year, item.month, item.day))
445 437 else:
446 438 yield (astyle.style_type_datetime, repr(item))
447 439 elif isinstance(item, datetime.time):
448 yield (-1, True)
449 440 if mode == "cell":
450 441 yield (astyle.style_type_datetime,
451 442 "%02d:%02d:%02d.%06d" % \
452 443 (item.hour, item.minute, item.second, item.microsecond))
453 444 else:
454 445 yield (astyle.style_type_datetime, repr(item))
455 446 elif isinstance(item, datetime.timedelta):
456 yield (-1, True)
457 447 yield (astyle.style_type_datetime, repr(item))
458 448 elif isinstance(item, Exception):
459 yield (-1, True)
460 449 if item.__class__.__module__ == "exceptions":
461 450 classname = item.__class__.__name__
462 451 else:
463 452 classname = "%s.%s" % \
464 453 (item.__class__.__module__, item.__class__.__name__)
465 454 if mode == "header" or mode == "footer":
466 455 yield (astyle.style_error, "%s: %s" % (classname, item))
467 456 else:
468 457 yield (astyle.style_error, classname)
469 458 elif isinstance(item, (list, tuple)):
470 yield (-1, False)
471 459 if mode == "header" or mode == "footer":
472 460 if item.__class__.__module__ == "__builtin__":
473 461 classname = item.__class__.__name__
474 462 else:
475 463 classname = "%s.%s" % \
476 464 (item.__class__.__module__,item.__class__.__name__)
477 465 yield (astyle.style_default,
478 466 "<%s object with %d items at 0x%x>" % \
479 467 (classname, len(item), id(item)))
480 468 else:
469 yield (-1, False)
481 470 if isinstance(item, list):
482 471 yield (astyle.style_default, "[")
483 472 end = "]"
484 473 else:
485 474 yield (astyle.style_default, "(")
486 475 end = ")"
487 476 for (i, subitem) in enumerate(item):
488 477 if i:
489 478 yield (astyle.style_default, ", ")
490 479 for part in xrepr(subitem, "default"):
491 480 yield part
492 481 yield (astyle.style_default, end)
493 482 elif isinstance(item, (dict, types.DictProxyType)):
494 yield (-1, False)
495 483 if mode == "header" or mode == "footer":
496 484 if item.__class__.__module__ == "__builtin__":
497 485 classname = item.__class__.__name__
498 486 else:
499 487 classname = "%s.%s" % \
500 488 (item.__class__.__module__,item.__class__.__name__)
501 489 yield (astyle.style_default,
502 490 "<%s object with %d items at 0x%x>" % \
503 491 (classname, len(item), id(item)))
504 492 else:
493 yield (-1, False)
505 494 if isinstance(item, dict):
506 495 yield (astyle.style_default, "{")
507 496 end = "}"
508 497 else:
509 498 yield (astyle.style_default, "dictproxy((")
510 499 end = "})"
511 500 for (i, (key, value)) in enumerate(item.iteritems()):
512 501 if i:
513 502 yield (astyle.style_default, ", ")
514 503 for part in xrepr(key, "default"):
515 504 yield part
516 505 yield (astyle.style_default, ": ")
517 506 for part in xrepr(value, "default"):
518 507 yield part
519 508 yield (astyle.style_default, end)
520 509 else:
521 yield (-1, True)
522 510 yield (astyle.style_default, repr(item))
523 511
524 512
525 513 def xattrs(item, mode):
526 514 try:
527 515 func = item.__xattrs__
528 516 except AttributeError:
529 517 if mode == "detail":
530 518 return dir(item)
531 519 else:
532 520 return (None,)
533 521 else:
534 522 try:
535 523 return func(mode)
536 524 except (KeyboardInterrupt, SystemExit):
537 525 raise
538 526 except Exception:
539 527 return (None,)
540 528
541 529
542 530 def xiter(item, mode):
543 531 if mode == "detail":
544 532 def items():
545 533 for name in xattrs(item, mode):
546 534 yield XAttr(item, name)
547 535 return items()
548 536 try:
549 537 func = item.__xiter__
550 538 except AttributeError:
551 539 if isinstance(item, (dict, types.DictProxyType)):
552 540 def items(item):
553 541 fields = ("key", "value")
554 542 for (key, value) in item.iteritems():
555 543 yield Fields(fields, key=key, value=value)
556 544 return items(item)
557 545 elif isinstance(item, new.module):
558 546 def items(item):
559 547 fields = ("key", "value")
560 548 for key in sorted(item.__dict__):
561 549 yield Fields(fields, key=key, value=getattr(item, key))
562 550 return items(item)
563 551 elif isinstance(item, basestring):
564 552 if not len(item):
565 553 raise ValueError("can't enter empty string")
566 554 lines = item.splitlines()
567 555 if len(lines) <= 1:
568 556 raise ValueError("can't enter one line string")
569 557 return iter(lines)
570 558 return iter(item)
571 559 else:
572 560 return iter(func(mode)) # iter() just to be safe
573 561
574 562
575 563 class ichain(Pipe):
576 564 """
577 565 Chains multiple ``Table``s into one.
578 566 """
579 567
580 568 def __init__(self, *iters):
581 569 self.iters = iters
582 570
583 571 def __xiter__(self, mode):
584 572 return itertools.chain(*self.iters)
585 573
586 574 def __xrepr__(self, mode):
587 yield (-1, True)
588 575 if mode == "header" or mode == "footer":
589 576 for (i, item) in enumerate(self.iters):
590 577 if i:
591 578 yield (astyle.style_default, "+")
592 579 if isinstance(item, Pipe):
593 580 yield (astyle.style_default, "(")
594 581 for part in xrepr(item, mode):
595 582 yield part
596 583 if isinstance(item, Pipe):
597 584 yield (astyle.style_default, ")")
598 585 else:
599 586 yield (astyle.style_default, repr(self))
600 587
601 588 def __repr__(self):
602 589 args = ", ".join([repr(it) for it in self.iters])
603 590 return "%s.%s(%s)" % \
604 591 (self.__class__.__module__, self.__class__.__name__, args)
605 592
606 593
607 594 class ifile(path.path):
608 595 """
609 596 file (or directory) object.
610 597 """
611 598
612 599 def __add_(self, other):
613 600 return ifile(path._base(self) + other)
614 601
615 602 def __radd_(self, other):
616 603 return ifile(other + path._base(self))
617 604
618 605 def __div_(self, other):
619 606 return ifile(path.__div__(self, other))
620 607
621 608 def getcwd():
622 609 return ifile(path.path.getcwd())
623 610 getcwd.__doc__ = path.path.getcwd.__doc__
624 611 getcwd = staticmethod(getcwd)
625 612
626 613 def abspath(self):
627 614 return ifile(path.path.abspath(self))
628 615 abspath.__doc__ = path.path.abspath.__doc__
629 616
630 617 def normcase(self):
631 618 return ifile(path.path.normcase(self))
632 619 normcase.__doc__ = path.path.normcase.__doc__
633 620
634 621 def normpath(self):
635 622 return ifile(path.path.normpath(self))
636 623 normpath.__doc__ = path.path.normpath.__doc__
637 624
638 625 def realpath(self):
639 626 return ifile(path.path.realpath(self))
640 627 realpath.__doc__ = path.path.realpath.__doc__
641 628
642 629 def expanduser(self):
643 630 return ifile(path.path.expanduser(self))
644 631 expanduser.__doc__ = path.path.expanduser.__doc__
645 632
646 633 def expandvars(self):
647 634 return ifile(path.path.expandvars(self))
648 635 expandvars.__doc__ = path.path.expandvars.__doc__
649 636
650 637 def dirname(self):
651 638 return ifile(path.path.dirname(self))
652 639 dirname.__doc__ = path.path.dirname.__doc__
653 640
654 641 parent = property(dirname, None, None, path.path.parent.__doc__)
655 642
656 643 def splitpath(self):
657 644 (parent, child) = path.path.splitpath(self)
658 645 return (ifile(parent), child)
659 646 splitpath.__doc__ = path.path.splitpath.__doc__
660 647
661 648 def splitdrive(self):
662 649 (drive, rel) = path.path.splitdrive(self)
663 650 return (ifile(drive), rel)
664 651 splitdrive.__doc__ = path.path.splitdrive.__doc__
665 652
666 653 def splitext(self):
667 654 (filename, ext) = path.path.splitext(self)
668 655 return (ifile(filename), ext)
669 656 splitext.__doc__ = path.path.splitext.__doc__
670 657
671 658 if hasattr(path.path, "splitunc"):
672 659 def splitunc(self):
673 660 (unc, rest) = path.path.splitunc(self)
674 661 return (ifile(unc), rest)
675 662 splitunc.__doc__ = path.path.splitunc.__doc__
676 663
677 664 def _get_uncshare(self):
678 665 unc, r = os.path.splitunc(self)
679 666 return ifile(unc)
680 667
681 668 uncshare = property(
682 669 _get_uncshare, None, None,
683 670 """ The UNC mount point for this path.
684 671 This is empty for paths on local drives. """)
685 672
686 673 def joinpath(self, *args):
687 674 return ifile(path.path.joinpath(self, *args))
688 675 joinpath.__doc__ = path.path.joinpath.__doc__
689 676
690 677 def splitall(self):
691 678 return map(ifile, path.path.splitall(self))
692 679 splitall.__doc__ = path.path.splitall.__doc__
693 680
694 681 def relpath(self):
695 682 return ifile(path.path.relpath(self))
696 683 relpath.__doc__ = path.path.relpath.__doc__
697 684
698 685 def relpathto(self, dest):
699 686 return ifile(path.path.relpathto(self, dest))
700 687 relpathto.__doc__ = path.path.relpathto.__doc__
701 688
702 689 def listdir(self, pattern=None):
703 690 return [ifile(child) for child in path.path.listdir(self, pattern)]
704 691 listdir.__doc__ = path.path.listdir.__doc__
705 692
706 693 def dirs(self, pattern=None):
707 694 return [ifile(child) for child in path.path.dirs(self, pattern)]
708 695 dirs.__doc__ = path.path.dirs.__doc__
709 696
710 697 def files(self, pattern=None):
711 698 return [ifile(child) for child in path.path.files(self, pattern)]
712 699 files.__doc__ = path.path.files.__doc__
713 700
714 701 def walk(self, pattern=None):
715 702 for child in path.path.walk(self, pattern):
716 703 yield ifile(child)
717 704 walk.__doc__ = path.path.walk.__doc__
718 705
719 706 def walkdirs(self, pattern=None):
720 707 for child in path.path.walkdirs(self, pattern):
721 708 yield ifile(child)
722 709 walkdirs.__doc__ = path.path.walkdirs.__doc__
723 710
724 711 def walkfiles(self, pattern=None):
725 712 for child in path.path.walkfiles(self, pattern):
726 713 yield ifile(child)
727 714 walkfiles.__doc__ = path.path.walkfiles.__doc__
728 715
729 716 def glob(self, pattern):
730 717 return map(ifile, path.path.glob(self, pattern))
731 718 glob.__doc__ = path.path.glob.__doc__
732 719
733 720 if hasattr(os, 'readlink'):
734 721 def readlink(self):
735 722 return ifile(path.path.readlink(self))
736 723 readlink.__doc__ = path.path.readlink.__doc__
737 724
738 725 def readlinkabs(self):
739 726 return ifile(path.path.readlinkabs(self))
740 727 readlinkabs.__doc__ = path.path.readlinkabs.__doc__
741 728
742 729 def getmode(self):
743 730 return self.stat().st_mode
744 731 mode = property(getmode, None, None, "Access mode")
745 732
746 733 def gettype(self):
747 734 data = [
748 735 (stat.S_ISREG, "file"),
749 736 (stat.S_ISDIR, "dir"),
750 737 (stat.S_ISCHR, "chardev"),
751 738 (stat.S_ISBLK, "blockdev"),
752 739 (stat.S_ISFIFO, "fifo"),
753 740 (stat.S_ISLNK, "symlink"),
754 741 (stat.S_ISSOCK,"socket"),
755 742 ]
756 743 lstat = self.lstat()
757 744 if lstat is not None:
758 745 types = set([text for (func, text) in data if func(lstat.st_mode)])
759 746 else:
760 747 types = set()
761 748 m = self.mode
762 749 types.update([text for (func, text) in data if func(m)])
763 750 return ", ".join(types)
764 751 type = property(gettype, None, None, "file type (file, directory, link, etc.)")
765 752
766 753 def getmodestr(self):
767 754 m = self.mode
768 755 data = [
769 756 (stat.S_IRUSR, "-r"),
770 757 (stat.S_IWUSR, "-w"),
771 758 (stat.S_IXUSR, "-x"),
772 759 (stat.S_IRGRP, "-r"),
773 760 (stat.S_IWGRP, "-w"),
774 761 (stat.S_IXGRP, "-x"),
775 762 (stat.S_IROTH, "-r"),
776 763 (stat.S_IWOTH, "-w"),
777 764 (stat.S_IXOTH, "-x"),
778 765 ]
779 766 return "".join([text[bool(m&bit)] for (bit, text) in data])
780 767
781 768 modestr = property(getmodestr, None, None, "Access mode as string")
782 769
783 770 def getblocks(self):
784 771 return self.stat().st_blocks
785 772 blocks = property(getblocks, None, None, "File size in blocks")
786 773
787 774 def getblksize(self):
788 775 return self.stat().st_blksize
789 776 blksize = property(getblksize, None, None, "Filesystem block size")
790 777
791 778 def getdev(self):
792 779 return self.stat().st_dev
793 780 dev = property(getdev)
794 781
795 782 def getnlink(self):
796 783 return self.stat().st_nlink
797 784 nlink = property(getnlink, None, None, "Number of links")
798 785
799 786 def getuid(self):
800 787 return self.stat().st_uid
801 788 uid = property(getuid, None, None, "User id of file owner")
802 789
803 790 def getgid(self):
804 791 return self.stat().st_gid
805 792 gid = property(getgid, None, None, "Group id of file owner")
806 793
807 794 def getowner(self):
808 795 stat = self.stat()
809 796 try:
810 797 return pwd.getpwuid(stat.st_uid).pw_name
811 798 except KeyError:
812 799 return stat.st_uid
813 800 owner = property(getowner, None, None, "Owner name (or id)")
814 801
815 802 def getgroup(self):
816 803 stat = self.stat()
817 804 try:
818 805 return grp.getgrgid(stat.st_gid).gr_name
819 806 except KeyError:
820 807 return stat.st_gid
821 808 group = property(getgroup, None, None, "Group name (or id)")
822 809
823 810 def getadate(self):
824 811 return datetime.datetime.utcfromtimestamp(self.atime)
825 812 adate = property(getadate, None, None, "Access date")
826 813
827 814 def getcdate(self):
828 815 return datetime.datetime.utcfromtimestamp(self.ctime)
829 816 cdate = property(getcdate, None, None, "Creation date")
830 817
831 818 def getmdate(self):
832 819 return datetime.datetime.utcfromtimestamp(self.mtime)
833 820 mdate = property(getmdate, None, None, "Modification date")
834 821
835 822 def getmimetype(self):
836 823 return mimetypes.guess_type(self.basename())[0]
837 824 mimetype = property(getmimetype, None, None, "MIME type")
838 825
839 826 def getencoding(self):
840 827 return mimetypes.guess_type(self.basename())[1]
841 828 encoding = property(getencoding, None, None, "Compression")
842 829
843 830 def __repr__(self):
844 831 return "ifile(%s)" % path._base.__repr__(self)
845 832
846 833 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
847 834
848 835 def __xattrs__(self, mode):
849 836 if mode == "detail":
850 837 return (
851 838 "name", "basename()", "abspath()", "realpath()",
852 839 "type", "mode", "modestr", "stat()", "lstat()",
853 840 "uid", "gid", "owner", "group", "dev", "nlink",
854 841 "ctime", "mtime", "atime", "cdate", "mdate", "adate",
855 842 "size", "blocks", "blksize", "isdir()", "islink()",
856 843 "mimetype", "encoding"
857 844 )
858 845 return self.defaultattrs
859 846
860 847 def __xrepr__(self, mode):
861 yield (-1, True)
862 848 try:
863 849 if self.isdir():
864 850 name = "idir"
865 851 style = astyle.style_dir
866 852 else:
867 853 name = "ifile"
868 854 style = astyle.style_file
869 855 except IOError:
870 856 name = "ifile"
871 857 style = astyle.style_default
872 858 if mode == "cell" or mode in "header" or mode == "footer":
873 859 abspath = repr(path._base(self.normpath()))
874 860 if abspath.startswith("u"):
875 861 abspath = abspath[2:-1]
876 862 else:
877 863 abspath = abspath[1:-1]
878 864 if mode == "cell":
879 865 yield (style, abspath)
880 866 else:
881 867 yield (style, "%s(%s)" % (name, abspath))
882 868 else:
883 869 yield (style, repr(self))
884 870
885 871 def __xiter__(self, mode):
886 872 if self.isdir():
887 873 yield iparentdir(self / os.pardir)
888 874 for child in sorted(self.listdir()):
889 875 yield child
890 876 else:
891 877 f = self.open("rb")
892 878 for line in f:
893 879 yield line
894 880 f.close()
895 881
896 882
897 883 class iparentdir(ifile):
898 884 def __xrepr__(self, mode):
899 yield (-1, True)
900 885 if mode == "cell":
901 886 yield (astyle.style_dir, os.pardir)
902 887 else:
903 888 for part in ifile.__xrepr__(self, mode):
904 889 yield part
905 890
906 891
907 892 class ils(Table):
908 893 """
909 894 List the current (or a specific) directory.
910 895
911 896 Examples:
912 897
913 898 >>> ils
914 899 >>> ils("/usr/local/lib/python2.4")
915 900 >>> ils("~")
916 901 """
917 902 def __init__(self, base=os.curdir):
918 903 self.base = os.path.expanduser(base)
919 904
920 905 def __xiter__(self, mode):
921 906 return xiter(ifile(self.base), mode)
922 907
923 908 def __xrepr__(self, mode):
924 909 return ifile(self.base).__xrepr__(mode)
925 910
926 911 def __repr__(self):
927 912 return "%s.%s(%r)" % \
928 913 (self.__class__.__module__, self.__class__.__name__, self.base)
929 914
930 915
931 916 class iglob(Table):
932 917 """
933 918 List all files and directories matching a specified pattern.
934 919 (See ``glob.glob()`` for more info.).
935 920
936 921 Examples:
937 922
938 923 >>> iglob("*.py")
939 924 """
940 925 def __init__(self, glob):
941 926 self.glob = glob
942 927
943 928 def __xiter__(self, mode):
944 929 for name in glob.glob(self.glob):
945 930 yield ifile(name)
946 931
947 932 def __xrepr__(self, mode):
948 yield (-1, True)
949 933 if mode == "header" or mode == "footer" or mode == "cell":
950 934 yield (astyle.style_default,
951 935 "%s(%r)" % (self.__class__.__name__, self.glob))
952 936 else:
953 937 yield (astyle.style_default, repr(self))
954 938
955 939 def __repr__(self):
956 940 return "%s.%s(%r)" % \
957 941 (self.__class__.__module__, self.__class__.__name__, self.glob)
958 942
959 943
960 944 class iwalk(Table):
961 945 """
962 946 List all files and directories in a directory and it's subdirectory.
963 947
964 948 >>> iwalk
965 949 >>> iwalk("/usr/local/lib/python2.4")
966 950 >>> iwalk("~")
967 951 """
968 952 def __init__(self, base=os.curdir, dirs=True, files=True):
969 953 self.base = os.path.expanduser(base)
970 954 self.dirs = dirs
971 955 self.files = files
972 956
973 957 def __xiter__(self, mode):
974 958 for (dirpath, dirnames, filenames) in os.walk(self.base):
975 959 if self.dirs:
976 960 for name in sorted(dirnames):
977 961 yield ifile(os.path.join(dirpath, name))
978 962 if self.files:
979 963 for name in sorted(filenames):
980 964 yield ifile(os.path.join(dirpath, name))
981 965
982 966 def __xrepr__(self, mode):
983 yield (-1, True)
984 967 if mode == "header" or mode == "footer" or mode == "cell":
985 968 yield (astyle.style_default,
986 969 "%s(%r)" % (self.__class__.__name__, self.base))
987 970 else:
988 971 yield (astyle.style_default, repr(self))
989 972
990 973 def __repr__(self):
991 974 return "%s.%s(%r)" % \
992 975 (self.__class__.__module__, self.__class__.__name__, self.base)
993 976
994 977
995 978 class ipwdentry(object):
996 979 """
997 980 ``ipwdentry`` objects encapsulate entries in the Unix user account and
998 981 password database.
999 982 """
1000 983 def __init__(self, id):
1001 984 self._id = id
1002 985 self._entry = None
1003 986
1004 987 def _getentry(self):
1005 988 if self._entry is None:
1006 989 if isinstance(self._id, basestring):
1007 990 self._entry = pwd.getpwnam(self._id)
1008 991 else:
1009 992 self._entry = pwd.getpwuid(self._id)
1010 993 return self._entry
1011 994
1012 995 def getname(self):
1013 996 if isinstance(self._id, basestring):
1014 997 return self._id
1015 998 else:
1016 999 return self._getentry().pw_name
1017 1000 name = property(getname, None, None, "User name")
1018 1001
1019 1002 def getpasswd(self):
1020 1003 return self._getentry().pw_passwd
1021 1004 passwd = property(getpasswd, None, None, "Password")
1022 1005
1023 1006 def getuid(self):
1024 1007 if isinstance(self._id, basestring):
1025 1008 return self._getentry().pw_uid
1026 1009 else:
1027 1010 return self._id
1028 1011 uid = property(getuid, None, None, "User id")
1029 1012
1030 1013 def getgid(self):
1031 1014 return self._getentry().pw_gid
1032 1015 gid = property(getgid, None, None, "Primary group id")
1033 1016
1034 1017 def getgroup(self):
1035 1018 return igrpentry(self.gid)
1036 1019 group = property(getgroup, None, None, "Group")
1037 1020
1038 1021 def getgecos(self):
1039 1022 return self._getentry().pw_gecos
1040 1023 gecos = property(getgecos, None, None, "Information (e.g. full user name)")
1041 1024
1042 1025 def getdir(self):
1043 1026 return self._getentry().pw_dir
1044 1027 dir = property(getdir, None, None, "$HOME directory")
1045 1028
1046 1029 def getshell(self):
1047 1030 return self._getentry().pw_shell
1048 1031 shell = property(getshell, None, None, "Login shell")
1049 1032
1050 1033 def __xattrs__(self, mode):
1051 1034 return ("name", "passwd", "uid", "gid", "gecos", "dir", "shell")
1052 1035
1053 1036 def __repr__(self):
1054 1037 return "%s.%s(%r)" % \
1055 1038 (self.__class__.__module__, self.__class__.__name__, self._id)
1056 1039
1057 1040
1058 1041 class ipwd(Table):
1059 1042 """
1060 1043 List all entries in the Unix user account and password database.
1061 1044
1062 1045 Example:
1063 1046
1064 1047 >>> ipwd | isort("uid")
1065 1048 """
1066 1049 def __iter__(self):
1067 1050 for entry in pwd.getpwall():
1068 1051 yield ipwdentry(entry.pw_name)
1069 1052
1070 1053 def __xrepr__(self, mode):
1071 yield (-1, True)
1072 1054 if mode == "header" or mode == "footer" or mode == "cell":
1073 1055 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1074 1056 else:
1075 1057 yield (astyle.style_default, repr(self))
1076 1058
1077 1059
1078 1060 class igrpentry(object):
1079 1061 """
1080 1062 ``igrpentry`` objects encapsulate entries in the Unix group database.
1081 1063 """
1082 1064 def __init__(self, id):
1083 1065 self._id = id
1084 1066 self._entry = None
1085 1067
1086 1068 def _getentry(self):
1087 1069 if self._entry is None:
1088 1070 if isinstance(self._id, basestring):
1089 1071 self._entry = grp.getgrnam(self._id)
1090 1072 else:
1091 1073 self._entry = grp.getgrgid(self._id)
1092 1074 return self._entry
1093 1075
1094 1076 def getname(self):
1095 1077 if isinstance(self._id, basestring):
1096 1078 return self._id
1097 1079 else:
1098 1080 return self._getentry().gr_name
1099 1081 name = property(getname, None, None, "Group name")
1100 1082
1101 1083 def getpasswd(self):
1102 1084 return self._getentry().gr_passwd
1103 1085 passwd = property(getpasswd, None, None, "Password")
1104 1086
1105 1087 def getgid(self):
1106 1088 if isinstance(self._id, basestring):
1107 1089 return self._getentry().gr_gid
1108 1090 else:
1109 1091 return self._id
1110 1092 gid = property(getgid, None, None, "Group id")
1111 1093
1112 1094 def getmem(self):
1113 1095 return self._getentry().gr_mem
1114 1096 mem = property(getmem, None, None, "Members")
1115 1097
1116 1098 def __xattrs__(self, mode):
1117 1099 return ("name", "passwd", "gid", "mem")
1118 1100
1119 1101 def __xrepr__(self, mode):
1120 yield (-1, True)
1121 1102 if mode == "header" or mode == "footer" or mode == "cell":
1122 1103 yield (astyle.style_default, "group ")
1123 1104 try:
1124 1105 yield (astyle.style_default, self.name)
1125 1106 except KeyError:
1126 1107 if isinstance(self._id, basestring):
1127 1108 yield (astyle.style_default, self.name_id)
1128 1109 else:
1129 1110 yield (astyle.style_type_number, str(self._id))
1130 1111 else:
1131 1112 yield (astyle.style_default, repr(self))
1132 1113
1133 1114 def __xiter__(self, mode):
1134 1115 for member in self.mem:
1135 1116 yield ipwdentry(member)
1136 1117
1137 1118 def __repr__(self):
1138 1119 return "%s.%s(%r)" % \
1139 1120 (self.__class__.__module__, self.__class__.__name__, self._id)
1140 1121
1141 1122
1142 1123 class igrp(Table):
1143 1124 """
1144 1125 This ``Table`` lists all entries in the Unix group database.
1145 1126 """
1146 1127 def __xiter__(self, mode):
1147 1128 for entry in grp.getgrall():
1148 1129 yield igrpentry(entry.gr_name)
1149 1130
1150 1131 def __xrepr__(self, mode):
1151 yield (-1, False)
1152 1132 if mode == "header" or mode == "footer":
1153 1133 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1154 1134 else:
1155 1135 yield (astyle.style_default, repr(self))
1156 1136
1157 1137
1158 1138 class Fields(object):
1159 1139 def __init__(self, fieldnames, **fields):
1160 1140 self.__fieldnames = fieldnames
1161 1141 for (key, value) in fields.iteritems():
1162 1142 setattr(self, key, value)
1163 1143
1164 1144 def __xattrs__(self, mode):
1165 1145 return self.__fieldnames
1166 1146
1167 1147 def __xrepr__(self, mode):
1168 1148 yield (-1, False)
1169 1149 if mode == "header" or mode == "cell":
1170 1150 yield (astyle.style_default, self.__class__.__name__)
1171 1151 yield (astyle.style_default, "(")
1172 1152 for (i, f) in enumerate(self.__fieldnames):
1173 1153 if i:
1174 1154 yield (astyle.style_default, ", ")
1175 1155 yield (astyle.style_default, f)
1176 1156 yield (astyle.style_default, "=")
1177 1157 for part in xrepr(getattr(self, f), "default"):
1178 1158 yield part
1179 1159 yield (astyle.style_default, ")")
1180 1160 elif mode == "footer":
1181 1161 yield (astyle.style_default, self.__class__.__name__)
1182 1162 yield (astyle.style_default, "(")
1183 1163 for (i, f) in enumerate(self.__fieldnames):
1184 1164 if i:
1185 1165 yield (astyle.style_default, ", ")
1186 1166 yield (astyle.style_default, f)
1187 1167 yield (astyle.style_default, ")")
1188 1168 else:
1189 1169 yield (astyle.style_default, repr(self))
1190 1170
1191 1171
1192 1172 class FieldTable(Table, list):
1193 1173 def __init__(self, *fields):
1194 1174 Table.__init__(self)
1195 1175 list.__init__(self)
1196 1176 self.fields = fields
1197 1177
1198 1178 def add(self, **fields):
1199 1179 self.append(Fields(self.fields, **fields))
1200 1180
1201 1181 def __xiter__(self, mode):
1202 1182 return list.__iter__(self)
1203 1183
1204 1184 def __xrepr__(self, mode):
1205 1185 yield (-1, False)
1206 1186 if mode == "header" or mode == "footer":
1207 1187 yield (astyle.style_default, self.__class__.__name__)
1208 1188 yield (astyle.style_default, "(")
1209 1189 for (i, f) in enumerate(self.__fieldnames):
1210 1190 if i:
1211 1191 yield (astyle.style_default, ", ")
1212 1192 yield (astyle.style_default, f)
1213 1193 yield (astyle.style_default, ")")
1214 1194 else:
1215 1195 yield (astyle.style_default, repr(self))
1216 1196
1217 1197 def __repr__(self):
1218 1198 return "<%s.%s object with fields=%r at 0x%x>" % \
1219 1199 (self.__class__.__module__, self.__class__.__name__,
1220 1200 ", ".join(map(repr, self.fields)), id(self))
1221 1201
1222 1202
1223 1203 class List(list):
1224 1204 def __xattrs__(self, mode):
1225 1205 return xrange(len(self))
1226 1206
1227 1207 def __xrepr__(self, mode):
1228 1208 yield (-1, False)
1229 1209 if mode == "header" or mode == "cell" or mode == "footer" or mode == "default":
1230 1210 yield (astyle.style_default, self.__class__.__name__)
1231 1211 yield (astyle.style_default, "(")
1232 1212 for (i, item) in enumerate(self):
1233 1213 if i:
1234 1214 yield (astyle.style_default, ", ")
1235 1215 for part in xrepr(item, "default"):
1236 1216 yield part
1237 1217 yield (astyle.style_default, ")")
1238 1218 else:
1239 1219 yield (astyle.style_default, repr(self))
1240 1220
1241 1221
1242 1222 class ienv(Table):
1243 1223 """
1244 1224 List environment variables.
1245 1225
1246 1226 Example:
1247 1227
1248 1228 >>> ienv
1249 1229 """
1250 1230
1251 1231 def __xiter__(self, mode):
1252 1232 fields = ("key", "value")
1253 1233 for (key, value) in os.environ.iteritems():
1254 1234 yield Fields(fields, key=key, value=value)
1255 1235
1256 1236 def __xrepr__(self, mode):
1257 yield (-1, True)
1258 1237 if mode == "header" or mode == "cell":
1259 1238 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1260 1239 else:
1261 1240 yield (astyle.style_default, repr(self))
1262 1241
1263 1242
1264 1243 class icsv(Pipe):
1265 1244 """
1266 1245 This ``Pipe`` lists turn the input (with must be a pipe outputting lines
1267 1246 or an ``ifile``) into lines of CVS columns.
1268 1247 """
1269 1248 def __init__(self, **csvargs):
1270 1249 """
1271 1250 Create an ``icsv`` object. ``cvsargs`` will be passed through as
1272 1251 keyword arguments to ``cvs.reader()``.
1273 1252 """
1274 1253 self.csvargs = csvargs
1275 1254
1276 1255 def __xiter__(self, mode):
1277 1256 input = self.input
1278 1257 if isinstance(input, ifile):
1279 1258 input = input.open("rb")
1280 1259 reader = csv.reader(input, **self.csvargs)
1281 1260 for line in reader:
1282 1261 yield List(line)
1283 1262
1284 1263 def __xrepr__(self, mode):
1285 1264 yield (-1, False)
1286 1265 if mode == "header" or mode == "footer":
1287 1266 input = getattr(self, "input", None)
1288 1267 if input is not None:
1289 1268 for part in xrepr(input, mode):
1290 1269 yield part
1291 1270 yield (astyle.style_default, " | ")
1292 1271 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1293 1272 for (i, (name, value)) in enumerate(self.csvargs.iteritems()):
1294 1273 if i:
1295 1274 yield (astyle.style_default, ", ")
1296 1275 yield (astyle.style_default, name)
1297 1276 yield (astyle.style_default, "=")
1298 1277 for part in xrepr(value, "default"):
1299 1278 yield part
1300 1279 yield (astyle.style_default, ")")
1301 1280 else:
1302 1281 yield (astyle.style_default, repr(self))
1303 1282
1304 1283 def __repr__(self):
1305 1284 args = ", ".join(["%s=%r" % item for item in self.csvargs.iteritems()])
1306 1285 return "<%s.%s %s at 0x%x>" % \
1307 1286 (self.__class__.__module__, self.__class__.__name__, args, id(self))
1308 1287
1309 1288
1310 1289 class ix(Table):
1311 1290 """
1312 1291 Execute a system command and list its output as lines
1313 1292 (similar to ``os.popen()``).
1314 1293
1315 1294 Examples:
1316 1295
1317 1296 >>> ix("ps x")
1318 1297 >>> ix("find .") | ifile
1319 1298 """
1320 1299 def __init__(self, cmd):
1321 1300 self.cmd = cmd
1322 1301 self._pipe = None
1323 1302
1324 1303 def __xiter__(self, mode):
1325 1304 self._pipe = os.popen(self.cmd)
1326 1305 for l in self._pipe:
1327 1306 yield l.rstrip("\r\n")
1328 1307 self._pipe.close()
1329 1308 self._pipe = None
1330 1309
1331 1310 def __del__(self):
1332 1311 if self._pipe is not None and not self._pipe.closed:
1333 1312 self._pipe.close()
1334 1313 self._pipe = None
1335 1314
1336 1315 def __xrepr__(self, mode):
1337 yield (-1, True)
1338 1316 if mode == "header" or mode == "footer":
1339 1317 yield (astyle.style_default,
1340 1318 "%s(%r)" % (self.__class__.__name__, self.cmd))
1341 1319 else:
1342 1320 yield (astyle.style_default, repr(self))
1343 1321
1344 1322 def __repr__(self):
1345 1323 return "%s.%s(%r)" % \
1346 1324 (self.__class__.__module__, self.__class__.__name__, self.cmd)
1347 1325
1348 1326
1349 1327 class ifilter(Pipe):
1350 1328 """
1351 1329 Filter an input pipe. Only objects where an expression evaluates to true
1352 1330 (and doesn't raise an exception) are listed.
1353 1331
1354 1332 Examples:
1355 1333
1356 1334 >>> ils | ifilter("_.isfile() and size>1000")
1357 1335 >>> igrp | ifilter("len(mem)")
1358 1336 >>> sys.modules | ifilter(lambda _:_.value is not None)
1359 1337 """
1360 1338
1361 1339 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1362 1340 """
1363 1341 Create an ``ifilter`` object. ``expr`` can be a callable or a string
1364 1342 containing an expression. ``globals`` will be used as the global
1365 1343 namespace for calling string expressions (defaulting to IPython's
1366 1344 user namespace). ``errors`` specifies how exception during evaluation
1367 1345 of ``expr`` are handled:
1368 1346
1369 1347 * ``drop``: drop all items that have errors;
1370 1348
1371 1349 * ``keep``: keep all items that have errors;
1372 1350
1373 1351 * ``keeperror``: keep the exception of all items that have errors;
1374 1352
1375 1353 * ``raise``: raise the exception;
1376 1354
1377 1355 * ``raiseifallfail``: raise the first exception if all items have errors;
1378 1356 otherwise drop those with errors (this is the default).
1379 1357 """
1380 1358 self.expr = expr
1381 1359 self.globals = globals
1382 1360 self.errors = errors
1383 1361
1384 1362 def __xiter__(self, mode):
1385 1363 if callable(self.expr):
1386 1364 def test(item):
1387 1365 return self.expr(item)
1388 1366 else:
1389 1367 g = getglobals(self.globals)
1390 1368 def test(item):
1391 1369 return eval(self.expr, g, AttrNamespace(item))
1392 1370
1393 1371 ok = 0
1394 1372 exc_info = None
1395 1373 for item in xiter(self.input, mode):
1396 1374 try:
1397 1375 if test(item):
1398 1376 yield item
1399 1377 ok += 1
1400 1378 except (KeyboardInterrupt, SystemExit):
1401 1379 raise
1402 1380 except Exception, exc:
1403 1381 if self.errors == "drop":
1404 1382 pass # Ignore errors
1405 1383 elif self.errors == "keep":
1406 1384 yield item
1407 1385 elif self.errors == "keeperror":
1408 1386 yield exc
1409 1387 elif self.errors == "raise":
1410 1388 raise
1411 1389 elif self.errors == "raiseifallfail":
1412 1390 if exc_info is None:
1413 1391 exc_info = sys.exc_info()
1414 1392 if not ok and exc_info is not None:
1415 1393 raise exc_info[0], exc_info[1], exc_info[2]
1416 1394
1417 1395 def __xrepr__(self, mode):
1418 yield (-1, True)
1419 1396 if mode == "header" or mode == "footer":
1420 1397 input = getattr(self, "input", None)
1421 1398 if input is not None:
1422 1399 for part in xrepr(input, mode):
1423 1400 yield part
1424 1401 yield (astyle.style_default, " | ")
1425 1402 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1426 1403 for part in xrepr(self.expr, "default"):
1427 1404 yield part
1428 1405 yield (astyle.style_default, ")")
1429 1406 else:
1430 1407 yield (astyle.style_default, repr(self))
1431 1408
1432 1409 def __repr__(self):
1433 1410 return "<%s.%s expr=%r at 0x%x>" % \
1434 1411 (self.__class__.__module__, self.__class__.__name__,
1435 1412 self.expr, id(self))
1436 1413
1437 1414
1438 1415 class ieval(Pipe):
1439 1416 """
1440 1417 Evaluate an expression for each object in the input pipe.
1441 1418
1442 1419 Examples:
1443 1420
1444 1421 >>> ils | ieval("_.abspath()")
1445 1422 >>> sys.path | ieval(ifile)
1446 1423 """
1447 1424
1448 1425 def __init__(self, expr, globals=None, errors="raiseifallfail"):
1449 1426 """
1450 1427 Create an ``ieval`` object. ``expr`` can be a callable or a string
1451 1428 containing an expression. For the meaning of ``globals`` and
1452 1429 ``errors`` see ``ifilter``.
1453 1430 """
1454 1431 self.expr = expr
1455 1432 self.globals = globals
1456 1433 self.errors = errors
1457 1434
1458 1435 def __xiter__(self, mode):
1459 1436 if callable(self.expr):
1460 1437 def do(item):
1461 1438 return self.expr(item)
1462 1439 else:
1463 1440 g = getglobals(self.globals)
1464 1441 def do(item):
1465 1442 return eval(self.expr, g, AttrNamespace(item))
1466 1443
1467 1444 ok = 0
1468 1445 exc_info = None
1469 1446 for item in xiter(self.input, mode):
1470 1447 try:
1471 1448 yield do(item)
1472 1449 except (KeyboardInterrupt, SystemExit):
1473 1450 raise
1474 1451 except Exception, exc:
1475 1452 if self.errors == "drop":
1476 1453 pass # Ignore errors
1477 1454 elif self.errors == "keep":
1478 1455 yield item
1479 1456 elif self.errors == "keeperror":
1480 1457 yield exc
1481 1458 elif self.errors == "raise":
1482 1459 raise
1483 1460 elif self.errors == "raiseifallfail":
1484 1461 if exc_info is None:
1485 1462 exc_info = sys.exc_info()
1486 1463 if not ok and exc_info is not None:
1487 1464 raise exc_info[0], exc_info[1], exc_info[2]
1488 1465
1489 1466 def __xrepr__(self, mode):
1490 yield (-1, True)
1491 1467 if mode == "header" or mode == "footer":
1492 1468 input = getattr(self, "input", None)
1493 1469 if input is not None:
1494 1470 for part in xrepr(input, mode):
1495 1471 yield part
1496 1472 yield (astyle.style_default, " | ")
1497 1473 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1498 1474 for part in xrepr(self.expr, "default"):
1499 1475 yield part
1500 1476 yield (astyle.style_default, ")")
1501 1477 else:
1502 1478 yield (astyle.style_default, repr(self))
1503 1479
1504 1480 def __repr__(self):
1505 1481 return "<%s.%s expr=%r at 0x%x>" % \
1506 1482 (self.__class__.__module__, self.__class__.__name__,
1507 1483 self.expr, id(self))
1508 1484
1509 1485
1510 1486 class ienum(Pipe):
1511 1487 """
1512 1488 Enumerate the input pipe (i.e. wrap each input object in an object
1513 1489 with ``index`` and ``object`` attributes).
1514 1490
1515 1491 Examples:
1516 1492
1517 1493 >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object")
1518 1494 """
1519 1495 def __xiter__(self, mode):
1520 1496 fields = ("index", "object")
1521 1497 for (index, object) in enumerate(xiter(self.input, mode)):
1522 1498 yield Fields(fields, index=index, object=object)
1523 1499
1524 1500
1525 1501 class isort(Pipe):
1526 1502 """
1527 1503 Sorts the input pipe.
1528 1504
1529 1505 Examples:
1530 1506
1531 1507 >>> ils | isort("size")
1532 1508 >>> ils | isort("_.isdir(), _.lower()", reverse=True)
1533 1509 """
1534 1510
1535 1511 def __init__(self, key, globals=None, reverse=False):
1536 1512 """
1537 1513 Create an ``isort`` object. ``key`` can be a callable or a string
1538 1514 containing an expression. If ``reverse`` is true the sort order will
1539 1515 be reversed. For the meaning of ``globals`` see ``ifilter``.
1540 1516 """
1541 1517 self.key = key
1542 1518 self.globals = globals
1543 1519 self.reverse = reverse
1544 1520
1545 1521 def __xiter__(self, mode):
1546 1522 if callable(self.key):
1547 1523 items = sorted(
1548 1524 xiter(self.input, mode),
1549 1525 key=self.key,
1550 1526 reverse=self.reverse
1551 1527 )
1552 1528 else:
1553 1529 g = getglobals(self.globals)
1554 1530 def key(item):
1555 1531 return eval(self.key, g, AttrNamespace(item))
1556 1532 items = sorted(
1557 1533 xiter(self.input, mode),
1558 1534 key=key,
1559 1535 reverse=self.reverse
1560 1536 )
1561 1537 for item in items:
1562 1538 yield item
1563 1539
1564 1540 def __xrepr__(self, mode):
1565 yield (-1, True)
1566 1541 if mode == "header" or mode == "footer":
1567 1542 input = getattr(self, "input", None)
1568 1543 if input is not None:
1569 1544 for part in xrepr(input, mode):
1570 1545 yield part
1571 1546 yield (astyle.style_default, " | ")
1572 1547 yield (astyle.style_default, "%s(" % self.__class__.__name__)
1573 1548 for part in xrepr(self.key, "default"):
1574 1549 yield part
1575 1550 if self.reverse:
1576 1551 yield (astyle.style_default, ", ")
1577 1552 for part in xrepr(True, "default"):
1578 1553 yield part
1579 1554 yield (astyle.style_default, ")")
1580 1555 else:
1581 1556 yield (astyle.style_default, repr(self))
1582 1557
1583 1558 def __repr__(self):
1584 1559 return "<%s.%s key=%r reverse=%r at 0x%x>" % \
1585 1560 (self.__class__.__module__, self.__class__.__name__,
1586 1561 self.key, self.reverse, id(self))
1587 1562
1588 1563
1589 1564 tab = 3 # for expandtabs()
1590 1565
1591 1566 def _format(field):
1592 1567 if isinstance(field, str):
1593 1568 text = repr(field.expandtabs(tab))[1:-1]
1594 1569 elif isinstance(field, unicode):
1595 1570 text = repr(field.expandtabs(tab))[2:-1]
1596 1571 elif isinstance(field, datetime.datetime):
1597 1572 # Don't use strftime() here, as this requires year >= 1900
1598 1573 text = "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
1599 1574 (field.year, field.month, field.day,
1600 1575 field.hour, field.minute, field.second, field.microsecond)
1601 1576 elif isinstance(field, datetime.date):
1602 1577 text = "%04d-%02d-%02d" % (field.year, field.month, field.day)
1603 1578 else:
1604 1579 text = repr(field)
1605 1580 return text
1606 1581
1607 1582
1608 1583 class Display(object):
1609 1584 class __metaclass__(type):
1610 1585 def __ror__(self, input):
1611 1586 return input | self()
1612 1587
1613 1588 def __ror__(self, input):
1614 1589 self.input = input
1615 1590 return self
1616 1591
1617 1592 def display(self):
1618 1593 pass
1619 1594
1620 1595
1621 1596 class iless(Display):
1622 1597 cmd = "less --quit-if-one-screen --LONG-PROMPT --LINE-NUMBERS --chop-long-lines --shift=8 --RAW-CONTROL-CHARS"
1623 1598
1624 1599 def display(self):
1625 1600 try:
1626 1601 pager = os.popen(self.cmd, "w")
1627 1602 try:
1628 1603 for item in xiter(self.input, "default"):
1629 1604 attrs = xattrs(item, "default")
1630 1605 attrs = ["%s=%s" % (a, _format(_getattr(item, a))) for a in attrs]
1631 1606 pager.write(" ".join(attrs))
1632 1607 pager.write("\n")
1633 1608 finally:
1634 1609 pager.close()
1635 1610 except Exception, exc:
1636 1611 print "%s: %s" % (exc.__class__.__name__, str(exc))
1637 1612
1638 1613
1639 1614 def xformat(value, mode, maxlength):
1640 1615 align = None
1641 full = False
1616 full = True
1642 1617 width = 0
1643 1618 text = astyle.Text()
1644 1619 for part in xrepr(value, mode):
1645 1620 # part is (alignment, stop)
1646 1621 if isinstance(part[0], int):
1647 1622 # only consider the first occurence
1648 1623 if align is None:
1649 1624 align = part[0]
1650 1625 full = part[1]
1651 1626 # part is (style, text)
1652 1627 else:
1653 1628 text.append(part)
1654 1629 width += len(part[1])
1655 1630 if width >= maxlength and not full:
1656 1631 text.append((astyle.style_ellisis, "..."))
1657 1632 width += 3
1658 1633 break
1659 1634 if align is None: # default to left alignment
1660 1635 align = -1
1661 1636 return (align, width, text)
1662 1637
1663 1638
1664 1639 class idump(Display):
1665 1640 # The approximate maximum length of a column entry
1666 1641 maxattrlength = 200
1667 1642
1668 1643 # Style for column names
1669 1644 style_header = astyle.Style.fromstr("white:black:bold")
1670 1645
1671 1646 def __init__(self, *attrs):
1672 1647 self.attrs = attrs
1673 1648 self.headerpadchar = " "
1674 1649 self.headersepchar = "|"
1675 1650 self.datapadchar = " "
1676 1651 self.datasepchar = "|"
1677 1652
1678 1653 def display(self):
1679 1654 stream = genutils.Term.cout
1680 1655 allattrs = []
1681 1656 allattrset = set()
1682 1657 colwidths = {}
1683 1658 rows = []
1684 1659 for item in xiter(self.input, "default"):
1685 1660 row = {}
1686 1661 attrs = self.attrs
1687 1662 if not attrs:
1688 1663 attrs = xattrs(item, "default")
1689 1664 for attrname in attrs:
1690 1665 if attrname not in allattrset:
1691 1666 allattrs.append(attrname)
1692 1667 allattrset.add(attrname)
1693 1668 colwidths[attrname] = len(_attrname(attrname))
1694 1669 try:
1695 1670 value = _getattr(item, attrname, None)
1696 1671 except (KeyboardInterrupt, SystemExit):
1697 1672 raise
1698 1673 except Exception, exc:
1699 1674 value = exc
1700 1675 (align, width, text) = xformat(value, "cell", self.maxattrlength)
1701 1676 colwidths[attrname] = max(colwidths[attrname], width)
1702 1677 # remember alignment, length and colored parts
1703 1678 row[attrname] = (align, width, text)
1704 1679 rows.append(row)
1705 1680
1706 1681 stream.write("\n")
1707 1682 for (i, attrname) in enumerate(allattrs):
1708 1683 self.style_header(_attrname(attrname)).write(stream)
1709 1684 spc = colwidths[attrname] - len(_attrname(attrname))
1710 1685 if i < len(colwidths)-1:
1711 1686 stream.write(self.headerpadchar*spc)
1712 1687 stream.write(self.headersepchar)
1713 1688 stream.write("\n")
1714 1689
1715 1690 for row in rows:
1716 1691 for (i, attrname) in enumerate(allattrs):
1717 1692 (align, width, text) = row[attrname]
1718 1693 spc = colwidths[attrname] - width
1719 1694 if align == -1:
1720 1695 text.write(stream)
1721 1696 if i < len(colwidths)-1:
1722 1697 stream.write(self.datapadchar*spc)
1723 1698 elif align == 0:
1724 1699 spc = colwidths[attrname] - width
1725 1700 spc1 = spc//2
1726 1701 spc2 = spc-spc1
1727 1702 stream.write(self.datapadchar*spc1)
1728 1703 text.write(stream)
1729 1704 if i < len(colwidths)-1:
1730 1705 stream.write(self.datapadchar*spc2)
1731 1706 else:
1732 1707 stream.write(self.datapadchar*spc)
1733 1708 text.write(stream)
1734 1709 if i < len(colwidths)-1:
1735 1710 stream.write(self.datasepchar)
1736 1711 stream.write("\n")
1737 1712
1738 1713
1739 1714 class XMode(object):
1740 1715 """
1741 1716 An ``XMode`` object describes one enter mode available for an object
1742 1717 """
1743 1718 def __init__(self, object, mode, title=None, description=None):
1744 1719 """
1745 1720 Create a new ``XMode`` object for the object ``object``. This object
1746 1721 must support the enter mode ``mode`` (i.e. ``object.__xiter__(mode)``
1747 1722 must return an iterable). ``title`` and ``description`` will be
1748 1723 displayed in the browser when selecting among the available modes.
1749 1724 """
1750 1725 self.object = object
1751 1726 self.mode = mode
1752 1727 self.title = title
1753 1728 self.description = description
1754 1729
1755 1730 def __repr__(self):
1756 1731 return "<%s.%s object mode=%r at 0x%x>" % \
1757 1732 (self.__class__.__module__, self.__class__.__name__,
1758 1733 self.mode, id(self))
1759 1734
1760 1735 def __xrepr__(self, mode):
1761 yield (-1, True)
1762 1736 if mode == "header" or mode == "footer":
1763 1737 yield (astyle.style_default, self.title)
1764 1738 else:
1765 1739 yield (astyle.style_default, repr(self))
1766 1740
1767 1741 def __xattrs__(self, mode):
1768 1742 if mode == "detail":
1769 1743 return ("object", "mode", "title", "description")
1770 1744 return ("title", "description")
1771 1745
1772 1746 def __xiter__(self, mode):
1773 1747 return xiter(self.object, self.mode)
1774 1748
1775 1749
1776 1750 class XAttr(object):
1777 1751 def __init__(self, object, name):
1778 1752 self.name = _attrname(name)
1779 1753
1780 1754 try:
1781 1755 self.value = _getattr(object, name)
1782 1756 except (KeyboardInterrupt, SystemExit):
1783 1757 raise
1784 1758 except Exception, exc:
1785 1759 if exc.__class__.__module__ == "exceptions":
1786 1760 self.value = exc.__class__.__name__
1787 1761 else:
1788 1762 self.value = "%s.%s" % \
1789 1763 (exc.__class__.__module__, exc.__class__.__name__)
1790 1764 self.type = self.value
1791 1765 else:
1792 1766 t = type(self.value)
1793 1767 if t.__module__ == "__builtin__":
1794 1768 self.type = t.__name__
1795 1769 else:
1796 1770 self.type = "%s.%s" % (t.__module__, t.__name__)
1797 1771
1798 1772 doc = None
1799 1773 if isinstance(name, basestring):
1800 1774 if name.endswith("()"):
1801 1775 doc = getattr(getattr(object, name[:-2]), "__doc__", None)
1802 1776 else:
1803 1777 try:
1804 1778 meta = getattr(type(object), name)
1805 1779 except AttributeError:
1806 1780 pass
1807 1781 else:
1808 1782 if isinstance(meta, property):
1809 1783 doc = getattr(meta, "__doc__", None)
1810 1784 elif callable(name):
1811 1785 doc = getattr(name, "__doc__", None)
1812 1786 if isinstance(doc, basestring):
1813 1787 doc = doc.strip()
1814 1788 self.doc = doc
1815 1789
1816 1790 def __xattrs__(self, mode):
1817 1791 return ("name", "type", "doc", "value")
1818 1792
1819 1793
1820 1794 try:
1821 1795 from ibrowse import ibrowse
1822 1796 except ImportError:
1823 1797 # No curses (probably Windows) => use ``idump`` as the default display.
1824 1798 defaultdisplay = idump
1825 1799 else:
1826 1800 defaultdisplay = ibrowse
1827 1801 __all__.append("ibrowse")
1828 1802
1829 1803
1830 1804 # If we're running under IPython, install an IPython displayhook that
1831 1805 # returns the object from Display.display(), else install a displayhook
1832 1806 # directly as sys.displayhook
1833 1807 api = None
1834 1808 if ipapi is not None:
1835 1809 try:
1836 1810 api = ipapi.get()
1837 1811 except AttributeError:
1838 1812 pass
1839 1813
1840 1814 if api is not None:
1841 1815 def displayhook(self, obj):
1842 1816 if isinstance(obj, type) and issubclass(obj, Table):
1843 1817 obj = obj()
1844 1818 if isinstance(obj, Table):
1845 1819 obj = obj | defaultdisplay
1846 1820 if isinstance(obj, Display):
1847 1821 return obj.display()
1848 1822 else:
1849 1823 raise ipapi.TryNext
1850 1824 api.set_hook("result_display", displayhook)
1851 1825 else:
1852 1826 def installdisplayhook():
1853 1827 _originalhook = sys.displayhook
1854 1828 def displayhook(obj):
1855 1829 if isinstance(obj, type) and issubclass(obj, Table):
1856 1830 obj = obj()
1857 1831 if isinstance(obj, Table):
1858 1832 obj = obj | defaultdisplay
1859 1833 if isinstance(obj, Display):
1860 1834 return obj.display()
1861 1835 else:
1862 1836 _originalhook(obj)
1863 1837 sys.displayhook = displayhook
1864 1838 installdisplayhook()
General Comments 0
You need to be logged in to leave comments. Login now