mwgencode 1.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. gencode/__init__.py +140 -0
  2. gencode/dd_models.py +256 -0
  3. gencode/ext.py +19 -0
  4. gencode/gen_code.py +343 -0
  5. gencode/gencode/__init__.py +0 -0
  6. gencode/gencode/export_class2swgclass.py +206 -0
  7. gencode/gencode/gen_bo_models_code.py +719 -0
  8. gencode/gencode/gen_state_code.py +171 -0
  9. gencode/gencode/gen_swagger_code.py +94 -0
  10. gencode/gencode/gen_tests_code.py +113 -0
  11. gencode/gencode/sample/__init__.py +2 -0
  12. gencode/gencode/sample/babel.cfg +3 -0
  13. gencode/gencode/sample/config-sample.ini +9 -0
  14. gencode/gencode/sample/config.ini +14 -0
  15. gencode/gencode/sample/create_new_table_run.pys +19 -0
  16. gencode/gencode/sample/dockerignore.dock +57 -0
  17. gencode/gencode/sample/file_utils.pys +396 -0
  18. gencode/gencode/sample/gencode.xmi +33 -0
  19. gencode/gencode/sample/gitignore.git +14 -0
  20. gencode/gencode/sample/migrate_run.bat +5 -0
  21. gencode/gencode/sample/migrate_run.pys +9 -0
  22. gencode/gencode/sample/requirements.txt +17 -0
  23. gencode/gencode/sample/run.sh +27 -0
  24. gencode/gencode/sample/seeds/__init__.py +0 -0
  25. gencode/gencode/sample/seeds/models_rm.pys +187 -0
  26. gencode/gencode/sample/seeds/seed_dev_data.pys +21 -0
  27. gencode/gencode/sample/seeds/seed_init.pys +17 -0
  28. gencode/gencode/sample/seeds/seed_rm.pys +39 -0
  29. gencode/gencode/sample/seeds/seed_run.pys +13 -0
  30. gencode/gencode/sample/seeds/seed_utils.pys +23 -0
  31. gencode/gencode/sample/test__init__.pys +6 -0
  32. gencode/gencode/sample/test_run.pys +4 -0
  33. gencode/gencode/sample/utils.pys +92 -0
  34. gencode/gencode/template/Dockerfile.tmp +55 -0
  35. gencode/gencode/template/README.md +91 -0
  36. gencode/gencode/template/__init__.py +0 -0
  37. gencode/gencode/template/__init__.pys +99 -0
  38. gencode/gencode/template/config.pys +134 -0
  39. gencode/gencode/template/default.conf +21 -0
  40. gencode/gencode/template/docker-compose-dev.yaml +52 -0
  41. gencode/gencode/template/docker-compose.yaml +55 -0
  42. gencode/gencode/template/drone.tmp +45 -0
  43. gencode/gencode/template/flask_models.pys +107 -0
  44. gencode/gencode/template/flask_models_base.pys +159 -0
  45. gencode/gencode/template/gen_code_flask.yaml +21 -0
  46. gencode/gencode/template/gen_code_run.pys +28 -0
  47. gencode/gencode/template/k8s-tmp.yml +141 -0
  48. gencode/gencode/template/run.pys +52 -0
  49. gencode/gencode/template/sample.mdj +1193 -0
  50. gencode/gencode/template/setup.tmp +48 -0
  51. gencode/gencode/template/supervisord.conf +21 -0
  52. gencode/gencode/template/swagger_file.yaml +195 -0
  53. gencode/gencode/template/swg_class.tmp +41 -0
  54. gencode/gencode/template/swg_ctrl_code.pys +130 -0
  55. gencode/gencode/template/swg_package_mng.tmp +4423 -0
  56. gencode/gencode/template/test_test_base.tmp +34 -0
  57. gencode/gencode/template/tests/__init__.py +0 -0
  58. gencode/gencode/template/tests/__init__.pys +5 -0
  59. gencode/gencode/template/tests/init_test_data.pys +80 -0
  60. gencode/gencode/template/tests/run.pys +4 -0
  61. gencode/gencode/template/tests/test_base.pys +87 -0
  62. gencode/gencode/template/tests/test_classmng.pys +58 -0
  63. gencode/gencode/template/uwsgi.ini +20 -0
  64. gencode/gencode/template/uwsgi_run.pys +44 -0
  65. gencode/importmdj/__init__.py +0 -0
  66. gencode/importmdj/import_dd_classes.py +369 -0
  67. gencode/importmdj/import_swagger2_class.py +371 -0
  68. gencode/importmdj/import_uml_models.py +466 -0
  69. gencode/importxmi/__init__.py +1 -0
  70. gencode/importxmi/import_classes.py +342 -0
  71. gencode/importxmi/import_sequences.py +291 -0
  72. gencode/importxmi/import_states.py +150 -0
  73. gencode/importxmi/import_swagger.py +151 -0
  74. gencode/swg2_class_models.py +179 -0
  75. gencode/uml_class_models.py +295 -0
  76. gencode/upgrade.py +113 -0
  77. gencode/utils.py +225 -0
  78. manage.py +194 -0
  79. mwgencode-1.4.1.dist-info/METADATA +325 -0
  80. mwgencode-1.4.1.dist-info/RECORD +84 -0
  81. mwgencode-1.4.1.dist-info/WHEEL +5 -0
  82. mwgencode-1.4.1.dist-info/entry_points.txt +2 -0
  83. mwgencode-1.4.1.dist-info/licenses/LICENSE.txt +19 -0
  84. mwgencode-1.4.1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,719 @@
1
+ '''
2
+ 产生 boclass 的model
3
+ '''
4
+
5
+ from gencode.dd_models import *
6
+ from gencode.utils import Keytype,FieldFrom,saveUTF8File
7
+ from gencode.ext import Session
8
+ from enum import Enum
9
+ import os
10
+ from jinja2 import FileSystemLoader, Environment
11
+ from gencode.importmdj.import_dd_classes import ImportDDModels
12
+ from collections import OrderedDict
13
+ import logging
14
+ MODELS_PY = 'models.py'
15
+
16
+ class DBTable_meta():
17
+ def __init__(self):
18
+ self.class_name = ''
19
+ self.table_name = ''
20
+ self.columns = []
21
+
22
+ class DBTable():
23
+ def __init__(self):
24
+ self.class_name = ''
25
+ self.table_name = ''
26
+ # 资料库不同于默认的资料库
27
+ self.bind_key = ''
28
+ # 继承关系的父类名称
29
+ self.parent_name = ''
30
+ self.is_parent_class = False
31
+ # 单表继承
32
+ self.is_sigletable = False
33
+ self.mapper_args = ''
34
+ # orm sql 不产生 output “__table_args__ = {'implicit_returning': False}”
35
+ self.table_args = {}
36
+ self.discriminator_column = None
37
+ self.columns = []
38
+ self.relationsips = []
39
+ self.unique_constraints = []
40
+ self.fkeyids = []
41
+ self.funcs= []
42
+ self.doc = ''
43
+ def __repr__(self):
44
+ return 'name:%s,doc:%s'%(self.table_name,self.doc)
45
+
46
+ class DBFunc():
47
+ def __init__(self,name):
48
+ self.name =name
49
+ self.isabstract = False
50
+ self.isquery = False
51
+ self.isstatic = False
52
+ self.params = ''
53
+ self.codes = ''
54
+ self.doc = ''
55
+ self.self_param =''
56
+
57
+ class DBColumn():
58
+ def __init__(self,name):
59
+ # self.foreign_key = ''
60
+ self.primary_key = ''
61
+ self.name = name
62
+ self.dbname= ''
63
+ self.type = ''
64
+ self.default = ''
65
+ self.sys_default = ''
66
+ self.unique = ''
67
+ self.nullable = ''
68
+ self.ondelete = ''
69
+ self.onupdate = ''
70
+ self.doc = ''
71
+
72
+ class Enume_model():
73
+ def __init__(self,name):
74
+ self.name = name
75
+ self.columns = {}
76
+
77
+ class DBColumn_fkeyid(DBColumn):
78
+ def __init__(self,name):
79
+ super().__init__(name)
80
+ self.reftable = ''
81
+ self.refid = ''
82
+
83
+ class DBRelationship():
84
+ def __init__(self,name):
85
+ self.name = name
86
+ self.relationship_cls = ''
87
+ self.uselist = ''
88
+ self.foreign_keys = ''
89
+ self.back_populates = ''
90
+ self.secondary = ''
91
+ self.cascade = ''
92
+ self.lazy = ''
93
+ self.remote_side = ''
94
+ self.primaryjoin = ''
95
+ self.order_by = ''
96
+
97
+ class Gen_type(Enum):
98
+ flask ='flask' # flask_sqlalchemy 的 model
99
+ sql = 'sql' # sqlalchemy 的 model
100
+
101
+ class BoCodeGenerator_base():
102
+ def __init__(self,database_dict):
103
+ self.database_dict = database_dict
104
+ # self.codes = []
105
+ self.tables_js=OrderedDict()
106
+ # self.dbtables = {}
107
+ self.tables_meta_js={}
108
+ self.enmumerations_js=[]
109
+ self.session = Session()
110
+ # 如:db.Model,db.Column
111
+ self.model_prefix = ''
112
+ # 类的后缀,如_base 。。。
113
+ self.class_suffix = ''
114
+ self.template_file = ''
115
+ # 把parentclass排前面,确保子类能引用
116
+ self.tables = self.session.query(Tabledictionary).\
117
+ filter(Tabledictionary.databasedictionaryid==self.database_dict.id).\
118
+ order_by(Tabledictionary.is_parentclass.desc()).all()
119
+
120
+ def __load_template(self, temp_file_name):
121
+ tmp_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'template')
122
+ load = FileSystemLoader(tmp_path)
123
+ env = Environment(loader=load)
124
+ return env.get_template(temp_file_name)
125
+
126
+ def covert2pytype(self,dbtype, size):
127
+ if dbtype == 'bit':
128
+ return '{model_pre}Boolean'.format(model_pre=self.model_prefix)
129
+ elif dbtype == 'char' or dbtype == 'varchar' or \
130
+ dbtype == 'nchar':
131
+ return '{model_pre}String({size})'.format(model_pre=self.model_prefix,
132
+ size=size)
133
+ elif dbtype == 'datetime':
134
+ return '{model_pre}DateTime'.format(model_pre=self.model_prefix)
135
+ elif dbtype == 'time':
136
+ return '{model_pre}Time'.format(model_pre=self.model_prefix)
137
+ elif dbtype == 'float':
138
+ return '{model_pre}Float'.format(model_pre=self.model_prefix)
139
+ elif dbtype == 'int':
140
+ return '{model_pre}Integer'.format(model_pre=self.model_prefix)
141
+ elif dbtype == 'numeric':
142
+ return '{model_pre}Float'.format(model_pre=self.model_prefix)
143
+ elif dbtype == 'text':
144
+ return '{model_pre}Text'.format(model_pre=self.model_prefix)
145
+ elif dbtype == 'AutoInt':
146
+ return 'db.Integer'.format(model_pre=self.model_prefix)
147
+ elif dbtype == 'date':
148
+ return '{model_pre}Date'.format(model_pre=self.model_prefix)
149
+ elif dbtype == 'image':
150
+ return '{model_pre}LargeBinary'.format(model_pre=self.model_prefix)
151
+
152
+ def __validDefault(self, fld, defvalue):
153
+ pytype = self.covert2pytype(fld.fieldtype, fld.fieldsize)
154
+ if pytype.startswith('{modle_pre}Boolean'.format(modle_pre=self.model_prefix)):
155
+ return defvalue.capitalize()
156
+ elif pytype.startswith('{modle_pre}String'.format(modle_pre=self.model_prefix)):
157
+ return '%s' % defvalue if defvalue.startswith('\'') else '"%s"' % defvalue
158
+ elif pytype.startswith('{modle_pre}DateTime'.format(modle_pre=self.model_prefix)) or \
159
+ pytype.startswith('{modle_pre}Date'.format(modle_pre=self.model_prefix)):
160
+ if defvalue.lower().find('now') != -1 or \
161
+ defvalue.lower().find('today') != -1 or \
162
+ defvalue.lower().find('date') != -1:
163
+ if defvalue.lower().find('+') != -1:
164
+ # 程序
165
+ s = defvalue.lower().split('+')
166
+ return 'datetime.now()+timedelta(days=%s)' % s[-1]
167
+ else:
168
+ # 插入时间
169
+ return 'datetime.now'
170
+ else:
171
+ return defvalue
172
+ else:
173
+ return defvalue
174
+
175
+ def __gen_o2o_code(self,role):
176
+ ''''''
177
+ '''
178
+ class Parent(Base):
179
+ child = relationship("Child", uselist=False, back_populates="parent")
180
+ '''
181
+ assert role.end1_multiplicity == 1 and role.end2_multiplicity == 1
182
+ # 如果是单向的一对一,转为多对一处理
183
+ if not role.end1_navigable and role.end2_navigable:
184
+ role.end1_multiplicity=65535
185
+ return self.__gen_m2o_code(role)
186
+ # fkeys_end1 = self.tables_js[role.end1_reftable.tablename].setdefault('f_keys', {})
187
+ fkeys_end1 = DBRelationship(role.end2_rolename)
188
+ fkeys_end1.relationship_cls= role.end2_reftable.tablename.capitalize()
189
+ fkeys_end1.foreign_keys =', foreign_keys="{end2_cls}.{fkey}"'.format(end2_cls=role.end2_reftable.tablename.capitalize(),
190
+ fkey=role.end1_foreign_key_name,)
191
+ fkeys_end1.uselist = ',uselist=False'
192
+ fkeys_end1.back_populates = ', back_populates = "{end1_role}"'.format(end1_role=role.end1_rolename) # if role.end1_navigable else ''
193
+ self.tables_js[role.end1_reftable.tablename].relationsips.append(fkeys_end1)
194
+ '''
195
+ class Child(Base):
196
+ parent_id = Column(Integer, ForeignKey('parent.id'))
197
+ parent = relationship("Parent", back_populates="child")
198
+ '''
199
+ # fkeys_end2 = self.tables_js[role.end2_reftable.tablename].setdefault('f_keys', {})
200
+ dbtable = self.tables_js[role.end2_reftable.tablename]
201
+ end1_tb_idfld = role.end1_reftable.get_keyfield()
202
+ column = DBColumn_fkeyid(role.end1_foreign_key_name)
203
+ column.dbname = '' if not role.end1_mapid else '"%s",' % role.end1_mapid.lower()
204
+ column.type = self.covert2pytype(end1_tb_idfld.fieldtype, end1_tb_idfld.fieldsize)
205
+ column.reftable = self.__get_table_name(role.end1_reftable) #.maptablename.lower()
206
+ column.refid = end1_tb_idfld.fieldname if not end1_tb_idfld.mapname else end1_tb_idfld.mapname
207
+ column.nullable = ', nullable= False' if role.req else ''
208
+ dbtable.fkeyids.append(column)
209
+ fkeys_end2 = DBRelationship(role.end1_rolename)
210
+ fkeys_end2.relationship_cls = role.end1_reftable.tablename.capitalize()
211
+ fkeys_end2.foreign_keys = ', foreign_keys="{end2_cls}.{fkey}"'.\
212
+ format(end2_cls=role.end2_reftable.tablename.capitalize(),
213
+ fkey=role.end1_foreign_key_name)
214
+ fkeys_end2.back_populates = ', back_populates="{end2_role}"'.\
215
+ format(end2_role=role.end2_rolename)
216
+ dbtable.relationsips.append(fkeys_end2)
217
+
218
+ def __get_table_name(self,table):
219
+ # 单表模式继承,且为son类,tablename用parent的
220
+ if table.is_sigletable and table.parent:
221
+ table = table.parent
222
+ tablename = table.tablename.lower() \
223
+ if table.maptablename is None \
224
+ else table.maptablename.lower()
225
+ return tablename
226
+
227
+ def __gen_m2o_code(self,role):
228
+ ''''''
229
+ '''
230
+ class Parent(Base):
231
+ child_id = Column(Integer, ForeignKey('child.id'))
232
+ child = relationship("Child")
233
+ class Child(Base):
234
+ '''
235
+ assert role.end1_multiplicity > 1 and role.end2_multiplicity == 1
236
+ dbtable = self.tables_js[role.end1_reftable.tablename]
237
+ end2_tb_idfld = role.end2_reftable.get_keyfield()
238
+ column = DBColumn_fkeyid(role.end2_foreign_key_name)
239
+ column.dbname = '' if not role.end2_mapid else '"%s",' % role.end2_mapid.lower()
240
+ column.type = self.covert2pytype(end2_tb_idfld.fieldtype, end2_tb_idfld.fieldsize)
241
+ column.reftable = self.__get_table_name(role.end2_reftable) #role.end2_reftable.maptablename
242
+ column.refid = end2_tb_idfld.fieldname if not end2_tb_idfld.mapname else end2_tb_idfld.mapname
243
+ column.nullable = ', nullable= False' if role.req else ''
244
+ # 一的一方可以为空时,删除一方需同时对引用值空
245
+ column.ondelete = ', ondelete="SET NULL"' if not role.req else ''
246
+ dbtable.fkeyids.append(column)
247
+ fkeys_end1 = DBRelationship(role.end2_rolename)
248
+ fkeys_end1.relationship_cls = role.end2_reftable.tablename.capitalize()
249
+ fkeys_end1.foreign_keys = ', foreign_keys="{end1_cls}.{fkey}"'.\
250
+ format( end1_cls=role.end1_reftable.tablename.capitalize(),
251
+ fkey=role.end2_foreign_key_name)
252
+ if role.is_tree():
253
+ fkeys_end1.remote_side =', remote_side=[%s]'%role.end1_reftable.get_keyfield().fieldname
254
+
255
+ # fkeys_end1.uselist = ', uselist=False'
256
+ dbtable.relationsips.append(fkeys_end1)
257
+
258
+ def __gen_o2m_code(self, role):
259
+ ''''''
260
+ '''
261
+ class Parent(Base):
262
+ children = relationship("Child", back_populates="parent")
263
+ '''
264
+ assert role.end1_multiplicity==1 and role.end2_multiplicity>1
265
+ dbtable_end1 = self.tables_js[role.end1_reftable.tablename]
266
+ fkeys_end1 = DBRelationship('%ss' % role.end2_rolename)
267
+ fkeys_end1.relationship_cls = role.end2_reftable.tablename.capitalize()
268
+ fkeys_end1.foreign_keys = ', foreign_keys="{end2_cls}.{fkey}"'.format(
269
+ end2_cls=role.end2_reftable.tablename.capitalize(),
270
+ fkey=role.end1_foreign_key_name)
271
+ fkeys_end1.back_populates ='{back_populates}'.format(
272
+ back_populates = ', back_populates="{end1_role}"'.format(end1_role=role.end1_rolename) if role.end1_navigable else ''
273
+ )
274
+
275
+ fkeys_end1.lazy = ', lazy="%s"'%role.end2_lazy if role.end2_lazy else ''
276
+ fkeys_end1.cascade = ', cascade="all, delete-orphan"' if role.is_md() else ''
277
+ if role.flt:
278
+ if 'remote' in role.flt or 'foreign' in role.flt:
279
+ fkeys_end1.primaryjoin = ' ,primaryjoin={flt}'.format(flt=role.flt)
280
+ else:
281
+ fkeys_end1.primaryjoin = ' ,primaryjoin="and_({end1_cls}.{end1_key}=={end2_cls}.{end2_fkey},{flt})"'.format(
282
+ end1_cls=role.end1_reftable.tablename.capitalize(),
283
+ end1_key=role.end2_reftable.get_keyfield().fieldname,
284
+ end2_cls=role.end2_reftable.tablename.capitalize(),
285
+ end2_fkey=role.end1_foreign_key_name,
286
+ flt=role.flt
287
+ )
288
+
289
+ if role.ord:
290
+ fkeys_end1.order_by = ', order_by="{ord_fld}"'.format(ord_fld=role.ord)
291
+ dbtable_end1.relationsips.append(fkeys_end1)
292
+ '''
293
+ class Child(Base):
294
+ parent_id = Column(Integer, ForeignKey('parent.id'))
295
+ parent = relationship("Parent", back_populates="children")
296
+ '''
297
+ dbtable_end2 = self.tables_js[role.end2_reftable.tablename]
298
+ end1_tb_idfld = role.end1_reftable.get_keyfield()
299
+ column = DBColumn_fkeyid(role.end1_foreign_key_name)
300
+ column.dbname = '' if not role.end1_mapid else '"%s",' % role.end1_mapid.lower()
301
+ column.type = self.covert2pytype(end1_tb_idfld.fieldtype, end1_tb_idfld.fieldsize)
302
+ column.reftable = self.__get_table_name(role.end1_reftable)#.maptablename.lower()
303
+ column.refid = end1_tb_idfld.fieldname if not end1_tb_idfld.mapname else end1_tb_idfld.mapname
304
+ column.nullable = ', nullable= False' if role.req else ''
305
+ dbtable_end2.fkeyids.append(column)
306
+ if role.end1_navigable:
307
+ fkeys_end2 = DBRelationship(role.end1_rolename)
308
+ fkeys_end2.relationship_cls = role.end1_reftable.tablename.capitalize()
309
+ fkeys_end2.foreign_keys = ', foreign_keys="{end2_cls}.{fkey}"'.format(
310
+ end2_cls=role.end2_reftable.tablename.capitalize(),
311
+ fkey=role.end1_foreign_key_name)
312
+ fkeys_end2.back_populates = ', back_populates="{end2_roles}"'.format(
313
+ end2_roles='%ss' % role.end2_rolename)
314
+ if role.is_tree():
315
+ fkeys_end2.remote_side = ', remote_side=[%s]'%role.end1_reftable.get_keyfield().fieldname
316
+ dbtable_end2.relationsips.append(fkeys_end2)
317
+
318
+ def __gen_m2m_code4assoc(self, role):
319
+ # def get_reftable(table):
320
+ # # 单表模式继承,且为son类,tablename用parent的
321
+ # if table.is_sigletable and table.parent:
322
+ # return table.parent.maptablename.lower()
323
+ # else:
324
+ # return table.maptablename.lower()
325
+ ''''''
326
+ '''
327
+ class Association(Base):
328
+ left_id = Column(Integer, ForeignKey('left.id'), primary_key=True)
329
+ right_id = Column(Integer, ForeignKey('right.id'), primary_key=True)
330
+ child = relationship("Child", back_populates="parents")
331
+ parent = relationship("Parent", back_populates="children")
332
+ '''
333
+ assert role.end1_multiplicity>1 and role.end2_multiplicity>1
334
+ dbtable_assoc = self.tables_js[role.assoc_table.tablename]
335
+ end1_tb_idfld = role.end1_reftable.get_keyfield()
336
+ column1 = DBColumn_fkeyid(role.end1_foreign_key_name)
337
+ column1.dbname = '' if not role.end1_mapid else '"%s",' % role.end1_mapid.lower()
338
+ column1.type = self.covert2pytype(end1_tb_idfld.fieldtype, end1_tb_idfld.fieldsize)
339
+ column1.reftable = self.__get_table_name(role.end1_reftable) #.maptablename.lower()
340
+ column1.refid = end1_tb_idfld.fieldname if not end1_tb_idfld.mapname else end1_tb_idfld.mapname
341
+ column1.primary_key = ', primary_key=True'
342
+ dbtable_assoc.fkeyids.append(column1)
343
+
344
+ end2_tb_idfld = role.end2_reftable.get_keyfield()
345
+ column2 = DBColumn_fkeyid(role.end2_foreign_key_name)
346
+ column2.dbname = '' if not role.end2_mapid else '"%s",' % role.end2_mapid.lower()
347
+ column2.type = self.covert2pytype(end2_tb_idfld.fieldtype, end2_tb_idfld.fieldsize)
348
+ column2.primary_key = ', primary_key=True'
349
+ column2.reftable = self.__get_table_name(role.end2_reftable) #role.end2_reftable.maptablename.lower()
350
+ column2.refid = end2_tb_idfld.fieldname if not end2_tb_idfld.mapname else end2_tb_idfld.mapname
351
+ dbtable_assoc.fkeyids.append(column2)
352
+ fkeys_end1 = DBRelationship(role.end1_rolename)
353
+ fkeys_end1.relationship_cls = role.end1_reftable.tablename.capitalize()
354
+ # fkeys_end1.lazy = ', lazy="%s"' % role.end2_lazy if role.end2_lazy else ''
355
+ fkeys_end1.foreign_keys = ', foreign_keys="{assoc_cls}.{fkey}"'.format(
356
+ assoc_cls = role.assoc_table.tablename.capitalize(),
357
+ fkey= role.end1_foreign_key_name,
358
+ )
359
+ fkeys_end1.back_populates = ', back_populates="{end2_roles}"'.format(
360
+ end2_roles='%ss'%role.end2_rolename
361
+ )
362
+ dbtable_assoc.relationsips.append(fkeys_end1)
363
+ fkeys_end2 = DBRelationship(role.end2_rolename)
364
+ fkeys_end2.relationship_cls = role.end2_reftable.tablename.capitalize()
365
+ # fkeys_end2.lazy = ', lazy="%s"' % role.end1_lazy if role.end1_lazy else ''
366
+ fkeys_end2.foreign_keys = ', foreign_keys="{assoc_cls}.{fkey}"'.format(
367
+ assoc_cls=role.assoc_table.tablename.capitalize(),
368
+ fkey=role.end2_foreign_key_name
369
+ )
370
+ fkeys_end2.back_populates = ', back_populates="{end1_roles}"'.format(
371
+ end1_roles='%ss' % role.end1_rolename
372
+ )
373
+ dbtable_assoc.relationsips.append(fkeys_end2)
374
+
375
+ '''
376
+ class Parent(Base):
377
+ children = relationship("Association", back_populates="parent")
378
+ '''
379
+ dbtable_end1 = self.tables_js[role.end1_reftable.tablename]
380
+ fkeys_end1 = DBRelationship('%ss' % role.end2_rolename)
381
+ fkeys_end1.relationship_cls = role.assoc_table.tablename.capitalize()
382
+ fkeys_end1.lazy = ', lazy="%s"' % role.end2_lazy if role.end2_lazy else ''
383
+ fkeys_end1.foreign_keys =', foreign_keys="{assoc_cls}.{fkey}"'.format(
384
+ assoc_cls=role.assoc_table.tablename.capitalize(),
385
+ fkey=role.end1_foreign_key_name
386
+ )
387
+ fkeys_end1.back_populates = ', back_populates="{end1_role}"'.format(
388
+ end1_role=role.end1_rolename
389
+ )
390
+ dbtable_end1.relationsips.append(fkeys_end1)
391
+
392
+ '''
393
+ class Child(Base):
394
+ parents = relationship("Association", back_populates="child")
395
+ '''
396
+ dbtable_end2 = self.tables_js[role.end2_reftable.tablename]
397
+ fkeys_end2 = DBRelationship('%ss' % role.end1_rolename)
398
+ fkeys_end2.relationship_cls = role.assoc_table.tablename.capitalize()
399
+ fkeys_end2.lazy = ', lazy="%s"' % role.end1_lazy if role.end1_lazy else ''
400
+ fkeys_end2.foreign_keys =', foreign_keys="{assoc_cls}.{fkey}"'.format(
401
+ assoc_cls=role.assoc_table.tablename.capitalize(),
402
+ fkey=role.end2_foreign_key_name
403
+ )
404
+ fkeys_end2.back_populates = ', back_populates="{end2_role}"'.format(
405
+ end2_role=role.end2_rolename
406
+ )
407
+ dbtable_end2.relationsips.append(fkeys_end2)
408
+
409
+ def __gen_m2m_code(self, role):
410
+ '''
411
+ :param role:
412
+ :return:
413
+ '''
414
+ '''
415
+ association_table = Table('association', Base.metadata,
416
+ Column('left_id', Integer, ForeignKey('left.id')),
417
+ Column('right_id', Integer, ForeignKey('right.id'))
418
+ )
419
+ '''
420
+ assert role.end1_multiplicity>1 and role.end2_multiplicity>1
421
+ # 多对多关联类不需要子类
422
+ role.assoc_table.is_need_sonboclass = False
423
+ tablename = self.__get_table_name(role.assoc_table)
424
+ # tablename = role.assoc_table.tablename.lower() \
425
+ # if role.assoc_table.maptablename is None \
426
+ # else role.assoc_table.maptablename.lower()
427
+ table_meta_class =self.tables_meta_js[tablename] = DBTable_meta()
428
+ table_meta_class.class_name = role.assoc_table.tablename.lower()
429
+ table_meta_class.table_name = tablename
430
+ end1_tb_idfld = role.end1_reftable.get_keyfield()
431
+ column0 = DBColumn_fkeyid(role.end1_foreign_key_name)
432
+ column0.dbname = role.end1_foreign_key_name
433
+ column0.type = self.covert2pytype(end1_tb_idfld.fieldtype, end1_tb_idfld.fieldsize)
434
+ column0.reftable = self.__get_table_name(role.end1_reftable)#self.role.end1_reftable.maptablename.lower()
435
+ column0.refid = end1_tb_idfld.fieldname if not end1_tb_idfld.mapname else end1_tb_idfld.mapname
436
+ table_meta_class.columns.append(column0)
437
+
438
+ end2_tb_idfld = role.end2_reftable.get_keyfield()
439
+ column1 = DBColumn_fkeyid(role.end2_foreign_key_name)
440
+ column1.dbname = role.end2_foreign_key_name
441
+ column1.type = self.covert2pytype(end2_tb_idfld.fieldtype, end2_tb_idfld.fieldsize)
442
+ column1.reftable = self.__get_table_name(role.end2_reftable)#.maptablename.lower()
443
+ column1.refid = end2_tb_idfld.fieldname if not end2_tb_idfld.mapname else end2_tb_idfld.mapname
444
+ table_meta_class.columns.append(column1)
445
+
446
+ '''
447
+ class Parent(Base):
448
+ children = relationship("Child",
449
+ secondary=association_table,
450
+ back_populates="parents")
451
+ '''
452
+ dbtable_end1 = self.tables_js[role.end1_reftable.tablename]
453
+ fkeys_end1 = DBRelationship('%ss' % role.end2_rolename)
454
+ fkeys_end1.relationship_cls = role.end2_reftable.tablename.capitalize()
455
+ fkeys_end1.lazy = ', lazy="%s"' % role.end2_lazy if role.end2_lazy else ''
456
+ fkeys_end1.secondary =',secondary={tablename} '.format(tablename=tablename)
457
+ fkeys_end1.back_populates = ', back_populates="{end1_roles}"'.format(
458
+ end1_roles='%ss' % role.end1_rolename
459
+ )
460
+ dbtable_end1.relationsips.append(fkeys_end1)
461
+
462
+ '''
463
+ class Child(Base):
464
+ parents = relationship("Parent",
465
+ secondary=association_table,
466
+ back_populates="children")
467
+ '''
468
+ dbtable_end2 = self.tables_js[role.end2_reftable.tablename]
469
+ fkeys_end2 = DBRelationship('%ss' % role.end1_rolename)
470
+ fkeys_end2.relationship_cls = role.end1_reftable.tablename.capitalize()
471
+ fkeys_end2.lazy = ', lazy="%s"' % role.end1_lazy if role.end1_lazy else ''
472
+ fkeys_end2.secondary =',secondary={tablename} '.format(tablename=tablename)
473
+ fkeys_end2.back_populates = ', back_populates="{end2_roles}"'.format(
474
+ end2_roles='%ss' % role.end2_rolename
475
+ )
476
+ dbtable_end2.relationsips.append(fkeys_end2)
477
+
478
+ def __gen_model_code(self):
479
+ for table in self.tables:
480
+ # 不包含属性的多对多关系直接产生meta table
481
+ if table.is_assoc_table and len(table.fielddictionarys)==1:
482
+ continue
483
+
484
+ tablename = table.tablename.lower() if table.maptablename is None \
485
+ else table.maptablename.lower()
486
+ table_js= DBTable()
487
+ table_js.doc = (table.description or '').replace('\n','\n ')
488
+ self.tables_js[table.tablename]=table_js
489
+ bo_class = table.tablename.capitalize()
490
+ table_js.class_name = bo_class
491
+ table_js.table_name = tablename
492
+ table_js.bind_key = table.bind_db
493
+ table_js.is_sigletable = table.is_sigletable
494
+ # todo 先跳过,等以后再升级(因为需要mysql升级到8.0.3之后)
495
+ # if table_js.doc :
496
+ # table_js.table_args['comment'] = table_js.doc
497
+ # 是单表继承
498
+ if table.is_sigletable:
499
+ # 父类,需要增加识别栏位
500
+ if table.is_parentclass:
501
+ # discriminator = db.Column('type', db.String(50))
502
+ column = DBColumn('discriminator')
503
+ column.type = '{model_pre}String({size})'.format(model_pre=self.model_prefix,
504
+ size=50)
505
+ column.dbname = '"type",'
506
+ table_js.discriminator_column = column
507
+ table_js.mapper_args = "{'polymorphic_on': discriminator}"
508
+ table_js.is_parent_class = True
509
+ elif table.parent :
510
+ # 子类不需要 table
511
+ table_js.mapper_args = "{'polymorphic_identity': '%s'}"%tablename
512
+ table_js.table_name = ''
513
+ table_js.parent_name = table.parent.tablename.capitalize()
514
+ else:
515
+ assert False,'not suport'
516
+
517
+ for fld in table.fielddictionarys:
518
+ fld_name = fld.fieldname.replace(' ', '')
519
+ column = DBColumn(fld_name)
520
+ column.doc = (fld.doc or '').replace('\n','. ')
521
+ column.type = self.covert2pytype(fld.fieldtype, fld.fieldsize)
522
+ column.dbname = '' if fld.mapname is None else '"%s",' % fld.mapname.lower()
523
+ if fld.keytype == Keytype.key.value :
524
+ # 关联表使用使用外键做key
525
+ if table.is_assoc_table:
526
+ continue
527
+ # 单表继承关系的子类不需要id
528
+ if table.is_sigletable and table.parent:
529
+ continue
530
+ column.primary_key = ', primary_key=True'
531
+ if fld.fieldtype in ('int','AutoInt'):
532
+ table_js.table_args['implicit_returning'] = False
533
+ elif fld.fieldfrom == FieldFrom.database.value:
534
+ pass
535
+ else:
536
+ continue
537
+ column.nullable =', nullable= False' if not fld.isallownull else ''
538
+ column.unique =', unique= True' if fld.repfields == fld.fieldname else ''
539
+ column.default= ', default= %s' % self.__validDefault(fld, fld.defaultvalue) if fld.defaultvalue else ''
540
+ table_js.columns.append(column)
541
+ # 多栏位不能重复
542
+ if fld.repfields and fld.repfields != fld.fieldname:
543
+ repflds = fld.repfields.split(';')
544
+ # 把fieldname替换成资料库的mapname
545
+ repflds = [fld.mapname if fld.mapname is not None and repfld == fld.fieldname else repfld for repfld
546
+ in repflds]
547
+ consraint = "{model_pre}UniqueConstraint({rep_flds}, name='unique_{table_name}_{comp_name}')" .format (
548
+ model_pre = self.model_prefix,
549
+ rep_flds = ','.join(["'%s'" % rf for rf in repflds]),
550
+ table_name = table.tablename,
551
+ comp_name = '_'.join([rf for rf in repflds]))
552
+ table_js.unique_constraints.append(consraint)
553
+ for op in table.ddoperations:
554
+ func = DBFunc(op.name)
555
+ func.isstatic = op.isstatic
556
+ func.isquery = op.isquery
557
+ func.isabstract = op.isabstract
558
+ func.params = ',%s'%op.py_params if op.py_params else ''
559
+ func.self_param = 'cls' if op.isstatic else 'self'
560
+ func.codes = ' pass' if op.isabstract else op.specification
561
+ func.doc = op.doc
562
+ table_js.funcs.append(func)
563
+ roles = self.session.query(Roledictionary).\
564
+ filter(Roledictionary.ddid==self.database_dict.id).all()
565
+ for role in roles:
566
+ if role.is_o2o():
567
+ self.__gen_o2o_code(role)
568
+ elif role.is_m2o():
569
+ self.__gen_m2o_code(role)
570
+ elif role.is_o2m():
571
+ self.__gen_o2m_code(role)
572
+ elif role.is_m2m():
573
+ if role.assoc_table is None:
574
+ raise Exception('the role 缺少关系定义,如:1-->*,%s'%role)
575
+ # 如果关联类包含栏位,需要做为类出现,否则只需要meta 类即可
576
+ if len(role.assoc_table.fielddictionarys)>1:
577
+ self.__gen_m2m_code4assoc(role)
578
+ else:
579
+ self.__gen_m2m_code(role)
580
+ dbenumerations = self.session.query(DBEnumeration).\
581
+ filter(DBEnumeration.ddid == self.database_dict.id).all()
582
+ for dbenum in dbenumerations:
583
+ enum_model = Enume_model(dbenum.name.capitalize())
584
+ self.enmumerations_js.append(enum_model)
585
+ for eitm in dbenum.enumeitems:
586
+ enum_model.columns[eitm.name] = '"%s"'%eitm.value if eitm.type=='string' else eitm.value
587
+
588
+ return self.tables_js
589
+
590
+ def gen_code(self,outfile,exists2cover=True):
591
+ tables = self.__gen_model_code()
592
+ template = self.__load_template(self.template_file)
593
+ # print(self.tables_meta_js)
594
+ result = template.render(tables= tables,
595
+ metatables= self.tables_meta_js,
596
+ enumerations= self.enmumerations_js)
597
+ codes = [line for line in result.split('\n') if line.strip() != '']
598
+ import os
599
+ if exists2cover and os.path.exists(outfile):
600
+ logging.warning('the file is exists,将被覆盖!,filename:%s' % outfile)
601
+ elif not exists2cover and os.path.exists(outfile):
602
+ logging.warning('the file is exists,不允许覆盖!,filename:%s' % outfile)
603
+ return
604
+ saveUTF8File(outfile, codes,writegeninfo=False)
605
+
606
+ class BoCodeGenerator_flask(BoCodeGenerator_base):
607
+ '''
608
+ 创建flask的model
609
+ '''
610
+ def __init__(self,database_dict):
611
+ super().__init__(database_dict)
612
+ # 如:db.Model,db.Column
613
+ self.model_prefix = 'db.'
614
+ # 类的后缀,如_base 。。。
615
+ self.class_suffix = '_base'
616
+ self.template_file = 'flask_models_base.pys'
617
+
618
+ def _get_models_class_code(self,outfile):
619
+ import os
620
+ import codecs
621
+ codes = []
622
+ models_file = os.path.join(os.path.dirname(outfile), MODELS_PY)
623
+ if os.path.exists(models_file):
624
+ with codecs.open(models_file, "r", "utf-8") as file:
625
+ for code in file.readlines():
626
+ if code.startswith('########'):
627
+ continue
628
+ if code.startswith('# create '):
629
+ continue
630
+ codes.append(code.rstrip())
631
+ return codes
632
+
633
+ def _gen_model_py_code(self,outfile):
634
+ models_class_code = self._get_models_class_code(outfile)
635
+ if not models_class_code:
636
+ models_code = ['from .models_base import *']
637
+ else:
638
+ models_code = models_class_code.copy()
639
+ class_def_lower = [c.lower().split('(')[0]+'(' for c in models_code if c.startswith('class ')]
640
+ for table in self.tables:
641
+ bo_class = table.tablename.capitalize()
642
+ # 1,继承的类不能在model中再继承定义,否则会不能新增数据
643
+ # if table.is_sigletable:
644
+ # continue
645
+ #,2,多对多关联类有带自定义属性的需要后代类
646
+ if not table.is_need_sonboclass:
647
+ continue
648
+ bo_class_def = 'class {cls_name}({cls_name}{cls_suffix}):' .format (
649
+ cls_name =bo_class,
650
+ cls_suffix=self.class_suffix)
651
+ # 只要包含class的定义即可,小写
652
+ if bo_class_def.split('(')[0].lower()+'(' not in class_def_lower :
653
+ models_code.append(bo_class_def)
654
+ models_code.append(' pass')
655
+ return models_code
656
+
657
+ def gen_code(self,outfile,exists2cover=True):
658
+ super().gen_code(outfile)
659
+ import os
660
+ # 创建models.py
661
+ models_code = self._gen_model_py_code(outfile)
662
+ models_file = os.path.join(os.path.dirname(outfile), MODELS_PY)
663
+ saveUTF8File(models_file, models_code)
664
+
665
+ class BoCodeGenerator_sqlalchemy(BoCodeGenerator_base):
666
+ '''
667
+ 创建sqlalchemy 的model
668
+ '''
669
+ def __init__(self,database_dict):
670
+ super().__init__(database_dict)
671
+ # 如:db.Model,db.Column
672
+ self.model_prefix = ''
673
+ # 类的后缀,如_base 。。。
674
+ self.class_suffix = ''
675
+ self.template_file = 'flask_models.pys'
676
+
677
+ def __gen_ext_py_code(self):
678
+ codes = []
679
+ codes.append('from sqlalchemy.ext.declarative import declarative_base')
680
+ codes.append('from sqlalchemy import create_engine')
681
+ codes.append('from sqlalchemy.orm import sessionmaker')
682
+ codes.append('Base = declarative_base()')
683
+ codes.append('engine = create_engine("sqlite:///:memory:")')
684
+ codes.append(" ")
685
+ codes.append('Session = sessionmaker(bind=engine)')
686
+ return codes
687
+
688
+ def gen_code(self,outfile,exists2cover=False):
689
+ # todo delete exists2cover = True
690
+ # exists2cover = True
691
+ super().gen_code(outfile,exists2cover)
692
+ import os
693
+ # 创建ext.py
694
+ ext_file =os.path.join(os.path.dirname(outfile), 'ext.py')
695
+ if not os.path.exists(ext_file):
696
+ saveUTF8File(ext_file,self.__gen_ext_py_code())
697
+
698
+ class Gen_bo_models():
699
+ def __init__(self,modelfile,outfile,type='flask'):
700
+ imp = ImportDDModels()
701
+ self.database_dictionary = imp.impUMLModels(modelfile)
702
+ self.outfile= outfile
703
+ if type == Gen_type.flask.value:
704
+ self.bo_code_generator = BoCodeGenerator_flask(self.database_dictionary)
705
+ elif type == Gen_type.sql.value:
706
+ self.bo_code_generator = BoCodeGenerator_sqlalchemy(self.database_dictionary)
707
+ else:
708
+ self.bo_code_generator = BoCodeGenerator_flask(self.database_dictionary)
709
+
710
+ def gen_code(self,exists2cover=True):
711
+ self.bo_code_generator.gen_code(self.outfile,exists2cover)
712
+
713
+
714
+
715
+
716
+
717
+
718
+
719
+