Mercurial > eagle-eye
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ikweb/tools/lazygen_model.py Mon Dec 01 00:27:22 2008 +0800 @@ -0,0 +1,228 @@ +#!/usr/bin/env python +import re +import os +import sys + +from sqlalchemy import * +# dirty import XD +gaeo_home = os.getenv('GAEO_HOME').replace('~',os.getenv('HOME'))+'/bin' +try: + sys.path.append(gaeo_home) + from gaeogen import * +except ImportError, e: + print "can not import gaeogen, the gaeogen path maybe wrong, got path:%s" % gaeo_home + sys.exit() + + +def sqlite_column_mapper(model_class, table_obj): + """ + map sqlite columns of the table to GAEO Model + + >>> metadata = MetaData() + >>> users_table = Table('users', metadata, + ... Column('id', Integer, primary_key=True), + ... Column('name', String), + ... Column('fullname', String), + ... Column('password', String) + ... ) + >>> model = sqlite_column_mapper(GenModel, users_table) + >>> model.generate_content() + """ + def convertor(col_type): + lowertype = col_type.lower() + + if re.match('char', lowertype): col_type = "String" + if re.match('(int|integer)', lowertype): col_type = 'Integer' + return col_type + + model = model_class(table_obj.name) + + for column in table_obj.columns: + model.add_property( "%s" % GenProperty(column.name, + column, + convertor)) + return model + +class GenProperty(object): + """ + GAE Property Generator. + + class Property(verbose_name=None, name=None, default=None, required=False, validator=None, choices=None) + """ + db_prefix = "^(SL|PG|Max|MS|FB|Ac|Info|Oracle)" + + def __init__(self, name, column=False, convertor=False): + """ + >>> col = Column('summary', String(2000)) + >>> p = GenProperty('summary', col) + >>> "%s" % p + "summary:StringProperty(verbose_name='summary',name='summary')" + >>> meta = MetaData() + >>> meta.bind = create_engine("sqlite:///dummy.sqlite") + >>> t = Table('ally', meta, autoload=True) + >>> p = GenProperty('name', t.columns.get('name')) + >>> "%s" % p + "name:TextProperty(verbose_name='name',name='name')" + >>> p = GenProperty('name', t.columns.get('time')) + >>> "%s" % p + "name:DatetimeProperty(verbose_name='name',name='name')" + """ + self.name = name + self.column = column + + # very dirty ... + if column: + self.type_name = re.sub( self.db_prefix,'', + column.type.__class__.__name__) + if convertor: + self.type_name = convertor(self.type_name) + + def __str__(self): + return self.gen() + + def gen(self): + """ + generate gaeo property code. + """ + clause= self.create_clause(self.type_name, self.column) + return gae_property_code(self.name, self.type_name, clause) + + def create_clause(self, type, column): + """ + create property cluase. + + >>> s = Column('summary', String(2000)) + >>> code = GenProperty(s.name).create_clause('string', s) + >>> code + {'verbose_name': 'summary', 'name': 'summary'} + """ + clause= self.create_basic_clause(column) + + try: + other_caluse = getattr(self, 'create_%s_clause' % type.lower())(column) + clause.update(other_caluse) + except: + pass + + return clause + + def create_basic_clause(self, column): + """ + create basic property cluase. + """ + clause = {'verbose_name':self.name, 'name':self.name} + + if column.default: + clause.setdefault('default', column.default) + elif column.server_default: + clause.setdefault('default', column.server_default) + + return clause + +def gae_property_code(name, type, clause): + """ + generate google app engine property code. + + >>> gae_property_code('name', 'string', {'default':'hychen','name':'hi'}) + "name:StringProperty(default='hychen',name='hi')" + """ + argv = [] + + def _quote(v): + try: + return "'"+v+"'" + except TypeError: + pass + + for k,v in clause.items(): + argv.append("%s=%s" % (k, _quote(v) ) ) + + return "%s:%sProperty(%s)" % (name, + type.capitalize(), + ','.join(argv)) + +class ModelMaker: + + is_build = False + + def __init__(self, **kwds): + """ + to create GAEO Model + + >>> maker = ModelMaker(schema="sqlite:///dummy.sqlite", autoload=True) + >>> maker.build() + """ + self.models = [] + self.set_engine(kwds['schema']) + + try: + if True == kwds['autoload']: + self.table_names = self.db_engine.table_names() + else: + self.table_names = kwds['include_tables'] + except KeyError: + print "input wrong argv." + + def set_engine(self, schema): + """ + set db engine + """ + self.db_engine = create_engine(schema) + self.meta = MetaData() + self.meta.bind = self.db_engine + + def build(self): + """ + build models by talbse in database. + """ + mapper_func = '%s_column_mapper' % self.db_engine.name.lower() + + for table_name in self.table_names: + table = Table(table_name, self.meta, autoload=True) + self.models.append( eval(mapper_func)( GenModel, table) ) + + self.is_build = True + + def save(self): + """ + save model + """ + if self.is_build: + application_dir = os.path.join(os.getcwd(), 'application') + model_dir = os.path.join(application_dir, 'model') + + # check if the model directory had been created + if not os.path.exists(os.path.join(model_dir, '__init__.py')): + create_file(os.path.join(model_dir, '__init__.py'), []) + + for model in self.models: + print 'Creating Model %s ...' % model.name + model.save(os.path.join(model_dir, '%s.py' % model.name)) + else: + print "not build yet." + +def gen_models_from_db(db_schema, include_tables=False): + """ + generate models form database. + + gen_models_from_db("sqlite://dumy.sqlite") + + # spefiy tables + gen_models_from_db("sqlite://dumy.sqlite", include_tables=['tb1','tb2']) + """ + if not include_tables: + maker = ModelMaker(schema=db_schema, autoload=True) + else: + maker = ModelMaker(schema=db_schema, include_tables=include_tables) + + maker.build() + maker.save() + +if '__main__' == __name__: + import sys + + if 'test' == sys.argv[1]: + import doctest + doctest.testmod() + else: + gen_models_from_db(sys.argv[1])