1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/micropython/report.py Sun Apr 18 21:10:41 2010 +0200
1.3 @@ -0,0 +1,261 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +View annotated sources.
1.8 +
1.9 +Copyright (C) 2006, 2007, 2010 Paul Boddie <paul@boddie.org.uk>
1.10 +
1.11 +This program is free software; you can redistribute it and/or modify it under
1.12 +the terms of the GNU General Public License as published by the Free Software
1.13 +Foundation; either version 3 of the License, or (at your option) any later
1.14 +version.
1.15 +
1.16 +This program is distributed in the hope that it will be useful, but WITHOUT
1.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.19 +details.
1.20 +
1.21 +You should have received a copy of the GNU General Public License along with
1.22 +this program. If not, see <http://www.gnu.org/licenses/>.
1.23 +"""
1.24 +
1.25 +from micropython.data import *
1.26 +from compiler.visitor import ASTVisitor
1.27 +import sys
1.28 +import os
1.29 +import textwrap
1.30 +
1.31 +# Classes.
1.32 +
1.33 +# HTML-related output production.
1.34 +
1.35 +html_header = """<?xml version="1.0" encoding="iso-8859-15"?>
1.36 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1.37 +<html xmlns="http://www.w3.org/1999/xhtml">
1.38 +<head>
1.39 + <title>Module</title>
1.40 + <style type="text/css">
1.41 + html {
1.42 + background-color: black; color: white;
1.43 + }
1.44 +
1.45 + body {
1.46 + padding-bottom: 4em;
1.47 + font-size: 14pt; font-family: monospace;
1.48 + background-color: black; color: white;
1.49 + }
1.50 +
1.51 + .nowrap { white-space: nowrap; }
1.52 +
1.53 + .class { margin-top: 1em; margin-bottom: 1em; }
1.54 + .function { margin-top: 1em; margin-bottom: 1em; }
1.55 + .body { padding-left: 2em; }
1.56 + .keyword { color: yellow; }
1.57 + .comment { color: blue; }
1.58 + .class-name { color: cyan; }
1.59 + .function-name { color: cyan; }
1.60 + .str { color: #FF00FF; }
1.61 + .doc { color: #FF00FF; margin-top: 1em; margin-bottom: 1em; }
1.62 + .invocation a { color: white; text-decoration: none; }
1.63 +
1.64 + .popup {
1.65 + display: none; z-index: 2;
1.66 + position: absolute; top: 2ex; left: 0;
1.67 + padding: 0.2em; background-color: #000000; color: white;
1.68 + border: 2px solid #dddddd;
1.69 + }
1.70 +
1.71 + .invocations {
1.72 + padding: 0.5em; background-color: #770000;
1.73 + clear: all;
1.74 + }
1.75 +
1.76 + .types {
1.77 + padding: 0.5em; background-color: #0000FF;
1.78 + float: right;
1.79 + }
1.80 +
1.81 + .raises {
1.82 + padding: 0.5em; background-color: #7700FF;
1.83 + float: right;
1.84 + }
1.85 +
1.86 + .scopes {
1.87 + padding: 0.5em; background-color: #007700;
1.88 + float: left;
1.89 + }
1.90 +
1.91 + .non-scopes {
1.92 + padding: 0.5em; background-color: #FF0000;
1.93 + float: left;
1.94 + }
1.95 +
1.96 + .no-types {
1.97 + background-color: #FF0000;
1.98 + }
1.99 +
1.100 + .op,
1.101 + .name,
1.102 + .attr,
1.103 + .conditional,
1.104 + .operator,
1.105 + .iterator,
1.106 + .call,
1.107 + .returns,
1.108 + .failure
1.109 + {
1.110 + position: relative;
1.111 + }
1.112 +
1.113 + .op:hover > .popup,
1.114 + .name:hover > .popup,
1.115 + .attr:hover > .popup,
1.116 + .conditional:hover > .popup,
1.117 + .operator:hover > .popup,
1.118 + .iterator:hover > .popup,
1.119 + .call:hover > .popup,
1.120 + .returns:hover > .popup,
1.121 + .failure:hover > .popup
1.122 + {
1.123 + display: block;
1.124 + }
1.125 +
1.126 + .summary-class {
1.127 + background-color: #004400;
1.128 + }
1.129 +
1.130 + .summary-instance {
1.131 + background-color: #0000FF;
1.132 + }
1.133 +
1.134 + .summary-attr {
1.135 + background-color: #007700;
1.136 + }
1.137 +
1.138 + </style>
1.139 +</head>
1.140 +<body>
1.141 +"""
1.142 +
1.143 +html_footer = """</body>
1.144 +</html>
1.145 +"""
1.146 +
1.147 +# Utility classes.
1.148 +
1.149 +class Writer:
1.150 +
1.151 + "A utility class providing useful HTML output methods."
1.152 +
1.153 + # Methods which return strings.
1.154 +
1.155 + def _text(self, text):
1.156 + return text.replace("&", "&").replace("<", "<").replace(">", ">")
1.157 +
1.158 + def _attr(self, attr):
1.159 + return self._text(attr).replace("'", "'").replace('"', """)
1.160 +
1.161 + def _url(self, url):
1.162 + return self._attr(url).replace("#", "%23").replace("-", "%2d")
1.163 +
1.164 + def _summary_link(self, module_name, name):
1.165 + return "<a href='%s-summary%sxhtml#%s'>%s</a>" % (module_name, os.path.extsep, self._attr(name), self._text(name))
1.166 +
1.167 + # Methods which write to the stream.
1.168 +
1.169 + def _comment(self, comment):
1.170 + self.stream.write("<span class='comment'># %s</span>\n" % comment)
1.171 +
1.172 + def _keyword(self, kw):
1.173 + self.stream.write("<span class='keyword'>%s</span> " % kw)
1.174 +
1.175 + def _doc(self, node):
1.176 + if node.doc is not None:
1.177 + self.stream.write("<pre class='doc'>\n")
1.178 + self.stream.write('"""')
1.179 + output = textwrap.dedent(node.doc.replace('"""', '\\"\\"\\"'))
1.180 + self.stream.write(self._text(output))
1.181 + self.stream.write('"""')
1.182 + self.stream.write("</pre>\n")
1.183 +
1.184 + def _name(self, name):
1.185 + self.stream.write("<span class='name'>%s</span>\n" % name)
1.186 +
1.187 +# Summary classes.
1.188 +
1.189 +class Summariser(Writer):
1.190 +
1.191 + def __init__(self, stream):
1.192 + self.stream = stream
1.193 +
1.194 + def process(self, module):
1.195 + self.module = module
1.196 + self._init_details()
1.197 + self.stream.write(html_header)
1.198 + self._write_classes(module)
1.199 + self.stream.write(html_footer)
1.200 +
1.201 + def _write_classes(self, module):
1.202 + self.stream.write("<table cellspacing='5' cellpadding='5'>\n")
1.203 +
1.204 + all_classes = {}
1.205 +
1.206 + for obj in self.module.all_objects:
1.207 + if isinstance(obj, Class):
1.208 + all_classes[obj.name] = obj
1.209 +
1.210 + all_class_names = all_classes.keys()
1.211 + all_class_names.sort()
1.212 +
1.213 + for name in all_class_names:
1.214 + self._write_class(all_classes[name])
1.215 +
1.216 + self.stream.write("</table>\n")
1.217 +
1.218 + def _write_class(self, obj):
1.219 +
1.220 + # Write the class...
1.221 +
1.222 + self.stream.write("<tbody class='class'>\n")
1.223 + self.stream.write("<tr>\n")
1.224 + self.stream.write("<th class='summary-class' id='%s'>\n" % obj.full_name())
1.225 + self._keyword("class")
1.226 + self.stream.write(obj.name)
1.227 + self.stream.write("</th>\n")
1.228 +
1.229 + # ...and all known attribute names.
1.230 +
1.231 + obj_attributes = obj.all_attribute_names()
1.232 +
1.233 + for name in self.attribute_names:
1.234 + if name in obj_attributes:
1.235 + self.stream.write("<th class='summary-attr'>%s</th>\n" % self._text(name))
1.236 + else:
1.237 + self.stream.write("<th></th>\n")
1.238 + self.stream.write("</tr>\n")
1.239 +
1.240 + self.stream.write("</tbody>\n")
1.241 +
1.242 + def _init_details(self):
1.243 + names = set()
1.244 +
1.245 + # Visit all classes.
1.246 +
1.247 + for obj in self.module.all_objects:
1.248 + if isinstance(obj, Class):
1.249 + names.update(obj.all_attribute_names())
1.250 +
1.251 + self.attribute_names = list(names)
1.252 + self.attribute_names.sort()
1.253 +
1.254 +# Convenience functions.
1.255 +
1.256 +def summary(module, filename):
1.257 + stream = open(filename, "wb")
1.258 + try:
1.259 + summariser = Summariser(stream)
1.260 + summariser.process(module)
1.261 + finally:
1.262 + stream.close()
1.263 +
1.264 +# vim: tabstop=4 expandtab shiftwidth=4