# HG changeset patch # User paulb@localhost.localdomain # Date 1170719870 -3600 # Node ID 363ef3814271eb133f3680492fa7b2f235ed912a # Parent 8c7d54b395bcc088c8195072064b08fa82749594 Attempted to add multiple instance support, collecting information from node collections, rather than individual simplified nodes. Added some Dict node support. diff -r 8c7d54b395bc -r 363ef3814271 viewer.py --- a/viewer.py Tue Feb 06 00:56:52 2007 +0100 +++ b/viewer.py Tue Feb 06 00:57:50 2007 +0100 @@ -125,15 +125,15 @@ A browsing visitor for AST nodes. Covered: Add, And, AssAttr, AssList, AssName, AssTuple, Assign, AugAssign, - Break, CallFunc, Class, Compare, Const, Continue, Discard, + Break, CallFunc, Class, Compare, Const, Continue, Dict, Discard, Div, FloorDiv, For, From, Function, Getattr, Global, If, Import, Keyword, Lambda, List, Mod, Module, Mul, Name, Not, Or, Pass, Power, Print, Printnl, Raise, Return, Slice, Stmt, Sub, Subscript, TryExcept, TryFinally, Tuple, UnaryAdd, UnarySub, While. - Missing: Assert, Backquote, Bitand, Bitor, Bitxor, Decorators, Dict, - Ellipsis, Exec, Invert, LeftShift, ListComp, ListCompFor, - ListCompIf, RightShift, Sliceobj, Yield. + Missing: Assert, Backquote, Bitand, Bitor, Bitxor, Decorators, Ellipsis, + Exec, Invert, LeftShift, ListComp, ListCompFor, ListCompIf, + RightShift, Sliceobj, Yield. """ def __init__(self, stream): @@ -180,13 +180,14 @@ def visitClass(self, node): definition = node._node + definitions = getattr(node, "_nodes", [definition]) structure = definition.expr.ref self.stream.write("
\n" % self._url(structure.full_name())) self.stream.write("
\n") self._keyword("class") self._name_start(structure.name) self._popup_start() - self._scopes(definition) + self._scopes(definitions) self._popup_end() self._name_end() bases = structure.bases @@ -201,8 +202,8 @@ self.stream.write(",\n") self._name_start(base.name) self._popup_start() - self._types(base) - self._scopes(base) + self._types([base]) + self._scopes([base]) self._popup_end() self._name_end() first = 0 @@ -266,7 +267,7 @@ self.stream.write("\n") self.stream.write(node.modname) self._popup_start() - self._types(node._modname) + self._types([node._modname]) self._popup_end() self.stream.write("\n") self._keyword("import") @@ -280,7 +281,7 @@ self.stream.write("\n") self.stream.write(alias or name) self._popup_start() - self._types(_name) + self._types([_name]) self._popup_end() self.stream.write("\n") first = 0 @@ -288,18 +289,20 @@ def visitFunction(self, node): definition = node._node + definitions = [n for n in getattr(node, "_nodes", [definition]) if not isinstance(n, Subprogram)] subprogram = definition.expr.ref + subprograms = [n for n in getattr(node, "_nodes", [subprogram]) if isinstance(n, Subprogram)] self.stream.write("
\n" % self._url(subprogram.full_name())) self.stream.write("
\n") self._keyword("def") self._name_start(subprogram.name) self._popup_start() - self._scopes(definition) - self._raises(subprogram) + self._scopes([definition]) # not dependent on subprograms + self._raises(subprograms) self._popup_end() self._name_end() self.stream.write("(") - self._parameters(subprogram) + self._parameters(subprogram, subprograms) self.stream.write(")") self.stream.write(":\n") self._comment(self._text(subprogram.full_name())) @@ -326,6 +329,7 @@ self.stream.write("
\n") first = 1 conditional = node._node + conditionals = getattr(node, "_nodes", [conditional]) for compare, stmt in node.tests: self.stream.write("
\n") self.stream.write("\n") @@ -371,7 +375,7 @@ self.stream.write("\n") self.stream.write(alias or name) self._popup_start() - self._types(_name) + self._types([_name]) self._popup_end() self.stream.write("\n") first = 0 @@ -420,11 +424,13 @@ self.stream.write("
\n") def visitReturn(self, node): + value = node._node + values = getattr(node, "_nodes", [value]) self.stream.write("
\n") self.stream.write("\n") self._keyword("return") self._popup_start() - self._types(node._node) + self._types(values) self._popup_end() self.stream.write("\n") self.dispatch(node.value) @@ -556,13 +562,15 @@ self.stream.write("") def visitAssAttr(self, node): + target = node._node + targets = getattr(node, "_nodes", [target]) self.stream.write("\n") self.dispatch(node.expr) self.stream.write("\n") self.stream.write(".%s\n" % self._text(node.attrname)) self._popup_start() - self._types(node._node) - self._scopes(node._node) + self._types(targets) + self._scopes(targets) self._popup_end() self.stream.write("\n") self.stream.write("\n") @@ -575,10 +583,12 @@ self.stream.write("\n") def visitAssName(self, node): - self._name_start(node._node.name) + target = node._node + targets = getattr(node, "_nodes", [target]) + self._name_start(target.name) self._popup_start() - self._types(node._node.expr) - self._scopes(node._node) + self._types(targets) # target.expr + self._scopes(targets) self._popup_end() self._name_end() @@ -590,12 +600,14 @@ self.stream.write("\n") def visitCallFunc(self, node): + target = node._node + targets = getattr(node, "_nodes", [target]) self.stream.write("\n") self.dispatch(node.node) self.stream.write("\n") self.stream.write("(") self._popup_start() - self._invocations(node._node) + self._invocations(target) self._popup_end() self.stream.write("\n") first = 1 @@ -633,6 +645,13 @@ def visitConst(self, node): self.stream.write(repr(node.value)) + def visitDict(self, node): + self.stream.write("\n") + self.stream.write("{") + self._mapping(node) + self.stream.write("}\n") + self.stream.write("\n") + def visitDiv(self, node): self._visitBinary(node, "div", "/") @@ -640,13 +659,15 @@ self._visitBinary(node, "floordiv", "//") def visitGetattr(self, node): + target = node._node + targets = getattr(node, "_nodes", [target]) self.stream.write("\n") self.dispatch(node.expr) self.stream.write("\n") self.stream.write(".%s\n" % self._text(node.attrname)) self._popup_start() - self._types(node._node) - self._scopes(node._node) + self._types(targets) + self._scopes(targets) self._popup_end() self.stream.write("\n") self.stream.write("\n") @@ -660,10 +681,12 @@ def visitLambda(self, node): definition = node._node + definitions = [n for n in getattr(node, "_nodes", [definition]) if not isinstance(n, Subprogram)] subprogram = definition.expr.ref + subprograms = [n for n in getattr(node, "_nodes", [subprogram]) if isinstance(n, Subprogram)] self.stream.write("\n") self._keyword("lambda") - self._parameters(subprogram) + self._parameters(subprogram, subprograms) self.dispatch(node.code) self.stream.write("\n") @@ -676,10 +699,12 @@ self._visitBinary(node, "mul", "*") def visitName(self, node): - self._name_start(node._node.name) + target = node._node + targets = getattr(node, "_nodes", [target]) + self._name_start(target.name) self._popup_start() - self._types(node._node) - self._scopes(node._node) + self._types(targets) + self._scopes(targets) self._popup_end() self._name_end() @@ -773,33 +798,94 @@ self.dispatch(n) first = 0 - def _parameters(self, subprogram): + def _mapping(self, node): first = 1 - for param, default in subprogram.params: + for k, v in node.items: if not first: self.stream.write(",\n") - self._parameter(subprogram, param, default) + self.dispatch(k) + self.stream.write(":\n") + self.dispatch(v) first = 0 - if subprogram.star is not None: + + def _parameters(self, subprogram, subprograms): + + # Get all the parameter lists. + + params = [] + nparams = 0 + for sub in subprograms: + params.append(sub.params) + nparams = max(nparams, len(sub.params)) + stars = [] + have_star = 0 + for sub in subprograms: + stars.append(sub.star) + if sub.star is not None: + have_star = 1 + dstars = [] + have_dstar = 0 + for sub in subprograms: + dstars.append(sub.dstar) + if sub.dstar is not None: + have_dstar = 1 + + # Traverse the parameter lists, choosing a "column" at a time. + + first = 1 + for n in range(0, nparams): + if not first: + self.stream.write(",\n") + main_param, main_default = subprogram.params[n] + self._name_start(main_param) + self._popup_start() + self.stream.write("
\n") + for i in range(0, len(subprograms)): + param, default = params[i][n] + self._parameter(subprograms[i], param) + self.stream.write("
\n") + self._popup_end() + self._name_end() + self._default(main_default) + first = 0 + + if have_star: if not first: self.stream.write(", *\n") - param, default = subprogram.star - self._parameter(subprogram, param, default) + main_param, main_default = subprogram.star + self._name_start(main_param) + self._popup_start() + self.stream.write("
\n") + for i in range(0, len(subprograms)): + param, default = stars[i] + self._parameter(subprograms[i], param) + self.stream.write("
\n") + self._popup_end() + self._name_end() + self._default(main_default) first = 0 - if subprogram.dstar is not None: + + if have_dstar: if not first: self.stream.write(", **\n") - param, default = subprogram.dstar - self._parameter(subprogram, param, default) + main_param, main_default = subprogram.dstar + self._name_start(main_param) + self._popup_start() + self.stream.write("
\n") + for i in range(0, len(subprograms)): + param, default = dstars[i] + self._parameter(subprograms[i], param) + self.stream.write("
\n") + self._popup_end() + self._name_end() + self._default(main_default) first = 0 - def _parameter(self, subprogram, param, default): - self._name_start(param) + def _parameter(self, subprogram, param): if hasattr(subprogram, "paramtypes"): - self._popup_start() self._types_list(subprogram.paramtypes[param]) - self._popup_end() - self._name_end() + + def _default(self, default): if default is not None and default.original is not None: self.stream.write("=\n") self.dispatch(default.original) @@ -844,7 +930,13 @@ self.stream.write("") self.stream.write("
\n") - def _types(self, node): + def _types(self, nodes): + self.stream.write("
\n") + for node in nodes: + self._type(node) + self.stream.write("
\n") + + def _type(self, node): if hasattr(node, "types"): if node.types: self._types_list(node.types) @@ -856,40 +948,59 @@ else: self._no_types() else: - self.stream.write("
\n") - self.stream.write("unvisited\n") - self.stream.write("
\n") + self._unvisited() + + def _unvisited(self): + self.stream.write("
") + self.stream.write("unvisited\n") + self.stream.write("
\n") def _no_types(self): - self.stream.write("
\n") + self.stream.write("
") self.stream.write("no types\n") self.stream.write("
\n") - def _types_list(self, types, style_class="types"): + def _types_container(self, types, style_class): self.stream.write("
\n" % style_class) + self._types_list(types) + self.stream.write("
\n") + + def _types_list(self, types): for type in types: fn = type.type.full_name() self.stream.write("
") self.stream.write(self._text(fn)) self.stream.write("
\n") + + def _raises(self, nodes): + + "Output the exception information for the given simplified 'nodes'." + + self.stream.write("
\n") + for node in nodes: + if hasattr(node, "namespace") and hasattr(node.namespace, "raises") and node.namespace.raises: + self._types_list(node.namespace.raises) self.stream.write("
\n") - def _raises(self, node): - if hasattr(node, "namespace") and hasattr(node.namespace, "raises") and node.namespace.raises: - self._types_list(node.namespace.raises, style_class="raises") + def _scopes(self, nodes): + + "Output the scope information for the given simplified 'nodes'." - def _scopes(self, node): + self.stream.write("
\n") + for node in nodes: + self._scope(node) + self.stream.write("
\n") + + def _scope(self, node): "Output the scope information for the given simplified 'node'." # Straightforward name loading/storing involves the local scope. if isinstance(node, StoreName) or isinstance(node, LoadName): - self.stream.write("
\n") self.stream.write("
") self.stream.write("(local)") self.stream.write("
\n") - self.stream.write("
\n") # Other loading/storing involves attributes accessed on modules, classes # and objects. @@ -899,7 +1010,6 @@ # Loading... if hasattr(node, "accesses") and node.accesses: - self.stream.write("
\n") for ref, accesses in node.accesses.items(): fn = ref.full_name() for attr, access in accesses: @@ -909,28 +1019,25 @@ if ref != access: self.stream.write(" (via " + self._text(access_fn) + ")") self.stream.write("
\n") - self.stream.write("
\n") # Storing... if hasattr(node, "writes") and node.writes: - self.stream.write("
\n") for ref in node.writes.keys(): fn = ref.full_name() self.stream.write("
") self.stream.write(self._text(fn)) self.stream.write("
\n") - self.stream.write("
\n") # Non-loading... if hasattr(node, "non_accesses") and node.non_accesses: - self._types_list(node.non_accesses, style_class="non-accesses") + self._types_container(node.non_accesses, "non-accesses") # Non-storing... if hasattr(node, "non_writes") and node.non_writes: - self._types_list(node.non_writes, style_class="non-writes") + self._types_container(node.non_writes, "non-writes") # Utility functions.