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