Bug fixes for the API generator
[plstackapi.git] / planetstack / apigen / modelgen
1 #!/usr/bin/python
2
3 import os
4 import pdb
5 import copy
6 import sys
7 import json
8 import re
9 from django.template import Context, Template
10
11 blacklist = ['SingletonModel','PlCoreBase']
12
13 # Django set up
14
15 sys.path.append('.')
16 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings")
17 from django.db.models.fields.related import ForeignKey, ManyToManyField
18 from core.models import *
19
20 def singular(foo, keys):
21         for k in keys:
22                 if (foo==k+'es'):
23                         return k
24                 elif (foo==k+'s'):
25                         return k
26         raise Exception('Plural to singular error for %s'%foo)
27
28 g = globals()
29
30 def enum_classes():
31         model_classes = []
32         for c in g.values():
33                 if type(c)==type(PlCoreBase) and c.__name__ not in blacklist:
34                         model_classes.append(c)
35         return model_classes
36
37
38 class GenObj(object):
39         def __str__(self):
40                 return str(self.model.__name__.lower())
41
42         def __init__(self, m):
43                 self.model = m
44                 self.props = []
45                 self.refs = []
46
47         def plural(self):
48                 name = str(self)
49                 if (name.endswith('s')):
50                         return name+'es'
51                 else:
52                         return name+'s'
53
54         def camel(self):
55                 name = str(self.model.__name__)
56                 return name
57                 
58 class Generator(dict):
59         def all(self):
60                 return self.values()
61         
62         def regex(self, r):
63                 filtered = filter(lambda o:re.match(r,str(o)), self.values())
64                 return filtered
65
66         def add_object(self, o):
67                 obj = GenObj(o)
68                 fields = o._meta.fields
69                 self[str(obj).lower()]=obj
70
71         def compute_links(self):
72                 for obj in self.values():
73                         #if (str(obj).lower()=='user'):
74                         #       pdb.set_trace()
75                         fields = obj.model._meta.fields
76                         for f in fields:
77                                 if type(f)==ForeignKey and f.name in self.keys():
78                                         refobj = self[f.name]
79                                         obj.refs.append(refobj)
80                                 else:
81                                         obj.props.append(f.name)
82                         m2m = obj.model._meta.many_to_many
83                         for f in m2m:
84                                 try:
85                                         related_model_name = f.m2m_reverse_field_name()
86                                 except:
87                                         related_model_name = f.m2m_db_table().rsplit('_',1)[-1]
88
89                                 if related_model_name in self.keys():
90                         #               pdb.set_trace()
91                                         refobj = self[related_model_name]
92                                         cobj = copy.deepcopy(obj)
93                                         cobj.multi=True
94                                         refobj.refs.append(cobj)
95
96                         
97 def main():
98         try:
99                 output = sys.argv[1]
100         except:
101                 print 'Usage: modelgen <output template>'
102                 exit(1)
103
104         generator = Generator()
105
106         models = enum_classes()
107
108         for m in models:
109                 generator.add_object(m)
110
111         generator.compute_links()
112         template_contents = open(output).read()
113         template = Template(template_contents)
114         context = Context({'generator':generator})
115         print template.render(context)
116
117
118 if (__name__=='__main__'):
119         main()