Show More
@@ -374,6 +374,7 b' style_type_none = Style.fromstr("magenta:black")' | |||||
374 | style_type_bool = Style.fromstr("magenta:black") |
|
374 | style_type_bool = Style.fromstr("magenta:black") | |
375 | style_type_number = Style.fromstr("yellow:black") |
|
375 | style_type_number = Style.fromstr("yellow:black") | |
376 | style_type_datetime = Style.fromstr("magenta:black") |
|
376 | style_type_datetime = Style.fromstr("magenta:black") | |
|
377 | style_type_type = Style.fromstr("cyan:black") | |||
377 |
|
378 | |||
378 | # Style for URLs and file/directory names |
|
379 | # Style for URLs and file/directory names | |
379 | style_url = Style.fromstr("green:black") |
|
380 | style_url = Style.fromstr("green:black") |
@@ -97,7 +97,7 b' class _BrowserHelp(object):' | |||||
97 | else: |
|
97 | else: | |
98 | yield (astyle.style_default, repr(self)) |
|
98 | yield (astyle.style_default, repr(self)) | |
99 |
|
99 | |||
100 |
def __ |
|
100 | def __iter__(self): | |
101 | # Get reverse key mapping |
|
101 | # Get reverse key mapping | |
102 | allkeys = {} |
|
102 | allkeys = {} | |
103 | for (key, cmd) in self.browser.keymap.iteritems(): |
|
103 | for (key, cmd) in self.browser.keymap.iteritems(): | |
@@ -125,7 +125,7 b' class _BrowserHelp(object):' | |||||
125 | lines = textwrap.wrap(description, 60) |
|
125 | lines = textwrap.wrap(description, 60) | |
126 | keys = allkeys.get(name, []) |
|
126 | keys = allkeys.get(name, []) | |
127 |
|
127 | |||
128 | yield ipipe.Fields(fields, description=astyle.Text((self.style_header, name))) |
|
128 | yield ipipe.Fields(fields, key="", description=astyle.Text((self.style_header, name))) | |
129 | for i in xrange(max(len(keys), len(lines))): |
|
129 | for i in xrange(max(len(keys), len(lines))): | |
130 | try: |
|
130 | try: | |
131 | key = self.browser.keylabel(keys[i]) |
|
131 | key = self.browser.keylabel(keys[i]) | |
@@ -183,13 +183,13 b' class _BrowserLevel(object):' | |||||
183 | # Size of row number (changes when scrolling) |
|
183 | # Size of row number (changes when scrolling) | |
184 | self.numbersizex = 0 |
|
184 | self.numbersizex = 0 | |
185 |
|
185 | |||
186 |
# Attribute |
|
186 | # Attributes to display (in this order) | |
187 | self.displayattrs = [] |
|
187 | self.displayattrs = [] | |
188 |
|
188 | |||
189 |
# index and |
|
189 | # index and attribute under the cursor | |
190 | self.displayattr = (None, ipipe.noitem) |
|
190 | self.displayattr = (None, ipipe.noitem) | |
191 |
|
191 | |||
192 |
# Maps attribute |
|
192 | # Maps attributes to column widths | |
193 | self.colwidths = {} |
|
193 | self.colwidths = {} | |
194 |
|
194 | |||
195 | # Set of hidden attributes |
|
195 | # Set of hidden attributes | |
@@ -207,6 +207,13 b' class _BrowserLevel(object):' | |||||
207 | except StopIteration: |
|
207 | except StopIteration: | |
208 | self.exhausted = True |
|
208 | self.exhausted = True | |
209 | break |
|
209 | break | |
|
210 | except (KeyboardInterrupt, SystemExit): | |||
|
211 | raise | |||
|
212 | except Exception, exc: | |||
|
213 | have += 1 | |||
|
214 | self.items.append(_BrowserCachedItem(exc)) | |||
|
215 | self.exhausted = True | |||
|
216 | break | |||
210 | else: |
|
217 | else: | |
211 | have += 1 |
|
218 | have += 1 | |
212 | self.items.append(_BrowserCachedItem(item)) |
|
219 | self.items.append(_BrowserCachedItem(item)) | |
@@ -215,22 +222,23 b' class _BrowserLevel(object):' | |||||
215 | # Calculate which attributes are available from the objects that are |
|
222 | # Calculate which attributes are available from the objects that are | |
216 | # currently visible on screen (and store it in ``self.displayattrs``) |
|
223 | # currently visible on screen (and store it in ``self.displayattrs``) | |
217 |
|
224 | |||
218 |
attr |
|
225 | attrs = set() | |
219 | self.displayattrs = [] |
|
226 | self.displayattrs = [] | |
220 | if self.attrs: |
|
227 | if self.attrs: | |
221 | # If the browser object specifies a fixed list of attributes, |
|
228 | # If the browser object specifies a fixed list of attributes, | |
222 | # simply use it (removing hidden attributes). |
|
229 | # simply use it (removing hidden attributes). | |
223 |
for attr |
|
230 | for attr in self.attrs: | |
224 | if attrname not in attrnames and attrname not in self.hiddenattrs: |
|
231 | attr = ipipe.upgradexattr(attr) | |
225 | self.displayattrs.append(attrname) |
|
232 | if attr not in attrs and attr not in self.hiddenattrs: | |
226 |
|
|
233 | self.displayattrs.append(attr) | |
|
234 | attrs.add(attr) | |||
227 | else: |
|
235 | else: | |
228 | endy = min(self.datastarty+self.mainsizey, len(self.items)) |
|
236 | endy = min(self.datastarty+self.mainsizey, len(self.items)) | |
229 | for i in xrange(self.datastarty, endy): |
|
237 | for i in xrange(self.datastarty, endy): | |
230 |
for attr |
|
238 | for attr in ipipe.xattrs(self.items[i].item, "default"): | |
231 |
if attr |
|
239 | if attr not in attrs and attr not in self.hiddenattrs: | |
232 |
self.displayattrs.append(attr |
|
240 | self.displayattrs.append(attr) | |
233 |
attr |
|
241 | attrs.add(attr) | |
234 |
|
242 | |||
235 | def getrow(self, i): |
|
243 | def getrow(self, i): | |
236 | # Return a dictinary with the attributes for the object |
|
244 | # Return a dictinary with the attributes for the object | |
@@ -239,9 +247,9 b' class _BrowserLevel(object):' | |||||
239 | # called before. |
|
247 | # called before. | |
240 | row = {} |
|
248 | row = {} | |
241 | item = self.items[i].item |
|
249 | item = self.items[i].item | |
242 |
for attr |
|
250 | for attr in self.displayattrs: | |
243 | try: |
|
251 | try: | |
244 |
value = |
|
252 | value = attr.value(item) | |
245 | except (KeyboardInterrupt, SystemExit): |
|
253 | except (KeyboardInterrupt, SystemExit): | |
246 | raise |
|
254 | raise | |
247 | except Exception, exc: |
|
255 | except Exception, exc: | |
@@ -249,7 +257,7 b' class _BrowserLevel(object):' | |||||
249 | # only store attribute if it exists (or we got an exception) |
|
257 | # only store attribute if it exists (or we got an exception) | |
250 | if value is not ipipe.noitem: |
|
258 | if value is not ipipe.noitem: | |
251 | # remember alignment, length and colored text |
|
259 | # remember alignment, length and colored text | |
252 |
row[attr |
|
260 | row[attr] = ipipe.xformat(value, "cell", self.browser.maxattrlength) | |
253 | return row |
|
261 | return row | |
254 |
|
262 | |||
255 | def calcwidths(self): |
|
263 | def calcwidths(self): | |
@@ -260,16 +268,16 b' class _BrowserLevel(object):' | |||||
260 | # column names to widths. |
|
268 | # column names to widths. | |
261 | self.colwidths = {} |
|
269 | self.colwidths = {} | |
262 | for row in self.displayrows: |
|
270 | for row in self.displayrows: | |
263 |
for attr |
|
271 | for attr in self.displayattrs: | |
264 | try: |
|
272 | try: | |
265 |
length = row[attr |
|
273 | length = row[attr][1] | |
266 | except KeyError: |
|
274 | except KeyError: | |
267 | length = 0 |
|
275 | length = 0 | |
268 | # always add attribute to colwidths, even if it doesn't exist |
|
276 | # always add attribute to colwidths, even if it doesn't exist | |
269 |
if attr |
|
277 | if attr not in self.colwidths: | |
270 |
self.colwidths[attr |
|
278 | self.colwidths[attr] = len(attr.name()) | |
271 |
newwidth = max(self.colwidths[attr |
|
279 | newwidth = max(self.colwidths[attr], length) | |
272 |
self.colwidths[attr |
|
280 | self.colwidths[attr] = newwidth | |
273 |
|
281 | |||
274 | # How many characters do we need to paint the largest item number? |
|
282 | # How many characters do we need to paint the largest item number? | |
275 | self.numbersizex = len(str(self.datastarty+self.mainsizey-1)) |
|
283 | self.numbersizex = len(str(self.datastarty+self.mainsizey-1)) | |
@@ -282,11 +290,11 b' class _BrowserLevel(object):' | |||||
282 | # Find out which attribute the cursor is on and store this |
|
290 | # Find out which attribute the cursor is on and store this | |
283 | # information in ``self.displayattr``. |
|
291 | # information in ``self.displayattr``. | |
284 | pos = 0 |
|
292 | pos = 0 | |
285 |
for (i, attr |
|
293 | for (i, attr) in enumerate(self.displayattrs): | |
286 |
if pos+self.colwidths[attr |
|
294 | if pos+self.colwidths[attr] >= self.curx: | |
287 |
self.displayattr = (i, attr |
|
295 | self.displayattr = (i, attr) | |
288 | break |
|
296 | break | |
289 |
pos += self.colwidths[attr |
|
297 | pos += self.colwidths[attr]+1 | |
290 | else: |
|
298 | else: | |
291 | self.displayattr = (None, ipipe.noitem) |
|
299 | self.displayattr = (None, ipipe.noitem) | |
292 |
|
300 | |||
@@ -1030,7 +1038,7 b' class ibrowse(ipipe.Display):' | |||||
1030 | """ |
|
1038 | """ | |
1031 | 'Pick' the object under the cursor (i.e. the row the cursor is on). |
|
1039 | 'Pick' the object under the cursor (i.e. the row the cursor is on). | |
1032 | This leaves the browser and returns the picked object to the caller. |
|
1040 | This leaves the browser and returns the picked object to the caller. | |
1033 |
(In IPython this object will be available as the |
|
1041 | (In IPython this object will be available as the ``_`` variable.) | |
1034 | """ |
|
1042 | """ | |
1035 | level = self.levels[-1] |
|
1043 | level = self.levels[-1] | |
1036 | self.returnvalue = level.items[level.cury].item |
|
1044 | self.returnvalue = level.items[level.cury].item | |
@@ -1042,17 +1050,17 b' class ibrowse(ipipe.Display):' | |||||
1042 | cursor is on). |
|
1050 | cursor is on). | |
1043 | """ |
|
1051 | """ | |
1044 | level = self.levels[-1] |
|
1052 | level = self.levels[-1] | |
1045 |
attr |
|
1053 | attr = level.displayattr[1] | |
1046 |
if attr |
|
1054 | if attr is ipipe.noitem: | |
1047 | curses.beep() |
|
1055 | curses.beep() | |
1048 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1056 | self.report(CommandError("no column under cursor")) | |
1049 | return |
|
1057 | return | |
1050 |
|
|
1058 | value = attr.value(level.items[level.cury].item) | |
1051 |
if |
|
1059 | if value is ipipe.noitem: | |
1052 | curses.beep() |
|
1060 | curses.beep() | |
1053 |
self.report(AttributeError( |
|
1061 | self.report(AttributeError(attr.name())) | |
1054 | else: |
|
1062 | else: | |
1055 |
self.returnvalue = |
|
1063 | self.returnvalue = value | |
1056 | return True |
|
1064 | return True | |
1057 |
|
1065 | |||
1058 | def cmd_pickallattrs(self): |
|
1066 | def cmd_pickallattrs(self): | |
@@ -1062,16 +1070,16 b' class ibrowse(ipipe.Display):' | |||||
1062 | will be returned as a list. |
|
1070 | will be returned as a list. | |
1063 | """ |
|
1071 | """ | |
1064 | level = self.levels[-1] |
|
1072 | level = self.levels[-1] | |
1065 |
attr |
|
1073 | attr = level.displayattr[1] | |
1066 |
if attr |
|
1074 | if attr is ipipe.noitem: | |
1067 | curses.beep() |
|
1075 | curses.beep() | |
1068 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1076 | self.report(CommandError("no column under cursor")) | |
1069 | return |
|
1077 | return | |
1070 | result = [] |
|
1078 | result = [] | |
1071 | for cache in level.items: |
|
1079 | for cache in level.items: | |
1072 | attr = ipipe._getattr(cache.item, attrname) |
|
1080 | value = attr.value(cache.item) | |
1073 |
if |
|
1081 | if value is not ipipe.noitem: | |
1074 |
result.append( |
|
1082 | result.append(value) | |
1075 | self.returnvalue = result |
|
1083 | self.returnvalue = result | |
1076 | return True |
|
1084 | return True | |
1077 |
|
1085 | |||
@@ -1090,17 +1098,17 b' class ibrowse(ipipe.Display):' | |||||
1090 | """ |
|
1098 | """ | |
1091 |
|
1099 | |||
1092 | level = self.levels[-1] |
|
1100 | level = self.levels[-1] | |
1093 |
attr |
|
1101 | attr = level.displayattr[1] | |
1094 |
if attr |
|
1102 | if attr is ipipe.noitem: | |
1095 | curses.beep() |
|
1103 | curses.beep() | |
1096 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1104 | self.report(CommandError("no column under cursor")) | |
1097 | return |
|
1105 | return | |
1098 | result = [] |
|
1106 | result = [] | |
1099 | for cache in level.items: |
|
1107 | for cache in level.items: | |
1100 | if cache.marked: |
|
1108 | if cache.marked: | |
1101 |
|
|
1109 | value = attr.value(cache.item) | |
1102 |
if |
|
1110 | if value is not ipipe.noitem: | |
1103 |
result.append( |
|
1111 | result.append(value) | |
1104 | self.returnvalue = result |
|
1112 | self.returnvalue = result | |
1105 | return True |
|
1113 | return True | |
1106 |
|
1114 | |||
@@ -1130,7 +1138,7 b' class ibrowse(ipipe.Display):' | |||||
1130 | def cmd_enterdefault(self): |
|
1138 | def cmd_enterdefault(self): | |
1131 | """ |
|
1139 | """ | |
1132 | Enter the object under the cursor. (what this mean depends on the object |
|
1140 | Enter the object under the cursor. (what this mean depends on the object | |
1133 |
itself (i.e. how it implements the |
|
1141 | itself (i.e. how it implements the ``__xiter__`` method). This opens a new | |
1134 | browser 'level'. |
|
1142 | browser 'level'. | |
1135 | """ |
|
1143 | """ | |
1136 | level = self.levels[-1] |
|
1144 | level = self.levels[-1] | |
@@ -1176,10 +1184,10 b' class ibrowse(ipipe.Display):' | |||||
1176 | Enter the attribute under the cursor. |
|
1184 | Enter the attribute under the cursor. | |
1177 | """ |
|
1185 | """ | |
1178 | level = self.levels[-1] |
|
1186 | level = self.levels[-1] | |
1179 |
attr |
|
1187 | attr = level.displayattr[1] | |
1180 |
if attr |
|
1188 | if attr is ipipe.noitem: | |
1181 | curses.beep() |
|
1189 | curses.beep() | |
1182 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1190 | self.report(CommandError("no column under cursor")) | |
1183 | return |
|
1191 | return | |
1184 | try: |
|
1192 | try: | |
1185 | item = level.items[level.cury].item |
|
1193 | item = level.items[level.cury].item | |
@@ -1187,12 +1195,13 b' class ibrowse(ipipe.Display):' | |||||
1187 | self.report(CommandError("No object")) |
|
1195 | self.report(CommandError("No object")) | |
1188 | curses.beep() |
|
1196 | curses.beep() | |
1189 | else: |
|
1197 | else: | |
1190 | attr = ipipe._getattr(item, attrname) |
|
1198 | value = attr.value(item) | |
1191 |
|
|
1199 | name = attr.name() | |
1192 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1200 | if value is ipipe.noitem: | |
|
1201 | self.report(AttributeError(name)) | |||
1193 | else: |
|
1202 | else: | |
1194 |
self.report("entering object attribute %s..." % |
|
1203 | self.report("entering object attribute %s..." % name) | |
1195 |
self.enter( |
|
1204 | self.enter(value, None) | |
1196 |
|
1205 | |||
1197 | def cmd_detail(self): |
|
1206 | def cmd_detail(self): | |
1198 | """ |
|
1207 | """ | |
@@ -1209,17 +1218,18 b' class ibrowse(ipipe.Display):' | |||||
1209 | curses.beep() |
|
1218 | curses.beep() | |
1210 | else: |
|
1219 | else: | |
1211 | self.report("entering detail view for object...") |
|
1220 | self.report("entering detail view for object...") | |
1212 | self.enter(item, "detail") |
|
1221 | attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")] | |
|
1222 | self.enter(attrs, "detail") | |||
1213 |
|
1223 | |||
1214 | def cmd_detailattr(self): |
|
1224 | def cmd_detailattr(self): | |
1215 | """ |
|
1225 | """ | |
1216 | Show a detail view of the attribute under the cursor. |
|
1226 | Show a detail view of the attribute under the cursor. | |
1217 | """ |
|
1227 | """ | |
1218 | level = self.levels[-1] |
|
1228 | level = self.levels[-1] | |
1219 |
attr |
|
1229 | attr = level.displayattr[1] | |
1220 |
if attr |
|
1230 | if attr is ipipe.noitem: | |
1221 | curses.beep() |
|
1231 | curses.beep() | |
1222 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1232 | self.report(CommandError("no attribute")) | |
1223 | return |
|
1233 | return | |
1224 | try: |
|
1234 | try: | |
1225 | item = level.items[level.cury].item |
|
1235 | item = level.items[level.cury].item | |
@@ -1227,12 +1237,16 b' class ibrowse(ipipe.Display):' | |||||
1227 | self.report(CommandError("No object")) |
|
1237 | self.report(CommandError("No object")) | |
1228 | curses.beep() |
|
1238 | curses.beep() | |
1229 | else: |
|
1239 | else: | |
1230 | attr = ipipe._getattr(item, attrname) |
|
1240 | try: | |
1231 |
|
|
1241 | item = attr.value(item) | |
1232 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1242 | except (KeyboardInterrupt, SystemExit): | |
|
1243 | raise | |||
|
1244 | except Exception, exc: | |||
|
1245 | self.report(exc) | |||
1233 | else: |
|
1246 | else: | |
1234 | self.report("entering detail view for attribute...") |
|
1247 | self.report("entering detail view for attribute %s..." % attr.name()) | |
1235 | self.enter(attr, "detail") |
|
1248 | attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")] | |
|
1249 | self.enter(attrs, "detail") | |||
1236 |
|
1250 | |||
1237 | def cmd_tooglemark(self): |
|
1251 | def cmd_tooglemark(self): | |
1238 | """ |
|
1252 | """ | |
@@ -1259,15 +1273,15 b' class ibrowse(ipipe.Display):' | |||||
1259 | the cursor as the sort key. |
|
1273 | the cursor as the sort key. | |
1260 | """ |
|
1274 | """ | |
1261 | level = self.levels[-1] |
|
1275 | level = self.levels[-1] | |
1262 |
attr |
|
1276 | attr = level.displayattr[1] | |
1263 |
if attr |
|
1277 | if attr is ipipe.noitem: | |
1264 | curses.beep() |
|
1278 | curses.beep() | |
1265 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1279 | self.report(CommandError("no column under cursor")) | |
1266 | return |
|
1280 | return | |
1267 |
self.report("sort by %s (ascending)" % |
|
1281 | self.report("sort by %s (ascending)" % attr.name()) | |
1268 | def key(item): |
|
1282 | def key(item): | |
1269 | try: |
|
1283 | try: | |
1270 |
return |
|
1284 | return attr.value(item) | |
1271 | except (KeyboardInterrupt, SystemExit): |
|
1285 | except (KeyboardInterrupt, SystemExit): | |
1272 | raise |
|
1286 | raise | |
1273 | except Exception: |
|
1287 | except Exception: | |
@@ -1280,15 +1294,15 b' class ibrowse(ipipe.Display):' | |||||
1280 | the cursor as the sort key. |
|
1294 | the cursor as the sort key. | |
1281 | """ |
|
1295 | """ | |
1282 | level = self.levels[-1] |
|
1296 | level = self.levels[-1] | |
1283 |
attr |
|
1297 | attr = level.displayattr[1] | |
1284 |
if attr |
|
1298 | if attr is ipipe.noitem: | |
1285 | curses.beep() |
|
1299 | curses.beep() | |
1286 | self.report(AttributeError(ipipe._attrname(attrname))) |
|
1300 | self.report(CommandError("no column under cursor")) | |
1287 | return |
|
1301 | return | |
1288 |
self.report("sort by %s (descending)" % |
|
1302 | self.report("sort by %s (descending)" % attr.name()) | |
1289 | def key(item): |
|
1303 | def key(item): | |
1290 | try: |
|
1304 | try: | |
1291 |
return |
|
1305 | return attr.value(item) | |
1292 | except (KeyboardInterrupt, SystemExit): |
|
1306 | except (KeyboardInterrupt, SystemExit): | |
1293 | raise |
|
1307 | raise | |
1294 | except Exception: |
|
1308 | except Exception: | |
@@ -1427,11 +1441,11 b' class ibrowse(ipipe.Display):' | |||||
1427 | scr.addstr(self.headersepchar, self.getstyle(self.style_colheadersep)) |
|
1441 | scr.addstr(self.headersepchar, self.getstyle(self.style_colheadersep)) | |
1428 | begx = level.numbersizex+3 |
|
1442 | begx = level.numbersizex+3 | |
1429 | posx = begx-level.datastartx |
|
1443 | posx = begx-level.datastartx | |
1430 |
for attr |
|
1444 | for attr in level.displayattrs: | |
1431 |
|
|
1445 | attrname = attr.name() | |
1432 |
cwidth = level.colwidths[attr |
|
1446 | cwidth = level.colwidths[attr] | |
1433 |
header = |
|
1447 | header = attrname.ljust(cwidth) | |
1434 |
if attr |
|
1448 | if attr is level.displayattr[1]: | |
1435 | style = self.style_colheaderhere |
|
1449 | style = self.style_colheaderhere | |
1436 | else: |
|
1450 | else: | |
1437 | style = self.style_colheader |
|
1451 | style = self.style_colheader | |
@@ -1527,19 +1541,19 b' class ibrowse(ipipe.Display):' | |||||
1527 | break |
|
1541 | break | |
1528 |
|
1542 | |||
1529 | attrstyle = [(astyle.style_default, "no attribute")] |
|
1543 | attrstyle = [(astyle.style_default, "no attribute")] | |
1530 |
attr |
|
1544 | attr = level.displayattr[1] | |
1531 |
if attr |
|
1545 | if attr is not ipipe.noitem and not isinstance(attr, ipipe.SelfDescriptor): | |
1532 | posx += self.addstr(posy, posx, 0, endx, " | ", self.style_footer) |
|
1546 | posx += self.addstr(posy, posx, 0, endx, " | ", self.style_footer) | |
1533 |
posx += self.addstr(posy, posx, 0, endx, |
|
1547 | posx += self.addstr(posy, posx, 0, endx, attr.name(), self.style_footer) | |
1534 | posx += self.addstr(posy, posx, 0, endx, ": ", self.style_footer) |
|
1548 | posx += self.addstr(posy, posx, 0, endx, ": ", self.style_footer) | |
1535 | try: |
|
1549 | try: | |
1536 |
|
|
1550 | value = attr.value(item) | |
1537 | except (SystemExit, KeyboardInterrupt): |
|
1551 | except (SystemExit, KeyboardInterrupt): | |
1538 | raise |
|
1552 | raise | |
1539 | except Exception, exc: |
|
1553 | except Exception, exc: | |
1540 | attr = exc |
|
1554 | attr = exc | |
1541 |
if |
|
1555 | if value is not ipipe.noitem: | |
1542 |
attrstyle = ipipe.xrepr( |
|
1556 | attrstyle = ipipe.xrepr(value, "footer") | |
1543 | for (nostyle, text) in attrstyle: |
|
1557 | for (nostyle, text) in attrstyle: | |
1544 | if not isinstance(nostyle, int): |
|
1558 | if not isinstance(nostyle, int): | |
1545 | posx += self.addstr(posy, posx, 0, endx, text, self.style_footer) |
|
1559 | posx += self.addstr(posy, posx, 0, endx, text, self.style_footer) |
This diff has been collapsed as it changes many lines, (592 lines changed) Show them Hide them | |||||
@@ -269,6 +269,251 b' def getglobals(g):' | |||||
269 | return g |
|
269 | return g | |
270 |
|
270 | |||
271 |
|
271 | |||
|
272 | class Descriptor(object): | |||
|
273 | def __hash__(self): | |||
|
274 | return hash(self.__class__) ^ hash(self.key()) | |||
|
275 | ||||
|
276 | def __eq__(self, other): | |||
|
277 | return self.__class__ is other.__class__ and self.key() == other.key() | |||
|
278 | ||||
|
279 | def __ne__(self, other): | |||
|
280 | return self.__class__ is not other.__class__ or self.key() != other.key() | |||
|
281 | ||||
|
282 | def key(self): | |||
|
283 | pass | |||
|
284 | ||||
|
285 | def name(self): | |||
|
286 | key = self.key() | |||
|
287 | if key is None: | |||
|
288 | return "_" | |||
|
289 | return str(key) | |||
|
290 | ||||
|
291 | def attrtype(self, obj): | |||
|
292 | pass | |||
|
293 | ||||
|
294 | def valuetype(self, obj): | |||
|
295 | pass | |||
|
296 | ||||
|
297 | def value(self, obj): | |||
|
298 | pass | |||
|
299 | ||||
|
300 | def doc(self, obj): | |||
|
301 | pass | |||
|
302 | ||||
|
303 | def shortdoc(self, obj): | |||
|
304 | doc = self.doc(obj) | |||
|
305 | if doc is not None: | |||
|
306 | doc = doc.strip().splitlines()[0].strip() | |||
|
307 | return doc | |||
|
308 | ||||
|
309 | def iter(self, obj): | |||
|
310 | return xiter(self.value(obj)) | |||
|
311 | ||||
|
312 | ||||
|
313 | class SelfDescriptor(Descriptor): | |||
|
314 | def key(self): | |||
|
315 | return None | |||
|
316 | ||||
|
317 | def attrtype(self, obj): | |||
|
318 | return "self" | |||
|
319 | ||||
|
320 | def valuetype(self, obj): | |||
|
321 | return type(obj) | |||
|
322 | ||||
|
323 | def value(self, obj): | |||
|
324 | return obj | |||
|
325 | ||||
|
326 | def __repr__(self): | |||
|
327 | return "Self" | |||
|
328 | ||||
|
329 | selfdescriptor = SelfDescriptor() # there's no need for more than one | |||
|
330 | ||||
|
331 | ||||
|
332 | class AttributeDescriptor(Descriptor): | |||
|
333 | __slots__ = ("_name", "_doc") | |||
|
334 | ||||
|
335 | def __init__(self, name, doc=None): | |||
|
336 | self._name = name | |||
|
337 | self._doc = doc | |||
|
338 | ||||
|
339 | def key(self): | |||
|
340 | return self._name | |||
|
341 | ||||
|
342 | def doc(self, obj): | |||
|
343 | return self._doc | |||
|
344 | ||||
|
345 | def attrtype(self, obj): | |||
|
346 | return "attr" | |||
|
347 | ||||
|
348 | def valuetype(self, obj): | |||
|
349 | return type(getattr(obj, self._name)) | |||
|
350 | ||||
|
351 | def value(self, obj): | |||
|
352 | return getattr(obj, self._name) | |||
|
353 | ||||
|
354 | def __repr__(self): | |||
|
355 | if self._doc is None: | |||
|
356 | return "Attribute(%r)" % self._name | |||
|
357 | else: | |||
|
358 | return "Attribute(%r, %r)" % (self._name, self._doc) | |||
|
359 | ||||
|
360 | ||||
|
361 | class IndexDescriptor(Descriptor): | |||
|
362 | __slots__ = ("_index",) | |||
|
363 | ||||
|
364 | def __init__(self, index): | |||
|
365 | self._index = index | |||
|
366 | ||||
|
367 | def key(self): | |||
|
368 | return self._index | |||
|
369 | ||||
|
370 | def attrtype(self, obj): | |||
|
371 | return "item" | |||
|
372 | ||||
|
373 | def valuetype(self, obj): | |||
|
374 | return type(obj[self._index]) | |||
|
375 | ||||
|
376 | def value(self, obj): | |||
|
377 | return obj[self._index] | |||
|
378 | ||||
|
379 | def __repr__(self): | |||
|
380 | return "Index(%r)" % self._index | |||
|
381 | ||||
|
382 | ||||
|
383 | class MethodDescriptor(Descriptor): | |||
|
384 | __slots__ = ("_name", "_doc") | |||
|
385 | ||||
|
386 | def __init__(self, name, doc=None): | |||
|
387 | self._name = name | |||
|
388 | self._doc = doc | |||
|
389 | ||||
|
390 | def key(self): | |||
|
391 | return self._name | |||
|
392 | ||||
|
393 | def doc(self, obj): | |||
|
394 | if self._doc is None: | |||
|
395 | return getattr(obj, self._name).__doc__ | |||
|
396 | return self._doc | |||
|
397 | ||||
|
398 | def attrtype(self, obj): | |||
|
399 | return "method" | |||
|
400 | ||||
|
401 | def valuetype(self, obj): | |||
|
402 | return type(self.value(obj)) | |||
|
403 | ||||
|
404 | def value(self, obj): | |||
|
405 | return getattr(obj, self._name)() | |||
|
406 | ||||
|
407 | def __repr__(self): | |||
|
408 | if self._doc is None: | |||
|
409 | return "Method(%r)" % self._name | |||
|
410 | else: | |||
|
411 | return "Method(%r, %r)" % (self._name, self._doc) | |||
|
412 | ||||
|
413 | ||||
|
414 | class IterAttributeDescriptor(Descriptor): | |||
|
415 | __slots__ = ("_name", "_doc") | |||
|
416 | ||||
|
417 | def __init__(self, name, doc=None): | |||
|
418 | self._name = name | |||
|
419 | self._doc = doc | |||
|
420 | ||||
|
421 | def key(self): | |||
|
422 | return self._name | |||
|
423 | ||||
|
424 | def doc(self, obj): | |||
|
425 | return self._doc | |||
|
426 | ||||
|
427 | def attrtype(self, obj): | |||
|
428 | return "iter" | |||
|
429 | ||||
|
430 | def valuetype(self, obj): | |||
|
431 | return noitem | |||
|
432 | ||||
|
433 | def value(self, obj): | |||
|
434 | return noitem | |||
|
435 | ||||
|
436 | def iter(self, obj): | |||
|
437 | return xiter(getattr(obj, self._name)) | |||
|
438 | ||||
|
439 | def __repr__(self): | |||
|
440 | if self._doc is None: | |||
|
441 | return "IterAttribute(%r)" % self._name | |||
|
442 | else: | |||
|
443 | return "IterAttribute(%r, %r)" % (self._name, self._doc) | |||
|
444 | ||||
|
445 | ||||
|
446 | class IterMethodDescriptor(Descriptor): | |||
|
447 | __slots__ = ("_name", "_doc") | |||
|
448 | ||||
|
449 | def __init__(self, name, doc=None): | |||
|
450 | self._name = name | |||
|
451 | self._doc = doc | |||
|
452 | ||||
|
453 | def key(self): | |||
|
454 | return self._name | |||
|
455 | ||||
|
456 | def doc(self, obj): | |||
|
457 | if self._doc is None: | |||
|
458 | return getattr(obj, self._name).__doc__ | |||
|
459 | return self._doc | |||
|
460 | ||||
|
461 | def attrtype(self, obj): | |||
|
462 | return "itermethod" | |||
|
463 | ||||
|
464 | def valuetype(self, obj): | |||
|
465 | return noitem | |||
|
466 | ||||
|
467 | def value(self, obj): | |||
|
468 | return noitem | |||
|
469 | ||||
|
470 | def iter(self, obj): | |||
|
471 | return xiter(getattr(obj, self._name)()) | |||
|
472 | ||||
|
473 | def __repr__(self): | |||
|
474 | if self._doc is None: | |||
|
475 | return "IterMethod(%r)" % self._name | |||
|
476 | else: | |||
|
477 | return "IterMethod(%r, %r)" % (self._name, self._doc) | |||
|
478 | ||||
|
479 | ||||
|
480 | class FunctionDescriptor(Descriptor): | |||
|
481 | __slots__ = ("_function", "_name", "_doc") | |||
|
482 | ||||
|
483 | def __init__(self, function, name=None, doc=None): | |||
|
484 | self._function = function | |||
|
485 | self._name = name | |||
|
486 | self._doc = doc | |||
|
487 | ||||
|
488 | def key(self): | |||
|
489 | return self._function | |||
|
490 | ||||
|
491 | def name(self): | |||
|
492 | if self._name is not None: | |||
|
493 | return self._name | |||
|
494 | return getattr(self._function, "__xname__", self._function.__name__) | |||
|
495 | ||||
|
496 | def doc(self, obj): | |||
|
497 | if self._doc is None: | |||
|
498 | return self._function.__doc__ | |||
|
499 | return self._doc | |||
|
500 | ||||
|
501 | def attrtype(self, obj): | |||
|
502 | return "function" | |||
|
503 | ||||
|
504 | def valuetype(self, obj): | |||
|
505 | return type(self._function(obj)) | |||
|
506 | ||||
|
507 | def value(self, obj): | |||
|
508 | return self._function(obj) | |||
|
509 | ||||
|
510 | def __repr__(self): | |||
|
511 | if self._doc is None: | |||
|
512 | return "Function(%r)" % self._name | |||
|
513 | else: | |||
|
514 | return "Function(%r, %r)" % (self._name, self._doc) | |||
|
515 | ||||
|
516 | ||||
272 | class Table(object): |
|
517 | class Table(object): | |
273 | """ |
|
518 | """ | |
274 | A ``Table`` is an object that produces items (just like a normal Python |
|
519 | A ``Table`` is an object that produces items (just like a normal Python | |
@@ -350,47 +595,7 b' class Pipe(Table):' | |||||
350 | return self |
|
595 | return self | |
351 |
|
596 | |||
352 |
|
597 | |||
353 | def _getattr(obj, name, default=noitem): |
|
598 | def xrepr(item, mode="default"): | |
354 | """ |
|
|||
355 | Internal helper for getting an attribute of an item. If ``name`` is ``None`` |
|
|||
356 | return the object itself. If ``name`` is an integer, use ``__getitem__`` |
|
|||
357 | instead. If the attribute or item does not exist, return ``default``. |
|
|||
358 | """ |
|
|||
359 | if name is None: |
|
|||
360 | return obj |
|
|||
361 | elif isinstance(name, basestring): |
|
|||
362 | if name.endswith("()"): |
|
|||
363 | return getattr(obj, name[:-2], default)() |
|
|||
364 | else: |
|
|||
365 | return getattr(obj, name, default) |
|
|||
366 | elif callable(name): |
|
|||
367 | try: |
|
|||
368 | return name(obj) |
|
|||
369 | except AttributeError: |
|
|||
370 | return default |
|
|||
371 | else: |
|
|||
372 | try: |
|
|||
373 | return obj[name] |
|
|||
374 | except IndexError: |
|
|||
375 | return default |
|
|||
376 |
|
||||
377 |
|
||||
378 | def _attrname(name): |
|
|||
379 | """ |
|
|||
380 | Internal helper that gives a proper name for the attribute ``name`` |
|
|||
381 | (which might be ``None`` or an ``int``). |
|
|||
382 | """ |
|
|||
383 | if name is None: |
|
|||
384 | return "_" |
|
|||
385 | elif isinstance(name, basestring): |
|
|||
386 | return name |
|
|||
387 | elif callable(name): |
|
|||
388 | return getattr(name, "__xname__", name.__name__) |
|
|||
389 | else: |
|
|||
390 | return str(name) |
|
|||
391 |
|
||||
392 |
|
||||
393 | def xrepr(item, mode): |
|
|||
394 | try: |
|
599 | try: | |
395 | func = item.__xrepr__ |
|
600 | func = item.__xrepr__ | |
396 | except AttributeError: |
|
601 | except AttributeError: | |
@@ -449,6 +654,11 b' def xrepr(item, mode):' | |||||
449 | yield (astyle.style_type_datetime, repr(item)) |
|
654 | yield (astyle.style_type_datetime, repr(item)) | |
450 | elif isinstance(item, datetime.timedelta): |
|
655 | elif isinstance(item, datetime.timedelta): | |
451 | yield (astyle.style_type_datetime, repr(item)) |
|
656 | yield (astyle.style_type_datetime, repr(item)) | |
|
657 | elif isinstance(item, type): | |||
|
658 | if item.__module__ == "__builtin__": | |||
|
659 | yield (astyle.style_type_type, item.__name__) | |||
|
660 | else: | |||
|
661 | yield (astyle.style_type_type, "%s.%s" % (item.__module__, item.__name__)) | |||
452 | elif isinstance(item, Exception): |
|
662 | elif isinstance(item, Exception): | |
453 | if item.__class__.__module__ == "exceptions": |
|
663 | if item.__class__.__module__ == "exceptions": | |
454 | classname = item.__class__.__name__ |
|
664 | classname = item.__class__.__name__ | |
@@ -514,33 +724,67 b' def xrepr(item, mode):' | |||||
514 | yield (astyle.style_default, repr(item)) |
|
724 | yield (astyle.style_default, repr(item)) | |
515 |
|
725 | |||
516 |
|
726 | |||
517 | def xattrs(item, mode): |
|
727 | def upgradexattr(attr): | |
|
728 | if attr is None: | |||
|
729 | return selfdescriptor | |||
|
730 | elif isinstance(attr, Descriptor): | |||
|
731 | return attr | |||
|
732 | elif isinstance(attr, str): | |||
|
733 | if attr.endswith("()"): | |||
|
734 | if attr.startswith("-"): | |||
|
735 | return IterMethodDescriptor(attr[1:-2]) | |||
|
736 | else: | |||
|
737 | return MethodDescriptor(attr[:-2]) | |||
|
738 | else: | |||
|
739 | if attr.startswith("-"): | |||
|
740 | return IterAttributeDescriptor(attr[1:]) | |||
|
741 | else: | |||
|
742 | return AttributeDescriptor(attr) | |||
|
743 | elif isinstance(attr, (int, long)): | |||
|
744 | return IndexDescriptor(attr) | |||
|
745 | elif callable(attr): | |||
|
746 | return FunctionDescriptor(attr) | |||
|
747 | else: | |||
|
748 | raise TypeError("can't handle descriptor %r" % attr) | |||
|
749 | ||||
|
750 | ||||
|
751 | def xattrs(item, mode="default"): | |||
518 | try: |
|
752 | try: | |
519 | func = item.__xattrs__ |
|
753 | func = item.__xattrs__ | |
520 | except AttributeError: |
|
754 | except AttributeError: | |
521 | if mode == "detail": |
|
755 | if mode == "detail": | |
522 |
|
|
756 | for attrname in dir(item): | |
|
757 | yield AttributeDescriptor(attrname) | |||
523 | else: |
|
758 | else: | |
524 | return (None,) |
|
759 | yield selfdescriptor | |
525 | else: |
|
760 | else: | |
|
761 | for attr in func(mode): | |||
|
762 | yield upgradexattr(attr) | |||
|
763 | ||||
|
764 | ||||
|
765 | def _isdict(item): | |||
526 |
|
|
766 | try: | |
527 | return func(mode) |
|
767 | itermeth = item.__class__.__iter__ | |
528 | except (KeyboardInterrupt, SystemExit): |
|
768 | except (AttributeError, TypeError): | |
529 |
|
|
769 | return False | |
530 | except Exception: |
|
770 | return itermeth is dict.__iter__ or itermeth is types.DictProxyType.__iter__ | |
531 | return (None,) |
|
|||
532 |
|
771 | |||
533 |
|
772 | |||
534 |
def |
|
773 | def _isstr(item): | |
535 | if mode == "detail": |
|
774 | if not isinstance(item, basestring): | |
536 | def items(): |
|
775 | return False | |
537 | for name in xattrs(item, mode): |
|
776 | try: | |
538 | yield XAttr(item, name) |
|
777 | itermeth = item.__class__.__iter__ | |
539 | return items() |
|
778 | except AttributeError: | |
|
779 | return True | |||
|
780 | return False # ``__iter__`` has been redefined | |||
|
781 | ||||
|
782 | ||||
|
783 | def xiter(item, mode="default"): | |||
540 | try: |
|
784 | try: | |
541 | func = item.__xiter__ |
|
785 | func = item.__xiter__ | |
542 | except AttributeError: |
|
786 | except AttributeError: | |
543 | if isinstance(item, (dict, types.DictProxyType)): |
|
787 | if _isdict(item): | |
544 | def items(item): |
|
788 | def items(item): | |
545 | fields = ("key", "value") |
|
789 | fields = ("key", "value") | |
546 | for (key, value) in item.iteritems(): |
|
790 | for (key, value) in item.iteritems(): | |
@@ -552,8 +796,8 b' def xiter(item, mode):' | |||||
552 | for key in sorted(item.__dict__): |
|
796 | for key in sorted(item.__dict__): | |
553 | yield Fields(fields, key=key, value=getattr(item, key)) |
|
797 | yield Fields(fields, key=key, value=getattr(item, key)) | |
554 | return items(item) |
|
798 | return items(item) | |
555 |
elif |
|
799 | elif _isstr(item): | |
556 |
if not |
|
800 | if not item: | |
557 | raise ValueError("can't enter empty string") |
|
801 | raise ValueError("can't enter empty string") | |
558 | lines = item.splitlines() |
|
802 | lines = item.splitlines() | |
559 | if len(lines) <= 1: |
|
803 | if len(lines) <= 1: | |
@@ -572,7 +816,7 b' class ichain(Pipe):' | |||||
572 | def __init__(self, *iters): |
|
816 | def __init__(self, *iters): | |
573 | self.iters = iters |
|
817 | self.iters = iters | |
574 |
|
818 | |||
575 |
def __ |
|
819 | def __iter__(self): | |
576 | return itertools.chain(*self.iters) |
|
820 | return itertools.chain(*self.iters) | |
577 |
|
821 | |||
578 | def __xrepr__(self, mode): |
|
822 | def __xrepr__(self, mode): | |
@@ -823,30 +1067,61 b' class ifile(path.path):' | |||||
823 | return datetime.datetime.utcfromtimestamp(self.mtime) |
|
1067 | return datetime.datetime.utcfromtimestamp(self.mtime) | |
824 | mdate = property(getmdate, None, None, "Modification date") |
|
1068 | mdate = property(getmdate, None, None, "Modification date") | |
825 |
|
1069 | |||
826 |
def |
|
1070 | def mimetype(self): | |
|
1071 | """ | |||
|
1072 | Return MIME type guessed from the extension. | |||
|
1073 | """ | |||
827 | return mimetypes.guess_type(self.basename())[0] |
|
1074 | return mimetypes.guess_type(self.basename())[0] | |
828 | mimetype = property(getmimetype, None, None, "MIME type") |
|
|||
829 |
|
1075 | |||
830 |
def |
|
1076 | def encoding(self): | |
|
1077 | """ | |||
|
1078 | Return guessed compression (like "compress" or "gzip"). | |||
|
1079 | """ | |||
831 | return mimetypes.guess_type(self.basename())[1] |
|
1080 | return mimetypes.guess_type(self.basename())[1] | |
832 | encoding = property(getencoding, None, None, "Compression") |
|
|||
833 |
|
1081 | |||
834 | def __repr__(self): |
|
1082 | def __repr__(self): | |
835 | return "ifile(%s)" % path._base.__repr__(self) |
|
1083 | return "ifile(%s)" % path._base.__repr__(self) | |
836 |
|
1084 | |||
837 | defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate") |
|
|||
838 |
|
||||
839 | def __xattrs__(self, mode): |
|
1085 | def __xattrs__(self, mode): | |
840 | if mode == "detail": |
|
1086 | if mode == "detail": | |
841 | return ( |
|
1087 | return ( | |
842 | "name", "basename()", "abspath()", "realpath()", |
|
1088 | "name", | |
843 | "type", "mode", "modestr", "stat()", "lstat()", |
|
1089 | "basename()", | |
844 | "uid", "gid", "owner", "group", "dev", "nlink", |
|
1090 | "abspath()", | |
845 | "ctime", "mtime", "atime", "cdate", "mdate", "adate", |
|
1091 | "realpath()", | |
846 | "size", "blocks", "blksize", "isdir()", "islink()", |
|
1092 | "type", | |
847 |
"m |
|
1093 | "mode", | |
|
1094 | "modestr", | |||
|
1095 | "stat()", | |||
|
1096 | "lstat()", | |||
|
1097 | "uid", | |||
|
1098 | "gid", | |||
|
1099 | "owner", | |||
|
1100 | "group", | |||
|
1101 | "dev", | |||
|
1102 | "nlink", | |||
|
1103 | "ctime", | |||
|
1104 | "mtime", | |||
|
1105 | "atime", | |||
|
1106 | "cdate", | |||
|
1107 | "mdate", | |||
|
1108 | "adate", | |||
|
1109 | "size", | |||
|
1110 | "blocks", | |||
|
1111 | "blksize", | |||
|
1112 | "isdir()", | |||
|
1113 | "islink()", | |||
|
1114 | "mimetype()", | |||
|
1115 | "encoding()", | |||
|
1116 | "-listdir()", | |||
|
1117 | "-dirs()", | |||
|
1118 | "-files()", | |||
|
1119 | "-walk()", | |||
|
1120 | "-walkdirs()", | |||
|
1121 | "-walkfiles()", | |||
848 | ) |
|
1122 | ) | |
849 | return self.defaultattrs |
|
1123 | else: | |
|
1124 | return (None, "type", "size", "modestr", "owner", "group", "mdate") | |||
850 |
|
1125 | |||
851 | def __xrepr__(self, mode): |
|
1126 | def __xrepr__(self, mode): | |
852 | try: |
|
1127 | try: | |
@@ -872,7 +1147,7 b' class ifile(path.path):' | |||||
872 | else: |
|
1147 | else: | |
873 | yield (style, repr(self)) |
|
1148 | yield (style, repr(self)) | |
874 |
|
1149 | |||
875 |
def __ |
|
1150 | def __iter__(self): | |
876 | if self.isdir(): |
|
1151 | if self.isdir(): | |
877 | yield iparentdir(self / os.pardir) |
|
1152 | yield iparentdir(self / os.pardir) | |
878 | for child in sorted(self.listdir()): |
|
1153 | for child in sorted(self.listdir()): | |
@@ -906,8 +1181,8 b' class ils(Table):' | |||||
906 | def __init__(self, base=os.curdir): |
|
1181 | def __init__(self, base=os.curdir): | |
907 | self.base = os.path.expanduser(base) |
|
1182 | self.base = os.path.expanduser(base) | |
908 |
|
1183 | |||
909 |
def __ |
|
1184 | def __iter__(self): | |
910 |
return xiter(ifile(self.base) |
|
1185 | return xiter(ifile(self.base)) | |
911 |
|
1186 | |||
912 | def __xrepr__(self, mode): |
|
1187 | def __xrepr__(self, mode): | |
913 | return ifile(self.base).__xrepr__(mode) |
|
1188 | return ifile(self.base).__xrepr__(mode) | |
@@ -929,7 +1204,7 b' class iglob(Table):' | |||||
929 | def __init__(self, glob): |
|
1204 | def __init__(self, glob): | |
930 | self.glob = glob |
|
1205 | self.glob = glob | |
931 |
|
1206 | |||
932 |
def __ |
|
1207 | def __iter__(self): | |
933 | for name in glob.glob(self.glob): |
|
1208 | for name in glob.glob(self.glob): | |
934 | yield ifile(name) |
|
1209 | yield ifile(name) | |
935 |
|
1210 | |||
@@ -958,7 +1233,7 b' class iwalk(Table):' | |||||
958 | self.dirs = dirs |
|
1233 | self.dirs = dirs | |
959 | self.files = files |
|
1234 | self.files = files | |
960 |
|
1235 | |||
961 |
def __ |
|
1236 | def __iter__(self): | |
962 | for (dirpath, dirnames, filenames) in os.walk(self.base): |
|
1237 | for (dirpath, dirnames, filenames) in os.walk(self.base): | |
963 | if self.dirs: |
|
1238 | if self.dirs: | |
964 | for name in sorted(dirnames): |
|
1239 | for name in sorted(dirnames): | |
@@ -1115,7 +1390,7 b' class igrpentry(object):' | |||||
1115 | else: |
|
1390 | else: | |
1116 | yield (astyle.style_default, repr(self)) |
|
1391 | yield (astyle.style_default, repr(self)) | |
1117 |
|
1392 | |||
1118 |
def __ |
|
1393 | def __iter__(self): | |
1119 | for member in self.mem: |
|
1394 | for member in self.mem: | |
1120 | yield ipwdentry(member) |
|
1395 | yield ipwdentry(member) | |
1121 |
|
1396 | |||
@@ -1128,7 +1403,7 b' class igrp(Table):' | |||||
1128 | """ |
|
1403 | """ | |
1129 | This ``Table`` lists all entries in the Unix group database. |
|
1404 | This ``Table`` lists all entries in the Unix group database. | |
1130 | """ |
|
1405 | """ | |
1131 |
def __ |
|
1406 | def __iter__(self): | |
1132 | for entry in grp.getgrall(): |
|
1407 | for entry in grp.getgrall(): | |
1133 | yield igrpentry(entry.gr_name) |
|
1408 | yield igrpentry(entry.gr_name) | |
1134 |
|
1409 | |||
@@ -1141,7 +1416,7 b' class igrp(Table):' | |||||
1141 |
|
1416 | |||
1142 | class Fields(object): |
|
1417 | class Fields(object): | |
1143 | def __init__(self, fieldnames, **fields): |
|
1418 | def __init__(self, fieldnames, **fields): | |
1144 | self.__fieldnames = fieldnames |
|
1419 | self.__fieldnames = [upgradexattr(fieldname) for fieldname in fieldnames] | |
1145 | for (key, value) in fields.iteritems(): |
|
1420 | for (key, value) in fields.iteritems(): | |
1146 | setattr(self, key, value) |
|
1421 | setattr(self, key, value) | |
1147 |
|
1422 | |||
@@ -1156,7 +1431,7 b' class Fields(object):' | |||||
1156 | for (i, f) in enumerate(self.__fieldnames): |
|
1431 | for (i, f) in enumerate(self.__fieldnames): | |
1157 | if i: |
|
1432 | if i: | |
1158 | yield (astyle.style_default, ", ") |
|
1433 | yield (astyle.style_default, ", ") | |
1159 | yield (astyle.style_default, f) |
|
1434 | yield (astyle.style_default, f.name()) | |
1160 | yield (astyle.style_default, "=") |
|
1435 | yield (astyle.style_default, "=") | |
1161 | for part in xrepr(getattr(self, f), "default"): |
|
1436 | for part in xrepr(getattr(self, f), "default"): | |
1162 | yield part |
|
1437 | yield part | |
@@ -1167,7 +1442,7 b' class Fields(object):' | |||||
1167 | for (i, f) in enumerate(self.__fieldnames): |
|
1442 | for (i, f) in enumerate(self.__fieldnames): | |
1168 | if i: |
|
1443 | if i: | |
1169 | yield (astyle.style_default, ", ") |
|
1444 | yield (astyle.style_default, ", ") | |
1170 | yield (astyle.style_default, f) |
|
1445 | yield (astyle.style_default, f.name()) | |
1171 | yield (astyle.style_default, ")") |
|
1446 | yield (astyle.style_default, ")") | |
1172 | else: |
|
1447 | else: | |
1173 | yield (astyle.style_default, repr(self)) |
|
1448 | yield (astyle.style_default, repr(self)) | |
@@ -1182,9 +1457,6 b' class FieldTable(Table, list):' | |||||
1182 | def add(self, **fields): |
|
1457 | def add(self, **fields): | |
1183 | self.append(Fields(self.fields, **fields)) |
|
1458 | self.append(Fields(self.fields, **fields)) | |
1184 |
|
1459 | |||
1185 | def __xiter__(self, mode): |
|
|||
1186 | return list.__iter__(self) |
|
|||
1187 |
|
||||
1188 | def __xrepr__(self, mode): |
|
1460 | def __xrepr__(self, mode): | |
1189 | yield (-1, False) |
|
1461 | yield (-1, False) | |
1190 | if mode == "header" or mode == "footer": |
|
1462 | if mode == "header" or mode == "footer": | |
@@ -1232,7 +1504,7 b' class ienv(Table):' | |||||
1232 | >>> ienv |
|
1504 | >>> ienv | |
1233 | """ |
|
1505 | """ | |
1234 |
|
1506 | |||
1235 |
def __ |
|
1507 | def __iter__(self): | |
1236 | fields = ("key", "value") |
|
1508 | fields = ("key", "value") | |
1237 | for (key, value) in os.environ.iteritems(): |
|
1509 | for (key, value) in os.environ.iteritems(): | |
1238 | yield Fields(fields, key=key, value=value) |
|
1510 | yield Fields(fields, key=key, value=value) | |
@@ -1256,7 +1528,7 b' class icsv(Pipe):' | |||||
1256 | """ |
|
1528 | """ | |
1257 | self.csvargs = csvargs |
|
1529 | self.csvargs = csvargs | |
1258 |
|
1530 | |||
1259 |
def __ |
|
1531 | def __iter__(self): | |
1260 | input = self.input |
|
1532 | input = self.input | |
1261 | if isinstance(input, ifile): |
|
1533 | if isinstance(input, ifile): | |
1262 | input = input.open("rb") |
|
1534 | input = input.open("rb") | |
@@ -1304,7 +1576,7 b' class ix(Table):' | |||||
1304 | self.cmd = cmd |
|
1576 | self.cmd = cmd | |
1305 | self._pipeout = None |
|
1577 | self._pipeout = None | |
1306 |
|
1578 | |||
1307 |
def __ |
|
1579 | def __iter__(self): | |
1308 | (_pipein, self._pipeout) = os.popen4(self.cmd) |
|
1580 | (_pipein, self._pipeout) = os.popen4(self.cmd) | |
1309 | _pipein.close() |
|
1581 | _pipein.close() | |
1310 | for l in self._pipeout: |
|
1582 | for l in self._pipeout: | |
@@ -1364,7 +1636,7 b' class ifilter(Pipe):' | |||||
1364 | self.globals = globals |
|
1636 | self.globals = globals | |
1365 | self.errors = errors |
|
1637 | self.errors = errors | |
1366 |
|
1638 | |||
1367 |
def __ |
|
1639 | def __iter__(self): | |
1368 | if callable(self.expr): |
|
1640 | if callable(self.expr): | |
1369 | test = self.expr |
|
1641 | test = self.expr | |
1370 | else: |
|
1642 | else: | |
@@ -1375,7 +1647,7 b' class ifilter(Pipe):' | |||||
1375 |
|
1647 | |||
1376 | ok = 0 |
|
1648 | ok = 0 | |
1377 | exc_info = None |
|
1649 | exc_info = None | |
1378 |
for item in xiter(self.input |
|
1650 | for item in xiter(self.input): | |
1379 | try: |
|
1651 | try: | |
1380 | if test(item): |
|
1652 | if test(item): | |
1381 | yield item |
|
1653 | yield item | |
@@ -1437,7 +1709,7 b' class ieval(Pipe):' | |||||
1437 | self.globals = globals |
|
1709 | self.globals = globals | |
1438 | self.errors = errors |
|
1710 | self.errors = errors | |
1439 |
|
1711 | |||
1440 |
def __ |
|
1712 | def __iter__(self): | |
1441 | if callable(self.expr): |
|
1713 | if callable(self.expr): | |
1442 | do = self.expr |
|
1714 | do = self.expr | |
1443 | else: |
|
1715 | else: | |
@@ -1448,7 +1720,7 b' class ieval(Pipe):' | |||||
1448 |
|
1720 | |||
1449 | ok = 0 |
|
1721 | ok = 0 | |
1450 | exc_info = None |
|
1722 | exc_info = None | |
1451 |
for item in xiter(self.input |
|
1723 | for item in xiter(self.input): | |
1452 | try: |
|
1724 | try: | |
1453 | yield do(item) |
|
1725 | yield do(item) | |
1454 | except (KeyboardInterrupt, SystemExit): |
|
1726 | except (KeyboardInterrupt, SystemExit): | |
@@ -1497,9 +1769,9 b' class ienum(Pipe):' | |||||
1497 |
|
1769 | |||
1498 | >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object") |
|
1770 | >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object") | |
1499 | """ |
|
1771 | """ | |
1500 |
def __ |
|
1772 | def __iter__(self): | |
1501 | fields = ("index", "object") |
|
1773 | fields = ("index", "object") | |
1502 |
for (index, object) in enumerate(xiter(self.input |
|
1774 | for (index, object) in enumerate(xiter(self.input)): | |
1503 | yield Fields(fields, index=index, object=object) |
|
1775 | yield Fields(fields, index=index, object=object) | |
1504 |
|
1776 | |||
1505 |
|
1777 | |||
@@ -1524,18 +1796,11 b' class isort(Pipe):' | |||||
1524 | self.globals = globals |
|
1796 | self.globals = globals | |
1525 | self.reverse = reverse |
|
1797 | self.reverse = reverse | |
1526 |
|
1798 | |||
1527 |
def __ |
|
1799 | def __iter__(self): | |
1528 | if self.key is None: |
|
1800 | if self.key is None: | |
1529 | items = sorted( |
|
1801 | items = sorted(xiter(self.input), reverse=self.reverse) | |
1530 | xiter(self.input, mode), |
|
|||
1531 | reverse=self.reverse |
|
|||
1532 | ) |
|
|||
1533 | elif callable(self.key): |
|
1802 | elif callable(self.key): | |
1534 | items = sorted( |
|
1803 | items = sorted(xiter(self.input), key=self.key, reverse=self.reverse) | |
1535 | xiter(self.input, mode), |
|
|||
1536 | key=self.key, |
|
|||
1537 | reverse=self.reverse |
|
|||
1538 | ) |
|
|||
1539 | else: |
|
1804 | else: | |
1540 | g = getglobals(self.globals) |
|
1805 | g = getglobals(self.globals) | |
1541 | key = compile(self.key, "ipipe-expression", "eval") |
|
1806 | key = compile(self.key, "ipipe-expression", "eval") | |
@@ -1613,8 +1878,8 b' class iless(Display):' | |||||
1613 | pager = os.popen(self.cmd, "w") |
|
1878 | pager = os.popen(self.cmd, "w") | |
1614 | try: |
|
1879 | try: | |
1615 | for item in xiter(self.input, "default"): |
|
1880 | for item in xiter(self.input, "default"): | |
1616 | attrs = xattrs(item, "default") |
|
1881 | attrs = tuple(_upgradexattrs(item, "default")) | |
1617 |
attrs = ["%s=%s" % (a |
|
1882 | attrs = ["%s=%s" % (a.name(item), a.value(item)) for a in attrs] | |
1618 | pager.write(" ".join(attrs)) |
|
1883 | pager.write(" ".join(attrs)) | |
1619 | pager.write("\n") |
|
1884 | pager.write("\n") | |
1620 | finally: |
|
1885 | finally: | |
@@ -1659,7 +1924,7 b' class idump(Display):' | |||||
1659 | style_header = astyle.Style.fromstr("white:black:bold") |
|
1924 | style_header = astyle.Style.fromstr("white:black:bold") | |
1660 |
|
1925 | |||
1661 | def __init__(self, *attrs): |
|
1926 | def __init__(self, *attrs): | |
1662 | self.attrs = attrs |
|
1927 | self.attrs = [upgradexattr(attr) for attr in attrs] | |
1663 | self.headerpadchar = " " |
|
1928 | self.headerpadchar = " " | |
1664 | self.headersepchar = "|" |
|
1929 | self.headersepchar = "|" | |
1665 | self.datapadchar = " " |
|
1930 | self.datapadchar = " " | |
@@ -1668,7 +1933,7 b' class idump(Display):' | |||||
1668 | def display(self): |
|
1933 | def display(self): | |
1669 | stream = genutils.Term.cout |
|
1934 | stream = genutils.Term.cout | |
1670 | allattrs = [] |
|
1935 | allattrs = [] | |
1671 |
|
|
1936 | attrset = set() | |
1672 | colwidths = {} |
|
1937 | colwidths = {} | |
1673 | rows = [] |
|
1938 | rows = [] | |
1674 | for item in xiter(self.input, "default"): |
|
1939 | for item in xiter(self.input, "default"): | |
@@ -1676,42 +1941,43 b' class idump(Display):' | |||||
1676 | attrs = self.attrs |
|
1941 | attrs = self.attrs | |
1677 | if not attrs: |
|
1942 | if not attrs: | |
1678 | attrs = xattrs(item, "default") |
|
1943 | attrs = xattrs(item, "default") | |
1679 |
for attr |
|
1944 | for attr in attrs: | |
1680 |
if attr |
|
1945 | if attr not in attrset: | |
1681 |
allattrs.append(attr |
|
1946 | allattrs.append(attr) | |
1682 |
|
|
1947 | attrset.add(attr) | |
1683 |
colwidths[attr |
|
1948 | colwidths[attr] = len(attr.name()) | |
1684 | try: |
|
1949 | try: | |
1685 |
value = |
|
1950 | value = attr.value(item) | |
1686 | except (KeyboardInterrupt, SystemExit): |
|
1951 | except (KeyboardInterrupt, SystemExit): | |
1687 | raise |
|
1952 | raise | |
1688 | except Exception, exc: |
|
1953 | except Exception, exc: | |
1689 | value = exc |
|
1954 | value = exc | |
1690 | (align, width, text) = xformat(value, "cell", self.maxattrlength) |
|
1955 | (align, width, text) = xformat(value, "cell", self.maxattrlength) | |
1691 |
colwidths[attr |
|
1956 | colwidths[attr] = max(colwidths[attr], width) | |
1692 | # remember alignment, length and colored parts |
|
1957 | # remember alignment, length and colored parts | |
1693 |
row[attr |
|
1958 | row[attr] = (align, width, text) | |
1694 | rows.append(row) |
|
1959 | rows.append(row) | |
1695 |
|
1960 | |||
1696 | stream.write("\n") |
|
1961 | stream.write("\n") | |
1697 |
for (i, attr |
|
1962 | for (i, attr) in enumerate(allattrs): | |
1698 | self.style_header(_attrname(attrname)).write(stream) |
|
1963 | attrname = attr.name() | |
1699 | spc = colwidths[attrname] - len(_attrname(attrname)) |
|
1964 | self.style_header(attrname).write(stream) | |
|
1965 | spc = colwidths[attr] - len(attrname) | |||
1700 | if i < len(colwidths)-1: |
|
1966 | if i < len(colwidths)-1: | |
1701 | stream.write(self.headerpadchar*spc) |
|
1967 | stream.write(self.headerpadchar*spc) | |
1702 | stream.write(self.headersepchar) |
|
1968 | stream.write(self.headersepchar) | |
1703 | stream.write("\n") |
|
1969 | stream.write("\n") | |
1704 |
|
1970 | |||
1705 | for row in rows: |
|
1971 | for row in rows: | |
1706 |
for (i, attr |
|
1972 | for (i, attr) in enumerate(allattrs): | |
1707 |
(align, width, text) = row[attr |
|
1973 | (align, width, text) = row[attr] | |
1708 |
spc = colwidths[attr |
|
1974 | spc = colwidths[attr] - width | |
1709 | if align == -1: |
|
1975 | if align == -1: | |
1710 | text.write(stream) |
|
1976 | text.write(stream) | |
1711 | if i < len(colwidths)-1: |
|
1977 | if i < len(colwidths)-1: | |
1712 | stream.write(self.datapadchar*spc) |
|
1978 | stream.write(self.datapadchar*spc) | |
1713 | elif align == 0: |
|
1979 | elif align == 0: | |
1714 |
spc = colwidths[attr |
|
1980 | spc = colwidths[attr] - width | |
1715 | spc1 = spc//2 |
|
1981 | spc1 = spc//2 | |
1716 | spc2 = spc-spc1 |
|
1982 | spc2 = spc-spc1 | |
1717 | stream.write(self.datapadchar*spc1) |
|
1983 | stream.write(self.datapadchar*spc1) | |
@@ -1755,55 +2021,57 b' class XMode(object):' | |||||
1755 |
|
2021 | |||
1756 | def __xattrs__(self, mode): |
|
2022 | def __xattrs__(self, mode): | |
1757 | if mode == "detail": |
|
2023 | if mode == "detail": | |
|
2024 | return ("object", "mode") | |||
|
2025 | else: | |||
1758 | return ("object", "mode", "title", "description") |
|
2026 | return ("object", "mode", "title", "description") | |
1759 | return ("title", "description") |
|
|||
1760 |
|
2027 | |||
1761 | def __xiter__(self, mode): |
|
2028 | def __xiter__(self, mode): | |
1762 | return xiter(self.object, self.mode) |
|
2029 | return xiter(self.object, self.mode) | |
1763 |
|
2030 | |||
1764 |
|
2031 | |||
1765 |
class |
|
2032 | class AttributeDetail(Table): | |
1766 |
def __init__(self, object, |
|
2033 | def __init__(self, object, descriptor): | |
1767 | self.name = _attrname(name) |
|
2034 | self.object = object | |
|
2035 | self.descriptor = descriptor | |||
1768 |
|
2036 | |||
1769 | try: |
|
2037 | def __iter__(self): | |
1770 | self.value = _getattr(object, name) |
|
2038 | return self.descriptor.iter(self.object) | |
1771 | except (KeyboardInterrupt, SystemExit): |
|
|||
1772 | raise |
|
|||
1773 | except Exception, exc: |
|
|||
1774 | if exc.__class__.__module__ == "exceptions": |
|
|||
1775 | self.value = exc.__class__.__name__ |
|
|||
1776 | else: |
|
|||
1777 | self.value = "%s.%s" % \ |
|
|||
1778 | (exc.__class__.__module__, exc.__class__.__name__) |
|
|||
1779 | self.type = self.value |
|
|||
1780 | else: |
|
|||
1781 | t = type(self.value) |
|
|||
1782 | if t.__module__ == "__builtin__": |
|
|||
1783 | self.type = t.__name__ |
|
|||
1784 | else: |
|
|||
1785 | self.type = "%s.%s" % (t.__module__, t.__name__) |
|
|||
1786 |
|
2039 | |||
1787 | doc = None |
|
2040 | def name(self): | |
1788 | if isinstance(name, basestring): |
|
2041 | return self.descriptor.name() | |
1789 | if name.endswith("()"): |
|
2042 | ||
1790 | doc = getattr(getattr(object, name[:-2]), "__doc__", None) |
|
2043 | def attrtype(self): | |
1791 | else: |
|
2044 | return self.descriptor.attrtype(self.object) | |
1792 | try: |
|
2045 | ||
1793 | meta = getattr(type(object), name) |
|
2046 | def valuetype(self): | |
1794 | except AttributeError: |
|
2047 | return self.descriptor.valuetype(self.object) | |
1795 | pass |
|
2048 | ||
1796 | else: |
|
2049 | def doc(self): | |
1797 | if isinstance(meta, property): |
|
2050 | return self.descriptor.doc(self.object) | |
1798 | doc = getattr(meta, "__doc__", None) |
|
2051 | ||
1799 | elif callable(name): |
|
2052 | def shortdoc(self): | |
1800 | doc = getattr(name, "__doc__", None) |
|
2053 | return self.descriptor.shortdoc(self.object) | |
1801 | if isinstance(doc, basestring): |
|
2054 | ||
1802 | doc = doc.strip() |
|
2055 | def value(self): | |
1803 | self.doc = doc |
|
2056 | return self.descriptor.value(self.object) | |
1804 |
|
2057 | |||
1805 | def __xattrs__(self, mode): |
|
2058 | def __xattrs__(self, mode): | |
1806 | return ("name", "type", "doc", "value") |
|
2059 | attrs = ("name()", "attrtype()", "valuetype()", "value()", "shortdoc()") | |
|
2060 | if mode == "detail": | |||
|
2061 | attrs += ("doc()",) | |||
|
2062 | return attrs | |||
|
2063 | ||||
|
2064 | def __xrepr__(self, mode): | |||
|
2065 | yield (-1, True) | |||
|
2066 | yield (astyle.style_default, self.attrtype()) | |||
|
2067 | yield (astyle.style_default, "(") | |||
|
2068 | for part in xrepr(self.valuetype()): | |||
|
2069 | yield part | |||
|
2070 | yield (astyle.style_default, ") ") | |||
|
2071 | yield (astyle.style_default, self.name()) | |||
|
2072 | yield (astyle.style_default, " of ") | |||
|
2073 | for part in xrepr(self.object): | |||
|
2074 | yield part | |||
1807 |
|
2075 | |||
1808 |
|
2076 | |||
1809 | try: |
|
2077 | try: |
@@ -3,6 +3,27 b'' | |||||
3 | * IPython/Extensions/ipipe.py: Fix getglobals() if we're |
|
3 | * IPython/Extensions/ipipe.py: Fix getglobals() if we're | |
4 | not running under IPython. |
|
4 | not running under IPython. | |
5 |
|
5 | |||
|
6 | * IPython/Extensions/ipipe.py: Rename XAttr to AttributeDetail | |||
|
7 | and make it iterable (iterating over the attribute itself). Add two new | |||
|
8 | magic strings for __xattrs__(): If the string starts with "-", the attribute | |||
|
9 | will not be displayed in ibrowse's detail view (but it can still be | |||
|
10 | iterated over). This makes it possible to add attributes that are large | |||
|
11 | lists or generator methods to the detail view. Replace magic attribute names | |||
|
12 | and _attrname() and _getattr() with "descriptors": For each type of magic | |||
|
13 | attribute name there's a subclass of Descriptor: None -> SelfDescriptor(); | |||
|
14 | "foo" -> AttributeDescriptor("foo"); "foo()" -> MethodDescriptor("foo"); | |||
|
15 | "-foo" -> IterAttributeDescriptor("foo"); "-foo()" -> IterMethodDescriptor("foo"); | |||
|
16 | foo() -> FunctionDescriptor(foo). Magic strings returned from __xattrs__() | |||
|
17 | are still supported. | |||
|
18 | ||||
|
19 | * IPython/Extensions/ibrowse.py: If fetching the next row from the input | |||
|
20 | fails in ibrowse.fetch(), the exception object is added as the last item | |||
|
21 | and item fetching is canceled. This prevents ibrowse from aborting if e.g. | |||
|
22 | a generator throws an exception midway through execution. | |||
|
23 | ||||
|
24 | * IPython/Extensions/ipipe.py: Turn ifile's properties mimetype and | |||
|
25 | encoding into methods. | |||
|
26 | ||||
6 | 2006-07-26 Ville Vainio <vivainio@gmail.com> |
|
27 | 2006-07-26 Ville Vainio <vivainio@gmail.com> | |
7 |
|
28 | |||
8 | * iplib.py: history now stores multiline input as single |
|
29 | * iplib.py: history now stores multiline input as single |
General Comments 0
You need to be logged in to leave comments.
Login now