1.1 --- a/viewer.py Tue Feb 06 00:56:52 2007 +0100
1.2 +++ b/viewer.py Tue Feb 06 00:57:50 2007 +0100
1.3 @@ -125,15 +125,15 @@
1.4 A browsing visitor for AST nodes.
1.5
1.6 Covered: Add, And, AssAttr, AssList, AssName, AssTuple, Assign, AugAssign,
1.7 - Break, CallFunc, Class, Compare, Const, Continue, Discard,
1.8 + Break, CallFunc, Class, Compare, Const, Continue, Dict, Discard,
1.9 Div, FloorDiv, For, From, Function, Getattr, Global, If, Import,
1.10 Keyword, Lambda, List, Mod, Module, Mul, Name, Not, Or, Pass,
1.11 Power, Print, Printnl, Raise, Return, Slice, Stmt, Sub, Subscript,
1.12 TryExcept, TryFinally, Tuple, UnaryAdd, UnarySub, While.
1.13
1.14 - Missing: Assert, Backquote, Bitand, Bitor, Bitxor, Decorators, Dict,
1.15 - Ellipsis, Exec, Invert, LeftShift, ListComp, ListCompFor,
1.16 - ListCompIf, RightShift, Sliceobj, Yield.
1.17 + Missing: Assert, Backquote, Bitand, Bitor, Bitxor, Decorators, Ellipsis,
1.18 + Exec, Invert, LeftShift, ListComp, ListCompFor, ListCompIf,
1.19 + RightShift, Sliceobj, Yield.
1.20 """
1.21
1.22 def __init__(self, stream):
1.23 @@ -180,13 +180,14 @@
1.24
1.25 def visitClass(self, node):
1.26 definition = node._node
1.27 + definitions = getattr(node, "_nodes", [definition])
1.28 structure = definition.expr.ref
1.29 self.stream.write("<div class='class' id='%s'>\n" % self._url(structure.full_name()))
1.30 self.stream.write("<div>\n")
1.31 self._keyword("class")
1.32 self._name_start(structure.name)
1.33 self._popup_start()
1.34 - self._scopes(definition)
1.35 + self._scopes(definitions)
1.36 self._popup_end()
1.37 self._name_end()
1.38 bases = structure.bases
1.39 @@ -201,8 +202,8 @@
1.40 self.stream.write(",\n")
1.41 self._name_start(base.name)
1.42 self._popup_start()
1.43 - self._types(base)
1.44 - self._scopes(base)
1.45 + self._types([base])
1.46 + self._scopes([base])
1.47 self._popup_end()
1.48 self._name_end()
1.49 first = 0
1.50 @@ -266,7 +267,7 @@
1.51 self.stream.write("<span class='name'>\n")
1.52 self.stream.write(node.modname)
1.53 self._popup_start()
1.54 - self._types(node._modname)
1.55 + self._types([node._modname])
1.56 self._popup_end()
1.57 self.stream.write("</span>\n")
1.58 self._keyword("import")
1.59 @@ -280,7 +281,7 @@
1.60 self.stream.write("<span class='name'>\n")
1.61 self.stream.write(alias or name)
1.62 self._popup_start()
1.63 - self._types(_name)
1.64 + self._types([_name])
1.65 self._popup_end()
1.66 self.stream.write("</span>\n")
1.67 first = 0
1.68 @@ -288,18 +289,20 @@
1.69
1.70 def visitFunction(self, node):
1.71 definition = node._node
1.72 + definitions = [n for n in getattr(node, "_nodes", [definition]) if not isinstance(n, Subprogram)]
1.73 subprogram = definition.expr.ref
1.74 + subprograms = [n for n in getattr(node, "_nodes", [subprogram]) if isinstance(n, Subprogram)]
1.75 self.stream.write("<div class='function' id='%s'>\n" % self._url(subprogram.full_name()))
1.76 self.stream.write("<div>\n")
1.77 self._keyword("def")
1.78 self._name_start(subprogram.name)
1.79 self._popup_start()
1.80 - self._scopes(definition)
1.81 - self._raises(subprogram)
1.82 + self._scopes([definition]) # not dependent on subprograms
1.83 + self._raises(subprograms)
1.84 self._popup_end()
1.85 self._name_end()
1.86 self.stream.write("(")
1.87 - self._parameters(subprogram)
1.88 + self._parameters(subprogram, subprograms)
1.89 self.stream.write(")")
1.90 self.stream.write(":\n")
1.91 self._comment(self._text(subprogram.full_name()))
1.92 @@ -326,6 +329,7 @@
1.93 self.stream.write("<div class='if'>\n")
1.94 first = 1
1.95 conditional = node._node
1.96 + conditionals = getattr(node, "_nodes", [conditional])
1.97 for compare, stmt in node.tests:
1.98 self.stream.write("<div>\n")
1.99 self.stream.write("<span class='conditional'>\n")
1.100 @@ -371,7 +375,7 @@
1.101 self.stream.write("<span class='name'>\n")
1.102 self.stream.write(alias or name)
1.103 self._popup_start()
1.104 - self._types(_name)
1.105 + self._types([_name])
1.106 self._popup_end()
1.107 self.stream.write("</span>\n")
1.108 first = 0
1.109 @@ -420,11 +424,13 @@
1.110 self.stream.write("</div>\n")
1.111
1.112 def visitReturn(self, node):
1.113 + value = node._node
1.114 + values = getattr(node, "_nodes", [value])
1.115 self.stream.write("<div class='return'>\n")
1.116 self.stream.write("<span class='returns'>\n")
1.117 self._keyword("return")
1.118 self._popup_start()
1.119 - self._types(node._node)
1.120 + self._types(values)
1.121 self._popup_end()
1.122 self.stream.write("</span>\n")
1.123 self.dispatch(node.value)
1.124 @@ -556,13 +562,15 @@
1.125 self.stream.write("</span>")
1.126
1.127 def visitAssAttr(self, node):
1.128 + target = node._node
1.129 + targets = getattr(node, "_nodes", [target])
1.130 self.stream.write("<span class='assattr'>\n")
1.131 self.dispatch(node.expr)
1.132 self.stream.write("<span class='attr'>\n")
1.133 self.stream.write(".%s\n" % self._text(node.attrname))
1.134 self._popup_start()
1.135 - self._types(node._node)
1.136 - self._scopes(node._node)
1.137 + self._types(targets)
1.138 + self._scopes(targets)
1.139 self._popup_end()
1.140 self.stream.write("</span>\n")
1.141 self.stream.write("</span>\n")
1.142 @@ -575,10 +583,12 @@
1.143 self.stream.write("</span>\n")
1.144
1.145 def visitAssName(self, node):
1.146 - self._name_start(node._node.name)
1.147 + target = node._node
1.148 + targets = getattr(node, "_nodes", [target])
1.149 + self._name_start(target.name)
1.150 self._popup_start()
1.151 - self._types(node._node.expr)
1.152 - self._scopes(node._node)
1.153 + self._types(targets) # target.expr
1.154 + self._scopes(targets)
1.155 self._popup_end()
1.156 self._name_end()
1.157
1.158 @@ -590,12 +600,14 @@
1.159 self.stream.write("</span>\n")
1.160
1.161 def visitCallFunc(self, node):
1.162 + target = node._node
1.163 + targets = getattr(node, "_nodes", [target])
1.164 self.stream.write("<span class='callfunc'>\n")
1.165 self.dispatch(node.node)
1.166 self.stream.write("<span class='call'>\n")
1.167 self.stream.write("(")
1.168 self._popup_start()
1.169 - self._invocations(node._node)
1.170 + self._invocations(target)
1.171 self._popup_end()
1.172 self.stream.write("</span>\n")
1.173 first = 1
1.174 @@ -633,6 +645,13 @@
1.175 def visitConst(self, node):
1.176 self.stream.write(repr(node.value))
1.177
1.178 + def visitDict(self, node):
1.179 + self.stream.write("<span class='dict'>\n")
1.180 + self.stream.write("{")
1.181 + self._mapping(node)
1.182 + self.stream.write("}\n")
1.183 + self.stream.write("</span>\n")
1.184 +
1.185 def visitDiv(self, node):
1.186 self._visitBinary(node, "div", "/")
1.187
1.188 @@ -640,13 +659,15 @@
1.189 self._visitBinary(node, "floordiv", "//")
1.190
1.191 def visitGetattr(self, node):
1.192 + target = node._node
1.193 + targets = getattr(node, "_nodes", [target])
1.194 self.stream.write("<span class='getattr'>\n")
1.195 self.dispatch(node.expr)
1.196 self.stream.write("<span class='attr'>\n")
1.197 self.stream.write(".%s\n" % self._text(node.attrname))
1.198 self._popup_start()
1.199 - self._types(node._node)
1.200 - self._scopes(node._node)
1.201 + self._types(targets)
1.202 + self._scopes(targets)
1.203 self._popup_end()
1.204 self.stream.write("</span>\n")
1.205 self.stream.write("</span>\n")
1.206 @@ -660,10 +681,12 @@
1.207
1.208 def visitLambda(self, node):
1.209 definition = node._node
1.210 + definitions = [n for n in getattr(node, "_nodes", [definition]) if not isinstance(n, Subprogram)]
1.211 subprogram = definition.expr.ref
1.212 + subprograms = [n for n in getattr(node, "_nodes", [subprogram]) if isinstance(n, Subprogram)]
1.213 self.stream.write("<span class='lambda'>\n")
1.214 self._keyword("lambda")
1.215 - self._parameters(subprogram)
1.216 + self._parameters(subprogram, subprograms)
1.217 self.dispatch(node.code)
1.218 self.stream.write("</span>\n")
1.219
1.220 @@ -676,10 +699,12 @@
1.221 self._visitBinary(node, "mul", "*")
1.222
1.223 def visitName(self, node):
1.224 - self._name_start(node._node.name)
1.225 + target = node._node
1.226 + targets = getattr(node, "_nodes", [target])
1.227 + self._name_start(target.name)
1.228 self._popup_start()
1.229 - self._types(node._node)
1.230 - self._scopes(node._node)
1.231 + self._types(targets)
1.232 + self._scopes(targets)
1.233 self._popup_end()
1.234 self._name_end()
1.235
1.236 @@ -773,33 +798,94 @@
1.237 self.dispatch(n)
1.238 first = 0
1.239
1.240 - def _parameters(self, subprogram):
1.241 + def _mapping(self, node):
1.242 first = 1
1.243 - for param, default in subprogram.params:
1.244 + for k, v in node.items:
1.245 if not first:
1.246 self.stream.write(",\n")
1.247 - self._parameter(subprogram, param, default)
1.248 + self.dispatch(k)
1.249 + self.stream.write(":\n")
1.250 + self.dispatch(v)
1.251 first = 0
1.252 - if subprogram.star is not None:
1.253 +
1.254 + def _parameters(self, subprogram, subprograms):
1.255 +
1.256 + # Get all the parameter lists.
1.257 +
1.258 + params = []
1.259 + nparams = 0
1.260 + for sub in subprograms:
1.261 + params.append(sub.params)
1.262 + nparams = max(nparams, len(sub.params))
1.263 + stars = []
1.264 + have_star = 0
1.265 + for sub in subprograms:
1.266 + stars.append(sub.star)
1.267 + if sub.star is not None:
1.268 + have_star = 1
1.269 + dstars = []
1.270 + have_dstar = 0
1.271 + for sub in subprograms:
1.272 + dstars.append(sub.dstar)
1.273 + if sub.dstar is not None:
1.274 + have_dstar = 1
1.275 +
1.276 + # Traverse the parameter lists, choosing a "column" at a time.
1.277 +
1.278 + first = 1
1.279 + for n in range(0, nparams):
1.280 + if not first:
1.281 + self.stream.write(",\n")
1.282 + main_param, main_default = subprogram.params[n]
1.283 + self._name_start(main_param)
1.284 + self._popup_start()
1.285 + self.stream.write("<div class='types'>\n")
1.286 + for i in range(0, len(subprograms)):
1.287 + param, default = params[i][n]
1.288 + self._parameter(subprograms[i], param)
1.289 + self.stream.write("</div>\n")
1.290 + self._popup_end()
1.291 + self._name_end()
1.292 + self._default(main_default)
1.293 + first = 0
1.294 +
1.295 + if have_star:
1.296 if not first:
1.297 self.stream.write(", *\n")
1.298 - param, default = subprogram.star
1.299 - self._parameter(subprogram, param, default)
1.300 + main_param, main_default = subprogram.star
1.301 + self._name_start(main_param)
1.302 + self._popup_start()
1.303 + self.stream.write("<div class='types'>\n")
1.304 + for i in range(0, len(subprograms)):
1.305 + param, default = stars[i]
1.306 + self._parameter(subprograms[i], param)
1.307 + self.stream.write("</div>\n")
1.308 + self._popup_end()
1.309 + self._name_end()
1.310 + self._default(main_default)
1.311 first = 0
1.312 - if subprogram.dstar is not None:
1.313 +
1.314 + if have_dstar:
1.315 if not first:
1.316 self.stream.write(", **\n")
1.317 - param, default = subprogram.dstar
1.318 - self._parameter(subprogram, param, default)
1.319 + main_param, main_default = subprogram.dstar
1.320 + self._name_start(main_param)
1.321 + self._popup_start()
1.322 + self.stream.write("<div class='types'>\n")
1.323 + for i in range(0, len(subprograms)):
1.324 + param, default = dstars[i]
1.325 + self._parameter(subprograms[i], param)
1.326 + self.stream.write("</div>\n")
1.327 + self._popup_end()
1.328 + self._name_end()
1.329 + self._default(main_default)
1.330 first = 0
1.331
1.332 - def _parameter(self, subprogram, param, default):
1.333 - self._name_start(param)
1.334 + def _parameter(self, subprogram, param):
1.335 if hasattr(subprogram, "paramtypes"):
1.336 - self._popup_start()
1.337 self._types_list(subprogram.paramtypes[param])
1.338 - self._popup_end()
1.339 - self._name_end()
1.340 +
1.341 + def _default(self, default):
1.342 if default is not None and default.original is not None:
1.343 self.stream.write("=\n")
1.344 self.dispatch(default.original)
1.345 @@ -844,7 +930,13 @@
1.346 self.stream.write("</a>")
1.347 self.stream.write("</div>\n")
1.348
1.349 - def _types(self, node):
1.350 + def _types(self, nodes):
1.351 + self.stream.write("<div class='types'>\n")
1.352 + for node in nodes:
1.353 + self._type(node)
1.354 + self.stream.write("</div>\n")
1.355 +
1.356 + def _type(self, node):
1.357 if hasattr(node, "types"):
1.358 if node.types:
1.359 self._types_list(node.types)
1.360 @@ -856,40 +948,59 @@
1.361 else:
1.362 self._no_types()
1.363 else:
1.364 - self.stream.write("<div class='types'>\n")
1.365 - self.stream.write("unvisited\n")
1.366 - self.stream.write("</div>\n")
1.367 + self._unvisited()
1.368 +
1.369 + def _unvisited(self):
1.370 + self.stream.write("<div class='type'>")
1.371 + self.stream.write("unvisited\n")
1.372 + self.stream.write("</div>\n")
1.373
1.374 def _no_types(self):
1.375 - self.stream.write("<div class='types'>\n")
1.376 + self.stream.write("<div class='type'>")
1.377 self.stream.write("no types\n")
1.378 self.stream.write("</div>\n")
1.379
1.380 - def _types_list(self, types, style_class="types"):
1.381 + def _types_container(self, types, style_class):
1.382 self.stream.write("<div class='%s'>\n" % style_class)
1.383 + self._types_list(types)
1.384 + self.stream.write("</div>\n")
1.385 +
1.386 + def _types_list(self, types):
1.387 for type in types:
1.388 fn = type.type.full_name()
1.389 self.stream.write("<div class='type'>")
1.390 self.stream.write(self._text(fn))
1.391 self.stream.write("</div>\n")
1.392 +
1.393 + def _raises(self, nodes):
1.394 +
1.395 + "Output the exception information for the given simplified 'nodes'."
1.396 +
1.397 + self.stream.write("<div class='raises'>\n")
1.398 + for node in nodes:
1.399 + if hasattr(node, "namespace") and hasattr(node.namespace, "raises") and node.namespace.raises:
1.400 + self._types_list(node.namespace.raises)
1.401 self.stream.write("</div>\n")
1.402
1.403 - def _raises(self, node):
1.404 - if hasattr(node, "namespace") and hasattr(node.namespace, "raises") and node.namespace.raises:
1.405 - self._types_list(node.namespace.raises, style_class="raises")
1.406 + def _scopes(self, nodes):
1.407 +
1.408 + "Output the scope information for the given simplified 'nodes'."
1.409
1.410 - def _scopes(self, node):
1.411 + self.stream.write("<div class='scopes'>\n")
1.412 + for node in nodes:
1.413 + self._scope(node)
1.414 + self.stream.write("</div>\n")
1.415 +
1.416 + def _scope(self, node):
1.417
1.418 "Output the scope information for the given simplified 'node'."
1.419
1.420 # Straightforward name loading/storing involves the local scope.
1.421
1.422 if isinstance(node, StoreName) or isinstance(node, LoadName):
1.423 - self.stream.write("<div class='scopes'>\n")
1.424 self.stream.write("<div class='scope'>")
1.425 self.stream.write("(local)")
1.426 self.stream.write("</div>\n")
1.427 - self.stream.write("</div>\n")
1.428
1.429 # Other loading/storing involves attributes accessed on modules, classes
1.430 # and objects.
1.431 @@ -899,7 +1010,6 @@
1.432 # Loading...
1.433
1.434 if hasattr(node, "accesses") and node.accesses:
1.435 - self.stream.write("<div class='scopes'>\n")
1.436 for ref, accesses in node.accesses.items():
1.437 fn = ref.full_name()
1.438 for attr, access in accesses:
1.439 @@ -909,28 +1019,25 @@
1.440 if ref != access:
1.441 self.stream.write(" (via " + self._text(access_fn) + ")")
1.442 self.stream.write("</div>\n")
1.443 - self.stream.write("</div>\n")
1.444
1.445 # Storing...
1.446
1.447 if hasattr(node, "writes") and node.writes:
1.448 - self.stream.write("<div class='scopes'>\n")
1.449 for ref in node.writes.keys():
1.450 fn = ref.full_name()
1.451 self.stream.write("<div class='scope'>")
1.452 self.stream.write(self._text(fn))
1.453 self.stream.write("</div>\n")
1.454 - self.stream.write("</div>\n")
1.455
1.456 # Non-loading...
1.457
1.458 if hasattr(node, "non_accesses") and node.non_accesses:
1.459 - self._types_list(node.non_accesses, style_class="non-accesses")
1.460 + self._types_container(node.non_accesses, "non-accesses")
1.461
1.462 # Non-storing...
1.463
1.464 if hasattr(node, "non_writes") and node.non_writes:
1.465 - self._types_list(node.non_writes, style_class="non-writes")
1.466 + self._types_container(node.non_writes, "non-writes")
1.467
1.468 # Utility functions.
1.469