diff -r 17984abf0c74 -r b0eeea9d6da6 scripts/graph.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/graph.py Wed Oct 01 07:26:45 2008 +0000 @@ -0,0 +1,104 @@ +#!/usr/bin/python2.5 +# +# Copyright 2008 the Melange authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A script which produces a UML diagram from the data model found in the +models directory. + +The output can be found in a file called model-map.png in the same directory as +this file. +""" + +__authors__ = [ + '"Tim \'mithro\' Ansell" ', +] + +import os +import os.path + +from types import TypeType + +import pygraphviz + +import sys +# App Engine +sys.path.append(os.path.join("..", "thirdparty", "google_appengine")) +# Our app +sys.path.append(os.path.join("..", "app")) + +def main(argv): + import google.appengine.ext.db + + G = pygraphviz.AGraph() + G.graph_attr['label'] = '-' + + import soc.models as models + for file in os.listdir(os.path.dirname(models.__file__)): + if not file.endswith(".py"): + continue + if "__init__" in file: + continue + + modelname = os.path.basename(file)[:-3] + try: + #model = __import__("app.soc.models.%s" % modelname, fromlist=[modelname]) + exec("import soc.models.%s as model" % modelname) + + # Add the module to the graph + for klassname in dir(model): + klass = getattr(model, klassname) + if not isinstance(klass, TypeType): + continue + + for parent in klass.__bases__: + G.add_edge(klassname, parent.__name__) + edge = G.get_edge(klassname, parent.__name__) + edge.attr['arrowhead'] = "empty" + + refs = "" + attrs = "" + for attrname in dir(klass): + attr = getattr(klass, attrname) + if type(attr) in google.appengine.ext.db.__dict__.values(): + if isinstance(attr, google.appengine.ext.db.ReferenceProperty): + hasa = attr.reference_class.__name__ + G.add_edge(hasa, klassname) + edge = G.get_edge(hasa, klassname) + edge.attr['arrowhead'] = 'inv' + + refs += "+ %s: %s\l" % (attrname, type(attr).__name__[:-8]) + elif isinstance(attr, google.appengine.ext.db._ReverseReferenceProperty): + pass + else: + attrs += "+ %s: %s\l" % (attrname, type(attr).__name__[:-8]) + label = "{%s|%s|%s}" % (klassname, attrs, refs) + + print label + + G.add_node(klassname) + node = G.get_node(klassname) + node.attr['label'] = label + node.attr['shape'] = "record" + + except Exception, e: + import traceback + print "Was unable to import %s: %s" % (modelname, e) + traceback.print_exc() + + G.layout(prog='dot') + G.draw('model-map.png') + +if __name__ == "__main__": + main(sys.argv)