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