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) return HttpResponseRedirect(url)
# Get workout from C2 ID # Get workout from C2 ID
def get_workout(user,c2id): def get_workout(user,c2id,do_async=False):
r = Rower.objects.get(user=user) r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None): if (r.c2token == '') or (r.c2token is None):
s = "Token doesn't exist. Need to authorize" 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): except (TypeError,AttributeError,KeyError):
tokenexpirydate = None tokenexpirydate = None
if (token == '') or (token is None): if (token == '') or (token is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
raise NoTokenError("User has no token") 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) r = Rower.objects.get(user=user)
if (r.nktoken == '') or (r.nktoken is None): if (r.nktoken == '') or (r.nktoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
@@ -260,6 +260,27 @@ def get_workout(user,nkid):
'sessionIds': 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) authorizationstring = str('Bearer ' + r.nktoken)
headers = {'Authorization': authorizationstring, headers = {'Authorization': authorizationstring,
@@ -292,7 +313,6 @@ def get_workout(user,nkid):
before = before+timedelta(days=1) before = before+timedelta(days=1)
before = str(int(before.timestamp())*1000) before = str(int(before.timestamp())*1000)
after = str(int(after.timestamp())*1000) after = str(int(after.timestamp())*1000)
print(after)
url = NK_API_LOCATION+"api/v1/sessions/" url = NK_API_LOCATION+"api/v1/sessions/"
+3 -41
View File
@@ -50,7 +50,7 @@ def to_time(milliseconds):
def rdata(file,rower=rrower()): def rdata(file,rower=rrower()):
try: try:
res = rrdata(csvfile=file,rower=rower) res = rrdata(csvfile=file,rower=rower)
except (IOError, IndexError, EOFError,FileNotFoundError): except (IOError, IndexError, EOFError,FileNotFoundError): # pragma: no cover
try: try:
res = rrdata(csvfile=file+'.gz',rower=rower) res = rrdata(csvfile=file+'.gz',rower=rower)
except (IOError, IndexError, EOFError,FileNotFoundError): except (IOError, IndexError, EOFError,FileNotFoundError):
@@ -85,16 +85,7 @@ from rowers.tasks import (
) )
from rowers.utils import totaltime_sec_to_string from rowers.utils import totaltime_sec_to_string
# nog niet af def ps_dict_get_description(d,short=False): # pragma: no cover
def ps_dict_get_durationdistance(d):
sdict = ps_dict_order(d)
return sdict
def ps_dict_get_description(d,short=False):
sdict,totalmeters,totalseconds = ps_dict_order(d,short=short) sdict,totalmeters,totalseconds = ps_dict_order(d,short=short)
s = '' s = ''
for item in sdict: for item in sdict:
@@ -115,35 +106,6 @@ def ps_dict_get_description_html(d,short=False):
return s 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): def checkscores(r,macrocycles):
for m in macrocycles: for m in macrocycles:
createmesofillers(m) 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") mesos = TrainingMesoCycle.objects.filter(plan__in=macros).order_by("startdate")
micros = TrainingMicroCycle.objects.filter(plan__in=mesos).order_by("startdate") micros = TrainingMicroCycle.objects.filter(plan__in=mesos).order_by("startdate")
micros = micros.exclude(enddate__lte=startdate).exclude(startdate__gte=enddate) 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) plans = TrainingPlan.objects.filter(startdate__lte=startdate,enddate__gte=startdate)
plans2 = TrainingPlan.objects.filter(enddate__lte=enddate,startdate__lte=enddate) plans2 = TrainingPlan.objects.filter(enddate__lte=enddate,startdate__lte=enddate)
plans = plans | plans2 plans = plans | plans2
+2
View File
@@ -114,12 +114,14 @@ def get_rp3_workout_list(user):
executed_at executed_at
} }
}""" }"""
response = requests.post( response = requests.post(
url=graphql_url, url=graphql_url,
headers=headers, headers=headers,
json={'query': get_workouts_list} json={'query': get_workouts_list}
) )
return response return response
def get_rp3_workouts(rower,do_async=True): def get_rp3_workouts(rower,do_async=True):
+1 -1
View File
@@ -92,7 +92,7 @@ def get_runkeeper_workout_list(user):
return s return s
# Get workout summary data by Runkeeper ID # 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) r = Rower.objects.get(user=user)
if (r.runkeepertoken == '') or (r.runkeepertoken is None): if (r.runkeepertoken == '') or (r.runkeepertoken is None):
return custom_exception_handler(401,s) return custom_exception_handler(401,s)
+1 -1
View File
@@ -97,7 +97,7 @@ def get_sporttracks_workout_list(user):
return s return s
# Get workout summary data by SportTracks ID # 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) r = Rower.objects.get(user=user)
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
return custom_exception_handler(401,s) return custom_exception_handler(401,s)
+1 -1
View File
@@ -382,7 +382,7 @@ def async_get_workout(user,stravaid):
return job return job
# Get a Strava workout summary data and stroke data by ID # 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: try:
thetoken = strava_open(user) thetoken = strava_open(user)
except NoTokenError: except NoTokenError:
+32 -23
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 have_link = True
workout_download_details = pd.json_normalize(response.json()['data']['download']) 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 counter += 1
if counter>max_attempts: if counter>max_attempts: # pragma: no cover
have_link = True have_link = True
time.sleep(waittime) time.sleep(waittime)
if download_url == '': if download_url == '': # pragma: no cover
return 0 return 0
filename = 'media/RP3Import_'+str(rp3id)+'.csv' filename = 'media/RP3Import_'+str(rp3id)+'.csv'
res = requests.get(download_url,headers=headers) res = requests.get(download_url,headers=headers)
if not startdatetime:
if not startdatetime: # pragma: no cover
startdatetime = str(timezone.now()) 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 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) response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
if response.status_code != 200: if response.status_code != 200: # pragma: no cover
return 0 return 0
workoutid = response.json()['id'] 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): def handle_nk_async_workout(alldata,userid,nktoken,nkid,delaysec,defaulttimezone,debug=False,**kwargs):
time.sleep(delaysec) time.sleep(delaysec)
try:
data = alldata[nkid] data = alldata[nkid]
except KeyError: # pragma: no cover
data = alldata[int(nkid)]
params = { params = {
'sessionIds': nkid, 'sessionIds': nkid,
@@ -2992,7 +3001,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
try: try:
t = data['comments'].split('\n', 1)[0] t = data['comments'].split('\n', 1)[0]
title += t[:40] title += t[:40]
except: except: # pragma: no cover
title = '' title = ''
weightcategory = 'hwt' weightcategory = 'hwt'
@@ -3024,7 +3033,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
try: try:
notes = data['comments'] notes = data['comments']
name = notes[:40] name = notes[:40]
except (KeyError,TypeError): except (KeyError,TypeError): # pragma: no cover
notes = 'C2 Import Workout from {startdatetime}'.format(startdatetime=startdatetime) notes = 'C2 Import Workout from {startdatetime}'.format(startdatetime=startdatetime)
name = notes 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" url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
try: try:
s = requests.get(url,headers=headers) s = requests.get(url,headers=headers)
except ConnectionError: except ConnectionError: # pragma: no cover
return 0 return 0
if s.status_code != 200: if s.status_code != 200: # pragma: no cover
return 0 return 0
strokedata = pd.DataFrame.from_dict(s.json()['data']) 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) nr_rows = len(unixtime)
try: try: # pragma: no cover
latcoord = strokedata.loc[:,'lat'] latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon'] loncoord = strokedata.loc[:,'lon']
except: except:
@@ -3066,19 +3075,19 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
try: try:
strokelength = strokedata.loc[:,'strokelength'] strokelength = strokedata.loc[:,'strokelength']
except: except: # pragma: no cover
strokelength = np.zeros(nr_rows) strokelength = np.zeros(nr_rows)
dist2 = 0.1*strokedata.loc[:,'d'] dist2 = 0.1*strokedata.loc[:,'d']
try: try:
spm = strokedata.loc[:,'spm'] spm = strokedata.loc[:,'spm']
except KeyError: except KeyError: # pragma: no cover
spm = 0*dist2 spm = 0*dist2
try: try:
hr = strokedata.loc[:,'hr'] hr = strokedata.loc[:,'hr']
except KeyError: except KeyError: # pragma: no cover
hr = 0*spm hr = 0*spm
pace = strokedata.loc[:,'p']/10. pace = strokedata.loc[:,'p']/10.
@@ -3087,7 +3096,7 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
velo = 500./pace velo = 500./pace
power = 2.8*velo**3 power = 2.8*velo**3
if workouttype == 'bike': if workouttype == 'bike': # pragma: no cover
velo = 1000./pace velo = 1000./pace
df = pd.DataFrame({'TimeStamp (sec)':unixtime, 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) response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
if response.status_code != 200: if response.status_code != 200: # pragma: no cover
return 0 return 0
workoutid = response.json()['id'] workoutid = response.json()['id']
if debug: if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False) engine = create_engine(database_url_debug, echo=False)
else: else:
engine = create_engine(database_url, echo=False) 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(): with engine.connect() as conn, conn.begin():
result = conn.execute(query) result = conn.execute(query)
tdata = result.fetchall() tdata = result.fetchall()
if tdata: if tdata: # pragma: no cover
newc2id = tdata[0][0] newc2id = tdata[0][0]
conn.close() conn.close()
@@ -3176,16 +3185,16 @@ def handle_c2_async_workout(alldata,userid,c2token,c2id,delaysec,defaulttimezone
# summary # summary
if 'workout' in data: if 'workout' in data:
if 'splits' in data['workout']: if 'splits' in data['workout']: # pragma: no cover
splitdata = data['workout']['splits'] splitdata = data['workout']['splits']
elif 'intervals' in data['workout']: elif 'intervals' in data['workout']: # pragma: no cover
splitdata = data['workout']['intervals'] splitdata = data['workout']['intervals']
else: else: # pragma: no cover
splitdata = False splitdata = False
else: else:
splitdata = False splitdata = False
if splitdata: if splitdata: # pragma: no cover
summary,sa,results = summaryfromsplitdata(splitdata,data,csvfilename,workouttype=workouttype) summary,sa,results = summaryfromsplitdata(splitdata,data,csvfilename,workouttype=workouttype)
query = "UPDATE `rowers_workout` SET `summary` = '%s' WHERE `id` = %s" % (summary, workoutid) 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: try:
power = strokedata.loc[:,'power'] power = strokedata.loc[:,'power']
except KeyError: except KeyError: # pragma: no cover
power = 2.8*velo**3 power = 2.8*velo**3
#if power.std() == 0 and power.mean() == 0: #if power.std() == 0 and power.mean() == 0:
+1 -1
View File
@@ -33,7 +33,7 @@
{% for workout in workouts %} {% for workout in workouts %}
<tr> <tr>
<td> <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>{{ workout|lookuplong:'name' }}</td>
<td class="block" style="width:auto">{{ workout|lookuplong:'starttime' }}</td> <td class="block" style="width:auto">{{ workout|lookuplong:'starttime' }}</td>
<td>{{ workout|lookup:'duration' }} </td> <td>{{ workout|lookup:'duration' }} </td>
+57 -1
View File
@@ -98,7 +98,6 @@ def mocked_myqueue(*args, **kwargs):
return Job() return Job()
def mock_c2open(*args, **kwargs): def mock_c2open(*args, **kwargs):
print('mock')
return('aap') return('aap')
def mocked_session(*args, **kwargs): def mocked_session(*args, **kwargs):
@@ -123,6 +122,16 @@ def mocked_session(*args, **kwargs):
def json(self): def json(self):
return self.json_data 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() return MockEngine()
def mocked_sqlalchemy(*args, **kwargs): 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: with open('rowers/tests/testdata/nk_list.json','r') as infile:
nkworkoutlist = json.load(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: with open('rowers/tests/testdata/example-session-strokes-with-impeller-data.json','r') as infile:
nkimpellerstrokedata = json.load(infile) nkimpellerstrokedata = json.load(infile)
@@ -781,6 +795,15 @@ def mocked_requests(*args, **kwargs):
def json(self): def json(self):
return self.json_data 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: class MockHeaderResponse:
def __init__(self, header_data, status_code): def __init__(self, header_data, status_code):
@@ -832,6 +855,9 @@ def mocked_requests(*args, **kwargs):
if 'garmin' in args: if 'garmin' in args:
return MockOAuth1Session() return MockOAuth1Session()
if 'url' in kwargs:
if 'rp3' in kwargs['url']:
args = [kwargs['url']]
if not args: if not args:
return MockSession() return MockSession()
@@ -845,6 +871,7 @@ def mocked_requests(*args, **kwargs):
uatester = re.compile('.*?mapmyfitness\.com') uatester = re.compile('.*?mapmyfitness\.com')
tptester = re.compile('.*?trainingpeaks\.com') tptester = re.compile('.*?trainingpeaks\.com')
nktester = re.compile('.*?nkrowlink\.com') nktester = re.compile('.*?nkrowlink\.com')
rp3tester = re.compile('.*?rp3rowing-app\.com')
garmintester = re.compile('.*?garmin\.com') garmintester = re.compile('.*?garmin\.com')
c2importregex = '.*?concept2.com\/api\/users\/me\/results\/\d+' c2importregex = '.*?concept2.com\/api\/users\/me\/results\/\d+'
@@ -865,6 +892,8 @@ def mocked_requests(*args, **kwargs):
nkstrokesregex = '.*?nkrowlink\.com\/api\/v1\/sessions\/strokes' nkstrokesregex = '.*?nkrowlink\.com\/api\/v1\/sessions\/strokes'
nkstrokestester = re.compile(nkstrokesregex) nkstrokestester = re.compile(nkstrokesregex)
rp3graphregex = '.*?rp3rowing-app\.com\/graphql'
rp3graphtester = re.compile(rp3graphregex)
stravaathleteregex = '.*?strava\.com\/api\/v3\/athlete$' stravaathleteregex = '.*?strava\.com\/api\/v3\/athlete$'
stravaathletetester = re.compile(stravaathleteregex) stravaathletetester = re.compile(stravaathleteregex)
@@ -1052,6 +1081,33 @@ def mocked_requests(*args, **kwargs):
return MockResponse(nkimpellerworkoutlist,200) return MockResponse(nkimpellerworkoutlist,200)
return MockResponse(nkworkoutlist,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]): if stravatester.match(args[0]):
+194 -5
View File
@@ -14,6 +14,9 @@ import rowers
from rowers import dataprep from rowers import dataprep
from rowers import tasks from rowers import tasks
from rowers import c2stuff from rowers import c2stuff
from rowers import stravastuff
import urllib
import json
@pytest.mark.django_db @pytest.mark.django_db
@override_settings(TESTING=True) @override_settings(TESTING=True)
@@ -292,6 +295,20 @@ class C2Objects(DjangoTestCase):
res = add_workout_from_strokedata(self.u,1,data,strokedata,source='c2') 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) @override_settings(TESTING=True)
class C2ObjectsTokenExpired(DjangoTestCase): class C2ObjectsTokenExpired(DjangoTestCase):
def setUp(self): def setUp(self):
@@ -447,6 +464,11 @@ class NKObjects(DjangoTestCase):
) )
self.assertTrue(res>0) 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.get', side_effect=mocked_requests)
@patch('rowers.nkstuff.requests.post', 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) w = Workout.objects.get(id=1)
#self.assertTrue(w.impeller) #self.assertTrue(w.impeller)
#@pytest.mark.django_db #@pytest.mark.django_db
@override_settings(TESTING=True) @override_settings(TESTING=True)
class StravaObjects(DjangoTestCase): class RP3Objects(DjangoTestCase):
def setUp(self): def setUp(self):
self.c = Client() self.c = Client()
self.u = User.objects.create_user('john', self.u = User.objects.create_user('john',
@@ -526,9 +547,9 @@ class StravaObjects(DjangoTestCase):
gdproptindate=timezone.now() gdproptindate=timezone.now()
) )
self.r.stravatoken = '12' self.r.rp3token = '12'
self.r.stravarefreshtoken = '123' self.r.rp3refreshtoken = '123'
self.r.stravatokenexpirydate = arrow.get(datetime.datetime.now()-datetime.timedelta(days=1)).datetime self.r.rp3tokenexpirydate = arrow.get(datetime.datetime.now()-datetime.timedelta(days=1)).datetime
self.r.save() self.r.save()
self.c.login(username='john',password='koeinsloot') self.c.login(username='john',password='koeinsloot')
@@ -565,6 +586,174 @@ class StravaObjects(DjangoTestCase):
csvfilename=filename 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.get', side_effect=mocked_requests)
@patch('rowers.stravastuff.requests.post', 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() nu = datetime.datetime.now()
from rowers.rower_rules import is_workout_user 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 #@pytest.mark.django_db
class WorkoutTests(TestCase): class WorkoutTests(TestCase):
+362 -9
View File
@@ -182,9 +182,8 @@ class TrainingPlanTest(TestCase):
# status_code=302,target_status_code=200) # status_code=302,target_status_code=200)
@override_settings(TESTING=True) @override_settings(TESTING=True)
class SessionLinkTest(TestCase): class SessionTemplateTest(TestCase):
def setUp(self): def setUp(self):
self.u = UserFactory() self.u = UserFactory()
@@ -196,6 +195,9 @@ class SessionLinkTest(TestCase):
self.c = Client() self.c = Client()
self.user_workouts = WorkoutFactory.create_batch(5, user=self.r) 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.factory = RequestFactory()
self.password = faker.word() self.password = faker.word()
self.u.set_password(self.password) self.u.set_password(self.password)
@@ -227,6 +229,109 @@ class SessionLinkTest(TestCase):
result = plannedsessions.add_rower_session(self.r,ps) 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): def tearDown(self):
for workout in self.user_workouts: for workout in self.user_workouts:
try: try:
@@ -241,11 +346,12 @@ class SessionLinkTest(TestCase):
w = self.user_workouts[0] w = self.user_workouts[0]
startdatetime = w.startdatetime startdatetime = arrow.get(w.date).datetime
startdate = (startdatetime-datetime.timedelta(days=1)).date() startdate = (startdatetime-datetime.timedelta(days=1)).date()
enddate = (startdatetime+datetime.timedelta(days=1)).date() enddate = (startdatetime+datetime.timedelta(days=1)).date()
url = '/rowers/sessions/' url = '/rowers/sessions/'
response = self.c.get(url) response = self.c.get(url)
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
@@ -286,8 +392,6 @@ class SessionLinkTest(TestCase):
enddate = enddate.strftime("%Y-%m-%d"), enddate = enddate.strftime("%Y-%m-%d"),
) )
workoutdata = {} workoutdata = {}
workoutdata['initial'] = [] workoutdata['initial'] = []
@@ -298,6 +402,7 @@ class SessionLinkTest(TestCase):
workoutdata['choices'] = tuple(choices) workoutdata['choices'] = tuple(choices)
form = PlannedSessionSelectForm(plannedsessionstuple,post_data) form = PlannedSessionSelectForm(plannedsessionstuple,post_data)
self.assertTrue(form.is_valid()) self.assertTrue(form.is_valid())
@@ -1335,6 +1440,107 @@ class PlannedSessionsView(TestCase):
self.ps_trimp.save() self.ps_trimp.save()
added = plannedsessions.add_rower_session(self.u.rower,self.ps_trimp) added = plannedsessions.add_rower_session(self.u.rower,self.ps_trimp)
added = plannedsessions.add_team_session(self.team,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): def tearDown(self):
try: try:
@@ -1359,6 +1565,53 @@ class PlannedSessionsView(TestCase):
# expected_url=expected_url, # expected_url=expected_url,
# status_code=302,target_status_code=200) # 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): def test_multiclone_view(self):
login = self.c.login(username=self.u.username, password=self.password) login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login) self.assertTrue(login)
@@ -1400,6 +1653,29 @@ class PlannedSessionsView(TestCase):
response = self.c.post(url,formdata,follow=True) response = self.c.post(url,formdata,follow=True)
self.assertEqual(response.status_code,200) 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): def test_multicreate_view(self):
login = self.c.login(username=self.u.username, password=self.password) login = self.c.login(username=self.u.username, password=self.password)
@@ -1441,6 +1717,7 @@ class PlannedSessionsView(TestCase):
form_data = { form_data = {
'team':[self.team.id], 'team':[self.team.id],
'members': [self.r.id],
'startdate': self.w1.startdatetime.date(), 'startdate': self.w1.startdatetime.date(),
'enddate': (self.w1.startdatetime+datetime.timedelta(days=5)).date(), 'enddate': (self.w1.startdatetime+datetime.timedelta(days=5)).date(),
'preferreddate': self.w1.startdatetime.date(), 'preferreddate': self.w1.startdatetime.date(),
@@ -1466,6 +1743,25 @@ class PlannedSessionsView(TestCase):
response = self.c.post(url,form_data,follow=True) response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200) 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): def test_teamedit_view(self):
login = self.c.login(username=self.u.username, password=self.password) 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) login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login) self.assertTrue(login)
url = '/rowers/sessions/{id}/edit/'.format( url = reverse('plannedsession_edit_view',kwargs={'id':self.ps_time.id})
id=self.ps_time.id,
)
response = self.c.get(url) response = self.c.get(url)
self.assertEqual(response.status_code,200) self.assertEqual(response.status_code,200)
@@ -1658,7 +1952,7 @@ class PlannedSessionsView(TestCase):
self.assertTrue(form.is_valid()) 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) self.assertEqual(response.status_code,200)
@@ -1706,3 +2000,62 @@ class PlannedSessionsView(TestCase):
response = self.c.post(url,follow=True) response = self.c.post(url,follow=True)
self.assertEqual(response.status_code,200) 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 .statements import *
from rowers.mytypes import rowtypes from rowers.mytypes import rowtypes
from rowers.utils import allmonths,allsundays
nu = datetime.datetime.now() nu = datetime.datetime.now()
@@ -12,8 +13,11 @@ nu = datetime.datetime.now()
# interactive plots # interactive plots
from rowers import interactiveplots from rowers import interactiveplots
from rowers import dataprep from rowers import dataprep
from rowers import plannedsessions
from rowers.views.workoutviews import get_video_id from rowers.views.workoutviews import get_video_id
class OtherUnitTests(TestCase): class OtherUnitTests(TestCase):
def test_get_video_id(self): def test_get_video_id(self):
url1 = 'http://youtu.be/_lOT2p_FCvA' url1 = 'http://youtu.be/_lOT2p_FCvA'
@@ -49,6 +53,249 @@ class OtherUnitTests(TestCase):
self.assertEqual(result,expected) 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): class DataPrepTests(TestCase):
def setUp(self): def setUp(self):
self.u = UserFactory() 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 return s
# Get workout summary data by Underarmour ID # 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) r = Rower.objects.get(user=user)
if (r.underarmourtoken == '') or (r.underarmourtoken is None): if (r.underarmourtoken == '') or (r.underarmourtoken is None):
return custom_exception_handler(401,s) return custom_exception_handler(401,s)
+9 -4
View File
@@ -496,6 +496,7 @@ urlpatterns = [
name='workout_getrp3importview'), name='workout_getrp3importview'),
re_path(r'^workout/rp3import/all/$',views.workout_getrp3workout_all,name='workout_getrp3workout_all'), 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+)/$',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/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/stravaimport/next/$',views.workout_getstravaworkout_next,name='workout_getstravaworkout_next'),
re_path(r'^workout/sporttracksimport/$',views.workout_sporttracksimport_view,name='workout_sporttracksimport_view'), re_path(r'^workout/sporttracksimport/$',views.workout_sporttracksimport_view,name='workout_sporttracksimport_view'),
@@ -760,16 +761,20 @@ urlpatterns = [
name='plannedsession_edit_view'), name='plannedsession_edit_view'),
re_path(r'^sessions/(?P<id>\d+)/templateedit/',views.plannedsession_templateedit_view, re_path(r'^sessions/(?P<id>\d+)/templateedit/',views.plannedsession_templateedit_view,
name='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/$', re_path(r'^sessions/(?P<id>\d+)/compare/$',
views.plannedsession_compare_view, views.plannedsession_compare_view,
name='plannedsession_compare_view'), name='plannedsession_compare_view'),
re_path(r'^sessions/(?P<id>\d+)/compare/user/(?P<userid>\d+)/$', re_path(r'^sessions/(?P<id>\d+)/compare/user/(?P<userid>\d+)/$',
views.plannedsession_compare_view, views.plannedsession_compare_view,
name='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+)/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), name='plannedsession_edit_view'),
re_path(r'^sessions/(?P<id>\d+)/clone/team/$',views.plannedsession_teamclone_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<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)/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), re_path(r'^sessions/(?P<psid>\d+)/detach/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.plannedsession_detach_view),
+143 -133
View File
@@ -7,7 +7,7 @@ from rowers.views.statements import *
import numpy import numpy
def default(o): def default(o): # pragma: no cover
if isinstance(o, numpy.int64): return int(o) if isinstance(o, numpy.int64): return int(o)
raise TypeError raise TypeError
@@ -21,7 +21,7 @@ def workout_tp_upload_view(request,id=0):
res = -1 res = -1
try: try:
thetoken = tp_open(r.user) thetoken = tp_open(r.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/tpauthorize/") return HttpResponseRedirect("/rowers/me/tpauthorize/")
# ready to upload. Hurray # ready to upload. Hurray
@@ -35,7 +35,7 @@ def workout_tp_upload_view(request,id=0):
r.tptoken,tcxfile, r.tptoken,tcxfile,
name=w.name name=w.name
) )
if res == 0: if res == 0: # pragma: no cover
message = "Upload to TrainingPeaks failed with status code "+str(status_code)+": "+reason message = "Upload to TrainingPeaks failed with status code "+str(status_code)+": "+reason
try: try:
os.remove(tcxfile) os.remove(tcxfile)
@@ -50,7 +50,7 @@ def workout_tp_upload_view(request,id=0):
os.remove(tcxfile) os.remove(tcxfile)
messages.info(request,'Uploaded to TrainingPeaks') messages.info(request,'Uploaded to TrainingPeaks')
else: # no tcxfile else: # pragma: no cover # no tcxfile
message = "Upload to TrainingPeaks failed" message = "Upload to TrainingPeaks failed"
w.uploadedtotp = -1 w.uploadedtotp = -1
w.save() w.save()
@@ -74,10 +74,10 @@ def workout_strava_upload_view(request,id=0):
try: try:
thetoken = strava_open(request.user) thetoken = strava_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/stravaauthorize/") 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" s = "Token doesn't exist. Need to authorize"
return HttpResponseRedirect("/rowers/me/stravaauthorize/") return HttpResponseRedirect("/rowers/me/stravaauthorize/")
else: else:
@@ -99,9 +99,9 @@ def workout_strava_upload_view(request,id=0):
if activity_type == 'match': if activity_type == 'match':
try: try:
activity_type = mytypes.stravamapping[w.workouttype] activity_type = mytypes.stravamapping[w.workouttype]
except KeyError: except KeyError: # pragma: no cover
activity_type = 'Ride' activity_type = 'Ride'
else: else: # pragma: no cover
try: try:
activity_type = mytypes.stravamapping[w.workouttype] activity_type = mytypes.stravamapping[w.workouttype]
except KeyError: except KeyError:
@@ -112,7 +112,7 @@ def workout_strava_upload_view(request,id=0):
r.stravatoken, r.stravatoken,
description=newnotes, description=newnotes,
activity_type=activity_type,quick=False) activity_type=activity_type,quick=False)
if res==0: if res==0: # pragma: no cover
messages.error(request,mes) messages.error(request,mes)
w.uploadedtostrava = -1 w.uploadedtostrava = -1
w.save() w.save()
@@ -132,13 +132,13 @@ def workout_strava_upload_view(request,id=0):
w.save() w.save()
try: try:
os.remove(tcxfile) os.remove(tcxfile)
except WindowsError: except WindowsError: # pragma: no cover
pass pass
url = reverse('workout_edit_view',kwargs={'id':w.id}) url = reverse('workout_edit_view',kwargs={'id':w.id})
messages.info(request,mes) messages.info(request,mes)
except: except: # pragma: no cover
with open("media/stravaerrors.log","a") as errorlog: with open("media/stravaerrors.log","a") as errorlog:
errorstring = str(sys.exc_info()[0]) errorstring = str(sys.exc_info()[0])
timestr = strftime("%Y%m%d-%H%M%S") 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") errorlog.write("views.py line 826\r\n")
message = 'Error: '+errorstring message = 'Error: '+errorstring
messages.error(request,message) messages.error(request,message)
else: # No tcxfile else: # pragma: no cover # No tcxfile
message = "Strava Data error "+tcxmessg message = "Strava Data error "+tcxmessg
messages.error(request,message) messages.error(request,message)
w.uploadedtostrava = -1 w.uploadedtostrava = -1
@@ -164,7 +164,7 @@ def workout_strava_upload_view(request,id=0):
} }
) )
response = HttpResponseRedirect(url) response = HttpResponseRedirect(url)
except ActivityUploadFailed as e: except ActivityUploadFailed as e: # pragma: no cover
message = "Strava Upload error: %s" % e message = "Strava Upload error: %s" % e
messages.error(request,message) messages.error(request,message)
w.uploadedtostrava = -1 w.uploadedtostrava = -1
@@ -188,10 +188,10 @@ def workout_c2_upload_view(request,id=0):
try: try:
message,c2id = c2stuff.workout_c2_upload(request.user,w) message,c2id = c2stuff.workout_c2_upload(request.user,w)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
if message and c2id <=0: if message and c2id <=0: # pragma: no cover
messages.error(request,message) messages.error(request,message)
elif message: elif message:
messages.info(request,message) messages.info(request,message)
@@ -216,14 +216,14 @@ def workout_runkeeper_upload_view(request,id=0):
try: try:
thetoken = runkeeper_open(r.user) thetoken = runkeeper_open(r.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") return HttpResponseRedirect("/rowers/me/runkeeperauthorize/")
# ready to upload. Hurray # ready to upload. Hurray
data = runkeeperstuff.createrunkeeperworkoutdata(w) data = runkeeperstuff.createrunkeeperworkoutdata(w)
if not data: if not data: # pragma: no cover
message = "Data error" message = "Data error"
messages.error(request,message) messages.error(request,message)
url = reverse(r.defaultlandingpage, 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)) response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
# check for duplicate error first # check for duplicate error first
if (response.status_code == 409 ): if (response.status_code == 409 ): # pragma: no cover # pragma: no cover
message = "Duplicate error" message = "Duplicate error"
messages.error(request,message) messages.error(request,message)
w.uploadedtorunkeeper = -1 w.uploadedtorunkeeper = -1
@@ -255,7 +255,7 @@ def workout_runkeeper_upload_view(request,id=0):
kwargs={'id':encoder.encode_hex(w.id)}) kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else: # pragma: no cover
s = response s = response
message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text) message = "Something went wrong in workout_runkeeper_upload_view: %s - %s" % (s.reason,s.text)
messages.error(request,message) messages.error(request,message)
@@ -264,9 +264,9 @@ def workout_runkeeper_upload_view(request,id=0):
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
kwargs = { kwargs = {
'id':encoder.encode_hex(w.id), 'id':encoder.encode_hex(w.id),
}) }) # pragma: no cover
return HttpResponseRedirect(url) return HttpResponseRedirect(url) # pragma: no cover
# Upload workout to Underarmour # Upload workout to Underarmour
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True) @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: try:
thetoken = underarmour_open(r.user) thetoken = underarmour_open(r.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/underarmourauthorize/") return HttpResponseRedirect("/rowers/me/underarmourauthorize/")
# ready to upload. Hurray # ready to upload. Hurray
data = underarmourstuff.createunderarmourworkoutdata(w) data = underarmourstuff.createunderarmourworkoutdata(w)
if not data: if not data: # pragma: no cover
message = "Data error" message = "Data error"
messages.error(request,message) messages.error(request,message)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
@@ -305,7 +305,7 @@ def workout_underarmour_upload_view(request,id=0):
# check for duplicate error first # check for duplicate error first
if (response.status_code == 409 ): if (response.status_code == 409 ): # pragma: no cover # pragma: no cover
message = "Duplicate error" message = "Duplicate error"
messages.error(request,message) messages.error(request,message)
w.uploadedtounderarmour = -1 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)}) url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else: # pragma: no cover
s = response s = response
message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason message = "Something went wrong in workout_underarmour_upload_view: %s " % s.reason
messages.error(request,message) messages.error(request,message)
@@ -325,9 +325,9 @@ def workout_underarmour_upload_view(request,id=0):
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
kwargs = { kwargs = {
'id':encoder.encode_hex(w.id), 'id':encoder.encode_hex(w.id),
}) }) # pragma: no cover
return HttpResponseRedirect(url) return HttpResponseRedirect(url) # pragma: no cover
# Upload workout to SportTracks # Upload workout to SportTracks
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid) @permission_required('workout.change_workout',fn=get_workout_by_opaqueid)
@@ -339,14 +339,14 @@ def workout_sporttracks_upload_view(request,id=0):
try: try:
thetoken = sporttracks_open(r.user) thetoken = sporttracks_open(r.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
data = sporttracksstuff.createsporttracksworkoutdata(w) data = sporttracksstuff.createsporttracksworkoutdata(w)
if not data: if not data: # pragma: no cover
message = "Data error" message = "Data error"
messages.error(request,message) messages.error(request,message)
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
@@ -365,7 +365,7 @@ def workout_sporttracks_upload_view(request,id=0):
# check for duplicate error first # check for duplicate error first
if (response.status_code == 409 ): if (response.status_code == 409 ): # pragma: no cover
message = "Duplicate error" message = "Duplicate error"
messages.error(request,message) messages.error(request,message)
w.uploadedtosporttracks = -1 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)}) url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else: # pragma: no cover
s = response s = response
message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason message = "Something went wrong in workout_sporttracks_upload_view: %s" % s.reason
messages.error(request,message) messages.error(request,message)
@@ -388,14 +388,14 @@ def workout_sporttracks_upload_view(request,id=0):
url = reverse(r.defaultlandingpage, url = reverse(r.defaultlandingpage,
kwargs = { kwargs = {
'id':encoder.encode_hex(w.id), 'id':encoder.encode_hex(w.id),
}) }) # pragma: no cover
return HttpResponseRedirect(url) return HttpResponseRedirect(url) # pragma: no cover
# NK LiNK authorization # NK LiNK authorization
@login_required() @login_required()
def rower_nk_authorize(request): def rower_nk_authorize(request): # pragma: no cover
state = str(uuid4()) state = str(uuid4())
scope = "read" scope = "read"
params = { params = {
@@ -415,7 +415,7 @@ def rower_nk_authorize(request):
# Concept2 authorization # Concept2 authorization
@login_required() @login_required()
def rower_c2_authorize(request): def rower_c2_authorize(request): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
@@ -430,7 +430,7 @@ def rower_c2_authorize(request):
# Garmin authorization # Garmin authorization
@login_required() @login_required()
def rower_garmin_authorize(request): def rower_garmin_authorize(request): # pragma: no cover
authorization_url,token,secret = garmin_stuff.garmin_authorize() authorization_url,token,secret = garmin_stuff.garmin_authorize()
request.session['garmin_owner_key'] = token request.session['garmin_owner_key'] = token
request.session['garmin_owner_secret'] = secret request.session['garmin_owner_secret'] = secret
@@ -438,7 +438,7 @@ def rower_garmin_authorize(request):
# Strava Authorization # Strava Authorization
@login_required() @login_required()
def rower_strava_authorize(request): def rower_strava_authorize(request): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
@@ -455,7 +455,7 @@ def rower_strava_authorize(request):
# Polar Authorization # Polar Authorization
@login_required() @login_required()
def rower_polar_authorize(request): def rower_polar_authorize(request): # pragma: no cover
state = str(uuid4()) state = str(uuid4())
@@ -473,7 +473,7 @@ def rower_polar_authorize(request):
# Runkeeper authorization # Runkeeper authorization
@login_required() @login_required()
def rower_runkeeper_authorize(request): def rower_runkeeper_authorize(request): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
@@ -491,7 +491,7 @@ def rower_runkeeper_authorize(request):
# SportTracks Authorization # SportTracks Authorization
@login_required() @login_required()
def rower_sporttracks_authorize(request): def rower_sporttracks_authorize(request): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
@@ -509,7 +509,7 @@ def rower_sporttracks_authorize(request):
# Underarmour Authorization # Underarmour Authorization
@login_required() @login_required()
def rower_underarmour_authorize(request): def rower_underarmour_authorize(request): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
@@ -526,7 +526,7 @@ def rower_underarmour_authorize(request):
# Underarmour Authorization # Underarmour Authorization
@login_required() @login_required()
def rower_rp3_authorize(request): def rower_rp3_authorize(request): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # Save it for use later to prevent xsrf attacks
@@ -541,7 +541,7 @@ def rower_rp3_authorize(request):
# Underarmour Authorization # Underarmour Authorization
@login_required() @login_required()
def rower_tp_authorize(request): def rower_tp_authorize(request): # pragma: no cover
# Generate a random string for the state parameter # Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks # 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" successmessage = "Tokens refreshed. Good to go"
messages.info(request,successmessage) messages.info(request,successmessage)
else: else: # pragma: no cover
message = "Something went wrong (refreshing tokens). Please reauthorize:" message = "Something went wrong (refreshing tokens). Please reauthorize:"
messages.error(request,message) messages.error(request,message)
@@ -677,7 +677,7 @@ def rower_process_callback(request):
try: try:
code = request.GET['code'] code = request.GET['code']
res = c2stuff.get_token(code) res = c2stuff.get_token(code)
except MultiValueDictKeyError: except MultiValueDictKeyError: # pragma: no cover
message = "The resource owner or authorization server denied the request" message = "The resource owner or authorization server denied the request"
messages.error(request,message) messages.error(request,message)
@@ -686,7 +686,7 @@ def rower_process_callback(request):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
access_token = res[0] access_token = res[0]
if access_token == 0: if access_token == 0: # pragma: no cover
message = res[1] message = res[1]
message += ' Contact info@rowsandall.com if this behavior persists.' message += ' Contact info@rowsandall.com if this behavior persists.'
messages.error(request,message) messages.error(request,message)
@@ -716,12 +716,12 @@ def rower_process_callback(request):
# dummy # dummy
@login_required() @login_required()
def rower_process_twittercallback(request): def rower_process_twittercallback(request): # pragma: no cover
return "dummy" return "dummy"
# Process Polar Callback # Process Polar Callback
@login_required() @login_required()
def rower_process_polarcallback(request): def rower_process_polarcallback(request): # pragma: no cover
try: try:
code = request.GET['code'] code = request.GET['code']
except MultiValueDictKeyError: except MultiValueDictKeyError:
@@ -754,7 +754,7 @@ def rower_process_polarcallback(request):
# process Garmin callback # process Garmin callback
@login_required() @login_required()
def rower_process_garmincallback(request): def rower_process_garmincallback(request): # pragma: no cover
r = getrower(request.user) r = getrower(request.user)
absoluteurl = request.build_absolute_uri() absoluteurl = request.build_absolute_uri()
@@ -775,7 +775,7 @@ def rower_process_garmincallback(request):
# Process NK Callback # Process NK Callback
@login_required() @login_required()
def rower_process_nkcallback(request): def rower_process_nkcallback(request): # pragma: no cover
# do stuff # do stuff
try: try:
code = request.GET.get('code',None) code = request.GET.get('code',None)
@@ -819,7 +819,7 @@ def rower_process_nkcallback(request):
def workout_getnkworkout_all(request): def workout_getnkworkout_all(request):
try: try:
thetoken = nk_open(request.user) thetoken = nk_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("rower_nk_authorize") return HttpResponseRedirect("rower_nk_authorize")
r = getrequestrower(request) r = getrequestrower(request)
@@ -828,7 +828,7 @@ def workout_getnkworkout_all(request):
if result: if result:
messages.info(request,"Your NK workouts will be imported in the coming few minutes") 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") messages.error(request,"Your NK workouts import failed")
url = reverse('workouts_view') url = reverse('workouts_view')
@@ -840,12 +840,12 @@ def workout_nkimport_view(request,userid=0,after=0,before=0):
r = getrequestrower(request,userid=userid) r = getrequestrower(request,userid=userid)
try: try:
thetoken = nk_open(request.user) thetoken = nk_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/nkauthorize/") return HttpResponseRedirect("/rowers/me/nkauthorize/")
res = nkstuff.get_nk_workout_list(request.user,before=before,after=after) 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): if (res.status_code == 401):
r = getrower(request.user) r = getrower(request.user)
if (r.stravatoken == '') or (r.stravatoken is None): 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: with open('nkblocked.json','r') as nkblocked:
jsondata = json.load(nkblocked) jsondata = json.load(nkblocked)
parkedids = jsondata['ids'] parkedids = jsondata['ids']
except FileNotFoundError: except FileNotFoundError: # pragma: no cover
pass pass
knownnkids = uniqify(knownnkids+tombstones+parkedids) knownnkids = uniqify(knownnkids+tombstones+parkedids)
@@ -893,7 +893,7 @@ def workout_nkimport_view(request,userid=0,after=0,before=0):
n = item['name'] n = item['name']
if i in knownnkids: if i in knownnkids:
nnn = '' nnn = ''
else: else: # pragma: no cover
nnn = 'NEW' nnn = 'NEW'
ttot = str(datetime.timedelta(seconds=int(float(item['elapsedTime'])/1000.))) ttot = str(datetime.timedelta(seconds=int(float(item['elapsedTime'])/1000.)))
s = arrow.get(item['startTime'],tzinfo=r.defaulttimezone).format(arrow.FORMAT_RFC850) s = arrow.get(item['startTime'],tzinfo=r.defaulttimezone).format(arrow.FORMAT_RFC850)
@@ -931,10 +931,10 @@ def rower_process_stravacallback(request):
try: try:
code = request.GET['code'] code = request.GET['code']
scope = request.GET['scope'] scope = request.GET['scope']
except MultiValueDictKeyError: except MultiValueDictKeyError:# pragma: no cover
try: try:
message = request.GET['error'] message = request.GET['error']
except MultiValueDictKeyError: except MultiValueDictKeyError:# pragma: no cover
message = "access error" message = "access error"
messages.error(request,message) messages.error(request,message)
@@ -964,7 +964,7 @@ def rower_process_stravacallback(request):
messages.info(request,successmessage) messages.info(request,successmessage)
url = reverse('rower_exportsettings_view') url = reverse('rower_exportsettings_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:# pragma: no cover
message = "Something went wrong with the Strava authorization" message = "Something went wrong with the Strava authorization"
messages.error(request,message) messages.error(request,message)
url = reverse('rower_exportsettings_view') url = reverse('rower_exportsettings_view')
@@ -979,7 +979,7 @@ def rower_process_runkeepercallback(request):
res = runkeeperstuff.get_token(code) res = runkeeperstuff.get_token(code)
access_token = res[0] access_token = res[0]
if access_token == 0: if access_token == 0:# pragma: no cover
messages.error(request,"Something went wrong importing the token") messages.error(request,"Something went wrong importing the token")
url = reverse('workouts_view') url = reverse('workouts_view')
@@ -1004,7 +1004,7 @@ def rower_process_runkeepercallback(request):
def rower_process_sporttrackscallback(request): def rower_process_sporttrackscallback(request):
try: try:
code = request.GET['code'] code = request.GET['code']
except: except:# pragma: no cover
messages.error(request,"Sorry, something went wrong.") messages.error(request,"Sorry, something went wrong.")
url = reverse('rower_exportsettings_view') url = reverse('rower_exportsettings_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -1058,7 +1058,7 @@ def rower_process_underarmourcallback(request):
# Process RP3 callback # Process RP3 callback
@login_required() @login_required()
def rower_process_rp3callback(request): def rower_process_rp3callback(request): # pragma: no cover
try: try:
code = request.GET['code'] code = request.GET['code']
except MultiValueDictKeyError: except MultiValueDictKeyError:
@@ -1095,7 +1095,7 @@ def rower_process_rp3callback(request):
def rower_process_tpcallback(request): def rower_process_tpcallback(request):
try: try:
code = request.GET['code'] code = request.GET['code']
except MultiValueDictKeyError: except MultiValueDictKeyError: # pragma: no cover
messages.error(request,"There was an error with the callback") messages.error(request,"There was an error with the callback")
try: try:
errormessage = request.GET['error'] errormessage = request.GET['error']
@@ -1128,7 +1128,7 @@ def rower_process_tpcallback(request):
# Process Own API callback - for API testing purposes # Process Own API callback - for API testing purposes
@login_required() @login_required()
def rower_process_testcallback(request): def rower_process_testcallback(request): # pragma: no cover
code = request.GET['code'] code = request.GET['code']
res = ownapistuff.get_token(code) res = ownapistuff.get_token(code)
@@ -1153,13 +1153,13 @@ def workout_rp3import_view(request,userid=0):
try: try:
thetoken = rp3stuff.rp3_open(request.user) thetoken = rp3stuff.rp3_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
url = reverse('rower_rp3_authorize') url = reverse('rower_rp3_authorize')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
res = rp3stuff.get_rp3_workout_list(request.user) 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): if (res.status_code == 401):
r = getrower(request.user) r = getrower(request.user)
if (r.stravatoken == '') or (r.stravatoken is None): 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(): for key,data in workouts_list.iterrows():
i = data['id'] i = data['id']
if i in knownrp3ids: if i in knownrp3ids: # pragma: no cover
nnn = '' nnn = ''
else: else:
nnn = 'NEW' 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") # messages.info(request,"You cannot import other people's workouts from Strava")
try: try:
thetoken = strava_open(request.user) thetoken = strava_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/stravaauthorize/") return HttpResponseRedirect("/rowers/me/stravaauthorize/")
res = stravastuff.get_strava_workout_list(request.user) 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): if (res.status_code == 401):
r = getrower(request.user) r = getrower(request.user)
if (r.stravatoken == '') or (r.stravatoken is None): 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) wfailed = Workout.objects.filter(user=r,uploadedtostrava=-1)
for w in wfailed: for w in wfailed: # pragma: no cover
for item in stravadata: for item in stravadata:
elapsed_time = item['elapsed_time'] elapsed_time = item['elapsed_time']
start_date = item['start_date'] start_date = item['start_date']
@@ -1282,7 +1282,7 @@ def workout_stravaimport_view(request,message="",userid=0):
for item in res.json(): for item in res.json():
d = int(float(item['distance'])) d = int(float(item['distance']))
i = item['id'] i = item['id']
if i in knownstravaids: if i in knownstravaids: # pragma: no cover
nnn = '' nnn = ''
else: else:
nnn = 'NEW' nnn = 'NEW'
@@ -1317,7 +1317,7 @@ def workout_stravaimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user), 'teams':get_my_teams(request.user),
}) })
return HttpResponse(res) return HttpResponse(res) # pragma: no cover
# for Strava webhook request validation # for Strava webhook request validation
@csrf_exempt @csrf_exempt
@@ -1325,7 +1325,7 @@ def strava_webhook_view(request):
if request.method == 'GET': if request.method == 'GET':
challenge = request.GET.get('hub.challenge') challenge = request.GET.get('hub.challenge')
verificationtoken = request.GET.get('hub.verify_token') verificationtoken = request.GET.get('hub.verify_token')
if verificationtoken != stravastuff.webhookverification: if verificationtoken != stravastuff.webhookverification: # pragma: no cover
return HttpResponse(status=403) return HttpResponse(status=403)
data = {"hub.challenge":challenge} data = {"hub.challenge":challenge}
return JSONResponse(data) return JSONResponse(data)
@@ -1341,12 +1341,16 @@ def strava_webhook_view(request):
# POST - does nothing so far # POST - does nothing so far
data = json.loads(request.body) 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: try:
aspect_type = data['aspect_type'] aspect_type = data['aspect_type']
object_type = data['object_type'] object_type = data['object_type']
strava_owner = data['owner_id'] strava_owner = data['owner_id']
starttimeunix = data['event_time'] starttimeunix = data['event_time']
except KeyError: except KeyError: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
@@ -1359,7 +1363,7 @@ def strava_webhook_view(request):
if aspect_type == 'create': if aspect_type == 'create':
try: try:
stravaid = data['object_id'] stravaid = data['object_id']
except KeyError: except KeyError: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
@@ -1370,7 +1374,7 @@ def strava_webhook_view(request):
try: try:
r = Rower.objects.get(strava_owner_id=strava_owner) 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) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
@@ -1381,14 +1385,14 @@ def strava_webhook_view(request):
ws = Workout.objects.filter(uploadedtostrava=stravaid) ws = Workout.objects.filter(uploadedtostrava=stravaid)
if ws.count()==0 and r.strava_auto_import: if ws.count()==0 and r.strava_auto_import:
job = stravastuff.async_get_workout(r.user,stravaid) 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) timestamp = time.strftime('%b-%d-%Y_%H%M',t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
f.write(timestamp) f.write(timestamp)
f.write(' ') f.write(' ')
f.write('Strava strava_open yielded NoTokenError') f.write('Strava strava_open yielded NoTokenError')
else: else: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
@@ -1400,7 +1404,7 @@ def strava_webhook_view(request):
elif aspect_type == 'delete': elif aspect_type == 'delete':
try: try:
stravaid = data['object_id'] stravaid = data['object_id']
except KeyError: except KeyError: # pragma: no cover
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
f.write(timestamp) f.write(timestamp)
@@ -1410,11 +1414,11 @@ def strava_webhook_view(request):
ws = Workout.objects.filter(uploadedtostrava=stravaid) ws = Workout.objects.filter(uploadedtostrava=stravaid)
if ws.count() == 0: if ws.count() == 0:
return HttpResponse(status=200) return HttpResponse(status=200)
except Workout.DoesNotExist: except Workout.DoesNotExist: # pragma: no cover
return HttpResponse(status=200) return HttpResponse(status=200)
try: try: # pragma: no cover
r = Rower.objects.get(strava_owner_id=strava_owner) 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) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
@@ -1422,7 +1426,7 @@ def strava_webhook_view(request):
f.write(' ') f.write(' ')
f.write('Rower not found') f.write('Rower not found')
return HttpResponse(status=200) return HttpResponse(status=200)
if r.strava_auto_delete: if r.strava_auto_delete: # pragma: no cover
for w in ws: for w in ws:
if w.user == r: if w.user == r:
w.delete() w.delete()
@@ -1430,7 +1434,7 @@ def strava_webhook_view(request):
try: try:
updates = data['updates'] updates = data['updates']
stravaid = data['object_id'] stravaid = data['object_id']
except KeyError: except KeyError: # pragma: no cover
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
f.write(timestamp) f.write(timestamp)
@@ -1439,9 +1443,9 @@ def strava_webhook_view(request):
return HttpResponse(status=200) return HttpResponse(status=200)
try: try:
ws = Workout.objects.filter(uploadedtostrava=stravaid) ws = Workout.objects.filter(uploadedtostrava=stravaid)
if ws.count() == 0: if ws.count() == 0: # pragma: no cover
return HttpResponse(status=200) return HttpResponse(status=200)
except Workout.DoesNotExist: except Workout.DoesNotExist: # pragma: no cover
timestamp = time.strftime('%b-%d-%Y_%H%M', t) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
@@ -1451,7 +1455,7 @@ def strava_webhook_view(request):
return HttpResponse(status=200) return HttpResponse(status=200)
try: try:
r = Rower.objects.get(strava_owner_id=strava_owner) 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) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
@@ -1469,7 +1473,7 @@ def strava_webhook_view(request):
try: try:
w.workouttype = mytypes.stravamappinginv[value] w.workouttype = mytypes.stravamappinginv[value]
w.save() w.save()
except KeyError: except KeyError: # pragma: no cover
with open('strava_webhooks.log','a') as f: with open('strava_webhooks.log','a') as f:
f.write('\n') f.write('\n')
f.write(timestamp) f.write(timestamp)
@@ -1481,7 +1485,7 @@ def strava_webhook_view(request):
# For push notifications from Garmin # For push notifications from Garmin
@csrf_exempt @csrf_exempt
def garmin_summaries_view(request): def garmin_summaries_view(request): # pragma: no cover
if request.method != 'POST': if request.method != 'POST':
return HttpResponse(status=200) return HttpResponse(status=200)
@@ -1504,7 +1508,7 @@ def garmin_summaries_view(request):
return HttpResponse(status=200) return HttpResponse(status=200)
@csrf_exempt @csrf_exempt
def garmin_newfiles_ping(request): def garmin_newfiles_ping(request): # pragma: no cover
t = time.localtime() t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t) timestamp = time.strftime('%b-%d-%Y_%H%M', t)
@@ -1528,11 +1532,11 @@ def garmin_newfiles_ping(request):
except KeyError: except KeyError:
pass pass
return HttpResponse(status=200) return HttpResponse(status=200) # pragma: no cover
@csrf_exempt @csrf_exempt
def garmin_deregistration_view(request): def garmin_deregistration_view(request):
if request.method != 'POST': if request.method != 'POST': # pragma: no cover
return HttpResponse(status=200) return HttpResponse(status=200)
data = json.loads(request.body) data = json.loads(request.body)
@@ -1544,16 +1548,16 @@ def garmin_deregistration_view(request):
r = Rower.objects.get(garmintoken=garmintoken) r = Rower.objects.get(garmintoken=garmintoken)
r.garmintoken = '' r.garmintoken = ''
r.save() r.save()
except Rower.DoesNotExist: except Rower.DoesNotExist: # pragma: no cover
pass pass
except KeyError: except KeyError: # pragma: no cover
pass pass
return HttpResponse(status=200) return HttpResponse(status=200)
@csrf_exempt @csrf_exempt
def garmin_details_view(request): def garmin_details_view(request):
if request.method != 'POST': if request.method != 'POST': # pragma: no cover
return HttpResponse(status=200) return HttpResponse(status=200)
t = time.localtime() t = time.localtime()
@@ -1577,12 +1581,12 @@ def workout_runkeeperimport_view(request,message="",userid=0):
if (r.runkeepertoken == '') or (r.runkeepertoken is None): if (r.runkeepertoken == '') or (r.runkeepertoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
return HttpResponseRedirect("/rowers/me/runkeeperauthorize/") return HttpResponseRedirect("/rowers/me/runkeeperauthorize/")
message = "Something went wrong in workout_runkeeperimport_view" message = "Something went wrong in workout_runkeeperimport_view" # pragma: no cover
messages.error(request,message) messages.error(request,message) # pragma: no cover
if settings.DEBUG: if settings.DEBUG: # pragma: no cover
return HttpResponse(res) return HttpResponse(res)
else: else: # pragma: no cover
url = reverse('workouts_view') url = reverse('workouts_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -1620,7 +1624,7 @@ def workout_runkeeperimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user), '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 # The page where you select which RunKeeper workout to import
@login_required() @login_required()
@@ -1638,7 +1642,7 @@ def workout_underarmourimport_view(request,message="",userid=0):
n = item['name'] n = item['name']
try: try:
d = item['aggregates']['distance_total'] d = item['aggregates']['distance_total']
except KeyError: except KeyError: # pragma: no cover
d = 0 d = 0
try: try:
ttot = item['aggregates']['active_time_total'] ttot = item['aggregates']['active_time_total']
@@ -1671,12 +1675,12 @@ def workout_underarmourimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user), '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 # the page where you select which Polar workout to Import
@login_required() @login_required()
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True) @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) exercises = polarstuff.get_polar_workouts(request.user)
workouts = [] workouts = []
@@ -1686,7 +1690,7 @@ def workout_polarimport_view(request,userid=0):
messages.error(request,'Not authorized. You need to connect to Polar first') messages.error(request,'Not authorized. You need to connect to Polar first')
url = reverse('workouts_view') url = reverse('workouts_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
except: except: # pragma: no cover
pass pass
for exercise in exercises: for exercise in exercises:
@@ -1744,13 +1748,13 @@ def workout_sporttracksimport_view(request,message="",userid=0):
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
s = "Token doesn't exist. Need to authorize" s = "Token doesn't exist. Need to authorize"
return HttpResponseRedirect("/rowers/me/sporttracksauthorize/") return HttpResponseRedirect("/rowers/me/sporttracksauthorize/")
else: else: # pragma: no cover
return HttpResponseRedirect("/rowers/me/sporttracksrefresh/") return HttpResponseRedirect("/rowers/me/sporttracksrefresh/")
message = "Something went wrong in workout_sporttracksimport_view" message = "Something went wrong in workout_sporttracksimport_view" # pragma: no cover
messages.error(request,message) messages.error(request,message) # pragma: no cover
if settings.DEBUG: if settings.DEBUG: # pragma: no cover
return HttpResponse(res) return HttpResponse(res)
else: else: # pragma: no cover
url = reverse('workouts_view') url = reverse('workouts_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -1764,7 +1768,7 @@ def workout_sporttracksimport_view(request,message="",userid=0):
for item in res.json()['items']: for item in res.json()['items']:
d = int(float(item['total_distance'])) d = int(float(item['total_distance']))
i = int(getidfromuri(item['uri'])) i = int(getidfromuri(item['uri']))
if i in knownstids: if i in knownstids: # pragma: no cover
nnn = '' nnn = ''
else: else:
nnn = 'NEW' nnn = 'NEW'
@@ -1798,14 +1802,14 @@ def workout_sporttracksimport_view(request,message="",userid=0):
'teams':get_my_teams(request.user), '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 # List of workouts on Concept2 logbook. This view only used for debugging
@login_required() @login_required()
def c2listdebug_view(request,page=1,message=""): def c2listdebug_view(request,page=1,message=""): # pragma: no cover
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
r = getrower(request.user) r = getrower(request.user)
@@ -1845,10 +1849,10 @@ def c2listdebug_view(request,page=1,message=""):
# Import all unknown workouts available on Concept2 logbook # Import all unknown workouts available on Concept2 logbook
@login_required() @login_required()
def workout_getc2workout_all(request,page=1,message=""): def workout_getc2workout_all(request,page=1,message=""): # pragma: no cover
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
r = getrequestrower(request) r = getrequestrower(request)
@@ -1864,10 +1868,10 @@ def workout_getc2workout_all(request,page=1,message=""):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@login_required() @login_required()
def workout_getrp3workout_all(request): def workout_getrp3workout_all(request): # pragma: no cover
try: try:
thetoken = rp3_open(request.user) thetoken = rp3_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/rp3authorize/") return HttpResponseRedirect("/rowers/me/rp3authorize/")
r = getrequestrower(request) r = getrequestrower(request)
@@ -1891,12 +1895,12 @@ def workout_c2import_view(request,page=1,userid=0,message=""):
try: try:
thetoken = c2_open(request.user) thetoken = c2_open(request.user)
except NoTokenError: except NoTokenError: # pragma: no cover
return HttpResponseRedirect("/rowers/me/c2authorize/") return HttpResponseRedirect("/rowers/me/c2authorize/")
res = c2stuff.get_c2_workout_list(request.user,page=page) 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)" message = "Something went wrong in workout_c2import_view (C2 token refresh)"
messages.error(request,message) messages.error(request,message)
url = reverse('workouts_view') 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: with open('c2blocked.json','r') as c2blocked:
jsondata = json.load(c2blocked) jsondata = json.load(c2blocked)
parkedids = jsondata['ids'] parkedids = jsondata['ids']
except FileNotFoundError: except FileNotFoundError: # pragma: no cover
pass pass
knownc2ids = uniqify(knownc2ids+tombstones+parkedids) knownc2ids = uniqify(knownc2ids+tombstones+parkedids)
@@ -1931,7 +1935,7 @@ def workout_c2import_view(request,page=1,userid=0,message=""):
c = item['comments'] c = item['comments']
if i in knownc2ids: if i in knownc2ids:
nnn = '' nnn = ''
else: else: # pragma: no cover
nnn = 'NEW' nnn = 'NEW'
keys = ['id','distance','duration','starttime','rowtype','source','comment','new'] keys = ['id','distance','duration','starttime','rowtype','source','comment','new']
values = [i,d,ttot,s,r,s2,c,nnn] values = [i,d,ttot,s,r,s2,c,nnn]
@@ -2001,10 +2005,16 @@ def workout_getrp3importview(request,externalid):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@login_required() @login_required()
def workout_getimportview(request,externalid,source = 'c2'): def workout_getimportview(request,externalid,source = 'c2',do_async=False):
data,strokedata = importsources[source].get_workout(request.user,externalid) data,strokedata = importsources[source].get_workout(request.user,externalid,
do_async=do_async)
if not data: 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") messages.error(request,"No strokedata received")
url = reverse('workouts_view') url = reverse('workouts_view')
@@ -2027,7 +2037,7 @@ def workout_getimportview(request,externalid,source = 'c2'):
pass pass
if strokedata.empty: if strokedata.empty: # pragma: no cover
distance = data['distance'] distance = data['distance']
c2id = data['id'] c2id = data['id']
workouttype = mytypes.c2mappinginv[data['type']] workouttype = mytypes.c2mappinginv[data['type']]
@@ -2100,7 +2110,7 @@ def workout_getimportview(request,externalid,source = 'c2'):
w = get_workout(encoder.encode_hex(id)) w = get_workout(encoder.encode_hex(id))
if 'workout' in data: if 'workout' in data: # pragma: no cover
if 'splits' in data['workout']: if 'splits' in data['workout']:
splitdata = data['workout']['splits'] splitdata = data['workout']['splits']
elif 'intervals' in data['workout']: elif 'intervals' in data['workout']:
@@ -2111,7 +2121,7 @@ def workout_getimportview(request,externalid,source = 'c2'):
splitdata = False splitdata = False
# splitdata (only for C2) # splitdata (only for C2)
if splitdata: if splitdata: # pragma: no cover
w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename,workouttype=workouttype) w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename,workouttype=workouttype)
w.save() w.save()
@@ -2136,20 +2146,20 @@ def workout_getimportview(request,externalid,source = 'c2'):
w.uploadedtostrava = externalid w.uploadedtostrava = externalid
elif source == 'c2': elif source == 'c2':
w.uploadedtoc2 = externalid w.uploadedtoc2 = externalid
elif source == 'polar': elif source == 'polar': # pragma: no cover
w.uploadedtopolar = externalid w.uploadedtopolar = externalid
elif source == 'runkeeper': elif source == 'runkeeper':
w.uploadedtorunkeeper = externalid w.uploadedtorunkeeper = externalid
elif source == 'sporttracks': elif source == 'sporttracks':
w.uploadedtosporttracks = externalid w.uploadedtosporttracks = externalid
elif source == 'trainingpeaks': elif source == 'trainingpeaks': # pragma: no cover
w.uploadedtotp = externalid w.uploadedtotp = externalid
elif source == 'underarmour': elif source == 'underarmour':
w.uploadedtounderarmour = externalid w.uploadedtounderarmour = externalid
w.save() w.save()
if message: if message: # pragma: no cover
messages.error(request,message) messages.error(request,message)
r = getrower(request.user) r = getrower(request.user)
@@ -2183,7 +2193,7 @@ def workout_getsporttracksworkout_all(request):
id,message = sporttracksstuff.add_workout_from_data( id,message = sporttracksstuff.add_workout_from_data(
request.user,sporttracksid,data,strokedata request.user,sporttracksid,data,strokedata
) )
if id==0: if id==0: # pragma: no cover
messages.error(request,message) messages.error(request,message)
else: else:
@@ -2200,7 +2210,7 @@ def workout_getsporttracksworkout_all(request):
def workout_getstravaworkout_all(request): def workout_getstravaworkout_all(request):
r = getrower(request.user) r = getrower(request.user)
res = stravastuff.get_strava_workouts(r) 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") messages.info(request,"Your workouts are being imported and should appear on the site in the next 15 minutes")
else: else:
messages.error(request,"Couldn't import Strava workouts ") messages.error(request,"Couldn't import Strava workouts ")
@@ -2211,7 +2221,7 @@ def workout_getstravaworkout_all(request):
# Imports all new workouts from SportTracks # Imports all new workouts from SportTracks
@login_required() @login_required()
def workout_getstravaworkout_next(request): def workout_getstravaworkout_next(request): # pragma: no cover
r = Rower.objects.get(user=request.user) 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 = cd['comment']
comment = bleach.clean(comment) comment = bleach.clean(comment)
try: try:
if isinstance(comment,unicode): if isinstance(comment,unicode): # pragma: no cover
comment = comment.encode('utf8') comment = comment.encode('utf8')
elif isinstance(comment, str): elif isinstance(comment, str): # pragma: no cover
comment = comment.decode('utf8') comment = comment.decode('utf8')
except: except:
pass pass
@@ -45,13 +45,13 @@ def plannedsession_comment_view(request,id=0,userid=0):
comment = comment, comment = comment,
url = url, url = url,
) )
if request.user != manager: if request.user != manager: # pragma: no cover
a_messages.info(r.user,message.encode('ascii','ignore')) a_messages.info(r.user,message.encode('ascii','ignore'))
sessiontype = 'training session' sessiontype = 'training session'
if ps.sessiontype == 'race': if ps.sessiontype == 'race': # pragma: no cover
sessiontype = 'online virtual race' sessiontype = 'online virtual race'
elif ps.sessiontype == 'indoorrace': elif ps.sessiontype == 'indoorrace': # pragma: no cover
sessiontype = 'indoor online virtual race' sessiontype = 'indoor online virtual race'
res = myqueue(queuehigh, 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} 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( registrations = VirtualRaceResult.objects.filter(
race__id=ps.id, race__id=ps.id,
emailnotifications=True) emailnotifications=True)
ids = [rg.userid for rg in registrations] ids = [rg.userid for rg in registrations]
rwrs = Rower.objects.filter(id__in= ids) rwrs = Rower.objects.filter(id__in= ids)
rowers = {u.user for u in rwrs} rowers = {u.user for u in rwrs}
elif ps.sessiontype=='indoorrace': elif ps.sessiontype=='indoorrace': # pragma: no cover
registrations = IndoorVirtualRaceResult.objects.filter( registrations = IndoorVirtualRaceResult.objects.filter(
race__id=ps.id, race__id=ps.id,
emailnotifications=True) emailnotifications=True)
@@ -87,9 +87,9 @@ def plannedsession_comment_view(request,id=0,userid=0):
for u in commenters: for u in commenters:
try: try:
a_messages.info(u,message) a_messages.info(u,message)
except ValueError: except ValueError: # pragma: no cover
pass 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) ocr = Rower.objects.get(user=u)
res = myqueue(queue, res = myqueue(queue,
handle_sendemailnewresponse, handle_sendemailnewresponse,
@@ -106,7 +106,7 @@ def plannedsession_comment_view(request,id=0,userid=0):
sessiontype = sessiontype, sessiontype = sessiontype,
commentlink = url 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) followers = VirtualRaceFollower.objects.filter(race__id=ps.id)
for follower in followers: for follower in followers:
othername = '' othername = ''
@@ -133,7 +133,7 @@ def plannedsession_comment_view(request,id=0,userid=0):
rower = getrower(request.user) rower = getrower(request.user)
if ps.sessiontype in ['race','indoorrace']: if ps.sessiontype in ['race','indoorrace']: # pragma: no cover
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse('virtualevents_view'), 'url':reverse('virtualevents_view'),
@@ -209,12 +209,14 @@ def plannedsession_message_view(request,id=0,userid=0):
message, 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) return HttpResponseRedirect(url)
if ps.sessiontype in ['race','indoorrace']: if ps.sessiontype in ['race','indoorrace']: # pragma: no cover
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse('virtualevents_view'), 'url':reverse('virtualevents_view'),
@@ -274,7 +276,7 @@ def plannedsession_multiclone_view(
startdate,enddate = get_dates_timeperiod(request) startdate,enddate = get_dates_timeperiod(request)
teamid = get_team(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) dateform = DateRangeForm(request.POST)
if dateform.is_valid(): if dateform.is_valid():
startdate = dateform.cleaned_data['startdate'] startdate = dateform.cleaned_data['startdate']
@@ -337,7 +339,7 @@ def plannedsession_multiclone_view(
"startdate","preferreddate","enddate").exclude( "startdate","preferreddate","enddate").exclude(
sessiontype='race') sessiontype='race')
if teamid: if teamid: # pragma: no cover
sps = sps.filter(team__in=[teamid]) sps = sps.filter(team__in=[teamid])
try: try:
team = Team.objects.get(id=teamid) team = Team.objects.get(id=teamid)
@@ -349,7 +351,7 @@ def plannedsession_multiclone_view(
team = None team = None
query = request.GET.get('q') query = request.GET.get('q')
if query: if query: # pragma: no cover
query_list = query.split() query_list = query.split()
sps = sps.filter( sps = sps.filter(
reduce(operator.and_, reduce(operator.and_,
@@ -390,7 +392,7 @@ def plannedsession_multiclone_view(
if Team.objects.filter(manager=request.user).count()>=1: if Team.objects.filter(manager=request.user).count()>=1:
teamform = RowerTeamForm(request.user) teamform = RowerTeamForm(request.user)
if teamid: if teamid: # pragma: no cover
teamform = RowerTeamForm(request.user,initial={'team':teamid}) teamform = RowerTeamForm(request.user,initial={'team':teamid})
else: else:
teamform = None teamform = None
@@ -422,7 +424,7 @@ def template_share_view(request,id=0,userid=0):
if ps.can_be_shared: if ps.can_be_shared:
ps.is_public = True ps.is_public = True
ps.save() ps.save()
else: else: # pragma: no cover
messages.error(request,'This planned session comes from a third party and cannot be shared') messages.error(request,'This planned session comes from a third party and cannot be shared')
return HttpResponseRedirect(reverse(template_library_view)) return HttpResponseRedirect(reverse(template_library_view))
@@ -471,7 +473,7 @@ def template_library_view(request,userid=0):
alltags = uniqify(alltags) alltags = uniqify(alltags)
tag = request.GET.get('tag') tag = request.GET.get('tag')
if tag: if tag: # pragma: no cover
tags = [tag] tags = [tag]
templates = templates.filter(tags__name__in=tags).distinct() 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={ url = reverse('plannedsession_edit_view',kwargs={
'id':ps.id, '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 = reverse('plannedsession_create_view',kwargs={'userid':userid})
url = url+'?when='+timeperiod url = url+'?when='+timeperiod
@@ -551,7 +553,7 @@ def plannedsession_create_view(request,
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
else: else:
if 'fstartdate' in request.session: if 'fstartdate' in request.session: # pragma: no cover
try: try:
fstartdate = arrow.get(request.session['fstartdate']).date() fstartdate = arrow.get(request.session['fstartdate']).date()
except KeyError: except KeyError:
@@ -586,7 +588,7 @@ def plannedsession_create_view(request,
preferreddate = startdate.date() preferreddate = startdate.date()
except AttributeError: except AttributeError:
preferreddate = startdate preferreddate = startdate
if preferreddate < timezone.now().date(): if preferreddate < timezone.now().date(): # pragma: no cover
preferreddate = timezone.now().date() preferreddate = timezone.now().date()
try: try:
@@ -594,7 +596,7 @@ def plannedsession_create_view(request,
except AttributeError: except AttributeError:
pass pass
if preferreddate > enddate: if preferreddate > enddate: # pragma: no cover
preferreddate = enddate preferreddate = enddate
forminitial = { forminitial = {
@@ -626,7 +628,7 @@ def plannedsession_create_view(request,
sessiontemplates = sessiontemplates.order_by("name") sessiontemplates = sessiontemplates.order_by("name")
alltags = [] alltags = []
for t in sessiontemplates: for t in sessiontemplates: # pragma: no cover
tags = t.tags.all() tags = t.tags.all()
for tag in tags: for tag in tags:
alltags.append(tag) alltags.append(tag)
@@ -634,7 +636,7 @@ def plannedsession_create_view(request,
alltags = uniqify(alltags) alltags = uniqify(alltags)
tag = request.GET.get('tag') tag = request.GET.get('tag')
if tag: if tag: # pragma: no cover
tags = [tag] tags = [tag]
sessiontemplates = sessiontemplates.filter(tags__name__in=tags).distinct() sessiontemplates = sessiontemplates.filter(tags__name__in=tags).distinct()
@@ -709,11 +711,11 @@ def plannedsession_createtemplate_view(request,
url = reverse('template_library_view') url = reverse('template_library_view')
if '_continue' in request.POST: if '_continue' in request.POST: # pragma: no cover
url = reverse('plannedsession_templateedit_view',kwargs={ url = reverse('plannedsession_templateedit_view',kwargs={
'id':ps.id, 'id':ps.id,
}) })
elif '_addanother' in request.POST: elif '_addanother' in request.POST: # pragma: no cover
url = reverse('plannedsession_createtemplate_view') url = reverse('plannedsession_createtemplate_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -733,7 +735,7 @@ def plannedsession_createtemplate_view(request,
sessiontemplates = sessiontemplates.order_by("name") sessiontemplates = sessiontemplates.order_by("name")
alltags = [] alltags = []
for t in sessiontemplates: for t in sessiontemplates: # pragma: no cover
tags = t.tags.all() tags = t.tags.all()
for tag in tags: for tag in tags:
alltags.append(tag) alltags.append(tag)
@@ -806,7 +808,7 @@ def plannedsession_multicreate_view(request,
).order_by("startdate","preferreddate","enddate").exclude( ).order_by("startdate","preferreddate","enddate").exclude(
sessiontype='race') sessiontype='race')
if teamid: if teamid: # pragma: no cover
qset = qset.filter(team__in=[teamid]) qset = qset.filter(team__in=[teamid])
try: try:
team = Team.objects.get(id=teamid) team = Team.objects.get(id=teamid)
@@ -844,10 +846,10 @@ def plannedsession_multicreate_view(request,
for ps in instances: for ps in instances:
ps.save() ps.save()
add_rower_session(r,ps) add_rower_session(r,ps)
if team: if team: # pragma: no cover
add_team_session(team,ps) add_team_session(team,ps)
messages.info(request,"Saved changes for Planned Session "+str(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)) messages.info(request,"Deleted Planned Session "+str(obj))
obj.delete() obj.delete()
@@ -862,7 +864,7 @@ def plannedsession_multicreate_view(request,
enddatestring = enddate.strftime('%Y-%m-%d') enddatestring = enddate.strftime('%Y-%m-%d')
url += '?when='+startdatestring+'/'+enddatestring url += '?when='+startdatestring+'/'+enddatestring
if team: if team: # pragma: no cover
url += '&team={teamid}'.format(teamid=team.id) url += '&team={teamid}'.format(teamid=team.id)
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -888,7 +890,7 @@ def plannedsession_multicreate_view(request,
if Team.objects.filter(manager=request.user).count()>=1: if Team.objects.filter(manager=request.user).count()>=1:
teamform = RowerTeamForm(request.user) teamform = RowerTeamForm(request.user)
if teamid: if teamid: # pragma: no cover
teamform = RowerTeamForm(request.user,initial={'team':teamid}) teamform = RowerTeamForm(request.user,initial={'team':teamid})
else: else:
teamform = None teamform = None
@@ -975,11 +977,11 @@ def plannedsession_teamcreate_view(request,
'userid':userid, 'userid':userid,
}) })
if '_continue' in request.POST: if '_continue' in request.POST: # pragma: no cover
url = reverse('plannedsession_edit_view',kwargs={ url = reverse('plannedsession_edit_view',kwargs={
'id':ps.id, '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 = reverse('plannedsession_teamcreate_view',kwargs={'userid':userid})
url = url+'?when='+timeperiod url = url+'?when='+timeperiod
@@ -995,7 +997,7 @@ def plannedsession_teamcreate_view(request,
#next = request.GET.get('next', url) #next = request.GET.get('next', url)
#return HttpResponseRedirect(next) #return HttpResponseRedirect(next)
else: else: # pragma: no cover
timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
breadcrumbs = [ breadcrumbs = [
{ {
@@ -1035,7 +1037,7 @@ def plannedsession_teamcreate_view(request,
'preferreddate':startdate, 'preferreddate':startdate,
} }
if 'teams' in request.session: if 'teams' in request.session: # pragma: no cover
teams = request.session['teams'] teams = request.session['teams']
theteams = Team.objects.filter(id__in=teams) theteams = Team.objects.filter(id__in=teams)
initialteam = { initialteam = {
@@ -1113,7 +1115,7 @@ def plannedsession_teamedit_view(request,
startdate__lte = startdate, startdate__lte = startdate,
rowers = r, rowers = r,
enddate__gte = enddate)[0] enddate__gte = enddate)[0]
except IndexError: except IndexError: # pragma: no cover
trainingplan = None trainingplan = None
sps = [] sps = []
@@ -1138,11 +1140,10 @@ def plannedsession_teamedit_view(request,
) )
sessionrowerform = PlannedSessionTeamMemberForm(ps,request.POST) sessionrowerform = PlannedSessionTeamMemberForm(ps,request.POST)
if sessioncreateform.is_valid(): if sessioncreateform.is_valid():
cd = sessioncreateform.cleaned_data cd = sessioncreateform.cleaned_data
if cd['sessionunit'] == 'min': if cd['sessionunit'] == 'min': # pragma: no cover
cd['sessionmode'] = 'time' cd['sessionmode'] = 'time'
elif cd['sessionunit'] in ['km','m']: elif cd['sessionunit'] in ['km','m']:
cd['sessionmode'] = 'distance' cd['sessionmode'] = 'distance'
@@ -1152,7 +1153,7 @@ def plannedsession_teamedit_view(request,
if res: if res:
messages.info(request,message) messages.info(request,message)
else: else: # pragma: no cover
messages.error(request,message) messages.error(request,message)
@@ -1166,14 +1167,15 @@ def plannedsession_teamedit_view(request,
rs = Rower.objects.filter(team__in=[team]) rs = Rower.objects.filter(team__in=[team])
for r in rs: for r in rs:
add_rower_session(r,ps) add_rower_session(r,ps)
else: else: # pragma: no cover
remove_team_session(team,ps) remove_team_session(team,ps)
else: else: # pragma: no cover
selectedteams = [] selectedteams = []
for team in teams: for team in teams:
remove_team_session(team,ps) remove_team_session(team,ps)
if sessionrowerform.is_valid(): if sessionrowerform.is_valid():
cd = sessionrowerform.cleaned_data cd = sessionrowerform.cleaned_data
selectedrowers = cd['members'] selectedrowers = cd['members']
@@ -1190,7 +1192,7 @@ def plannedsession_teamedit_view(request,
url = reverse('plannedsessions_view') url = reverse('plannedsessions_view')
if "_continue" in request.POST: if "_continue" in request.POST: # pragma: no cover
url = reverse(plannedsession_edit_view, url = reverse(plannedsession_edit_view,
kwargs={ kwargs={
'id':int(ps.id), 'id':int(ps.id),
@@ -1279,7 +1281,7 @@ def plannedsessions_coach_view(request,
trainingplan = None trainingplan = None
if teamid != 0: if teamid != 0:# pragma: no cover
try: try:
theteam = Team.objects.get(id=teamid) theteam = Team.objects.get(id=teamid)
except Team.DoesNotExist: except Team.DoesNotExist:
@@ -1297,13 +1299,13 @@ def plannedsessions_coach_view(request,
if therower.rowerplan != 'freecoach': if therower.rowerplan != 'freecoach':
rowers = [therower] rowers = [therower]
else: else:# pragma: no cover
rowers = [] rowers = []
for ps in sps: for ps in sps:
if 'coach' in request.user.rower.rowerplan: if 'coach' in request.user.rower.rowerplan:
rowers += ps.rower.all().exclude(rowerplan='freecoach') rowers += ps.rower.all().exclude(rowerplan='freecoach')
else: else: # pragma: no cover
rowers += ps.rower.filter(team__in=rteams).exclude(rowerplan='freecoach') rowers += ps.rower.filter(team__in=rteams).exclude(rowerplan='freecoach')
rowers = list(set(rowers)) rowers = list(set(rowers))
@@ -1356,7 +1358,7 @@ def plannedsessions_coach_view(request,
}) })
ttemplate = 'plannedsessionscoach.html' 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' ttemplate = 'plannedsessionscoach2.html'
@@ -1386,16 +1388,16 @@ def plannedsessions_view(request,
try: try:
r = getrequestplanrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
except PermissionDenied: except PermissionDenied: # pragma: no cover
r = request.user.rower r = request.user.rower
if startdatestring: if startdatestring: # pragma: no cover
try: try:
startdate = iso8601.parse_date(startdatestring) startdate = iso8601.parse_date(startdatestring)
except ParseError: except ParseError:
pass pass
if enddatestring: if enddatestring: # pragma: no cover
try: try:
enddate = iso8601.parse_date(enddatestring) enddate = iso8601.parse_date(enddatestring)
except ParseError: except ParseError:
@@ -1454,7 +1456,7 @@ def plannedsessions_view(request,
tss = hrtss tss = hrtss
totals['distance'] += w.distance totals['distance'] += w.distance
totals['time'] += timefield_to_seconds_duration(w.duration) totals['time'] += timefield_to_seconds_duration(w.duration)
if w.plannedsession: if w.plannedsession: # pragma: no cover
if w.plannedsession.sessionmode == 'distance': if w.plannedsession.sessionmode == 'distance':
totals['actualdistance'] += w.distance totals['actualdistance'] += w.distance
elif w.plannedsession.sessionmode == 'time': elif w.plannedsession.sessionmode == 'time':
@@ -1464,7 +1466,7 @@ def plannedsessions_view(request,
elif w.plannedsession.sessionmode == 'TRIMP': elif w.plannedsession.sessionmode == 'TRIMP':
totals['actualtrimp'] += thetrimp 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, messages.error(request,
"You must purchase Coach or Self-coach plans or be part of a team to get planned sessions") "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 totals['planneddistance'] += ps.sessionvalue
elif ps.sessionmode == 'time': elif ps.sessionmode == 'time':
totals['plannedtime'] += ps.sessionvalue totals['plannedtime'] += ps.sessionvalue
elif ps.sessionmode == 'rScore': elif ps.sessionmode == 'rScore': # pragma: no cover
totals['plannedrscore'] += ps.sessionvalue totals['plannedrscore'] += ps.sessionvalue
elif ps.sessionmode == 'TRIMP': elif ps.sessionmode == 'TRIMP': # pragma: no cover
totals['plannedtrimp'] += ps.sessionvalue totals['plannedtrimp'] += ps.sessionvalue
totals['time'] = int(totals['time']/60.) totals['time'] = int(totals['time']/60.)
@@ -1572,7 +1574,7 @@ def plannedsessions_manage_view(request,userid=0,
initialsession=0): initialsession=0):
is_ajax = False is_ajax = False
if request.is_ajax(): if request.is_ajax(): # pragma: no cover
is_ajax = True is_ajax = True
r = getrequestrower(request,userid=userid) r = getrequestrower(request,userid=userid)
@@ -1614,7 +1616,7 @@ def plannedsessions_manage_view(request,userid=0,
linkedworkouts = [] linkedworkouts = []
for w in ws: for w in ws:
if w.plannedsession is not None: if w.plannedsession is not None: # pragma: no cover
linkedworkouts.append(w.id) linkedworkouts.append(w.id)
plannedsessionstuple = [] plannedsessionstuple = []
@@ -1646,10 +1648,10 @@ def plannedsessions_manage_view(request,userid=0,
ps = PlannedSession.objects.get(id=ps_form.cleaned_data['plannedsession']) ps = PlannedSession.objects.get(id=ps_form.cleaned_data['plannedsession'])
if w_form.is_valid(): if w_form.is_valid():
selectedworkouts = w_form.cleaned_data['workouts'] selectedworkouts = w_form.cleaned_data['workouts']
else: else: # pragma: no cover
selectedworkouts = [] selectedworkouts = []
if len(selectedworkouts)==0: if len(selectedworkouts)==0: # pragma: no cover
for w in ws: for w in ws:
remove_workout_plannedsession(w,ps) 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) result,comments,errors = add_workouts_plannedsession(workouts,ps,r)
for c in comments: for c in comments:
messages.info(request,c) messages.info(request,c)
for er in errors: for er in errors: # pragma: no cover
messages.error(request,er) messages.error(request,er)
@@ -1672,7 +1674,7 @@ def plannedsessions_manage_view(request,userid=0,
w_form = WorkoutSessionSelectForm(workoutdata=workoutdata) w_form = WorkoutSessionSelectForm(workoutdata=workoutdata)
if is_ajax: if is_ajax: # pragma: no cover
ajax_workouts = [] ajax_workouts = []
for id,name in workoutdata['choices']: for id,name in workoutdata['choices']:
ininitial = id in initialworkouts ininitial = id in initialworkouts
@@ -1746,7 +1748,7 @@ def plannedsession_clone_view(request,id=0,userid=0):
startdate__lte = startdate, startdate__lte = startdate,
rowers = r, rowers = r,
enddate__gte = enddate)[0] enddate__gte = enddate)[0]
except IndexError: except IndexError: # pragma: no cover
trainingplan = None trainingplan = None
ps = get_object_or_404(PlannedSession,pk=id) ps = get_object_or_404(PlannedSession,pk=id)
@@ -1773,7 +1775,7 @@ def plannedsession_clone_view(request,id=0,userid=0):
if rowers: if rowers:
for rower in rowers: for rower in rowers:
add_rower_session(rower,ps) add_rower_session(rower,ps)
else: else: # pragma: no cover
add_rower_session(r,ps) add_rower_session(r,ps)
for team in teams: for team in teams:
add_team_session(team,ps) add_team_session(team,ps)
@@ -1803,10 +1805,10 @@ def plannedsession_teamclone_view(request,id=0):
r = getrequestplanrower(request) r = getrequestplanrower(request)
teams = Team.objects.filter(manager=request.user) 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] teamchoices = [(team.id, team.name) for team in teams]
teaminitial = [str(teams[0].id)] 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.") messages.info(request,"You have no teams established yet. We are redirecting you to the Team Management page.")
url = reverse('rower_teams_view') url = reverse('rower_teams_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -1871,16 +1873,16 @@ def plannedsession_templateedit_view(request,id=0):
try: try:
ps = PlannedSession.objects.get(id=id) ps = PlannedSession.objects.get(id=id)
except PlannedSession.DoesNotExist: except PlannedSession.DoesNotExist: # pragma: no cover
raise Http404("Planned Session does not exist") 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") 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") 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.pk = None
ps.id = None ps.id = None
ps.is_template = True ps.is_template = True
@@ -1898,7 +1900,7 @@ def plannedsession_templateedit_view(request,id=0):
cd = sessioncreateform.cleaned_data cd = sessioncreateform.cleaned_data
if cd['sessionunit'] == 'min': if cd['sessionunit'] == 'min':
cd['sessionmode'] = 'time' cd['sessionmode'] = 'time'
elif cd['sessionunit'] in ['km','m']: elif cd['sessionunit'] in ['km','m']: # pragma: no cover
cd['sessionmode'] = 'distance' cd['sessionmode'] = 'distance'
obj = sessioncreateform.save(commit=False) obj = sessioncreateform.save(commit=False)
@@ -1910,12 +1912,12 @@ def plannedsession_templateedit_view(request,id=0):
if res: if res:
messages.info(request,message) messages.info(request,message)
else: else: # pragma: no cover
messages.error(request,message) messages.error(request,message)
url = reverse('template_library_view') url = reverse('template_library_view')
if '_continue' in request.POST: if '_continue' in request.POST: # pragma: no cover
url = reverse('plannedsession_templateedit_view',kwargs={ url = reverse('plannedsession_templateedit_view',kwargs={
'id':ps.id, 'id':ps.id,
}) })
@@ -2010,7 +2012,7 @@ def plannedsession_edit_view(request,id=0,userid=0):
startdate__lte = startdate, startdate__lte = startdate,
rowers = r, rowers = r,
enddate__gte = enddate)[0] enddate__gte = enddate)[0]
except IndexError: except IndexError: # pragma: no cover
trainingplan = None trainingplan = None
ps = get_object_or_404(PlannedSession,pk=id) 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(): if sessioncreateform.is_valid():
cd = sessioncreateform.cleaned_data cd = sessioncreateform.cleaned_data
if cd['sessionunit'] == 'min': if cd['sessionunit'] == 'min': # pragma: no cover
cd['sessionmode'] = 'time' cd['sessionmode'] = 'time'
elif cd['sessionunit'] in ['km','m']: elif cd['sessionunit'] in ['km','m']:
cd['sessionmode'] = 'distance' cd['sessionmode'] = 'distance'
@@ -2039,12 +2041,12 @@ def plannedsession_edit_view(request,id=0,userid=0):
if res: if res:
messages.info(request,message) messages.info(request,message)
else: else: # pragma: no cover
messages.error(request,message) messages.error(request,message)
url = reverse('plannedsessions_view') url = reverse('plannedsessions_view')
if "_continue" in request.POST: if "_continue" in request.POST: # pragma: no cover
url = reverse(plannedsession_edit_view, url = reverse(plannedsession_edit_view,
kwargs={ kwargs={
'id':int(ps.id), 'id':int(ps.id),
@@ -2147,13 +2149,13 @@ def plannedsession_view(request,id=0,userid=0):
r = getrequestplanrower(request,userid=userid) r = getrequestplanrower(request,userid=userid)
ps = get_object_or_404(PlannedSession,pk=id) 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 jsons = ps.steps
else: else:
jsons = {} jsons = {}
try: try: # pragma: no cover
r = VirtualRace.objects.get(id=ps.id) r = VirtualRace.objects.get(id=ps.id)
url = reverse('virtualevent_view', url = reverse('virtualevent_view',
kwargs={'id':ps.id} kwargs={'id':ps.id}
@@ -2162,7 +2164,7 @@ def plannedsession_view(request,id=0,userid=0):
except VirtualRace.DoesNotExist: except VirtualRace.DoesNotExist:
pass pass
if ps.course: if ps.course: # pragma: no cover
coursescript,coursediv = course_map(ps.course) coursescript,coursediv = course_map(ps.course)
else: else:
coursescript = '' coursescript = ''
@@ -2208,7 +2210,7 @@ def plannedsession_view(request,id=0,userid=0):
'sessionresult':0, 'sessionresult':0,
'workoutid':w.id, 'workoutid':w.id,
} }
if ps.sessiontype == 'coursetest': if ps.sessiontype == 'coursetest': # pragma: no cover
vs = CourseTestResult.objects.filter(plannedsession=ps, vs = CourseTestResult.objects.filter(plannedsession=ps,
workoutid=w.id) workoutid=w.id)
@@ -2254,10 +2256,10 @@ def plannedsession_view(request,id=0,userid=0):
wdict['distance'] = ps.course.distance wdict['distance'] = ps.course.distance
wdict['coursecompleted'] = False wdict['coursecompleted'] = False
ranking.append(wdict) ranking.append(wdict)
if ps.sessiontype == 'coursetest': if ps.sessiontype == 'coursetest': # pragma: no cover
ranking = sorted(ranking, key=lambda k: k['time']) 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) vs = CourseTestResult.objects.filter(plannedsession=ps)
if vs: if vs:
@@ -2293,7 +2295,7 @@ def plannedsession_view(request,id=0,userid=0):
pass pass
ranking = sorted(ranking, key=lambda k: k['time']) 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) vs = CourseTestResult.objects.filter(plannedsession=ps)
if vs: if vs:
@@ -2363,7 +2365,7 @@ def plannedsession_view(request,id=0,userid=0):
comments = PlannedSessionComment.objects.filter(plannedsession=ps).order_by("created") comments = PlannedSessionComment.objects.filter(plannedsession=ps).order_by("created")
steps = '' steps = ''
if ps.steps: if ps.steps: # pragma: no cover
d = ps.steps d = ps.steps
steps = ps_dict_get_description_html(d,short=False) steps = ps_dict_get_description_html(d,short=False)
@@ -2407,7 +2409,7 @@ class PlannedSessionDelete(DeleteView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(PlannedSessionDelete,self).get_context_data(**kwargs) context = super(PlannedSessionDelete,self).get_context_data(**kwargs)
if 'userid' in kwargs: if 'userid' in kwargs: # pragma: no cover
userid = kwargs['userid'] userid = kwargs['userid']
else: else:
userid = 0 userid = 0
@@ -2455,7 +2457,7 @@ class PlannedSessionDelete(DeleteView):
def get_success_url(self): def get_success_url(self):
ws = Workout.objects.filter(plannedsession=self.object) ws = Workout.objects.filter(plannedsession=self.object)
for w in ws: for w in ws: # pragma: no cover
w.plannedsession = None w.plannedsession = None
w.save() w.save()
@@ -2468,14 +2470,14 @@ class PlannedSessionDelete(DeleteView):
def get_object(self, *args, **kwargs): def get_object(self, *args, **kwargs):
obj = super(PlannedSessionDelete, self).get_object(*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') raise PermissionDenied('You are not allowed to delete this planned session')
return obj return obj
def rower_view_instantplan(request,id='',userid=0): def rower_view_instantplan(request,id='',userid=0):
r = getrequestrower(request,userid=userid) r = getrequestrower(request,userid=userid)
if not id: if not id: # pragma: no cover
raise Http404("Plan does not exist") raise Http404("Plan does not exist")
plan = InstantPlan.objects.get(uuid=id) plan = InstantPlan.objects.get(uuid=id)
@@ -2486,7 +2488,7 @@ def rower_view_instantplan(request,id='',userid=0):
headers = {'Authorization':authorizationstring} headers = {'Authorization':authorizationstring}
response = requests.get(url=url,headers=headers) 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") messages.error(request,"Could not connect to the training plan server")
return HttpResponseRedirect(reverse('rower_select_instantplan')) return HttpResponseRedirect(reverse('rower_select_instantplan'))
@@ -2518,7 +2520,7 @@ def rower_view_instantplan(request,id='',userid=0):
).order_by("-date") ).order_by("-date")
if request.method == 'POST' and not request.user.is_anonymous: 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') 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={ url = reverse('rower_view_instantplan',kwargs={
'id':id, 'id':id,
@@ -2532,11 +2534,11 @@ def rower_view_instantplan(request,id='',userid=0):
name = form.cleaned_data['name'] name = form.cleaned_data['name']
try: try:
targetid = form.cleaned_data['target'] targetid = form.cleaned_data['target']
if targetid != '': if targetid != '': # pragma: no cover
target = TrainingTarget.objects.get(id=int(targetid)) target = TrainingTarget.objects.get(id=int(targetid))
else: else:
target = None target = None
except KeyError: except KeyError: # pragma: no cover
try: try:
targetid = request.POST['target'] targetid = request.POST['target']
if targetid != '': if targetid != '':
@@ -2551,12 +2553,12 @@ def rower_view_instantplan(request,id='',userid=0):
datechoice = form.cleaned_data['datechoice'] datechoice = form.cleaned_data['datechoice']
status = True status = True
if target and datechoice == 'target': if target and datechoice == 'target': # pragma: no cover
enddate = target.date enddate = target.date
startdate = enddate-datetime.timedelta(days=plan.duration) startdate = enddate-datetime.timedelta(days=plan.duration)
elif datechoice == 'startdate': elif datechoice == 'startdate':
enddate = startdate+datetime.timedelta(days=plan.duration) enddate = startdate+datetime.timedelta(days=plan.duration)
else: else: # pragma: no cover
startdate = enddate-datetime.timedelta(days=plan.duration) 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: elif not request.user.is_anonymous:
form = InstantPlanSelectForm(targets=targets,instantplan=plan,initial={'datechoice':'startdate'}) form = InstantPlanSelectForm(targets=targets,instantplan=plan,initial={'datechoice':'startdate'})
else: else: # pragma: no cover
form = None form = None
breadcrumbs = [ breadcrumbs = [
@@ -2630,7 +2632,7 @@ def remove_groupsession_view(request,id=0):
if res: if res:
messages.info(request,"We have removed you from this group session") 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") messages.error(request,"For some reason we could not remove you from this group session")
url = reverse('plannedsessions_view') url = reverse('plannedsessions_view')
@@ -2639,12 +2641,12 @@ def remove_groupsession_view(request,id=0):
@login_required() @login_required()
def add_instantplan_view(request): def add_instantplan_view(request):
if not request.user.is_staff: if not request.user.is_staff: # pragma: no cover
raise PermissionDenied("Not Allowed") raise PermissionDenied("Not Allowed")
r = getrequestrower(request) r = getrequestrower(request)
if request.method == 'POST': if request.method == 'POST': # pragma: no cover
form = InstantPlanForm(request.POST,request.FILES) form = InstantPlanForm(request.POST,request.FILES)
if form.is_valid(): if form.is_valid():
ip = form.save(commit=False) ip = form.save(commit=False)
@@ -2762,9 +2764,9 @@ def rower_create_trainingplan(request,id=0):
targetid = request.POST['target'] targetid = request.POST['target']
if targetid != '': if targetid != '':
target = TrainingTarget.objects.get(id=int(targetid)) target = TrainingTarget.objects.get(id=int(targetid))
else: else: # pragma: no cover
target = None target = None
except KeyError: except KeyError: # pragma: no cover
target = None target = None
startdate = form.cleaned_data['startdate'] startdate = form.cleaned_data['startdate']
status = form.cleaned_data['status'] status = form.cleaned_data['status']
@@ -2812,7 +2814,7 @@ def rower_create_trainingplan(request,id=0):
status=True, status=True,
).order_by("-startdate") ).order_by("-startdate")
for p in plans_to_deactivate: for p in plans_to_deactivate: # pragma: no cover
p.status = False p.status = False
p.save() p.save()
@@ -2861,18 +2863,6 @@ def rower_delete_trainingtarget(request,id=0):
return HttpResponseRedirect(url) 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): class TrainingPlanDelete(DeleteView):
model = TrainingPlan model = TrainingPlan
template_name = 'trainingplan_delete.html' template_name = 'trainingplan_delete.html'
@@ -2880,12 +2870,12 @@ class TrainingPlanDelete(DeleteView):
def get_object(self, *args, **kwargs): def get_object(self, *args, **kwargs):
obj = super(TrainingPlanDelete, self).get_object(*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') raise PermissionDenied('You are not allowed to delete this training plan')
return obj return obj
class MicroCycleDelete(DeleteView): class MicroCycleDelete(DeleteView): # pragma: no cover
model = TrainingMicroCycle model = TrainingMicroCycle
template_name = 'trainingplan_delete.html' template_name = 'trainingplan_delete.html'
@@ -2951,7 +2941,7 @@ class MicroCycleDelete(DeleteView):
return obj return obj
class MesoCycleDelete(DeleteView): class MesoCycleDelete(DeleteView): # pragma: no cover
model = TrainingMesoCycle model = TrainingMesoCycle
template_name = 'trainingplan_delete.html' template_name = 'trainingplan_delete.html'
@@ -3014,7 +3004,7 @@ class MesoCycleDelete(DeleteView):
return obj return obj
class MacroCycleDelete(DeleteView): class MacroCycleDelete(DeleteView): # pragma: no cover
model = TrainingMacroCycle model = TrainingMacroCycle
template_name = 'trainingplan_delete.html' template_name = 'trainingplan_delete.html'
@@ -3083,13 +3073,13 @@ def rower_trainingplan_execution_view(request,
if int(id)>0: if int(id)>0:
try: try:
plan = TrainingPlan.objects.get(id=id) plan = TrainingPlan.objects.get(id=id)
except TrainingPlan.DoesNotExist: except TrainingPlan.DoesNotExist: # pragma: no cover
raise Http404("Training Plan Does Not Exist") 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(): if request.user.rower not in plan.rowers.all():
raise PermissionDenied("Access denied") raise PermissionDenied("Access denied")
if not startdate or not enddate: if not startdate or not enddate: # pragma: no cover
if int(id)>0: if int(id)>0:
startdate = plan.startdate startdate = plan.startdate
enddate = plan.enddate enddate = plan.enddate
@@ -3101,12 +3091,12 @@ def rower_trainingplan_execution_view(request,
if int(id)>0: if int(id)>0:
data,message = get_execution_report(r,startdate,enddate,plan=plan) data,message = get_execution_report(r,startdate,enddate,plan=plan)
else: else: # pragma: no cover
data,message = get_execution_report(r,startdate,enddate) data,message = get_execution_report(r,startdate,enddate)
if not data.empty: if not data.empty:
script, div = interactive_planchart(data,startdate,enddate) script, div = interactive_planchart(data,startdate,enddate)
else: else: # pragma: no cover
script = '' script = ''
div = '' div = ''
messages.error(request,'The plan does not cover this time range') messages.error(request,'The plan does not cover this time range')
@@ -3131,7 +3121,7 @@ def rower_trainingplan_execution_view(request,
'name': 'Execution' 'name': 'Execution'
} }
] ]
else: else: # pragma: no cover
breadcrumbs = [ breadcrumbs = [
{ {
'url':reverse(plannedsessions_view, 'url':reverse(plannedsessions_view,
@@ -3222,7 +3212,7 @@ def rower_trainingplan_view(request,
try: try:
thismicro = get_todays_micro(plan,thedate=startdate) thismicro = get_todays_micro(plan,thedate=startdate)
thismicroid = thismicro.pk thismicroid = thismicro.pk
except AttributeError: except AttributeError: # pragma: no cover
thismicroid = None thismicroid = None
@@ -3240,7 +3230,7 @@ def rower_trainingplan_view(request,
} }
) )
class TrainingMacroCycleUpdate(UpdateView): class TrainingMacroCycleUpdate(UpdateView): # pragma: no cover
model = TrainingMacroCycle model = TrainingMacroCycle
template_name = 'trainingplan_edit.html' template_name = 'trainingplan_edit.html'
form_class = TrainingMacroCycleForm form_class = TrainingMacroCycleForm
@@ -3305,7 +3295,7 @@ class TrainingMacroCycleUpdate(UpdateView):
obj.save() obj.save()
return obj return obj
class TrainingMesoCycleUpdate(UpdateView): class TrainingMesoCycleUpdate(UpdateView): # pragma: no cover
model = TrainingMesoCycle model = TrainingMesoCycle
template_name = 'trainingplan_edit.html' template_name = 'trainingplan_edit.html'
form_class = TrainingMesoCycleForm form_class = TrainingMesoCycleForm
@@ -3379,7 +3369,7 @@ class TrainingMesoCycleUpdate(UpdateView):
obj.plan.save() obj.plan.save()
return obj return obj
class TrainingMicroCycleUpdate(UpdateView): class TrainingMicroCycleUpdate(UpdateView): # pragma: no cover
model = TrainingMicroCycle model = TrainingMicroCycle
template_name = 'trainingplan_edit.html' template_name = 'trainingplan_edit.html'
form_class = TrainingMicroCycleForm form_class = TrainingMicroCycleForm
@@ -3458,7 +3448,7 @@ class TrainingMicroCycleUpdate(UpdateView):
obj.plan.save() obj.plan.save()
return obj return obj
class TrainingPlanUpdate(UpdateView): class TrainingPlanUpdate(UpdateView): # pragma: no cover
model = TrainingPlan model = TrainingPlan
template_name = 'trainingplan_edit.html' template_name = 'trainingplan_edit.html'
form_class = TrainingPlanForm form_class = TrainingPlanForm
@@ -3517,7 +3507,7 @@ class TrainingPlanUpdate(UpdateView):
return obj return obj
class TrainingTargetUpdate(UpdateView): class TrainingTargetUpdate(UpdateView): # pragma: no cover
model = TrainingTarget model = TrainingTarget
template_name = 'trainingplan_edit.html' template_name = 'trainingplan_edit.html'
form_class = TrainingTargetForm form_class = TrainingTargetForm
@@ -3573,7 +3563,7 @@ from rowers.utils import allsundays
message="This functionality requires a Coach or Self-Coach plan", message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None) redirect_field_name=None)
@permission_required('cycle.change_cycle',fn=get_meso_by_pk,raise_exception=True) @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) cycle = get_object_or_404(TrainingMesoCycle,pk=id)
micros = TrainingMicroCycle.objects.filter(plan=cycle) 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", message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None) redirect_field_name=None)
@permission_required('cycle.change_cycle',fn=get_macro_by_pk,raise_exception=True) @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) cycle = get_object_or_404(TrainingMacroCycle,pk=id)
mesos = TrainingMesoCycle.objects.filter(plan=cycle) mesos = TrainingMesoCycle.objects.filter(plan=cycle)
+197 -197
View File
File diff suppressed because it is too large Load Diff