##// END OF EJS Templates
IPython/Extensions/ipipe.py: xrepr(), xiter() and xattrs() are now...
walter.doerwald -
Show More
@@ -0,0 +1,5 b''
1 """
2 This package contains all third-party modules bundled with IPython.
3 """
4
5 __all__ = ["simplegeneric"]
@@ -0,0 +1,130 b''
1 __all__ = ["generic"]
2
3 from types import ClassType, InstanceType
4 classtypes = type, ClassType
5
6 # This is version 0.6 of Philip J. Eby's simplegeneric module
7 # (http://cheeseshop.python.org/pypi/simplegeneric) patched to work
8 # with Python 2.3 (which doesn't support assigning to __name__)
9
10 def generic(func):
11 """Create a simple generic function"""
12
13 _sentinel = object()
14
15 def _by_class(*args, **kw):
16 cls = args[0].__class__
17 for t in type(cls.__name__, (cls,object), {}).__mro__:
18 f = _gbt(t, _sentinel)
19 if f is not _sentinel:
20 return f(*args, **kw)
21 else:
22 return func(*args, **kw)
23
24 _by_type = {object: func, InstanceType: _by_class}
25 _gbt = _by_type.get
26
27 def when_type(t):
28 """Decorator to add a method that will be called for type `t`"""
29 if not isinstance(t, classtypes):
30 raise TypeError(
31 "%r is not a type or class" % (t,)
32 )
33 def decorate(f):
34 if _by_type.setdefault(t,f) is not f:
35 raise TypeError(
36 "%r already has method for type %r" % (func, t)
37 )
38 return f
39 return decorate
40
41
42
43
44
45
46 _by_object = {}
47 _gbo = _by_object.get
48
49 def when_object(o):
50 """Decorator to add a method that will be called for object `o`"""
51 def decorate(f):
52 if _by_object.setdefault(id(o), (o,f))[1] is not f:
53 raise TypeError(
54 "%r already has method for object %r" % (func, o)
55 )
56 return f
57 return decorate
58
59
60 def dispatch(*args, **kw):
61 f = _gbo(id(args[0]), _sentinel)
62 if f is _sentinel:
63 for t in type(args[0]).__mro__:
64 f = _gbt(t, _sentinel)
65 if f is not _sentinel:
66 return f(*args, **kw)
67 else:
68 return func(*args, **kw)
69 else:
70 return f[1](*args, **kw)
71
72 try:
73 dispatch.__name__ = func.__name__
74 except TypeError:
75 pass
76 dispatch.__dict__ = func.__dict__.copy()
77 dispatch.__doc__ = func.__doc__
78 dispatch.__module__ = func.__module__
79
80 dispatch.when_type = when_type
81 dispatch.when_object = when_object
82 dispatch.default = func
83 dispatch.has_object = lambda o: id(o) in _by_object
84 dispatch.has_type = lambda t: t in _by_type
85 return dispatch
86
87
88
89
90 def test_suite():
91 import doctest
92 return doctest.DocFileSuite(
93 'README.txt',
94 optionflags=doctest.ELLIPSIS|doctest.REPORT_ONLY_FIRST_FAILURE,
95 )
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
@@ -12,6 +12,12 b' except NameError:'
12 import sets
12 import sets
13 set = sets.Set
13 set = sets.Set
14
14
15 # Python 2.3 compatibility
16 try:
17 sorted
18 except NameError:
19 from ipipe import sorted
20
15
21
16 class UnassignedKeyError(Exception):
22 class UnassignedKeyError(Exception):
17 """
23 """
@@ -21,7 +27,7 b' class UnassignedKeyError(Exception):'
21
27
22 class UnknownCommandError(Exception):
28 class UnknownCommandError(Exception):
23 """
29 """
24 Exception that is used for reporting unknown command (this should never
30 Exception that is used for reporting unknown commands (this should never
25 happen).
31 happen).
26 """
32 """
27
33
@@ -733,14 +739,13 b' class ibrowse(ipipe.Display):'
733 keymap.register("pickallattrs", "C")
739 keymap.register("pickallattrs", "C")
734 keymap.register("pickmarked", "m")
740 keymap.register("pickmarked", "m")
735 keymap.register("pickmarkedattr", "M")
741 keymap.register("pickmarkedattr", "M")
736 keymap.register("enterdefault", "\r\n")
737 # FIXME: What's happening here?
738 keymap.register("leave", curses.KEY_BACKSPACE, "x\x08\x7f")
739 keymap.register("hideattr", "h")
742 keymap.register("hideattr", "h")
740 keymap.register("unhideattrs", "H")
743 keymap.register("unhideattrs", "H")
741 keymap.register("help", "?")
744 keymap.register("help", "?")
742 keymap.register("enter", "e")
745 keymap.register("enter", "eenterdefault", "\r\n")
743 keymap.register("enterattr", "E")
746 keymap.register("enterattr", "E")
747 # FIXME: What's happening here?
748 keymap.register("leave", curses.KEY_BACKSPACE, "x\x08\x7f")
744 keymap.register("detail", "d")
749 keymap.register("detail", "d")
745 keymap.register("detailattr", "D")
750 keymap.register("detailattr", "D")
746 keymap.register("tooglemark", " ")
751 keymap.register("tooglemark", " ")
@@ -879,13 +884,13 b' class ibrowse(ipipe.Display):'
879 """
884 """
880 self._report = msg
885 self._report = msg
881
886
882 def enter(self, item, mode, *attrs):
887 def enter(self, item, *attrs):
883 """
888 """
884 Enter the object ``item`` in the mode ``mode``. If ``attrs`` is
889 Enter the object ``item``. If ``attrs`` is specified, it will be used
885 specified, it will be used as a fixed list of attributes to display.
890 as a fixed list of attributes to display.
886 """
891 """
887 try:
892 try:
888 iterator = ipipe.xiter(item, mode)
893 iterator = ipipe.xiter(item)
889 except (KeyboardInterrupt, SystemExit):
894 except (KeyboardInterrupt, SystemExit):
890 raise
895 raise
891 except Exception, exc:
896 except Exception, exc:
@@ -1135,11 +1140,10 b' class ibrowse(ipipe.Display):'
1135 cache.marked = True
1140 cache.marked = True
1136 level.marked += 1
1141 level.marked += 1
1137
1142
1138 def cmd_enterdefault(self):
1143 def cmd_enter(self):
1139 """
1144 """
1140 Enter the object under the cursor. (what this mean depends on the object
1145 Enter the object under the cursor. (what this mean depends on the object
1141 itself (i.e. how it implements the ``__xiter__`` method). This opens a new
1146 itself (i.e. how it implements iteration). This opens a new browser 'level'.
1142 browser 'level'.
1143 """
1147 """
1144 level = self.levels[-1]
1148 level = self.levels[-1]
1145 try:
1149 try:
@@ -1148,8 +1152,8 b' class ibrowse(ipipe.Display):'
1148 self.report(CommandError("No object"))
1152 self.report(CommandError("No object"))
1149 curses.beep()
1153 curses.beep()
1150 else:
1154 else:
1151 self.report("entering object (default mode)...")
1155 self.report("entering object...")
1152 self.enter(item, "default")
1156 self.enter(item)
1153
1157
1154 def cmd_leave(self):
1158 def cmd_leave(self):
1155 """
1159 """
@@ -1163,22 +1167,6 b' class ibrowse(ipipe.Display):'
1163 self.report(CommandError("This is the last level"))
1167 self.report(CommandError("This is the last level"))
1164 curses.beep()
1168 curses.beep()
1165
1169
1166 def cmd_enter(self):
1167 """
1168 Enter the object under the cursor. If the object provides different
1169 enter modes a menu of all modes will be presented; choose one and enter
1170 it (via the 'enter' or 'enterdefault' command).
1171 """
1172 level = self.levels[-1]
1173 try:
1174 item = level.items[level.cury].item
1175 except IndexError:
1176 self.report(CommandError("No object"))
1177 curses.beep()
1178 else:
1179 self.report("entering object...")
1180 self.enter(item, None)
1181
1182 def cmd_enterattr(self):
1170 def cmd_enterattr(self):
1183 """
1171 """
1184 Enter the attribute under the cursor.
1172 Enter the attribute under the cursor.
@@ -1201,7 +1189,7 b' class ibrowse(ipipe.Display):'
1201 self.report(AttributeError(name))
1189 self.report(AttributeError(name))
1202 else:
1190 else:
1203 self.report("entering object attribute %s..." % name)
1191 self.report("entering object attribute %s..." % name)
1204 self.enter(value, None)
1192 self.enter(value)
1205
1193
1206 def cmd_detail(self):
1194 def cmd_detail(self):
1207 """
1195 """
@@ -1219,7 +1207,7 b' class ibrowse(ipipe.Display):'
1219 else:
1207 else:
1220 self.report("entering detail view for object...")
1208 self.report("entering detail view for object...")
1221 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
1209 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
1222 self.enter(attrs, "detail")
1210 self.enter(attrs)
1223
1211
1224 def cmd_detailattr(self):
1212 def cmd_detailattr(self):
1225 """
1213 """
@@ -1246,7 +1234,7 b' class ibrowse(ipipe.Display):'
1246 else:
1234 else:
1247 self.report("entering detail view for attribute %s..." % attr.name())
1235 self.report("entering detail view for attribute %s..." % attr.name())
1248 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
1236 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
1249 self.enter(attrs, "detail")
1237 self.enter(attrs)
1250
1238
1251 def cmd_tooglemark(self):
1239 def cmd_tooglemark(self):
1252 """
1240 """
@@ -1362,7 +1350,7 b' class ibrowse(ipipe.Display):'
1362 self.report(CommandError("help already active"))
1350 self.report(CommandError("help already active"))
1363 return
1351 return
1364
1352
1365 self.enter(_BrowserHelp(self), "default")
1353 self.enter(_BrowserHelp(self))
1366
1354
1367 def cmd_quit(self):
1355 def cmd_quit(self):
1368 """
1356 """
@@ -1400,7 +1388,7 b' class ibrowse(ipipe.Display):'
1400
1388
1401 self.levels = []
1389 self.levels = []
1402 # enter the first level
1390 # enter the first level
1403 self.enter(self.input, ipipe.xiter(self.input, "default"), *self.attrs)
1391 self.enter(self.input, *self.attrs)
1404
1392
1405 self._calcheaderlines(None)
1393 self._calcheaderlines(None)
1406
1394
@@ -1551,7 +1539,7 b' class ibrowse(ipipe.Display):'
1551 except (SystemExit, KeyboardInterrupt):
1539 except (SystemExit, KeyboardInterrupt):
1552 raise
1540 raise
1553 except Exception, exc:
1541 except Exception, exc:
1554 attr = exc
1542 value = exc
1555 if value is not ipipe.noitem:
1543 if value is not ipipe.noitem:
1556 attrstyle = ipipe.xrepr(value, "footer")
1544 attrstyle = ipipe.xrepr(value, "footer")
1557 for (nostyle, text) in attrstyle:
1545 for (nostyle, text) in attrstyle:
This diff has been collapsed as it changes many lines, (670 lines changed) Show them Hide them
@@ -15,9 +15,9 b' This gives a listing of all environment variables sorted by name.'
15
15
16 There are three types of objects in a pipeline expression:
16 There are three types of objects in a pipeline expression:
17
17
18 * ``Table``s: These objects produce items. Examples are ``ls`` (listing the
18 * ``Table``s: These objects produce items. Examples are ``ils`` (listing the
19 current directory, ``ienv`` (listing environment variables), ``ipwd`` (listing
19 current directory, ``ienv`` (listing environment variables), ``ipwd`` (listing
20 user account) and ``igrp`` (listing user groups). A ``Table`` must be the
20 user accounts) and ``igrp`` (listing user groups). A ``Table`` must be the
21 first object in a pipe expression.
21 first object in a pipe expression.
22
22
23 * ``Pipe``s: These objects sit in the middle of a pipe expression. They
23 * ``Pipe``s: These objects sit in the middle of a pipe expression. They
@@ -29,7 +29,7 b' There are three types of objects in a pipeline expression:'
29 * ``Display``s: These objects can be put as the last object in a pipeline
29 * ``Display``s: These objects can be put as the last object in a pipeline
30 expression. There are responsible for displaying the result of the pipeline
30 expression. There are responsible for displaying the result of the pipeline
31 expression. If a pipeline expression doesn't end in a display object a default
31 expression. If a pipeline expression doesn't end in a display object a default
32 display objects will be used. One example is ``browse`` which is a ``curses``
32 display objects will be used. One example is ``ibrowse`` which is a ``curses``
33 based browser.
33 based browser.
34
34
35
35
@@ -37,47 +37,16 b' Adding support for pipeline expressions to your own objects can be done through'
37 three extensions points (all of them optional):
37 three extensions points (all of them optional):
38
38
39 * An object that will be displayed as a row by a ``Display`` object should
39 * An object that will be displayed as a row by a ``Display`` object should
40 implement the method ``__xattrs__(self, mode)``. This method must return a
40 implement the method ``__xattrs__(self, mode)`` method or register an
41 sequence of attribute names. This sequence may also contain integers, which
41 implementation of the generic function ``xattrs``. For more info see ``xattrs``.
42 will be treated as sequence indizes. Also supported is ``None``, which uses
42
43 the object itself and callables which will be called with the object as the
43 * When an object ``foo`` is displayed by a ``Display`` object, the generic
44 an argument. If ``__xattrs__()`` isn't implemented ``(None,)`` will be used as
44 function ``xrepr`` is used.
45 the attribute sequence (i.e. the object itself (it's ``repr()`` format) will
45
46 be being displayed. The global function ``xattrs()`` implements this
46 * Objects that can be iterated by ``Pipe``s must iterable. For special cases,
47 functionality.
47 where iteration for display is different than the normal iteration a special
48
48 implementation can be registered with the generic function ``xiter``. This makes
49 * When an object ``foo`` is displayed in the header, footer or table cell of the
49 it possible to use dictionaries and modules in pipeline expressions, for example:
50 browser ``foo.__xrepr__(mode)`` is called. Mode can be ``"header"`` or
51 ``"footer"`` for the header or footer line and ``"cell"`` for a table cell.
52 ``__xrepr__()```must return an iterable (e.g. by being a generator) which
53 produces the following items: The first item should be a tuple containing
54 the alignment (-1 left aligned, 0 centered and 1 right aligned) and whether
55 the complete output must be displayed or if the browser is allowed to stop
56 output after enough text has been produced (e.g. a syntax highlighted text
57 line would use ``True``, but for a large data structure (i.e. a nested list,
58 tuple or dictionary) ``False`` would be used). The other output ``__xrepr__()``
59 may produce is tuples of ``Style```objects and text (which contain the text
60 representation of the object; see the ``astyle`` module). If ``__xrepr__()``
61 recursively outputs a data structure the function ``xrepr(object, mode)`` can
62 be used and ``"default"`` must be passed as the mode in these calls. This in
63 turn calls the ``__xrepr__()`` method on ``object`` (or uses ``repr(object)``
64 as the string representation if ``__xrepr__()`` doesn't exist).
65
66 * Objects that can be iterated by ``Pipe``s must implement the method
67 ``__xiter__(self, mode)``. ``mode`` can take the following values:
68
69 - ``"default"``: This is the default value and ist always used by pipeline
70 expressions. Other values are only used in the browser.
71 - ``None``: This value is passed by the browser. The object must return an
72 iterable of ``XMode`` objects describing all modes supported by the object.
73 (This should never include ``"default"`` or ``None``).
74 - Any other value that the object supports.
75
76 The global function ``xiter()`` can be called to get such an iterator. If
77 the method ``_xiter__`` isn't implemented, ``xiter()`` falls back to
78 ``__iter__``. In addition to that, dictionaries and modules receive special
79 treatment (returning an iterator over ``(key, value)`` pairs). This makes it
80 possible to use dictionaries and modules in pipeline expressions, for example:
81
50
82 >>> import sys
51 >>> import sys
83 >>> sys | ifilter("isinstance(value, int)") | idump
52 >>> sys | ifilter("isinstance(value, int)") | idump
@@ -152,6 +121,8 b' try:'
152 except ImportError:
121 except ImportError:
153 grp = None
122 grp = None
154
123
124 from IPython.external import simplegeneric
125
155 import path
126 import path
156 try:
127 try:
157 from IPython import genutils, ipapi
128 from IPython import genutils, ipapi
@@ -229,7 +200,7 b' def item(iterator, index, default=noitem):'
229 """
200 """
230 Return the ``index``th item from the iterator ``iterator``.
201 Return the ``index``th item from the iterator ``iterator``.
231 ``index`` must be an integer (negative integers are relative to the
202 ``index`` must be an integer (negative integers are relative to the
232 end (i.e. the last item produced by the iterator)).
203 end (i.e. the last items produced by the iterator)).
233
204
234 If ``default`` is given, this will be the default value when
205 If ``default`` is given, this will be the default value when
235 the iterator doesn't contain an item at this position. Otherwise an
206 the iterator doesn't contain an item at this position. Otherwise an
@@ -260,6 +231,11 b' def item(iterator, index, default=noitem):'
260
231
261
232
262 def getglobals(g):
233 def getglobals(g):
234 """
235 Return the global namespace that is used for expression strings in
236 ``ifilter`` and others. This is ``g`` or (if ``g`` is ``None``) IPython's
237 user namespace.
238 """
263 if g is None:
239 if g is None:
264 if ipapi is not None:
240 if ipapi is not None:
265 api = ipapi.get()
241 api = ipapi.get()
@@ -270,6 +246,9 b' def getglobals(g):'
270
246
271
247
272 class Descriptor(object):
248 class Descriptor(object):
249 """
250 A ``Descriptor`` object is used for describing the attributes of objects.
251 """
273 def __hash__(self):
252 def __hash__(self):
274 return hash(self.__class__) ^ hash(self.key())
253 return hash(self.__class__) ^ hash(self.key())
275
254
@@ -283,34 +262,57 b' class Descriptor(object):'
283 pass
262 pass
284
263
285 def name(self):
264 def name(self):
265 """
266 Return the name of this attribute for display by a ``Display`` object
267 (e.g. as a column title).
268 """
286 key = self.key()
269 key = self.key()
287 if key is None:
270 if key is None:
288 return "_"
271 return "_"
289 return str(key)
272 return str(key)
290
273
291 def attrtype(self, obj):
274 def attrtype(self, obj):
292 pass
275 """
276 Return the type of this attribute (i.e. something like "attribute" or
277 "method").
278 """
293
279
294 def valuetype(self, obj):
280 def valuetype(self, obj):
295 pass
281 """
282 Return the type of this attribute value of the object ``obj``.
283 """
296
284
297 def value(self, obj):
285 def value(self, obj):
298 pass
286 """
287 Return the value of this attribute of the object ``obj``.
288 """
299
289
300 def doc(self, obj):
290 def doc(self, obj):
301 pass
291 """
292 Return the documentation for this attribute.
293 """
302
294
303 def shortdoc(self, obj):
295 def shortdoc(self, obj):
296 """
297 Return a short documentation for this attribute (defaulting to the
298 first line).
299 """
304 doc = self.doc(obj)
300 doc = self.doc(obj)
305 if doc is not None:
301 if doc is not None:
306 doc = doc.strip().splitlines()[0].strip()
302 doc = doc.strip().splitlines()[0].strip()
307 return doc
303 return doc
308
304
309 def iter(self, obj):
305 def iter(self, obj):
306 """
307 Return an iterator for this attribute of the object ``obj``.
308 """
310 return xiter(self.value(obj))
309 return xiter(self.value(obj))
311
310
312
311
313 class SelfDescriptor(Descriptor):
312 class SelfDescriptor(Descriptor):
313 """
314 A ``SelfDescriptor`` describes the object itself.
315 """
314 def key(self):
316 def key(self):
315 return None
317 return None
316
318
@@ -330,6 +332,9 b" selfdescriptor = SelfDescriptor() # there's no need for more than one"
330
332
331
333
332 class AttributeDescriptor(Descriptor):
334 class AttributeDescriptor(Descriptor):
335 """
336 An ``AttributeDescriptor`` describes a simple attribute of an object.
337 """
333 __slots__ = ("_name", "_doc")
338 __slots__ = ("_name", "_doc")
334
339
335 def __init__(self, name, doc=None):
340 def __init__(self, name, doc=None):
@@ -359,6 +364,10 b' class AttributeDescriptor(Descriptor):'
359
364
360
365
361 class IndexDescriptor(Descriptor):
366 class IndexDescriptor(Descriptor):
367 """
368 An ``IndexDescriptor`` describes an "attribute" of an object that is fetched
369 via ``__getitem__``.
370 """
362 __slots__ = ("_index",)
371 __slots__ = ("_index",)
363
372
364 def __init__(self, index):
373 def __init__(self, index):
@@ -381,6 +390,10 b' class IndexDescriptor(Descriptor):'
381
390
382
391
383 class MethodDescriptor(Descriptor):
392 class MethodDescriptor(Descriptor):
393 """
394 A ``MethodDescriptor`` describes a method of an object that can be called
395 without argument. Note that this method shouldn't change the object.
396 """
384 __slots__ = ("_name", "_doc")
397 __slots__ = ("_name", "_doc")
385
398
386 def __init__(self, name, doc=None):
399 def __init__(self, name, doc=None):
@@ -412,6 +425,11 b' class MethodDescriptor(Descriptor):'
412
425
413
426
414 class IterAttributeDescriptor(Descriptor):
427 class IterAttributeDescriptor(Descriptor):
428 """
429 An ``IterAttributeDescriptor`` works like an ``AttributeDescriptor`` but
430 doesn't return an attribute values (because this value might be e.g. a large
431 list).
432 """
415 __slots__ = ("_name", "_doc")
433 __slots__ = ("_name", "_doc")
416
434
417 def __init__(self, name, doc=None):
435 def __init__(self, name, doc=None):
@@ -444,6 +462,10 b' class IterAttributeDescriptor(Descriptor):'
444
462
445
463
446 class IterMethodDescriptor(Descriptor):
464 class IterMethodDescriptor(Descriptor):
465 """
466 An ``IterMethodDescriptor`` works like an ``MethodDescriptor`` but doesn't
467 return an attribute values (because this value might be e.g. a large list).
468 """
447 __slots__ = ("_name", "_doc")
469 __slots__ = ("_name", "_doc")
448
470
449 def __init__(self, name, doc=None):
471 def __init__(self, name, doc=None):
@@ -478,6 +500,10 b' class IterMethodDescriptor(Descriptor):'
478
500
479
501
480 class FunctionDescriptor(Descriptor):
502 class FunctionDescriptor(Descriptor):
503 """
504 A ``FunctionDescriptor`` turns a function into a descriptor. The function
505 will be called with the object to get the type and value of the attribute.
506 """
481 __slots__ = ("_function", "_name", "_doc")
507 __slots__ = ("_function", "_name", "_doc")
482
508
483 def __init__(self, function, name=None, doc=None):
509 def __init__(self, function, name=None, doc=None):
@@ -572,9 +598,6 b' class Table(object):'
572 other = other()
598 other = other()
573 return ichain(other, self)
599 return ichain(other, self)
574
600
575 def __iter__(self):
576 return xiter(self, "default")
577
578
601
579 class Pipe(Table):
602 class Pipe(Table):
580 """
603 """
@@ -596,10 +619,41 b' class Pipe(Table):'
596
619
597
620
598 def xrepr(item, mode="default"):
621 def xrepr(item, mode="default"):
622 """
623 Generic function that adds color output and different display modes to ``repr``.
624
625 The result of an ``xrepr`` call is iterable and consists of ``(style, string)``
626 tuples. The ``style`` in this tuple must be a ``Style`` object from the
627 ``astring`` module. To reconfigure the output the first yielded tuple can be
628 a ``(aligment, full)`` tuple instead of a ``(style, string)`` tuple.
629 ``alignment`` can be -1 for left aligned, 0 for centered and 1 for right
630 aligned (the default is left alignment). ``full`` is a boolean that specifies
631 whether the complete output must be displayed or the ``Display`` object is
632 allowed to stop output after enough text has been produced (e.g. a syntax
633 highlighted text line would use ``True``, but for a large data structure
634 (i.e. a nested list, tuple or dictionary) ``False`` would be used).
635 The default is full output.
636
637 There are four different possible values for ``mode`` depending on where
638 the ``Display`` object will display ``item``:
639
640 * ``"header"``: ``item`` will be displayed in a header line (this is used by
641 ``ibrowse``).
642 * ``"footer"``: ``item`` will be displayed in a footer line (this is used by
643 ``ibrowse``).
644 * ``"cell"``: ``item`` will be displayed in a table cell/list.
645 * ``"default"``: default mode. If an ``xrepr`` implementation recursively
646 outputs objects, ``"default"`` must be passed in the recursive calls to
647 ``xrepr``.
648
649 If no implementation is registered for ``item``, ``xrepr`` will try the
650 ``__xrepr__`` method on ``item``. If ``item`` doesn't have an ``__xrepr__``
651 method it falls back to ``repr``/``__repr__`` for all modes.
652 """
599 try:
653 try:
600 func = item.__xrepr__
654 func = item.__xrepr__
601 except AttributeError:
655 except AttributeError:
602 pass
656 yield (astyle.style_default, repr(item))
603 else:
657 else:
604 try:
658 try:
605 for x in func(mode):
659 for x in func(mode):
@@ -608,123 +662,179 b' def xrepr(item, mode="default"):'
608 raise
662 raise
609 except Exception:
663 except Exception:
610 yield (astyle.style_default, repr(item))
664 yield (astyle.style_default, repr(item))
611 return
665 xrepr = simplegeneric.generic(xrepr)
612 if item is None:
666
613 yield (astyle.style_type_none, repr(item))
667
614 elif isinstance(item, bool):
668 def xrepr_none(self, mode="default"):
615 yield (astyle.style_type_bool, repr(item))
669 yield (astyle.style_type_none, repr(self))
616 elif isinstance(item, str):
670 xrepr.when_object(None)(xrepr_none)
617 if mode == "cell":
671
618 yield (astyle.style_default, repr(item.expandtabs(tab))[1:-1])
672
619 else:
673 def xrepr_bool(self, mode="default"):
620 yield (astyle.style_default, repr(item))
674 yield (astyle.style_type_bool, repr(self))
621 elif isinstance(item, unicode):
675 xrepr.when_type(bool)(xrepr_bool)
622 if mode == "cell":
676
623 yield (astyle.style_default, repr(item.expandtabs(tab))[2:-1])
677
624 else:
678 def xrepr_str(self, mode="default"):
625 yield (astyle.style_default, repr(item))
679 if mode == "cell":
626 elif isinstance(item, (int, long, float)):
680 yield (astyle.style_default, repr(self.expandtabs(tab))[1:-1])
627 yield (1, True)
681 else:
628 yield (astyle.style_type_number, repr(item))
682 yield (astyle.style_default, repr(self))
629 elif isinstance(item, complex):
683 xrepr.when_type(str)(xrepr_str)
630 yield (astyle.style_type_number, repr(item))
684
631 elif isinstance(item, datetime.datetime):
685
632 if mode == "cell":
686 def xrepr_unicode(self, mode="default"):
633 # Don't use strftime() here, as this requires year >= 1900
687 if mode == "cell":
634 yield (astyle.style_type_datetime,
688 yield (astyle.style_default, repr(self.expandtabs(tab))[2:-1])
635 "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
689 else:
636 (item.year, item.month, item.day,
690 yield (astyle.style_default, repr(self))
637 item.hour, item.minute, item.second,
691 xrepr.when_type(unicode)(xrepr_unicode)
638 item.microsecond),
692
639 )
693
640 else:
694 def xrepr_number(self, mode="default"):
641 yield (astyle.style_type_datetime, repr(item))
695 yield (1, True)
642 elif isinstance(item, datetime.date):
696 yield (astyle.style_type_number, repr(self))
643 if mode == "cell":
697 xrepr.when_type(int)(xrepr_number)
644 yield (astyle.style_type_datetime,
698 xrepr.when_type(long)(xrepr_number)
645 "%04d-%02d-%02d" % (item.year, item.month, item.day))
699 xrepr.when_type(float)(xrepr_number)
646 else:
700
647 yield (astyle.style_type_datetime, repr(item))
701
648 elif isinstance(item, datetime.time):
702 def xrepr_complex(self, mode="default"):
649 if mode == "cell":
703 yield (astyle.style_type_number, repr(self))
650 yield (astyle.style_type_datetime,
704 xrepr.when_type(complex)(xrepr_number)
651 "%02d:%02d:%02d.%06d" % \
705
652 (item.hour, item.minute, item.second, item.microsecond))
706
653 else:
707 def xrepr_datetime(self, mode="default"):
654 yield (astyle.style_type_datetime, repr(item))
708 if mode == "cell":
655 elif isinstance(item, datetime.timedelta):
709 # Don't use strftime() here, as this requires year >= 1900
656 yield (astyle.style_type_datetime, repr(item))
710 yield (astyle.style_type_datetime,
657 elif isinstance(item, type):
711 "%04d-%02d-%02d %02d:%02d:%02d.%06d" % \
658 if item.__module__ == "__builtin__":
712 (self.year, self.month, self.day,
659 yield (astyle.style_type_type, item.__name__)
713 self.hour, self.minute, self.second,
660 else:
714 self.microsecond),
661 yield (astyle.style_type_type, "%s.%s" % (item.__module__, item.__name__))
715 )
662 elif isinstance(item, Exception):
716 else:
663 if item.__class__.__module__ == "exceptions":
717 yield (astyle.style_type_datetime, repr(self))
664 classname = item.__class__.__name__
718 xrepr.when_type(datetime.datetime)(xrepr_datetime)
719
720
721 def xrepr_date(self, mode="default"):
722 if mode == "cell":
723 yield (astyle.style_type_datetime,
724 "%04d-%02d-%02d" % (self.year, self.month, self.day))
725 else:
726 yield (astyle.style_type_datetime, repr(self))
727 xrepr.when_type(datetime.date)(xrepr_date)
728
729
730 def xrepr_time(self, mode="default"):
731 if mode == "cell":
732 yield (astyle.style_type_datetime,
733 "%02d:%02d:%02d.%06d" % \
734 (self.hour, self.minute, self.second, self.microsecond))
735 else:
736 yield (astyle.style_type_datetime, repr(self))
737 xrepr.when_type(datetime.time)(xrepr_time)
738
739
740 def xrepr_timedelta(self, mode="default"):
741 yield (astyle.style_type_datetime, repr(self))
742 xrepr.when_type(datetime.timedelta)(xrepr_timedelta)
743
744
745 def xrepr_type(self, mode="default"):
746 if self.__module__ == "__builtin__":
747 yield (astyle.style_type_type, self.__name__)
748 else:
749 yield (astyle.style_type_type, "%s.%s" % (self.__module__, self.__name__))
750 xrepr.when_type(type)(xrepr_type)
751
752
753 def xrepr_exception(self, mode="default"):
754 if self.__class__.__module__ == "exceptions":
755 classname = self.__class__.__name__
756 else:
757 classname = "%s.%s" % \
758 (self.__class__.__module__, self.__class__.__name__)
759 if mode == "header" or mode == "footer":
760 yield (astyle.style_error, "%s: %s" % (classname, self))
761 else:
762 yield (astyle.style_error, classname)
763 xrepr.when_type(Exception)(xrepr_exception)
764
765
766 def xrepr_listtuple(self, mode="default"):
767 if mode == "header" or mode == "footer":
768 if self.__class__.__module__ == "__builtin__":
769 classname = self.__class__.__name__
665 else:
770 else:
666 classname = "%s.%s" % \
771 classname = "%s.%s" % \
667 (item.__class__.__module__, item.__class__.__name__)
772 (self.__class__.__module__,self.__class__.__name__)
668 if mode == "header" or mode == "footer":
773 yield (astyle.style_default,
669 yield (astyle.style_error, "%s: %s" % (classname, item))
774 "<%s object with %d items at 0x%x>" % \
670 else:
775 (classname, len(self), id(self)))
671 yield (astyle.style_error, classname)
776 else:
672 elif isinstance(item, (list, tuple)):
777 yield (-1, False)
673 if mode == "header" or mode == "footer":
778 if isinstance(self, list):
674 if item.__class__.__module__ == "__builtin__":
779 yield (astyle.style_default, "[")
675 classname = item.__class__.__name__
780 end = "]"
676 else:
677 classname = "%s.%s" % \
678 (item.__class__.__module__,item.__class__.__name__)
679 yield (astyle.style_default,
680 "<%s object with %d items at 0x%x>" % \
681 (classname, len(item), id(item)))
682 else:
781 else:
683 yield (-1, False)
782 yield (astyle.style_default, "(")
684 if isinstance(item, list):
783 end = ")"
685 yield (astyle.style_default, "[")
784 for (i, subself) in enumerate(self):
686 end = "]"
785 if i:
687 else:
786 yield (astyle.style_default, ", ")
688 yield (astyle.style_default, "(")
787 for part in xrepr(subself, "default"):
689 end = ")"
788 yield part
690 for (i, subitem) in enumerate(item):
789 yield (astyle.style_default, end)
691 if i:
790 xrepr.when_type(list)(xrepr_listtuple)
692 yield (astyle.style_default, ", ")
791 xrepr.when_type(tuple)(xrepr_listtuple)
693 for part in xrepr(subitem, "default"):
792
694 yield part
793
695 yield (astyle.style_default, end)
794 def xrepr_dict(self, mode="default"):
696 elif isinstance(item, (dict, types.DictProxyType)):
795 if mode == "header" or mode == "footer":
697 if mode == "header" or mode == "footer":
796 if self.__class__.__module__ == "__builtin__":
698 if item.__class__.__module__ == "__builtin__":
797 classname = self.__class__.__name__
699 classname = item.__class__.__name__
700 else:
701 classname = "%s.%s" % \
702 (item.__class__.__module__,item.__class__.__name__)
703 yield (astyle.style_default,
704 "<%s object with %d items at 0x%x>" % \
705 (classname, len(item), id(item)))
706 else:
798 else:
707 yield (-1, False)
799 classname = "%s.%s" % \
708 if isinstance(item, dict):
800 (self.__class__.__module__,self.__class__.__name__)
709 yield (astyle.style_default, "{")
801 yield (astyle.style_default,
710 end = "}"
802 "<%s object with %d items at 0x%x>" % \
711 else:
803 (classname, len(self), id(self)))
712 yield (astyle.style_default, "dictproxy((")
713 end = "})"
714 for (i, (key, value)) in enumerate(item.iteritems()):
715 if i:
716 yield (astyle.style_default, ", ")
717 for part in xrepr(key, "default"):
718 yield part
719 yield (astyle.style_default, ": ")
720 for part in xrepr(value, "default"):
721 yield part
722 yield (astyle.style_default, end)
723 else:
804 else:
724 yield (astyle.style_default, repr(item))
805 yield (-1, False)
806 if isinstance(self, dict):
807 yield (astyle.style_default, "{")
808 end = "}"
809 else:
810 yield (astyle.style_default, "dictproxy((")
811 end = "})"
812 for (i, (key, value)) in enumerate(self.iteritems()):
813 if i:
814 yield (astyle.style_default, ", ")
815 for part in xrepr(key, "default"):
816 yield part
817 yield (astyle.style_default, ": ")
818 for part in xrepr(value, "default"):
819 yield part
820 yield (astyle.style_default, end)
821 xrepr.when_type(dict)(xrepr_dict)
822 xrepr.when_type(types.DictProxyType)(xrepr_dict)
725
823
726
824
727 def upgradexattr(attr):
825 def upgradexattr(attr):
826 """
827 Convert an attribute descriptor string to a real descriptor object.
828
829 If attr already is a descriptor object return if unmodified. A
830 ``SelfDescriptor`` will be returned if ``attr`` is ``None``. ``"foo"``
831 returns an ``AttributeDescriptor`` for the attribute named ``"foo"``.
832 ``"foo()"`` returns a ``MethodDescriptor`` for the method named ``"foo"``.
833 ``"-foo"`` will return an ``IterAttributeDescriptor`` for the attribute
834 named ``"foo"`` and ``"-foo()"`` will return an ``IterMethodDescriptor``
835 for the method named ``"foo"``. Furthermore integer will return the appropriate
836 ``IndexDescriptor`` and callables will return a ``FunctionDescriptor``.
837 """
728 if attr is None:
838 if attr is None:
729 return selfdescriptor
839 return selfdescriptor
730 elif isinstance(attr, Descriptor):
840 elif isinstance(attr, Descriptor):
@@ -749,6 +859,28 b' def upgradexattr(attr):'
749
859
750
860
751 def xattrs(item, mode="default"):
861 def xattrs(item, mode="default"):
862 """
863 Generic function that returns an iterable of attribute descriptors
864 to be used for displaying the attributes ob the object ``item`` in display
865 mode ``mode``.
866
867 There are two possible modes:
868
869 * ``"detail"``: The ``Display`` object wants to display a detailed list
870 of the object attributes.
871 * ``"default"``: The ``Display`` object wants to display the object in a
872 list view.
873
874 If no implementation is registered for the object ``item`` ``xattrs`` falls
875 back to trying the ``__xattrs__`` method of the object. If this doesn't
876 exist either, ``dir(item)`` is used for ``"detail"`` mode and ``(None,)``
877 for ``"default"`` mode.
878
879 The implementation must yield attribute descriptor (see the class
880 ``Descriptor`` for more info). The ``__xattrs__`` method may also return
881 attribute descriptor string (and ``None``) which will be converted to real
882 descriptors by ``upgradexattr()``.
883 """
752 try:
884 try:
753 func = item.__xattrs__
885 func = item.__xattrs__
754 except AttributeError:
886 except AttributeError:
@@ -760,6 +892,14 b' def xattrs(item, mode="default"):'
760 else:
892 else:
761 for attr in func(mode):
893 for attr in func(mode):
762 yield upgradexattr(attr)
894 yield upgradexattr(attr)
895 xattrs = simplegeneric.generic(xattrs)
896
897
898 def xattrs_complex(self, mode="default"):
899 if mode == "detail":
900 return (AttributeDescriptor("real"), AttributeDescriptor("imag"))
901 return (selfdescriptor,)
902 xattrs.when_type(complex)(xattrs_complex)
763
903
764
904
765 def _isdict(item):
905 def _isdict(item):
@@ -780,7 +920,11 b' def _isstr(item):'
780 return False # ``__iter__`` has been redefined
920 return False # ``__iter__`` has been redefined
781
921
782
922
783 def xiter(item, mode="default"):
923 def xiter(item):
924 """
925 Generic function that implements iteration for pipeline expression. If no
926 implementation is registered for ``item`` ``xiter`` falls back to ``iter``.
927 """
784 try:
928 try:
785 func = item.__xiter__
929 func = item.__xiter__
786 except AttributeError:
930 except AttributeError:
@@ -799,13 +943,11 b' def xiter(item, mode="default"):'
799 elif _isstr(item):
943 elif _isstr(item):
800 if not item:
944 if not item:
801 raise ValueError("can't enter empty string")
945 raise ValueError("can't enter empty string")
802 lines = item.splitlines()
946 return iter(item.splitlines())
803 if len(lines) <= 1:
804 raise ValueError("can't enter one line string")
805 return iter(lines)
806 return iter(item)
947 return iter(item)
807 else:
948 else:
808 return iter(func(mode)) # iter() just to be safe
949 return iter(func()) # iter() just to be safe
950 xiter = simplegeneric.generic(xiter)
809
951
810
952
811 class ichain(Pipe):
953 class ichain(Pipe):
@@ -819,7 +961,7 b' class ichain(Pipe):'
819 def __iter__(self):
961 def __iter__(self):
820 return itertools.chain(*self.iters)
962 return itertools.chain(*self.iters)
821
963
822 def __xrepr__(self, mode):
964 def __xrepr__(self, mode="default"):
823 if mode == "header" or mode == "footer":
965 if mode == "header" or mode == "footer":
824 for (i, item) in enumerate(self.iters):
966 for (i, item) in enumerate(self.iters):
825 if i:
967 if i:
@@ -954,7 +1096,7 b' class ifile(path.path):'
954
1096
955 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
1097 defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate")
956
1098
957 def __xattrs__(self, mode):
1099 def __xattrs__(self, mode="default"):
958 if mode == "detail":
1100 if mode == "detail":
959 return (
1101 return (
960 "name",
1102 "name",
@@ -995,54 +1137,51 b' class ifile(path.path):'
995 else:
1137 else:
996 return self.defaultattrs
1138 return self.defaultattrs
997
1139
998 def __xrepr__(self, mode):
999 try:
1000 if self.isdir():
1001 name = "idir"
1002 style = astyle.style_dir
1003 else:
1004 name = "ifile"
1005 style = astyle.style_file
1006 except IOError:
1007 name = "ifile"
1008 style = astyle.style_default
1009 if mode == "cell" or mode in "header" or mode == "footer":
1010 abspath = repr(path._base(self.normpath()))
1011 if abspath.startswith("u"):
1012 abspath = abspath[2:-1]
1013 else:
1014 abspath = abspath[1:-1]
1015 if mode == "cell":
1016 yield (style, abspath)
1017 else:
1018 yield (style, "%s(%s)" % (name, abspath))
1019 else:
1020 yield (style, repr(self))
1021
1140
1022 def __iter__(self):
1141 def xiter_ifile(self):
1023 if self.isdir():
1142 if self.isdir():
1024 yield iparentdir(self / os.pardir)
1143 yield (self / os.pardir).abspath()
1025 for child in sorted(self.listdir()):
1144 for child in sorted(self.listdir()):
1026 yield child
1145 yield child
1027 else:
1146 else:
1028 f = self.open("rb")
1147 f = self.open("rb")
1029 for line in f:
1148 for line in f:
1030 yield line
1149 yield line
1031 f.close()
1150 f.close()
1151 xiter.when_type(ifile)(xiter_ifile)
1032
1152
1033
1153
1034 class iparentdir(ifile):
1154 # We need to implement ``xrepr`` for ``ifile`` as a generic function, because
1035 def __xrepr__(self, mode):
1155 # otherwise ``xrepr_str`` would kick in.
1156 def xrepr_ifile(self, mode="default"):
1157 try:
1158 if self.isdir():
1159 name = "idir"
1160 style = astyle.style_dir
1161 else:
1162 name = "ifile"
1163 style = astyle.style_file
1164 except IOError:
1165 name = "ifile"
1166 style = astyle.style_default
1167 if mode == "cell" or mode in "header" or mode == "footer":
1168 abspath = repr(path._base(self.normpath()))
1169 if abspath.startswith("u"):
1170 abspath = abspath[2:-1]
1171 else:
1172 abspath = abspath[1:-1]
1036 if mode == "cell":
1173 if mode == "cell":
1037 yield (astyle.style_dir, os.pardir)
1174 yield (style, abspath)
1038 else:
1175 else:
1039 for part in ifile.__xrepr__(self, mode):
1176 yield (style, "%s(%s)" % (name, abspath))
1040 yield part
1177 else:
1178 yield (style, repr(self))
1179 xrepr.when_type(ifile)(xrepr_ifile)
1041
1180
1042
1181
1043 class ils(Table):
1182 class ils(Table):
1044 """
1183 """
1045 List the current (or a specific) directory.
1184 List the current (or a specified) directory.
1046
1185
1047 Examples:
1186 Examples:
1048
1187
@@ -1056,7 +1195,9 b' class ils(Table):'
1056 self.files = files
1195 self.files = files
1057
1196
1058 def __iter__(self):
1197 def __iter__(self):
1059 for child in ifile(self.base).listdir():
1198 base = ifile(self.base)
1199 yield (base / os.pardir).abspath()
1200 for child in base.listdir():
1060 if self.dirs:
1201 if self.dirs:
1061 if self.files:
1202 if self.files:
1062 yield child
1203 yield child
@@ -1067,7 +1208,7 b' class ils(Table):'
1067 if not child.isdir():
1208 if not child.isdir():
1068 yield child
1209 yield child
1069
1210
1070 def __xrepr__(self, mode):
1211 def __xrepr__(self, mode="default"):
1071 return ifile(self.base).__xrepr__(mode)
1212 return ifile(self.base).__xrepr__(mode)
1072
1213
1073 def __repr__(self):
1214 def __repr__(self):
@@ -1091,7 +1232,7 b' class iglob(Table):'
1091 for name in glob.glob(self.glob):
1232 for name in glob.glob(self.glob):
1092 yield ifile(name)
1233 yield ifile(name)
1093
1234
1094 def __xrepr__(self, mode):
1235 def __xrepr__(self, mode="default"):
1095 if mode == "header" or mode == "footer" or mode == "cell":
1236 if mode == "header" or mode == "footer" or mode == "cell":
1096 yield (astyle.style_default,
1237 yield (astyle.style_default,
1097 "%s(%r)" % (self.__class__.__name__, self.glob))
1238 "%s(%r)" % (self.__class__.__name__, self.glob))
@@ -1125,7 +1266,7 b' class iwalk(Table):'
1125 for name in sorted(filenames):
1266 for name in sorted(filenames):
1126 yield ifile(os.path.join(dirpath, name))
1267 yield ifile(os.path.join(dirpath, name))
1127
1268
1128 def __xrepr__(self, mode):
1269 def __xrepr__(self, mode="default"):
1129 if mode == "header" or mode == "footer" or mode == "cell":
1270 if mode == "header" or mode == "footer" or mode == "cell":
1130 yield (astyle.style_default,
1271 yield (astyle.style_default,
1131 "%s(%r)" % (self.__class__.__name__, self.base))
1272 "%s(%r)" % (self.__class__.__name__, self.base))
@@ -1192,7 +1333,7 b' class ipwdentry(object):'
1192 return self._getentry().pw_shell
1333 return self._getentry().pw_shell
1193 shell = property(getshell, None, None, "Login shell")
1334 shell = property(getshell, None, None, "Login shell")
1194
1335
1195 def __xattrs__(self, mode):
1336 def __xattrs__(self, mode="default"):
1196 return ("name", "passwd", "uid", "gid", "gecos", "dir", "shell")
1337 return ("name", "passwd", "uid", "gid", "gecos", "dir", "shell")
1197
1338
1198 def __repr__(self):
1339 def __repr__(self):
@@ -1212,7 +1353,7 b' class ipwd(Table):'
1212 for entry in pwd.getpwall():
1353 for entry in pwd.getpwall():
1213 yield ipwdentry(entry.pw_name)
1354 yield ipwdentry(entry.pw_name)
1214
1355
1215 def __xrepr__(self, mode):
1356 def __xrepr__(self, mode="default"):
1216 if mode == "header" or mode == "footer" or mode == "cell":
1357 if mode == "header" or mode == "footer" or mode == "cell":
1217 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1358 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1218 else:
1359 else:
@@ -1257,10 +1398,10 b' class igrpentry(object):'
1257 return self._getentry().gr_mem
1398 return self._getentry().gr_mem
1258 mem = property(getmem, None, None, "Members")
1399 mem = property(getmem, None, None, "Members")
1259
1400
1260 def __xattrs__(self, mode):
1401 def __xattrs__(self, mode="default"):
1261 return ("name", "passwd", "gid", "mem")
1402 return ("name", "passwd", "gid", "mem")
1262
1403
1263 def __xrepr__(self, mode):
1404 def __xrepr__(self, mode="default"):
1264 if mode == "header" or mode == "footer" or mode == "cell":
1405 if mode == "header" or mode == "footer" or mode == "cell":
1265 yield (astyle.style_default, "group ")
1406 yield (astyle.style_default, "group ")
1266 try:
1407 try:
@@ -1290,7 +1431,7 b' class igrp(Table):'
1290 for entry in grp.getgrall():
1431 for entry in grp.getgrall():
1291 yield igrpentry(entry.gr_name)
1432 yield igrpentry(entry.gr_name)
1292
1433
1293 def __xrepr__(self, mode):
1434 def __xrepr__(self, mode="default"):
1294 if mode == "header" or mode == "footer":
1435 if mode == "header" or mode == "footer":
1295 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1436 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1296 else:
1437 else:
@@ -1303,10 +1444,10 b' class Fields(object):'
1303 for (key, value) in fields.iteritems():
1444 for (key, value) in fields.iteritems():
1304 setattr(self, key, value)
1445 setattr(self, key, value)
1305
1446
1306 def __xattrs__(self, mode):
1447 def __xattrs__(self, mode="default"):
1307 return self.__fieldnames
1448 return self.__fieldnames
1308
1449
1309 def __xrepr__(self, mode):
1450 def __xrepr__(self, mode="default"):
1310 yield (-1, False)
1451 yield (-1, False)
1311 if mode == "header" or mode == "cell":
1452 if mode == "header" or mode == "cell":
1312 yield (astyle.style_default, self.__class__.__name__)
1453 yield (astyle.style_default, self.__class__.__name__)
@@ -1340,7 +1481,7 b' class FieldTable(Table, list):'
1340 def add(self, **fields):
1481 def add(self, **fields):
1341 self.append(Fields(self.fields, **fields))
1482 self.append(Fields(self.fields, **fields))
1342
1483
1343 def __xrepr__(self, mode):
1484 def __xrepr__(self, mode="default"):
1344 yield (-1, False)
1485 yield (-1, False)
1345 if mode == "header" or mode == "footer":
1486 if mode == "header" or mode == "footer":
1346 yield (astyle.style_default, self.__class__.__name__)
1487 yield (astyle.style_default, self.__class__.__name__)
@@ -1360,10 +1501,10 b' class FieldTable(Table, list):'
1360
1501
1361
1502
1362 class List(list):
1503 class List(list):
1363 def __xattrs__(self, mode):
1504 def __xattrs__(self, mode="default"):
1364 return xrange(len(self))
1505 return xrange(len(self))
1365
1506
1366 def __xrepr__(self, mode):
1507 def __xrepr__(self, mode="default"):
1367 yield (-1, False)
1508 yield (-1, False)
1368 if mode == "header" or mode == "cell" or mode == "footer" or mode == "default":
1509 if mode == "header" or mode == "cell" or mode == "footer" or mode == "default":
1369 yield (astyle.style_default, self.__class__.__name__)
1510 yield (astyle.style_default, self.__class__.__name__)
@@ -1392,7 +1533,7 b' class ienv(Table):'
1392 for (key, value) in os.environ.iteritems():
1533 for (key, value) in os.environ.iteritems():
1393 yield Fields(fields, key=key, value=value)
1534 yield Fields(fields, key=key, value=value)
1394
1535
1395 def __xrepr__(self, mode):
1536 def __xrepr__(self, mode="default"):
1396 if mode == "header" or mode == "cell":
1537 if mode == "header" or mode == "cell":
1397 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1538 yield (astyle.style_default, "%s()" % self.__class__.__name__)
1398 else:
1539 else:
@@ -1419,7 +1560,7 b' class icsv(Pipe):'
1419 for line in reader:
1560 for line in reader:
1420 yield List(line)
1561 yield List(line)
1421
1562
1422 def __xrepr__(self, mode):
1563 def __xrepr__(self, mode="default"):
1423 yield (-1, False)
1564 yield (-1, False)
1424 if mode == "header" or mode == "footer":
1565 if mode == "header" or mode == "footer":
1425 input = getattr(self, "input", None)
1566 input = getattr(self, "input", None)
@@ -1472,7 +1613,7 b' class ix(Table):'
1472 self._pipeout.close()
1613 self._pipeout.close()
1473 self._pipeout = None
1614 self._pipeout = None
1474
1615
1475 def __xrepr__(self, mode):
1616 def __xrepr__(self, mode="default"):
1476 if mode == "header" or mode == "footer":
1617 if mode == "header" or mode == "footer":
1477 yield (astyle.style_default,
1618 yield (astyle.style_default,
1478 "%s(%r)" % (self.__class__.__name__, self.cmd))
1619 "%s(%r)" % (self.__class__.__name__, self.cmd))
@@ -1552,7 +1693,7 b' class ifilter(Pipe):'
1552 if not ok and exc_info is not None:
1693 if not ok and exc_info is not None:
1553 raise exc_info[0], exc_info[1], exc_info[2]
1694 raise exc_info[0], exc_info[1], exc_info[2]
1554
1695
1555 def __xrepr__(self, mode):
1696 def __xrepr__(self, mode="default"):
1556 if mode == "header" or mode == "footer":
1697 if mode == "header" or mode == "footer":
1557 input = getattr(self, "input", None)
1698 input = getattr(self, "input", None)
1558 if input is not None:
1699 if input is not None:
@@ -1623,7 +1764,7 b' class ieval(Pipe):'
1623 if not ok and exc_info is not None:
1764 if not ok and exc_info is not None:
1624 raise exc_info[0], exc_info[1], exc_info[2]
1765 raise exc_info[0], exc_info[1], exc_info[2]
1625
1766
1626 def __xrepr__(self, mode):
1767 def __xrepr__(self, mode="default"):
1627 if mode == "header" or mode == "footer":
1768 if mode == "header" or mode == "footer":
1628 input = getattr(self, "input", None)
1769 input = getattr(self, "input", None)
1629 if input is not None:
1770 if input is not None:
@@ -1693,7 +1834,7 b' class isort(Pipe):'
1693 for item in items:
1834 for item in items:
1694 yield item
1835 yield item
1695
1836
1696 def __xrepr__(self, mode):
1837 def __xrepr__(self, mode="default"):
1697 if mode == "header" or mode == "footer":
1838 if mode == "header" or mode == "footer":
1698 input = getattr(self, "input", None)
1839 input = getattr(self, "input", None)
1699 if input is not None:
1840 if input is not None:
@@ -1756,10 +1897,18 b' class iless(Display):'
1756 try:
1897 try:
1757 pager = os.popen(self.cmd, "w")
1898 pager = os.popen(self.cmd, "w")
1758 try:
1899 try:
1759 for item in xiter(self.input, "default"):
1900 for item in xiter(self.input):
1760 attrs = tuple(_upgradexattrs(item, "default"))
1901 first = False
1761 attrs = ["%s=%s" % (a.name(item), a.value(item)) for a in attrs]
1902 for attr in xattrs(item, "default"):
1762 pager.write(" ".join(attrs))
1903 if first:
1904 first = False
1905 else:
1906 pager.write(" ")
1907 attr = upgradexattr(attr)
1908 if not isinstance(attr, SelfDescriptor):
1909 pager.write(attr.name())
1910 pager.write("=")
1911 pager.write(str(attr.value(item)))
1763 pager.write("\n")
1912 pager.write("\n")
1764 finally:
1913 finally:
1765 pager.close()
1914 pager.close()
@@ -1815,7 +1964,7 b' class idump(Display):'
1815 attrset = set()
1964 attrset = set()
1816 colwidths = {}
1965 colwidths = {}
1817 rows = []
1966 rows = []
1818 for item in xiter(self.input, "default"):
1967 for item in xiter(self.input):
1819 row = {}
1968 row = {}
1820 attrs = self.attrs
1969 attrs = self.attrs
1821 if not attrs:
1970 if not attrs:
@@ -1871,44 +2020,11 b' class idump(Display):'
1871 stream.write("\n")
2020 stream.write("\n")
1872
2021
1873
2022
1874 class XMode(object):
2023 class AttributeDetail(Table):
1875 """
2024 """
1876 An ``XMode`` object describes one enter mode available for an object
2025 ``AttributeDetail`` objects are use for displaying a detailed list of object
2026 attributes.
1877 """
2027 """
1878 def __init__(self, object, mode, title=None, description=None):
1879 """
1880 Create a new ``XMode`` object for the object ``object``. This object
1881 must support the enter mode ``mode`` (i.e. ``object.__xiter__(mode)``
1882 must return an iterable). ``title`` and ``description`` will be
1883 displayed in the browser when selecting among the available modes.
1884 """
1885 self.object = object
1886 self.mode = mode
1887 self.title = title
1888 self.description = description
1889
1890 def __repr__(self):
1891 return "<%s.%s object mode=%r at 0x%x>" % \
1892 (self.__class__.__module__, self.__class__.__name__,
1893 self.mode, id(self))
1894
1895 def __xrepr__(self, mode):
1896 if mode == "header" or mode == "footer":
1897 yield (astyle.style_default, self.title)
1898 else:
1899 yield (astyle.style_default, repr(self))
1900
1901 def __xattrs__(self, mode):
1902 if mode == "detail":
1903 return ("object", "mode")
1904 else:
1905 return ("object", "mode", "title", "description")
1906
1907 def __xiter__(self, mode):
1908 return xiter(self.object, self.mode)
1909
1910
1911 class AttributeDetail(Table):
1912 def __init__(self, object, descriptor):
2028 def __init__(self, object, descriptor):
1913 self.object = object
2029 self.object = object
1914 self.descriptor = descriptor
2030 self.descriptor = descriptor
@@ -1934,19 +2050,21 b' class AttributeDetail(Table):'
1934 def value(self):
2050 def value(self):
1935 return self.descriptor.value(self.object)
2051 return self.descriptor.value(self.object)
1936
2052
1937 def __xattrs__(self, mode):
2053 def __xattrs__(self, mode="default"):
1938 attrs = ("name()", "attrtype()", "valuetype()", "value()", "shortdoc()")
2054 attrs = ("name()", "attrtype()", "valuetype()", "value()", "shortdoc()")
1939 if mode == "detail":
2055 if mode == "detail":
1940 attrs += ("doc()",)
2056 attrs += ("doc()",)
1941 return attrs
2057 return attrs
1942
2058
1943 def __xrepr__(self, mode):
2059 def __xrepr__(self, mode="default"):
1944 yield (-1, True)
2060 yield (-1, True)
2061 valuetype = self.valuetype()
2062 if valuetype is not noitem:
2063 for part in xrepr(valuetype):
2064 yield part
2065 yield (astyle.style_default, " ")
1945 yield (astyle.style_default, self.attrtype())
2066 yield (astyle.style_default, self.attrtype())
1946 yield (astyle.style_default, "(")
2067 yield (astyle.style_default, " ")
1947 for part in xrepr(self.valuetype()):
1948 yield part
1949 yield (astyle.style_default, ") ")
1950 yield (astyle.style_default, self.name())
2068 yield (astyle.style_default, self.name())
1951 yield (astyle.style_default, " of ")
2069 yield (astyle.style_default, " of ")
1952 for part in xrepr(self.object):
2070 for part in xrepr(self.object):
@@ -1,3 +1,26 b''
1 2006-11-03 Walter Doerwald <walter@livinglogic.de>
2
3 * IPython/Extensions/ipipe.py: xrepr(), xiter() and xattrs() are now
4 generic functions (using Philip J. Eby's simplegeneric package).
5 This makes it possible to customize the display of third-party classes
6 without having to monkeypatch them. xiter() no longer supports a mode
7 argument and the XMode class has been removed. The same functionality can
8 be implemented via IterAttributeDescriptor and IterMethodDescriptor.
9 One consequence of the switch to generic functions is that xrepr() and
10 xattrs() implementation must define the default value for the mode
11 argument themselves and xattrs() implementations must return real
12 descriptors.
13
14 * IPython/external: This new subpackage will contain all third-party
15 packages that are bundled with IPython. (The first one is simplegeneric).
16
17 * IPython/Extensions/ipipe.py (ifile/ils): Readd output of the parent
18 directory which as been dropped in r1703.
19
20 * IPython/Extensions/ipipe.py (iless): Fixed.
21
22 * IPython/Extensions/ibrowse: Fixed sorting under Python 2.3.
23
1 2006-11-03 Fernando Perez <Fernando.Perez@colorado.edu>
24 2006-11-03 Fernando Perez <Fernando.Perez@colorado.edu>
2
25
3 * scripts/ipython: remove the very first entry in sys.path which
26 * scripts/ipython: remove the very first entry in sys.path which
@@ -50,7 +73,7 b''
50
73
51 2006-10-28 Fernando Perez <Fernando.Perez@colorado.edu>
74 2006-10-28 Fernando Perez <Fernando.Perez@colorado.edu>
52
75
53 * IPython/UserConfig/ipythonrc-scipy: minor clenaups to remove old
76 * IPython/UserConfig/ipythonrc-scipy: minor cleanups to remove old
54 Numeric leftovers.
77 Numeric leftovers.
55
78
56 * ipython.el (py-execute-region): apply Stefan's patch to fix
79 * ipython.el (py-execute-region): apply Stefan's patch to fix
General Comments 0
You need to be logged in to leave comments. Login now