udata 9.0.1.dev29536__py2.py3-none-any.whl → 9.0.1.dev29541__py2.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.
Potentially problematic release.
This version of udata might be problematic. Click here for more details.
- udata/commands/db.py +88 -48
- udata/db/__init__.py +0 -0
- udata/db/tasks.py +6 -0
- udata/static/chunks/{11.7266fef2dddc1db403d9.js → 11.ae54612e36c6d46f85db.js} +3 -3
- udata/static/chunks/{11.7266fef2dddc1db403d9.js.map → 11.ae54612e36c6d46f85db.js.map} +1 -1
- udata/static/chunks/{13.91b177d7d531fd55cf5d.js → 13.d8ccb992a49875966313.js} +2 -2
- udata/static/chunks/{13.91b177d7d531fd55cf5d.js.map → 13.d8ccb992a49875966313.js.map} +1 -1
- udata/static/chunks/{16.e866757bab9f6b0a3f1b.js → 16.4565605e68bab129a471.js} +2 -2
- udata/static/chunks/{16.e866757bab9f6b0a3f1b.js.map → 16.4565605e68bab129a471.js.map} +1 -1
- udata/static/chunks/{19.619b83ac597516dcd03e.js → 19.f993a75d5bfe2382548d.js} +3 -3
- udata/static/chunks/{19.619b83ac597516dcd03e.js.map → 19.f993a75d5bfe2382548d.js.map} +1 -1
- udata/static/chunks/{5.48417db6b33328fa9d6a.js → 5.cc2e7bf65ef32f9c8604.js} +3 -3
- udata/static/chunks/{5.48417db6b33328fa9d6a.js.map → 5.cc2e7bf65ef32f9c8604.js.map} +1 -1
- udata/static/chunks/{6.f84539bd4c419b36cc19.js → 6.cad898a38692eda28965.js} +3 -3
- udata/static/chunks/{6.f84539bd4c419b36cc19.js.map → 6.cad898a38692eda28965.js.map} +1 -1
- udata/static/chunks/{9.07503e7f7ec02919f696.js → 9.d5b992e9ef51921aeb57.js} +2 -2
- udata/static/chunks/{9.07503e7f7ec02919f696.js.map → 9.d5b992e9ef51921aeb57.js.map} +1 -1
- udata/static/common.js +1 -1
- udata/static/common.js.map +1 -1
- udata/tasks.py +1 -0
- {udata-9.0.1.dev29536.dist-info → udata-9.0.1.dev29541.dist-info}/METADATA +2 -1
- {udata-9.0.1.dev29536.dist-info → udata-9.0.1.dev29541.dist-info}/RECORD +26 -24
- {udata-9.0.1.dev29536.dist-info → udata-9.0.1.dev29541.dist-info}/LICENSE +0 -0
- {udata-9.0.1.dev29536.dist-info → udata-9.0.1.dev29541.dist-info}/WHEEL +0 -0
- {udata-9.0.1.dev29536.dist-info → udata-9.0.1.dev29541.dist-info}/entry_points.txt +0 -0
- {udata-9.0.1.dev29536.dist-info → udata-9.0.1.dev29541.dist-info}/top_level.txt +0 -0
udata/commands/db.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import collections
|
|
2
|
+
from itertools import groupby
|
|
2
3
|
import logging
|
|
3
4
|
import os
|
|
5
|
+
import traceback
|
|
4
6
|
|
|
7
|
+
from bson import DBRef
|
|
5
8
|
import click
|
|
6
9
|
import mongoengine
|
|
7
10
|
|
|
@@ -135,8 +138,14 @@ def display_op(op):
|
|
|
135
138
|
echo('{label:.<70} [{date}]'.format(label=label, date=timestamp))
|
|
136
139
|
format_output(op['output'], success=op['success'], traceback=op.get('traceback'))
|
|
137
140
|
|
|
138
|
-
|
|
139
141
|
def check_references(models_to_check):
|
|
142
|
+
# Cannot modify local scope from Python… :-(
|
|
143
|
+
class Log: errors = []
|
|
144
|
+
|
|
145
|
+
def print_and_save(text: str):
|
|
146
|
+
Log.errors.append(text.strip())
|
|
147
|
+
print(text)
|
|
148
|
+
|
|
140
149
|
errors = collections.defaultdict(int)
|
|
141
150
|
|
|
142
151
|
_models = []
|
|
@@ -147,7 +156,7 @@ def check_references(models_to_check):
|
|
|
147
156
|
]
|
|
148
157
|
|
|
149
158
|
references = []
|
|
150
|
-
for model in _models:
|
|
159
|
+
for model in set(_models):
|
|
151
160
|
if model.__name__ == 'Activity':
|
|
152
161
|
print(f'Skipping Activity model, scheduled for deprecation')
|
|
153
162
|
continue
|
|
@@ -240,53 +249,84 @@ def check_references(models_to_check):
|
|
|
240
249
|
print(f'- {reference["repr"]}({reference["destination"]}) — {reference["type"]}')
|
|
241
250
|
print('')
|
|
242
251
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
_ = sub.id
|
|
258
|
-
except mongoengine.errors.DoesNotExist:
|
|
259
|
-
errors[reference["repr"]] += 1
|
|
260
|
-
elif reference['type'] == 'embed_list':
|
|
261
|
-
p1, p2 = reference['name'].split('__')
|
|
262
|
-
for sub in getattr(obj, p1):
|
|
263
|
-
try:
|
|
264
|
-
getattr(sub, p2)
|
|
265
|
-
except mongoengine.errors.DoesNotExist:
|
|
266
|
-
errors[reference["repr"]] += 1
|
|
267
|
-
elif reference['type'] == 'embed':
|
|
268
|
-
p1, p2 = reference['name'].split('__')
|
|
269
|
-
sub = getattr(obj, p1)
|
|
270
|
-
try:
|
|
271
|
-
getattr(sub, p2)
|
|
272
|
-
except mongoengine.errors.DoesNotExist:
|
|
273
|
-
errors[reference["repr"]] += 1
|
|
274
|
-
elif reference['type'] == 'embed_list_ref':
|
|
275
|
-
p1, p2 = reference['name'].split('__')
|
|
276
|
-
sub = getattr(getattr(obj, p1), p2)
|
|
277
|
-
for obj in sub:
|
|
278
|
-
try:
|
|
279
|
-
obj.id
|
|
280
|
-
except mongoengine.errors.DoesNotExist:
|
|
281
|
-
errors[reference["repr"]] += 1
|
|
282
|
-
else:
|
|
283
|
-
print(f'Unknown ref type {reference["type"]}')
|
|
284
|
-
print('Errors:', errors[reference["repr"]])
|
|
285
|
-
except mongoengine.errors.FieldDoesNotExist as e:
|
|
286
|
-
print('[ERROR]', e)
|
|
287
|
-
|
|
288
|
-
print(f'\n Total errors: {sum(errors.values())}')
|
|
252
|
+
total = 0
|
|
253
|
+
for model, model_references in groupby(references, lambda i: i["model"]):
|
|
254
|
+
model_references = list(model_references)
|
|
255
|
+
count = model.objects.count()
|
|
256
|
+
print(f'- doing {count} {model.__name__}…')
|
|
257
|
+
errors[model] = {}
|
|
258
|
+
|
|
259
|
+
qs = model.objects().no_cache().all()
|
|
260
|
+
with click.progressbar(qs, length=count) as models:
|
|
261
|
+
for obj in models:
|
|
262
|
+
for reference in model_references:
|
|
263
|
+
key = f'\t- {reference["repr"]}({reference["destination"]}) — {reference["type"]}…'
|
|
264
|
+
if key not in errors[model]:
|
|
265
|
+
errors[model][key] = 0
|
|
289
266
|
|
|
267
|
+
try:
|
|
268
|
+
if reference['type'] == 'direct':
|
|
269
|
+
try:
|
|
270
|
+
_ = getattr(obj, reference['name'])
|
|
271
|
+
except mongoengine.errors.DoesNotExist:
|
|
272
|
+
errors[model][key] += 1
|
|
273
|
+
print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for `{reference["name"]}`')
|
|
274
|
+
elif reference['type'] == 'list':
|
|
275
|
+
attr_list = getattr(obj, reference['name'], [])
|
|
276
|
+
for i, sub in enumerate(attr_list):
|
|
277
|
+
# If it's still an instance of DBRef it means that it failed to
|
|
278
|
+
# dereference the ID.
|
|
279
|
+
if isinstance(sub, DBRef):
|
|
280
|
+
errors[model][key] += 1
|
|
281
|
+
print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {reference["name"]}[{i}]')
|
|
282
|
+
elif reference['type'] == 'embed_list':
|
|
283
|
+
p1, p2 = reference['name'].split('__')
|
|
284
|
+
attr_list = getattr(obj, p1, [])
|
|
285
|
+
for i, sub in enumerate(attr_list):
|
|
286
|
+
try:
|
|
287
|
+
getattr(sub, p2)
|
|
288
|
+
except mongoengine.errors.DoesNotExist:
|
|
289
|
+
errors[model][key] += 1
|
|
290
|
+
print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {p1}[{i}].{p2}')
|
|
291
|
+
elif reference['type'] == 'embed':
|
|
292
|
+
p1, p2 = reference['name'].split('__')
|
|
293
|
+
sub = getattr(obj, p1)
|
|
294
|
+
if sub is None: continue
|
|
295
|
+
try:
|
|
296
|
+
getattr(sub, p2)
|
|
297
|
+
except mongoengine.errors.DoesNotExist:
|
|
298
|
+
errors[model][key] += 1
|
|
299
|
+
print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {p1}.{p2}')
|
|
300
|
+
elif reference['type'] == 'embed_list_ref':
|
|
301
|
+
p1, p2 = reference['name'].split('__')
|
|
302
|
+
a = getattr(obj, p1)
|
|
303
|
+
if a is None: continue
|
|
304
|
+
sub = getattr(a, p2, [])
|
|
305
|
+
for i, child in enumerate(sub):
|
|
306
|
+
# If it's still an instance of DBRef it means that it failed to
|
|
307
|
+
# dereference the ID.
|
|
308
|
+
if isinstance(child, DBRef):
|
|
309
|
+
errors[model][key] += 1
|
|
310
|
+
print_and_save(f'\t{model.__name__}#{obj.id} have a broken reference for {p1}.{p2}[{i}]')
|
|
311
|
+
else:
|
|
312
|
+
print_and_save(f'Unknown ref type {reference["type"]}')
|
|
313
|
+
except mongoengine.errors.FieldDoesNotExist as e:
|
|
314
|
+
print_and_save(f'[ERROR for {model.__name__} {obj.id}] {traceback.format_exc()}')
|
|
315
|
+
|
|
316
|
+
for key, nb_errors in errors[model].items():
|
|
317
|
+
print(f'{key}: {nb_errors}')
|
|
318
|
+
total += nb_errors
|
|
319
|
+
|
|
320
|
+
print(f'\n Total errors: {total}')
|
|
321
|
+
|
|
322
|
+
if total > 0:
|
|
323
|
+
try:
|
|
324
|
+
import sentry_sdk
|
|
325
|
+
with sentry_sdk.push_scope() as scope:
|
|
326
|
+
scope.set_extra("errors", Log.errors)
|
|
327
|
+
sentry_sdk.capture_message(f"{total} integrity errors", "fatal")
|
|
328
|
+
except ImportError:
|
|
329
|
+
print("`sentry_sdk` not installed. The errors weren't reported")
|
|
290
330
|
|
|
291
331
|
@grp.command()
|
|
292
332
|
@click.option('--models', multiple=True, default=[], help='Model(s) to check')
|
udata/db/__init__.py
ADDED
|
File without changes
|