def _import_fact(data, dry_run=False): db = default_storage() assert data.id if HamsterFact.objects(db).where(x_hamster_id=int(data.id)).count(): return False prepared = _prepare_data(data) fact = HamsterFact(**prepared) if not dry_run: fact.save(db) print 'ADD', fact return fact
def update_facts(args): """Updates all facts previously imported from Hamster. Please note that this will only work for activity and category titles. Hamster does update records when they are changed. However, it *replaces* facts instead of updating them when other fields change their values, e.g. description or tags. """ imported = HamsterFact.objects(db).order_by('date_time') start_date = imported[0].date_time if imported else datetime.date(1980,1,1) print('Updating all facts since {0}'.format(start_date)) if args.dry_run: print('(dry run, no data will be actually updated.)') seen_cnt = updated_cnt = 0 storage = hamster.client.Storage() for data in storage.get_facts(start_date, datetime.date.today()): updated = _update_fact(data, dry_run=args.dry_run) if updated: updated_cnt += 1 seen_cnt += 1 print('Updated {updated_cnt} facts of {seen_cnt}.'.format(**locals())) if args.dry_run: print('(None was actually saved in dry run mode.)')
def import_facts(args): """Imports all available facts from Hamster. Checks uniqueness.""" db = default_storage() if args.date: start_date = datetime.datetime.strptime(args.date, '%Y-%m-%d').date() else: imported = HamsterFact.objects(db).order_by('date_time', reverse=True) if imported: start_date = imported[0].date_time else: start_date = datetime.date(1980,1,1) print('Importing all facts since {0}'.format(start_date)) if args.dry_run: print('(dry run, no data will be actually saved.)') imported_cnt = 0 storage = hamster.client.Storage() for data in storage.get_facts(start_date, datetime.date.today()): saved = _import_fact(data, dry_run=args.dry_run) if saved: imported_cnt += 1 print('Imported {imported_cnt} facts.'.format(**locals())) if args.dry_run: print('(None was actually saved in dry run mode.)')
def _update_fact(data, dry_run=False): db = default_storage() facts = HamsterFact.objects(db).where(x_hamster_id=int(data['id'])) if not facts: print 'no fact with id', repr(data['id']) return False assert 1 == len(facts) fact = facts[0] prepared = _prepare_data(data) if prepared['tags'] == []: prepared['tags'] = None # this is how the schema works for key in prepared: old_value = fact[key] if isinstance(old_value, datetime.datetime): old_value = pytz.utc.localize(old_value) if prepared[key] != old_value: print '---', fact print 'NOTEQ {0}: {1} vs. {2}'.format( key, repr(prepared[key]), repr(fact[key])) break #print 'EQ:', repr(prepared[key]), 'vs.', repr(fact[key]) else: #print 'SAME', fact return False # same data fact.update(**prepared) if not dry_run: fact.save() return fact
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.)')