Private
Public Access
1
0

Merge branch 'release/v16.0.4'

This commit is contained in:
Sander Roosendaal
2021-04-21 08:42:52 +02:00
25 changed files with 1740 additions and 731 deletions
+1 -1
View File
@@ -902,7 +902,7 @@ def make_authorization_url(request):
return HttpResponseRedirect(url)
# Get workout from C2 ID
def get_workout(user,c2id):
def get_workout(user,c2id,do_async=False):
r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None):
s = "Token doesn't exist. Need to authorize"
+1
View File
@@ -93,6 +93,7 @@ def imports_open(user,oauth_data):
except (TypeError,AttributeError,KeyError):
tokenexpirydate = None
if (token == '') or (token is None):
s = "Token doesn't exist. Need to authorize"
raise NoTokenError("User has no token")
+175 -175
View File
File diff suppressed because it is too large Load Diff
+22 -2
View File
@@ -247,7 +247,7 @@ def get_nk_workout_list(user,fake=False,after=0,before=0):
#
def get_workout(user,nkid):
def get_workout(user,nkid,do_async=False):
r = Rower.objects.get(user=user)
if (r.nktoken == '') or (r.nktoken is None):
s = "Token doesn't exist. Need to authorize"
@@ -260,6 +260,27 @@ def get_workout(user,nkid):
'sessionIds': nkid,
}
if do_async:
res = get_nk_workout_list(r.user)
if res.status_code != 200:
return 0
alldata = {}
for item in res.json():
alldata[item['id']] = item
res = myqueue(
queuehigh,
handle_nk_async_workout,
alldata,
r.user.id,
r.nktoken,
nkid,
0,
r.defaulttimezone,
)
return {},pd.DataFrame()
authorizationstring = str('Bearer ' + r.nktoken)
headers = {'Authorization': authorizationstring,
@@ -292,7 +313,6 @@ def get_workout(user,nkid):
before = before+timedelta(days=1)
before = str(int(before.timestamp())*1000)
after = str(int(after.timestamp())*1000)
print(after)
url = NK_API_LOCATION+"api/v1/sessions/"
+3 -41
View File
@@ -50,7 +50,7 @@ def to_time(milliseconds):
def rdata(file,rower=rrower()):
try:
res = rrdata(csvfile=file,rower=rower)
except (IOError, IndexError, EOFError,FileNotFoundError):
except (IOError, IndexError, EOFError,FileNotFoundError): # pragma: no cover
try:
res = rrdata(csvfile=file+'.gz',rower=rower)
except (IOError, IndexError, EOFError,FileNotFoundError):
@@ -85,16 +85,7 @@ from rowers.tasks import (
)
from rowers.utils import totaltime_sec_to_string
# nog niet af
def ps_dict_get_durationdistance(d):
sdict = ps_dict_order(d)
return sdict
def ps_dict_get_description(d,short=False):
def ps_dict_get_description(d,short=False): # pragma: no cover
sdict,totalmeters,totalseconds = ps_dict_order(d,short=short)
s = ''
for item in sdict:
@@ -115,35 +106,6 @@ def ps_dict_get_description_html(d,short=False):
return s
class FitWorkoutSteps(object):
def __init__(self,json_string,name='',sport='Custom'):
self.json = json_string
self.steps = json.loads(json_string)
self.name = name
self.sport = sport
# message 0 is file id
# message 1 must be workout description
def to_json(self):
d = self.get_dict()
return json.dumps(d)
def get_dict(self):
return self.steps
def get_description(self):
s = ''
for step in self.steps:
s += step_to_string(step)
s += '\n'
return s
def checkscores(r,macrocycles):
for m in macrocycles:
createmesofillers(m)
@@ -246,7 +208,7 @@ def get_execution_report(rower,startdate,enddate,plan=None):
mesos = TrainingMesoCycle.objects.filter(plan__in=macros).order_by("startdate")
micros = TrainingMicroCycle.objects.filter(plan__in=mesos).order_by("startdate")
micros = micros.exclude(enddate__lte=startdate).exclude(startdate__gte=enddate)
else:
else: # pragma: no cover
plans = TrainingPlan.objects.filter(startdate__lte=startdate,enddate__gte=startdate)
plans2 = TrainingPlan.objects.filter(enddate__lte=enddate,startdate__lte=enddate)
plans = plans | plans2
+2
View File
@@ -114,12 +114,14 @@ def get_rp3_workout_list(user):
executed_at
}
}"""
response = requests.post(
url=graphql_url,
headers=headers,
json={'query': get_workouts_list}
)
return response
def get_rp3_workouts(rower,do_async=True):
+1 -1
View File
@@ -92,7 +92,7 @@ def get_runkeeper_workout_list(user):
return s
# Get workout summary data by Runkeeper ID
def get_workout(user,runkeeperid):
def get_workout(user,runkeeperid,do_async=False):
r = Rower.objects.get(user=user)
if (r.runkeepertoken == '') or (r.runkeepertoken is None):
return custom_exception_handler(401,s)
+1 -1
View File
@@ -97,7 +97,7 @@ def get_sporttracks_workout_list(user):
return s
# Get workout summary data by SportTracks ID
def get_workout(user,sporttracksid):
def get_workout(user,sporttracksid,do_async=False):
r = Rower.objects.get(user=user)
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
return custom_exception_handler(401,s)
+2 -2
View File
@@ -382,7 +382,7 @@ def async_get_workout(user,stravaid):
return job
# Get a Strava workout summary data and stroke data by ID
def get_workout(user,stravaid):
def get_workout(user,stravaid,do_async=False):
try:
thetoken = strava_open(user)
except NoTokenError:
@@ -773,7 +773,7 @@ def workout_strava_upload(user,w, quick=False,asynchron=True):
activity_type = mytypes.stravamapping[w.workouttype]
except KeyError:
activity_type = 'Rowing'
with open(tcxfile,'rb') as f:
res,mes = handle_stravaexport(
f,w.name,
+33 -24
View File
@@ -2834,7 +2834,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts,de
)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
have_link = True
workout_download_details = pd.json_normalize(response.json()['data']['download'])
@@ -2845,22 +2845,28 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts,de
counter += 1
if counter>max_attempts:
if counter>max_attempts: # pragma: no cover
have_link = True
time.sleep(waittime)
if download_url == '':
if download_url == '': # pragma: no cover
return 0
filename = 'media/RP3Import_'+str(rp3id)+'.csv'
res = requests.get(download_url,headers=headers)
if not startdatetime:
if not startdatetime: # pragma: no cover
startdatetime = str(timezone.now())
if res.status_code != 200:
try:
startdatetime = str(startdatetime)
except: # pragma: no cover
pass
if res.status_code != 200: # pragma: no cover
return 0
@@ -2883,7 +2889,7 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts,de
response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
return 0
workoutid = response.json()['id']
@@ -2894,7 +2900,10 @@ def handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts,de
def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone,debug=False,**kwargs):
time.sleep(delaysec)
data = alldata[nkid]
try:
data = alldata[nkid]
except KeyError: # pragma: no cover
data = alldata[int(nkid)]
params = {
'sessionIds': nkid,
@@ -2992,7 +3001,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
try:
t = data['comments'].split('\n', 1)[0]
title += t[:40]
except:
except: # pragma: no cover
title = ''
weightcategory = 'hwt'
@@ -3024,7 +3033,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
try:
notes = data['comments']
name = notes[:40]
except (KeyError,TypeError):
except (KeyError,TypeError): # pragma: no cover
notes = 'C2 Import Workout from {startdatetime}'.format(startdatetime=startdatetime)
name = notes
@@ -3035,10 +3044,10 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
try:
s = requests.get(url,headers=headers)
except ConnectionError:
except ConnectionError: # pragma: no cover
return 0
if s.status_code != 200:
if s.status_code != 200: # pragma: no cover
return 0
strokedata = pd.DataFrame.from_dict(s.json()['data'])
@@ -3056,7 +3065,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
nr_rows = len(unixtime)
try:
try: # pragma: no cover
latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon']
except:
@@ -3066,19 +3075,19 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
try:
strokelength = strokedata.loc[:,'strokelength']
except:
except: # pragma: no cover
strokelength = np.zeros(nr_rows)
dist2 = 0.1*strokedata.loc[:,'d']
try:
spm = strokedata.loc[:,'spm']
except KeyError:
except KeyError: # pragma: no cover
spm = 0*dist2
try:
hr = strokedata.loc[:,'hr']
except KeyError:
except KeyError: # pragma: no cover
hr = 0*spm
pace = strokedata.loc[:,'p']/10.
@@ -3087,7 +3096,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
velo = 500./pace
power = 2.8*velo**3
if workouttype == 'bike':
if workouttype == 'bike': # pragma: no cover
velo = 1000./pace
df = pd.DataFrame({'TimeStamp (sec)':unixtime,
@@ -3133,12 +3142,12 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
return 0
workoutid = response.json()['id']
if debug:
if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
@@ -3149,7 +3158,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
tdata = result.fetchall()
if tdata:
if tdata: # pragma: no cover
newc2id = tdata[0][0]
conn.close()
@@ -3176,16 +3185,16 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
# summary
if 'workout' in data:
if 'splits' in data['workout']:
if 'splits' in data['workout']: # pragma: no cover
splitdata = data['workout']['splits']
elif 'intervals' in data['workout']:
elif 'intervals' in data['workout']: # pragma: no cover
splitdata = data['workout']['intervals']
else:
else: # pragma: no cover
splitdata = False
else:
splitdata = False
if splitdata:
if splitdata: # pragma: no cover
summary,sa,results = summaryfromsplitdata(splitdata,data,csvfilename,workouttype=workouttype)
query = "UPDATE `rowers_workout` SET `summary` = '%s' WHERE `id` = %s" % (summary, workoutid)
@@ -3431,7 +3440,7 @@ def fetch_strava_workout(stravatoken,oauth_data,stravaid,csvfilename,userid,debu
try:
power = strokedata.loc[:,'power']
except KeyError:
except KeyError: # pragma: no cover
power = 2.8*velo**3
#if power.std() == 0 and power.mean() == 0:
+1 -1
View File
@@ -33,7 +33,7 @@
{% for workout in workouts %}
<tr>
<td>
<a href="/rowers/workout/nkimport/{{ workout|lookup:'id' }}/">Import</a></td>
<a href="/rowers/workout/nkimport/{{ workout|lookup:'id' }}/async/">Import</a></td>
<td>{{ workout|lookuplong:'name' }}</td>
<td class="block" style="width:auto">{{ workout|lookuplong:'starttime' }}</td>
<td>{{ workout|lookup:'duration' }} </td>
+57 -1
View File
@@ -98,7 +98,6 @@ def mocked_myqueue(*args, **kwargs):
return Job()
def mock_c2open(*args, **kwargs):
print('mock')
return('aap')
def mocked_session(*args, **kwargs):
@@ -123,6 +122,16 @@ def mocked_session(*args, **kwargs):
def json(self):
return self.json_data
class MockContentResponse:
def __init__(self,filename,status_code):
with open(filename,'rb') as f:
s = f.read()
self.content = s
self.status_code = status_code
self.ok = True
return MockEngine()
def mocked_sqlalchemy(*args, **kwargs):
@@ -697,6 +706,11 @@ def mocked_requests(*args, **kwargs):
with open('rowers/tests/testdata/nk_list.json','r') as infile:
nkworkoutlist = json.load(infile)
with open('rowers/tests/testdata/rp3_list.json','r') as infile:
rp3workoutlist = json.load(infile)
rp3linkready = {'data': {'download': {'id': 591621, 'status': 'ready', 'link': 'https://rp3rowing-app.com/api/workouts/591621/download?type=csv'}}}
with open('rowers/tests/testdata/example-session-strokes-with-impeller-data.json','r') as infile:
nkimpellerstrokedata = json.load(infile)
@@ -781,6 +795,15 @@ def mocked_requests(*args, **kwargs):
def json(self):
return self.json_data
class MockContentResponse:
def __init__(self,filename,status_code):
with open(filename,'rb') as f:
s = f.read()
self.content = s
self.status_code = status_code
self.ok = True
class MockHeaderResponse:
def __init__(self, header_data, status_code):
@@ -832,6 +855,9 @@ def mocked_requests(*args, **kwargs):
if 'garmin' in args:
return MockOAuth1Session()
if 'url' in kwargs:
if 'rp3' in kwargs['url']:
args = [kwargs['url']]
if not args:
return MockSession()
@@ -845,6 +871,7 @@ def mocked_requests(*args, **kwargs):
uatester = re.compile('.*?mapmyfitness\.com')
tptester = re.compile('.*?trainingpeaks\.com')
nktester = re.compile('.*?nkrowlink\.com')
rp3tester = re.compile('.*?rp3rowing-app\.com')
garmintester = re.compile('.*?garmin\.com')
c2importregex = '.*?concept2.com\/api\/users\/me\/results\/\d+'
@@ -865,6 +892,8 @@ def mocked_requests(*args, **kwargs):
nkstrokesregex = '.*?nkrowlink\.com\/api\/v1\/sessions\/strokes'
nkstrokestester = re.compile(nkstrokesregex)
rp3graphregex = '.*?rp3rowing-app\.com\/graphql'
rp3graphtester = re.compile(rp3graphregex)
stravaathleteregex = '.*?strava\.com\/api\/v3\/athlete$'
stravaathletetester = re.compile(stravaathleteregex)
@@ -1052,6 +1081,33 @@ def mocked_requests(*args, **kwargs):
return MockResponse(nkimpellerworkoutlist,200)
return MockResponse(nkworkoutlist,200)
if rp3tester.match(args[0]):
if 'token' in args[0]:
json_data = {
'access_token': 'TA3n1vrNjuQJWw0TdCDHnjSmrjIPULhTlejMIWqq',
'expires_in': 604800,
'refresh_token': 'jHJhFzCfOOKB8oyiayubhLAlxaMkG3ruC1E8YxaR'
}
return MockResponse(json_data,200)
if 'api' in args[0]:
if '591621' in args[0]:
return MockContentResponse('rowers/tests/testdata/rp3content.csv',200)
if rp3graphtester.match(args[0]):
if 'json' in kwargs:
try:
query = kwargs['json']['query']
if 'download' in query:
return MockResponse(rp3linkready,200)
except KeyError:
pass
json_data = rp3workoutlist
return MockResponse(json_data,200)
if stravatester.match(args[0]):
+194 -5
View File
@@ -14,6 +14,9 @@ import rowers
from rowers import dataprep
from rowers import tasks
from rowers import c2stuff
from rowers import stravastuff
import urllib
import json
@pytest.mark.django_db
@override_settings(TESTING=True)
@@ -292,6 +295,20 @@ class C2Objects(DjangoTestCase):
res = add_workout_from_strokedata(self.u,1,data,strokedata,source='c2')
@patch('rowers.tasks.requests.get',side_effect=mocked_requests)
@patch('rowers.tasks.requests.post',side_effect=mocked_requests)
@patch('rowers.tasks.requests.session', side_effect=mocked_requests)
def test_handle_c2_get_workouts(self, mock_get, mockpost,MockSession):
with open('rowers/tests/testdata/c2workoutlist.txt','r') as infile:
c2workoutdata = json.load(infile)
alldata = {}
for item in c2workoutdata['data']:
alldata[item['id']] = item
res = tasks.handle_c2_async_workout(alldata,self.u.id,self.r.c2token,33991243,0,self.r.defaulttimezone)
self.assertEqual(res,1)
@override_settings(TESTING=True)
class C2ObjectsTokenExpired(DjangoTestCase):
def setUp(self):
@@ -447,6 +464,11 @@ class NKObjects(DjangoTestCase):
)
self.assertTrue(res>0)
@patch('rowers.nkstuff.requests.post', side_effect=mocked_requests)
def notest_nk_callback(self, mock_post):
response = self.c.get('/nk_callback?code=absdef23&scope=read',follow=True)
self.assertEqual(response.status_code, 200)
@patch('rowers.nkstuff.requests.get', side_effect=mocked_requests)
@patch('rowers.nkstuff.requests.post', side_effect=mocked_requests)
@@ -509,10 +531,9 @@ class NKObjects(DjangoTestCase):
w = Workout.objects.get(id=1)
#self.assertTrue(w.impeller)
#@pytest.mark.django_db
@override_settings(TESTING=True)
class StravaObjects(DjangoTestCase):
class RP3Objects(DjangoTestCase):
def setUp(self):
self.c = Client()
self.u = User.objects.create_user('john',
@@ -526,9 +547,9 @@ class StravaObjects(DjangoTestCase):
gdproptindate=timezone.now()
)
self.r.stravatoken = '12'
self.r.stravarefreshtoken = '123'
self.r.stravatokenexpirydate = arrow.get(datetime.datetime.now()-datetime.timedelta(days=1)).datetime
self.r.rp3token = '12'
self.r.rp3refreshtoken = '123'
self.r.rp3tokenexpirydate = arrow.get(datetime.datetime.now()-datetime.timedelta(days=1)).datetime
self.r.save()
self.c.login(username='john',password='koeinsloot')
@@ -565,6 +586,174 @@ class StravaObjects(DjangoTestCase):
csvfilename=filename
)
@patch('rowers.rp3stuff.requests.get', side_effect=mocked_requests)
@patch('rowers.rp3stuff.requests.post', side_effect=mocked_requests)
@patch('rowers.dataprep.getsmallrowdata_db', side_effect=mocked_getsmallrowdata_db)
def test_rp3_import(self, mock_get, mockpost,
mocked_getsmallrowdata_db):
response = self.c.get('/rowers/workout/rp3import/591621',follow=True)
expected_url = reverse('workout_rp3import_view')
self.assertRedirects(response,
expected_url=expected_url,
status_code=301,target_status_code=200)
self.assertEqual(response.status_code, 200)
w = Workout.objects.get(id=1)
@patch('rowers.tasks.requests.get',side_effect=mocked_requests)
@patch('rowers.tasks.requests.post',side_effect=mocked_requests)
@patch('rowers.tasks.requests.session', side_effect=mocked_requests)
def test_handle_rp3_get_workouts(self, mock_get, mockpost,MockSession):
userid = self.u.id
rp3token = 'ap'
rp3id = '591621'
startdatetime = timezone.now()-datetime.timedelta(days=30)
max_attempts = 2
res = tasks.handle_rp3_async_workout(userid,rp3token,rp3id,startdatetime,max_attempts)
self.assertEqual(res,1)
@patch('rowers.rp3stuff.requests.post', side_effect=mocked_requests)
def notest_rp3_callback(self, mock_post):
response = self.c.get('/rp3_callback?code=absdef23&scope=read',follow=True)
self.assertEqual(response.status_code, 200)
#@pytest.mark.django_db
@override_settings(TESTING=True)
class StravaObjects(DjangoTestCase):
def setUp(self):
self.c = Client()
self.u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
self.u.first_name = 'John'
self.u.last_name = 'Sander'
self.u.save()
self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
strava_auto_import=True,
strava_auto_delete=True,
)
self.r.stravatoken = '12'
self.r.stravarefreshtoken = '123'
self.r.stravatokenexpirydate = arrow.get(datetime.datetime.now()-datetime.timedelta(days=1)).datetime
self.r.strava_owner_id = 4
self.r.save()
self.c.login(username='john',password='koeinsloot')
self.nu = datetime.datetime.now()
filename = 'rowers/tests/testdata/testdata.csv'
rr = rrower(hrmax=self.r.max,hrut2=self.r.ut2,
hrut1=self.r.ut1,hrat=self.r.at,
hrtr=self.r.tr,hran=self.r.an,ftp=self.r.ftp)
row = rdata(csvfile=filename,rower=rr)
totaldist = row.df['cum_dist'].max()
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.loc[:,' ElapsedTime (sec)'].iloc[0]
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
self.w = Workout.objects.create(
name='testworkout',workouttype='water',
user=self.r,date=self.nu.strftime('%Y-%m-%d'),
starttime=workoutstarttime,
startdatetime=row.rowdatetime,
duration=duration,distance=totaldist,
csvfilename=filename,uploadedtostrava=123,
)
@patch('rowers.stravastuff.requests.post', side_effect=mocked_requests)
@patch('rowers.stravastuff.requests.get', side_effect=mocked_requests)
def test_strava_webhook(self, mock_get, mock_post):
url = reverse('strava_webhook_view')
params = {
'hub.challenge':'aap',
'hub.verify_token':stravastuff.webhookverification,
}
url2 = url+'?'+urllib.parse.urlencode(params)
response = self.c.get(url2)
self.assertEqual(response.status_code,200)
data = {
'aspect_type':'create',
'object_id': 245,
'object_type':'activity',
'owner_id': self.r.strava_owner_id,
'event_time': arrow.get(datetime.datetime.now()).timestamp(),
}
raw_data = json.dumps(data)
response = self.c.generic('POST', url, raw_data)
self.assertEqual(response.status_code,200)
data = {
'aspect_type':'update',
'updates':{
'title':faker.word(),
'type': 'Ride',
},
'object_id': 123,
'object_type':'activity',
'owner_id': self.r.strava_owner_id,
'event_time': arrow.get(datetime.datetime.now()).timestamp(),
}
raw_data = json.dumps(data)
response = self.c.generic('POST', url, raw_data)
self.assertEqual(response.status_code,200)
data = {
'aspect_type':'delete',
'object_id': 245,
'object_type':'activity',
'owner_id': self.r.strava_owner_id,
'event_time': arrow.get(datetime.datetime.now()).timestamp(),
}
raw_data = json.dumps(data)
response = self.c.generic('POST', url, raw_data)
self.assertEqual(response.status_code,200)
@patch('rowers.stravastuff.requests.post', side_effect=mocked_requests)
@patch('rowers.stravastuff.requests.get', side_effect=mocked_requests)
@patch('rowers.stravastuff.stravalib.Client',side_effect=MockStravalibClient)
def test_strava_upload(self, mock_get, mock_post,MockStravalibClient):
response = self.c.get('/rowers/workout/'+encoded1+'/stravauploadw/')
self.assertRedirects(response,
expected_url = '/rowers/workout/'+encoded1+'/edit/',
status_code=302,target_status_code=200)
self.assertEqual(response.url, '/rowers/workout/'+encoded1+'/edit/')
self.assertEqual(response.status_code, 302)
@patch('rowers.stravastuff.requests.get', side_effect=mocked_requests)
@patch('rowers.stravastuff.requests.post', side_effect=mocked_requests)
+8
View File
@@ -9,6 +9,14 @@ from .statements import *
nu = datetime.datetime.now()
from rowers.rower_rules import is_workout_user
from rowers.models import update_records
class MiscTests(TestCase):
def setUp(self):
pass
def test_c2records(self):
update_records(verbose=False)
#@pytest.mark.django_db
class WorkoutTests(TestCase):
+362 -9
View File
@@ -182,9 +182,8 @@ class TrainingPlanTest(TestCase):
# status_code=302,target_status_code=200)
@override_settings(TESTING=True)
class SessionLinkTest(TestCase):
class SessionTemplateTest(TestCase):
def setUp(self):
self.u = UserFactory()
@@ -196,6 +195,9 @@ class SessionLinkTest(TestCase):
self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
for w in self.user_workouts:
w.startdatetime = arrow.get(w.date).datetime
self.factory = RequestFactory()
self.password = faker.word()
self.u.set_password(self.password)
@@ -227,6 +229,109 @@ class SessionLinkTest(TestCase):
result = plannedsessions.add_rower_session(self.r,ps)
def tearDown(self):
for workout in self.user_workouts:
try:
os.remove(workout.csvfilename)
except (IOError, FileNotFoundError,OSError):
pass
def test_createtemplate_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('plannedsession_createtemplate_view')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
post_data = {
'comment': faker.text(),
'criterium': 'none',
'sessionsport': 'water',
'sessionmode':'time',
'sessiontype':'session',
'sessionunit':'min',
'sessionvalue': '60',
'name': faker.word(),
}
form = PlannedSessionTemplateForm(post_data)
self.assertTrue(form.is_valid())
expected_url = reverse('template_library_view')
response = self.c.post(url,post_data,follow=True)
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
templates = PlannedSession.objects.filter(is_template=True)
self.assertEqual(templates.count(),1)
t = templates[0]
t.tags.add('test')
url = reverse('template_share_view',kwargs={'id':t.id})
response = self.c.get(url,follow=True)
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
url = reverse('template_makeprivate_view',kwargs={'id':t.id})
response = self.c.get(url,follow=True)
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
url = reverse('plannedsession_templateedit_view',kwargs={'id':t.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
post_data['name'] = faker.word()
response = self.c.post(url,post_data,follow=True)
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
@override_settings(TESTING=True)
class SessionLinkTest(TestCase):
def setUp(self):
self.u = UserFactory()
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
self.factory = RequestFactory()
self.password = faker.word()
self.u.set_password(self.password)
self.u.save()
self.pss = []
for w in self.user_workouts:
startdatetime = arrow.get(w.date).datetime
startdate = (startdatetime-datetime.timedelta(days=1)).date()
enddate = (startdatetime+datetime.timedelta(days=1)).date()
preferreddate = startdatetime.date()
ps = SessionFactory(startdate=startdate,enddate=enddate,
sessiontype='session',
sessionmode = 'time',
criterium = 'none',
sessionvalue = 60,
sessionunit='min',
preferreddate=preferreddate,
manager=self.u,
)
ps.save()
self.pss.append(ps)
result = plannedsessions.add_rower_session(self.r,ps)
def tearDown(self):
for workout in self.user_workouts:
try:
@@ -241,11 +346,12 @@ class SessionLinkTest(TestCase):
w = self.user_workouts[0]
startdatetime = w.startdatetime
startdatetime = arrow.get(w.date).datetime
startdate = (startdatetime-datetime.timedelta(days=1)).date()
enddate = (startdatetime+datetime.timedelta(days=1)).date()
url = '/rowers/sessions/'
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -286,8 +392,6 @@ class SessionLinkTest(TestCase):
enddate = enddate.strftime("%Y-%m-%d"),
)
workoutdata = {}
workoutdata['initial'] = []
@@ -298,6 +402,7 @@ class SessionLinkTest(TestCase):
workoutdata['choices'] = tuple(choices)
form = PlannedSessionSelectForm(plannedsessionstuple,post_data)
self.assertTrue(form.is_valid())
@@ -1335,6 +1440,107 @@ class PlannedSessionsView(TestCase):
self.ps_trimp.save()
added = plannedsessions.add_rower_session(self.u.rower,self.ps_trimp)
added = plannedsessions.add_team_session(self.team,self.ps_trimp)
self.ps_trimp.save()
s = b"""filename: britishrowing.json
name: British Rowing Training Plan Beginner Week 1
trainingDays:
- order: 1
workouts:
- workoutName: Week 1 Session 1
steps:
- stepId: 0
wkt_step_name: Warmup
durationType: Time
durationValue: 300000
intensity: Warmup
description: ""
- stepId: 1
wkt_step_name: Intervals
durationType: Time
durationValue: 60000
intensity: Active
description: ""
- stepId: 2
wkt_step_name: Interval Rest
durationType: Time
durationValue: 60000
intensity: Rest
description: ""
- stepId: 3
wkt_step_name: Rep
durationType: RepeatUntilStepsCmplt
durationValue: 1
targetValue: 5
- stepId: 4
wkt_step_name: Cooldown
durationType: Time
durationValue: 300000
intensity: Cooldown
description: ""
sport: ""
description: ""
- order: 4
workouts:
- workoutName: Week 1 Session 2
steps:
- stepId: 0
wkt_step_name: Warmup
durationType: Time
durationValue: 300000
intensity: Warmup
description: ""
- stepId: 1
wkt_step_name: Interval
durationType: Time
durationValue: 300000
intensity: Active
description: ""
- stepId: 2
wkt_step_name: Interval Rest
durationType: Time
durationValue: 180000
intensity: Rest
description: ""
- stepId: 3
wkt_step_name: Rep
durationType: RepeatUntilStepsCmplt
durationValue: 1
targetValue: 5
- stepId: 4
wkt_step_name: Cooldown
durationType: Time
durationValue: 300000
intensity: Cooldown
description: ""
sport: ""
description: ""
duration: 7
description: ""
"""
self.file_data = {'yaml': SimpleUploadedFile('britishrowing.yml', s)}
with open('media/temp.yml','wb') as f:
f.write(s)
self.instantplan = InstantPlan(
uuid = "79b0dacf-9b49-4f33-9acf-e2e6734e22dc",
url = "https://thepeteplan.wordpress.com/beginner-training/",
name = faker.word(),
goal = faker.word(),
duration = 42,
description = faker.word(),
target = faker.word(),
hoursperweek = 3,
sessionsperweek = 3,
price = 0,
yaml = 'temp.yml',
)
self.instantplan.save()
def tearDown(self):
try:
@@ -1359,6 +1565,53 @@ class PlannedSessionsView(TestCase):
# expected_url=expected_url,
# status_code=302,target_status_code=200)
def test_teamclone_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('plannedsession_teamclone_view',kwargs={'id':self.ps_trimp.id})
today = datetime.date.today()
b = datetime.date.today()-timezone.timedelta(today.weekday())
e = b+timezone.timedelta(days=6)
expected_url = '/rowers/sessions/teamedit/5/'
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
def test_totemplate_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('plannedsession_totemplate_view',kwargs={'id':self.ps_trimp.id})
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
def test_message_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('plannedsession_message_view',kwargs={'id':self.ps_trimp.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
form_data = {
'rower':[self.r.id],
'subject':'test',
'message':'apestaart en knokroos'
}
form = VirtualRaceAthleteForm(form_data,instance=self.ps_trimp)
self.assertTrue(form.is_valid())
response = self.c.post(url,form_data,follow=True)
expected_url = reverse('plannedsession_view',kwargs={'id':self.ps_trimp.id})
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
def test_multiclone_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
@@ -1400,6 +1653,29 @@ class PlannedSessionsView(TestCase):
response = self.c.post(url,formdata,follow=True)
self.assertEqual(response.status_code,200)
def test_deletetarget_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('rower_delete_trainingtarget',kwargs={'id':self.target.id})
response = self.c.get(url)
self.assertEqual(response.status_code,302)
def test_deletetrainingplan_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('trainingplan_delete_view',kwargs={'pk':self.plan.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
form = {}
response = self.c.post(url,form)
self.assertEqual(response.status_code,302)
def test_multicreate_view(self):
login = self.c.login(username=self.u.username, password=self.password)
@@ -1441,6 +1717,7 @@ class PlannedSessionsView(TestCase):
form_data = {
'team':[self.team.id],
'members': [self.r.id],
'startdate': self.w1.startdatetime.date(),
'enddate': (self.w1.startdatetime+datetime.timedelta(days=5)).date(),
'preferreddate': self.w1.startdatetime.date(),
@@ -1466,6 +1743,25 @@ class PlannedSessionsView(TestCase):
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
pss = PlannedSession.objects.filter(name=form_data['name'],comment=form_data['comment'])
self.assertEqual(pss.count(),1)
ps = pss[0]
url = reverse('plannedsession_teamedit_view',kwargs={'id':ps.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
form_data['name'] = faker.word()
plannedsessionform = PlannedSessionForm(form_data,instance=ps)
self.assertTrue(plannedsessionform.is_valid())
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
url = reverse('remove_groupsession_view',kwargs={'id':self.ps_trimp.id})
response = self.c.get(url)
self.assertEqual(response.status_code,302)
def test_teamedit_view(self):
login = self.c.login(username=self.u.username, password=self.password)
@@ -1630,9 +1926,7 @@ class PlannedSessionsView(TestCase):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = '/rowers/sessions/{id}/edit/'.format(
id=self.ps_time.id,
)
url = reverse('plannedsession_edit_view',kwargs={'id':self.ps_time.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
@@ -1658,7 +1952,7 @@ class PlannedSessionsView(TestCase):
self.assertTrue(form.is_valid())
response = self.c.post(url,follow=True)
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
@@ -1706,3 +2000,62 @@ class PlannedSessionsView(TestCase):
response = self.c.post(url,follow=True)
self.assertEqual(response.status_code,200)
# next test should mock training plan server
def test_instantplan_view(self):
self.u.is_staff = True
self.u.save()
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('rower_select_instantplan')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
# add a plan
url = reverse('add_instantplan_view')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
form_data = {
'name': 'Test Plan',
'price': 0,
'url':'https://nos.nl',
'goal':'hard roeien',
'description':'win everything with this plan',
'duration':28,
'target':'race faster',
'hoursperweek':4,
'sessionsperweek':4,
#'yaml': {'yaml': SimpleUploadedFile('britishrowing.yml', f.read())}
}
form = InstantPlanForm(form_data,self.file_data)
if not form.is_valid():
print(form.errors)
self.assertTrue(form.is_valid())
# look at a instant plan
url = reverse('rower_view_instantplan',kwargs={'id':self.instantplan.uuid})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
form_data = {
'name':faker.word(),
'target': '',
'startdate':datetime.datetime.now().strftime('%Y-%m-%d'),
'enddate':(datetime.datetime.now()+datetime.timedelta(days=self.instantplan.duration)).strftime('%Y-%m-%d'),
'notes': faker.word(),
'datechoice':'startdate',
}
form = InstantPlanSelectForm(form_data)
self.assertTrue(form.is_valid())
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
+247
View File
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
from .statements import *
from rowers.mytypes import rowtypes
from rowers.utils import allmonths,allsundays
nu = datetime.datetime.now()
@@ -12,8 +13,11 @@ nu = datetime.datetime.now()
# interactive plots
from rowers import interactiveplots
from rowers import dataprep
from rowers import plannedsessions
from rowers.views.workoutviews import get_video_id
class OtherUnitTests(TestCase):
def test_get_video_id(self):
url1 = 'http://youtu.be/_lOT2p_FCvA'
@@ -49,6 +53,249 @@ class OtherUnitTests(TestCase):
self.assertEqual(result,expected)
class PlannedSessionTests(TestCase):
def setUp(self):
self.u = UserFactory()
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach')
self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r)
self.factory = RequestFactory()
self.password = faker.word()
self.u.set_password(self.password)
self.u.save()
self.u2 = UserFactory(username='testbasicuser')
self.r2 = Rower.objects.create(user=self.u2,
birthdate=faker.profile()['birthdate'],
gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='basic')
self.password2 = faker.word()
self.u2.set_password(self.password2)
self.u2.save()
self.team = Team.objects.create(
name = faker.word(),
notes = faker.text(),
manager = self.u,
)
self.team.save()
self.r.team.add(self.team)
self.r2.team.add(self.team)
self.r.save()
self.r2.save()
result = get_random_file(filename='rowers/tests/testdata/2019-01-13_session.csv',name='sprintervals')
self.factory = RequestFactory()
self.password = faker.word()
self.u.set_password(self.password)
self.u.save()
self.w1 = Workout.objects.create(
name='sprintervals',
notes=faker.text(),
startdatetime = result['startdatetime'],
starttime = result['starttime'],
workouttype='rower',
date=result['date'],
duration=result['duration'],
distance=result['totaldist'],
csvfilename=result['filename'],
trimp = 77,
rscore = 69,
hrtss = 43,
normp = 236,
user=self.r,
)
# plan
self.target = TrainingTarget.objects.create(
name = faker.word(),
manager = self.u.rower,
notes = faker.text()
)
self.target.rowers.add(self.u.rower)
self.target.save()
self.plan = TrainingPlan.objects.create(
manager = self.u.rower,
name = faker.word(),
status=True,
target = self.target,
startdate=timezone.now().date(),
enddate = self.target.date,
)
self.plan.rowers.add(self.u.rower)
self.plan.save()
# cycles
self.macro = TrainingMacroCycle.objects.create(
plan=self.plan,
name=faker.word(),
type='userdefined',
notes = faker.text(),
startdate = self.plan.startdate,
enddate = self.plan.enddate,
)
mesos = TrainingMesoCycle.objects.filter(plan=self.macro)
for m in mesos:
m.delete()
monthstarts = [d for d in allmonths(self.macro.startdate,self.macro.enddate)]
monthstarts.append(self.macro.enddate)
for i in range(len(monthstarts)-1):
firstday = monthstarts[i]
lastday = monthstarts[i+1]-datetime.timedelta(days=1)
if lastday < self.macro.enddate and i == len(monthstarts)-2:
lastday = self.macro.enddate
meso = TrainingMesoCycle(startdate=firstday,
enddate=lastday,
plan=self.macro,
name = '%s' % firstday.strftime("%B"),
type = 'userdefined')
meso.save()
mesos = TrainingMesoCycle.objects.filter(plan=self.macro)
for cycle in mesos:
micros = TrainingMicroCycle.objects.filter(plan=cycle)
for m in micros:
m.delete()
sundays = [s for s in allsundays(cycle.startdate,cycle.enddate)]
if sundays and sundays[-1] < cycle.enddate:
sundays = sundays+[cycle.enddate]
elif not sundays:
sundays = [cycle.enddate]
for i in range(len(sundays)):
if i==0:
monday = cycle.startdate
else:
monday = sundays[i]-datetime.timedelta(days=6)
if monday < cycle.startdate:
monday = cycle.startdate
nextsunday = sundays[i]
micro = TrainingMicroCycle(startdate=monday,
enddate=nextsunday,
plan=cycle,
name = 'Week %s' % monday.isocalendar()[1],
type='userdefined')
micro.save()
# sessions
startdatetime = self.w1.startdatetime
startdate = (startdatetime-datetime.timedelta(days=1)).date()
enddate = (startdatetime+datetime.timedelta(days=1)).date()
preferreddate = startdatetime.date()
self.startdate = startdate
self.enddate = enddate
self.ps_rscore = SessionFactory(
startdate=startdate,enddate=enddate,
sessiontype='test',
sessionmode = 'rScore',
criterium = 'none',
sessionvalue = 69,
sessionunit='None',
preferreddate=preferreddate,
manager=self.u,
)
self.ps_rscore.save()
added = plannedsessions.add_rower_session(self.u.rower,self.ps_rscore)
self.ps_dist = SessionFactory(
startdate=startdate,enddate=enddate,
sessiontype='test',
sessionmode = 'distance',
criterium = 'none',
sessionvalue = result['totaldist'],
sessionunit='m',
preferreddate=preferreddate,
manager=self.u,
)
self.ps_dist.save()
added = plannedsessions.add_rower_session(self.u.rower,self.ps_dist)
self.ps_time = SessionFactory(
startdate=startdate,enddate=enddate,
sessiontype='test',
sessionmode = 'time',
criterium = 'none',
sessionvalue = 38,
sessionunit='min',
preferreddate=preferreddate,
manager=self.u,
)
self.ps_time.save()
added = plannedsessions.add_rower_session(self.u.rower,self.ps_time)
self.ps_trimp = SessionFactory(
startdate=startdate,enddate=enddate,
sessiontype='test',
sessionmode = 'TRIMP',
criterium = 'none',
sessionvalue = 77,
sessionunit='none',
preferreddate=preferreddate,
manager=self.u,
)
self.ps_trimp.save()
added = plannedsessions.add_rower_session(self.u.rower,self.ps_trimp)
added = plannedsessions.add_team_session(self.team,self.ps_trimp)
self.ps_trimp.save()
def tearDown(self):
pass
def test_to_time(self):
calculatedTime = plannedsessions.to_time(8100000)
expectedTime = datetime.time(2,15,0,0)
def test_checkscores(self):
macrocycles = TrainingMacroCycle.objects.filter(plan=self.plan)
plannedsessions.checkscores(self.r,macrocycles)
def test_executionreport(self):
data, ok = plannedsessions.get_execution_report(self.r,self.plan.startdate,self.plan.enddate)
self.assertEqual(ok,'ok')
def test_todays_micro(self):
micro1 = plannedsessions.get_todays_micro(self.plan)
micro2 = plannedsessions.get_todays_micro(self.plan,thedate=datetime.date.today())
self.assertEqual(micro1.id,micro2.id)
class DataPrepTests(TestCase):
def setUp(self):
self.u = UserFactory()
+75
View File
@@ -0,0 +1,75 @@
filename: britishrowing.json
name: British Rowing Training Plan Beginner Week 1
trainingDays:
- order: 1
workouts:
- workoutName: Week 1 Session 1
steps:
- stepId: 0
wkt_step_name: Warmup
durationType: Time
durationValue: 300000
intensity: Warmup
description: ""
- stepId: 1
wkt_step_name: Intervals
durationType: Time
durationValue: 60000
intensity: Active
description: ""
- stepId: 2
wkt_step_name: Interval Rest
durationType: Time
durationValue: 60000
intensity: Rest
description: ""
- stepId: 3
wkt_step_name: Rep
durationType: RepeatUntilStepsCmplt
durationValue: 1
targetValue: 5
- stepId: 4
wkt_step_name: Cooldown
durationType: Time
durationValue: 300000
intensity: Cooldown
description: ""
sport: ""
description: ""
- order: 4
workouts:
- workoutName: Week 1 Session 2
steps:
- stepId: 0
wkt_step_name: Warmup
durationType: Time
durationValue: 300000
intensity: Warmup
description: ""
- stepId: 1
wkt_step_name: Interval
durationType: Time
durationValue: 300000
intensity: Active
description: ""
- stepId: 2
wkt_step_name: Interval Rest
durationType: Time
durationValue: 180000
intensity: Rest
description: ""
- stepId: 3
wkt_step_name: Rep
durationType: RepeatUntilStepsCmplt
durationValue: 1
targetValue: 5
- stepId: 4
wkt_step_name: Cooldown
durationType: Time
durationValue: 300000
intensity: Cooldown
description: ""
sport: ""
description: ""
duration: 7
description: ""
+7
View File
@@ -0,0 +1,7 @@
id,workout_interval_id,ref,stroke_number,power,avg_power,stroke_rate,time,stroke_length,distance,distance_per_stroke,estimated_500m_time,energy_per_stroke,energy_sum,pulse,work_per_pulse,peak_force,peak_force_pos,rel_peak_force_pos,drive_time,recover_time,k,curve_data,stroke_number_in_interval,avg_calculated_power
,963271,55,1,31.73,28.78,65.05,0.95,83.6,2.07,207.2,222.6,537.75,0.54,0,0,509,26.4,31.58,0.92,0,1,"1,181,327,391,410,432,449,464,479,492,503,509,509,507,502,493,482,469,461,452,441,429,416,400,381,364,345,327,312,298,283,260,228,183,135,86,40,2,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768",1,31.73
,963271,56,2,94.06,53.18,71.18,1.8,70.4,4.79,271.98,154.96,356.01,0.89,0,0,435,26.4,37.5,0.47,0.37,0.82,"29,25,83,167,283,366,401,419,413,420,431,435,425,422,405,391,385,372,366,361,342,326,312,290,275,258,232,203,162,111,68,39,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768",2,62.895
,963271,57,3,156.86,90.58,77.96,2.43,61.6,7.74,294.47,130.67,262.23,1.16,0,0,364,17.6,28.57,0.36,0.41,0.8,"44,36,113,190,293,338,342,364,328,343,352,338,343,339,336,317,309,288,268,260,249,217,203,164,136,107,76,36,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768",3,94.216666666667
,963271,58,4,182.59,122.14,79.38,3.06,57.2,10.78,304.24,124.22,208.42,1.36,0,0,318,17.6,30.77,0.32,0.44,0.81,"52,41,116,174,277,312,299,318,302,296,313,292,291,281,271,258,238,233,203,199,167,129,108,76,45,5,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768",4,116.31
,963271,59,5,185.23,101.92,88.26,4.08,41.8,13.53,274.94,123.63,92.53,1.46,0,0,203,13.2,31.58,0.23,0.45,0.8,"55,21,72,125,170,203,181,174,170,158,151,150,139,109,110,91,69,59,41,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768",5,130.094
,963271,60,6,180.11,111.58,98.39,4.68,15.4,15.97,244.35,124.79,14.35,1.47,0,0,59,6.6,42.86,0.09,0.52,0.8,"52,30,59,46,48,44,16,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768",6,138.43
1 id workout_interval_id ref stroke_number power avg_power stroke_rate time stroke_length distance distance_per_stroke estimated_500m_time energy_per_stroke energy_sum pulse work_per_pulse peak_force peak_force_pos rel_peak_force_pos drive_time recover_time k curve_data stroke_number_in_interval avg_calculated_power
2 963271 55 1 31.73 28.78 65.05 0.95 83.6 2.07 207.2 222.6 537.75 0.54 0 0 509 26.4 31.58 0.92 0 1 1,181,327,391,410,432,449,464,479,492,503,509,509,507,502,493,482,469,461,452,441,429,416,400,381,364,345,327,312,298,283,260,228,183,135,86,40,2,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768 1 31.73
3 963271 56 2 94.06 53.18 71.18 1.8 70.4 4.79 271.98 154.96 356.01 0.89 0 0 435 26.4 37.5 0.47 0.37 0.82 29,25,83,167,283,366,401,419,413,420,431,435,425,422,405,391,385,372,366,361,342,326,312,290,275,258,232,203,162,111,68,39,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768 2 62.895
4 963271 57 3 156.86 90.58 77.96 2.43 61.6 7.74 294.47 130.67 262.23 1.16 0 0 364 17.6 28.57 0.36 0.41 0.8 44,36,113,190,293,338,342,364,328,343,352,338,343,339,336,317,309,288,268,260,249,217,203,164,136,107,76,36,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768 3 94.216666666667
5 963271 58 4 182.59 122.14 79.38 3.06 57.2 10.78 304.24 124.22 208.42 1.36 0 0 318 17.6 30.77 0.32 0.44 0.81 52,41,116,174,277,312,299,318,302,296,313,292,291,281,271,258,238,233,203,199,167,129,108,76,45,5,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768 4 116.31
6 963271 59 5 185.23 101.92 88.26 4.08 41.8 13.53 274.94 123.63 92.53 1.46 0 0 203 13.2 31.58 0.23 0.45 0.8 55,21,72,125,170,203,181,174,170,158,151,150,139,109,110,91,69,59,41,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768 5 130.094
7 963271 60 6 180.11 111.58 98.39 4.68 15.4 15.97 244.35 124.79 14.35 1.47 0 0 59 6.6 42.86 0.09 0.52 0.8 52,30,59,46,48,44,16,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768 6 138.43
+75
View File
@@ -0,0 +1,75 @@
filename: britishrowing.json
name: British Rowing Training Plan Beginner Week 1
trainingDays:
- order: 1
workouts:
- workoutName: Week 1 Session 1
steps:
- stepId: 0
wkt_step_name: Warmup
durationType: Time
durationValue: 300000
intensity: Warmup
description: ""
- stepId: 1
wkt_step_name: Intervals
durationType: Time
durationValue: 60000
intensity: Active
description: ""
- stepId: 2
wkt_step_name: Interval Rest
durationType: Time
durationValue: 60000
intensity: Rest
description: ""
- stepId: 3
wkt_step_name: Rep
durationType: RepeatUntilStepsCmplt
durationValue: 1
targetValue: 5
- stepId: 4
wkt_step_name: Cooldown
durationType: Time
durationValue: 300000
intensity: Cooldown
description: ""
sport: ""
description: ""
- order: 4
workouts:
- workoutName: Week 1 Session 2
steps:
- stepId: 0
wkt_step_name: Warmup
durationType: Time
durationValue: 300000
intensity: Warmup
description: ""
- stepId: 1
wkt_step_name: Interval
durationType: Time
durationValue: 300000
intensity: Active
description: ""
- stepId: 2
wkt_step_name: Interval Rest
durationType: Time
durationValue: 180000
intensity: Rest
description: ""
- stepId: 3
wkt_step_name: Rep
durationType: RepeatUntilStepsCmplt
durationValue: 1
targetValue: 5
- stepId: 4
wkt_step_name: Cooldown
durationType: Time
durationValue: 300000
intensity: Cooldown
description: ""
sport: ""
description: ""
duration: 7
description: ""
Binary file not shown.
+1 -1
View File
@@ -70,7 +70,7 @@ def get_underarmour_workout_list(user):
return s
# Get workout summary data by Underarmour ID
def get_workout(user,underarmourid):
def get_workout(user,underarmourid,do_async=False):
r = Rower.objects.get(user=user)
if (r.underarmourtoken == '') or (r.underarmourtoken is None):
return custom_exception_handler(401,s)
+9 -4
View File
@@ -496,6 +496,7 @@ urlpatterns = [
name='workout_getrp3importview'),
re_path(r'^workout/rp3import/all/$',views.workout_getrp3workout_all,name='workout_getrp3workout_all'),
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/$',views.workout_getimportview,name='workout_getimportview'),
re_path(r'^workout/(?P<source>\w+.*)import/(?P<externalid>\d+)/async/$',views.workout_getimportview,{'do_async':True},name='workout_getimportview'),
re_path(r'^workout/stravaimport/all/$',views.workout_getstravaworkout_all,name='workout_getstravaworkout_all'),
re_path(r'^workout/stravaimport/next/$',views.workout_getstravaworkout_next,name='workout_getstravaworkout_next'),
re_path(r'^workout/sporttracksimport/$',views.workout_sporttracksimport_view,name='workout_sporttracksimport_view'),
@@ -760,16 +761,20 @@ urlpatterns = [
name='plannedsession_edit_view'),
re_path(r'^sessions/(?P<id>\d+)/templateedit/',views.plannedsession_templateedit_view,
name='plannedsession_templateedit_view'),
re_path(r'^sessions/(?P<id>\d+)/maketemplate/$',views.plannedsession_totemplate_view),
re_path(r'^sessions/(?P<id>\d+)/maketemplate/$',views.plannedsession_totemplate_view,
name='plannedsession_totemplate_view'),
re_path(r'^sessions/(?P<id>\d+)/compare/$',
views.plannedsession_compare_view,
name='plannedsession_compare_view'),
re_path(r'^sessions/(?P<id>\d+)/compare/user/(?P<userid>\d+)/$',
views.plannedsession_compare_view,
name='plannedsession_compare_view'),
re_path(r'^sessions/(?P<id>\d+)/edit/user/(?P<userid>\d+)/$',views.plannedsession_edit_view),
re_path(r'^sessions/(?P<id>\d+)/clone/user/(?P<userid>\d+)/$',views.plannedsession_clone_view),
re_path(r'^sessions/(?P<id>\d+)/clone/team/$',views.plannedsession_teamclone_view),
re_path(r'^sessions/(?P<id>\d+)/edit/user/(?P<userid>\d+)/$',views.plannedsession_edit_view,
name='plannedsession_edit_view'),
re_path(r'^sessions/(?P<id>\d+)/clone/user/(?P<userid>\d+)/$',views.plannedsession_clone_view,
name='plannedsession_clone_view'),
re_path(r'^sessions/(?P<id>\d+)/clone/team/$',views.plannedsession_teamclone_view,
name='plannedsession_teamclone_view'),
re_path(r'^sessions/(?P<id>\d+)/clone/$',views.plannedsession_clone_view),
re_path(r'^sessions/(?P<psid>\d+)/detach/(?P<id>\b[0-9A-Fa-f]+\b)/user/(?P<userid>\d+)/$',views.plannedsession_detach_view),
re_path(r'^sessions/(?P<psid>\d+)/detach/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.plannedsession_detach_view),
+144 -134
View File
@@ -7,7 +7,7 @@ from rowers.views.statements import *
import numpy
def default(o):
def default(o): # pragma: no cover
if isinstance(o, numpy.int64): return int(o)
raise TypeError
@@ -21,7 +21,7 @@ def workout_tp_upload_view(request,id=0):
res = -1
try:
thetoken = tp_open(r.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/tpauthorize/")
# ready to upload. Hurray
@@ -35,7 +35,7 @@ def workout_tp_upload_view(request,id=0):
r.tptoken,tcxfile,
name=w.name
)
if res == 0:
if res == 0: # pragma: no cover
message = "Upload to TrainingPeaks failed with status code "+str(status_code)+": "+reason
try:
os.remove(tcxfile)
@@ -50,7 +50,7 @@ def workout_tp_upload_view(request,id=0):
os.remove(tcxfile)
messages.info(request,'Uploaded to TrainingPeaks')
else: # no tcxfile
else: # pragma: no cover # no tcxfile
message = "Upload to TrainingPeaks failed"
w.uploadedtotp = -1
w.save()
@@ -74,10 +74,10 @@ def workout_strava_upload_view(request,id=0):
try:
thetoken = strava_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/stravaauthorize/")
if (r.stravatoken == '') or (r.stravatoken is None):
if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return HttpResponseRedirect("/rowers/me/stravaauthorize/")
else:
@@ -99,9 +99,9 @@ def workout_strava_upload_view(request,id=0):
if activity_type == 'match':
try:
activity_type = mytypes.stravamapping[w.workouttype]
except KeyError:
except KeyError: # pragma: no cover
activity_type = 'Ride'
else:
else: # pragma: no cover
try:
activity_type = mytypes.stravamapping[w.workouttype]
except KeyError:
@@ -112,7 +112,7 @@ def workout_strava_upload_view(request,id=0):
r.stravatoken,
description=newnotes,
activity_type=activity_type,quick=False)
if res==0:
if res==0: # pragma: no cover
messages.error(request,mes)
w.uploadedtostrava = -1
w.save()
@@ -132,13 +132,13 @@ def workout_strava_upload_view(request,id=0):
w.save()
try:
os.remove(tcxfile)
except WindowsError:
except WindowsError: # pragma: no cover
pass
url = reverse('workout_edit_view',kwargs={'id':w.id})
messages.info(request,mes)
except:
except: # pragma: no cover
with open("media/stravaerrors.log","a") as errorlog:
errorstring = str(sys.exc_info()[0])
timestr = strftime("%Y%m%d-%H%M%S")
@@ -146,7 +146,7 @@ def workout_strava_upload_view(request,id=0):
errorlog.write("views.py line 826\r\n")
message = 'Error: '+errorstring
messages.error(request,message)
else: # No tcxfile
else: # pragma: no cover # No tcxfile
message = "Strava Data error "+tcxmessg
messages.error(request,message)
w.uploadedtostrava = -1
@@ -164,7 +164,7 @@ def workout_strava_upload_view(request,id=0):
}
)
response = HttpResponseRedirect(url)
except ActivityUploadFailed as e:
except ActivityUploadFailed as e: # pragma: no cover
message = "Strava Upload error: %s" % e
messages.error(request,message)
w.uploadedtostrava = -1
@@ -188,10 +188,10 @@ def workout_c2_upload_view(request,id=0):
try:
message,c2id = c2stuff.workout_c2_upload(request.user,w)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/")
if message and c2id <=0:
if message and c2id <=0: # pragma: no cover
messages.error(request,message)
elif message:
messages.info(request,message)
@@ -216,14 +216,14 @@ def workout_runkeeper_upload_view(request,id=0):
try:
thetoken = runkeeper_open(r.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/runkeeperauthorize/")
# ready to upload. Hurray
data = runkeeperstuff.createrunkeeperworkoutdata(w)
if not data:
if not data: # pragma: no cover
message = "Data error"
messages.error(request,message)
url = reverse(r.defaultlandingpage,
@@ -242,7 +242,7 @@ def workout_runkeeper_upload_view(request,id=0):
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
# check for duplicate error first
if (response.status_code == 409 ):
if (response.status_code == 409 ): # pragma: no cover # pragma: no cover
message = "Duplicate error"
messages.error(request,message)
w.uploadedtorunkeeper = -1
@@ -255,7 +255,7 @@ def workout_runkeeper_upload_view(request,id=0):
kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
s = response
message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text)
messages.error(request,message)
@@ -264,9 +264,9 @@ def workout_runkeeper_upload_view(request,id=0):
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
}) # pragma: no cover
return HttpResponseRedirect(url)
return HttpResponseRedirect(url) # pragma: no cover
# Upload workout to Underarmour
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@@ -277,14 +277,14 @@ def workout_underarmour_upload_view(request,id=0):
try:
thetoken = underarmour_open(r.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/underarmourauthorize/")
# ready to upload. Hurray
data = underarmourstuff.createunderarmourworkoutdata(w)
if not data:
if not data: # pragma: no cover
message = "Data error"
messages.error(request,message)
url = reverse(r.defaultlandingpage,
@@ -305,7 +305,7 @@ def workout_underarmour_upload_view(request,id=0):
# check for duplicate error first
if (response.status_code == 409 ):
if (response.status_code == 409 ): # pragma: no cover # pragma: no cover
message = "Duplicate error"
messages.error(request,message)
w.uploadedtounderarmour = -1
@@ -317,7 +317,7 @@ def workout_underarmour_upload_view(request,id=0):
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
s = response
message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason
messages.error(request,message)
@@ -325,9 +325,9 @@ def workout_underarmour_upload_view(request,id=0):
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
}) # pragma: no cover
return HttpResponseRedirect(url)
return HttpResponseRedirect(url) # pragma: no cover
# Upload workout to SportTracks
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid)
@@ -339,14 +339,14 @@ def workout_sporttracks_upload_view(request,id=0):
try:
thetoken = sporttracks_open(r.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
data = sporttracksstuff.createsporttracksworkoutdata(w)
if not data:
if not data: # pragma: no cover
message = "Data error"
messages.error(request,message)
url = reverse(r.defaultlandingpage,
@@ -365,7 +365,7 @@ def workout_sporttracks_upload_view(request,id=0):
# check for duplicate error first
if (response.status_code == 409 ):
if (response.status_code == 409 ): # pragma: no cover
message = "Duplicate error"
messages.error(request,message)
w.uploadedtosporttracks = -1
@@ -380,7 +380,7 @@ def workout_sporttracks_upload_view(request,id=0):
url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
s = response
message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason
messages.error(request,message)
@@ -388,14 +388,14 @@ def workout_sporttracks_upload_view(request,id=0):
url = reverse(r.defaultlandingpage,
kwargs = {
'id':encoder.encode_hex(w.id),
})
}) # pragma: no cover
return HttpResponseRedirect(url)
return HttpResponseRedirect(url) # pragma: no cover
# NK LiNK authorization
@login_required()
def rower_nk_authorize(request):
def rower_nk_authorize(request): # pragma: no cover
state = str(uuid4())
scope = "read"
params = {
@@ -415,7 +415,7 @@ def rower_nk_authorize(request):
# Concept2 authorization
@login_required()
def rower_c2_authorize(request):
def rower_c2_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -430,7 +430,7 @@ def rower_c2_authorize(request):
# Garmin authorization
@login_required()
def rower_garmin_authorize(request):
def rower_garmin_authorize(request): # pragma: no cover
authorization_url,token,secret = garmin_stuff.garmin_authorize()
request.session['garmin_owner_key'] = token
request.session['garmin_owner_secret'] = secret
@@ -438,7 +438,7 @@ def rower_garmin_authorize(request):
# Strava Authorization
@login_required()
def rower_strava_authorize(request):
def rower_strava_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -455,7 +455,7 @@ def rower_strava_authorize(request):
# Polar Authorization
@login_required()
def rower_polar_authorize(request):
def rower_polar_authorize(request): # pragma: no cover
state = str(uuid4())
@@ -473,7 +473,7 @@ def rower_polar_authorize(request):
# Runkeeper authorization
@login_required()
def rower_runkeeper_authorize(request):
def rower_runkeeper_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -491,7 +491,7 @@ def rower_runkeeper_authorize(request):
# SportTracks Authorization
@login_required()
def rower_sporttracks_authorize(request):
def rower_sporttracks_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -509,7 +509,7 @@ def rower_sporttracks_authorize(request):
# Underarmour Authorization
@login_required()
def rower_underarmour_authorize(request):
def rower_underarmour_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -526,7 +526,7 @@ def rower_underarmour_authorize(request):
# Underarmour Authorization
@login_required()
def rower_rp3_authorize(request):
def rower_rp3_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -541,7 +541,7 @@ def rower_rp3_authorize(request):
# Underarmour Authorization
@login_required()
def rower_tp_authorize(request):
def rower_tp_authorize(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -576,7 +576,7 @@ def rower_c2_token_refresh(request):
successmessage = "Tokens refreshed. Good to go"
messages.info(request,successmessage)
else:
else: # pragma: no cover
message = "Something went wrong (refreshing tokens). Please reauthorize:"
messages.error(request,message)
@@ -677,7 +677,7 @@ def rower_process_callback(request):
try:
code = request.GET['code']
res = c2stuff.get_token(code)
except MultiValueDictKeyError:
except MultiValueDictKeyError: # pragma: no cover
message = "The resource owner or authorization server denied the request"
messages.error(request,message)
@@ -686,7 +686,7 @@ def rower_process_callback(request):
return HttpResponseRedirect(url)
access_token = res[0]
if access_token == 0:
if access_token == 0: # pragma: no cover
message = res[1]
message += ' Contact info@rowsandall.com if this behavior persists.'
messages.error(request,message)
@@ -716,12 +716,12 @@ def rower_process_callback(request):
# dummy
@login_required()
def rower_process_twittercallback(request):
def rower_process_twittercallback(request): # pragma: no cover
return "dummy"
# Process Polar Callback
@login_required()
def rower_process_polarcallback(request):
def rower_process_polarcallback(request): # pragma: no cover
try:
code = request.GET['code']
except MultiValueDictKeyError:
@@ -754,7 +754,7 @@ def rower_process_polarcallback(request):
# process Garmin callback
@login_required()
def rower_process_garmincallback(request):
def rower_process_garmincallback(request): # pragma: no cover
r = getrower(request.user)
absoluteurl = request.build_absolute_uri()
@@ -775,7 +775,7 @@ def rower_process_garmincallback(request):
# Process NK Callback
@login_required()
def rower_process_nkcallback(request):
def rower_process_nkcallback(request): # pragma: no cover
# do stuff
try:
code = request.GET.get('code',None)
@@ -819,7 +819,7 @@ def rower_process_nkcallback(request):
def workout_getnkworkout_all(request):
try:
thetoken = nk_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("rower_nk_authorize")
r = getrequestrower(request)
@@ -828,7 +828,7 @@ def workout_getnkworkout_all(request):
if result:
messages.info(request,"Your NK workouts will be imported in the coming few minutes")
else:
else: # pragma: no cover
messages.error(request,"Your NK workouts import failed")
url = reverse('workouts_view')
@@ -840,12 +840,12 @@ def workout_nkimport_view(request,userid=0,after=0,before=0):
r = getrequestrower(request,userid=userid)
try:
thetoken = nk_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/nkauthorize/")
res = nkstuff.get_nk_workout_list(request.user,before=before,after=after)
if (res.status_code != 200):
if (res.status_code != 200): # pragma: no cover
if (res.status_code == 401):
r = getrower(request.user)
if (r.stravatoken == '') or (r.stravatoken is None):
@@ -869,7 +869,7 @@ def workout_nkimport_view(request,userid=0,after=0,before=0):
with open('nkblocked.json','r') as nkblocked:
jsondata = json.load(nkblocked)
parkedids = jsondata['ids']
except FileNotFoundError:
except FileNotFoundError: # pragma: no cover
pass
knownnkids = uniqify(knownnkids+tombstones+parkedids)
@@ -893,7 +893,7 @@ def workout_nkimport_view(request,userid=0,after=0,before=0):
n = item['name']
if i in knownnkids:
nnn = ''
else:
else: # pragma: no cover
nnn = 'NEW'
ttot = str(datetime.timedelta(seconds=int(float(item['elapsedTime'])/1000.)))
s = arrow.get(item['startTime'],tzinfo=r.defaulttimezone).format(arrow.FORMAT_RFC850)
@@ -931,10 +931,10 @@ def rower_process_stravacallback(request):
try:
code = request.GET['code']
scope = request.GET['scope']
except MultiValueDictKeyError:
except MultiValueDictKeyError:# pragma: no cover
try:
message = request.GET['error']
except MultiValueDictKeyError:
except MultiValueDictKeyError:# pragma: no cover
message = "access error"
messages.error(request,message)
@@ -964,7 +964,7 @@ def rower_process_stravacallback(request):
messages.info(request,successmessage)
url = reverse('rower_exportsettings_view')
return HttpResponseRedirect(url)
else:
else:# pragma: no cover
message = "Something went wrong with the Strava authorization"
messages.error(request,message)
url = reverse('rower_exportsettings_view')
@@ -979,7 +979,7 @@ def rower_process_runkeepercallback(request):
res = runkeeperstuff.get_token(code)
access_token = res[0]
if access_token == 0:
if access_token == 0:# pragma: no cover
messages.error(request,"Something went wrong importing the token")
url = reverse('workouts_view')
@@ -1004,7 +1004,7 @@ def rower_process_runkeepercallback(request):
def rower_process_sporttrackscallback(request):
try:
code = request.GET['code']
except:
except:# pragma: no cover
messages.error(request,"Sorry, something went wrong.")
url = reverse('rower_exportsettings_view')
return HttpResponseRedirect(url)
@@ -1058,7 +1058,7 @@ def rower_process_underarmourcallback(request):
# Process RP3 callback
@login_required()
def rower_process_rp3callback(request):
def rower_process_rp3callback(request): # pragma: no cover
try:
code = request.GET['code']
except MultiValueDictKeyError:
@@ -1095,7 +1095,7 @@ def rower_process_rp3callback(request):
def rower_process_tpcallback(request):
try:
code = request.GET['code']
except MultiValueDictKeyError:
except MultiValueDictKeyError: # pragma: no cover
messages.error(request,"There was an error with the callback")
try:
errormessage = request.GET['error']
@@ -1128,7 +1128,7 @@ def rower_process_tpcallback(request):
# Process Own API callback - for API testing purposes
@login_required()
def rower_process_testcallback(request):
def rower_process_testcallback(request): # pragma: no cover
code = request.GET['code']
res = ownapistuff.get_token(code)
@@ -1153,13 +1153,13 @@ def workout_rp3import_view(request,userid=0):
try:
thetoken = rp3stuff.rp3_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
url = reverse('rower_rp3_authorize')
return HttpResponseRedirect(url)
res = rp3stuff.get_rp3_workout_list(request.user)
if (res.status_code != 200):
if (res.status_code != 200): # pragma: no cover
if (res.status_code == 401):
r = getrower(request.user)
if (r.stravatoken == '') or (r.stravatoken is None):
@@ -1185,7 +1185,7 @@ def workout_rp3import_view(request,userid=0):
for key,data in workouts_list.iterrows():
i = data['id']
if i in knownrp3ids:
if i in knownrp3ids: # pragma: no cover
nnn = ''
else:
nnn = 'NEW'
@@ -1229,14 +1229,14 @@ def workout_stravaimport_view(request,message="",userid=0):
# messages.info(request,"You cannot import other people's workouts from Strava")
try:
thetoken = strava_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/stravaauthorize/")
res = stravastuff.get_strava_workout_list(request.user)
if (res.status_code != 200):
if (res.status_code != 200): # pragma: no cover
if (res.status_code == 401):
r = getrower(request.user)
if (r.stravatoken == '') or (r.stravatoken is None):
@@ -1258,7 +1258,7 @@ def workout_stravaimport_view(request,message="",userid=0):
wfailed = Workout.objects.filter(user=r,uploadedtostrava=-1)
for w in wfailed:
for w in wfailed: # pragma: no cover
for item in stravadata:
elapsed_time = item['elapsed_time']
start_date = item['start_date']
@@ -1282,7 +1282,7 @@ def workout_stravaimport_view(request,message="",userid=0):
for item in res.json():
d = int(float(item['distance']))
i = item['id']
if i in knownstravaids:
if i in knownstravaids: # pragma: no cover
nnn = ''
else:
nnn = 'NEW'
@@ -1317,7 +1317,7 @@ def workout_stravaimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user),
})
return HttpResponse(res)
return HttpResponse(res) # pragma: no cover
# for Strava webhook request validation
@csrf_exempt
@@ -1325,7 +1325,7 @@ def strava_webhook_view(request):
if request.method == 'GET':
challenge = request.GET.get('hub.challenge')
verificationtoken = request.GET.get('hub.verify_token')
if verificationtoken != stravastuff.webhookverification:
if verificationtoken != stravastuff.webhookverification: # pragma: no cover
return HttpResponse(status=403)
data = {"hub.challenge":challenge}
return JSONResponse(data)
@@ -1341,12 +1341,16 @@ def strava_webhook_view(request):
# POST - does nothing so far
data = json.loads(request.body)
aspect_type = data['aspect_type']
object_type = data['object_type']
strava_owner = data['owner_id']
starttimeunix = data['event_time']
try:
aspect_type = data['aspect_type']
object_type = data['object_type']
strava_owner = data['owner_id']
starttimeunix = data['event_time']
except KeyError:
except KeyError: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
@@ -1359,7 +1363,7 @@ def strava_webhook_view(request):
if aspect_type == 'create':
try:
stravaid = data['object_id']
except KeyError:
except KeyError: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
@@ -1370,7 +1374,7 @@ def strava_webhook_view(request):
try:
r = Rower.objects.get(strava_owner_id=strava_owner)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
@@ -1381,14 +1385,14 @@ def strava_webhook_view(request):
ws = Workout.objects.filter(uploadedtostrava=stravaid)
if ws.count()==0 and r.strava_auto_import:
job = stravastuff.async_get_workout(r.user,stravaid)
if job == 0:
if job == 0: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M',t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
f.write(timestamp)
f.write(' ')
f.write('Strava strava_open yielded NoTokenError')
else:
else: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
@@ -1400,7 +1404,7 @@ def strava_webhook_view(request):
elif aspect_type == 'delete':
try:
stravaid = data['object_id']
except KeyError:
except KeyError: # pragma: no cover
with open('strava_webhooks.log','a') as f:
f.write('\n')
f.write(timestamp)
@@ -1410,11 +1414,11 @@ def strava_webhook_view(request):
ws = Workout.objects.filter(uploadedtostrava=stravaid)
if ws.count() == 0:
return HttpResponse(status=200)
except Workout.DoesNotExist:
except Workout.DoesNotExist: # pragma: no cover
return HttpResponse(status=200)
try:
try: # pragma: no cover
r = Rower.objects.get(strava_owner_id=strava_owner)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
@@ -1422,7 +1426,7 @@ def strava_webhook_view(request):
f.write(' ')
f.write('Rower not found')
return HttpResponse(status=200)
if r.strava_auto_delete:
if r.strava_auto_delete: # pragma: no cover
for w in ws:
if w.user == r:
w.delete()
@@ -1430,7 +1434,7 @@ def strava_webhook_view(request):
try:
updates = data['updates']
stravaid = data['object_id']
except KeyError:
except KeyError: # pragma: no cover
with open('strava_webhooks.log','a') as f:
f.write('\n')
f.write(timestamp)
@@ -1439,9 +1443,9 @@ def strava_webhook_view(request):
return HttpResponse(status=200)
try:
ws = Workout.objects.filter(uploadedtostrava=stravaid)
if ws.count() == 0:
if ws.count() == 0: # pragma: no cover
return HttpResponse(status=200)
except Workout.DoesNotExist:
except Workout.DoesNotExist: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
@@ -1451,7 +1455,7 @@ def strava_webhook_view(request):
return HttpResponse(status=200)
try:
r = Rower.objects.get(strava_owner_id=strava_owner)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f:
f.write('\n')
@@ -1469,7 +1473,7 @@ def strava_webhook_view(request):
try:
w.workouttype = mytypes.stravamappinginv[value]
w.save()
except KeyError:
except KeyError: # pragma: no cover
with open('strava_webhooks.log','a') as f:
f.write('\n')
f.write(timestamp)
@@ -1481,7 +1485,7 @@ def strava_webhook_view(request):
# For push notifications from Garmin
@csrf_exempt
def garmin_summaries_view(request):
def garmin_summaries_view(request): # pragma: no cover
if request.method != 'POST':
return HttpResponse(status=200)
@@ -1504,7 +1508,7 @@ def garmin_summaries_view(request):
return HttpResponse(status=200)
@csrf_exempt
def garmin_newfiles_ping(request):
def garmin_newfiles_ping(request): # pragma: no cover
t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
@@ -1528,11 +1532,11 @@ def garmin_newfiles_ping(request):
except KeyError:
pass
return HttpResponse(status=200)
return HttpResponse(status=200) # pragma: no cover
@csrf_exempt
def garmin_deregistration_view(request):
if request.method != 'POST':
if request.method != 'POST': # pragma: no cover
return HttpResponse(status=200)
data = json.loads(request.body)
@@ -1544,16 +1548,16 @@ def garmin_deregistration_view(request):
r = Rower.objects.get(garmintoken=garmintoken)
r.garmintoken = ''
r.save()
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
pass
except KeyError:
except KeyError: # pragma: no cover
pass
return HttpResponse(status=200)
@csrf_exempt
def garmin_details_view(request):
if request.method != 'POST':
if request.method != 'POST': # pragma: no cover
return HttpResponse(status=200)
t = time.localtime()
@@ -1577,12 +1581,12 @@ def workout_runkeeperimport_view(request,message="",userid=0):
if (r.runkeepertoken == '') or (r.runkeepertoken is None):
s = "Token doesn't exist. Need to authorize"
return HttpResponseRedirect("/rowers/me/runkeeperauthorize/")
message = "Something went wrong in workout_runkeeperimport_view"
messages.error(request,message)
message = "Something went wrong in workout_runkeeperimport_view" # pragma: no cover
messages.error(request,message) # pragma: no cover
if settings.DEBUG:
if settings.DEBUG: # pragma: no cover
return HttpResponse(res)
else:
else: # pragma: no cover
url = reverse('workouts_view')
return HttpResponseRedirect(url)
@@ -1620,7 +1624,7 @@ def workout_runkeeperimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user),
})
return HttpResponse(res)
return HttpResponse(res) # pragma: no cover
# The page where you select which RunKeeper workout to import
@login_required()
@@ -1638,7 +1642,7 @@ def workout_underarmourimport_view(request,message="",userid=0):
n = item['name']
try:
d = item['aggregates']['distance_total']
except KeyError:
except KeyError: # pragma: no cover
d = 0
try:
ttot = item['aggregates']['active_time_total']
@@ -1671,12 +1675,12 @@ def workout_underarmourimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user),
})
return HttpResponse(res)
return HttpResponse(res) # pragma: no cover
# the page where you select which Polar workout to Import
@login_required()
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def workout_polarimport_view(request,userid=0):
def workout_polarimport_view(request,userid=0): # pragma: no cover
exercises = polarstuff.get_polar_workouts(request.user)
workouts = []
@@ -1686,7 +1690,7 @@ def workout_polarimport_view(request,userid=0):
messages.error(request,'Not authorized. You need to connect to Polar first')
url = reverse('workouts_view')
return HttpResponseRedirect(url)
except:
except: # pragma: no cover
pass
for exercise in exercises:
@@ -1744,13 +1748,13 @@ def workout_sporttracksimport_view(request,message="",userid=0):
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
s = "Token doesn't exist. Need to authorize"
return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
else:
else: # pragma: no cover
return HttpResponseRedirect("/rowers/me/sporttracksrefresh/")
message = "Something went wrong in workout_sporttracksimport_view"
messages.error(request,message)
if settings.DEBUG:
message = "Something went wrong in workout_sporttracksimport_view" # pragma: no cover
messages.error(request,message) # pragma: no cover
if settings.DEBUG: # pragma: no cover
return HttpResponse(res)
else:
else: # pragma: no cover
url = reverse('workouts_view')
return HttpResponseRedirect(url)
@@ -1764,7 +1768,7 @@ def workout_sporttracksimport_view(request,message="",userid=0):
for item in res.json()['items']:
d = int(float(item['total_distance']))
i = int(getidfromuri(item['uri']))
if i in knownstids:
if i in knownstids: # pragma: no cover
nnn = ''
else:
nnn = 'NEW'
@@ -1798,14 +1802,14 @@ def workout_sporttracksimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user),
})
return HttpResponse(res)
return HttpResponse(res) # pragma: no cover
# List of workouts on Concept2 logbook. This view only used for debugging
@login_required()
def c2listdebug_view(request,page=1,message=""):
def c2listdebug_view(request,page=1,message=""): # pragma: no cover
try:
thetoken = c2_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/")
r = getrower(request.user)
@@ -1845,10 +1849,10 @@ def c2listdebug_view(request,page=1,message=""):
# Import all unknown workouts available on Concept2 logbook
@login_required()
def workout_getc2workout_all(request,page=1,message=""):
def workout_getc2workout_all(request,page=1,message=""): # pragma: no cover
try:
thetoken = c2_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/")
r = getrequestrower(request)
@@ -1864,10 +1868,10 @@ def workout_getc2workout_all(request,page=1,message=""):
return HttpResponseRedirect(url)
@login_required()
def workout_getrp3workout_all(request):
def workout_getrp3workout_all(request): # pragma: no cover
try:
thetoken = rp3_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/rp3authorize/")
r = getrequestrower(request)
@@ -1891,12 +1895,12 @@ def workout_c2import_view(request,page=1,userid=0,message=""):
try:
thetoken = c2_open(request.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/")
res = c2stuff.get_c2_workout_list(request.user,page=page)
if (res.status_code != 200):
if (res.status_code != 200): # pragma: no cover
message = "Something went wrong in workout_c2import_view (C2 token refresh)"
messages.error(request,message)
url = reverse('workouts_view')
@@ -1915,7 +1919,7 @@ def workout_c2import_view(request,page=1,userid=0,message=""):
with open('c2blocked.json','r') as c2blocked:
jsondata = json.load(c2blocked)
parkedids = jsondata['ids']
except FileNotFoundError:
except FileNotFoundError: # pragma: no cover
pass
knownc2ids = uniqify(knownc2ids+tombstones+parkedids)
@@ -1931,7 +1935,7 @@ def workout_c2import_view(request,page=1,userid=0,message=""):
c = item['comments']
if i in knownc2ids:
nnn = ''
else:
else: # pragma: no cover
nnn = 'NEW'
keys = ['id','distance','duration','starttime','rowtype','source','comment','new']
values = [i,d,ttot,s,r,s2,c,nnn]
@@ -2001,10 +2005,16 @@ def workout_getrp3importview(request,externalid):
return HttpResponseRedirect(url)
@login_required()
def workout_getimportview(request,externalid,source = 'c2'):
data,strokedata = importsources[source].get_workout(request.user,externalid)
if not data:
def workout_getimportview(request,externalid,source = 'c2',do_async=False):
data,strokedata = importsources[source].get_workout(request.user,externalid,
do_async=do_async)
if do_async: # pragma: no cover
messages.info(request,"Your workout will be imported in the background")
url = reverse('workouts_view')
return HttpResponseRedirect(url)
if not data: # pragma: no cover
messages.error(request,"No strokedata received")
url = reverse('workouts_view')
@@ -2027,7 +2037,7 @@ def workout_getimportview(request,externalid,source = 'c2'):
pass
if strokedata.empty:
if strokedata.empty: # pragma: no cover
distance = data['distance']
c2id = data['id']
workouttype = mytypes.c2mappinginv[data['type']]
@@ -2100,7 +2110,7 @@ def workout_getimportview(request,externalid,source = 'c2'):
w = get_workout(encoder.encode_hex(id))
if 'workout' in data:
if 'workout' in data: # pragma: no cover
if 'splits' in data['workout']:
splitdata = data['workout']['splits']
elif 'intervals' in data['workout']:
@@ -2111,7 +2121,7 @@ def workout_getimportview(request,externalid,source = 'c2'):
splitdata = False
# splitdata (only for C2)
if splitdata:
if splitdata: # pragma: no cover
w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename,workouttype=workouttype)
w.save()
@@ -2136,20 +2146,20 @@ def workout_getimportview(request,externalid,source = 'c2'):
w.uploadedtostrava = externalid
elif source == 'c2':
w.uploadedtoc2 = externalid
elif source == 'polar':
elif source == 'polar': # pragma: no cover
w.uploadedtopolar = externalid
elif source == 'runkeeper':
w.uploadedtorunkeeper = externalid
elif source == 'sporttracks':
w.uploadedtosporttracks = externalid
elif source == 'trainingpeaks':
elif source == 'trainingpeaks': # pragma: no cover
w.uploadedtotp = externalid
elif source == 'underarmour':
w.uploadedtounderarmour = externalid
w.save()
if message:
if message: # pragma: no cover
messages.error(request,message)
r = getrower(request.user)
@@ -2183,7 +2193,7 @@ def workout_getsporttracksworkout_all(request):
id,message = sporttracksstuff.add_workout_from_data(
request.user,sporttracksid,data,strokedata
)
if id==0:
if id==0: # pragma: no cover
messages.error(request,message)
else:
@@ -2200,7 +2210,7 @@ def workout_getsporttracksworkout_all(request):
def workout_getstravaworkout_all(request):
r = getrower(request.user)
res = stravastuff.get_strava_workouts(r)
if res == 1:
if res == 1: # pragma: no cover
messages.info(request,"Your workouts are being imported and should appear on the site in the next 15 minutes")
else:
messages.error(request,"Couldn't import Strava workouts ")
@@ -2211,7 +2221,7 @@ def workout_getstravaworkout_all(request):
# Imports all new workouts from SportTracks
@login_required()
def workout_getstravaworkout_next(request):
def workout_getstravaworkout_next(request): # pragma: no cover
r = Rower.objects.get(user=request.user)
+122 -132
View File
@@ -25,9 +25,9 @@ def plannedsession_comment_view(request,id=0,userid=0):
comment = cd['comment']
comment = bleach.clean(comment)
try:
if isinstance(comment,unicode):
if isinstance(comment,unicode): # pragma: no cover
comment = comment.encode('utf8')
elif isinstance(comment, str):
elif isinstance(comment, str): # pragma: no cover
comment = comment.decode('utf8')
except:
pass
@@ -45,13 +45,13 @@ def plannedsession_comment_view(request,id=0,userid=0):
comment = comment,
url = url,
)
if request.user != manager:
if request.user != manager: # pragma: no cover
a_messages.info(r.user,message.encode('ascii','ignore'))
sessiontype = 'training session'
if ps.sessiontype == 'race':
if ps.sessiontype == 'race': # pragma: no cover
sessiontype = 'online virtual race'
elif ps.sessiontype == 'indoorrace':
elif ps.sessiontype == 'indoorrace': # pragma: no cover
sessiontype = 'indoor online virtual race'
res = myqueue(queuehigh,
@@ -67,14 +67,14 @@ def plannedsession_comment_view(request,id=0,userid=0):
)
commenters = {oc.user for oc in comments if oc.notification}
if ps.sessiontype=='race':
if ps.sessiontype=='race': # pragma: no cover
registrations = VirtualRaceResult.objects.filter(
race__id=ps.id,
emailnotifications=True)
ids = [rg.userid for rg in registrations]
rwrs = Rower.objects.filter(id__in= ids)
rowers = {u.user for u in rwrs}
elif ps.sessiontype=='indoorrace':
elif ps.sessiontype=='indoorrace': # pragma: no cover
registrations = IndoorVirtualRaceResult.objects.filter(
race__id=ps.id,
emailnotifications=True)
@@ -87,9 +87,9 @@ def plannedsession_comment_view(request,id=0,userid=0):
for u in commenters:
try:
a_messages.info(u,message)
except ValueError:
except ValueError: # pragma: no cover
pass
if u != request.user and u != r.user:
if u != request.user and u != r.user: # pragma: no cover
ocr = Rower.objects.get(user=u)
res = myqueue(queue,
handle_sendemailnewresponse,
@@ -106,7 +106,7 @@ def plannedsession_comment_view(request,id=0,userid=0):
sessiontype = sessiontype,
commentlink = url
)
if ps.sessiontype in ['race','indoorrace']:
if ps.sessiontype in ['race','indoorrace']: # pragma: no cover
followers = VirtualRaceFollower.objects.filter(race__id=ps.id)
for follower in followers:
othername = ''
@@ -133,7 +133,7 @@ def plannedsession_comment_view(request,id=0,userid=0):
rower = getrower(request.user)
if ps.sessiontype in ['race','indoorrace']:
if ps.sessiontype in ['race','indoorrace']: # pragma: no cover
breadcrumbs = [
{
'url':reverse('virtualevents_view'),
@@ -209,12 +209,14 @@ def plannedsession_message_view(request,id=0,userid=0):
message,
)
url = reverse('plannedsession_view',kwargs={'id':ps.id})
if ps.sessiontype in ['race','indoorrace']: # pragma: no cover
url = reverse('virtualevent_view',kwargs={'id':ps.id})
url = reverse('virtualevent_view',kwargs={'id':ps.id})
return HttpResponseRedirect(url)
if ps.sessiontype in ['race','indoorrace']:
if ps.sessiontype in ['race','indoorrace']: # pragma: no cover
breadcrumbs = [
{
'url':reverse('virtualevents_view'),
@@ -274,7 +276,7 @@ def plannedsession_multiclone_view(
startdate,enddate = get_dates_timeperiod(request)
teamid = get_team(request)
if request.method == 'POST' and 'daterange' in request.POST:
if request.method == 'POST' and 'daterange' in request.POST: # pragma: no cover
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
startdate = dateform.cleaned_data['startdate']
@@ -337,7 +339,7 @@ def plannedsession_multiclone_view(
"startdate","preferreddate","enddate").exclude(
sessiontype='race')
if teamid:
if teamid: # pragma: no cover
sps = sps.filter(team__in=[teamid])
try:
team = Team.objects.get(id=teamid)
@@ -349,7 +351,7 @@ def plannedsession_multiclone_view(
team = None
query = request.GET.get('q')
if query:
if query: # pragma: no cover
query_list = query.split()
sps = sps.filter(
reduce(operator.and_,
@@ -390,7 +392,7 @@ def plannedsession_multiclone_view(
if Team.objects.filter(manager=request.user).count()>=1:
teamform = RowerTeamForm(request.user)
if teamid:
if teamid: # pragma: no cover
teamform = RowerTeamForm(request.user,initial={'team':teamid})
else:
teamform = None
@@ -422,7 +424,7 @@ def template_share_view(request,id=0,userid=0):
if ps.can_be_shared:
ps.is_public = True
ps.save()
else:
else: # pragma: no cover
messages.error(request,'This planned session comes from a third party and cannot be shared')
return HttpResponseRedirect(reverse(template_library_view))
@@ -471,7 +473,7 @@ def template_library_view(request,userid=0):
alltags = uniqify(alltags)
tag = request.GET.get('tag')
if tag:
if tag: # pragma: no cover
tags = [tag]
templates = templates.filter(tags__name__in=tags).distinct()
@@ -539,11 +541,11 @@ def plannedsession_create_view(request,
})
if '_continue' in request.POST:
if '_continue' in request.POST: # pragma: no cover
url = reverse('plannedsession_edit_view',kwargs={
'id':ps.id,
})
elif '_addanother' in request.POST:
elif '_addanother' in request.POST: # pragma: no cover
url = reverse('plannedsession_create_view',kwargs={'userid':userid})
url = url+'?when='+timeperiod
@@ -551,7 +553,7 @@ def plannedsession_create_view(request,
return HttpResponseRedirect(url)
else:
if 'fstartdate' in request.session:
if 'fstartdate' in request.session: # pragma: no cover
try:
fstartdate = arrow.get(request.session['fstartdate']).date()
except KeyError:
@@ -586,7 +588,7 @@ def plannedsession_create_view(request,
preferreddate = startdate.date()
except AttributeError:
preferreddate = startdate
if preferreddate < timezone.now().date():
if preferreddate < timezone.now().date(): # pragma: no cover
preferreddate = timezone.now().date()
try:
@@ -594,7 +596,7 @@ def plannedsession_create_view(request,
except AttributeError:
pass
if preferreddate > enddate:
if preferreddate > enddate: # pragma: no cover
preferreddate = enddate
forminitial = {
@@ -626,7 +628,7 @@ def plannedsession_create_view(request,
sessiontemplates = sessiontemplates.order_by("name")
alltags = []
for t in sessiontemplates:
for t in sessiontemplates: # pragma: no cover
tags = t.tags.all()
for tag in tags:
alltags.append(tag)
@@ -634,7 +636,7 @@ def plannedsession_create_view(request,
alltags = uniqify(alltags)
tag = request.GET.get('tag')
if tag:
if tag: # pragma: no cover
tags = [tag]
sessiontemplates = sessiontemplates.filter(tags__name__in=tags).distinct()
@@ -709,11 +711,11 @@ def plannedsession_createtemplate_view(request,
url = reverse('template_library_view')
if '_continue' in request.POST:
if '_continue' in request.POST: # pragma: no cover
url = reverse('plannedsession_templateedit_view',kwargs={
'id':ps.id,
})
elif '_addanother' in request.POST:
elif '_addanother' in request.POST: # pragma: no cover
url = reverse('plannedsession_createtemplate_view')
return HttpResponseRedirect(url)
@@ -733,7 +735,7 @@ def plannedsession_createtemplate_view(request,
sessiontemplates = sessiontemplates.order_by("name")
alltags = []
for t in sessiontemplates:
for t in sessiontemplates: # pragma: no cover
tags = t.tags.all()
for tag in tags:
alltags.append(tag)
@@ -806,7 +808,7 @@ def plannedsession_multicreate_view(request,
).order_by("startdate","preferreddate","enddate").exclude(
sessiontype='race')
if teamid:
if teamid: # pragma: no cover
qset = qset.filter(team__in=[teamid])
try:
team = Team.objects.get(id=teamid)
@@ -844,10 +846,10 @@ def plannedsession_multicreate_view(request,
for ps in instances:
ps.save()
add_rower_session(r,ps)
if team:
if team: # pragma: no cover
add_team_session(team,ps)
messages.info(request,"Saved changes for Planned Session "+str(ps))
for obj in ps_formset.deleted_objects:
for obj in ps_formset.deleted_objects: # pragma: no cover
messages.info(request,"Deleted Planned Session "+str(obj))
obj.delete()
@@ -862,7 +864,7 @@ def plannedsession_multicreate_view(request,
enddatestring = enddate.strftime('%Y-%m-%d')
url += '?when='+startdatestring+'/'+enddatestring
if team:
if team: # pragma: no cover
url += '&team={teamid}'.format(teamid=team.id)
return HttpResponseRedirect(url)
@@ -888,7 +890,7 @@ def plannedsession_multicreate_view(request,
if Team.objects.filter(manager=request.user).count()>=1:
teamform = RowerTeamForm(request.user)
if teamid:
if teamid: # pragma: no cover
teamform = RowerTeamForm(request.user,initial={'team':teamid})
else:
teamform = None
@@ -975,11 +977,11 @@ def plannedsession_teamcreate_view(request,
'userid':userid,
})
if '_continue' in request.POST:
if '_continue' in request.POST: # pragma: no cover
url = reverse('plannedsession_edit_view',kwargs={
'id':ps.id,
})
elif '_addanother' in request.POST:
elif '_addanother' in request.POST: # pragma: no cover
url = reverse('plannedsession_teamcreate_view',kwargs={'userid':userid})
url = url+'?when='+timeperiod
@@ -995,7 +997,7 @@ def plannedsession_teamcreate_view(request,
#next = request.GET.get('next', url)
#return HttpResponseRedirect(next)
else:
else: # pragma: no cover
timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
breadcrumbs = [
{
@@ -1035,7 +1037,7 @@ def plannedsession_teamcreate_view(request,
'preferreddate':startdate,
}
if 'teams' in request.session:
if 'teams' in request.session: # pragma: no cover
teams = request.session['teams']
theteams = Team.objects.filter(id__in=teams)
initialteam = {
@@ -1113,7 +1115,7 @@ def plannedsession_teamedit_view(request,
startdate__lte = startdate,
rowers = r,
enddate__gte = enddate)[0]
except IndexError:
except IndexError: # pragma: no cover
trainingplan = None
sps = []
@@ -1138,11 +1140,10 @@ def plannedsession_teamedit_view(request,
)
sessionrowerform = PlannedSessionTeamMemberForm(ps,request.POST)
if sessioncreateform.is_valid():
cd = sessioncreateform.cleaned_data
if cd['sessionunit'] == 'min':
if cd['sessionunit'] == 'min': # pragma: no cover
cd['sessionmode'] = 'time'
elif cd['sessionunit'] in ['km','m']:
cd['sessionmode'] = 'distance'
@@ -1152,7 +1153,7 @@ def plannedsession_teamedit_view(request,
if res:
messages.info(request,message)
else:
else: # pragma: no cover
messages.error(request,message)
@@ -1166,14 +1167,15 @@ def plannedsession_teamedit_view(request,
rs = Rower.objects.filter(team__in=[team])
for r in rs:
add_rower_session(r,ps)
else:
else: # pragma: no cover
remove_team_session(team,ps)
else:
else: # pragma: no cover
selectedteams = []
for team in teams:
remove_team_session(team,ps)
if sessionrowerform.is_valid():
cd = sessionrowerform.cleaned_data
selectedrowers = cd['members']
@@ -1190,7 +1192,7 @@ def plannedsession_teamedit_view(request,
url = reverse('plannedsessions_view')
if "_continue" in request.POST:
if "_continue" in request.POST: # pragma: no cover
url = reverse(plannedsession_edit_view,
kwargs={
'id':int(ps.id),
@@ -1279,7 +1281,7 @@ def plannedsessions_coach_view(request,
trainingplan = None
if teamid != 0:
if teamid != 0:# pragma: no cover
try:
theteam = Team.objects.get(id=teamid)
except Team.DoesNotExist:
@@ -1297,13 +1299,13 @@ def plannedsessions_coach_view(request,
if therower.rowerplan != 'freecoach':
rowers = [therower]
else:
else:# pragma: no cover
rowers = []
for ps in sps:
if 'coach' in request.user.rower.rowerplan:
rowers += ps.rower.all().exclude(rowerplan='freecoach')
else:
else: # pragma: no cover
rowers += ps.rower.filter(team__in=rteams).exclude(rowerplan='freecoach')
rowers = list(set(rowers))
@@ -1356,7 +1358,7 @@ def plannedsessions_coach_view(request,
})
ttemplate = 'plannedsessionscoach.html'
if len(rowers) > 5 and len(rowers) > len(sps):
if len(rowers) > 5 and len(rowers) > len(sps): # pragma: no cover
ttemplate = 'plannedsessionscoach2.html'
@@ -1386,16 +1388,16 @@ def plannedsessions_view(request,
try:
r = getrequestplanrower(request,userid=userid)
except PermissionDenied:
except PermissionDenied: # pragma: no cover
r = request.user.rower
if startdatestring:
if startdatestring: # pragma: no cover
try:
startdate = iso8601.parse_date(startdatestring)
except ParseError:
pass
if enddatestring:
if enddatestring: # pragma: no cover
try:
enddate = iso8601.parse_date(enddatestring)
except ParseError:
@@ -1454,7 +1456,7 @@ def plannedsessions_view(request,
tss = hrtss
totals['distance'] += w.distance
totals['time'] += timefield_to_seconds_duration(w.duration)
if w.plannedsession:
if w.plannedsession: # pragma: no cover
if w.plannedsession.sessionmode == 'distance':
totals['actualdistance'] += w.distance
elif w.plannedsession.sessionmode == 'time':
@@ -1464,7 +1466,7 @@ def plannedsessions_view(request,
elif w.plannedsession.sessionmode == 'TRIMP':
totals['actualtrimp'] += thetrimp
if not sps and request.user.rower.rowerplan == 'basic':
if not sps and request.user.rower.rowerplan == 'basic': # pragma: no cover
messages.error(request,
"You must purchase Coach or Self-coach plans or be part of a team to get planned sessions")
@@ -1479,9 +1481,9 @@ def plannedsessions_view(request,
totals['planneddistance'] += ps.sessionvalue
elif ps.sessionmode == 'time':
totals['plannedtime'] += ps.sessionvalue
elif ps.sessionmode == 'rScore':
elif ps.sessionmode == 'rScore': # pragma: no cover
totals['plannedrscore'] += ps.sessionvalue
elif ps.sessionmode == 'TRIMP':
elif ps.sessionmode == 'TRIMP': # pragma: no cover
totals['plannedtrimp'] += ps.sessionvalue
totals['time'] = int(totals['time']/60.)
@@ -1572,7 +1574,7 @@ def plannedsessions_manage_view(request,userid=0,
initialsession=0):
is_ajax = False
if request.is_ajax():
if request.is_ajax(): # pragma: no cover
is_ajax = True
r = getrequestrower(request,userid=userid)
@@ -1614,7 +1616,7 @@ def plannedsessions_manage_view(request,userid=0,
linkedworkouts = []
for w in ws:
if w.plannedsession is not None:
if w.plannedsession is not None: # pragma: no cover
linkedworkouts.append(w.id)
plannedsessionstuple = []
@@ -1646,10 +1648,10 @@ def plannedsessions_manage_view(request,userid=0,
ps = PlannedSession.objects.get(id=ps_form.cleaned_data['plannedsession'])
if w_form.is_valid():
selectedworkouts = w_form.cleaned_data['workouts']
else:
else: # pragma: no cover
selectedworkouts = []
if len(selectedworkouts)==0:
if len(selectedworkouts)==0: # pragma: no cover
for w in ws:
remove_workout_plannedsession(w,ps)
@@ -1662,7 +1664,7 @@ def plannedsessions_manage_view(request,userid=0,
result,comments,errors = add_workouts_plannedsession(workouts,ps,r)
for c in comments:
messages.info(request,c)
for er in errors:
for er in errors: # pragma: no cover
messages.error(request,er)
@@ -1672,7 +1674,7 @@ def plannedsessions_manage_view(request,userid=0,
w_form = WorkoutSessionSelectForm(workoutdata=workoutdata)
if is_ajax:
if is_ajax: # pragma: no cover
ajax_workouts = []
for id,name in workoutdata['choices']:
ininitial = id in initialworkouts
@@ -1746,7 +1748,7 @@ def plannedsession_clone_view(request,id=0,userid=0):
startdate__lte = startdate,
rowers = r,
enddate__gte = enddate)[0]
except IndexError:
except IndexError: # pragma: no cover
trainingplan = None
ps = get_object_or_404(PlannedSession,pk=id)
@@ -1773,7 +1775,7 @@ def plannedsession_clone_view(request,id=0,userid=0):
if rowers:
for rower in rowers:
add_rower_session(rower,ps)
else:
else: # pragma: no cover
add_rower_session(r,ps)
for team in teams:
add_team_session(team,ps)
@@ -1803,10 +1805,10 @@ def plannedsession_teamclone_view(request,id=0):
r = getrequestplanrower(request)
teams = Team.objects.filter(manager=request.user)
if teams.count()>0:
if teams.count()>0: # pragma: no cover
teamchoices = [(team.id, team.name) for team in teams]
teaminitial = [str(teams[0].id)]
else:
else: # pragma: no cover
messages.info(request,"You have no teams established yet. We are redirecting you to the Team Management page.")
url = reverse('rower_teams_view')
return HttpResponseRedirect(url)
@@ -1871,16 +1873,16 @@ def plannedsession_templateedit_view(request,id=0):
try:
ps = PlannedSession.objects.get(id=id)
except PlannedSession.DoesNotExist:
except PlannedSession.DoesNotExist: # pragma: no cover
raise Http404("Planned Session does not exist")
if ps.manager != request.user:
if ps.manager != request.user: # pragma: no cover
raise PermissionDenied("You are not allowed to edit this planned session")
if ps.sessiontype in ['race','indoorrace']:
if ps.sessiontype in ['race','indoorrace']: # pragma: no cover
raise PermissionDenied("You are not allowed to edit this planned session because it is a race")
if not ps.is_template:
if not ps.is_template: # pragma: no cover
ps.pk = None
ps.id = None
ps.is_template = True
@@ -1898,7 +1900,7 @@ def plannedsession_templateedit_view(request,id=0):
cd = sessioncreateform.cleaned_data
if cd['sessionunit'] == 'min':
cd['sessionmode'] = 'time'
elif cd['sessionunit'] in ['km','m']:
elif cd['sessionunit'] in ['km','m']: # pragma: no cover
cd['sessionmode'] = 'distance'
obj = sessioncreateform.save(commit=False)
@@ -1910,12 +1912,12 @@ def plannedsession_templateedit_view(request,id=0):
if res:
messages.info(request,message)
else:
else: # pragma: no cover
messages.error(request,message)
url = reverse('template_library_view')
if '_continue' in request.POST:
if '_continue' in request.POST: # pragma: no cover
url = reverse('plannedsession_templateedit_view',kwargs={
'id':ps.id,
})
@@ -2010,7 +2012,7 @@ def plannedsession_edit_view(request,id=0,userid=0):
startdate__lte = startdate,
rowers = r,
enddate__gte = enddate)[0]
except IndexError:
except IndexError: # pragma: no cover
trainingplan = None
ps = get_object_or_404(PlannedSession,pk=id)
@@ -2028,7 +2030,7 @@ def plannedsession_edit_view(request,id=0,userid=0):
if sessioncreateform.is_valid():
cd = sessioncreateform.cleaned_data
if cd['sessionunit'] == 'min':
if cd['sessionunit'] == 'min': # pragma: no cover
cd['sessionmode'] = 'time'
elif cd['sessionunit'] in ['km','m']:
cd['sessionmode'] = 'distance'
@@ -2039,12 +2041,12 @@ def plannedsession_edit_view(request,id=0,userid=0):
if res:
messages.info(request,message)
else:
else: # pragma: no cover
messages.error(request,message)
url = reverse('plannedsessions_view')
if "_continue" in request.POST:
if "_continue" in request.POST: # pragma: no cover
url = reverse(plannedsession_edit_view,
kwargs={
'id':int(ps.id),
@@ -2147,13 +2149,13 @@ def plannedsession_view(request,id=0,userid=0):
r = getrequestplanrower(request,userid=userid)
ps = get_object_or_404(PlannedSession,pk=id)
if ps.steps is not None:
if ps.steps is not None: # pragma: no cover
jsons = ps.steps
else:
jsons = {}
try:
try: # pragma: no cover
r = VirtualRace.objects.get(id=ps.id)
url = reverse('virtualevent_view',
kwargs={'id':ps.id}
@@ -2162,7 +2164,7 @@ def plannedsession_view(request,id=0,userid=0):
except VirtualRace.DoesNotExist:
pass
if ps.course:
if ps.course: # pragma: no cover
coursescript,coursediv = course_map(ps.course)
else:
coursescript = ''
@@ -2208,7 +2210,7 @@ def plannedsession_view(request,id=0,userid=0):
'sessionresult':0,
'workoutid':w.id,
}
if ps.sessiontype == 'coursetest':
if ps.sessiontype == 'coursetest': # pragma: no cover
vs = CourseTestResult.objects.filter(plannedsession=ps,
workoutid=w.id)
@@ -2254,10 +2256,10 @@ def plannedsession_view(request,id=0,userid=0):
wdict['distance'] = ps.course.distance
wdict['coursecompleted'] = False
ranking.append(wdict)
if ps.sessiontype == 'coursetest':
if ps.sessiontype == 'coursetest': # pragma: no cover
ranking = sorted(ranking, key=lambda k: k['time'])
if ps.sessiontype == 'fastest_distance':
if ps.sessiontype == 'fastest_distance': # pragma: no cover
vs = CourseTestResult.objects.filter(plannedsession=ps)
if vs:
@@ -2293,7 +2295,7 @@ def plannedsession_view(request,id=0,userid=0):
pass
ranking = sorted(ranking, key=lambda k: k['time'])
if ps.sessiontype == 'fastest_time':
if ps.sessiontype == 'fastest_time': # pragma: no cover
vs = CourseTestResult.objects.filter(plannedsession=ps)
if vs:
@@ -2363,7 +2365,7 @@ def plannedsession_view(request,id=0,userid=0):
comments = PlannedSessionComment.objects.filter(plannedsession=ps).order_by("created")
steps = ''
if ps.steps:
if ps.steps: # pragma: no cover
d = ps.steps
steps = ps_dict_get_description_html(d,short=False)
@@ -2407,7 +2409,7 @@ class PlannedSessionDelete(DeleteView):
def get_context_data(self, **kwargs):
context = super(PlannedSessionDelete,self).get_context_data(**kwargs)
if 'userid' in kwargs:
if 'userid' in kwargs: # pragma: no cover
userid = kwargs['userid']
else:
userid = 0
@@ -2455,7 +2457,7 @@ class PlannedSessionDelete(DeleteView):
def get_success_url(self):
ws = Workout.objects.filter(plannedsession=self.object)
for w in ws:
for w in ws: # pragma: no cover
w.plannedsession = None
w.save()
@@ -2468,14 +2470,14 @@ class PlannedSessionDelete(DeleteView):
def get_object(self, *args, **kwargs):
obj = super(PlannedSessionDelete, self).get_object(*args, **kwargs)
if not can_delete_session(self.request.user,obj):
if not can_delete_session(self.request.user,obj): # pragma: no cover
raise PermissionDenied('You are not allowed to delete this planned session')
return obj
def rower_view_instantplan(request,id='',userid=0):
r = getrequestrower(request,userid=userid)
if not id:
if not id: # pragma: no cover
raise Http404("Plan does not exist")
plan = InstantPlan.objects.get(uuid=id)
@@ -2486,7 +2488,7 @@ def rower_view_instantplan(request,id='',userid=0):
headers = {'Authorization':authorizationstring}
response = requests.get(url=url,headers=headers)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
messages.error(request,"Could not connect to the training plan server")
return HttpResponseRedirect(reverse('rower_select_instantplan'))
@@ -2518,7 +2520,7 @@ def rower_view_instantplan(request,id='',userid=0):
).order_by("-date")
if request.method == 'POST' and not request.user.is_anonymous:
if not can_plan(request.user):
if not can_plan(request.user): # pragma: no cover
messages.error(request,'You must be on a <a href="/rowers/paidplans">paid plan</a> to use this functionality')
url = reverse('rower_view_instantplan',kwargs={
'id':id,
@@ -2532,11 +2534,11 @@ def rower_view_instantplan(request,id='',userid=0):
name = form.cleaned_data['name']
try:
targetid = form.cleaned_data['target']
if targetid != '':
if targetid != '': # pragma: no cover
target = TrainingTarget.objects.get(id=int(targetid))
else:
target = None
except KeyError:
except KeyError: # pragma: no cover
try:
targetid = request.POST['target']
if targetid != '':
@@ -2551,12 +2553,12 @@ def rower_view_instantplan(request,id='',userid=0):
datechoice = form.cleaned_data['datechoice']
status = True
if target and datechoice == 'target':
if target and datechoice == 'target': # pragma: no cover
enddate = target.date
startdate = enddate-datetime.timedelta(days=plan.duration)
elif datechoice == 'startdate':
enddate = startdate+datetime.timedelta(days=plan.duration)
else:
else: # pragma: no cover
startdate = enddate-datetime.timedelta(days=plan.duration)
@@ -2583,7 +2585,7 @@ def rower_view_instantplan(request,id='',userid=0):
elif not request.user.is_anonymous:
form = InstantPlanSelectForm(targets=targets,instantplan=plan,initial={'datechoice':'startdate'})
else:
else: # pragma: no cover
form = None
breadcrumbs = [
@@ -2630,7 +2632,7 @@ def remove_groupsession_view(request,id=0):
if res:
messages.info(request,"We have removed you from this group session")
else:
else: # pragma: no cover
messages.error(request,"For some reason we could not remove you from this group session")
url = reverse('plannedsessions_view')
@@ -2639,12 +2641,12 @@ def remove_groupsession_view(request,id=0):
@login_required()
def add_instantplan_view(request):
if not request.user.is_staff:
if not request.user.is_staff: # pragma: no cover
raise PermissionDenied("Not Allowed")
r = getrequestrower(request)
if request.method == 'POST':
if request.method == 'POST': # pragma: no cover
form = InstantPlanForm(request.POST,request.FILES)
if form.is_valid():
ip = form.save(commit=False)
@@ -2762,9 +2764,9 @@ def rower_create_trainingplan(request,id=0):
targetid = request.POST['target']
if targetid != '':
target = TrainingTarget.objects.get(id=int(targetid))
else:
else: # pragma: no cover
target = None
except KeyError:
except KeyError: # pragma: no cover
target = None
startdate = form.cleaned_data['startdate']
status = form.cleaned_data['status']
@@ -2812,7 +2814,7 @@ def rower_create_trainingplan(request,id=0):
status=True,
).order_by("-startdate")
for p in plans_to_deactivate:
for p in plans_to_deactivate: # pragma: no cover
p.status = False
p.save()
@@ -2861,18 +2863,6 @@ def rower_delete_trainingtarget(request,id=0):
return HttpResponseRedirect(url)
@user_passes_test(can_plan,login_url="/rowers/paidplans",
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
@permission_required('target.delete_plan',fn=get_plan_by_pk,raise_exception=True)
def rower_delete_trainingplan(request,id=0):
plan = get_object_or_404(TrainingPlan,pk=id)
plan.delete()
url = reverse(rower_create_trainingplan)
return HttpResponseRedirect(url)
class TrainingPlanDelete(DeleteView):
model = TrainingPlan
template_name = 'trainingplan_delete.html'
@@ -2880,12 +2870,12 @@ class TrainingPlanDelete(DeleteView):
def get_object(self, *args, **kwargs):
obj = super(TrainingPlanDelete, self).get_object(*args, **kwargs)
if not can_delete_plan(self.request.user,obj):
if not can_delete_plan(self.request.user,obj): # pragma: no cover
raise PermissionDenied('You are not allowed to delete this training plan')
return obj
class MicroCycleDelete(DeleteView):
class MicroCycleDelete(DeleteView): # pragma: no cover
model = TrainingMicroCycle
template_name = 'trainingplan_delete.html'
@@ -2951,7 +2941,7 @@ class MicroCycleDelete(DeleteView):
return obj
class MesoCycleDelete(DeleteView):
class MesoCycleDelete(DeleteView): # pragma: no cover
model = TrainingMesoCycle
template_name = 'trainingplan_delete.html'
@@ -3014,7 +3004,7 @@ class MesoCycleDelete(DeleteView):
return obj
class MacroCycleDelete(DeleteView):
class MacroCycleDelete(DeleteView): # pragma: no cover
model = TrainingMacroCycle
template_name = 'trainingplan_delete.html'
@@ -3083,13 +3073,13 @@ def rower_trainingplan_execution_view(request,
if int(id)>0:
try:
plan = TrainingPlan.objects.get(id=id)
except TrainingPlan.DoesNotExist:
except TrainingPlan.DoesNotExist: # pragma: no cover
raise Http404("Training Plan Does Not Exist")
if not is_coach_user(request.user,plan.manager.user):
if not is_coach_user(request.user,plan.manager.user): # pragma: no cover
if request.user.rower not in plan.rowers.all():
raise PermissionDenied("Access denied")
if not startdate or not enddate:
if not startdate or not enddate: # pragma: no cover
if int(id)>0:
startdate = plan.startdate
enddate = plan.enddate
@@ -3101,12 +3091,12 @@ def rower_trainingplan_execution_view(request,
if int(id)>0:
data,message = get_execution_report(r,startdate,enddate,plan=plan)
else:
else: # pragma: no cover
data,message = get_execution_report(r,startdate,enddate)
if not data.empty:
script, div = interactive_planchart(data,startdate,enddate)
else:
else: # pragma: no cover
script = ''
div = ''
messages.error(request,'The plan does not cover this time range')
@@ -3131,7 +3121,7 @@ def rower_trainingplan_execution_view(request,
'name': 'Execution'
}
]
else:
else: # pragma: no cover
breadcrumbs = [
{
'url':reverse(plannedsessions_view,
@@ -3222,7 +3212,7 @@ def rower_trainingplan_view(request,
try:
thismicro = get_todays_micro(plan,thedate=startdate)
thismicroid = thismicro.pk
except AttributeError:
except AttributeError: # pragma: no cover
thismicroid = None
@@ -3240,7 +3230,7 @@ def rower_trainingplan_view(request,
}
)
class TrainingMacroCycleUpdate(UpdateView):
class TrainingMacroCycleUpdate(UpdateView): # pragma: no cover
model = TrainingMacroCycle
template_name = 'trainingplan_edit.html'
form_class = TrainingMacroCycleForm
@@ -3305,7 +3295,7 @@ class TrainingMacroCycleUpdate(UpdateView):
obj.save()
return obj
class TrainingMesoCycleUpdate(UpdateView):
class TrainingMesoCycleUpdate(UpdateView): # pragma: no cover
model = TrainingMesoCycle
template_name = 'trainingplan_edit.html'
form_class = TrainingMesoCycleForm
@@ -3379,7 +3369,7 @@ class TrainingMesoCycleUpdate(UpdateView):
obj.plan.save()
return obj
class TrainingMicroCycleUpdate(UpdateView):
class TrainingMicroCycleUpdate(UpdateView): # pragma: no cover
model = TrainingMicroCycle
template_name = 'trainingplan_edit.html'
form_class = TrainingMicroCycleForm
@@ -3458,7 +3448,7 @@ class TrainingMicroCycleUpdate(UpdateView):
obj.plan.save()
return obj
class TrainingPlanUpdate(UpdateView):
class TrainingPlanUpdate(UpdateView): # pragma: no cover
model = TrainingPlan
template_name = 'trainingplan_edit.html'
form_class = TrainingPlanForm
@@ -3517,7 +3507,7 @@ class TrainingPlanUpdate(UpdateView):
return obj
class TrainingTargetUpdate(UpdateView):
class TrainingTargetUpdate(UpdateView): # pragma: no cover
model = TrainingTarget
template_name = 'trainingplan_edit.html'
form_class = TrainingTargetForm
@@ -3573,7 +3563,7 @@ from rowers.utils import allsundays
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
@permission_required('cycle.change_cycle',fn=get_meso_by_pk,raise_exception=True)
def planmesocyclebyweek(request,id=0,userid=0):
def planmesocyclebyweek(request,id=0,userid=0): # pragma: no cover
cycle = get_object_or_404(TrainingMesoCycle,pk=id)
micros = TrainingMicroCycle.objects.filter(plan=cycle)
@@ -3623,7 +3613,7 @@ from rowers.utils import allmonths
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
@permission_required('cycle.change_cycle',fn=get_macro_by_pk,raise_exception=True)
def planmacrocyclebymonth(request,id=0,userid=0):
def planmacrocyclebymonth(request,id=0,userid=0): # pragma: no cover
cycle = get_object_or_404(TrainingMacroCycle,pk=id)
mesos = TrainingMesoCycle.objects.filter(plan=cycle)
+197 -197
View File
File diff suppressed because it is too large Load Diff