##// END OF EJS Templates
Use os.popen4() so that the error output of the running...
walter.doerwald -
Show More

The requested changes are too big and content was truncated. Show full diff

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