def purge_facts(args): """Deletes all facts previously imported from Hamster and not currently present there. WARNING: the command does *NOT* check if the "orphaned" facts are in the scope of given Hamster storage. That is, all facts gathered from an older storage will be DROPPED. This should be fixed later. """ db = default_storage() imported = HamsterFact.objects(db).order_by('date_time') storage = hamster.client.Storage() seen_cnt = deleted_cnt = 0 print('Purging orphaned facts...') if args.dry_run: print('(dry run, no data will be actually updated.)') for fact in imported: fact_id = int(fact.x_hamster_id) try: storage.get_fact(fact_id) except dbus.exceptions.DBusException: # fact is no more in Hamster # XXX TODO: check if the Hamster storage is not newer than known # facts!!! if it is, we'll lose older data print 'DEL', fact, fact.get_duration() # check if the fact can be safely deleted. # FIXME this is a quick fix for plan references. We should instead # check for *all* attributes (via Document instance) and copy them # to the newer fact; if the newer fact cannot be found (e.g. # date/time were updated), then just leave it as is. # This should *not* apply to the created/updated tmestamps. plan_pk = fact.get('plan') plan = Plan.object(db, plan_pk) if plan_pk else None if plan: # try finding exact match by date/time (exact replacement) same_facts = imported.where(date_time=fact.date_time) same_facts = [f for f in same_facts if f.pk != fact.pk] replacement = same_facts[0] if same_facts else None if replacement: print(' Copying plan to fact {0}'.format(replacement.pk)) assert not replacement.get('plan'), ( 'the replacing fact must be freshly imported') d = Document.object(db, replacement.pk) d['plan'] = plan.pk if not args.dry_run: d.save() fact.delete() deleted_cnt += 1 else: print(' Not deleting: fact references plan {0}'.format(plan)) else: if not args.dry_run: fact.delete() deleted_cnt += 1 seen_cnt += 1 print('Deleted {deleted_cnt} facts of {seen_cnt}.'.format(**locals())) if args.dry_run: print('(None was actually deleted in dry run mode.)')
def report(request): query = Document.objects(default_storage()) # TODO: only docs registered with admin? form = CastForm(request.form) factors = [] pivot_factors = [] aggregate = Count() if form.validate(): factors = form.data.get('factors') factors = factors.split(' ') if factors else [] pivot_factors = form.data.get('pivot_factors') pivot_factors = pivot_factors.split(' ') if pivot_factors else [] aggregate = form.get_aggregate() or Count() table = dark.cast(query, factors, pivot_factors, aggregate) return {'form': form, 'table': table}