Show More
@@ -374,6 +374,7 b' style_type_none = Style.fromstr("magenta:black")' | |||
|
374 | 374 | style_type_bool = Style.fromstr("magenta:black") |
|
375 | 375 | style_type_number = Style.fromstr("yellow:black") |
|
376 | 376 | style_type_datetime = Style.fromstr("magenta:black") |
|
377 | style_type_type = Style.fromstr("cyan:black") | |
|
377 | 378 | |
|
378 | 379 | # Style for URLs and file/directory names |
|
379 | 380 | style_url = Style.fromstr("green:black") |
@@ -97,7 +97,7 b' class _BrowserHelp(object):' | |||
|
97 | 97 | else: |
|
98 | 98 | yield (astyle.style_default, repr(self)) |
|
99 | 99 | |
|
100 |
def __ |
|
|
100 | def __iter__(self): | |
|
101 | 101 | # Get reverse key mapping |
|
102 | 102 | allkeys = {} |
|
103 | 103 | for (key, cmd) in self.browser.keymap.iteritems(): |
@@ -125,7 +125,7 b' class _BrowserHelp(object):' | |||
|
125 | 125 | lines = textwrap.wrap(description, 60) |
|
126 | 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 | 129 | for i in xrange(max(len(keys), len(lines))): |
|
130 | 130 | try: |
|
131 | 131 | key = self.browser.keylabel(keys[i]) |
@@ -183,13 +183,13 b' class _BrowserLevel(object):' | |||
|
183 | 183 | # Size of row number (changes when scrolling) |
|
184 | 184 | self.numbersizex = 0 |
|
185 | 185 | |
|
186 |
# Attribute |
|
|
186 | # Attributes to display (in this order) | |
|
187 | 187 | self.displayattrs = [] |
|
188 | 188 | |
|
189 |
# index and |
|
|
189 | # index and attribute under the cursor | |
|
190 | 190 | self.displayattr = (None, ipipe.noitem) |
|
191 | 191 | |
|
192 |
# Maps attribute |
|
|
192 | # Maps attributes to column widths | |
|
193 | 193 | self.colwidths = {} |
|
194 | 194 | |
|
195 | 195 | # Set of hidden attributes |
@@ -207,6 +207,13 b' class _BrowserLevel(object):' | |||
|
207 | 207 | except StopIteration: |
|
208 | 208 | self.exhausted = True |
|
209 | 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 | 217 | else: |
|
211 | 218 | have += 1 |
|
212 | 219 | self.items.append(_BrowserCachedItem(item)) |
@@ -215,22 +222,23 b' class _BrowserLevel(object):' | |||
|
215 | 222 | # Calculate which attributes are available from the objects that are |
|
216 | 223 | # currently visible on screen (and store it in ``self.displayattrs``) |
|
217 | 224 | |
|
218 |
attr |
|
|
225 | attrs = set() | |
|
219 | 226 | self.displayattrs = [] |
|
220 | 227 | if self.attrs: |
|
221 | 228 | # If the browser object specifies a fixed list of attributes, |
|
222 | 229 | # simply use it (removing hidden attributes). |
|
223 |
for attr |
|
|
224 | if attrname not in attrnames and attrname not in self.hiddenattrs: | |
|
225 | self.displayattrs.append(attrname) | |
|
226 |
|
|
|
230 | for attr in self.attrs: | |
|
231 | attr = ipipe.upgradexattr(attr) | |
|
232 | if attr not in attrs and attr not in self.hiddenattrs: | |
|
233 | self.displayattrs.append(attr) | |
|
234 | attrs.add(attr) | |
|
227 | 235 | else: |
|
228 | 236 | endy = min(self.datastarty+self.mainsizey, len(self.items)) |
|
229 | 237 | for i in xrange(self.datastarty, endy): |
|
230 |
for attr |
|
|
231 |
if attr |
|
|
232 |
self.displayattrs.append(attr |
|
|
233 |
attr |
|
|
238 | for attr in ipipe.xattrs(self.items[i].item, "default"): | |
|
239 | if attr not in attrs and attr not in self.hiddenattrs: | |
|
240 | self.displayattrs.append(attr) | |
|
241 | attrs.add(attr) | |
|
234 | 242 | |
|
235 | 243 | def getrow(self, i): |
|
236 | 244 | # Return a dictinary with the attributes for the object |
@@ -239,9 +247,9 b' class _BrowserLevel(object):' | |||
|
239 | 247 | # called before. |
|
240 | 248 | row = {} |
|
241 | 249 | item = self.items[i].item |
|
242 |
for attr |
|
|
250 | for attr in self.displayattrs: | |
|
243 | 251 | try: |
|
244 |
value = |
|
|
252 | value = attr.value(item) | |
|
245 | 253 | except (KeyboardInterrupt, SystemExit): |
|
246 | 254 | raise |
|
247 | 255 | except Exception, exc: |
@@ -249,7 +257,7 b' class _BrowserLevel(object):' | |||
|
249 | 257 | # only store attribute if it exists (or we got an exception) |
|
250 | 258 | if value is not ipipe.noitem: |
|
251 | 259 | # remember alignment, length and colored text |
|
252 |
row[attr |
|
|
260 | row[attr] = ipipe.xformat(value, "cell", self.browser.maxattrlength) | |
|
253 | 261 | return row |
|
254 | 262 | |
|
255 | 263 | def calcwidths(self): |
@@ -260,16 +268,16 b' class _BrowserLevel(object):' | |||
|
260 | 268 | # column names to widths. |
|
261 | 269 | self.colwidths = {} |
|
262 | 270 | for row in self.displayrows: |
|
263 |
for attr |
|
|
271 | for attr in self.displayattrs: | |
|
264 | 272 | try: |
|
265 |
length = row[attr |
|
|
273 | length = row[attr][1] | |
|
266 | 274 | except KeyError: |
|
267 | 275 | length = 0 |
|
268 | 276 | # always add attribute to colwidths, even if it doesn't exist |
|
269 |
if attr |
|
|
270 |
self.colwidths[attr |
|
|
271 |
newwidth = max(self.colwidths[attr |
|
|
272 |
self.colwidths[attr |
|
|
277 | if attr not in self.colwidths: | |
|
278 | self.colwidths[attr] = len(attr.name()) | |
|
279 | newwidth = max(self.colwidths[attr], length) | |
|
280 | self.colwidths[attr] = newwidth | |
|
273 | 281 | |
|
274 | 282 | # How many characters do we need to paint the largest item number? |
|
275 | 283 | self.numbersizex = len(str(self.datastarty+self.mainsizey-1)) |
@@ -282,11 +290,11 b' class _BrowserLevel(object):' | |||
|
282 | 290 | # Find out which attribute the cursor is on and store this |
|
283 | 291 | # information in ``self.displayattr``. |
|
284 | 292 | pos = 0 |
|
285 |
for (i, attr |
|
|
286 |
if pos+self.colwidths[attr |
|
|
287 |
self.displayattr = (i, attr |
|
|
293 | for (i, attr) in enumerate(self.displayattrs): | |
|
294 | if pos+self.colwidths[attr] >= self.curx: | |
|
295 | self.displayattr = (i, attr) | |
|
288 | 296 | break |
|
289 |
pos += self.colwidths[attr |
|
|
297 | pos += self.colwidths[attr]+1 | |
|
290 | 298 | else: |
|
291 | 299 | self.displayattr = (None, ipipe.noitem) |
|
292 | 300 | |
@@ -1030,7 +1038,7 b' class ibrowse(ipipe.Display):' | |||
|
1030 | 1038 | """ |
|
1031 | 1039 | 'Pick' the object under the cursor (i.e. the row the cursor is on). |
|
1032 | 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 | 1043 | level = self.levels[-1] |
|
1036 | 1044 | self.returnvalue = level.items[level.cury].item |
@@ -1042,17 +1050,17 b' class ibrowse(ipipe.Display):' | |||
|
1042 | 1050 | cursor is on). |
|
1043 | 1051 | """ |
|
1044 | 1052 | level = self.levels[-1] |
|
1045 |
attr |
|
|
1046 |
if attr |
|
|
1053 | attr = level.displayattr[1] | |
|
1054 | if attr is ipipe.noitem: | |
|
1047 | 1055 | curses.beep() |
|
1048 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1056 | self.report(CommandError("no column under cursor")) | |
|
1049 | 1057 | return |
|
1050 |
|
|
|
1051 |
if |
|
|
1058 | value = attr.value(level.items[level.cury].item) | |
|
1059 | if value is ipipe.noitem: | |
|
1052 | 1060 | curses.beep() |
|
1053 |
self.report(AttributeError( |
|
|
1061 | self.report(AttributeError(attr.name())) | |
|
1054 | 1062 | else: |
|
1055 |
self.returnvalue = |
|
|
1063 | self.returnvalue = value | |
|
1056 | 1064 | return True |
|
1057 | 1065 | |
|
1058 | 1066 | def cmd_pickallattrs(self): |
@@ -1062,16 +1070,16 b' class ibrowse(ipipe.Display):' | |||
|
1062 | 1070 | will be returned as a list. |
|
1063 | 1071 | """ |
|
1064 | 1072 | level = self.levels[-1] |
|
1065 |
attr |
|
|
1066 |
if attr |
|
|
1073 | attr = level.displayattr[1] | |
|
1074 | if attr is ipipe.noitem: | |
|
1067 | 1075 | curses.beep() |
|
1068 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1076 | self.report(CommandError("no column under cursor")) | |
|
1069 | 1077 | return |
|
1070 | 1078 | result = [] |
|
1071 | 1079 | for cache in level.items: |
|
1072 | attr = ipipe._getattr(cache.item, attrname) | |
|
1073 |
if |
|
|
1074 |
result.append( |
|
|
1080 | value = attr.value(cache.item) | |
|
1081 | if value is not ipipe.noitem: | |
|
1082 | result.append(value) | |
|
1075 | 1083 | self.returnvalue = result |
|
1076 | 1084 | return True |
|
1077 | 1085 | |
@@ -1090,17 +1098,17 b' class ibrowse(ipipe.Display):' | |||
|
1090 | 1098 | """ |
|
1091 | 1099 | |
|
1092 | 1100 | level = self.levels[-1] |
|
1093 |
attr |
|
|
1094 |
if attr |
|
|
1101 | attr = level.displayattr[1] | |
|
1102 | if attr is ipipe.noitem: | |
|
1095 | 1103 | curses.beep() |
|
1096 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1104 | self.report(CommandError("no column under cursor")) | |
|
1097 | 1105 | return |
|
1098 | 1106 | result = [] |
|
1099 | 1107 | for cache in level.items: |
|
1100 | 1108 | if cache.marked: |
|
1101 |
|
|
|
1102 |
if |
|
|
1103 |
result.append( |
|
|
1109 | value = attr.value(cache.item) | |
|
1110 | if value is not ipipe.noitem: | |
|
1111 | result.append(value) | |
|
1104 | 1112 | self.returnvalue = result |
|
1105 | 1113 | return True |
|
1106 | 1114 | |
@@ -1130,7 +1138,7 b' class ibrowse(ipipe.Display):' | |||
|
1130 | 1138 | def cmd_enterdefault(self): |
|
1131 | 1139 | """ |
|
1132 | 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 | 1142 | browser 'level'. |
|
1135 | 1143 | """ |
|
1136 | 1144 | level = self.levels[-1] |
@@ -1176,10 +1184,10 b' class ibrowse(ipipe.Display):' | |||
|
1176 | 1184 | Enter the attribute under the cursor. |
|
1177 | 1185 | """ |
|
1178 | 1186 | level = self.levels[-1] |
|
1179 |
attr |
|
|
1180 |
if attr |
|
|
1187 | attr = level.displayattr[1] | |
|
1188 | if attr is ipipe.noitem: | |
|
1181 | 1189 | curses.beep() |
|
1182 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1190 | self.report(CommandError("no column under cursor")) | |
|
1183 | 1191 | return |
|
1184 | 1192 | try: |
|
1185 | 1193 | item = level.items[level.cury].item |
@@ -1187,12 +1195,13 b' class ibrowse(ipipe.Display):' | |||
|
1187 | 1195 | self.report(CommandError("No object")) |
|
1188 | 1196 | curses.beep() |
|
1189 | 1197 | else: |
|
1190 | attr = ipipe._getattr(item, attrname) | |
|
1191 |
|
|
|
1192 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1198 | value = attr.value(item) | |
|
1199 | name = attr.name() | |
|
1200 | if value is ipipe.noitem: | |
|
1201 | self.report(AttributeError(name)) | |
|
1193 | 1202 | else: |
|
1194 |
self.report("entering object attribute %s..." % |
|
|
1195 |
self.enter( |
|
|
1203 | self.report("entering object attribute %s..." % name) | |
|
1204 | self.enter(value, None) | |
|
1196 | 1205 | |
|
1197 | 1206 | def cmd_detail(self): |
|
1198 | 1207 | """ |
@@ -1209,17 +1218,18 b' class ibrowse(ipipe.Display):' | |||
|
1209 | 1218 | curses.beep() |
|
1210 | 1219 | else: |
|
1211 | 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 | 1224 | def cmd_detailattr(self): |
|
1215 | 1225 | """ |
|
1216 | 1226 | Show a detail view of the attribute under the cursor. |
|
1217 | 1227 | """ |
|
1218 | 1228 | level = self.levels[-1] |
|
1219 |
attr |
|
|
1220 |
if attr |
|
|
1229 | attr = level.displayattr[1] | |
|
1230 | if attr is ipipe.noitem: | |
|
1221 | 1231 | curses.beep() |
|
1222 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1232 | self.report(CommandError("no attribute")) | |
|
1223 | 1233 | return |
|
1224 | 1234 | try: |
|
1225 | 1235 | item = level.items[level.cury].item |
@@ -1227,12 +1237,16 b' class ibrowse(ipipe.Display):' | |||
|
1227 | 1237 | self.report(CommandError("No object")) |
|
1228 | 1238 | curses.beep() |
|
1229 | 1239 | else: |
|
1230 | attr = ipipe._getattr(item, attrname) | |
|
1231 |
|
|
|
1232 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1240 | try: | |
|
1241 | item = attr.value(item) | |
|
1242 | except (KeyboardInterrupt, SystemExit): | |
|
1243 | raise | |
|
1244 | except Exception, exc: | |
|
1245 | self.report(exc) | |
|
1233 | 1246 | else: |
|
1234 | self.report("entering detail view for attribute...") | |
|
1235 | self.enter(attr, "detail") | |
|
1247 | self.report("entering detail view for attribute %s..." % attr.name()) | |
|
1248 | attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")] | |
|
1249 | self.enter(attrs, "detail") | |
|
1236 | 1250 | |
|
1237 | 1251 | def cmd_tooglemark(self): |
|
1238 | 1252 | """ |
@@ -1259,15 +1273,15 b' class ibrowse(ipipe.Display):' | |||
|
1259 | 1273 | the cursor as the sort key. |
|
1260 | 1274 | """ |
|
1261 | 1275 | level = self.levels[-1] |
|
1262 |
attr |
|
|
1263 |
if attr |
|
|
1276 | attr = level.displayattr[1] | |
|
1277 | if attr is ipipe.noitem: | |
|
1264 | 1278 | curses.beep() |
|
1265 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1279 | self.report(CommandError("no column under cursor")) | |
|
1266 | 1280 | return |
|
1267 |
self.report("sort by %s (ascending)" % |
|
|
1281 | self.report("sort by %s (ascending)" % attr.name()) | |
|
1268 | 1282 | def key(item): |
|
1269 | 1283 | try: |
|
1270 |
return |
|
|
1284 | return attr.value(item) | |
|
1271 | 1285 | except (KeyboardInterrupt, SystemExit): |
|
1272 | 1286 | raise |
|
1273 | 1287 | except Exception: |
@@ -1280,15 +1294,15 b' class ibrowse(ipipe.Display):' | |||
|
1280 | 1294 | the cursor as the sort key. |
|
1281 | 1295 | """ |
|
1282 | 1296 | level = self.levels[-1] |
|
1283 |
attr |
|
|
1284 |
if attr |
|
|
1297 | attr = level.displayattr[1] | |
|
1298 | if attr is ipipe.noitem: | |
|
1285 | 1299 | curses.beep() |
|
1286 | self.report(AttributeError(ipipe._attrname(attrname))) | |
|
1300 | self.report(CommandError("no column under cursor")) | |
|
1287 | 1301 | return |
|
1288 |
self.report("sort by %s (descending)" % |
|
|
1302 | self.report("sort by %s (descending)" % attr.name()) | |
|
1289 | 1303 | def key(item): |
|
1290 | 1304 | try: |
|
1291 |
return |
|
|
1305 | return attr.value(item) | |
|
1292 | 1306 | except (KeyboardInterrupt, SystemExit): |
|
1293 | 1307 | raise |
|
1294 | 1308 | except Exception: |
@@ -1427,11 +1441,11 b' class ibrowse(ipipe.Display):' | |||
|
1427 | 1441 | scr.addstr(self.headersepchar, self.getstyle(self.style_colheadersep)) |
|
1428 | 1442 | begx = level.numbersizex+3 |
|
1429 | 1443 | posx = begx-level.datastartx |
|
1430 |
for attr |
|
|
1431 |
|
|
|
1432 |
cwidth = level.colwidths[attr |
|
|
1433 |
header = |
|
|
1434 |
if attr |
|
|
1444 | for attr in level.displayattrs: | |
|
1445 | attrname = attr.name() | |
|
1446 | cwidth = level.colwidths[attr] | |
|
1447 | header = attrname.ljust(cwidth) | |
|
1448 | if attr is level.displayattr[1]: | |
|
1435 | 1449 | style = self.style_colheaderhere |
|
1436 | 1450 | else: |
|
1437 | 1451 | style = self.style_colheader |
@@ -1527,19 +1541,19 b' class ibrowse(ipipe.Display):' | |||
|
1527 | 1541 | break |
|
1528 | 1542 | |
|
1529 | 1543 | attrstyle = [(astyle.style_default, "no attribute")] |
|
1530 |
attr |
|
|
1531 |
if attr |
|
|
1544 | attr = level.displayattr[1] | |
|
1545 | if attr is not ipipe.noitem and not isinstance(attr, ipipe.SelfDescriptor): | |
|
1532 | 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 | 1548 | posx += self.addstr(posy, posx, 0, endx, ": ", self.style_footer) |
|
1535 | 1549 | try: |
|
1536 |
|
|
|
1550 | value = attr.value(item) | |
|
1537 | 1551 | except (SystemExit, KeyboardInterrupt): |
|
1538 | 1552 | raise |
|
1539 | 1553 | except Exception, exc: |
|
1540 | 1554 | attr = exc |
|
1541 |
if |
|
|
1542 |
attrstyle = ipipe.xrepr( |
|
|
1555 | if value is not ipipe.noitem: | |
|
1556 | attrstyle = ipipe.xrepr(value, "footer") | |
|
1543 | 1557 | for (nostyle, text) in attrstyle: |
|
1544 | 1558 | if not isinstance(nostyle, int): |
|
1545 | 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 | 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 | 517 | class Table(object): |
|
273 | 518 | """ |
|
274 | 519 | A ``Table`` is an object that produces items (just like a normal Python |
@@ -350,47 +595,7 b' class Pipe(Table):' | |||
|
350 | 595 | return self |
|
351 | 596 | |
|
352 | 597 | |
|
353 | def _getattr(obj, name, default=noitem): | |
|
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): | |
|
598 | def xrepr(item, mode="default"): | |
|
394 | 599 | try: |
|
395 | 600 | func = item.__xrepr__ |
|
396 | 601 | except AttributeError: |
@@ -449,6 +654,11 b' def xrepr(item, mode):' | |||
|
449 | 654 | yield (astyle.style_type_datetime, repr(item)) |
|
450 | 655 | elif isinstance(item, datetime.timedelta): |
|
451 | 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 | 662 | elif isinstance(item, Exception): |
|
453 | 663 | if item.__class__.__module__ == "exceptions": |
|
454 | 664 | classname = item.__class__.__name__ |
@@ -514,33 +724,67 b' def xrepr(item, mode):' | |||
|
514 | 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 | 752 | try: |
|
519 | 753 | func = item.__xattrs__ |
|
520 | 754 | except AttributeError: |
|
521 | 755 | if mode == "detail": |
|
522 |
|
|
|
756 | for attrname in dir(item): | |
|
757 | yield AttributeDescriptor(attrname) | |
|
523 | 758 | else: |
|
524 | return (None,) | |
|
759 | yield selfdescriptor | |
|
525 | 760 | else: |
|
761 | for attr in func(mode): | |
|
762 | yield upgradexattr(attr) | |
|
763 | ||
|
764 | ||
|
765 | def _isdict(item): | |
|
526 | 766 |
|
|
527 | return func(mode) | |
|
528 | except (KeyboardInterrupt, SystemExit): | |
|
529 |
|
|
|
530 | except Exception: | |
|
531 | return (None,) | |
|
767 | itermeth = item.__class__.__iter__ | |
|
768 | except (AttributeError, TypeError): | |
|
769 | return False | |
|
770 | return itermeth is dict.__iter__ or itermeth is types.DictProxyType.__iter__ | |
|
532 | 771 | |
|
533 | 772 | |
|
534 |
def |
|
|
535 | if mode == "detail": | |
|
536 | def items(): | |
|
537 | for name in xattrs(item, mode): | |
|
538 | yield XAttr(item, name) | |
|
539 | return items() | |
|
773 | def _isstr(item): | |
|
774 | if not isinstance(item, basestring): | |
|
775 | return False | |
|
776 | try: | |
|
777 | itermeth = item.__class__.__iter__ | |
|
778 | except AttributeError: | |
|
779 | return True | |
|
780 | return False # ``__iter__`` has been redefined | |
|
781 | ||
|
782 | ||
|
783 | def xiter(item, mode="default"): | |
|
540 | 784 | try: |
|
541 | 785 | func = item.__xiter__ |
|
542 | 786 | except AttributeError: |
|
543 | if isinstance(item, (dict, types.DictProxyType)): | |
|
787 | if _isdict(item): | |
|
544 | 788 | def items(item): |
|
545 | 789 | fields = ("key", "value") |
|
546 | 790 | for (key, value) in item.iteritems(): |
@@ -552,8 +796,8 b' def xiter(item, mode):' | |||
|
552 | 796 | for key in sorted(item.__dict__): |
|
553 | 797 | yield Fields(fields, key=key, value=getattr(item, key)) |
|
554 | 798 | return items(item) |
|
555 |
elif |
|
|
556 |
if not |
|
|
799 | elif _isstr(item): | |
|
800 | if not item: | |
|
557 | 801 | raise ValueError("can't enter empty string") |
|
558 | 802 | lines = item.splitlines() |
|
559 | 803 | if len(lines) <= 1: |
@@ -572,7 +816,7 b' class ichain(Pipe):' | |||
|
572 | 816 | def __init__(self, *iters): |
|
573 | 817 | self.iters = iters |
|
574 | 818 | |
|
575 |
def __ |
|
|
819 | def __iter__(self): | |
|
576 | 820 | return itertools.chain(*self.iters) |
|
577 | 821 | |
|
578 | 822 | def __xrepr__(self, mode): |
@@ -823,30 +1067,61 b' class ifile(path.path):' | |||
|
823 | 1067 | return datetime.datetime.utcfromtimestamp(self.mtime) |
|
824 | 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 | 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 | 1080 | return mimetypes.guess_type(self.basename())[1] |
|
832 | encoding = property(getencoding, None, None, "Compression") | |
|
833 | 1081 | |
|
834 | 1082 | def __repr__(self): |
|
835 | 1083 | return "ifile(%s)" % path._base.__repr__(self) |
|
836 | 1084 | |
|
837 | defaultattrs = (None, "type", "size", "modestr", "owner", "group", "mdate") | |
|
838 | ||
|
839 | 1085 | def __xattrs__(self, mode): |
|
840 | 1086 | if mode == "detail": |
|
841 | 1087 | return ( |
|
842 | "name", "basename()", "abspath()", "realpath()", | |
|
843 | "type", "mode", "modestr", "stat()", "lstat()", | |
|
844 | "uid", "gid", "owner", "group", "dev", "nlink", | |
|
845 | "ctime", "mtime", "atime", "cdate", "mdate", "adate", | |
|
846 | "size", "blocks", "blksize", "isdir()", "islink()", | |
|
847 |
"m |
|
|
1088 | "name", | |
|
1089 | "basename()", | |
|
1090 | "abspath()", | |
|
1091 | "realpath()", | |
|
1092 | "type", | |
|
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 | 1126 | def __xrepr__(self, mode): |
|
852 | 1127 | try: |
@@ -872,7 +1147,7 b' class ifile(path.path):' | |||
|
872 | 1147 | else: |
|
873 | 1148 | yield (style, repr(self)) |
|
874 | 1149 | |
|
875 |
def __ |
|
|
1150 | def __iter__(self): | |
|
876 | 1151 | if self.isdir(): |
|
877 | 1152 | yield iparentdir(self / os.pardir) |
|
878 | 1153 | for child in sorted(self.listdir()): |
@@ -906,8 +1181,8 b' class ils(Table):' | |||
|
906 | 1181 | def __init__(self, base=os.curdir): |
|
907 | 1182 | self.base = os.path.expanduser(base) |
|
908 | 1183 | |
|
909 |
def __ |
|
|
910 |
return xiter(ifile(self.base) |
|
|
1184 | def __iter__(self): | |
|
1185 | return xiter(ifile(self.base)) | |
|
911 | 1186 | |
|
912 | 1187 | def __xrepr__(self, mode): |
|
913 | 1188 | return ifile(self.base).__xrepr__(mode) |
@@ -929,7 +1204,7 b' class iglob(Table):' | |||
|
929 | 1204 | def __init__(self, glob): |
|
930 | 1205 | self.glob = glob |
|
931 | 1206 | |
|
932 |
def __ |
|
|
1207 | def __iter__(self): | |
|
933 | 1208 | for name in glob.glob(self.glob): |
|
934 | 1209 | yield ifile(name) |
|
935 | 1210 | |
@@ -958,7 +1233,7 b' class iwalk(Table):' | |||
|
958 | 1233 | self.dirs = dirs |
|
959 | 1234 | self.files = files |
|
960 | 1235 | |
|
961 |
def __ |
|
|
1236 | def __iter__(self): | |
|
962 | 1237 | for (dirpath, dirnames, filenames) in os.walk(self.base): |
|
963 | 1238 | if self.dirs: |
|
964 | 1239 | for name in sorted(dirnames): |
@@ -1115,7 +1390,7 b' class igrpentry(object):' | |||
|
1115 | 1390 | else: |
|
1116 | 1391 | yield (astyle.style_default, repr(self)) |
|
1117 | 1392 | |
|
1118 |
def __ |
|
|
1393 | def __iter__(self): | |
|
1119 | 1394 | for member in self.mem: |
|
1120 | 1395 | yield ipwdentry(member) |
|
1121 | 1396 | |
@@ -1128,7 +1403,7 b' class igrp(Table):' | |||
|
1128 | 1403 | """ |
|
1129 | 1404 | This ``Table`` lists all entries in the Unix group database. |
|
1130 | 1405 | """ |
|
1131 |
def __ |
|
|
1406 | def __iter__(self): | |
|
1132 | 1407 | for entry in grp.getgrall(): |
|
1133 | 1408 | yield igrpentry(entry.gr_name) |
|
1134 | 1409 | |
@@ -1141,7 +1416,7 b' class igrp(Table):' | |||
|
1141 | 1416 | |
|
1142 | 1417 | class Fields(object): |
|
1143 | 1418 | def __init__(self, fieldnames, **fields): |
|
1144 | self.__fieldnames = fieldnames | |
|
1419 | self.__fieldnames = [upgradexattr(fieldname) for fieldname in fieldnames] | |
|
1145 | 1420 | for (key, value) in fields.iteritems(): |
|
1146 | 1421 | setattr(self, key, value) |
|
1147 | 1422 | |
@@ -1156,7 +1431,7 b' class Fields(object):' | |||
|
1156 | 1431 | for (i, f) in enumerate(self.__fieldnames): |
|
1157 | 1432 | if i: |
|
1158 | 1433 | yield (astyle.style_default, ", ") |
|
1159 | yield (astyle.style_default, f) | |
|
1434 | yield (astyle.style_default, f.name()) | |
|
1160 | 1435 | yield (astyle.style_default, "=") |
|
1161 | 1436 | for part in xrepr(getattr(self, f), "default"): |
|
1162 | 1437 | yield part |
@@ -1167,7 +1442,7 b' class Fields(object):' | |||
|
1167 | 1442 | for (i, f) in enumerate(self.__fieldnames): |
|
1168 | 1443 | if i: |
|
1169 | 1444 | yield (astyle.style_default, ", ") |
|
1170 | yield (astyle.style_default, f) | |
|
1445 | yield (astyle.style_default, f.name()) | |
|
1171 | 1446 | yield (astyle.style_default, ")") |
|
1172 | 1447 | else: |
|
1173 | 1448 | yield (astyle.style_default, repr(self)) |
@@ -1182,9 +1457,6 b' class FieldTable(Table, list):' | |||
|
1182 | 1457 | def add(self, **fields): |
|
1183 | 1458 | self.append(Fields(self.fields, **fields)) |
|
1184 | 1459 | |
|
1185 | def __xiter__(self, mode): | |
|
1186 | return list.__iter__(self) | |
|
1187 | ||
|
1188 | 1460 | def __xrepr__(self, mode): |
|
1189 | 1461 | yield (-1, False) |
|
1190 | 1462 | if mode == "header" or mode == "footer": |
@@ -1232,7 +1504,7 b' class ienv(Table):' | |||
|
1232 | 1504 | >>> ienv |
|
1233 | 1505 | """ |
|
1234 | 1506 | |
|
1235 |
def __ |
|
|
1507 | def __iter__(self): | |
|
1236 | 1508 | fields = ("key", "value") |
|
1237 | 1509 | for (key, value) in os.environ.iteritems(): |
|
1238 | 1510 | yield Fields(fields, key=key, value=value) |
@@ -1256,7 +1528,7 b' class icsv(Pipe):' | |||
|
1256 | 1528 | """ |
|
1257 | 1529 | self.csvargs = csvargs |
|
1258 | 1530 | |
|
1259 |
def __ |
|
|
1531 | def __iter__(self): | |
|
1260 | 1532 | input = self.input |
|
1261 | 1533 | if isinstance(input, ifile): |
|
1262 | 1534 | input = input.open("rb") |
@@ -1304,7 +1576,7 b' class ix(Table):' | |||
|
1304 | 1576 | self.cmd = cmd |
|
1305 | 1577 | self._pipeout = None |
|
1306 | 1578 | |
|
1307 |
def __ |
|
|
1579 | def __iter__(self): | |
|
1308 | 1580 | (_pipein, self._pipeout) = os.popen4(self.cmd) |
|
1309 | 1581 | _pipein.close() |
|
1310 | 1582 | for l in self._pipeout: |
@@ -1364,7 +1636,7 b' class ifilter(Pipe):' | |||
|
1364 | 1636 | self.globals = globals |
|
1365 | 1637 | self.errors = errors |
|
1366 | 1638 | |
|
1367 |
def __ |
|
|
1639 | def __iter__(self): | |
|
1368 | 1640 | if callable(self.expr): |
|
1369 | 1641 | test = self.expr |
|
1370 | 1642 | else: |
@@ -1375,7 +1647,7 b' class ifilter(Pipe):' | |||
|
1375 | 1647 | |
|
1376 | 1648 | ok = 0 |
|
1377 | 1649 | exc_info = None |
|
1378 |
for item in xiter(self.input |
|
|
1650 | for item in xiter(self.input): | |
|
1379 | 1651 | try: |
|
1380 | 1652 | if test(item): |
|
1381 | 1653 | yield item |
@@ -1437,7 +1709,7 b' class ieval(Pipe):' | |||
|
1437 | 1709 | self.globals = globals |
|
1438 | 1710 | self.errors = errors |
|
1439 | 1711 | |
|
1440 |
def __ |
|
|
1712 | def __iter__(self): | |
|
1441 | 1713 | if callable(self.expr): |
|
1442 | 1714 | do = self.expr |
|
1443 | 1715 | else: |
@@ -1448,7 +1720,7 b' class ieval(Pipe):' | |||
|
1448 | 1720 | |
|
1449 | 1721 | ok = 0 |
|
1450 | 1722 | exc_info = None |
|
1451 |
for item in xiter(self.input |
|
|
1723 | for item in xiter(self.input): | |
|
1452 | 1724 | try: |
|
1453 | 1725 | yield do(item) |
|
1454 | 1726 | except (KeyboardInterrupt, SystemExit): |
@@ -1497,9 +1769,9 b' class ienum(Pipe):' | |||
|
1497 | 1769 | |
|
1498 | 1770 | >>> xrange(20) | ieval("_,_*_") | ienum | ifilter("index % 2 == 0") | ieval("object") |
|
1499 | 1771 | """ |
|
1500 |
def __ |
|
|
1772 | def __iter__(self): | |
|
1501 | 1773 | fields = ("index", "object") |
|
1502 |
for (index, object) in enumerate(xiter(self.input |
|
|
1774 | for (index, object) in enumerate(xiter(self.input)): | |
|
1503 | 1775 | yield Fields(fields, index=index, object=object) |
|
1504 | 1776 | |
|
1505 | 1777 | |
@@ -1524,18 +1796,11 b' class isort(Pipe):' | |||
|
1524 | 1796 | self.globals = globals |
|
1525 | 1797 | self.reverse = reverse |
|
1526 | 1798 | |
|
1527 |
def __ |
|
|
1799 | def __iter__(self): | |
|
1528 | 1800 | if self.key is None: |
|
1529 | items = sorted( | |
|
1530 | xiter(self.input, mode), | |
|
1531 | reverse=self.reverse | |
|
1532 | ) | |
|
1801 | items = sorted(xiter(self.input), reverse=self.reverse) | |
|
1533 | 1802 | elif callable(self.key): |
|
1534 | items = sorted( | |
|
1535 | xiter(self.input, mode), | |
|
1536 | key=self.key, | |
|
1537 | reverse=self.reverse | |
|
1538 | ) | |
|
1803 | items = sorted(xiter(self.input), key=self.key, reverse=self.reverse) | |
|
1539 | 1804 | else: |
|
1540 | 1805 | g = getglobals(self.globals) |
|
1541 | 1806 | key = compile(self.key, "ipipe-expression", "eval") |
@@ -1613,8 +1878,8 b' class iless(Display):' | |||
|
1613 | 1878 | pager = os.popen(self.cmd, "w") |
|
1614 | 1879 | try: |
|
1615 | 1880 | for item in xiter(self.input, "default"): |
|
1616 | attrs = xattrs(item, "default") | |
|
1617 |
attrs = ["%s=%s" % (a |
|
|
1881 | attrs = tuple(_upgradexattrs(item, "default")) | |
|
1882 | attrs = ["%s=%s" % (a.name(item), a.value(item)) for a in attrs] | |
|
1618 | 1883 | pager.write(" ".join(attrs)) |
|
1619 | 1884 | pager.write("\n") |
|
1620 | 1885 | finally: |
@@ -1659,7 +1924,7 b' class idump(Display):' | |||
|
1659 | 1924 | style_header = astyle.Style.fromstr("white:black:bold") |
|
1660 | 1925 | |
|
1661 | 1926 | def __init__(self, *attrs): |
|
1662 | self.attrs = attrs | |
|
1927 | self.attrs = [upgradexattr(attr) for attr in attrs] | |
|
1663 | 1928 | self.headerpadchar = " " |
|
1664 | 1929 | self.headersepchar = "|" |
|
1665 | 1930 | self.datapadchar = " " |
@@ -1668,7 +1933,7 b' class idump(Display):' | |||
|
1668 | 1933 | def display(self): |
|
1669 | 1934 | stream = genutils.Term.cout |
|
1670 | 1935 | allattrs = [] |
|
1671 |
|
|
|
1936 | attrset = set() | |
|
1672 | 1937 | colwidths = {} |
|
1673 | 1938 | rows = [] |
|
1674 | 1939 | for item in xiter(self.input, "default"): |
@@ -1676,42 +1941,43 b' class idump(Display):' | |||
|
1676 | 1941 | attrs = self.attrs |
|
1677 | 1942 | if not attrs: |
|
1678 | 1943 | attrs = xattrs(item, "default") |
|
1679 |
for attr |
|
|
1680 |
if attr |
|
|
1681 |
allattrs.append(attr |
|
|
1682 |
|
|
|
1683 |
colwidths[attr |
|
|
1944 | for attr in attrs: | |
|
1945 | if attr not in attrset: | |
|
1946 | allattrs.append(attr) | |
|
1947 | attrset.add(attr) | |
|
1948 | colwidths[attr] = len(attr.name()) | |
|
1684 | 1949 | try: |
|
1685 |
value = |
|
|
1950 | value = attr.value(item) | |
|
1686 | 1951 | except (KeyboardInterrupt, SystemExit): |
|
1687 | 1952 | raise |
|
1688 | 1953 | except Exception, exc: |
|
1689 | 1954 | value = exc |
|
1690 | 1955 | (align, width, text) = xformat(value, "cell", self.maxattrlength) |
|
1691 |
colwidths[attr |
|
|
1956 | colwidths[attr] = max(colwidths[attr], width) | |
|
1692 | 1957 | # remember alignment, length and colored parts |
|
1693 |
row[attr |
|
|
1958 | row[attr] = (align, width, text) | |
|
1694 | 1959 | rows.append(row) |
|
1695 | 1960 | |
|
1696 | 1961 | stream.write("\n") |
|
1697 |
for (i, attr |
|
|
1698 | self.style_header(_attrname(attrname)).write(stream) | |
|
1699 | spc = colwidths[attrname] - len(_attrname(attrname)) | |
|
1962 | for (i, attr) in enumerate(allattrs): | |
|
1963 | attrname = attr.name() | |
|
1964 | self.style_header(attrname).write(stream) | |
|
1965 | spc = colwidths[attr] - len(attrname) | |
|
1700 | 1966 | if i < len(colwidths)-1: |
|
1701 | 1967 | stream.write(self.headerpadchar*spc) |
|
1702 | 1968 | stream.write(self.headersepchar) |
|
1703 | 1969 | stream.write("\n") |
|
1704 | 1970 | |
|
1705 | 1971 | for row in rows: |
|
1706 |
for (i, attr |
|
|
1707 |
(align, width, text) = row[attr |
|
|
1708 |
spc = colwidths[attr |
|
|
1972 | for (i, attr) in enumerate(allattrs): | |
|
1973 | (align, width, text) = row[attr] | |
|
1974 | spc = colwidths[attr] - width | |
|
1709 | 1975 | if align == -1: |
|
1710 | 1976 | text.write(stream) |
|
1711 | 1977 | if i < len(colwidths)-1: |
|
1712 | 1978 | stream.write(self.datapadchar*spc) |
|
1713 | 1979 | elif align == 0: |
|
1714 |
spc = colwidths[attr |
|
|
1980 | spc = colwidths[attr] - width | |
|
1715 | 1981 | spc1 = spc//2 |
|
1716 | 1982 | spc2 = spc-spc1 |
|
1717 | 1983 | stream.write(self.datapadchar*spc1) |
@@ -1755,55 +2021,57 b' class XMode(object):' | |||
|
1755 | 2021 | |
|
1756 | 2022 | def __xattrs__(self, mode): |
|
1757 | 2023 | if mode == "detail": |
|
2024 | return ("object", "mode") | |
|
2025 | else: | |
|
1758 | 2026 | return ("object", "mode", "title", "description") |
|
1759 | return ("title", "description") | |
|
1760 | 2027 | |
|
1761 | 2028 | def __xiter__(self, mode): |
|
1762 | 2029 | return xiter(self.object, self.mode) |
|
1763 | 2030 | |
|
1764 | 2031 | |
|
1765 |
class |
|
|
1766 |
def __init__(self, object, |
|
|
1767 | self.name = _attrname(name) | |
|
2032 | class AttributeDetail(Table): | |
|
2033 | def __init__(self, object, descriptor): | |
|
2034 | self.object = object | |
|
2035 | self.descriptor = descriptor | |
|
1768 | 2036 | |
|
1769 | try: | |
|
1770 | self.value = _getattr(object, name) | |
|
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__) | |
|
2037 | def __iter__(self): | |
|
2038 | return self.descriptor.iter(self.object) | |
|
1786 | 2039 | |
|
1787 | doc = None | |
|
1788 | if isinstance(name, basestring): | |
|
1789 | if name.endswith("()"): | |
|
1790 | doc = getattr(getattr(object, name[:-2]), "__doc__", None) | |
|
1791 | else: | |
|
1792 | try: | |
|
1793 | meta = getattr(type(object), name) | |
|
1794 | except AttributeError: | |
|
1795 | pass | |
|
1796 | else: | |
|
1797 | if isinstance(meta, property): | |
|
1798 | doc = getattr(meta, "__doc__", None) | |
|
1799 | elif callable(name): | |
|
1800 | doc = getattr(name, "__doc__", None) | |
|
1801 | if isinstance(doc, basestring): | |
|
1802 | doc = doc.strip() | |
|
1803 | self.doc = doc | |
|
2040 | def name(self): | |
|
2041 | return self.descriptor.name() | |
|
2042 | ||
|
2043 | def attrtype(self): | |
|
2044 | return self.descriptor.attrtype(self.object) | |
|
2045 | ||
|
2046 | def valuetype(self): | |
|
2047 | return self.descriptor.valuetype(self.object) | |
|
2048 | ||
|
2049 | def doc(self): | |
|
2050 | return self.descriptor.doc(self.object) | |
|
2051 | ||
|
2052 | def shortdoc(self): | |
|
2053 | return self.descriptor.shortdoc(self.object) | |
|
2054 | ||
|
2055 | def value(self): | |
|
2056 | return self.descriptor.value(self.object) | |
|
1804 | 2057 | |
|
1805 | 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 | 2077 | try: |
@@ -3,6 +3,27 b'' | |||
|
3 | 3 | * IPython/Extensions/ipipe.py: Fix getglobals() if we're |
|
4 | 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 | 27 | 2006-07-26 Ville Vainio <vivainio@gmail.com> |
|
7 | 28 | |
|
8 | 29 | * iplib.py: history now stores multiline input as single |
General Comments 0
You need to be logged in to leave comments.
Login now