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