1.1 --- a/viewer.py Sun Feb 18 01:39:11 2007 +0100
1.2 +++ b/viewer.py Thu Feb 22 22:06:10 2007 +0100
1.3 @@ -127,13 +127,13 @@
1.4 Covered: Add, And, AssAttr, AssList, AssName, AssTuple, Assign, AugAssign,
1.5 Break, CallFunc, Class, Compare, Const, Continue, Dict, Discard,
1.6 Div, FloorDiv, For, From, Function, Getattr, Global, If, Import,
1.7 - Keyword, Lambda, List, Mod, Module, Mul, Name, Not, Or, Pass,
1.8 - Power, Print, Printnl, Raise, Return, Slice, Stmt, Sub, Subscript,
1.9 - TryExcept, TryFinally, Tuple, UnaryAdd, UnarySub, While.
1.10 + Keyword, Lambda, List, ListComp, ListCompFor, ListCompIf, Mod,
1.11 + Module, Mul, Name, Not, Or, Pass, Power, Print, Printnl, Raise,
1.12 + Return, Slice, Sliceobj, Stmt, Sub, Subscript, TryExcept,
1.13 + TryFinally, Tuple, UnaryAdd, UnarySub, While.
1.14
1.15 Missing: Assert, Backquote, Bitand, Bitor, Bitxor, Decorators, Ellipsis,
1.16 - Exec, Invert, LeftShift, ListComp, ListCompFor, ListCompIf,
1.17 - RightShift, Sliceobj, Yield.
1.18 + Exec, Invert, LeftShift, RightShift, Yield.
1.19 """
1.20
1.21 def __init__(self, stream):
1.22 @@ -164,11 +164,9 @@
1.23 self.dispatch(node.node)
1.24 self.stream.write("<span class='operator'>\n")
1.25 self.stream.write("%s\n" % node.op)
1.26 - self._popup_start()
1.27 - self.stream.write("<div class='invocations'>\n")
1.28 - self._invocations_list(node._op_call.active())
1.29 - self.stream.write("</div>\n")
1.30 - self._popup_end()
1.31 + self._popup(
1.32 + self._invocations(node._op_call.active())
1.33 + )
1.34 self.stream.write("</span>\n")
1.35 self.dispatch(node.expr)
1.36 self.stream.write("</div>\n")
1.37 @@ -186,9 +184,9 @@
1.38 self.stream.write("<div>\n")
1.39 self._keyword("class")
1.40 self._name_start(structure.name)
1.41 - self._popup_start()
1.42 - self._scopes(definitions)
1.43 - self._popup_end()
1.44 + self._popup(
1.45 + self._scopes(definitions)
1.46 + )
1.47 self._name_end()
1.48 bases = structure.bases
1.49
1.50 @@ -201,10 +199,10 @@
1.51 if not first:
1.52 self.stream.write(",\n")
1.53 self._name_start(base.name)
1.54 - self._popup_start()
1.55 - self._scopes([base])
1.56 - self._types([base])
1.57 - self._popup_end()
1.58 + self._popup(
1.59 + self._scopes([base]) +
1.60 + self._types([base])
1.61 + )
1.62 self._name_end()
1.63 first = 0
1.64 self.stream.write(")")
1.65 @@ -234,16 +232,16 @@
1.66 self.stream.write("<div>\n")
1.67 self.stream.write("<span class='iterator'>\n")
1.68 self._keyword("for")
1.69 - self._popup_start()
1.70 - self._invocations(node._next_call.active())
1.71 - self._popup_end()
1.72 + self._popup(
1.73 + self._invocations(node._next_call.active())
1.74 + )
1.75 self.stream.write("</span>\n")
1.76 self.dispatch(node.assign)
1.77 self.stream.write("<span class='iterator'>\n")
1.78 self._keyword("in")
1.79 - self._popup_start()
1.80 - self._invocations(node._iter_call.active())
1.81 - self._popup_end()
1.82 + self._popup(
1.83 + self._invocations(node._iter_call.active())
1.84 + )
1.85 self.stream.write("</span>\n")
1.86 self.dispatch(node.list)
1.87 self.stream.write(":\n")
1.88 @@ -266,9 +264,9 @@
1.89 self._keyword("from")
1.90 self.stream.write("<span class='name'>\n")
1.91 self.stream.write(node.modname)
1.92 - self._popup_start()
1.93 - self._types(node._modname.active())
1.94 - self._popup_end()
1.95 + self._popup(
1.96 + self._types(node._modname.active())
1.97 + )
1.98 self.stream.write("</span>\n")
1.99 self._keyword("import")
1.100 first = 1
1.101 @@ -280,9 +278,9 @@
1.102 self._keyword("as")
1.103 self.stream.write("<span class='name'>\n")
1.104 self.stream.write(alias or name)
1.105 - self._popup_start()
1.106 - self._types([_name])
1.107 - self._popup_end()
1.108 + self._popup(
1.109 + self._types([_name])
1.110 + )
1.111 self.stream.write("</span>\n")
1.112 first = 0
1.113 self.stream.write("</div>\n")
1.114 @@ -296,10 +294,10 @@
1.115 self.stream.write("<div>\n")
1.116 self._keyword("def")
1.117 self._name_start(subprogram.name)
1.118 - self._popup_start()
1.119 - self._scopes([definition]) # not dependent on subprograms
1.120 - self._raises(subprograms)
1.121 - self._popup_end()
1.122 + self._popup(
1.123 + self._scopes([definition]) + # not dependent on subprograms
1.124 + self._raises(subprograms)
1.125 + )
1.126 self._name_end()
1.127 self.stream.write("(")
1.128 self._parameters(subprogram, subprograms)
1.129 @@ -337,9 +335,9 @@
1.130 self._keyword("if")
1.131 else:
1.132 self._keyword("elif")
1.133 - self._popup_start()
1.134 - self._invocations([c.test for c in conditionals])
1.135 - self._popup_end()
1.136 + self._popup(
1.137 + self._invocations([c.test for c in conditionals])
1.138 + )
1.139 self.stream.write("</span>\n")
1.140 self.dispatch(compare)
1.141 self.stream.write(":\n")
1.142 @@ -349,8 +347,10 @@
1.143 self.stream.write("</div>\n")
1.144 if conditional.else_:
1.145 conditional = conditional.else_[0]
1.146 + conditionals = conditional.active()
1.147 else:
1.148 conditional = None
1.149 + conditionals = []
1.150 first = 0
1.151 if node.else_ is not None:
1.152 self.stream.write("<div>\n")
1.153 @@ -374,9 +374,9 @@
1.154 self._keyword("as")
1.155 self.stream.write("<span class='name'>\n")
1.156 self.stream.write(alias or name)
1.157 - self._popup_start()
1.158 - self._types([_name])
1.159 - self._popup_end()
1.160 + self._popup(
1.161 + self._types([_name])
1.162 + )
1.163 self.stream.write("</span>\n")
1.164 first = 0
1.165 self.stream.write("</div>\n")
1.166 @@ -429,9 +429,9 @@
1.167 self.stream.write("<div class='return'>\n")
1.168 self.stream.write("<span class='returns'>\n")
1.169 self._keyword("return")
1.170 - self._popup_start()
1.171 - self._types(values)
1.172 - self._popup_end()
1.173 + self._popup(
1.174 + self._types(values)
1.175 + )
1.176 self.stream.write("</span>\n")
1.177 self.dispatch(node.value)
1.178 self.stream.write("</div>\n")
1.179 @@ -496,9 +496,9 @@
1.180 self.stream.write("<div>\n")
1.181 self.stream.write("<span class='conditional'>\n")
1.182 self._keyword("while")
1.183 - self._popup_start()
1.184 - self._invocations(node._test_call.active())
1.185 - self._popup_end()
1.186 + self._popup(
1.187 + self._invocations(node._test_call.active())
1.188 + )
1.189 self.stream.write("</span>\n")
1.190 self.dispatch(node.test)
1.191 self.stream.write(":\n")
1.192 @@ -523,11 +523,9 @@
1.193 self.dispatch(node.left)
1.194 self.stream.write("<span class='operator'>\n")
1.195 self.stream.write(symbol)
1.196 - self._popup_start()
1.197 - self.stream.write("<div class='invocations'>\n")
1.198 - self._invocations_list(node._left_call.active() + node._right_call.active())
1.199 - self.stream.write("</div>\n")
1.200 - self._popup_end()
1.201 + self._popup(
1.202 + self._invocations(node._left_call.active() + node._right_call.active())
1.203 + )
1.204 self.stream.write("</span>\n")
1.205 self.dispatch(node.right)
1.206 self.stream.write("</span>")
1.207 @@ -536,11 +534,9 @@
1.208 self.stream.write("<span class='%s'>\n" % name)
1.209 self.stream.write("<span class='operator'>\n")
1.210 self.stream.write(symbol)
1.211 - self._popup_start()
1.212 - self.stream.write("<div class='invocations'>\n")
1.213 - self._invocations_list(node._unary_call.active())
1.214 - self.stream.write("</div>\n")
1.215 - self._popup_end()
1.216 + self._popup(
1.217 + self._invocations(node._unary_call.active())
1.218 + )
1.219 self.stream.write("</span>\n")
1.220 self.dispatch(node.expr)
1.221 self.stream.write("</span>")
1.222 @@ -567,10 +563,10 @@
1.223 self.dispatch(node.expr)
1.224 self.stream.write("<span class='attr'>\n")
1.225 self.stream.write(".%s\n" % self._text(node.attrname))
1.226 - self._popup_start()
1.227 - self._scopes(targets)
1.228 - self._types(targets)
1.229 - self._popup_end()
1.230 + self._popup(
1.231 + self._scopes(targets) +
1.232 + self._types(targets)
1.233 + )
1.234 self.stream.write("</span>\n")
1.235 self.stream.write("</span>\n")
1.236
1.237 @@ -585,10 +581,10 @@
1.238 target = node._node
1.239 targets = target.active()
1.240 self._name_start(target.name)
1.241 - self._popup_start()
1.242 - self._scopes(targets)
1.243 - self._types(targets)
1.244 - self._popup_end()
1.245 + self._popup(
1.246 + self._scopes(targets) +
1.247 + self._types(targets)
1.248 + )
1.249 self._name_end()
1.250
1.251 def visitAssTuple(self, node):
1.252 @@ -605,9 +601,9 @@
1.253 self.dispatch(node.node)
1.254 self.stream.write("<span class='call'>\n")
1.255 self.stream.write("(")
1.256 - self._popup_start()
1.257 - self._invocations(targets)
1.258 - self._popup_end()
1.259 + self._popup(
1.260 + self._invocations(targets)
1.261 + )
1.262 self.stream.write("</span>\n")
1.263 first = 1
1.264 for arg in node.args:
1.265 @@ -634,9 +630,9 @@
1.266 for op in node._ops:
1.267 self.stream.write("<span class='op'>\n")
1.268 self.stream.write(op.name)
1.269 - self._popup_start()
1.270 - self._op(op)
1.271 - self._popup_end()
1.272 + self._popup(
1.273 + self._op(op)
1.274 + )
1.275 self.stream.write("</span>\n")
1.276 self.dispatch(op.expr)
1.277 self.stream.write("</span>\n")
1.278 @@ -664,10 +660,10 @@
1.279 self.dispatch(node.expr)
1.280 self.stream.write("<span class='attr'>\n")
1.281 self.stream.write(".%s\n" % self._text(node.attrname))
1.282 - self._popup_start()
1.283 - self._scopes(targets)
1.284 - self._types(targets)
1.285 - self._popup_end()
1.286 + self._popup(
1.287 + self._scopes(targets) +
1.288 + self._types(targets)
1.289 + )
1.290 self.stream.write("</span>\n")
1.291 self.stream.write("</span>\n")
1.292
1.293 @@ -691,6 +687,48 @@
1.294
1.295 visitList = visitAssList
1.296
1.297 + def visitListComp(self, node):
1.298 + self.stream.write("<span class='listcomp'>\n")
1.299 + self.stream.write("[")
1.300 + self.dispatch(node.expr)
1.301 + for qual in node.quals:
1.302 + self.dispatch(qual)
1.303 + self.stream.write("]\n")
1.304 + self.stream.write("</span>\n")
1.305 +
1.306 + def visitListCompFor(self, node):
1.307 + self.stream.write("<span class='listcompfor'>\n")
1.308 + self.stream.write("<span class='iterator'>\n")
1.309 + self._keyword("for")
1.310 + self._popup(
1.311 + self._invocations(node._next_call.active())
1.312 + )
1.313 + self.stream.write("</span>\n")
1.314 + self.dispatch(node.assign)
1.315 + self.stream.write("<span class='iterator'>\n")
1.316 + self._keyword("in")
1.317 + self._popup(
1.318 + self._invocations(node._iter_call.active())
1.319 + )
1.320 + self.stream.write("</span>\n")
1.321 + self.dispatch(node.list)
1.322 + for if_ in node.ifs:
1.323 + self.dispatch(if_)
1.324 + self.stream.write("</span>\n")
1.325 +
1.326 + def visitListCompIf(self, node):
1.327 + conditional = node._node
1.328 + conditionals = conditional.active()
1.329 + self.stream.write("<span class='listcompif'>\n")
1.330 + self.stream.write("<span class='conditional'>\n")
1.331 + self._keyword("if")
1.332 + self._popup(
1.333 + self._invocations([c.test for c in conditionals])
1.334 + )
1.335 + self.stream.write("</span>\n")
1.336 + self.dispatch(node.test)
1.337 + self.stream.write("</span>\n")
1.338 +
1.339 def visitMod(self, node):
1.340 self._visitBinary(node, "mod", "%")
1.341
1.342 @@ -701,10 +739,10 @@
1.343 target = node._node
1.344 targets = target.active()
1.345 self._name_start(target.name)
1.346 - self._popup_start()
1.347 - self._scopes(targets)
1.348 - self._types(targets)
1.349 - self._popup_end()
1.350 + self._popup(
1.351 + self._scopes(targets) +
1.352 + self._types(targets)
1.353 + )
1.354 self._name_end()
1.355
1.356 def visitNot(self, node):
1.357 @@ -739,6 +777,15 @@
1.358 self.stream.write("]")
1.359 self.stream.write("</span>\n")
1.360
1.361 + def visitSliceobj(self, node):
1.362 + self.stream.write("<span class='sliceobj'>\n")
1.363 + first = 1
1.364 + for n in node.nodes:
1.365 + if not first:
1.366 + self.stream.write(":")
1.367 + self.dispatch(n)
1.368 + self.stream.write("</span>\n")
1.369 +
1.370 def visitSub(self, node):
1.371 self._visitBinary(node, "sub", "-")
1.372
1.373 @@ -837,11 +884,9 @@
1.374 self.stream.write(",\n")
1.375 main_param, main_default = subprogram.params[n]
1.376 self._name_start(main_param)
1.377 - self._popup_start()
1.378 - self.stream.write("<div class='types'>\n")
1.379 - self._parameter(subprograms, params, n)
1.380 - self.stream.write("</div>\n")
1.381 - self._popup_end()
1.382 + self._popup(
1.383 + self._parameter(subprograms, params, n)
1.384 + )
1.385 self._name_end()
1.386 self._default(main_default)
1.387 first = 0
1.388 @@ -851,11 +896,9 @@
1.389 self.stream.write(", *\n")
1.390 main_param, main_default = subprogram.star
1.391 self._name_start(main_param)
1.392 - self._popup_start()
1.393 - self.stream.write("<div class='types'>\n")
1.394 - self._parameter(subprograms, stars)
1.395 - self.stream.write("</div>\n")
1.396 - self._popup_end()
1.397 + self._popup(
1.398 + self._parameter(subprograms, stars)
1.399 + )
1.400 self._name_end()
1.401 self._default(main_default)
1.402 first = 0
1.403 @@ -865,11 +908,9 @@
1.404 self.stream.write(", **\n")
1.405 main_param, main_default = subprogram.dstar
1.406 self._name_start(main_param)
1.407 - self._popup_start()
1.408 - self.stream.write("<div class='types'>\n")
1.409 - self._parameter(subprograms, dstars)
1.410 - self.stream.write("</div>\n")
1.411 - self._popup_end()
1.412 + self._popup(
1.413 + self._parameter(subprograms, dstars)
1.414 + )
1.415 self._name_end()
1.416 self._default(main_default)
1.417 first = 0
1.418 @@ -884,7 +925,7 @@
1.419 param, default = params[i]
1.420 if hasattr(subprogram, "paramtypes"):
1.421 types += subprogram.paramtypes[param]
1.422 - self._types_list(types)
1.423 + return self._types_container(types, "types")
1.424
1.425 def _default(self, default):
1.426 if default is not None and default.original is not None:
1.427 @@ -900,29 +941,28 @@
1.428 def _name_end(self):
1.429 self.stream.write("</span>\n")
1.430
1.431 - def _popup_start(self):
1.432 - self.stream.write("<span class='popup'>\n")
1.433 -
1.434 - def _popup_end(self):
1.435 - self.stream.write("</span>\n")
1.436 + def _popup(self, info):
1.437 + if info:
1.438 + self.stream.write("<span class='popup'>\n")
1.439 + for section, subsection, labels in info:
1.440 + self.stream.write("<div class='%s'>\n" % section)
1.441 + for label in labels:
1.442 + self.stream.write("<div class='%s'>\n" % subsection)
1.443 + self.stream.write(label)
1.444 + self.stream.write("</div>\n")
1.445 + self.stream.write("</div>\n")
1.446 + self.stream.write("</span>\n")
1.447
1.448 def _op(self, node):
1.449 - self.stream.write("<div class='invocations'>\n")
1.450 if hasattr(node, "_left_call") and hasattr(node, "_right_call"):
1.451 - self._invocations_list(node._left_call.active() + node._right_call.active())
1.452 + return self._invocations(node._left_call.active() + node._right_call.active())
1.453 else:
1.454 _node = node._node
1.455 if isinstance(_node, Not):
1.456 _node = _node.expr
1.457 - self._invocations_list(_node.active())
1.458 - self.stream.write("</div>\n")
1.459 + return self._invocations(_node.active())
1.460
1.461 def _invocations(self, nodes):
1.462 - self.stream.write("<div class='invocations'>\n")
1.463 - self._invocations_list(nodes)
1.464 - self.stream.write("</div>\n")
1.465 -
1.466 - def _invocations_list(self, nodes):
1.467 invocations = []
1.468 for node in nodes:
1.469 if hasattr(node, "invocations"):
1.470 @@ -946,112 +986,95 @@
1.471
1.472 # Produce the list.
1.473
1.474 - for label, link in links.items():
1.475 - self.stream.write("<div class='invocation'>")
1.476 - self.stream.write("<a href='%s.html#%s'>" % link)
1.477 - self.stream.write(label)
1.478 - self.stream.write("</a>")
1.479 - self.stream.write("</div>\n")
1.480 + if links:
1.481 + popup_labels = []
1.482 + for label, link in links.items():
1.483 + popup_labels.append("<a href='%s.html#%s'>%s</a>" % (link + (label,)))
1.484 + else:
1.485 + popup_labels = []
1.486 +
1.487 + if popup_labels:
1.488 + return [("invocations", "invocation", popup_labels)]
1.489 + else:
1.490 + return []
1.491
1.492 def _types(self, nodes):
1.493 - self.stream.write("<div class='types'>\n")
1.494 all_types = [(getattr(n, "types", []) or flatten(getattr(n, "writes", {}).values())) for n in nodes]
1.495 types = flatten(all_types)
1.496 - if not types:
1.497 - self._no_types()
1.498 - else:
1.499 - self._types_list(types)
1.500 - self.stream.write("</div>\n")
1.501 -
1.502 - def _unvisited(self):
1.503 - self.stream.write("<div class='type'>")
1.504 - self.stream.write("unvisited\n")
1.505 - self.stream.write("</div>\n")
1.506 -
1.507 - def _no_types(self):
1.508 - self.stream.write("<div class='type'>")
1.509 - self.stream.write("no types\n")
1.510 - self.stream.write("</div>\n")
1.511 + return self._types_container(types, "types")
1.512
1.513 def _types_container(self, types, style_class):
1.514 - self.stream.write("<div class='%s'>\n" % style_class)
1.515 - self._types_list(types)
1.516 - self.stream.write("</div>\n")
1.517 -
1.518 - def _types_list(self, types):
1.519 types = unique(types)
1.520 + labels = {}
1.521 for type in types:
1.522 fn = type.type.full_name()
1.523 - self.stream.write("<div class='type'>")
1.524 - self.stream.write(self._text(fn))
1.525 - self.stream.write("</div>\n")
1.526 + labels[self._text(fn)] = None
1.527 +
1.528 + if labels:
1.529 + return [(style_class, 'type', labels.keys())]
1.530 + else:
1.531 + return []
1.532
1.533 def _raises(self, nodes):
1.534
1.535 "Output the exception information for the given simplified 'nodes'."
1.536
1.537 - self.stream.write("<div class='raises'>\n")
1.538 + raises = []
1.539 for node in nodes:
1.540 if hasattr(node, "raises") and node.raises:
1.541 - self._types_list(node.raises)
1.542 - self.stream.write("</div>\n")
1.543 + raises += node.raises
1.544 + return self._types_container(raises, "raises")
1.545
1.546 def _scopes(self, nodes):
1.547
1.548 "Output the scope information for the given simplified 'nodes'."
1.549
1.550 - self.stream.write("<div class='scopes'>\n")
1.551 + labels = {}
1.552 for node in nodes:
1.553 - self._scope(node)
1.554 - self.stream.write("</div>\n")
1.555
1.556 - def _scope(self, node):
1.557 -
1.558 - "Output the scope information for the given simplified 'node'."
1.559 -
1.560 - # Straightforward name loading/storing involves the local scope.
1.561 + # Straightforward name loading/storing involves the local scope.
1.562
1.563 - if isinstance(node, StoreName) or isinstance(node, LoadName):
1.564 - self.stream.write("<div class='scope'>")
1.565 - self.stream.write("(local)")
1.566 - self.stream.write("</div>\n")
1.567 + if isinstance(node, StoreName) or isinstance(node, LoadName):
1.568 + labels["(local)"] = None
1.569
1.570 - # Other loading/storing involves attributes accessed on modules, classes
1.571 - # and objects.
1.572 + # Other loading/storing involves attributes accessed on modules, classes
1.573 + # and objects.
1.574
1.575 - else:
1.576 + else:
1.577
1.578 - # Loading...
1.579 + # Loading...
1.580
1.581 - if hasattr(node, "accesses") and node.accesses:
1.582 - for ref, accesses in node.accesses.items():
1.583 - fn = ref.full_name()
1.584 - for attr, access in accesses:
1.585 - access_fn = access.full_name()
1.586 - self.stream.write("<div class='scope'>")
1.587 - self.stream.write(self._text(fn))
1.588 - if ref != access:
1.589 - self.stream.write(" (via " + self._text(access_fn) + ")")
1.590 - self.stream.write("</div>\n")
1.591 + if hasattr(node, "accesses") and node.accesses:
1.592 + for ref, accesses in node.accesses.items():
1.593 + fn = ref.full_name()
1.594 + for attr, access in accesses:
1.595 + access_fn = access.full_name()
1.596 + label = self._text(fn)
1.597 + if ref != access:
1.598 + label += " (via " + self._text(access_fn) + ")"
1.599 + labels[label] = None
1.600
1.601 - # Storing...
1.602 + # Storing...
1.603
1.604 - if hasattr(node, "writes") and node.writes:
1.605 - for ref in node.writes.keys():
1.606 - fn = ref.full_name()
1.607 - self.stream.write("<div class='scope'>")
1.608 - self.stream.write(self._text(fn))
1.609 - self.stream.write("</div>\n")
1.610 + if hasattr(node, "writes") and node.writes:
1.611 + for ref in node.writes.keys():
1.612 + fn = ref.full_name()
1.613 + labels[self._text(fn)] = None
1.614 +
1.615 + # Non-loading...
1.616 +
1.617 + if hasattr(node, "non_accesses") and node.non_accesses:
1.618 + self._types_container(node.non_accesses, "non-accesses")
1.619
1.620 - # Non-loading...
1.621 + # Non-storing...
1.622
1.623 - if hasattr(node, "non_accesses") and node.non_accesses:
1.624 - self._types_container(node.non_accesses, "non-accesses")
1.625 + if hasattr(node, "non_writes") and node.non_writes:
1.626 + self._types_container(node.non_writes, "non-writes")
1.627
1.628 - # Non-storing...
1.629 -
1.630 - if hasattr(node, "non_writes") and node.non_writes:
1.631 - self._types_container(node.non_writes, "non-writes")
1.632 + if labels:
1.633 + return [("scopes", "scope", labels.keys())]
1.634 + else:
1.635 + return []
1.636
1.637 # Utility functions.
1.638