1
1
import pathlib
2
2
import re
3
+ import warnings
3
4
4
- from ..introspection import get_mod_and_name , FilePrinter
5
+ from ..introspection import get_mod_and_name , GelORMWarning , FilePrinter
5
6
6
7
7
8
GEL_SCALAR_MAP = {
24
25
'cal::local_date' : 'DateField' ,
25
26
'cal::local_datetime' : 'DateTimeField' ,
26
27
'cal::local_time' : 'TimeField' ,
27
- # all kinds of duration is not supported due to this error:
28
+ # all kinds of durations are not supported due to this error:
28
29
# iso_8601 intervalstyle currently not supported
29
30
}
30
31
@@ -53,7 +54,6 @@ class GelPGMeta:
53
54
'This is a model reflected from Gel using Postgres protocol.'
54
55
'''
55
56
56
- FK_RE = re .compile (r'''models\.ForeignKey\((.+?),''' )
57
57
CLOSEPAR_RE = re .compile (r'\)(?=\s+#|$)' )
58
58
59
59
@@ -83,19 +83,16 @@ def __init__(self, *, out):
83
83
84
84
def spec_to_modules_dict (self , spec ):
85
85
modules = {
86
- mod : {} for mod in sorted (spec ['modules' ])
86
+ mod : {'link_tables' : {}, 'object_types' : {}}
87
+ for mod in sorted (spec ['modules' ])
87
88
}
88
89
89
90
for rec in spec ['link_tables' ]:
90
91
mod = rec ['module' ]
91
- if 'link_tables' not in modules [mod ]:
92
- modules [mod ]['link_tables' ] = {}
93
92
modules [mod ]['link_tables' ][rec ['table' ]] = rec
94
93
95
94
for rec in spec ['object_types' ]:
96
95
mod , name = get_mod_and_name (rec ['name' ])
97
- if 'object_types' not in modules [mod ]:
98
- modules [mod ]['object_types' ] = {}
99
96
modules [mod ]['object_types' ][name ] = rec
100
97
101
98
return modules ['default' ]
@@ -128,10 +125,12 @@ def build_models(self, maps):
128
125
# process properties as fields
129
126
for prop in rec ['properties' ]:
130
127
pname = prop ['name' ]
131
- if pname == 'id' :
128
+ if pname == 'id' or prop [ 'cardinality' ] == 'Many' :
132
129
continue
133
130
134
- mod .props [pname ] = self .render_prop (prop )
131
+ code = self .render_prop (prop )
132
+ if code :
133
+ mod .props [pname ] = code
135
134
136
135
# process single links as fields
137
136
for link in rec ['links' ]:
@@ -142,7 +141,9 @@ def build_models(self, maps):
142
141
143
142
lname = link ['name' ]
144
143
bklink = mod .get_backlink_name (lname )
145
- mod .links [lname ] = self .render_link (link , bklink )
144
+ code = self .render_link (link , bklink )
145
+ if code :
146
+ mod .links [lname ] = code
146
147
147
148
modmap [mod .name ] = mod
148
149
@@ -153,7 +154,16 @@ def build_models(self, maps):
153
154
mod .meta ['unique_together' ] = "(('source', 'target'),)"
154
155
155
156
# Only have source and target
156
- _ , target = get_mod_and_name (rec ['target' ])
157
+ mtgt , target = get_mod_and_name (rec ['target' ])
158
+ if mtgt != 'default' :
159
+ # skip this whole link table
160
+ warnings .warn (
161
+ f'Skipping link { fwname !r} : link target '
162
+ f'{ rec ["target" ]!r} is not supported' ,
163
+ GelORMWarning ,
164
+ )
165
+ continue
166
+
157
167
mod .links ['source' ] = (
158
168
f"LTForeignKey({ source !r} , models.DO_NOTHING, "
159
169
f"db_column='source', primary_key=True)"
@@ -190,8 +200,11 @@ def render_prop(self, prop):
190
200
try :
191
201
ftype = GEL_SCALAR_MAP [target ]
192
202
except KeyError :
193
- raise RuntimeError (
194
- f'Scalar type { target } is not supported' )
203
+ warnings .warn (
204
+ f'Scalar type { target } is not supported' ,
205
+ GelORMWarning ,
206
+ )
207
+ return ''
195
208
196
209
return f'models.{ ftype } ({ req } )'
197
210
@@ -201,7 +214,15 @@ def render_link(self, link, bklink=None):
201
214
else :
202
215
req = ', blank=True, null=True'
203
216
204
- _ , target = get_mod_and_name (link ['target' ]['name' ])
217
+ mod , target = get_mod_and_name (link ['target' ]['name' ])
218
+
219
+ if mod != 'default' :
220
+ warnings .warn (
221
+ f'Skipping link { link ["name" ]!r} : link target '
222
+ f'{ link ["target" ]["name" ]!r} is not supported' ,
223
+ GelORMWarning ,
224
+ )
225
+ return ''
205
226
206
227
if bklink :
207
228
bklink = f', related_name={ bklink !r} '
@@ -215,23 +236,28 @@ def render_models(self, spec):
215
236
# Check that there is only "default" module
216
237
mods = spec ['modules' ]
217
238
if mods [0 ] != 'default' or len (mods ) > 1 :
218
- raise RuntimeError (
219
- f"Django reflection doesn't support multiple modules or "
220
- f"non-default modules."
239
+ skipped = ', ' .join ([repr (m ) for m in mods if m != 'default' ])
240
+ warnings .warn (
241
+ f"Skipping modules { skipped } : Django reflection doesn't "
242
+ f"support multiple modules or non-default modules." ,
243
+ GelORMWarning ,
221
244
)
222
245
# Check that we don't have multiprops or link properties as they
223
246
# produce models without `id` field and Django doesn't like that. It
224
247
# causes Django to mistakenly use `source` as `id` and also attempt to
225
248
# UPDATE `target` on link tables.
226
249
if len (spec ['prop_objects' ]) > 0 :
227
- raise RuntimeError (
228
- f"Django reflection doesn't support multi properties as they "
229
- f"produce models without `id` field."
250
+ warnings .warn (
251
+ f"Skipping multi properties: Django reflection doesn't "
252
+ f"support multi properties as they produce models without "
253
+ f"`id` field." ,
254
+ GelORMWarning ,
230
255
)
231
256
if len (spec ['link_objects' ]) > 0 :
232
- raise RuntimeError (
233
- f"Django reflection doesn't support link properties as they "
234
- f"produce models without `id` field."
257
+ warnings .warn (
258
+ f"Skipping link properties: Django reflection doesn't support "
259
+ f"link properties as they produce models without `id` field." ,
260
+ GelORMWarning ,
235
261
)
236
262
237
263
maps = self .spec_to_modules_dict (spec )
0 commit comments