diff --git a/.coveragerc b/.coveragerc index 29245f10..744c334d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,15 +1,3 @@ -[run] -include = - ./* -omit = - *tests* - *migrations* - *cvkbrno* - */py2/* - */venv/* - *__init__* [report] -exclude_lines = - pragma: no cover - if __name__ == .__main__.: - +show_missing = True +omit = py39/* \ No newline at end of file diff --git a/rowers/integrations/c2.py b/rowers/integrations/c2.py index fd8e0d50..b7fee546 100644 --- a/rowers/integrations/c2.py +++ b/rowers/integrations/c2.py @@ -1,5 +1,5 @@ -from .integrations import SyncIntegration, NoTokenError -from rowers.models import User, Rower, Workout, TombStone, SyncRecord +from .integrations import SyncIntegration, NoTokenError, create_or_update_syncrecord, get_known_ids +from rowers.models import User, Rower, Workout, TombStone from django.db.utils import IntegrityError from rowingdata import rowingdata @@ -360,15 +360,9 @@ class C2Integration(SyncIntegration): def get_workout(self, id, *args, **kwargs): _ = self.open() + r = self.rower - record = SyncRecord( - rower = self.rower, - c2id = id, - ) - try: - record.save() - except IntegrityError: - return 0 + record = create_or_update_syncrecord(r, None, c2id=id) _ = myqueue(queuehigh, handle_c2_getworkout, @@ -428,9 +422,7 @@ class C2Integration(SyncIntegration): workouts = [] c2ids = [item['id'] for item in res.json()['data']] - knownc2ids = uniqify([ - record.c2id for record in SyncRecord.objects.filter(rower=r) - ]) + knownc2ids = get_known_ids(r, 'c2id') for item in res.json()['data']: d = item['distance'] diff --git a/rowers/integrations/integrations.py b/rowers/integrations/integrations.py index 87aa1661..0cfaf0ad 100644 --- a/rowers/integrations/integrations.py +++ b/rowers/integrations/integrations.py @@ -1,6 +1,6 @@ from abc import ABCMeta, ABC, abstractmethod from importlib import import_module -from rowers.models import Rower, User +from rowers.models import Rower, User, create_or_update_syncrecord, get_known_ids from rowers.utils import NoTokenError,dologging import requests diff --git a/rowers/integrations/nk.py b/rowers/integrations/nk.py index 3c95729c..d109b415 100644 --- a/rowers/integrations/nk.py +++ b/rowers/integrations/nk.py @@ -1,5 +1,5 @@ -from .integrations import SyncIntegration, NoTokenError -from rowers.models import User, Rower, Workout, TombStone, SyncRecord +from .integrations import SyncIntegration, NoTokenError, create_or_update_syncrecord, get_known_ids +from rowers.models import User, Rower, Workout, TombStone from django.db.utils import IntegrityError from rowers import mytypes @@ -91,14 +91,7 @@ class NKIntegration(SyncIntegration): _ = self.open() r = self.rower - record = SyncRecord( - rower = r, - nkid = id, - ) - try: - record.save() - except IntegrityError: - return 0 + record = create_or_update_syncrecord(r, None, nkid=id) before = kwargs.get('before',0) after = kwargs.get('after',0) @@ -192,9 +185,7 @@ class NKIntegration(SyncIntegration): # get NK IDs nkids = [item['id'] for item in jsondata] - knownnkids = uniqify([ - record.nkid for record in SyncRecord.objects.filter(rower=r) - ]) + knownnkids = get_known_ids(r, 'nkid') workouts = [] diff --git a/rowers/integrations/rp3.py b/rowers/integrations/rp3.py index fba8b4e2..6e5b3467 100644 --- a/rowers/integrations/rp3.py +++ b/rowers/integrations/rp3.py @@ -1,4 +1,4 @@ -from .integrations import SyncIntegration, NoTokenError +from .integrations import SyncIntegration, NoTokenError, create_or_update_syncrecord, get_known_ids from rowers.models import User, Rower, Workout, TombStone from rowers.tasks import handle_rp3_async_workout @@ -100,6 +100,8 @@ class RP3Integration(SyncIntegration): startdatetime = kwargs.get('startdatetime', None) if not startdatetime: startdatetime = str(timezone.now()) + + record = create_or_update_syncrecord(self.rower, None, rp3id=id) auth_token = self.open() _ = myqueue( @@ -172,9 +174,7 @@ class RP3Integration(SyncIntegration): workouts_list = pd.json_normalize(workouts_json['data']['workouts']) - knownrp3ids = uniqify([ - w.uploadedtorp3 for w in Workout.objects.filter(user=r) - ]) + knownrp3ids = get_known_ids(r, 'rp3id') workouts = [] diff --git a/rowers/integrations/sporttracks.py b/rowers/integrations/sporttracks.py index 9b4de159..d004b4f4 100644 --- a/rowers/integrations/sporttracks.py +++ b/rowers/integrations/sporttracks.py @@ -1,4 +1,4 @@ -from .integrations import SyncIntegration, NoTokenError +from .integrations import SyncIntegration, NoTokenError, create_or_update_syncrecord, get_known_ids from rowers.models import User, Rower, Workout, TombStone from rowingdata import rowingdata @@ -238,9 +238,7 @@ class SportTracksIntegration(SyncIntegration): stids = [int(getidfromuri(item['uri'])) for item in workouts_json['items']] - knownstids = uniqify([ - w.uploadedtosporttracks for w in Workout.objects.filter(user=r) - ]) + knownstids = get_known_ids(r, 'sporttracksid') newids = [stid for stid in stids if stid not in knownstids] for sporttracksid in newids: id = self.get_workout(sporttracksid) @@ -254,6 +252,7 @@ class SportTracksIntegration(SyncIntegration): r = self.rower + record = create_or_update_syncrecord(r, None, sporttracksid=id) job = myqueue( queue, @@ -289,9 +288,8 @@ class SportTracksIntegration(SyncIntegration): workouts = [] - knownstids = uniqify([ - w.uploadedtosporttracks for w in Workout.objects.filter(user=r) - ]) + knownstids = get_known_ids(r, 'sporttracksid') + for item in workouts_json['items']: d = int(float(item['total_distance'])) i = int(getidfromuri(item['uri'])) diff --git a/rowers/integrations/strava.py b/rowers/integrations/strava.py index 6f99af05..068ff07d 100644 --- a/rowers/integrations/strava.py +++ b/rowers/integrations/strava.py @@ -1,4 +1,4 @@ -from .integrations import SyncIntegration, NoTokenError +from .integrations import SyncIntegration, NoTokenError, create_or_update_syncrecord, get_known_ids from rowers.models import User, Rower, Workout, TombStone from rowingdata import rowingdata @@ -212,6 +212,8 @@ class StravaIntegration(SyncIntegration): except NoTokenError("Strava error"): return 0 + record = create_or_update_syncrecord(self.rower, None, stravaid=id) + csvfilename = 'media/{code}_{id}.csv'.format( code=uuid4().hex[:16], id=id) job = myqueue(queue, @@ -279,9 +281,7 @@ class StravaIntegration(SyncIntegration): w.uploadedtostrava = int(stravaid) w.save() - knownstravaids = uniqify([ - w.uploadedtostrava for w in Workout.objects.filter(user=self.rower) - ]) + knownstravaids = get_known_ids(self.rower,'stravaid') for item in res.json(): d = int(float(item['distance'])) diff --git a/rowers/models.py b/rowers/models.py index bacd03db..4d66ab55 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -5,7 +5,7 @@ from rowers.courseutils import coordinate_in_path from rowers.utils import ( # workflowleftpanel, workflowmiddlepanel, defaultleft, defaultmiddle, landingpages, landingpages2, - steps_read_fit, steps_write_fit, ps_dict_order + steps_read_fit, steps_write_fit, ps_dict_order, uniqify ) from rowers.metrics import axlabels from rowers.utils import geo_distance @@ -3625,19 +3625,36 @@ class SyncRecord(models.Model): nkid = models.BigIntegerField(unique=True,null=True,default=None) c2id = models.BigIntegerField(unique=True,null=True,default=None) tpid = models.BigIntegerField(unique=True,null=True,default=None) + rp3id = models.BigIntegerField(unique=True,null=True,default=None) def save(self, *args, **kwargs): if self.workout: self.rower = self.workout.user return super(SyncRecord, self).save(*args, **kwargs) + + def __str__(self): + str = 'SyncRecord {i} {r} {w} '.format( + i = self.id, + r = self.rower, + w = self.workout, + ) + + str2 = '' + + for field in ['stravaid', 'sporttracksid', 'nkid', 'c2id', 'tpid']: + value = getattr(self, field, None) + if value is not None: + str2 += '{w}: {v},'.format( + w = field, + v = value + ) + + if str2: + str = str+'('+str2+')' + + return str def create_or_update_syncrecord(rower, workout, **kwargs): - records = SyncRecord.objects.filter(workout=workout,rower=rower) - if records.count(): - record = records[0] - else: - record = SyncRecord(workout=workout, rower=rower) - try: kwargs.pop('rower') except KeyError: @@ -3648,6 +3665,26 @@ def create_or_update_syncrecord(rower, workout, **kwargs): except KeyError: pass + if workout: + records = SyncRecord.objects.filter(workout=workout,rower=rower) + if records.count(): + record = records[0] + else: + records = SyncRecord.objects.filter(**kwargs,rower=rower) + if records.count(): + record = records[0] + record.workout = workout + else: + record = SyncRecord(rower=rower, workout=workout) + + else: # not workout + records = SyncRecord.objects.filter(**kwargs, rower=rower) + if records.count(): + record = records[0] + else: + record = SyncRecord(rower=rower) + + for field in record._meta.fields: value = kwargs.get(field.name, None) if value: @@ -3660,7 +3697,12 @@ def create_or_update_syncrecord(rower, workout, **kwargs): return record +def get_known_ids(rower, field_name): + knownids = uniqify( + getattr(record, field_name, None) for record in SyncRecord.objects.filter(rower=rower) + ) + return knownids diff --git a/rowers/tasks.py b/rowers/tasks.py index b7394de6..e34d100e 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -405,6 +405,7 @@ def check_tp_workout_id(workout, location, attempts=5, debug=False, **kwargs): if status == 'Success': tpid = response.json()['WorkoutIds'][0] workout.uploadedtotp = tpid + record = create_or_update_syncrecord(workout.user, workout, tpid=tpid) workout.save() return 1 @@ -432,6 +433,7 @@ def handle_workout_tp_upload(w, thetoken, tcxfilename, debug=False, **kwargs): return 0 w.uploadedtotp = res + record = create_or_update_syncrecord(w.user, w, tpid=tpid) tpid = res w.save() os.remove(tcxfilename) @@ -729,7 +731,7 @@ def handle_sporttracks_sync(workoutid, url, headers, data, debug=False, **kwargs workout = Workout.objects.get(id=workoutid) workout.uploadedtosporttracks = id workout.save() - + record = create_or_update_syncrecord(workout.user, workout, sporttracksid=id) return 1 @@ -798,6 +800,7 @@ def handle_strava_sync(stravatoken, workout.uploadedtostrava = res.id workout.save() + record = create_or_update_syncrecord(workout.user, workout, stravaid=res.id) try: act = client.update_activity(res.id, activity_type=activity_type, description=description, device_name='Rowsandall.com') diff --git a/rowers/tests/testdata/testdata.tcx.gz b/rowers/tests/testdata/testdata.tcx.gz index f59a6ec8..254504ee 100644 Binary files a/rowers/tests/testdata/testdata.tcx.gz and b/rowers/tests/testdata/testdata.tcx.gz differ diff --git a/rowers/uploads.py b/rowers/uploads.py index 960a4e0d..15210848 100644 --- a/rowers/uploads.py +++ b/rowers/uploads.py @@ -142,6 +142,7 @@ def do_sync(w, options, quick=False): # upload_to_strava = False do_strava_export = False w.save() + record = create_or_update_syncrecord(w.user, w, {stravaid:options['stravaid']}) except KeyError: pass @@ -192,6 +193,7 @@ def do_sync(w, options, quick=False): if options['rp3id'] != 0 and options['rp3id'] != '': # pragma: no cover w.uploadedtorp3 = options['rp3id'] w.save() + record = create_or_update_syncrecord(w.user, w, {rp3id:options['rp3id']}) except KeyError: pass @@ -242,6 +244,7 @@ def do_sync(w, options, quick=False): w.uploadedtosporttracks = sporttracksid w.save() do_st_export = False + record = create_or_update_syncrecord(w.user, w, {'sporttracksid':sporttracksid}) try: # pragma: no cover upload_to_st = options['upload_to_SportTracks'] or do_st_export do_st_export = upload_to_st