comparison ikweb/tools/lazygen_model.py @ 247:7747bbe5b68e

start to develope Information Exchange Center of Ikariam Game. (prototpye)
author "Hisn Yi, Chen <ossug.hychen@gmail.com>"
date Mon, 01 Dec 2008 00:27:22 +0800
parents
children
comparison
equal deleted inserted replaced
246:60c4b4b78a01 247:7747bbe5b68e
1 #!/usr/bin/env python
2 import re
3 import os
4 import sys
5
6 from sqlalchemy import *
7 # dirty import XD
8 gaeo_home = os.getenv('GAEO_HOME').replace('~',os.getenv('HOME'))+'/bin'
9 try:
10 sys.path.append(gaeo_home)
11 from gaeogen import *
12 except ImportError, e:
13 print "can not import gaeogen, the gaeogen path maybe wrong, got path:%s" % gaeo_home
14 sys.exit()
15
16
17 def sqlite_column_mapper(model_class, table_obj):
18 """
19 map sqlite columns of the table to GAEO Model
20
21 >>> metadata = MetaData()
22 >>> users_table = Table('users', metadata,
23 ... Column('id', Integer, primary_key=True),
24 ... Column('name', String),
25 ... Column('fullname', String),
26 ... Column('password', String)
27 ... )
28 >>> model = sqlite_column_mapper(GenModel, users_table)
29 >>> model.generate_content()
30 """
31 def convertor(col_type):
32 lowertype = col_type.lower()
33
34 if re.match('char', lowertype): col_type = "String"
35 if re.match('(int|integer)', lowertype): col_type = 'Integer'
36 return col_type
37
38 model = model_class(table_obj.name)
39
40 for column in table_obj.columns:
41 model.add_property( "%s" % GenProperty(column.name,
42 column,
43 convertor))
44 return model
45
46 class GenProperty(object):
47 """
48 GAE Property Generator.
49
50 class Property(verbose_name=None, name=None, default=None, required=False, validator=None, choices=None)
51 """
52 db_prefix = "^(SL|PG|Max|MS|FB|Ac|Info|Oracle)"
53
54 def __init__(self, name, column=False, convertor=False):
55 """
56 >>> col = Column('summary', String(2000))
57 >>> p = GenProperty('summary', col)
58 >>> "%s" % p
59 "summary:StringProperty(verbose_name='summary',name='summary')"
60 >>> meta = MetaData()
61 >>> meta.bind = create_engine("sqlite:///dummy.sqlite")
62 >>> t = Table('ally', meta, autoload=True)
63 >>> p = GenProperty('name', t.columns.get('name'))
64 >>> "%s" % p
65 "name:TextProperty(verbose_name='name',name='name')"
66 >>> p = GenProperty('name', t.columns.get('time'))
67 >>> "%s" % p
68 "name:DatetimeProperty(verbose_name='name',name='name')"
69 """
70 self.name = name
71 self.column = column
72
73 # very dirty ...
74 if column:
75 self.type_name = re.sub( self.db_prefix,'',
76 column.type.__class__.__name__)
77 if convertor:
78 self.type_name = convertor(self.type_name)
79
80 def __str__(self):
81 return self.gen()
82
83 def gen(self):
84 """
85 generate gaeo property code.
86 """
87 clause= self.create_clause(self.type_name, self.column)
88 return gae_property_code(self.name, self.type_name, clause)
89
90 def create_clause(self, type, column):
91 """
92 create property cluase.
93
94 >>> s = Column('summary', String(2000))
95 >>> code = GenProperty(s.name).create_clause('string', s)
96 >>> code
97 {'verbose_name': 'summary', 'name': 'summary'}
98 """
99 clause= self.create_basic_clause(column)
100
101 try:
102 other_caluse = getattr(self, 'create_%s_clause' % type.lower())(column)
103 clause.update(other_caluse)
104 except:
105 pass
106
107 return clause
108
109 def create_basic_clause(self, column):
110 """
111 create basic property cluase.
112 """
113 clause = {'verbose_name':self.name, 'name':self.name}
114
115 if column.default:
116 clause.setdefault('default', column.default)
117 elif column.server_default:
118 clause.setdefault('default', column.server_default)
119
120 return clause
121
122 def gae_property_code(name, type, clause):
123 """
124 generate google app engine property code.
125
126 >>> gae_property_code('name', 'string', {'default':'hychen','name':'hi'})
127 "name:StringProperty(default='hychen',name='hi')"
128 """
129 argv = []
130
131 def _quote(v):
132 try:
133 return "'"+v+"'"
134 except TypeError:
135 pass
136
137 for k,v in clause.items():
138 argv.append("%s=%s" % (k, _quote(v) ) )
139
140 return "%s:%sProperty(%s)" % (name,
141 type.capitalize(),
142 ','.join(argv))
143
144 class ModelMaker:
145
146 is_build = False
147
148 def __init__(self, **kwds):
149 """
150 to create GAEO Model
151
152 >>> maker = ModelMaker(schema="sqlite:///dummy.sqlite", autoload=True)
153 >>> maker.build()
154 """
155 self.models = []
156 self.set_engine(kwds['schema'])
157
158 try:
159 if True == kwds['autoload']:
160 self.table_names = self.db_engine.table_names()
161 else:
162 self.table_names = kwds['include_tables']
163 except KeyError:
164 print "input wrong argv."
165
166 def set_engine(self, schema):
167 """
168 set db engine
169 """
170 self.db_engine = create_engine(schema)
171 self.meta = MetaData()
172 self.meta.bind = self.db_engine
173
174 def build(self):
175 """
176 build models by talbse in database.
177 """
178 mapper_func = '%s_column_mapper' % self.db_engine.name.lower()
179
180 for table_name in self.table_names:
181 table = Table(table_name, self.meta, autoload=True)
182 self.models.append( eval(mapper_func)( GenModel, table) )
183
184 self.is_build = True
185
186 def save(self):
187 """
188 save model
189 """
190 if self.is_build:
191 application_dir = os.path.join(os.getcwd(), 'application')
192 model_dir = os.path.join(application_dir, 'model')
193
194 # check if the model directory had been created
195 if not os.path.exists(os.path.join(model_dir, '__init__.py')):
196 create_file(os.path.join(model_dir, '__init__.py'), [])
197
198 for model in self.models:
199 print 'Creating Model %s ...' % model.name
200 model.save(os.path.join(model_dir, '%s.py' % model.name))
201 else:
202 print "not build yet."
203
204 def gen_models_from_db(db_schema, include_tables=False):
205 """
206 generate models form database.
207
208 gen_models_from_db("sqlite://dumy.sqlite")
209
210 # spefiy tables
211 gen_models_from_db("sqlite://dumy.sqlite", include_tables=['tb1','tb2'])
212 """
213 if not include_tables:
214 maker = ModelMaker(schema=db_schema, autoload=True)
215 else:
216 maker = ModelMaker(schema=db_schema, include_tables=include_tables)
217
218 maker.build()
219 maker.save()
220
221 if '__main__' == __name__:
222 import sys
223
224 if 'test' == sys.argv[1]:
225 import doctest
226 doctest.testmod()
227 else:
228 gen_models_from_db(sys.argv[1])