1
1
import edgedb
2
2
import json
3
+ import re
3
4
4
5
5
6
DSN = 'edgedb://edgedb@localhost:5656/edgedb?tls_security=insecure'
65
66
not re_test('^(std|cfg|sys|schema)::', .name);
66
67
'''
67
68
69
+ CLEAN_RE = re .compile (r'[^A-Za-z0-9]+' )
68
70
69
- def get_object_type_name (name ):
70
- # for now just assume stuff is in "defualt" module
71
- return name .replace ('default::' , '' )
71
+
72
+ def get_clean_name (name ):
73
+ # Just remove default module name
74
+ if name .startswith ('default::' ):
75
+ name = name [9 :]
76
+ elif '::' in name :
77
+ raise RuntimeError (f'Only the default modile is supported: { name } ' )
78
+
79
+ # After this replace all non-alphanumeric chartacters with '_'
80
+ name = CLEAN_RE .sub ('_' , name )
81
+
82
+ # Prefix with '_' if name starts with a digit
83
+ if name [0 ].isnumeric ():
84
+ name = '_' + name
85
+
86
+ return name
87
+
88
+
89
+ def get_sql_name (name ):
90
+ # Just remove default module name
91
+ if name .startswith ('default::' ):
92
+ name = name [9 :]
93
+ elif '::' in name :
94
+ raise RuntimeError (f'Only the default modile is supported: { name } ' )
95
+
96
+ return name
72
97
73
98
74
99
def get_schema_json (client ):
@@ -88,31 +113,36 @@ def _process_links(types):
88
113
link_tables = []
89
114
type_map = {}
90
115
for spec in types :
91
- type_map [get_object_type_name (spec ['name' ])] = spec
116
+ type_map [get_clean_name (spec ['name' ])] = spec
92
117
93
118
for spec in types :
94
119
for link in spec ['links' ]:
95
120
if link ['name' ] != '__type__' :
96
- target = get_object_type_name (link ['target' ]['name' ])
121
+ target = get_clean_name (link ['target' ]['name' ])
122
+ sql_target = get_sql_name (link ['target' ]['name' ])
97
123
cardinality = link ['cardinality' ]
98
124
exclusive = link ['exclusive' ]
125
+ name = get_clean_name (link ['name' ])
126
+ sql_name = get_sql_name (link ['name' ])
99
127
100
128
objtype = type_map [target ]
101
129
objtype ['backlinks' ].append ({
102
- 'name' : f'backlink_via_{ link [ " name" ] } ' ,
130
+ 'name' : f'backlink_via_{ name } ' ,
103
131
'cardinality' : 'One' if exclusive else 'Many' ,
104
132
'exclusive' : cardinality == 'One' ,
105
133
'target' : {'name' : spec ['name' ]},
106
134
})
107
135
108
136
# Add a link table for One-to-Many and Many-to-Many
109
137
if cardinality == 'Many' :
110
- source = get_object_type_name (spec ["name" ])
138
+ source = get_clean_name (spec ["name" ])
139
+ sql_source = get_sql_name (spec ["name" ])
111
140
link_tables .append ({
112
- 'name' : f'{ source } _{ link ["name" ]} _table' ,
113
- 'table' : f'{ source } .{ link ["name" ]} ' ,
114
- 'source' : f'{ source } .id' ,
115
- 'target' : f'{ target } .id' ,
141
+ 'name' : f'{ source } _{ name } _table' ,
142
+ 'table' : f'{ sql_source } .{ sql_name } ' ,
143
+ 'source' : f'{ sql_source } .id' ,
144
+ 'target' : f'{ sql_target } .id' ,
145
+ 'properties' : link ['properties' ],
116
146
})
117
147
118
148
return {
@@ -127,17 +157,24 @@ def render_link_table(spec):
127
157
{ spec ["table" ]!r} ,
128
158
Base.metadata,
129
159
Column("source", ForeignKey({ spec ["source" ]!r} )),
130
- Column("target", ForeignKey({ spec ["target" ]!r} )),
131
- )\
132
- ''' )
160
+ Column("target", ForeignKey({ spec ["target" ]!r} )),''' )
161
+
162
+ for prop in spec ['properties' ]:
163
+ sql_name = get_sql_name (prop ['name' ])
164
+ _ , sqlatype = GEL_SCALAR_MAP [prop ['target' ]['name' ]]
165
+
166
+ print (f'{ INDENT } Column({ sql_name !r} , { sqlatype } ()),' )
167
+
168
+ print (')' )
133
169
134
170
135
171
def render_type (spec ):
136
172
# assume nice names for now
137
- name = get_object_type_name (spec ['name' ])
173
+ name = get_clean_name (spec ['name' ])
174
+ sql_name = get_sql_name (spec ['name' ])
138
175
139
176
print (f'class { name } (Base):' )
140
- print (f'{ INDENT } __tablename__ = { name !r} ' )
177
+ print (f'{ INDENT } __tablename__ = { sql_name !r} ' )
141
178
142
179
# Add two fields that all objects have
143
180
print (
@@ -169,30 +206,40 @@ def render_type(spec):
169
206
170
207
171
208
def render_prop (spec ):
172
- name = spec ['name' ]
209
+ name = get_clean_name (spec ['name' ])
210
+ sql_name = get_sql_name (spec ['name' ])
173
211
nullable = not spec ['required' ]
174
212
175
213
pytype , sqlatype = GEL_SCALAR_MAP [spec ['target' ]['name' ]]
176
214
215
+ maybe_sql_name = ''
216
+ if name != sql_name :
217
+ maybe_sql_name = f'{ sql_name !r} , '
218
+
177
219
print (
178
220
f'\
179
221
{ name } : Mapped[{ pytype } ] = '
180
- f'mapped_column({ sqlatype } (), nullable={ nullable } )'
222
+ f'mapped_column({ maybe_sql_name } { sqlatype } (), nullable={ nullable } )'
181
223
)
182
224
183
225
184
226
def render_link (spec , parent ):
185
- name = spec ['name' ]
227
+ name = get_clean_name (spec ['name' ])
228
+ sql_name = get_sql_name (spec ['name' ])
186
229
nullable = not spec ['required' ]
187
- target = get_object_type_name (spec ['target' ]['name' ])
230
+ target = get_clean_name (spec ['target' ]['name' ])
188
231
cardinality = spec ['cardinality' ]
189
232
bklink = f'backlink_via_{ name } '
190
233
234
+ maybe_sql_name = ''
235
+ if name != sql_name :
236
+ maybe_sql_name = f'{ sql_name + "_id" !r} , '
237
+
191
238
if cardinality == 'One' :
192
239
print (
193
240
f'{ INDENT } { name } _id: Mapped[uuid.UUID] = '
194
- f'mapped_column(Uuid(), ForeignKey(" { target } .id" ), '
195
- f'nullable={ nullable } )'
241
+ f'mapped_column({ maybe_sql_name } Uuid( ), '
242
+ f'ForeignKey(" { target } .id"), nullable={ nullable } )'
196
243
)
197
244
print (
198
245
f'{ INDENT } { name } : Mapped[{ target !r} ] = '
@@ -210,7 +257,7 @@ def render_link(spec, parent):
210
257
211
258
def render_backlink (spec ):
212
259
name = spec ['name' ]
213
- target = get_object_type_name (spec ['target' ]['name' ])
260
+ target = get_clean_name (spec ['target' ]['name' ])
214
261
cardinality = spec ['cardinality' ]
215
262
exclusive = spec ['exclusive' ]
216
263
bklink = name .replace ('backlink_via_' , '' , 1 )
0 commit comments