Support optional application-name argument, fix CamelCased objects in ForeignKeys
[plstackapi.git] / planetstack / dmdot
1 #!/usr/bin/python
2
3 import os
4 import pdb
5 import sys
6 import json
7
8 sys.path.append('.')
9
10 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
11
12 from django.db.models.fields.related import ForeignKey
13
14 # defaults
15 app = "core"
16 output = "-json"
17
18 # syntax: dmdot [-json | -dot] [app_name]
19
20 # poor man's argument parser
21 for arg in sys.argv[1:]:
22     if arg.startswith("-"):
23         output = arg
24     else:
25         app = arg
26
27 app = app + ".models"
28 #models_module = imp.load_source(app, ".")
29 models_module = __import__(app)
30 for part in app.split(".")[1:]:
31     models_module = getattr(models_module,part)
32
33 PlCoreBase = getattr(models_module,"PlCoreBase")
34
35 model_classes = []
36 class_names = []
37 lower_class_names = {}
38 for classname in dir(models_module):
39         c = getattr(models_module, classname, None)
40         if type(c)==type(PlCoreBase):
41                 model_classes.append(c)
42                 class_names.append(c.__name__)
43                 lower_class_names[c.__name__.lower()] = c
44
45 # django doesn't use the correct case in field.name.title() for objects that
46 # have CamelCased class names. So, compare everything in lower case.
47
48 if (output=='-dot'):
49         print "digraph plstack {";
50         for c in model_classes:
51                 fields = c._meta.fields
52                 for f in fields:
53                         if type(f)==ForeignKey and f.name.lower() in lower_class_names:
54                                 linked_class = lower_class_names[f.name.lower()]
55                                 print '\t"%s"->"%s";'%(c.__name__,linked_class.__name__)
56         print "}\n";
57 elif (output=='-json'):
58         d = {}
59         for c in model_classes:
60                 fields = c._meta.fields
61                 for f in fields:
62                         if type(f)==ForeignKey and f.name.lower() in lower_class_names:
63                                 linked_class = lower_class_names[f.name.lower()]
64                                 try:
65                                         d[c.__name__].append(linked_class.__name__)
66                                 except KeyError:
67                                         d[c.__name__]=[linked_class.__name__]
68         print json.dumps(d,indent=4)
69         
70