scripts/graph.py
changeset 243 b0eeea9d6da6
child 417 a88affc13f98
equal deleted inserted replaced
242:17984abf0c74 243:b0eeea9d6da6
       
     1 #!/usr/bin/python2.5
       
     2 #
       
     3 # Copyright 2008 the Melange authors.
       
     4 #
       
     5 # Licensed under the Apache License, Version 2.0 (the "License");
       
     6 # you may not use this file except in compliance with the License.
       
     7 # You may obtain a copy of the License at
       
     8 #
       
     9 #   http://www.apache.org/licenses/LICENSE-2.0
       
    10 #
       
    11 # Unless required by applicable law or agreed to in writing, software
       
    12 # distributed under the License is distributed on an "AS IS" BASIS,
       
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    14 # See the License for the specific language governing permissions and
       
    15 # limitations under the License.
       
    16 
       
    17 """A script which produces a UML diagram from the data model found in the
       
    18 models directory.
       
    19 
       
    20 The output can be found in a file called model-map.png in the same directory as
       
    21 this file.
       
    22 """
       
    23 
       
    24 __authors__ = [
       
    25   '"Tim \'mithro\' Ansell" <mithro@mithis.com>',
       
    26 ]
       
    27 
       
    28 import os
       
    29 import os.path
       
    30 
       
    31 from types import TypeType
       
    32 
       
    33 import pygraphviz
       
    34 
       
    35 import sys
       
    36 # App Engine
       
    37 sys.path.append(os.path.join("..", "thirdparty", "google_appengine"))
       
    38 # Our app
       
    39 sys.path.append(os.path.join("..", "app"))
       
    40 
       
    41 def main(argv):
       
    42   import google.appengine.ext.db
       
    43 
       
    44   G = pygraphviz.AGraph()
       
    45   G.graph_attr['label'] = '-'
       
    46 
       
    47   import soc.models as models
       
    48   for file in os.listdir(os.path.dirname(models.__file__)):
       
    49     if not file.endswith(".py"):
       
    50       continue
       
    51     if "__init__" in file:
       
    52       continue
       
    53 
       
    54     modelname = os.path.basename(file)[:-3]
       
    55     try:
       
    56       #model = __import__("app.soc.models.%s" % modelname, fromlist=[modelname])
       
    57       exec("import soc.models.%s as model" % modelname)
       
    58 
       
    59       # Add the module to the graph
       
    60       for klassname in dir(model):
       
    61         klass = getattr(model, klassname)
       
    62         if not isinstance(klass, TypeType):
       
    63           continue
       
    64 
       
    65         for parent in klass.__bases__:
       
    66           G.add_edge(klassname, parent.__name__)
       
    67           edge = G.get_edge(klassname, parent.__name__)
       
    68           edge.attr['arrowhead'] = "empty"
       
    69 
       
    70         refs = ""
       
    71         attrs = ""
       
    72         for attrname in dir(klass):
       
    73           attr = getattr(klass, attrname)
       
    74           if type(attr) in google.appengine.ext.db.__dict__.values():
       
    75             if isinstance(attr, google.appengine.ext.db.ReferenceProperty):
       
    76               hasa = attr.reference_class.__name__
       
    77               G.add_edge(hasa, klassname)
       
    78               edge = G.get_edge(hasa, klassname)
       
    79               edge.attr['arrowhead'] = 'inv'
       
    80 
       
    81               refs += "+ %s: %s\l" % (attrname, type(attr).__name__[:-8])
       
    82             elif isinstance(attr, google.appengine.ext.db._ReverseReferenceProperty):
       
    83               pass
       
    84             else:
       
    85               attrs += "+ %s: %s\l" % (attrname, type(attr).__name__[:-8])
       
    86         label = "{%s|%s|%s}" % (klassname, attrs, refs)
       
    87 
       
    88         print label
       
    89 
       
    90         G.add_node(klassname)
       
    91         node = G.get_node(klassname)
       
    92         node.attr['label'] = label
       
    93         node.attr['shape'] = "record"
       
    94 
       
    95     except Exception, e:
       
    96       import traceback
       
    97       print "Was unable to import %s: %s" % (modelname, e)
       
    98       traceback.print_exc()
       
    99 
       
   100   G.layout(prog='dot')
       
   101   G.draw('model-map.png')
       
   102 
       
   103 if __name__ == "__main__":
       
   104   main(sys.argv)