##// END OF EJS Templates
Make isort usable without a key argument....
walter.doerwald -
Show More

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

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