Private
Public Access
1
0

Merge branch 'release/v16.0.6'

This commit is contained in:
Sander Roosendaal
2021-04-29 15:49:44 +02:00
85 changed files with 3448 additions and 1477 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
from django.conf import settings
def google_analytics(request):
def google_analytics(request): # pragma: no cover
"""
Use the variables returned in this function to
render your Google Analytics tracking code template.
@@ -14,7 +14,7 @@ def google_analytics(request):
}
return {}
def hello_world(request):
def hello_world(request): # pragma: no cover
return {
'helloworld': 'hi Sander'
}
+2 -2
View File
@@ -79,10 +79,10 @@ class UserAdmin(admin.ModelAdmin):
search_fields = ["username","first_name","last_name","email"]
def rowerplan(self, obj):
def rowerplan(self, obj): # pragma: no cover
return obj.rower.rowerplan
def clubsize(self, obj):
def clubsize(self, obj): # pragma: no cover
return obj.rower.clubsize
class WorkoutAdmin(admin.ModelAdmin):
+7 -7
View File
@@ -10,7 +10,7 @@ def create_alert(manager, rower, measured,period=7, emailalert=True,
name='',**kwargs):
# check if manager is coach of rower. If not return 0
if manager.rower != rower:
if manager.rower != rower: # pragma: no cover
if rower not in coach_getcoachees(manager.rower):
return 0,'You are not allowed to create this alert'
@@ -85,7 +85,7 @@ def alert_add_filters(alert,filters):
# get alert stats
# nperiod = 0: current period, i.e. next_run - n days to today
# nperiod = 1: 1 period ago , i.e. next_run -2n days to next_run -n days
def alert_get_stats(alert,nperiod=0):
def alert_get_stats(alert,nperiod=0): # pragma: no cover
# get strokes
workstrokesonly = not alert.reststrokes
startdate = (alert.next_run - datetime.timedelta(days=(nperiod+1)*alert.period-1))
@@ -117,10 +117,10 @@ def alert_get_stats(alert,nperiod=0):
}
# check if filters are in columns list
pdcolumns = set(df.columns)
pdcolumns = set(df.columns) # pragma: no cover
# drop strokes through filter
if set(columns) <= pdcolumns:
if set(columns) <= pdcolumns: # pragma: no cover
for condition in alert.filter.all():
if condition.condition == '>':
mask = df[condition.metric] > condition.value1
@@ -137,7 +137,7 @@ def alert_get_stats(alert,nperiod=0):
df.loc[mask,alert.measured.metric] = np.nan
df.dropna(inplace=True,axis=0)
else:
else: # pragma: no cover
return {
'workouts':workouts.count(),
'startdate':startdate,
@@ -201,6 +201,6 @@ def alert_get_stats(alert,nperiod=0):
def checkalertowner(alert,user):
if alert.manager == user:
return True
if alert.rower.user == user:
if alert.rower.user == user: # pragma: no cover
return True
return False
return False # pragma: no cover
+51 -44
View File
@@ -34,7 +34,7 @@ from rowsandall_app.settings import (
BRAINTREE_SANDBOX_PRIVATE_KEY, BRAINTREE_MERCHANT_ACCOUNT_ID
)
if settings.DEBUG or 'dev' in settings.SITE_URL:
if settings.DEBUG or 'dev' in settings.SITE_URL: # pragma: no cover
gateway = braintree.BraintreeGateway(
braintree.Configuration(
braintree.Environment.Sandbox,
@@ -58,16 +58,20 @@ from rowers.models import Rower,PaidPlan, CoachingGroup
from rowers.utils import ProcessorCustomerError
def process_webhook(notification):
with open('braintreewebhooks.log','a') as f:
t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
f.write(timestamp+' '+notification.kind+'\n')
if not settings.TESTING: # pragma: no cover
with open('braintreewebhooks.log','a') as f:
t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
try:
f.write(timestamp+' '+notification.kind+'\n')
except TypeError:
f.write(timestamp+'\n')
if notification.kind == 'subscription_charged_successfully':
return send_invoice(notification.subscription)
if notification.kind == 'subscription_canceled':
subscription = notification.subscription
rs = Rower.objects.filter(subscription_id=subscription.id)
if rs.count() == 0:
if rs.count() == 0: # pragma: no cover
with open('braintreewebhooks.log','a') as f:
f.write('Could not find rowers with subscription ID '+subscription.id+'\n')
return 0
@@ -75,21 +79,21 @@ def process_webhook(notification):
result,mesg,errormsg = cancel_subscription(r,subscription.id)
if result:
with open('braintreewebhooks.log','a') as f:
f.write('Subscription canceled: '+subscription.id+'\n')
f.write('Subscription canceled: '+str(subscription.id)+'\n')
return subscription.id
with open('braintreewebhooks.log','a') as f:
f.write('Could not cancel Subscription: '+subscription.id+'\n')
return 0
with open('braintreewebhooks.log','a') as f: # pragma: no cover
f.write('Could not cancel Subscription: '+str(subscription.id)+'\n')
return 0 # pragma: no cover
return 0
def send_invoice(subscription):
with open('braintreewebhooks.log','a') as f:
t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
f.write('Subscription ID '+subscription.id+'\n')
f.write('Subscription ID '+str(subscription.id)+'\n')
subscription_id = subscription.id
rs = Rower.objects.filter(subscription_id=subscription_id)
if rs.count() == 0:
if rs.count() == 0: # pragma: no cover
return 0
else:
r = rs[0]
@@ -98,7 +102,7 @@ def send_invoice(subscription):
fakturoid_contact_id = fakturoid.get_contacts(r)
with open('braintreewebhooks.log','a') as f:
f.write('Fakturoid Contact ID '+str(fakturoid_contact_id)+'\n')
if not fakturoid_contact_id:
if not fakturoid_contact_id: # pragma: no cover
fakturoid_contact_id = fakturoid.create_contact(r)
with open('braintreewebhooks.log','a') as f:
f.write('Created Fakturoid Contact ID '+str(fakturoid_contact_id)+'\n')
@@ -111,7 +115,7 @@ def send_invoice(subscription):
contact_id=fakturoid_contact_id)
return id
return 0
return 0 # pragma: no cover
def webhook(request):
@@ -119,7 +123,7 @@ def webhook(request):
webhook_notification = gateway.webhook_notification.parse(
str(request.POST['bt_signature']),
request.POST['bt_payload'])
except InvalidSignatureError:
except InvalidSignatureError: # pragma: no cover
return 4
result = process_webhook(webhook_notification)
@@ -135,14 +139,14 @@ def create_customer(rower,force=False):
'last_name':rower.user.last_name,
'email':rower.user.email,
})
if not result.is_success:
if not result.is_success: # pragma: no cover
raise ProcessorCustomerError
else:
rower.customer_id = result.customer.id
rower.paymentprocessor = 'braintree'
rower.save()
return rower.customer_id
else:
else: # pragma: no cover
return rower.customer_id
@@ -152,7 +156,7 @@ def get_client_token(rower):
client_token = gateway.client_token.generate({
"customer_id":rower.customer_id,
})
except ValueError:
except ValueError: # pragma: no cover
customer_id = create_customer(rower,force=True)
client_token = gateway.client_token.generate({
@@ -161,7 +165,7 @@ def get_client_token(rower):
return client_token
def get_plans_costs():
def get_plans_costs(): # pragma: no cover
plans = gateway.plan.all()
localplans = PaidPlan.object.filter(paymentprocessor='braintree')
@@ -178,7 +182,7 @@ def make_payment(rower,data):
nonce_from_the_client = data['payment_method_nonce']
nonce = gateway.payment_method_nonce.find(nonce_from_the_client)
info = nonce.three_d_secure_info
if nonce.type.lower() == 'creditcard':
if nonce.type.lower() == 'creditcard': # pragma: no cover
if info is None or not info.liability_shifted:
return False,0
@@ -206,11 +210,14 @@ def make_payment(rower,data):
id = fakturoid.create_invoice(rower,amount,transaction.id,dosend=True,contact_id=fakturoid_contact_id,
name='Rowsandall Purchase')
job = myqueue(queuehigh,handle_send_email_transaction,
name, rower.user.email, amount)
try:
job = myqueue(queuehigh,handle_send_email_transaction,
name, rower.user.email, amount)
except: # pragma: no cover
pass
return amount,True
else:
else: # pragma: no cover
return 0,False
def update_subscription(rower,data,method='up'):
@@ -219,7 +226,7 @@ def update_subscription(rower,data,method='up'):
nonce_from_the_client = data['payment_method_nonce']
nonce = gateway.payment_method_nonce.find(nonce_from_the_client)
info = nonce.three_d_secure_info
if nonce.type.lower() == 'creditcard':
if nonce.type.lower() == 'creditcard': # pragma: no cover
if info is None or not info.liability_shifted:
return False,0
amount = data['amount']
@@ -238,7 +245,7 @@ def update_subscription(rower,data,method='up'):
if plan.paymenttype == 'single':
gatewaydata['number_of_billing_cycles'] = 1
else:
else: # pragma: no cover
gatewaydata['never_expires'] = True
try:
@@ -246,7 +253,7 @@ def update_subscription(rower,data,method='up'):
rower.subscription_id,
gatewaydata
)
except:
except: # pragma: no cover
return False,0
if result.is_success:
@@ -269,14 +276,14 @@ def update_subscription(rower,data,method='up'):
if rower.paidplan != 'coach':
try:
coachgroup = rower.mycoachgroup
except CoachingGroup.DoesNotExist:
except CoachingGroup.DoesNotExist: # pragma: no cover
coachgroup = CoachingGroup()
coachgroup.save()
rower.mycoachgroup = coachgroup
rower.save()
athletes = Rower.objects.filter(coachinggroups__in=[rower.mycoachgroup]).distinct()
for athlete in athletes:
for athlete in athletes: # pragma: no cover
athlete.coachinggroups.remove(rower.mycoachgroup)
if method == 'up':
@@ -284,9 +291,9 @@ def update_subscription(rower,data,method='up'):
if transactions:
amount = transactions[0].amount
else:
else: # pragma: no cover
amount = 0
else:
else: # pragma: no cover
amount = 0
@@ -301,7 +308,7 @@ def update_subscription(rower,data,method='up'):
method)
return True,amount
else:
else: # pragma: no cover
errors = result.errors.for_object("subscription")
codes = [str(e.code) for e in errors]
create_new = False
@@ -315,7 +322,7 @@ def update_subscription(rower,data,method='up'):
return False,0
return False,0
return False,0 # pragma: no cover
def create_subscription(rower,data):
@@ -324,7 +331,7 @@ def create_subscription(rower,data):
info = nonce.three_d_secure_info
paymenttype = nonce.type
if nonce.type != 'PayPalAccount':
if nonce.type != 'PayPalAccount': # pragma: no cover
if info is None or not info.liability_shifted:
return False,0
amount = data['amount']
@@ -343,7 +350,7 @@ def create_subscription(rower,data):
if result.is_success:
payment_method_token = result.payment_method.token
else:
else: # pragma: no cover
return False,0
result = gateway.subscription.create({
@@ -384,11 +391,11 @@ def create_subscription(rower,data):
result.subscription.billing_period_end_date.strftime('%Y-%m-%d')
)
return True,plan.price
else:
else: # pragma: no cover
return False,0
return False,0
return False,0 # pragma: no cover
def cancel_subscription(rower,id):
themessages = []
@@ -396,7 +403,7 @@ def cancel_subscription(rower,id):
try:
result = gateway.subscription.cancel(id)
themessages.append("Subscription canceled")
except:
except: # pragma: no cover
errormessages.append("We could not find the subscription record in our customer database. We have notified the site owner, who will contact you.")
@@ -425,29 +432,29 @@ def cancel_subscription(rower,id):
def find_subscriptions(rower):
try:
result = gateway.customer.find(rower.customer_id)
except:
except: # pragma: no cover
raise ProcessorCustomerError("We could not find the customer in the database")
active_subscriptions = []
cards = result.credit_cards
for card in cards:
for card in cards: # pragma: no cover
for subscription in card.subscriptions:
if subscription.status == 'Active':
active_subscriptions.append(subscription)
try:
paypal_accounts = result.paypal_accounts
for account in paypal_accounts:
for account in paypal_accounts: # pragma: no cover
for subscription in account.subscriptions:
if subscription.status == 'Active':
active_subscriptions.append(subscription)
except AttributeError:
except AttributeError: # pragma: no cover
pass
result = []
for subscription in active_subscriptions:
for subscription in active_subscriptions: # pragma: no cover
plan = PaidPlan.objects.filter(paymentprocessor="braintree",
external_id=subscription.plan_id)[0]
@@ -465,7 +472,7 @@ def find_subscriptions(rower):
return result
def get_transactions(start_date,end_date):
def get_transactions(start_date,end_date): # pragma: no cover
results = gateway.transaction.search(
braintree.TransactionSearch.created_at.between(
start_date,
@@ -552,5 +559,5 @@ def get_transactions(start_date,end_date):
return df
def mocktest(rower):
def mocktest(rower): # pragma: no cover
return '5'
+103 -183
View File
@@ -19,6 +19,7 @@ from iso8601 import ParseError
import numpy
import json
from scipy import optimize
from json.decoder import JSONDecodeError
from rowsandall_app.settings import (
@@ -41,7 +42,7 @@ from django.core.exceptions import PermissionDenied
def getagegrouprecord(age,sex='male',weightcategory='hwt',
distance=2000,duration=None,indf=pd.DataFrame()):
if not indf.empty:
if not indf.empty: # pragma: no cover
if not duration:
df = indf[indf['distance'] == distance]
else:
@@ -83,7 +84,7 @@ def getagegrouprecord(age,sex='male',weightcategory='hwt',
try:
p1, success = optimize.leastsq(errfunc,p0[:],
args = (ages,powers))
except:
except: # pragma: no cover
p1 = p0
success = 0
@@ -93,7 +94,7 @@ def getagegrouprecord(age,sex='male',weightcategory='hwt',
#power = np.polyval(poly_coefficients,age)
power = 0.5*(np.abs(power)+power)
else:
else: # pragma: no cover
power = 0
else:
power = 0
@@ -126,48 +127,26 @@ def c2_open(user):
else:
if (timezone.now()>r.tokenexpirydate):
res = rower_c2_token_refresh(user)
if res == None:
if res == None: # pragma: no cover
raise NoTokenError("User has no token")
if res[0] != None:
thetoken = res[0]
else:
else: # pragma: no cover
raise NoTokenError("User has no token")
else:
thetoken = r.c2token
return thetoken
def add_stroke_data(user,c2id,workoutid,startdatetime,csvfilename,
workouttype='rower'):
r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None):
return custom_exception_handler(401,s)
s = "Token doesn't exist. Need to authorize"
elif (timezone.now()>r.tokenexpirydate):
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
starttimeunix = arrow.get(startdatetime).timestamp()
job = myqueue(queue,
handle_c2_import_stroke_data,
r.c2token,
c2id,
workoutid,
starttimeunix,
csvfilename,workouttype=workouttype)
return 1
def get_c2_workouts(rower,do_async=True):
try:
thetoken = c2_open(rower.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return 0
res = get_c2_workout_list(rower.user,page=1)
if (res.status_code != 200):
if (res.status_code != 200): # pragma: no cover
return 0
else:
c2ids = [item['id'] for item in res.json()['data']]
@@ -189,13 +168,15 @@ def get_c2_workouts(rower,do_async=True):
with open('c2blocked.json','r') as c2blocked:
jsondata = json.load(c2blocked)
parkedids = jsondata['ids']
except FileNotFoundError:
except FileNotFoundError: # pragma: no cover
pass
knownc2ids = uniqify(knownc2ids+tombstones+parkedids)
newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
if settings.TESTING:
newids = c2ids
newparkedids = uniqify(newids+parkedids)
@@ -205,7 +186,7 @@ def get_c2_workouts(rower,do_async=True):
counter = 0
for c2id in newids:
if do_async:
if do_async: # pragma: no cover
res = myqueue(queuehigh,
handle_c2_async_workout,
alldata,
@@ -285,10 +266,10 @@ def create_async_workout(alldata,user,c2id):
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
try:
s = requests.get(url,headers=headers)
except ConnectionError:
except ConnectionError: # pragma: no cover
return 0
if s.status_code != 200:
if s.status_code != 200: # pragma: no cover
return 0
strokedata = pd.DataFrame.from_dict(s.json()['data'])
@@ -306,7 +287,7 @@ def create_async_workout(alldata,user,c2id):
nr_rows = len(unixtime)
try:
try: # pragma: no cover
latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon']
except:
@@ -323,12 +304,12 @@ def create_async_workout(alldata,user,c2id):
try:
spm = strokedata.loc[:,'spm']
except KeyError:
except KeyError: # pragma: no cover
spm = 0*dist2
try:
hr = strokedata.loc[:,'hr']
except KeyError:
except KeyError: # pragma: no cover
hr = 0*spm
pace = strokedata.loc[:,'p']/10.
@@ -337,7 +318,7 @@ def create_async_workout(alldata,user,c2id):
velo = 500./pace
power = 2.8*velo**3
if workouttype == 'bike':
if workouttype == 'bike': # pragma: no cover
velo = 1000./pace
df = pd.DataFrame({'TimeStamp (sec)':unixtime,
@@ -385,12 +366,12 @@ def create_async_workout(alldata,user,c2id):
response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
return 0
try:
workoutid = response.json()['id']
except KeyError:
except KeyError: # pragma: no cover
workoutid = 1
newc2id = Workout.objects.get(id=workoutid).uploadedtoc2
@@ -407,7 +388,7 @@ def create_async_workout(alldata,user,c2id):
json.dump(data,c2blocked)
# summary
if 'workout' in data:
if 'workout' in data: # pragma: no cover
if 'splits' in data['workout']:
splitdata = data['workout']['splits']
elif 'intervals' in data['workout']:
@@ -417,7 +398,7 @@ def create_async_workout(alldata,user,c2id):
else:
splitdata = False
if splitdata:
if splitdata: # pragma: no cover
summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,csvfilename,workouttype=workouttype)
w = Workout.objects.get(id=workoutid)
w.summary = summary
@@ -448,7 +429,7 @@ def makeseconds(t):
# convert our weight class code to Concept2 weight class code
def c2wc(weightclass):
if (weightclass=="lwt"):
if (weightclass=="lwt"): # pragma: no cover
res = "L"
else:
res = "H"
@@ -465,38 +446,38 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'):
totaltime = data['time']/10.
try:
spm = data['stroke_rate']
except KeyError:
except KeyError: # pragma: no cover
spm = 0
try:
resttime = data['rest_time']/10.
except KeyError:
except KeyError: # pragma: no cover
resttime = 0
try:
restdistance = data['rest_distance']
except KeyError:
except KeyError: # pragma: no cover
restdistance = 0
try:
avghr = data['heart_rate']['average']
except KeyError:
except KeyError: # pragma: no cover
avghr = 0
try:
maxhr = data['heart_rate']['max']
except KeyError:
except KeyError: # pragma: no cover
maxhr = 0
try:
avgpace = 500.*totaltime/totaldist
except (ZeroDivisionError,OverflowError):
except (ZeroDivisionError,OverflowError): # pragma: no cover
avgpace = 0.
try:
restpace = 500.*resttime/restdistance
except (ZeroDivisionError,OverflowError):
except (ZeroDivisionError,OverflowError): # pragma: no cover
restpace = 0.
velo = totaldist/totaltime
avgpower = 2.8*velo**(3.0)
if workouttype in ['bike','bikeerg']:
if workouttype in ['bike','bikeerg']: # pragma: no cover
velo = velo/2.
avgpower = 2.8*velo**(3.0)
velo = velo*2
@@ -504,18 +485,18 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'):
try:
restvelo = restdistance/resttime
except (ZeroDivisionError,OverflowError):
except (ZeroDivisionError,OverflowError): # pragma: no cover
restvelo = 0
restpower = 2.8*restvelo**(3.0)
if workouttype in ['bike','bikeerg']:
if workouttype in ['bike','bikeerg']: # pragma: no cover
restvelo = restvelo/2.
restpower = 2.8*restvelo**(3.0)
restvelo = restvelo*2
try:
avgdps = totaldist/data['stroke_count']
except (ZeroDivisionError,OverflowError,KeyError):
except (ZeroDivisionError,OverflowError,KeyError): # pragma: no cover
avgdps = 0
from rowingdata import summarystring,workstring,interval_string
@@ -543,45 +524,45 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'):
try:
timebased = data['workout_type'] in ['FixedTimeSplits','FixedTimeInterval']
except KeyError:
except KeyError: # pragma: no cover
timebased = False
for interval in splitdata:
try:
idist = interval['distance']
except KeyError:
except KeyError: # pragma: no cover
idist = 0
try:
itime = interval['time']/10.
except KeyError:
except KeyError: # pragma: no cover
itime = 0
try:
ipace = 500.*itime/idist
except (ZeroDivisionError,OverflowError):
except (ZeroDivisionError,OverflowError): # pragma: no cover
ipace = 180.
try:
ispm = interval['stroke_rate']
except KeyError:
except KeyError: # pragma: no cover
ispm = 0
try:
irest_time = interval['rest_time']/10.
except KeyError:
except KeyError: # pragma: no cover
irest_time = 0
try:
iavghr = interval['heart_rate']['average']
except KeyError:
except KeyError: # pragma: no cover
iavghr = 0
try:
imaxhr = interval['heart_rate']['average']
except KeyError:
except KeyError: # pragma: no cover
imaxhr = 0
# create interval values
iarr = [idist,'meters','work']
resarr = [itime]
if timebased:
if timebased: # pragma: no cover
iarr = [itime,'seconds','work']
resarr = [idist]
@@ -589,7 +570,7 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'):
iarr += [irest_time,'seconds','rest']
try:
resarr += [interval['rest_distance']]
except KeyError:
except KeyError: # pragma: no cover
resarr += [np.nan]
sa += iarr
@@ -598,9 +579,9 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'):
if itime != 0:
ivelo = idist/itime
ipower = 2.8*ivelo**(3.0)
if workouttype in ['bike','bikeerg']:
if workouttype in ['bike','bikeerg']: # pragma: no cover
ipower = 2.8*(ivelo/2.)**(3.0)
else:
else: # pragma: no cover
ivelo = 0
ipower = 0
@@ -610,70 +591,6 @@ def summaryfromsplitdata(splitdata,data,filename,sep='|',workouttype='rower'):
return sums,sa,results
# Not used now. Could be used to add workout split data to Concept2
# logbook but needs to be reviewed.
def createc2workoutdata_as_splits(w):
filename = w.csvfilename
row = rowingdata(csvfile=filename)
# resize per minute
df = row.df.groupby(lambda x:x/60).mean()
averagehr = int(df[' HRCur (bpm)'].mean())
maxhr = int(df[' HRCur (bpm)'].max())
# adding diff, trying to see if this is valid
t = 10*df.loc[:,' ElapsedTime (sec)'].diff().values
t[0] = t[1]
d = df.loc[:,' Horizontal (meters)'].diff().values
d[0] = d[1]
p = 10*df.loc[:,' Stroke500mPace (sec/500m)'].values
t = t.astype(int)
d = d.astype(int)
p = p.astype(int)
spm = df[' Cadence (stokes/min)'].astype(int)
spm[0] = spm[1]
hr = df[' HRCur (bpm)'].astype(int)
split_data = []
for i in range(len(t)):
thisrecord = {"time":t[i],"distance":d[i],"stroke_rate":spm[i],
"heart_rate":{
"average:":hr[i]
}
}
split_data.append(thisrecord)
try:
durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S.%f")
except ValueError:
durationstr = datetime.datetime.strptime(str(w.duration),"%H:%M:%S")
try:
newnotes = w.notes+'\n from '+w.workoutsource+' via rowsandall.com'
except TypeError:
newnotes = 'from '+w.workoutsource+' via rowsandall.com'
wtype = w.workouttype
if wtype in otwtypes:
wtype = 'water'
data = {
"type": wtype,
"date": w.startdatetime.isoformat(),
"distance": int(w.distance),
"time": int(10*makeseconds(durationstr)),
"timezone": w.timezone,
"weight_class": c2wc(w.weightcategory),
"comments": newnotes,
"heart_rate": {
"average": averagehr,
"max": maxhr,
},
"splits": split_data,
}
return data
# Create the Data object for the stroke data to be sent to Concept2 logbook
# API
@@ -681,21 +598,24 @@ def createc2workoutdata(w):
filename = w.csvfilename
try:
row = rowingdata(csvfile=filename)
except IOError:
except IOError: # pragma: no cover
return 0
try:
averagehr = int(row.df[' HRCur (bpm)'].mean())
maxhr = int(row.df[' HRCur (bpm)'].max())
except ValueError:
except (ValueError,KeyError): # pragma: no cover
averagehr = 0
maxhr = 0
# Calculate intervalstats
itime, idist, itype = row.intervalstats_values()
lapnames = row.df[' lapIdx'].unique()
try:
lapnames = row.df[' lapIdx'].unique()
except KeyError: # pragma: no cover
lapnames = range(len(itime))
nrintervals = len(itime)
if len(lapnames != nrintervals):
if len(lapnames) != nrintervals:
newlapnames = []
for name in lapnames:
newlapnames += [name,name]
@@ -721,18 +641,18 @@ def createc2workoutdata(w):
t = 10*row.df.loc[:,'TimeStamp (sec)'].values-10*row.df.loc[:,'TimeStamp (sec)'].iloc[0]
try:
t[0] = t[1]
except IndexError:
except IndexError: # pragma: no cover
pass
d = 10*row.df.loc[:,' Horizontal (meters)'].values
try:
d[0] = d[1]
except IndexError:
except IndexError: # pragma: no cover
pass
p = abs(10*row.df.loc[:,' Stroke500mPace (sec/500m)'].values)
p = np.clip(p,0,3600)
if w.workouttype == 'bike':
if w.workouttype == 'bike': # pragma: no cover
p = 2.0*p
t = t.astype(int)
@@ -742,11 +662,11 @@ def createc2workoutdata(w):
try:
spm[0] = spm[1]
except (KeyError,IndexError):
except (KeyError,IndexError): # pragma: no cover
spm = 0*t
try:
hr = row.df[' HRCur (bpm)'].astype(int)
except ValueError:
except ValueError: # pragma: no cover
hr = 0*d
stroke_data = []
@@ -822,14 +742,14 @@ def do_refresh_token(refreshtoken):
try:
token_json = response.json()
except JSONDecodeError:
except JSONDecodeError: # pragma: no cover
return [None,None,None]
try:
thetoken = token_json['access_token']
expires_in = token_json['expires_in']
refresh_token = token_json['refresh_token']
except:
except: # pragma: no cover
with open("media/c2errors.log","a") as errorlog:
errorstring = str(sys.exc_info()[0])
timestr = time.strftime("%Y%m%d-%H%M%S")
@@ -868,25 +788,25 @@ def get_token(code):
try:
status_code = response.status_code
# status_code = token_json['status_code']
except AttributeError:
except AttributeError: # pragma: no cover
# except KeyError:
return (0,response.text)
try:
status_code = token_json.status_code
except AttributeError:
except AttributeError: # pragma: no cover
return (0,'Attribute Error on c2_get_token')
if status_code == 200:
thetoken = token_json['access_token']
expires_in = token_json['expires_in']
refresh_token = token_json['refresh_token']
else:
else: # pragma: no cover
return (0,token_json['message'])
return (thetoken,expires_in,refresh_token,messg)
# Make URL for authorization and load it
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
from uuid import uuid4
@@ -904,7 +824,7 @@ def make_authorization_url(request):
# Get workout from C2 ID
def get_workout(user,c2id,do_async=False):
r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None):
if (r.c2token == '') or (r.c2token is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s) ,0
elif (timezone.now()>r.tokenexpirydate):
@@ -919,7 +839,7 @@ def get_workout(user,c2id,do_async=False):
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)
s = requests.get(url,headers=headers)
if s.status_code != 200:
if s.status_code != 200: # pragma: no cover
if s.status_code == 404:
raise PermissionDenied("You have no access to this resource")
else:
@@ -930,11 +850,11 @@ def get_workout(user,c2id,do_async=False):
splitdata = None
if 'workout' in data:
if 'splits' in data['workout']:
if 'splits' in data['workout']: # pragma: no cover
splitdata = data['workout']['splits']
elif 'intervals' in data['workout']:
elif 'intervals' in data['workout']: # pragma: no cover
splitdata = data['workout']['intervals']
else:
else: # pragma: no cover
splitdata = None
# Check if workout has stroke data, and get the stroke data
@@ -943,9 +863,9 @@ def get_workout(user,c2id,do_async=False):
res2 = get_c2_workout_strokes(user,c2id)
if res2.status_code == 200:
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
else:
else: # pragma: no cover
strokedata = pd.DataFrame()
else:
else: # pragma: no cover
strokedata = pd.DataFrame()
return data,strokedata
@@ -953,10 +873,10 @@ def get_workout(user,c2id,do_async=False):
# Get stroke data belonging to C2 ID
def get_c2_workout_strokes(user,c2id):
r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None):
if (r.c2token == '') or (r.c2token is None): # pragma: no cover
return custom_exception_handler(401,s)
s = "Token doesn't exist. Need to authorize"
elif (timezone.now()>r.tokenexpirydate):
elif (timezone.now()>r.tokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
@@ -974,10 +894,10 @@ def get_c2_workout_strokes(user,c2id):
# assuming that users don't want to import their old workouts
def get_c2_workout_list(user,page=1):
r = Rower.objects.get(user=user)
if (r.c2token == '') or (r.c2token is None):
if (r.c2token == '') or (r.c2token is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s)
elif (timezone.now()>r.tokenexpirydate):
elif (timezone.now()>r.tokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
@@ -997,7 +917,7 @@ def get_c2_workout_list(user,page=1):
# Get username, having access token.
# Handy for checking if the API access is working
def get_username(access_token):
def get_username(access_token): # pragma: no cover
authorizationstring = str('Bearer ' + access_token)
headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
@@ -1028,23 +948,23 @@ def get_userid(access_token):
url = "https://log.concept2.com/api/users/me"
try:
response = requests.get(url,headers=headers)
except:
except: # pragma: no cover
return 0
try:
me_json = response.json()
except:
except: # pragma: no cover
return 0
try:
res = me_json['data']['id']
except KeyError:
except KeyError: # pragma: no cover
return 0
return res
# For debugging purposes
def process_callback(request):
def process_callback(request): # pragma: no cover
# need error handling
code = request.GET['code']
@@ -1055,7 +975,7 @@ def process_callback(request):
return HttpResponse("got a user name: %s" % username)
def default(o):
def default(o): # pragma: no cover
if isinstance(o, numpy.int64): return int(o)
raise TypeError
@@ -1063,9 +983,9 @@ def default(o):
def workout_c2_upload(user,w,asynchron=False):
message = 'trying C2 upload'
try:
if mytypes.c2mapping[w.workouttype] is None:
if mytypes.c2mapping[w.workouttype] is None: # pragma: no cover
return "This workout type cannot be uploaded to Concept2",0
except KeyError:
except KeyError: # pragma: no cover
return "This workout type cannot be uploaded to Concept2",0
thetoken = c2_open(user)
@@ -1075,12 +995,12 @@ def workout_c2_upload(user,w,asynchron=False):
# ready to upload. Hurray
if (is_workout_user(user,w)):
c2userid = get_userid(r.c2token)
if not c2userid:
if not c2userid: # pragma: no cover
raise NoTokenError("User has no token")
data = createc2workoutdata(w)
if data == 0:
if data == 0: # pragma: no cover
return "Error: No data file. Contact info@rowsandall.com if the problem persists",0
authorizationstring = str('Bearer ' + r.c2token)
@@ -1093,7 +1013,7 @@ def workout_c2_upload(user,w,asynchron=False):
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
if (response.status_code == 409 ):
if (response.status_code == 409 ): # pragma: no cover
message = "Concept2 Duplicate error"
w.uploadedtoc2 = -1
c2id = -1
@@ -1105,10 +1025,10 @@ def workout_c2_upload(user,w,asynchron=False):
w.uploadedtoc2 = c2id
w.save()
message = "Upload to Concept2 was successful"
else:
else: # pragma: no cover
message = "Something went wrong in workout_c2_upload_view. Response code 200/201 but C2 sync failed: "+response.text
c2id = 0
else:
else: # pragma: no cover
job = myqueue(queue,
handle_c2_sync,
w.id,
@@ -1136,7 +1056,7 @@ def rower_c2_token_refresh(user):
r.save()
return r.c2token
else:
else: # pragma: no cover
return None
# Create workout data from Strava or Concept2
@@ -1146,14 +1066,14 @@ def add_workout_from_data(user,importid,data,strokedata,
workoutsource='concept2'):
try:
workouttype = mytypes.c2mappinginv[data['type']]
except KeyError:
except KeyError: # pragma: no cover
workouttype = 'rower'
if workouttype not in [x[0] for x in Workout.workouttypes]:
if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover
workouttype = 'other'
try:
comments = data['comments']
except:
except: # pragma: no cover
comments = ' '
try:
@@ -1165,9 +1085,9 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
rowdatetime = iso8601.parse_date(data['date_utc'])
except KeyError:
except KeyError: # pragma: no cover
rowdatetime = iso8601.parse_date(data['start_date'])
except ParseError:
except ParseError: # pragma: no cover
rowdatetime = iso8601.parse_date(data['date'])
@@ -1175,7 +1095,7 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
c2intervaltype = data['workout_type']
except KeyError:
except KeyError: # pragma: no cover
c2intervaltype = ''
try:
@@ -1185,12 +1105,12 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
t = data['comments'].split('\n', 1)[0]
title += t[:40]
except:
except: # pragma: no cover
title = ''
try:
comments = data['comments']
except KeyError:
except KeyError: # pragma: no cover
comments = ''
starttimeunix = arrow.get(rowdatetime).timestamp()
@@ -1207,7 +1127,7 @@ def add_workout_from_data(user,importid,data,strokedata,
nr_rows = len(unixtime)
try:
try: # pragma: no cover
latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon']
except:
@@ -1224,12 +1144,12 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
spm = strokedata.loc[:,'spm']
except KeyError:
except KeyError: # pragma: no cover
spm = 0*dist2
try:
hr = strokedata.loc[:,'hr']
except KeyError:
except KeyError: # pragma: no cover
hr = 0*spm
pace = strokedata.loc[:,'p']/10.
pace = np.clip(pace,0,1e4)
@@ -1237,7 +1157,7 @@ def add_workout_from_data(user,importid,data,strokedata,
velo = 500./pace
power = 2.8*velo**3
if workouttype in ['bike','bikeerg']:
if workouttype in ['bike','bikeerg']: # pragma: no cover
velo = 1000./pace
pace = 500./velo
@@ -1285,10 +1205,10 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
totaldist = data['distance']
totaltime = data['time']/10.
except KeyError:
except KeyError: # pragma: no cover
totaldist = 0
totaltime = 0
else:
else: # pragma: no cover
totaldist = 0
totaltime = 0
+1 -1
View File
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
from django.conf import settings # import the settings file
def braintree_merchant(request):
def braintree_merchant(request): # pragma: no cover
# return the value you want as a dictionnary. you may add multiple values in there.
# return {'BRAINTREE_MERCHANT_ID': settings.BRAINTREE_MERCHANT_ID}
return {'BRAINTREE_MERCHANT_ID': 'jytq7yxsm66qqdzb' }
+6 -6
View File
@@ -83,7 +83,7 @@ def get_polygons(polygonpms):
coordinates = pm.findall('.//opengis:coordinates',ns)
if coordinates:
cc = coordinates[0].text
else:
else: # pragma: no cover
cc = ''
pointstring = cc.split()
@@ -157,7 +157,7 @@ def kmltocourse(f):
doc = et.parse(f)
courses = doc.findall('.//opengis:Folder[opengis:Placemark]',ns)
if not courses:
if not courses: # pragma: no cover
courses = doc.findall('.//opengis:Document[opengis:Placemark]',ns)
if not courses:
courses = doc.findall('.//opengis:Placemark',ns)
@@ -165,9 +165,9 @@ def kmltocourse(f):
if courses:
return crewnerdcourse(courses)
polygonpms = doc.findall('.//opengis:Placemark[opengis:Polygon]',ns)
polygonpms = doc.findall('.//opengis:Placemark[opengis:Polygon]',ns) # pragma: no cover
return get_polygons(polygonpms)
return get_polygons(polygonpms) # pragma: no cover
@@ -190,7 +190,7 @@ def createcourse(
g = geocoder.osm([latitude,longitude],method='reverse')
if g.ok:
country = g.json['country']
else:
else: # pragma: no cover
country = 'unknown'
c.country = country
c.save()
@@ -210,7 +210,7 @@ def createcourse(
return c
def get_time_course(ws,course):
def get_time_course(ws,course): # pragma: no cover
coursetimeseconds = 0.0
coursecompleted = False
+19 -19
View File
@@ -13,15 +13,15 @@ def coordinate_in_path(latitude,longitude, p):
return p.contains_points([(latitude,longitude)])[0]
class InvalidTrajectoryError(Exception):
def __init__(self,value):
def __init__(self,value): # pragma: no cover
self.value=value
def __str__(self):
def __str__(self): # pragma: no cover
return repr(self.value)
def time_in_path(df,p,maxmin='max',getall=False,name='unknown',logfile=None):
if df.empty:
if df.empty: # pragma: no cover
return 0
latitude = df.latitude
@@ -33,12 +33,12 @@ def time_in_path(df,p,maxmin='max',getall=False,name='unknown',logfile=None):
if maxmin=='max':
b = (~df['inpolygon']).shift(-1)+df['inpolygon']
else:
else: # pragma: no cover
b = (~df['inpolygon']).shift(1)+df['inpolygon']
if len(df[b==2]):
if logfile is not None:
if logfile is not None: # pragma: no cover
t = time.localtime()
timestamp = bytes('{t}'.format(t=time.strftime('%b-%d-%Y_%H%M', t)),'utf-8')
with open(logfile,'ab') as f:
@@ -57,12 +57,12 @@ def time_in_path(df,p,maxmin='max',getall=False,name='unknown',logfile=None):
f.write(b' passes found')
else:
f.write(b' pass found')
if getall:
if getall: # pragma: no cover
return df[b==2]['time'],df[b==2]['cum_dist']
else:
return df[b==2]['time'].min(),df[b==2]['cum_dist'].min()
if logfile is not None:
if logfile is not None: # pragma: no cover
t = time.localtime()
timestamp = bytes('{t}'.format(t=time.strftime('%b-%d-%Y_%H%M', t)),'utf-8')
with open(logfile,'ab') as f:
@@ -78,10 +78,10 @@ def time_in_path(df,p,maxmin='max',getall=False,name='unknown',logfile=None):
f.write(bytes(str(len(df[b==2])),'utf-8'))
f.write(b' ')
f.write(b' pass not found')
raise InvalidTrajectoryError("Trajectory doesn't go through path")
raise InvalidTrajectoryError("Trajectory doesn't go through path") # pragma: no cover
return 0
return 0 # pragma: no cover
def coursetime_first(data,paths,polygons=[],logfile=None):
@@ -97,7 +97,7 @@ def coursetime_first(data,paths,polygons=[],logfile=None):
try:
entrytime,entrydistance = time_in_path(data,paths[0],maxmin='max',name=polygons[0][1],logfile=logfile)
coursecompleted = True
except InvalidTrajectoryError:
except InvalidTrajectoryError: # pragma: no cover
entrytime = data['time'].max()
entrydistance = data['cum_dist'].max()
coursecompleted = False
@@ -113,8 +113,8 @@ def coursetime_paths(data,paths,finalmaxmin='min',polygons=[],logfile=None):
polygons = [(0,str(i)) for i in range(len(paths))]
# corner case - empty list of paths
if len(paths) == 0:
return 0,True
if len(paths) == 0: # pragma: no cover
return 0,0,True
# end - just the Finish polygon
if len(paths) == 1:
@@ -124,7 +124,7 @@ def coursetime_paths(data,paths,finalmaxmin='min',polygons=[],logfile=None):
entrydistance
) = time_in_path(data,paths[0],maxmin=finalmaxmin,name = polygons[0][1],logfile=logfile)
coursecompleted = True
except InvalidTrajectoryError:
except InvalidTrajectoryError: # pragma: no cover
entrytime = data['time'].max()
entrydistance = data['cum_dist'].max()
coursecompleted = False
@@ -133,18 +133,18 @@ def coursetime_paths(data,paths,finalmaxmin='min',polygons=[],logfile=None):
if len(paths) > 1:
try:
time,dist = time_in_path(data, paths[0],name=polygons[0][1],logfile=logfile)
data = data[data['time']>time]
data['time'] = data['time']-time
data['cum_dist'] = data['cum_dist']-dist
data2 = data[data['time']>time].copy()
data2['time'] = data2['time'].apply(lambda x:x-time)
data2['cum_dist'] = data2['cum_dist'].apply(lambda x:x-dist)
(
timenext,
distnext,
coursecompleted
) = coursetime_paths(data,paths[1:],polygons=polygons[1:],logfile=logfile)
) = coursetime_paths(data2,paths[1:],polygons=polygons[1:],logfile=logfile)
return time+timenext, dist+distnext,coursecompleted
except InvalidTrajectoryError:
except InvalidTrajectoryError: # pragma: no cover
entrytime = data['time'].max()
entrydistance = data['cum_dist'].max()
coursecompleted = False
return entrytime, entrydistance, coursecompleted
return entrytime, entrydistance, coursecompleted # pragma: no cover
+29 -22
View File
@@ -92,7 +92,7 @@ import sqlalchemy as sa
import sys
import rowers.utils as utils
import rowers.datautils as datautils
from rowers.utils import lbstoN,myqueue,is_ranking_piece,wavg
from rowers.utils import lbstoN,myqueue,wavg
from timezonefinder import TimezoneFinder
@@ -265,7 +265,7 @@ def get_latlon(id):
rowdata = rdata(w.csvfilename)
if rowdata.df.empty: # pragma: no cover
return [pd.Series([]), pd.Series([])]
return [pd.Series([],dtype='float'), pd.Series([],dtype='float')]
try:
try:
@@ -276,9 +276,9 @@ def get_latlon(id):
longitude = 0 * rowdata.df.loc[:, 'TimeStamp (sec)']
return [latitude, longitude]
except AttributeError: # pragma: no cover
return [pd.Series([]), pd.Series([])]
return [pd.Series([],dtype='float'), pd.Series([],dtype='float')]
return [pd.Series([]), pd.Series([])] # pragma: no cover
return [pd.Series([],dtype='float'), pd.Series([],dtype='float')] # pragma: no cover
def get_latlon_time(id):
try:
@@ -290,7 +290,7 @@ def get_latlon_time(id):
rowdata = rdata(w.csvfilename)
if rowdata.df.empty: # pragma: no cover
return [pd.Series([]), pd.Series([])]
return [pd.Series([],dtype='float'), pd.Series([],dtype='float')]
try:
try:
@@ -1099,10 +1099,14 @@ def calculate_goldmedalstandard(rower,workout,recurrance=True):
try:
df = pd.read_parquet(cpfile)
except:
df, delta, cpvalues = setcp(workout,background=True)
background = True
if settings.TESTING:
background = False
df, delta, cpvalues = setcp(workout,background=background)
if df.empty:
return 0,0
if df.empty and recurrance: # pragma: no cover
df, delta, cpvalues = setcp(workout,recurrance=False,background=True)
if df.empty:
@@ -1110,12 +1114,15 @@ def calculate_goldmedalstandard(rower,workout,recurrance=True):
age = calculate_age(rower.birthdate,today=workout.date)
agerecords = CalcAgePerformance.objects.filter(
age=age,
sex=rower.sex,
weightcategory = rower.weightcategory
)
wcdurations = []
wcpower = []
getrecords = False
@@ -1145,8 +1152,8 @@ def calculate_goldmedalstandard(rower,workout,recurrance=True):
job = myqueue(queuelow,handle_getagegrouprecords,
jsondf,distances,durations,age,rower.sex,rower.weightcategory)
wcpower = pd.Series(wcpower)
wcdurations = pd.Series(wcdurations)
wcpower = pd.Series(wcpower,dtype='float')
wcdurations = pd.Series(wcdurations,dtype='float')
fitfunc = lambda pars,x: pars[0]/(1+(x/pars[2])) + pars[1]/(1+(x/pars[3]))
errfunc = lambda pars,x,y: fitfunc(pars,x)-y
@@ -1196,14 +1203,14 @@ def fetchcp_new(rower,workouts):
if len(data) == 0:
return pd.Series(),pd.Series(),0,pd.Series(),pd.Series()
return pd.Series(dtype='float'),pd.Series(dtype='float'),0,pd.Series(dtype='float'),pd.Series(dtype='float')
if len(data)>1:
df = pd.concat(data,axis=0)
try:
df = df[df['cp'] == df.groupby(['delta'])['cp'].transform('max')]
except KeyError: # pragma: no cover
pd.Series(),pd.Series(),0,pd.Series(),pd.Series()
return pd.Series(dtype='float'),pd.Series(dtype='float'),0,pd.Series(dtype='float'),pd.Series(dtype='float')
df = df.sort_values(['delta']).reset_index()
@@ -1214,16 +1221,16 @@ def setcp(workout,background=False,recurrance=True):
filename = 'media/cpdata_{id}.parquet.gz'.format(id=workout.id)
strokesdf = getsmallrowdata_db(['power','workoutid','time'],ids = [workout.id])
try:
if strokesdf['power'].std()==0:
return pd.DataFrame(),pd.Series(),pd.Series()
return pd.DataFrame(),pd.Series(dtype='float'),pd.Series(dtype='float')
except KeyError:
return pd.DataFrame(),pd.Series(),pd.Series()
return pd.DataFrame(),pd.Series(dtype='float'),pd.Series(dtype='float')
if background:
if background: # pragma: no cover
job = myqueue(queuelow,handle_setcp,strokesdf,filename,workout.id)
return pd.DataFrame({'delta':[],'cp':[]}),pd.Series(),pd.Series()
return pd.DataFrame({'delta':[],'cp':[]}),pd.Series(dtype='float'),pd.Series(dtype='float')
if not strokesdf.empty:
totaltime = strokesdf['time'].max()
@@ -1254,7 +1261,7 @@ def setcp(workout,background=False,recurrance=True):
workout.save()
return df,delta,cpvalues
return pd.DataFrame({'delta':[],'cp':[]}),pd.Series(),pd.Series()
return pd.DataFrame({'delta':[],'cp':[]}),pd.Series(dtype='float'),pd.Series(dtype='float')
def update_rolling_cp(r,types,mode='water'):
firstdate = datetime.date.today()-datetime.timedelta(days=r.cprange)
@@ -1308,20 +1315,20 @@ def fetchcp(rower,theworkouts,table='cpdata'): # pragma: no cover
avgpower2 = {}
for id in theids:
avgpower2[id] = 0
return pd.Series([]),pd.Series([]),avgpower2
return pd.Series([],dtype='float'),pd.Series([],dtype='float'),avgpower2
try:
dfgrouped = df.groupby(['workoutid'])
except KeyError:
avgpower2 = {}
return pd.Series([]),pd.Series([]),avgpower2
return pd.Series([],dtype='float'),pd.Series([],dtype='float'),avgpower2
try:
avgpower2 = dict(dfgrouped.mean()['power'].astype(int))
except KeyError:
avgpower2 = {}
for id in theids:
avgpower2[id] = 0
return pd.Series([]),pd.Series([]),avgpower2
return pd.Series([],dtype='float'),pd.Series([],dtype='float'),avgpower2
cpdf = getcpdata_sql(rower.id,table=table)
@@ -1334,10 +1341,10 @@ def fetchcp(rower,theworkouts,table='cpdata'): # pragma: no cover
theids,
table=table)
return pd.Series([]),pd.Series([]),avgpower2
return pd.Series([],dtype='float'),pd.Series([],dtype='float'),avgpower2
return pd.Series([]),pd.Series([]),avgpower2
return pd.Series([],dtype='float'),pd.Series([],dtype='float'),avgpower2
# create a new workout from manually entered data
@@ -1624,7 +1631,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
else: # pragma: no cover
velo2 = velo
velo3 = pd.Series(velo2)
velo3 = pd.Series(velo2,dtype='float')
velo3 = velo3.replace([-np.inf, np.inf], np.nan)
velo3 = velo3.fillna(method='ffill')
+65 -65
View File
@@ -38,24 +38,24 @@ from timezonefinder import TimezoneFinder
try:
user = DATABASES['default']['USER']
except KeyError:
except KeyError: # pragma: no cover
user = ''
try:
password = DATABASES['default']['PASSWORD']
except KeyError:
except KeyError: # pragma: no cover
password = ''
try:
database_name = DATABASES['default']['NAME']
except KeyError:
except KeyError: # pragma: no cover
database_name = ''
try:
host = DATABASES['default']['HOST']
except KeyError:
except KeyError: # pragma: no cover
host = ''
try:
port = DATABASES['default']['PORT']
except KeyError:
except KeyError: # pragma: no cover
port = ''
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
@@ -113,7 +113,7 @@ def strfdelta(tdelta):
try:
minutes,seconds = divmod(tdelta.seconds,60)
tenths = int(tdelta.microseconds/1e5)
except AttributeError:
except AttributeError: # pragma: no cover
minutes,seconds = divmod(tdelta.view(np.int64),60e9)
seconds,rest = divmod(seconds,1e9)
tenths = int(rest/1e8)
@@ -137,13 +137,13 @@ def nicepaceformat(values):
def timedeltaconv(x):
if not np.isnan(x):
dt = datetime.timedelta(seconds=x)
else:
else: # pragma: no cover
dt = datetime.timedelta(seconds=350.)
return dt
def rdata(file,rower=rrower()):
def rdata(file,rower=rrower()): # pragma: no cover
try:
res = rrdata(csvfile=file,rower=rower)
except IOError:
@@ -161,7 +161,7 @@ from rowers.metrics import dtypes
# Creates C2 stroke data
def create_c2_stroke_data_db(
distance,duration,workouttype,
workoutid,starttimeunix,csvfilename,debug=False):
workoutid,starttimeunix,csvfilename,debug=False): # pragma: no cover
nr_strokes = int(distance/10.)
@@ -247,7 +247,7 @@ def add_c2_stroke_data_db(strokedata,workoutid,starttimeunix,csvfilename,
nr_rows = len(unixtime)
try:
try: # pragma: no cover
latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon']
except:
@@ -264,12 +264,12 @@ def add_c2_stroke_data_db(strokedata,workoutid,starttimeunix,csvfilename,
try:
spm = strokedata.loc[:,'spm']
except KeyError:
except KeyError: # pragma: no cover
spm = 0*dist2
try:
hr = strokedata.loc[:,'hr']
except KeyError:
except KeyError: # pragma: no cover
hr = 0*spm
pace = strokedata.loc[:,'p']/10.
@@ -278,7 +278,7 @@ def add_c2_stroke_data_db(strokedata,workoutid,starttimeunix,csvfilename,
velo = 500./pace
power = 2.8*velo**3
if workouttype == 'bike':
if workouttype == 'bike': # pragma: no cover
velo = 1000./pace
@@ -320,13 +320,13 @@ def add_c2_stroke_data_db(strokedata,workoutid,starttimeunix,csvfilename,
try:
data = dataprep(df,id=workoutid,bands=False,debug=debug)
except:
except: # pragma: no cover
return 0
return data
def handle_nonpainsled(f2,fileformat,summary=''):
def handle_nonpainsled(f2,fileformat,summary=''): # pragma: no cover
oarlength = 2.89
inboard = 0.88
# handle RowPro:
@@ -413,19 +413,19 @@ def delete_strokedata(id,debug=False):
dirname = 'media/strokedata_{id}.parquet.gz'.format(id=id)
try:
shutil.rmtree(dirname)
except FileNotFoundError:
except FileNotFoundError: # pragma: no cover
pass
def update_strokedata(id,df,debug=False):
delete_strokedata(id,debug=debug)
if debug:
if debug: # pragma: no cover # pragma: no cover
print("updating ",id)
rowdata = dataprep(df,id=id,bands=True,barchart=True,otwpower=True,
debug=debug)
return rowdata
def update_empower(id, inboard, oarlength, boattype, df, f1, debug=False):
def update_empower(id, inboard, oarlength, boattype, df, f1, debug=False): # pragma: no cover
corr_factor = 1.0
if 'x' in boattype:
@@ -452,11 +452,11 @@ def update_empower(id, inboard, oarlength, boattype, df, f1, debug=False):
if success:
delete_strokedata(id,debug=debug)
if debug:
if debug: # pragma: no cover
print("updated ",id)
print("correction ",corr_factor)
else:
if debug:
if debug: # pragma: no cover
print("not updated ",id)
@@ -469,7 +469,7 @@ def update_empower(id, inboard, oarlength, boattype, df, f1, debug=False):
return success
def testdata(time,distance,pace,spm):
def testdata(time,distance,pace,spm): # pragma: no cover
t1 = np.issubdtype(time,np.number)
t2 = np.issubdtype(distance,np.number)
t3 = np.issubdtype(pace,np.number)
@@ -486,7 +486,7 @@ def getsmallrowdata_db(columns,ids=[],debug=False):
df = pd.DataFrame()
if len(ids)>1:
if len(ids)>1: # pragma: no cover
for id, f in zip(ids,csvfilenames):
try:
df = pd.read_parquet(f,columns=columns,engine='pyarrow')
@@ -503,16 +503,16 @@ def getsmallrowdata_db(columns,ids=[],debug=False):
elif len(ids)==1:
try:
df = pd.read_parquet(csvfilenames[0],columns=columns,engine='pyarrow')
except (OSError,IndexError):
except (OSError,IndexError): # pragma: no cover
df = pd.DataFrame()
else:
else: # pragma: no cover
df = pd.DataFrame()
return df
def update_workout_field_sql(workoutid,fieldname,value,debug=False):
if debug:
if debug: # pragma: no cover # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
@@ -530,7 +530,7 @@ def update_workout_field_sql(workoutid,fieldname,value,debug=False):
return 1
def update_c2id_sql(id,c2id):
def update_c2id_sql(id,c2id): # pragma: no cover
engine = create_engine(database_url, echo=False)
table = 'rowers_workout'
@@ -548,7 +548,7 @@ def update_c2id_sql(id,c2id):
def read_cols_df_sql(ids,columns,debug=False):
def read_cols_df_sql(ids,columns,debug=False): # pragma: no cover
columns = list(columns)+['distance','spm']
columns = [x for x in columns if x != 'None']
columns = list(set(columns))
@@ -579,7 +579,7 @@ def read_cols_df_sql(ids,columns,debug=False):
return df
def read_df_sql(id,debug=False):
def read_df_sql(id,debug=False): # pragma: no cover
try:
f = 'media/strokedata_{id}.parquet.gz'.format(id=id)
df = pd.read_parquet(f)
@@ -590,8 +590,8 @@ def read_df_sql(id,debug=False):
return df
def getcpdata_sql(rower_id,table='cpdata',debug=False):
if debug:
def getcpdata_sql(rower_id,table='cpdata',debug=False): # pragma: no cover
if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
@@ -605,8 +605,8 @@ def getcpdata_sql(rower_id,table='cpdata',debug=False):
return df
def deletecpdata_sql(rower_id,table='cpdata',debug=False):
if debug:
def deletecpdata_sql(rower_id,table='cpdata',debug=False): # pragma: no cover
if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
@@ -618,15 +618,15 @@ def deletecpdata_sql(rower_id,table='cpdata',debug=False):
with engine.connect() as conn, conn.begin():
try:
result = conn.execute(query)
except:
except: # pragma: no cover
print("Database locked")
conn.close()
engine.dispose()
def delete_agegroup_db(age,sex,weightcategory,debug=False):
if debug:
if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
else: # pragma: no cover
engine = create_engine(database_url, echo=False)
query = sa.text('DELETE from {table} WHERE age={age} and weightcategory = {weightcategory} and sex={sex};'.format(
@@ -638,7 +638,7 @@ def delete_agegroup_db(age,sex,weightcategory,debug=False):
with engine.connect() as conn, conn.begin():
try:
result = conn.execute(query)
except:
except: # pragma: no cover
print("Database locked")
conn.close()
engine.dispose()
@@ -664,7 +664,7 @@ def update_agegroup_db(age,sex,weightcategory,wcdurations,wcpower,
df.replace([np.inf,-np.inf],np.nan,inplace=True)
df.dropna(axis=0,inplace=True)
if debug:
if debug: # pragma: no cover # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
@@ -676,7 +676,7 @@ def update_agegroup_db(age,sex,weightcategory,wcdurations,wcpower,
engine.dispose()
def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=pd.Series([]),debug=False):
def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=pd.Series([],dtype='float'),debug=False):
deletecpdata_sql(rower_id,table=table,debug=debug)
df = pd.DataFrame(
{
@@ -690,7 +690,7 @@ def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=pd.Series([]),deb
if not distance.empty:
df['distance'] = distance
if debug:
if debug: # pragma: no cover
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
@@ -706,7 +706,7 @@ def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=pd.Series([]),deb
def smalldataprep(therows,xparam,yparam1,yparam2):
def smalldataprep(therows,xparam,yparam1,yparam2): # pragma: no cover
df = pd.DataFrame()
if yparam2 == 'None':
yparam2 = 'power'
@@ -749,8 +749,8 @@ def smalldataprep(therows,xparam,yparam1,yparam2):
def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
empower=True,debug=False,inboard=0.88,forceunit='lbs'):
if rowdatadf.empty:
if debug:
if rowdatadf.empty: # pragma: no cover
if debug: # pragma: no cover
print("empty")
return 0
@@ -776,7 +776,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
drivelength = rowdatadf.loc[:,' DriveLength (meters)']
try:
workoutstate = rowdatadf.loc[:,' WorkoutState']
except KeyError:
except KeyError: # pragma: no cover
workoutstate = 0*hr
peakforce = rowdatadf.loc[:,' PeakDriveForce (lbs)']
@@ -789,18 +789,18 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
recoverytime = rowdatadf.loc[:,' StrokeRecoveryTime (ms)']
rhythm = 100.*drivetime/(recoverytime+drivetime)
rhythm = rhythm.fillna(value=0)
except:
except: # pragma: no cover
rhythm = 0.0*forceratio
f = rowdatadf['TimeStamp (sec)'].diff().mean()
if f != 0:
try:
windowsize = 2*(int(10./(f)))+1
except ValueError:
except ValueError: # pragma: no cover
windowsize = 1
else:
else: # pragma: no cover
windowsize = 1
if windowsize <= 3:
if windowsize <= 3: # pragma: no cover
windowsize = 5
if windowsize > 3 and windowsize<len(hr):
@@ -811,7 +811,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
try:
t2 = t.fillna(method='ffill').apply(lambda x: timedeltaconv(x))
except TypeError:
except TypeError: # pragma: no cover
t2 = 0*t
@@ -819,19 +819,19 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
try:
drivespeed = drivelength/rowdatadf[' DriveTime (ms)']*1.0e3
except KeyError:
except KeyError: # pragma: no cover
drivespeed = 0.0*rowdatadf['TimeStamp (sec)']
except TypeError:
except TypeError: # pragma: no cover
drivespeed = 0.0*rowdatadf['TimeStamp (sec)']
drivespeed = drivespeed.fillna(value=0)
try:
driveenergy = rowdatadf['driveenergy']
except KeyError:
except KeyError: # pragma: no cover
if forceunit == 'lbs':
driveenergy = drivelength*averageforce*lbstoN
else:
else: # pragma: no cover
drivenergy = drivelength*averageforce
distance = rowdatadf.loc[:,'cum_dist']
@@ -882,7 +882,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
try:
tel = rowdatadf.loc[:,' ElapsedTime (sec)']
except KeyError:
except KeyError: # pragma: no cover
rowdatadf[' ElapsedTime (sec)'] = rowdatadf['TimeStamp (sec)']
@@ -918,7 +918,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
arclength = (inboard-0.05)*(np.radians(finish)-np.radians(catch))
if arclength.mean()>0:
if arclength.mean()>0: # pragma: no cover
drivelength = arclength
elif drivelength.mean() == 0:
drivelength = driveenergy/(averageforce*4.44822)
@@ -931,7 +931,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
try:
totalangle = finish-catch
effectiveangle = finish-wash-catch-slip
except ValueError:
except ValueError: # pragma: no cover
totalangle = 0*t
effectiveangle = 0*t
@@ -939,39 +939,39 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
if windowsize > 3 and windowsize<len(slip):
try:
wash = savgol_filter(wash,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
slip = savgol_filter(slip,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
catch = savgol_filter(catch,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
finish = savgol_filter(finish,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
peakforceangle = savgol_filter(peakforceangle,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
driveenergy = savgol_filter(driveenergy,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
drivelength = savgol_filter(drivelength,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
totalangle = savgol_filter(totalangle,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
try:
effectiveangle = savgol_filter(effectiveangle,windowsize,3)
except TypeError:
except TypeError: # pragma: no cover
pass
velo = 500./p
@@ -993,7 +993,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True,
data['totalangle'] = totalangle
data['effectiveangle'] = effectiveangle
data['efficiency'] = efficiency
except ValueError:
except ValueError: # pragma: no cover
pass
if otwpower:
+24 -22
View File
@@ -27,7 +27,7 @@ rpetotss = {
10:140,
}
def updatecp(delta,cpvalues,r,workouttype='water'):
def updatecp(delta,cpvalues,r,workouttype='water'): # pragma: no cover
if workouttype in otwtypes:
p0 = r.p0
p1 = r.p1
@@ -88,7 +88,7 @@ def cpfit(powerdf,fraclimit=0.0001,nmax=1000):
if len(thesecs)>=4:
try:
p1, success = optimize.leastsq(errfunc, p0[:], args = (thesecs,theavpower))
except:
except: # pragma: no cover
factor = fitfunc(p0,thesecs.mean())/theavpower.mean()
p1 = [p0[0]/factor,p0[1]/factor,p0[2],p0[3]]
@@ -132,17 +132,17 @@ def getlogarr(maxt):
for la in logarr:
try:
v = 5+int(10.**(la))
except ValueError:
except ValueError: # pragma: no cover
v = 0
res.append(v)
logarr = pd.Series(res)
logarr = pd.Series(res,dtype='float')
logarr.drop_duplicates(keep='first',inplace=True)
logarr = logarr.values
return logarr
def getsinglecp(df):
def getsinglecp(df): # pragma: no cover
thesecs = df['TimeStamp (sec)'].max()-df['TimeStamp (sec)'].min()
if thesecs != 0:
maxt = 1.05*thesecs
@@ -164,11 +164,13 @@ def getsinglecp(df):
return delta,cpvalue,avgpower
def getcp_new(dfgrouped,logarr):
def getcp_new(dfgrouped,logarr): # pragma: no cover
delta = []
cpvalue = []
avgpower = {}
#print(dfgrouped)
for id, group in dfgrouped:
tt = group['time'].copy()
@@ -195,11 +197,11 @@ def getcp_new(dfgrouped,logarr):
newt,method='linear',
rescale=True)
tt = pd.Series(newt)
ww = pd.Series(ww)
tt = pd.Series(newt,dtype='float')
ww = pd.Series(ww,dtype='float')
G = pd.Series(ww.cumsum())
G = pd.concat([pd.Series([0]),G])
G = pd.Series(ww.cumsum(),dtype='float')
G = pd.concat([pd.Series([0],dtype='float'),G])
h = np.mgrid[0:len(tt)+1:1,0:len(tt)+1:1]
@@ -305,7 +307,7 @@ def getcp(dfgrouped,logarr):
try:
avgpower[id] = int(ww.mean())
except ValueError:
except ValueError: # pragma: no cover
avgpower[id] = '---'
if not np.isnan(ww.mean()):
length = len(ww)
@@ -319,8 +321,8 @@ def getcp(dfgrouped,logarr):
cpw.append(wmax)
dt = pd.Series(dt)
cpw = pd.Series(cpw)
dt = pd.Series(dt,dtype='float')
cpw = pd.Series(cpw,dtype='float')
if len(dt)>2:
cpvalues = griddata(dt.values,
cpw.values,
@@ -334,8 +336,8 @@ def getcp(dfgrouped,logarr):
delta = pd.Series(delta,name='Delta')
cpvalue = pd.Series(cpvalue,name='CP')
delta = pd.Series(delta,name='Delta',dtype='float')
cpvalue = pd.Series(cpvalue,name='CP',dtype='float')
cpdf = pd.DataFrame({
@@ -373,7 +375,7 @@ def getmaxwattinterval(tt,ww,i):
except KeyError:
wmax = 0
deltat = 0
else:
else: # pragma: no cover
wmax = 0
deltat = 0
@@ -384,10 +386,10 @@ def getfastest(df,thevalue,mode='distance'):
dd = df['cumdist'].copy()
tmax = tt.max()
if mode == 'distance':
if mode == 'distance': # pragma: no cover
if dd.max() < thevalue:
return 0
else:
else: # pragma: no cover
if tt.max() < thevalue:
return 0
@@ -408,8 +410,8 @@ def getfastest(df,thevalue,mode='distance'):
dd = griddata(tt.values,
dd.values,newt,method='linear',rescale=True)
tt = pd.Series(newt)
dd = pd.Series(dd)
tt = pd.Series(newt,dtype='float')
dd = pd.Series(dd,dtype='float')
G = pd.concat([pd.Series([0]),dd])
T = pd.concat([pd.Series([0]),dd])
@@ -461,7 +463,7 @@ def getfastest(df,thevalue,mode='distance'):
endtime = starttime+duration
#print(duration,starttime,endtime,'aa')
return duration[0]/1000.,starttime[0]/1000.,endtime[0]/1000.
else:
else: # pragma: no cover
distance = griddata(restime,distance,[thevalue*60*1000],method='linear',rescale=True)
starttime = griddata(restime,starttimes,[thevalue*60*1000],method='linear',rescale=True)
duration = griddata(restime,restime,[thevalue*60*1000],method='linear',rescale=True)
@@ -469,4 +471,4 @@ def getfastest(df,thevalue,mode='distance'):
print(distance,starttime,endtime )
return distance[0],starttime[0]/1000.,endtime[0]/1000.
return 0
return 0 # pragma: no cover
+2 -2
View File
@@ -13,7 +13,7 @@ from django.contrib import messages
try:
from functools import wraps
except ImportError:
except ImportError: # pragma: no cover
from django.utils.functional import wraps
@@ -40,7 +40,7 @@ def user_passes_test(test_func, message=default_message,login_url=None,redirect_
return _wrapped_view
return decorator
def login_required_message(function=None, message=default_message):
def login_required_message(function=None, message=default_message): # pragma: no cover
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
+6 -6
View File
@@ -81,19 +81,19 @@ def send_template_email(from_email,to_email,subject,
# html_content = newlinetobr(html_content)
if 'bcc' in kwargs and 'cc' in kwargs:
if 'bcc' in kwargs and 'cc' in kwargs: # pragma: no cover
msg = EmailMultiAlternatives(subject, text_content, from_email, to_email,cc=kwargs['cc'],
bcc=kwargs['bcc'])
elif 'bcc' in kwargs:
elif 'bcc' in kwargs: # pragma: no cover
msg = EmailMultiAlternatives(subject, text_content, from_email, to_email,bcc=kwargs['bcc'])
elif 'cc' in kwargs:
elif 'cc' in kwargs: # pragma: no cover
msg = EmailMultiAlternatives(subject, text_content, from_email, to_email,cc=kwargs['cc'])
else:
msg = EmailMultiAlternatives(subject, text_content, from_email, to_email)
msg.attach_alternative(html_content, "text/html")
if 'attach_file' in kwargs:
if 'attach_file' in kwargs: # pragma: no cover
fileobj = kwargs['attach_file']
if os.path.isfile(fileobj):
msg.attach_file(fileobj)
@@ -107,7 +107,7 @@ def send_template_email(from_email,to_email,subject,
except IOError:
pass
if 'emailbounced' in kwargs:
if 'emailbounced' in kwargs: # pragma: no cover
emailbounced = kwargs['emailbounced']
else:
emailbounced = False
@@ -116,7 +116,7 @@ def send_template_email(from_email,to_email,subject,
if not emailbounced:
res = msg.send()
else:
else: # pragma: no cover
return 0
return res
+7 -6
View File
@@ -28,10 +28,11 @@ def get_contacts(rower):
res = requests.get(url, auth=auth, headers=headers)
with open('braintreewebhooks.log','a') as f:
f.write('Searching Contact Status code '+str(res.status_code)+'\n')
if res.status_code != 200:
if res.status_code != 200: # pragma: no cover
return None
with open('braintreewebhooks.log','a') as f:
@@ -73,7 +74,7 @@ def create_contact(rower):
with open('braintreewebhooks.log','a') as f:
f.write('Status Code '+str(res.status_code)+'\n')
if res.status_code not in [200,201]:
if res.status_code not in [200,201]: # pragma: no cover
return 0
with open('braintreewebhooks.log','a') as f:
@@ -85,7 +86,7 @@ def create_contact(rower):
def create_invoice(rower,amount,braintreeid,dosend=True,
contact_id=None,name=None):
if not contact_id:
if not contact_id: # pragma: no cover
contact_id = get_contacts(rower)
if not name:
@@ -95,7 +96,7 @@ def create_invoice(rower,amount,braintreeid,dosend=True,
with open('braintreewebhooks.log','a') as f:
f.write('Creating invoice for contact iD '+str(contact_id)+'\n')
if not contact_id:
if not contact_id: # pragma: no cover
return 0
post_data = {
@@ -120,7 +121,7 @@ def create_invoice(rower,amount,braintreeid,dosend=True,
with open('braintreewebhooks.log','a') as f:
f.write('Invoice Created - status code '+str(res.status_code)+'\n')
if res.status_code not in [200,201]:
if res.status_code not in [200,201]: # pragma: no cover
return 0
url = res.json()['url']
@@ -139,7 +140,7 @@ def create_invoice(rower,amount,braintreeid,dosend=True,
with open('braintreewebhooks.log','a') as f:
f.write('Invoice Set to paid - status code '+str(res.status_code)+'\n')
if res.status_code not in [200,201]:
if res.status_code not in [200,201]: # pragma: no cover
return 0
if dosend:
+2 -2
View File
@@ -11,7 +11,7 @@ class GroupedModelChoiceIterator(ModelChoiceIterator):
super().__init__(field)
def __iter__(self):
if self.field.empty_label is not None:
if self.field.empty_label is not None: # pragma: no cover
yield ("", self.field.empty_label)
queryset = self.queryset
# Can't use iterator() when queryset uses prefetch_related()
@@ -25,7 +25,7 @@ class GroupedModelChoiceField(ModelChoiceField):
def __init__(self, *args, choices_groupby, **kwargs):
if isinstance(choices_groupby, str):
choices_groupby = attrgetter(choices_groupby)
elif not callable(choices_groupby):
elif not callable(choices_groupby): # pragma: no cover
raise TypeError('choices_groupby must either be a str or a callable accepting a single argument')
self.iterator = partial(GroupedModelChoiceIterator, groupby=choices_groupby)
super().__init__(*args, **kwargs)
+20 -20
View File
@@ -51,10 +51,10 @@ class FlexibleDecimalField(forms.DecimalField):
pass
try:
dot_index = value.index('.')
except ValueError:
except ValueError: # pragma: no cover
pass
if value:
if comma_index > dot_index:
if comma_index > dot_index: # pragma: no cover
value = value.replace('.', '').replace(',', '.')
return super(FlexibleDecimalField, self).to_python(value)
@@ -362,7 +362,7 @@ class WorkFlowLeftPanelForm(forms.Form):
js = ['/admin/jsi18n/']
def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs): # pragma: no cover
if 'instance' in kwargs:
r = kwargs.pop('instance')
panels = r.workflowleftpanel
@@ -395,7 +395,7 @@ class WorkFlowMiddlePanelForm(forms.Form):
}
js = ['/admin/jsi18n/']
def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs): # pragma: no cover
if 'instance' in kwargs:
r = kwargs.pop('instance')
panels = r.workflowmiddlepanel
@@ -500,18 +500,18 @@ class UploadOptionsForm(forms.Form):
choices3 = [(0,'---')]
noregistrations = []
for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(),sessiontype='race'):
for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(),sessiontype='race'): # pragma: no cover
rs = VirtualRaceResult.objects.filter(race = ra,userid=r.id)
if rs.count()==0:
noregistrations.append((-ra.id,ra.name))
for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(),sessiontype='indoorrace'):
for ra in VirtualRace.objects.filter(registration_closure__gt=timezone.now(),sessiontype='indoorrace'): # pragma: no cover
rs = IndoorVirtualRaceResult.objects.filter(race = ra,userid=r.id)
if rs.count()==0:
noregistrations.append((-ra.id,ra.name))
choices = choices3+choices1+choices2+noregistrations
if int(raceid) in [r.id for r in races]:
if int(raceid) in [r.id for r in races]: # pragma: no cover
therace = VirtualRace.objects.get(id=raceid)
self.fields['raceid'].initial = therace.id
if therace.sessiontype == 'race':
@@ -526,7 +526,7 @@ class UploadOptionsForm(forms.Form):
choices = [(r.id,str(r)) for r in registrations]
choices = choices+[(0,'---')]
if races:
if races: # pragma: no cover
self.fields['submitrace'].choices = choices
else:
del self.fields['submitrace']
@@ -920,7 +920,7 @@ class RegistrationFormUniqueEmail(RegistrationFormTermsOfService):
Validate that the supplied email address is unique for the
site.
"""
if User.objects.filter(email__iexact=self.cleaned_data['email']):
if User.objects.filter(email__iexact=self.cleaned_data['email']): # pragma: no cover
raise forms.ValidationError("This email address is already in use. Please supply a different email address.")
return self.cleaned_data['email']
@@ -949,7 +949,7 @@ class RegistrationFormSex(RegistrationFormUniqueEmail):
def clean_birthdate(self):
dob = self.cleaned_data['birthdate']
age = (timezone.now() - dob).days/365
if age < 16:
if age < 16: # pragma: no cover
raise forms.ValidationError('Must be at least 16 years old to register')
return self.cleaned_data['birthdate']
@@ -970,7 +970,7 @@ class RegistrationFormSex(RegistrationFormUniqueEmail):
# Time field supporting microseconds. Not used, I believe.
class MyTimeField(forms.TimeField):
def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs): # pragma: no cover
super(MyTimeField, self).__init__(*args, **kwargs)
supports_microseconds = True
@@ -1085,7 +1085,7 @@ class StatsOptionsForm(forms.Form):
def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs): # pragma: no cover
super(StatsOptionsForm, self).__init__(*args,**kwargs)
for type in mytypes.checktypes:
@@ -1128,7 +1128,7 @@ class PlanSelectForm(forms.Form):
class CourseSelectForm(forms.Form):
course = forms.ModelChoiceField(queryset=GeoCourse.objects.filter())
def __init__(self, *args, **kwargs):
def __init__(self, *args, **kwargs): # pragma: no cover
course = kwargs.pop('course',None)
manager = kwargs.pop('manager',None)
super(CourseSelectForm,self).__init__(*args,**kwargs)
@@ -1380,7 +1380,7 @@ class FusionMetricChoiceForm(ModelForm):
if df.loc[:,label].std() == 0:
try:
formaxlabels2.pop(label)
except KeyError:
except KeyError: # pragma: no cover
pass
metricchoices = list(sorted(formaxlabels2.items(), key = lambda x:x[1]))
@@ -1511,7 +1511,7 @@ class RaceResultFilterForm(forms.Form):
if len(theboatclasses)<= 1:
del self.fields['boatclass']
else:
else: # pragma: no cover
boatclasschoices = []
for choice in self.fields['boatclass'].choices:
if choice[0] in theboatclasses:
@@ -1522,7 +1522,7 @@ class RaceResultFilterForm(forms.Form):
try:
theboattypees = [record.boattype for record in records]
theboattypees = list(set(theboattypees))
except AttributeError:
except AttributeError: # pragma: no cover
theboattypees = []
if len(theboattypees)<= 1:
@@ -1540,7 +1540,7 @@ class RaceResultFilterForm(forms.Form):
if len(theweightcategoryes)<= 1:
del self.fields['weightcategory']
else:
else: # pragma: no cover
weightcategorychoices = []
for choice in self.fields['weightcategory'].choices:
if choice[0] in theweightcategoryes:
@@ -1553,7 +1553,7 @@ class RaceResultFilterForm(forms.Form):
if len(theadaptivecategoryes)<= 1:
del self.fields['adaptivecategory']
else:
else: # pragma: no cover
adaptivecategorychoices = []
for choice in self.fields['adaptivecategory'].choices:
if choice[0] in theadaptivecategoryes:
@@ -1622,7 +1622,7 @@ class PlannedSessionTeamForm(forms.Form):
self.fields['team'].queryset = Team.objects.filter(manager=user)
def clean(self):
if any(self.errors):
if any(self.errors): # pragma: no cover
return
cd = self.cleaned_data
@@ -1651,7 +1651,7 @@ def get_countries():
countries = VirtualRace.objects.order_by('country').values_list('country').distinct()
countries = tuple([(c[0],c[0]) for c in countries])
countries = countries+(('All','All'),)
except:
except: # pragma: no cover
countries = (('All','All'))
return countries
+56 -31
View File
@@ -81,7 +81,7 @@ columns = {
'bikeCadenceInRPM':' Cadence (stokes/min)',
}
def garmin_authorize():
def garmin_authorize(): # pragma: no cover
redirect_uri = oauth_data['redirect_uri']
client_secret = oauth_data['client_secret']
client_id = oauth_data['client_id']
@@ -98,7 +98,7 @@ def garmin_authorize():
authorization_url = garmin.authorization_url(base_uri)
return authorization_url,resource_owner_key,resource_owner_secret
def garmin_processcallback(redirect_response,resource_owner_key,resource_owner_secret):
def garmin_processcallback(redirect_response,resource_owner_key,resource_owner_secret): # pragma: no cover
garmin = OAuth1Session(oauth_data['client_id'],
client_secret=oauth_data['client_secret'],
)
@@ -124,7 +124,7 @@ def garmin_processcallback(redirect_response,resource_owner_key,resource_owner_s
return garmintoken,garminrefreshtoken
def garmin_open(user):
def garmin_open(user): # pragma: no cover
r = Rower.objects.get(user=user)
token = Rower.garmintoken
@@ -133,7 +133,7 @@ def garmin_open(user):
return token
def get_garmin_file(r,callbackURL,starttime,fileType):
def get_garmin_file(r,callbackURL,starttime,fileType): # pragma: no cover
job = myqueue(
queue,
handle_get_garmin_file,
@@ -148,7 +148,7 @@ def get_garmin_file(r,callbackURL,starttime,fileType):
return job.id
def get_garmin_workout_list(user):
def get_garmin_workout_list(user): # pragma: no cover
r = Rower.objects.get(user=user)
if (r.garmintoken == '') or (r.garmintoken is None):
s = "Token doesn't exist. Need to authorize"
@@ -166,7 +166,7 @@ def get_garmin_workout_list(user):
return result
def garmin_can_export_session(user):
def garmin_can_export_session(user): # pragma: no cover
result = get_garmin_permissions(user)
if 'WORKOUT_IMPORT' in result:
return True
@@ -179,58 +179,83 @@ def step_to_garmin(step,order=0):
durationtype = step['dict']['durationType']
durationvalue = step['dict']['durationValue']
durationvaluetype = ''
if durationtype == 'Time':
try:
intensity = step['dict']['intensity']
except KeyError:
intensity = None
#durationvaluetype = ''
if durationtype == 'Time': # pragma: no cover
durationtype = 'TIME'
durationvalue = int(durationvalue/1000.)
elif durationtype == 'Distance':
elif durationtype == 'Distance': # pragma: no cover
durationtype = 'DISTANCE'
durationvalue = int(durationvalue/100)
durationvaluetype = 'METER'
elif durationtype == 'HrLessThan':
elif durationtype == 'HrLessThan': # pragma: no cover
durationtype = 'HR_LESS_THAN'
if durationvalue <= 100:
durationvaluetype = 'PERCENT'
else:
durationvaluetype = ''
durationvalue -= 100
elif durationtype == 'HrGreaterThan':
elif durationtype == 'HrGreaterThan': # pragma: no cover
durationtype = 'HR_GREATER_THAN'
if durationvalue <= 100:
durationvaluetype = 'PERCENT'
else:
durationvaluetype = ''
durationvalue -= 100
elif durationtype == 'PowerLessThan':
elif durationtype == 'PowerLessThan': # pragma: no cover
durationtype = 'POWER_LESS_THAN'
if durationvalue <= 1000:
durationvaluetype = 'PERCENT'
else:
durationvaluetype = ''
durationvalue -= 1000
elif durationtype == 'PowerGreaterThan':
elif durationtype == 'PowerGreaterThan': # pragma: no cover
durationtype = 'POWER_GREATER_THAN'
if durationvalue <= 1000:
durationvaluetype = 'PERCENT'
else:
durationvaluetype = ''
durationvalue -= 1000
elif durationtype == 'Reps':
elif durationtype == 'Reps': # pragma: no cover
durationtype = 'REPS'
try:
targetType = step['dict']['targetType']
except KeyError:
targetType = None
try:
targetValue = step['dict']['targetValue']
except KeyError:
targetValue = None
try:
targetValueLow = step['dict']['targetValueLow']
except KeyError:
targetValueLow = None
try:
targetValueHigh = step['dict']['targetValueHigh'],
except KeyError:
targetValueHigh = None
out = {
'type': step['type'],
'stepOrder':order,
'repeatType':step['type'],
'repeatValue':step['repeatValue'],
'intensity':step['dict']['intensity'],
'intensity':intensity,
'description':step['dict']['wkt_step_name'],
'durationType':durationtype,
'durationValue':durationvalue,
'durationValueType':durationvaluetype,
'targetType':step['dict']['targetType'],
'targetValue':step['dict']['targetValue'],
'targetValueLow':step['dict']['targetValueLow'],
'targetValueHigh':step['dict']['targetValueHigh'],
'targetType':targetType,
'targetValue':targetValue,
'targetValueLow':targetValueLow,
'targetValueHigh':targetValueHigh,
}
try:
steps = step['steps']
@@ -312,7 +337,7 @@ def ps_to_garmin(ps,r):
return response
def get_garmin_permissions(user):
def get_garmin_permissions(user): # pragma: no cover
r = Rower.objects.get(user=user)
if (r.garmintoken == '') or (r.garmintoken is None):
s = "Token doesn't exist. Need to authorize"
@@ -333,7 +358,7 @@ def get_garmin_permissions(user):
return []
def garmin_session_create(ps,user):
def garmin_session_create(ps,user): # pragma: no cover
if not ps.steps:
return 0
if not garmin_can_export_session(user):
@@ -366,7 +391,7 @@ def garmin_getworkout(garminid,r,activity):
startdatetime = arrow.get(starttime)
try:
offset = activity['startTimeOffsetInSeconds']
except KeyError:
except KeyError: # pragma: no cover
offset = 0
durationseconds = activity['durationInSeconds']
duration = dataprep.totaltime_sec_to_string(durationseconds)
@@ -380,7 +405,7 @@ def garmin_getworkout(garminid,r,activity):
try:
averagehr = activity['averageHeartRateInBeatsPerMinute']
maxhr = activity['maxHeartRateInBeatsPerMinute']
except KeyError:
except KeyError: # pragma: no cover
averagehr = 0
maxhr = 0
try:
@@ -396,11 +421,11 @@ def garmin_getworkout(garminid,r,activity):
now = datetime.datetime.now(pytz.utc)
zones = [tz.zone for tz in map(pytz.timezone, pytz.all_timezones_set)
if now.astimezone(tz).utcoffset() == utc_offset]
if r.defaulttimezone in zones:
if r.defaulttimezone in zones: # pragma: no cover
thetimezone = r.defaulttimezone
elif len(zones):
thetimezone = zones[0]
else:
else: # pragma: no cover
thetimezone = utc
startdatetime = datetime.datetime(
@@ -416,11 +441,11 @@ def garmin_getworkout(garminid,r,activity):
w.starttime = w.startdatetime.time()
try:
w.duration = datetime.datetime.strptime(duration,"%H:%M:%S.%f").time()
except ValueError:
except ValueError: # pragma: no cover
w.duration = datetime.datetime.strptime(duration,"%H:%M:%S")
try:
w.workouttype = mytypes.garminmappinginv[activitytype]
except KeyError:
except KeyError: # pragma: no cover
w.workouttype = 'other'
w.name = name
w.date = date
@@ -435,11 +460,11 @@ def garmin_getworkout(garminid,r,activity):
def garmin_workouts_from_details(data):
activities = data['activityDetails']
for activity in activities:
try:
try: # pragma: no cover
garmintoken = activity['userAccessToken']
except KeyError:
except KeyError: # pragma: no cover
return 0
except TypeError:
except TypeError: # pragma: no cover
return 0
try:
r = Rower.objects.get(garmintoken=garmintoken)
@@ -478,7 +503,7 @@ def garmin_workouts_from_details(data):
w.save()
trimp,hrtss = dataprep.workout_trimp(w)
rscore,normp = dataprep.workout_rscore(w)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
pass
return 1
@@ -490,7 +515,7 @@ def garmin_workouts_from_summaries(activities):
r = Rower.objects.get(garmintoken=garmintoken)
id = activity['summaryId']
w = garmin_getworkout(id,r,activity)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
pass
return 1
+17 -17
View File
@@ -109,7 +109,7 @@ def imports_open(user,oauth_data):
expirydatename,
oauth_data,
)
elif tokenexpirydate is None and expirydatename is not None and 'strava' in expirydatename:
elif tokenexpirydate is None and expirydatename is not None and 'strava' in expirydatename: # pragma: no cover
token = imports_token_refresh(
user,
tokenname,
@@ -142,7 +142,7 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''):
if 'grant_type' in oauth_data:
if oauth_data['grant_type']:
post_data['grant_type'] = oauth_data['grant_type']
else:
else: # pragma: no cover
grant_type = post_data.pop('grant_type',None)
if oauth_data['bearer_auth']:
@@ -155,7 +155,7 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''):
response = requests.post(baseurl,
data=json.dumps(post_data),
headers=headers,verify=False)
except:
except: # pragma: no cover
raise NoTokenError("Failed to get token")
else:
try:
@@ -163,19 +163,19 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''):
data=post_data,
headers=headers,verify=False,
)
except:
except: # pragma: no cover
raise NoTokenError("Failed to get token")
if response.status_code == 200 or response.status_code == 201:
token_json = response.json()
else:
else: # pragma: no cover
raise NoTokenError("User has no token")
try:
thetoken = token_json['access_token']
except KeyError:
except KeyError: # pragma: no cover
raise NoTokenError("User has no token")
try:
@@ -184,15 +184,15 @@ def imports_do_refresh_token(refreshtoken,oauth_data,access_token=''):
try:
expires_at = arrow.get(token_json['expires_at']).timestamp()
expires_in = expires_at - arrow.now().timestamp()
except KeyError:
except KeyError: # pragma: no cover
expires_in = 0
try:
refresh_token = token_json['refresh_token']
except KeyError:
except KeyError: # pragma: no cover
refresh_token = refreshtoken
try:
expires_in = int(expires_in)
except (TypeError,ValueError):
except (TypeError,ValueError): # pragma: no cover
expires_in = 0
return [thetoken,expires_in,refresh_token]
@@ -234,7 +234,7 @@ def imports_get_token(
post_data['grant_type'] = oauth_data['grant_type']
if 'strava' in oauth_data['autorization_uri']:
post_data['grant_type'] = "authorization_code"
else:
else: # pragma: no cover
grant_type = post_data.pop('grant_type',None)
@@ -253,28 +253,28 @@ def imports_get_token(
token_json = response.json()
try:
thetoken = token_json['access_token']
except KeyError:
except KeyError: # pragma: no cover
return [0,0,0]
try:
refresh_token = token_json['refresh_token']
except KeyError:
except KeyError: # pragma: no cover
refresh_token = ''
try:
expires_in = token_json['expires_in']
except KeyError:
except KeyError: # pragma: no cover
expires_in = 0
try:
expires_in = int(expires_in)
except (ValueError,TypeError):
except (ValueError,TypeError): # pragma: no cover
expires_in = 0
else:
else: # pragma: no cover
return [0,response.text,0]
return [thetoken,expires_in,refresh_token]
# Make authorization URL including random string
def imports_make_authorization_url(oauth_data):
def imports_make_authorization_url(oauth_data): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
@@ -299,7 +299,7 @@ def imports_token_refresh(user,tokenname,refreshtokenname,expirydatename,oauth_d
refreshtoken = getattr(r,refreshtokenname)
# for Strava transition
if not refreshtoken:
if not refreshtoken: # pragma: no cover
refreshtoken = getattr(r,tokenname)
+17 -22
View File
@@ -211,7 +211,7 @@ def tailwind(bearing,vwind,winddir):
return vtail
from rowers.dataprep import nicepaceformat,niceformat
from rowers.dataprep import nicepaceformat,niceformat,strfdelta
from rowers.dataprep import timedeltaconv
from math import pi
@@ -836,7 +836,7 @@ def interactive_activitychart2(workouts,startdate,enddate,stack='type',toolbar_l
callback = CustomJS(args={'links':df.link}, code="""
callback = CustomJS(args={'links':df['link']}, code="""
var index = cb_data.source.selected['1d'].indices[0];
console.log(links);
console.log(index);
@@ -3336,7 +3336,7 @@ def interactive_otwcpchart(powerdf,promember=0,rowername="",r=None,cpfit='data',
title='',type='water',
wcpower=[],wcdurations=[],cpoverlay=False):
powerdf = powerdf[~(powerdf == 0).any(axis=1)]
powerdf2 = powerdf[~(powerdf == 0).any(axis=1)].copy()
# plot tools
if (promember==1): # pragma: no cover
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
@@ -3347,24 +3347,24 @@ def interactive_otwcpchart(powerdf,promember=0,rowername="",r=None,cpfit='data',
x_axis_type = 'log'
y_axis_type = 'linear'
deltas = powerdf['Delta'].apply(lambda x: timedeltaconv(x))
powerdf['ftime'] = niceformat(deltas)
powerdf['Deltaminutes'] = powerdf['Delta']/60.
deltas = powerdf2['Delta'].apply(lambda x: timedeltaconv(x))
powerdf2['ftime'] = deltas.apply(lambda x:strfdelta(x))
powerdf2['Deltaminutes'] = powerdf2['Delta']/60.
source = ColumnDataSource(
data = powerdf
data = powerdf2
)
# there is no Paul's law for OTW
thesecs = powerdf['Delta']
theavpower = powerdf['CP']
thesecs = powerdf2['Delta']
theavpower = powerdf2['CP']
p1,fitt,fitpower,ratio = datautils.cpfit(powerdf)
p1,fitt,fitpower,ratio = datautils.cpfit(powerdf2)
if cpfit == 'automatic' and r is not None:
if type == 'water':
p1 = [r.p0,r.p1,r.p2,r.p3]
@@ -3383,12 +3383,12 @@ def interactive_otwcpchart(powerdf,promember=0,rowername="",r=None,cpfit='data',
deltas = fitt.apply(lambda x: timedeltaconv(x))
ftime = niceformat(deltas)
workouts = powerdf['workout']
urls = powerdf['url']
workouts = powerdf2['workout']
urls = powerdf2['url']
# add world class
wcpower = pd.Series(wcpower)
wcdurations = pd.Series(wcdurations)
wcpower = pd.Series(wcpower,dtype='float')
wcdurations = pd.Series(wcdurations,dtype='float')
# fitting WC data to three parameter CP model
@@ -3683,8 +3683,8 @@ def interactive_cpchart(rower,thedistances,thesecs,theavpower,
errfunc = lambda pars,x,y: fitfunc(pars,x)-y
# p0 = [500,350,10,8000]
wcpower = pd.Series(wcpower)
wcdurations = pd.Series(wcdurations)
wcpower = pd.Series(wcpower,dtype='float')
wcdurations = pd.Series(wcdurations,dtype='float')
# fitting WC data to three parameter CP model
if len(wcdurations)>=4:
@@ -4086,11 +4086,6 @@ def interactive_chart(id=0,promember=0,intervaldata = {}):
row = Workout.objects.get(id=id)
if datadf.empty:
return "","No Valid Data Available"
#else:
# try:
# datadf.sort_values(by='time',ascending=True,inplace=True)
# except KeyError:
# return "","No valid data available"
try:
spm = datadf['spm']
@@ -4179,7 +4174,7 @@ def interactive_chart(id=0,promember=0,intervaldata = {}):
intervaldf['itime'] = intervaldf['itime']*1.e3
intervaldf['time'] = intervaldf['itime'].cumsum()
intervaldf['time'] = intervaldf['time'].shift(1)
intervaldf.loc[:,'time'].iloc[0] = 0
intervaldf.loc[0,'time'] = 0
intervaldf['time_r'] = intervaldf['time'] +intervaldf['itime']
intervaldf['value'] = 100
mask = intervaldf['itype'] == 3
+3 -3
View File
@@ -20,7 +20,7 @@ import requests
from rowsandall_app.settings import SITE_URL
from rowsandall_app.settings_dev import SITE_URL as SITE_URL_DEV
def getvalue(data):
def getvalue(data): # pragma: no cover
perc = 0
total = 1
done = 0
@@ -41,7 +41,7 @@ def getvalue(data):
def longtask(aantal,jobid=None,debug=False,
session_key=None):
session_key=None): # pragma: no cover
counter = 0
channel = 'tasks'
@@ -66,7 +66,7 @@ def longtask(aantal,jobid=None,debug=False,
return 1
def longtask2(aantal,jobid=None,debug=False,secret=''):
def longtask2(aantal,jobid=None,debug=False,secret=''): # pragma: no cover
counter = 0
channel = 'tasks'
+10 -10
View File
@@ -40,7 +40,7 @@ queuehigh = django_rq.get_queue('default')
# Sends a confirmation with a link to the workout
from rowers.emails import send_template_email
def send_confirm(user, name, link, options):
def send_confirm(user, name, link, options): # pragma: no cover
d = {
'first_name':user.first_name,
'name':name,
@@ -65,12 +65,12 @@ def rdata(file, rower=rrower()):
""" Reads rowingdata data or returns 0 on Error """
try:
result = rrdata(csvfile=file, rower=rower)
except IOError:
except IOError: # pragma: no cover
try:
result = rrdata(csvfile=file + '.gz', rower=rower)
except IOError:
result = 0
except TypeError:
except TypeError: # pragma: no cover
try:
result = rrdata(csvfile=file)
except IOError:
@@ -88,18 +88,18 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
workouttype = 'rower'
impeller = False
try:
try: # pragma: no cover
datafilename = datafile.name
fileformat = get_file_type('media/' + datafilename)
raise ValueError
except IOError:
except IOError: # pragma: no cover
datafilename = datafile.name + '.gz'
fileformat = get_file_type('media/' + datafilename)
except AttributeError:
datafilename = datafile
fileformat = get_file_type('media/' + datafile)
if len(fileformat) == 3 and fileformat[0] == 'zip':
if len(fileformat) == 3 and fileformat[0] == 'zip': # pragma: no cover
with zipfile.ZipFile('media/' + datafilename) as zip_file:
datafilename = zip_file.extract(
zip_file.namelist()[0],
@@ -112,7 +112,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
f,e = os.path.splitext(datafilename)
if fileformat == 'unknown' and 'txt' not in e:
fcopy = "media/"+datafilename
if not testing:
if not testing: # pragma: no cover
if settings.CELERY:
res = handle_sendemail_unrecognized.delay(
fcopy,
@@ -141,7 +141,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
if fileformat != 'csv':
filename_mediadir, summary, oarlength, inboard,fileformat,impeller = dataprep.handle_nonpainsled(
'media/' + datafilename, fileformat, summary)
if not filename_mediadir:
if not filename_mediadir: # pragma: no cover
return 0
else:
filename_mediadir = 'media/' + datafilename
@@ -149,7 +149,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
oarlength = 2.89
row = rdata(filename_mediadir)
if row == 0:
if row == 0: # pragma: no cover
return 0
# change filename
@@ -169,7 +169,7 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
dosummary = (fileformat != 'fit' and 'speedcoach2' not in fileformat)
dosummary = dosummary or summary == ''
if name == '':
if name == '': # pragma: no cover
name = 'Workout from Background Queue'
id, message = dataprep.save_workout_database(
+25 -25
View File
@@ -50,7 +50,7 @@ os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings'
if not getattr(__builtins__, "WindowsError", None):
class WindowsError(OSError): pass
def rdata(file_obj, rower=rrower()):
def rdata(file_obj, rower=rrower()): # pragma: no cover
""" Read rowing data file and return 0 if file doesn't exist"""
try:
result = rrdata(file_obj, rower=rower)
@@ -71,7 +71,7 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
try:
with io.open('media/'+filename,'rb') as fop:
line = fop.readline()
except (IOError, UnicodeEncodeError):
except (IOError, UnicodeEncodeError): # pragma: no cover
return 0
@@ -80,9 +80,9 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
users = User.objects.filter(username=uploadoptions['username'])
if len(users)==1:
therower = users[0].rower
elif uploadoptions['username'] == '':
elif uploadoptions['username'] == '': # pragma: no cover
therower = rower
else:
else: # pragma: no cover
return 0
else:
therower = rower
@@ -94,7 +94,7 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
uploadoptions['title'] = title
url = settings.UPLOAD_SERVICE_URL
if not testing:
if not testing: # pragma: no cover
response = requests.post(url,data=uploadoptions)
# print("Upload response status code",response.status_code, response.json())
if response.status_code == 200:
@@ -125,7 +125,7 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
race = VirtualRace.objects.get(id=uploadoptions['raceid'])
if race.manager == rower.user:
result = email_submit_race(therower,race,workoutid[0])
except VirtualRace.DoesNotExist:
except VirtualRace.DoesNotExist: # pragma: no cover
pass
@@ -135,22 +135,22 @@ def get_from_address(message):
from_address = message.from_address[0].lower()
if message.encoded:
if message.encoded: # pragma: no cover
body = message.text.splitlines()
else:
body = message.get_body().splitlines()
try:
first_line = body[0].lower()
except IndexError:
except IndexError: # pragma: no cover
first_line = ''
try:
first_line = first_line.decode('utf-8')
except AttributeError:
except AttributeError: # pragma: no cover
pass
if "quiske" in first_line:
if "quiske" in first_line: # pragma: no cover
match = re.search(r'[\w\.-]+@[\w\.-]+', first_line)
return match.group(0)
@@ -178,17 +178,17 @@ class Command(BaseCommand):
def handle(self, *args, **options):
if 'testing' in options:
testing = options['testing']
else:
else: # pragma: no cover
testing = False
if 'mailbox' in options:
workoutmailbox = Mailbox.objects.get(name=options['mailbox'])
else:
else: # pragma: no cover
workoutmailbox = Mailbox.objects.get(name='workouts')
if 'failedmailbox' in options:
if 'failedmailbox' in options: # pragma: no cover
failedmailbox = Mailbox.objects.get(name=options['failedmailbox'])
else:
else: # pragma: no cover
failedmailbox = Mailbox.objects.get(name='Failed')
# Polar
@@ -197,17 +197,17 @@ class Command(BaseCommand):
# Concept2
rowers = Rower.objects.filter(c2_auto_import=True)
for r in rowers:
for r in rowers: # pragma: no cover
if user_is_not_basic(r.user):
c2stuff.get_c2_workouts(r)
rowers = Rower.objects.filter(rp3_auto_import=True)
for r in rowers:
for r in rowers: # pragma: no cover
if user_is_not_basic(r.user):
res = rp3stuff.get_rp3_workouts(r)
rowers = Rower.objects.filter(nk_auto_import=True)
for r in rowers:
for r in rowers: # pragma: no cover
if user_is_not_basic(r.user):
res = nkstuff.get_nk_workouts(r)
@@ -223,7 +223,7 @@ class Command(BaseCommand):
# extension = attachment.document.name[-3:].lower()
try:
message = Message.objects.get(id=attachment.message_id)
if message.encoded:
if message.encoded: # pragma: no cover
# if message.text:
body = "\n".join(message.text.splitlines())
else:
@@ -239,16 +239,16 @@ class Command(BaseCommand):
rowers = [
r for r in Rower.objects.all() if r.user.email.lower() == from_address
]
try:
try: # pragma: no cover
rowers2 = [
r for r in Rower.objects.all() if from_address in r.emailalternatives
]
rowers = rowers+rowers2
except TypeError:
pass
except IOError:
except IOError: # pragma: no cover
rowers = []
except Message.DoesNotExist:
except Message.DoesNotExist: # pragma: no cover
try:
attachment.delete()
except:
@@ -268,7 +268,7 @@ class Command(BaseCommand):
rower, datafile, title, uploadoptions,
testing=testing
)
except BadZipFile:
except BadZipFile: # pragma: no cover
pass
else:
@@ -282,16 +282,16 @@ class Command(BaseCommand):
# We're done with the attachment. It can be deleted
try:
attachment.delete()
except IOError:
except IOError: # pragma: no cover
pass
except WindowsError:
except WindowsError: # pragma: no cover
if not testing:
time.sleep(2)
try:
attachment.delete()
except WindowsError:
pass
except:
except: # pragma: no cover
message.mailbox = failedmailbox
message.save()
+2 -2
View File
@@ -377,7 +377,7 @@ dtypes = {}
for name,d in rowingmetrics:
if d['numtype'] == 'float':
dtypes[name] = float
elif d['numtype'] == 'int':
elif d['numtype'] == 'int': # pragma: no cover
dtypes[name] = int
axesnew = [
@@ -479,7 +479,7 @@ This value should be fairly constant across all stroke rates.""",
def calc_trimp(df,sex,hrmax,hrmin,hrftp):
def calc_trimp(df,sex,hrmax,hrmin,hrftp): # pragma: no cover
if sex == 'male':
f = 1.92
else:
+4 -4
View File
@@ -44,10 +44,10 @@ class SurveyMiddleWare(object):
if request.user.is_authenticated and request.path not in allowed_paths:
r = getrower(request.user)
nexturl = request.path
if 'survey' in nexturl:
if 'survey' in nexturl: # pragma: no cover
nexturl = '/rowers/list-workouts'
mustseesurvey = request.user.date_joined <= timezone.now()-datetime.timedelta(days=14) and not r.surveydone
if mustseesurvey:
if mustseesurvey: # pragma: no cover
return redirect(
'/rowers/survey/?next=%s' % nexturl
)
@@ -64,7 +64,7 @@ class GDPRMiddleWare(object):
if request.user.is_authenticated and request.path not in allowed_paths:
r = getrower(request.user)
nexturl = request.path
if 'optin' in nexturl:
if 'optin' in nexturl: # pragma: no cover
nexturl = '/rowers/list-workouts'
if not r.gdproptin:
return redirect(
@@ -82,7 +82,7 @@ class RowerPlanMiddleWare(object):
def __call__(self, request):
if request.user.is_authenticated and request.user.rower.rowerplan not in ['basic','freecoach']:
if request.user.rower.paymenttype == 'single':
if request.user.rower.planexpires < timezone.now().date():
if request.user.rower.planexpires < timezone.now().date(): # pragma: no cover
messg = 'Your paid plan has expired. We have reset you to a free basic plan.'
messages.error(request,messg)
r = getrower(request.user)
-2
View File
@@ -117,8 +117,6 @@ class UserFullnameChoiceField(forms.ModelChoiceField):
def label_from_instance(self,obj):
return obj.get_full_name()
class PlannedSessionStepField(models.TextField):
pass
def get_file_path(instance, filename):
ext = filename.split('.')[-1]
+4 -8
View File
@@ -12,7 +12,7 @@ def strfdelta(tdelta):
try:
minutes, seconds = divmod(tdelta.seconds, 60)
tenths = int(tdelta.microseconds / 1e5)
except AttributeError:
except AttributeError: # pragma: no cover
minutes, seconds = divmod(tdelta.view(np.int64), 60e9)
seconds, rest = divmod(seconds, 1e9)
tenths = int(rest / 1e8)
@@ -51,7 +51,7 @@ def add_workout_from_data(userid,nkid,data,strokedata,source='nk',splitdata=None
totalDistance = totalDistanceGps
useImpeller = False
if speedInput:
if speedInput: # pragma: no cover
totdalDistance = totalDistanceImp
useImpeller = True
@@ -70,7 +70,7 @@ def add_workout_from_data(userid,nkid,data,strokedata,source='nk',splitdata=None
oarlockfirmware = oarlocksession["firmwareVersion"]
except KeyError:
oarlockfirmware = ''
else:
else: # pragma: no cover
boatName = ''
oarLength = 289
oarInboardLength = 88
@@ -103,7 +103,7 @@ def add_workout_from_data(userid,nkid,data,strokedata,source='nk',splitdata=None
response = session.post(UPLOAD_SERVICE_URL,json=uploadoptions)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
return 0,response.text
try:
@@ -219,10 +219,6 @@ def get_nk_summary(workoutdata,strokedata):
return stri1
return stri1
def get_nk_allstats(data,workoutdata):
stri = get_nk_summary(data, workoutdata) + \
get_nk_intervalstats(data, workoutdata)
+19 -19
View File
@@ -29,7 +29,7 @@ import gzip
from rowsandall_app.settings import (
NK_CLIENT_ID, NK_REDIRECT_URI, NK_CLIENT_SECRET,
SITE_URL, NK_API_LOCATION,
SITE_URL, NK_API_LOCATION,NK_OAUTH_LOCATION,
UPLOAD_SERVICE_URL, UPLOAD_SERVICE_SECRET,
)
@@ -38,7 +38,7 @@ from rowers.tasks import handle_nk_async_workout
try:
from json.decoder import JSONDecodeError
except ImportError:
except ImportError: # pragma: no cover
JSONDecodeError = ValueError
from rowers.imports import *
@@ -48,19 +48,19 @@ oauth_data = {
'client_id': NK_CLIENT_ID,
'client_secret': NK_CLIENT_SECRET,
'redirect_uri': NK_REDIRECT_URI,
'autorization_uri': "https://oauth-stage.nkrowlink.com/oauth/authorize",
'autorization_uri': NK_OAUTH_LOCATION+"/oauth/authorize",
'content_type': 'application/json',
'tokenname': 'nktoken',
'refreshtokenname': 'nkrefreshtoken',
'expirydatename': 'nktokenexpirydate',
'bearer_auth': True,
'base_url': "https://oauth-stage.nkrowlink.com/oauth/token",
'base_url': NK_OAUTH_LOCATION+"/oauth/token",
'scope':'read',
}
from requests.auth import HTTPBasicAuth
def get_token(code):
def get_token(code): # pragma: no cover
url = oauth_data['base_url']
@@ -97,14 +97,14 @@ def get_token(code):
def nk_open(user):
r = Rower.objects.get(user=user)
if (r.nktoken == '') or (r.nktoken is None):
if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
raise NoTokenError("User has no token")
else:
if (timezone.now()>r.nktokenexpirydate):
thetoken = rower_nk_token_refresh(user)
if thetoken == None:
if thetoken == None: # pragma: no cover
raise NoTokenError("User has no token")
return thetoken
else:
@@ -115,12 +115,12 @@ def nk_open(user):
def get_nk_workouts(rower, do_async=True):
try:
thetoken = nk_open(rower.user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return 0
res = get_nk_workout_list(rower.user)
if res.status_code != 200:
if res.status_code != 200: # pragma: no cover
return 0
nkids = [item['id'] for item in res.json()]
@@ -141,7 +141,7 @@ def get_nk_workouts(rower, do_async=True):
with open('nkblocked.json','r') as nkblocked:
jsondata = json.load(nkblocked)
parkedids = jsondata['ids']
except FileNotFoundError:
except FileNotFoundError: # pragma: no cover
pass
knownnkids = uniqify(knownnkids+tombstones+parkedids)
@@ -180,7 +180,7 @@ def do_refresh_token(refreshtoken):
response = requests.post(url,data=post_data,auth=HTTPBasicAuth(oauth_data['client_id'],oauth_data['client_secret']))
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
return [0,0,0]
token_json = response.json()
@@ -207,16 +207,16 @@ def rower_nk_token_refresh(user):
return r.nktoken
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
return imports_make_authorization_url(oauth_data)
def get_nk_workout_list(user,fake=False,after=0,before=0):
r = Rower.objects.get(user=user)
if (r.nktoken == '') or (r.nktoken is None):
if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s)
elif (r.nktokenexpirydate is None or timezone.now()+timedelta(seconds=10)>r.nktokenexpirydate):
elif (r.nktokenexpirydate is None or timezone.now()+timedelta(seconds=10)>r.nktokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
@@ -249,10 +249,10 @@ def get_nk_workout_list(user,fake=False,after=0,before=0):
def get_workout(user,nkid,do_async=False):
r = Rower.objects.get(user=user)
if (r.nktoken == '') or (r.nktoken is None):
if (r.nktoken == '') or (r.nktoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s) ,0
elif (timezone.now()>r.nktokenexpirydate):
elif (timezone.now()>r.nktokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s),0
@@ -260,7 +260,7 @@ def get_workout(user,nkid,do_async=False):
'sessionIds': nkid,
}
if do_async:
if do_async: # pragma: no cover
res = get_nk_workout_list(r.user)
if res.status_code != 200:
return 0
@@ -293,7 +293,7 @@ def get_workout(user,nkid,do_async=False):
response = requests.get(url,headers=headers,params=params)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
# error handling and logging
return {},pd.DataFrame()
@@ -323,7 +323,7 @@ def get_workout(user,nkid,do_async=False):
response = requests.get(url, headers=headers,params=params)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
# error handling and logging
return {},df
+2 -2
View File
@@ -48,7 +48,7 @@ class OpaqueEncoder:
"""Transcode an integer and return it as an 8-character hex string."""
return "%08x" % self.transcode(i)
def encode_base64(self, i):
def encode_base64(self, i): # pragma: no cover
"""Transcode an integer and return it as a 6-character base64 string."""
return base64.b64encode(struct.pack('!L', self.transcode(i)), self.extra_chars)[:6]
@@ -56,7 +56,7 @@ class OpaqueEncoder:
"""Decode an 8-character hex string, returning the original integer."""
return self.transcode(int(str(s), 16))
def decode_base64(self, s):
def decode_base64(self, s): # pragma: no cover
"""Decode a 6-character base64 string, returning the original integer."""
return self.transcode(struct.unpack('!L', base64.b64decode(s + '==', self.extra_chars))[0])
+6 -6
View File
@@ -25,22 +25,22 @@ class PowerServicer(object):
"""Power service definition
"""
def CalcPower(self, request, context):
def CalcPower(self, request, context): # pragma: no cover
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
context.set_code(grpc.StatusCode.UNIMPLEMENTED) # pragma: no cover
context.set_details('Method not implemented!') # pragma: no cover
raise NotImplementedError('Method not implemented!') # pragma: no cover
def add_PowerServicer_to_server(servicer, server):
def add_PowerServicer_to_server(servicer, server): # pragma: no cover
rpc_method_handlers = {
'CalcPower': grpc.unary_unary_rpc_method_handler(
servicer.CalcPower,
request_deserializer=otw__power__calculator__pb2.WorkoutPowerRequest.FromString,
response_serializer=otw__power__calculator__pb2.CalculationResult.SerializeToString,
),
}
} # pragma: no cover
generic_handler = grpc.method_handlers_generic_handler(
'otw_power_calculator.Power', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
+9 -9
View File
@@ -43,7 +43,7 @@ TEST_CLIENT_SECRET = "aapnootmies"
TEST_REDIRECT_URI = "http://localhost:8000/rowers/test_callback"
def custom_exception_handler(exc,message):
def custom_exception_handler(exc,message): # pragma: no cover
response = {
"errors": [
@@ -60,7 +60,7 @@ def custom_exception_handler(exc,message):
return res
def do_refresh_token(refreshtoken):
def do_refresh_token(refreshtoken): # pragma: no cover
client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET)
post_data = {"grant_type": "refresh_token",
"client_secret": TEST_CLIENT_SECRET,
@@ -88,7 +88,7 @@ def do_refresh_token(refreshtoken):
return [thetoken,expires_in,refresh_token]
def get_token(code):
def get_token(code): # pragma: no cover
client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET)
post_data = {"grant_type": "authorization_code",
"code": code,
@@ -114,7 +114,7 @@ def get_token(code):
return [thetoken,expires_in,refresh_token]
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
from uuid import uuid4
@@ -133,7 +133,7 @@ def make_authorization_url(request):
return HttpResponseRedirect(url)
def rower_ownapi_token_refresh(user):
def rower_ownapi_token_refresh(user): # pragma: no cover
r = Rower.objects.get(user=user)
res = do_refresh_token(r.ownapirefreshtoken)
access_token = res[0]
@@ -149,7 +149,7 @@ def rower_ownapi_token_refresh(user):
r.save()
return r.ownapitoken
def get_ownapi_workout_list(user):
def get_ownapi_workout_list(user): # pragma: no cover
r = Rower.objects.get(user=user)
if (r.ownapitoken == '') or (r.ownapitoken is None):
s = "Token doesn't exist. Need to authorize"
@@ -169,7 +169,7 @@ def get_ownapi_workout_list(user):
return s
def get_ownapi_workout(user,ownapiid):
def get_ownapi_workout(user,ownapiid): # pragma: no cover
r = Rower.objects.get(user=user)
if (r.ownapitoken == '') or (r.ownapitoken is None):
return custom_exception_handler(401,s)
@@ -188,7 +188,7 @@ def get_ownapi_workout(user,ownapiid):
return s
def createownapiworkoutdata(w):
def createownapiworkoutdata(w): # pragma: no cover
filename = w.csvfilename
row = rowingdata(csvfile=filename)
averagehr = int(row.df[' HRCur (bpm)'].mean())
@@ -277,7 +277,7 @@ def createownapiworkoutdata(w):
return data
def getidfromresponse(response):
def getidfromresponse(response): # pragma: no cover
t = json.loads(response.text)
uri = t['uris'][0]
id = uri[len(uri)-13:len(uri)-5]
+2 -27
View File
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
from rowers.models import Rower,PaidPlan
# run once - copies plans to paypal
def planstopaypal():
def planstopaypal(): # pragma: no cover
plans = PaidPlan.objects.all()
for plan in plans:
@@ -14,32 +14,8 @@ def planstopaypal():
plan.external_id = None
plan.save()
#def initiaterowerplans():
# rowers = Rower.objects.filter(paymenttype = 'recurring',paidplan = None)
# for r in rowers:
# r.paymentprocessor = 'paypal'
# r.save()
#def setrowerplans():
# rowers = Rower.objects.all()
# for r in rowers:
# paidplans = PaidPlan.objects.filter(
# shortname = r.rowerplan,
# paymenttype = r.paymenttype,
# clubsize = r.clubsize,
# paymentprocessor=r.paymentprocessor)
# if paidplans:
# r.paidplan = paidplans[0]
# r.save()
# else:
# try:
# print 'Could not set plan for ',r.user.username
# except:
# pass
def is_existing_customer(rower):
def is_existing_customer(rower): # pragma: no cover
if rower.country is not None and rower.customer_id is not None and rower.country != '':
if rower.subscription_id is None or rower.subscription_id == '':
return False
@@ -47,4 +23,3 @@ def is_existing_customer(rower):
return True
return False
+7 -7
View File
@@ -15,35 +15,35 @@ class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
if request.method in permissions.SAFE_METHODS: # pragma: no cover
return True
# Write permissions are only allowed to the owner of the snippet.
return obj.user == request.user
return obj.user == request.user # pragma: no cover
class IsOwnerOrNot(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
def has_object_permission(self, request, view, obj): # pragma: no cover
r = Rower.objects.get(user=request.user)
return (obj.user == r)
class IsRowerOrNot(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
def has_object_permission(self, request, view, obj): # pragma: no cover
r = Rower.objects.get(user=request.user)
return (r in obj.rower.all())
class IsPlanOrHigher(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
def has_object_permission(self, request, view, obj): # pragma: no cover
r = Rower.objects.get(user=request.user)
return r not in ['basic','pro','freecoach']
class IsCompetitorOrNot(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
def has_object_permission(self, request, view, obj): # pragma: no cover
return (obj.userid == request.user.id)
class IsManagerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
def has_object_permission(self, request, view, obj): # pragma: no cover
if request.method in permissions.SAFE_METHODS:
return True
+9 -10
View File
@@ -7,7 +7,7 @@ from matplotlib.ticker import MultipleLocator,FuncFormatter,NullFormatter
import matplotlib.pyplot as plt
import numpy as np
from rowers.rows import format_pace_tick, format_pace, format_time, format_time_tick
from rowers.rows import format_pace_tick, format_pace, format_time, format_time_tick
# Formatting the distance tick marks
@@ -36,7 +36,7 @@ def y_axis_range(ydata,miny=0,padding=.1,ultimate=[-1e9,1e9]):
if (yrange == 0):
if (yrange == 0): # pragma: no cover
if ymin == 0:
yrangemin = -padding
else:
@@ -49,23 +49,23 @@ def y_axis_range(ydata,miny=0,padding=.1,ultimate=[-1e9,1e9]):
yrangemin = ymin-padding*yrange
yrangemax = ymax+padding*yrange
if (yrangemin < ultimate[0]):
if (yrangemin < ultimate[0]): # pragma: no cover
yrangemin = ultimate[0]
if (yrangemax > ultimate[1]):
yrangemax = ultimate[1]
return [yrangemin,yrangemax]
# Make a plot (this one is only used for testing)
def mkplot(row,title):
df = row.df
t = df.loc[:,' ElapsedTime (sec)']
p = df.loc[:,' Stroke500mPace (sec/500m)']
hr = df.loc[:,' HRCur (bpm)']
t = df.loc[:,' ElapsedTime (sec)'].values
p = df.loc[:,' Stroke500mPace (sec/500m)'].values
hr = df.loc[:,' HRCur (bpm)'].values
end_time = int(df.loc[:,'TimeStamp (sec)'].iloc[df.shape[0]-1])
fig, ax1 = plt.subplots(figsize=(5,4))
@@ -85,7 +85,7 @@ def mkplot(row,title):
majorFormatter = FuncFormatter(format_pace_tick)
majorLocator = (5)
timeTickFormatter = NullFormatter()
ax1.yaxis.set_major_formatter(majorFormatter)
for tl in ax1.get_yticklabels():
@@ -100,8 +100,7 @@ def mkplot(row,title):
ax2.patch.set_alpha(0.0)
for tl in ax2.get_yticklabels():
tl.set_color('r')
plt.subplots_adjust(hspace=0)
return fig
+10 -10
View File
@@ -62,7 +62,7 @@ from rowers.utils import NoTokenError, custom_exception_handler
import rowers.mytypes as mytypes
# Exchange access code for long-lived access token
def get_token(code):
def get_token(code): # pragma: no cover
post_data = {"grant_type": "authorization_code",
"code": code,
@@ -99,7 +99,7 @@ def get_token(code):
return [thetoken,expires_in,user_id]
# Make authorization URL including random string
def make_authorization_url():
def make_authorization_url(): # pragma: no cover
# Generate a random string for the state parameter
# Save it for use later to prevent xsrf attacks
state = str(uuid4())
@@ -130,7 +130,7 @@ def get_polar_notifications():
try:
response = requests.get(url, headers=headers)
except ConnectionError:
except ConnectionError: # pragma: no cover
response = {
'status_code':400,
}
@@ -145,7 +145,7 @@ def get_polar_notifications():
from rowers.rower_rules import ispromember
def get_all_new_workouts(available_data,testing=False):
for record in available_data:
for record in available_data: # pragma: no cover
if testing:
print(record)
if record['data-type'] == 'EXERCISE':
@@ -159,7 +159,7 @@ def get_all_new_workouts(available_data,testing=False):
except Rower.DoesNotExist:
pass
return 1
return 1 # pragma: no cover
def get_polar_workouts(user):
@@ -170,10 +170,10 @@ def get_polar_workouts(user):
if (r.polartoken == '') or (r.polartoken is None):
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s)
elif (timezone.now()>r.polartokenexpirydate):
elif (timezone.now()>r.polartokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh"
return custom_exception_handler(401,s)
else:
else: # pragma: no cover
authorizationstring = str('Bearer ' + r.polartoken)
headers = {'Authorization':authorizationstring,
'Accept': 'application/json'}
@@ -245,9 +245,9 @@ def get_polar_workouts(user):
# commit transaction
requests.put(url, headers=headers)
return exercise_list
return exercise_list # pragma: no cover
def get_polar_user_info(user,physical=False):
def get_polar_user_info(user,physical=False): # pragma: no cover
r = Rower.objects.get(user=user)
if (r.polartoken == '') or (r.polartoken is None):
s = "Token doesn't exist. Need to authorize"
@@ -285,7 +285,7 @@ def get_polar_user_info(user,physical=False):
return response
def get_polar_workout(user,id,transactionid):
def get_polar_workout(user,id,transactionid): # pragma: no cover
r = Rower.objects.get(user=user)
if (r.polartoken == '') or (r.polartoken is None):
+51 -52
View File
@@ -79,7 +79,7 @@ def user_is_not_basic(user):
return True
if user.rower.protrialexpires >= datetime.date.today():
return True
return True # pragma: no cover
return False
@@ -89,7 +89,7 @@ def user_is_basic(user):
@rules.predicate
def can_start_trial(user):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
@@ -97,13 +97,13 @@ def can_start_trial(user):
@rules.predicate
def can_start_plantrial(user):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return user.rower.plantrialexpires == datetime.date(1970,1,1)
@rules.predicate
def is_staff(user):
def is_staff(user): # pragma: no cover
return user.is_staff
@rules.predicate
@@ -117,7 +117,7 @@ def is_paid_coach(user):
def is_planmember(user):
try:
r = user.rower
except AttributeError:
except AttributeError: # pragma: no cover
return False
return r.rowerplan in ['coach','plan'] # freecoach?
@@ -144,7 +144,7 @@ def is_protrial(user):
if r.mycoachgroup is not None:
return len(r.mycoachgroup)>=4
return False
return False # pragma: no cover
@@ -171,7 +171,7 @@ def can_add_plan(user):
@rules.predicate
def can_add_workout(user):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return user.rower.rowerplan != 'freecoach'
@@ -180,7 +180,7 @@ def can_add_workout(user):
def is_plantrial(user):
try:
r = user.rower
except AttributeError:
except AttributeError: # pragma: no cover
return False
if r.rowerplan in ['basic','pro']:
@@ -189,7 +189,7 @@ def is_plantrial(user):
if r.mycoachgroup is not None:
return len(r.mycoachgroup)>=4
return False
return False # pragma: no cover
isplanmember = is_planmember | is_plantrial
@@ -202,13 +202,13 @@ def can_add_session(user):
@rules.predicate
def can_plan(user):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
if user.rower.rowerplan in ['plan','coach']:
return True
if user.rower.rowerplan in ['basic','pro']:
return user.rower.plantrialexpires >= datetime.date.today()
if user.rower.rowerplan == 'freecoach':
if user.rower.rowerplan == 'freecoach': # pragma: no cover
if user.rower.mycoachgroup is not None:
return len(user.rower.mycoachgroup)>=4
@@ -238,8 +238,7 @@ def is_coach_user(usercoach,userrower):
# checks if rower is coach of user (or is user himself)
@rules.predicate
def is_anonymous_or_coach(usercoach,userrower):
print(usercoach,userrower)
def is_anonymous_or_coach(usercoach,userrower): # pragma: no cover
if usercoach == userrower:
return True
@@ -267,7 +266,7 @@ def is_anonymous_or_coach(usercoach,userrower):
# check if rower and user are members of the same team
@rules.predicate
def is_rower_team_member(user,rower):
if user.rower == rower:
if user.rower == rower: # pragma: no cover
return True
if is_coach_user(user,rower.user):
@@ -286,11 +285,11 @@ def is_rower_team_member(user,rower):
@rules.predicate
def can_add_workout_member(user,rower):
if not user:
if not user: # pragma: no cover
return False
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
if user == rower.user:
if user == rower.user: # pragma: no cover
return True
# only below tested - need test user == rower.user
return is_coach(user) and user.rower in rower.get_coaches()
@@ -310,7 +309,7 @@ def can_plan_user(user,rower):
# free coach, plan etc cannot plan for basic
if not is_paid_coach(user) and user_is_not_basic(user):
for t in teams:
if rower in t.rower.all():
if rower in t.rower.all(): # pragma: no cover
return True
# paying coach can plan for all kinds of rowers
@@ -362,7 +361,7 @@ def is_workout_user(user,workout):
try:
r = user.rower
except AttributeError:
except AttributeError: # pragma: no cover
return False
if workout.user == r:
@@ -373,12 +372,12 @@ def is_workout_user(user,workout):
# check if user is in same team as owner of workout
@rules.predicate
def is_workout_team(user,workout):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
try:
r = user.rower
except AttributeError:
except AttributeError: # pragma: no cover
return False
if workout.user == r:
@@ -391,9 +390,9 @@ def is_workout_team(user,workout):
def can_view_workout(user,workout):
if workout.privacy != 'private':
return True
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return user == workout.user.user
return user == workout.user.user # pragma: no cover
can_change_workout = is_workout_user
@@ -444,7 +443,7 @@ rules.add_perm('workout.view_workout',can_view_workout) # replaces checkworkoutu
# untested can_view_target to can_delete_target
@rules.predicate
def can_view_target(user,target):
def can_view_target(user,target): # pragma: no cover
if user.is_anonymous:
return False
if user == target.manager.user:
@@ -459,14 +458,14 @@ def can_view_target(user,target):
return True
@rules.predicate
def can_change_target(user,target):
def can_change_target(user,target): # pragma: no cover
if user.is_anonymous:
return False
return user == target.manager.user
@rules.predicate
def can_delete_target(user,target):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return user == target.manager.user
@@ -476,30 +475,30 @@ rules.add_perm('target.delete_target',can_delete_target)
@rules.predicate
def can_view_plan(user,plan):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
if user == plan.manager.user:
return True
# a plan's coach can view as well
# below untested
if is_coach_user(user,plan.manager.user):
if is_coach_user(user,plan.manager.user): # pragma: no cover
return True
# the object can view as well
if user.rower in plan.rowers.all():
if user.rower in plan.rowers.all(): # pragma: no cover
return True
@rules.predicate
def can_change_plan(user,plan):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return user == plan.manager.user
return user == plan.manager.user # pragma: no cover
# below untested
@rules.predicate
def can_delete_plan(user,plan):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return user == plan.manager.user
@@ -512,7 +511,7 @@ rules.add_perm('plan.can_add_plan',can_add_plan)
# untested
@rules.predicate
def can_view_cycle(user,cycle):
def can_view_cycle(user,cycle): # pragma: no cover
try:
return can_view_cycle(user,cycle.plan)
except AttributeError:
@@ -521,7 +520,7 @@ def can_view_cycle(user,cycle):
return False
@rules.predicate
def can_change_cycle(user,cycle):
def can_change_cycle(user,cycle): # pragma: no cover
try:
return can_change_cycle(user,cycle.plan)
except AttributeError:
@@ -530,7 +529,7 @@ def can_change_cycle(user,cycle):
return False
@rules.predicate
def can_delete_cycle(user,cycle):
def can_delete_cycle(user,cycle): # pragma: no cover
try:
return can_delete_cycle(user,cycle.plan)
except AttributeError:
@@ -547,43 +546,43 @@ rules.add_perm('cycle.delete_cycle',can_delete_cycle)
# check if user has view access to session
@rules.predicate
def can_view_session(user,session):
if session.sessiontype in ['race','indoorrace']:
if session.sessiontype in ['race','indoorrace']: # pragma: no cover
return True
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
# session manager can view session
if user == session.manager:
return True
# if you're a rower in the session you can view it
# below untested
if user.rower in session.rower.all():
if user.rower in session.rower.all(): # pragma: no cover
return True
# coach users can view sessions created by their team members
# below untested
if is_coach(user):
if is_coach(user): # pragma: no cover
teams = user.rower.get_managed_teams()
for t in teams:
teamusers = [member.u for member in t.rower.all()]
if session.manager in teamusers:
return True
return False
return False # pragma: no cover
@rules.predicate
def can_change_session(user,session):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
# session part of a race should not be changed through the session interface
if session.sessiontype in ['race','indoorrace']:
if session.sessiontype in ['race','indoorrace']: # pragma: no cover
return False
if user == session.manager:
return True
return False
return False # pragma: no cover
@rules.predicate
def can_delete_session(user,session):
def can_delete_session(user,session): # pragma: no cover
if user.is_anonymous:
return False
@@ -636,7 +635,7 @@ def is_team_manager(user,team):
# check is user is member of team - untested
@rules.predicate
def is_team_member(user,team):
def is_team_member(user,team): # pragma: no cover
members = team.rower.all()
return user in [member.user for member in members]
@@ -644,13 +643,13 @@ def is_team_member(user,team):
@rules.predicate
def can_view_team(user,team):
# user based - below untested
if user.rower.rowerplan == 'basic' and team.manager.rower.rowerplan != 'coach':
if user.rower.rowerplan == 'basic' and team.manager.rower.rowerplan != 'coach': # pragma: no cover
return is_plantrial(user) or is_protrial(user)
# team is public
if team.private == 'open':
return True
# team is private - below untested
return is_team_member(user,team) | is_team_manager(user,team)
return is_team_member(user,team) | is_team_manager(user,team) # pragma: no cover
@rules.predicate
def can_change_team(user,team):
@@ -682,7 +681,7 @@ rules.add_perm('teams.delete_team',can_delete_team)
@rules.predicate
def can_change_course(user,course):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return course.manager == user.rower
@@ -690,21 +689,21 @@ def can_change_course(user,course):
# untested
@rules.predicate
def can_delete_course(user,course):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return course.manager == user.rower
@rules.predicate
def can_delete_logo(user,logo):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return logo.user == user
return logo.user == user # pragma: no cover
@rules.predicate
def can_change_race(user,race):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
return race.manager == user
+4 -4
View File
@@ -28,12 +28,12 @@ class MetricsServicer(object):
def CalcMetrics(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
context.set_code(grpc.StatusCode.UNIMPLEMENTED) # pragma: no cover
context.set_details('Method not implemented!') # pragma: no cover
raise NotImplementedError('Method not implemented!') # pragma: no cover
def add_MetricsServicer_to_server(servicer, server):
def add_MetricsServicer_to_server(servicer, server): # pragma: no cover
rpc_method_handlers = {
'CalcMetrics': grpc.unary_unary_rpc_method_handler(
servicer.CalcMetrics,
+10 -10
View File
@@ -14,21 +14,21 @@ import uuid
from django.core.exceptions import ValidationError
def format_pace_tick(x,pos=None):
def format_pace_tick(x,pos=None): # pragma: no cover
minu=int(x/60)
sec=int(x-minu*60.)
sec_str=str(sec).zfill(2)
template='%d:%s'
return template % (minu,sec_str)
def format_time_tick(x,pos=None):
def format_time_tick(x,pos=None): # pragma: no cover
hour=int(x/3600)
min=int((x-hour*3600.)/60)
min_str=str(min).zfill(2)
template='%d:%s'
return template % (hour,min_str)
def format_pace(x,pos=None):
def format_pace(x,pos=None): # pragma: no cover
if isinf(x) or isnan(x):
x=0
@@ -42,7 +42,7 @@ def format_pace(x,pos=None):
return str1
def format_time(x,pos=None):
def format_time(x,pos=None): # pragma: no cover
min = int(x/60.)
@@ -60,7 +60,7 @@ def validate_image_extension(value):
ext = os.path.splitext(value.name)[1].lower()
valid_extension = ['.jpg','.jpeg','.png','.gif']
if not ext in valid_extension:
if not ext in valid_extension: # pragma: no cover
raise ValidationError(u'File not supported')
def validate_file_extension(value):
@@ -69,25 +69,25 @@ def validate_file_extension(value):
valid_extensions = ['.tcx','.csv','.TCX','.gpx','.GPX',
'.CSV','.fit','.FIT','.zip','.ZIP',
'.gz','.GZ','.xls']
if not ext in valid_extensions:
if not ext in valid_extensions: # pragma: no cover
raise ValidationError(u'File not supported!')
def must_be_csv(value):
import os
ext = os.path.splitext(value.name)[1]
valid_extensions = ['.csv','.CSV']
if not ext in valid_extensions:
if not ext in valid_extensions: # pragma: no cover
raise ValidationError(u'File not supported!')
def validate_kml(value):
import os
ext = os.path.splitext(value.name)[1]
valid_extensions = ['.kml','.KML']
if not ext in valid_extensions:
if not ext in valid_extensions: # pragma: no cover
raise ValidationError(u'File not supported!')
def handle_uploaded_image(i):
def handle_uploaded_image(i): # pragma: no cover
from io import StringIO, BytesIO
from PIL import Image, ImageOps, ExifTags
import os
@@ -121,7 +121,7 @@ def handle_uploaded_image(i):
try:
if exif[orientation] == 3:
mage=image.rotate(180, expand=True)
image=image.rotate(180, expand=True)
elif exif[orientation] == 6:
image=image.rotate(270, expand=True)
elif exif[orientation] == 8:
+8 -8
View File
@@ -61,11 +61,11 @@ def rp3_open(user):
return imports_open(user, oauth_data)
# Refresh ST token using refresh token
def do_refresh_token(refreshtoken):
def do_refresh_token(refreshtoken): # pragma: no cover
return imports_do_refresh_token(refreshtoken, oauth_data)
# Exchange access code for long-lived access token
def get_token(code):
def get_token(code): # pragma: no cover
client_auth = requests.auth.HTTPBasicAuth(RP3_CLIENT_KEY, RP3_CLIENT_SECRET)
post_data = {
"client_id":RP3_CLIENT_KEY,
@@ -97,7 +97,7 @@ def get_token(code):
return thetoken,expires_in,refresh_token
# Make authorization URL including random string
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
return imports_make_authorization_url(oauth_data)
@@ -124,7 +124,7 @@ def get_rp3_workout_list(user):
return response
def get_rp3_workouts(rower,do_async=True):
def get_rp3_workouts(rower,do_async=True): # pragma: no cover
try:
auth_token = rp3_open(rower.user)
except NoTokenError:
@@ -160,7 +160,7 @@ def get_rp3_workouts(rower,do_async=True):
return 1
def download_rp3_file(url,auth_token,filename):
def download_rp3_file(url,auth_token,filename): # pragma: no cover
headers = {'Authorization': 'Bearer ' + auth_token }
res = requests.get(url,headers=headers)
@@ -171,7 +171,7 @@ def download_rp3_file(url,auth_token,filename):
return res.status_code
def get_rp3_workout_token(workout_id,auth_token,waittime=3,max_attempts=20):
def get_rp3_workout_token(workout_id,auth_token,waittime=3,max_attempts=20): # pragma: no cover
headers = {'Authorization': 'Bearer ' + auth_token }
get_download_link = """{
@@ -211,13 +211,13 @@ def get_rp3_workout_token(workout_id,auth_token,waittime=3,max_attempts=20):
return download_url
def get_rp3_workout_link(user,workout_id,waittime=3,max_attempts=20):
def get_rp3_workout_link(user,workout_id,waittime=3,max_attempts=20): # pragma: no cover
r = Rower.objects.get(user=user)
auth_token = rp3_open(user)
return get_rp3_workout_token(workout_id,auth_token,waittime=waittime,max_attempts=max_attempts)
def get_rp3_workout(user,workout_id,startdatetime=None):
def get_rp3_workout(user,workout_id,startdatetime=None): # pragma: no cover
url = get_rp3_workout_link(user,workout_id)
filename = 'media/RP3Import_'+str(workout_id)+'.csv'
+33 -26
View File
@@ -71,7 +71,7 @@ def get_token(code):
return imports_get_token(code,oauth_data)
# Make authorization URL including random string
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
return imports_make_authorization_url(oauth_data)
# Get list of workouts available on Runkeeper
@@ -94,7 +94,7 @@ def get_runkeeper_workout_list(user):
# Get workout summary data by Runkeeper ID
def get_workout(user,runkeeperid,do_async=False):
r = Rower.objects.get(user=user)
if (r.runkeepertoken == '') or (r.runkeepertoken is None):
if (r.runkeepertoken == '') or (r.runkeepertoken is None): # pragma: no cover
return custom_exception_handler(401,s)
s = "Token doesn't exist. Need to authorize"
else:
@@ -108,7 +108,7 @@ def get_workout(user,runkeeperid,do_async=False):
try:
data = s.json()
except ValueError:
except ValueError: # pragma: no cover
data = {}
return data,"Something went wrong with the workout import"
@@ -123,19 +123,26 @@ def createrunkeeperworkoutdata(w):
filename = w.csvfilename
try:
row = rowingdata(csvfile=filename)
except:
except: # pragma: no cover
return 0
averagehr = int(row.df[' HRCur (bpm)'].mean())
maxhr = int(row.df[' HRCur (bpm)'].max())
try:
averagehr = int(row.df[' HRCur (bpm)'].mean())
maxhr = int(row.df[' HRCur (bpm)'].max())
except KeyError: # pragma: no cover
averagehr = 0
maxhr = 0
duration = w.duration.hour*3600
duration += w.duration.minute*60
duration += w.duration.second
duration += +1.0e-6*w.duration.microsecond
# adding diff, trying to see if this is valid
#t = row.df.ix[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)']
t = row.df.loc[:,'TimeStamp (sec)'].values-row.df.loc[:,'TimeStamp (sec)'].iloc[0]
try:
t = row.df.loc[:,'TimeStamp (sec)'].values-row.df.loc[:,'TimeStamp (sec)'].iloc[0]
except KeyError: # pragma: no cover
return pd.DataFrame()
t[0] = t[1]
d = row.df.loc[:,'cum_dist'].values
@@ -151,9 +158,9 @@ def createrunkeeperworkoutdata(w):
try:
lat = row.df[' latitude'].values
lon = row.df[' longitude'].values
if not lat.std() and not lon.std():
if not lat.std() and not lon.std(): # pragma: no cover
haslatlon = 0
except KeyError:
except KeyError: # pragma: no cover
haslatlon = 0
t = t.tolist()
@@ -236,7 +243,7 @@ def getidfromresponse(response):
return int(id)
def geturifromid(access_token,id):
def geturifromid(access_token,id): # pragma: no cover
authorizationstring = str('Bearer ' + access_token)
headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
@@ -271,21 +278,21 @@ def get_userid(access_token):
try:
me_json = response.json()
except:
except: # pragma: no cover
return ''
try:
res = me_json['userID']
except KeyError:
except KeyError: # pragma: no cover
res = ''
return str(res)
def default(o):
def default(o): # pragma: no cover
if isinstance(o, numpy.int64): return int(o)
raise TypeError
def workout_runkeeper_upload(user,w,asynchron=False):
def workout_runkeeper_upload(user,w,asynchron=False): # pragma: no cover
message = "Uploading to Runkeeper"
rkid = 0
@@ -351,7 +358,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper',
workouttype = 'other'
try:
comments = data['notes']
except:
except: # pragma: no cover
comments = ''
try:
@@ -364,14 +371,14 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper',
try:
rowdatetime = iso8601.parse_date(data['start_time'])
except iso8601.ParseError:
try:
try: # pragma: no cover
rowdatetime = datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except ValueError:
try:
rowdatetime = parser.parse(data['start_time'])
#rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
except:
except: # pragma: no cover
rowdatetime = datetime.strptime(data['date'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
starttimeunix = arrow.get(rowdatetime).timestamp()
@@ -399,14 +406,14 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper',
latcoord = res[1]
loncoord = res[2]
except:
except: # pragma: no cover
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in types.otwtypes:
workouttype = 'rower'
try:
try: # pragma: no cover
res = splitrunkeeperdata(data['cadence'],'timestamp','cadence')
times_spm = res[0]
spm = res[1]
@@ -418,7 +425,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper',
res = splitrunkeeperdata(data['heart_rate'],'timestamp','heart_rate')
hr = res[1]
times_hr = res[0]
except KeyError:
except KeyError: # pragma: no cover
times_hr = times_distance
hr = 0*times_distance
@@ -429,13 +436,13 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper',
latseries = pd.Series(latcoord,index=times_location)
try:
latseries = latseries.groupby(latseries.index).first()
except TypeError:
except TypeError: # pragma: no cover
latseries = 0.0*distseries
lonseries = pd.Series(loncoord,index=times_location)
try:
lonseries = lonseries.groupby(lonseries.index).first()
except TypeError:
except TypeError: # pragma: no cover
lonseries = 0.0*distseries
spmseries = pd.Series(spm,index=times_spm)
@@ -443,7 +450,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper',
hrseries = pd.Series(hr,index=times_hr)
try:
hrseries = hrseries.groupby(hrseries.index).first()
except TypeError:
except TypeError: # pragma: no cover
hrseries = 0*distseries
@@ -484,7 +491,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='runkeeper',
unixtime = cum_time+starttimeunix
try:
unixtime[0] = starttimeunix
except IndexError:
except IndexError: # pragma: no cover
return (0,'No data to import')
df['TimeStamp (sec)'] = unixtime
+19 -19
View File
@@ -12,10 +12,10 @@ def save_scoring(name,user,filename,id=0,notes=""):
collection = StandardCollection(name=name,manager=user,notes=notes)
collection.save()
standards = CourseStandard.objects.filter(standardcollection=collection)
for standard in standards:
for standard in standards: # pragma: no cover
standards.delete()
else:
else: # pragma: no cover
try:
collection = StandardCollection.objects.get(id=id)
collection.name = name
@@ -34,7 +34,7 @@ def save_scoring(name,user,filename,id=0,notes=""):
try:
df = pd.read_csv(filename)
except:
except: # pragma: no cover
return 0
df.rename(
@@ -58,7 +58,7 @@ def save_scoring(name,user,filename,id=0,notes=""):
for index, row in df.iterrows():
try:
name = row['Name']
except KeyError:
except KeyError: # pragma: no cover
continue
try:
@@ -69,7 +69,7 @@ def save_scoring(name,user,filename,id=0,notes=""):
seconds = delta.total_seconds()
referencespeed = coursedistance/seconds
except KeyError:
except KeyError: # pragma: no cover
continue
try:
@@ -77,7 +77,7 @@ def save_scoring(name,user,filename,id=0,notes=""):
agemax = row['MaxAge']
agemin = int(agemin)
agemax = int(agemax)
except KeyError:
except KeyError: # pragma: no cover
agemin = 0
agemax = 120
@@ -85,24 +85,24 @@ def save_scoring(name,user,filename,id=0,notes=""):
boatclass = row['BoatClass']
if boatclass.lower() in ['standard','olympic','normal','water']:
boatclass = 'water'
elif boatclass.lower() in ['erg','c2','concept','static','rower']:
elif boatclass.lower() in ['erg','c2','concept','static','rower']: # pragma: no cover
boatclass = 'rower'
elif boatclass.lower() in ['dynamic']:
elif boatclass.lower() in ['dynamic']: # pragma: no cover
boatclass = 'dynamic'
elif boatclass.lower() in ['slides','slide','slider','sliders']:
elif boatclass.lower() in ['slides','slide','slider','sliders']: # pragma: no cover
boatclass = 'slides'
elif boatclass.lower() in ['c','c-boat']:
elif boatclass.lower() in ['c','c-boat']: # pragma: no cover
boatclass = 'c-boat'
elif boatclass.lower() in ['coastal','coast']:
elif boatclass.lower() in ['coastal','coast']: # pragma: no cover
boatclass = 'coastal'
elif boatclass.lower() in ['church','churchboat','finnish','finland']:
elif boatclass.lower() in ['church','churchboat','finnish','finland']: # pragma: no cover
boatclass = 'churchboat'
except KeyError:
except KeyError: # pragma: no cover
boatclass = 'water'
try:
boattype = row['BoatType']
except KeyError:
except KeyError: # pragma: no cover
boattype = '1x'
try:
@@ -113,7 +113,7 @@ def save_scoring(name,user,filename,id=0,notes=""):
sex = 'mixed'
else:
sex = 'female'
except KeyError:
except KeyError: # pragma: no cover
sex = 'female'
try:
@@ -122,7 +122,7 @@ def save_scoring(name,user,filename,id=0,notes=""):
weightclass = 'hwt'
elif weightclass.lower() in ['lwt','l','light','lights','lighties']:
weightclass = 'lwt'
except KeyError:
except KeyError: # pragma: no cover
weightclass = 'hwt'
adaptiveclass = 'None'
@@ -130,18 +130,18 @@ def save_scoring(name,user,filename,id=0,notes=""):
adaptiveclass = row['AdaptiveClass']
if adaptiveclass.lower() in ['o','open','none','no']:
adaptiveclass = 'None'
except KeyError:
except KeyError: # pragma: no cover
adaptiveclass = 'None'
try:
skillclass = row['SkillClass']
except KeyError:
except KeyError: # pragma: no cover
skillclass = 'Open'
# finding existing standard
existingstandards = CourseStandard.objects.filter(name=name,standardcollection=collection)
#print(existingstandards,collection)
if existingstandards:
if existingstandards: # pragma: no cover
existingstandards.update(
name=name,
coursedistance=coursedistance,
+5 -5
View File
@@ -151,7 +151,7 @@ class PlannedSessionSerializer(serializers.ModelSerializer):
'fitfile'
)
def create(self, validated_data):
def create(self, validated_data): # pragma: no cover
if self.context['request'].user.is_authenticated:
r = Rower.objects.get(user=self.context['request'].user)
else:
@@ -206,7 +206,7 @@ class WorkoutSerializer(serializers.ModelSerializer):
'rankingpiece'
)
def create(self, validated_data):
def create(self, validated_data): # pragma: no cover
if self.context['request'].user.is_authenticated:
r = Rower.objects.get(user=self.context['request'].user)
else:
@@ -226,7 +226,7 @@ class WorkoutSerializer(serializers.ModelSerializer):
return Workout.objects.create(**validated_data)
def update(self, instance, validated_data):
def update(self, instance, validated_data): # pragma: no cover
d = validated_data['date']
t = validated_data['starttime']
rowdatetime = datetime.datetime(d.year,
@@ -263,7 +263,7 @@ class StrokeDataSerializer(serializers.Serializer):
workoutid = serializers.IntegerField
strokedata = serializers.JSONField
def create(self, workoutid, strokedata):
def create(self, workoutid, strokedata): # pragma: no cover
"""
Create and enter a new set of stroke data into the DB
"""
@@ -307,7 +307,7 @@ class GeoCourseSerializer(serializers.ModelSerializer):
'polygons',
)
def update(self, instance, validated_data):
def update(self, instance, validated_data): # pragma: no cover
instance.name = validated_data.get('name',instance.name)
instance.country = validated_data.get('country',instance.country)
instance.notes = validated_data.get('notes',instance.notes)
+17 -17
View File
@@ -55,11 +55,11 @@ def get_token(code):
return imports_get_token(code,oauth_data)
# Make authorization URL including random string
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
return imports_make_authorization_url(oauth_data)
# This is token refresh. Looks for tokens in our database, then refreshes
def rower_sporttracks_token_refresh(user):
def rower_sporttracks_token_refresh(user): # pragma: no cover
r = Rower.objects.get(user=user)
res = do_refresh_token(r.sporttracksrefreshtoken)
access_token = res[0]
@@ -82,7 +82,7 @@ def get_sporttracks_workout_list(user):
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s)
elif (timezone.now()>r.sporttrackstokenexpirydate):
elif (timezone.now()>r.sporttrackstokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
@@ -99,10 +99,10 @@ def get_sporttracks_workout_list(user):
# Get workout summary data by SportTracks ID
def get_workout(user,sporttracksid,do_async=False):
r = Rower.objects.get(user=user)
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None):
if (r.sporttrackstoken == '') or (r.sporttrackstoken is None): # pragma: no cover
return custom_exception_handler(401,s)
s = "Token doesn't exist. Need to authorize"
elif (timezone.now()>r.sporttrackstokenexpirydate):
elif (timezone.now()>r.sporttrackstokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
@@ -129,13 +129,13 @@ def createsporttracksworkoutdata(w):
filename = w.csvfilename
try:
row = rowingdata(csvfile=filename)
except:
except: # pragma: no cover
return 0
try:
averagehr = int(row.df[' HRCur (bpm)'].mean())
maxhr = int(row.df[' HRCur (bpm)'].max())
except KeyError:
except KeyError: # pragma: no cover
averagehr = 0
maxhr = 0
@@ -162,7 +162,7 @@ def createsporttracksworkoutdata(w):
try:
lat = row.df[' latitude'].values
lon = row.df[' longitude'].values
if not lat.std() and not lon.std():
if not lat.std() and not lon.std(): # pragma: no cover
haslatlon = 0
except KeyError:
haslatlon = 0
@@ -171,7 +171,7 @@ def createsporttracksworkoutdata(w):
haspower = 1
try:
power = row.df[' Power (watts)'].astype(int).values
except KeyError:
except KeyError: # pragma: no cover
haspower = 0
locdata = []
@@ -259,13 +259,13 @@ def getidfromresponse(response):
return int(id)
def default(o):
def default(o): # pragma: no cover
if isinstance(o, numpy.int64): return int(o)
raise TypeError
def workout_sporttracks_upload(user,w,asynchron=False):
def workout_sporttracks_upload(user,w,asynchron=False): # pragma: no cover
message = "Uploading to SportTracks"
stid = 0
# ready to upload. Hurray
@@ -325,7 +325,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks',
workoutsource='sporttracks'):
try:
workouttype = data['type']
except KeyError:
except KeyError: # pragma: no cover
workouttype = 'other'
if workouttype not in [x[0] for x in Workout.workouttypes]:
@@ -339,7 +339,7 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks',
r = Rower.objects.get(user=user)
try:
rowdatetime = iso8601.parse_date(data['start_time'])
except iso8601.ParseError:
except iso8601.ParseError: # pragma: no cover
try:
rowdatetime = datetime.datetime.strptime(data['start_time'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
@@ -354,14 +354,14 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks',
try:
title = data['name']
except:
except: # pragma: no cover
title = "Imported data"
try:
res = splitstdata(data['distance'])
distance = res[1]
times_distance = res[0]
except KeyError:
except KeyError: # pragma: no cover
try:
res = splitstdata(data['heartrate'])
times_distance = res[0]
@@ -388,14 +388,14 @@ def add_workout_from_data(user,importid,data,strokedata,source='sporttracks',
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
if workouttype in mytypes.otwtypes:
if workouttype in mytypes.otwtypes: # pragma: no cover
workouttype = 'rower'
try:
res = splitstdata(data['cadence'])
times_spm = res[0]
spm = res[1]
except KeyError:
except KeyError: # pragma: no cover
times_spm = times_distance
spm = 0*times_distance
+84 -80
View File
@@ -41,7 +41,7 @@ from rowsandall_app.settings import (
try:
from json.decoder import JSONDecodeError
except ImportError:
except ImportError: # pragma: no cover
JSONDecodeError = ValueError
from rowers.imports import *
@@ -91,7 +91,7 @@ def strava_open(user):
f.write(json.dumps(oauth_data))
f.write('\n')
token = imports_open(user, oauth_data)
if user.rower.strava_owner_id == 0:
if user.rower.strava_owner_id == 0: # pragma: no cover
strava_owner_id = set_strava_athlete_id(user)
return token
@@ -114,10 +114,10 @@ def rower_strava_token_refresh(user):
return r.stravatoken
# Make authorization URL including random string
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
return imports_make_authorization_url(oauth_data)
def strava_establish_push():
def strava_establish_push(): # pragma: no cover
url = "https://www.strava.com/api/v3/push_subscriptions"
post_data = {
'client_id': STRAVA_CLIENT_ID,
@@ -133,7 +133,7 @@ def strava_establish_push():
return response.status_code
def strava_list_push():
def strava_list_push(): # pragma: no cover
url = "https://www.strava.com/api/v3/push_subscriptions"
params = {
'client_id': STRAVA_CLIENT_ID,
@@ -147,7 +147,7 @@ def strava_list_push():
return [w['id'] for w in data]
return []
def strava_push_delete(id):
def strava_push_delete(id): # pragma: no cover
url = "https://www.strava.com/api/v3/push_subscriptions/{id}".format(id=id)
params = {
'client_id': STRAVA_CLIENT_ID,
@@ -159,7 +159,7 @@ def strava_push_delete(id):
def set_strava_athlete_id(user):
r = Rower.objects.get(user=user)
if (r.stravatoken == '') or (r.stravatoken is None):
if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s)
elif (r.stravatokenexpirydate is None or timezone.now()+timedelta(seconds=3599)>r.stravatokenexpirydate):
@@ -173,7 +173,7 @@ def set_strava_athlete_id(user):
response = requests.get(url,headers=headers,params={})
if response.status_code == 200:
if response.status_code == 200: # pragma: no cover
r.strava_owner_id = response.json()['id']
r.save()
return response.json()['id']
@@ -185,10 +185,10 @@ def set_strava_athlete_id(user):
def get_strava_workout_list(user,limit_n=0):
r = Rower.objects.get(user=user)
if (r.stravatoken == '') or (r.stravatoken is None):
if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s)
elif (r.stravatokenexpirydate is None or timezone.now()+timedelta(seconds=3599)>r.stravatokenexpirydate):
elif (r.stravatokenexpirydate is None or timezone.now()+timedelta(seconds=3599)>r.stravatokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
@@ -202,7 +202,7 @@ def get_strava_workout_list(user,limit_n=0):
if limit_n==0:
params = {}
else:
else: # pragma: no cover
params = {'per_page':limit_n}
s = requests.get(url,headers=headers,params=params)
@@ -212,7 +212,7 @@ def get_strava_workout_list(user,limit_n=0):
# gets all new Strava workouts for a rower
def get_strava_workouts(rower):
def get_strava_workouts(rower): # pragma: no cover
try:
thetoken = strava_open(rower.user)
except NoTokenError:
@@ -279,13 +279,13 @@ def create_async_workout(alldata,user,stravaid,debug=False):
stravaid = data['id']
try:
workouttype = mytypes.stravamappinginv[data['type']]
except:
except: # pragma: no cover
workouttype = 'other'
if workouttype not in [x[0] for x in Workout.workouttypes]:
if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover
workouttype = 'other'
if workouttype.lower() == 'rowing':
if workouttype.lower() == 'rowing': # pragma: no cover
workouttype = 'rower'
if 'summary_polyline' in data['map']:
workouttype = 'water'
@@ -305,18 +305,18 @@ def create_async_workout(alldata,user,stravaid,debug=False):
rowdatetime = iso8601.parse_date(data['date_utc'])
except KeyError:
rowdatetime = iso8601.parse_date(data['start_date'])
except ParseError:
except ParseError: # pragma: no cover
rowdatetime = iso8601.parse_date(data['date'])
try:
c2intervaltype = data['workout_type']
except KeyError:
except KeyError: # pragma: no cover
c2intervaltype = ''
try:
title = data['name']
except KeyError:
except KeyError: # pragma: no cover
title = ""
try:
t = data['comments'].split('\n', 1)[0]
@@ -367,7 +367,7 @@ from rowers.utils import get_strava_stream
def async_get_workout(user,stravaid):
try:
token = strava_open(user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return 0
csvfilename = 'media/{code}_{stravaid}.csv'.format(code=uuid4().hex[:16],stravaid=stravaid)
@@ -385,15 +385,15 @@ def async_get_workout(user,stravaid):
def get_workout(user,stravaid,do_async=False):
try:
thetoken = strava_open(user)
except NoTokenError:
except NoTokenError: # pragma: no cover
s = "Token error"
return custom_exception_handler(401,s)
r = Rower.objects.get(user=user)
if (r.stravatoken == '') or (r.stravatoken is None):
if (r.stravatoken == '') or (r.stravatoken is None): # pragma: no cover
s = "Token doesn't exist. Need to authorize"
return custom_exception_handler(401,s)
elif (r.stravatokenexpirydate is not None and timezone.now()>r.stravatokenexpirydate):
elif (r.stravatokenexpirydate is not None and timezone.now()>r.stravatokenexpirydate): # pragma: no cover
s = "Token expired. Needs to refresh."
return custom_exception_handler(401,s)
else:
@@ -411,7 +411,7 @@ def get_workout(user,stravaid,do_async=False):
workoutsummary['timezone'] = "Etc/UTC"
try:
startdatetime = workoutsummary['start_date']
except KeyError:
except KeyError: # pragma: no cover
startdatetime = timezone.now()
spm = get_strava_stream(r,'cadence',stravaid)
@@ -424,29 +424,29 @@ def get_workout(user,stravaid,do_async=False):
if t is not None:
nr_rows = len(t)
else:
else: # pragma: no cover
duration = int(workoutsummary['elapsed_time'])
t = pd.Series(range(duration+1))
nr_rows = len(t)
if nr_rows == 0:
if nr_rows == 0: # pragma: no cover
return (0,"Error: Time data had zero length")
if d is None:
if d is None: # pragma: no cover
d = 0*t
if spm is None:
if spm is None: # pragma: no cover
spm = np.zeros(nr_rows)
if power is None:
if power is None: # pragma: no cover
power = np.zeros(nr_rows)
if hr is None:
if hr is None: # pragma: no cover
hr = np.zeros(nr_rows)
if velo is None:
if velo is None: # pragma: no cover
velo = np.zeros(nr_rows)
dt = np.diff(t).mean()
@@ -458,10 +458,10 @@ def get_workout(user,stravaid,do_async=False):
try:
lat = coords[:,0]
lon = coords[:,1]
except IndexError:
except IndexError: # pragma: no cover
lat = np.zeros(len(t))
lon = np.zeros(len(t))
else:
else: # pragma: no cover
lat = np.zeros(len(t))
lon = np.zeros(len(t))
@@ -497,7 +497,7 @@ def createstravaworkoutdata(w,dozip=True):
filename = w.csvfilename
try:
row = rowingdata(csvfile=filename)
except IOError:
except IOError: # pragma: no cover
data = dataprep.read_df_sql(w.id)
try:
datalength = len(data)
@@ -532,12 +532,12 @@ def createstravaworkoutdata(w,dozip=True):
try:
os.remove(tcxfilename)
except WindowError:
except WindowError: # pragma: no cover
pass
return gzfilename,""
else:
else: # pragma: no cover
return tcxfilename,""
@@ -551,13 +551,13 @@ def handle_stravaexport(f2,workoutname,stravatoken,description='',
act = client.upload_activity(f2,'tcx.gz',name=workoutname)
try:
if quick:
if quick: # pragma: no cover
res = act.wait(poll_interval=1.0, timeout=10)
message = 'Workout successfully synchronized to Strava'
else:
res = act.wait(poll_interval=5.0,timeout=30)
message = 'Workout successfully synchronized to Strava'
except:
except: # pragma: no cover
res = 0
message = 'Strava upload timed out'
@@ -566,9 +566,9 @@ def handle_stravaexport(f2,workoutname,stravatoken,description='',
if res:
try:
act = client.update_activity(res.id,activity_type=activity_type,description=description,device_name='Rowsandall.com')
except TypeError:
except TypeError: # pragma: no cover
act = client.update_activity(res.id,activity_type=activity_type,description=description)
else:
else: # pragma: no cover
message = 'Strava activity update timed out.'
return (0,message)
@@ -581,16 +581,16 @@ def add_workout_from_data(user,importid,data,strokedata,
workoutsource='strava'):
try:
workouttype = mytypes.stravamappinginv[data['type']]
except KeyError:
except KeyError: # pragma: no cover
workouttype = 'other'
if workouttype.lower() == 'rowing':
if workouttype.lower() == 'rowing': # pragma: no cover
workouttype = 'rower'
if 'summary_polyline' in data['map'] and workouttype=='rower':
if 'summary_polyline' in data['map'] and workouttype=='rower': # pragma: no cover
workouttype = 'water'
if workouttype not in [x[0] for x in Workout.workouttypes]:
if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover
workouttype = 'other'
try:
comments = data['comments']
@@ -607,7 +607,7 @@ def add_workout_from_data(user,importid,data,strokedata,
rowdatetime = iso8601.parse_date(data['date_utc'])
except KeyError:
rowdatetime = iso8601.parse_date(data['start_date'])
except ParseError:
except ParseError: # pragma: no cover
rowdatetime = iso8601.parse_date(data['date'])
@@ -619,7 +619,7 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
title = data['name']
except KeyError:
except KeyError: # pragma: no cover
title = ""
try:
t = data['comments'].split('\n', 1)[0]
@@ -641,9 +641,9 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon']
if latcoord.std() == 0 and loncoord.std() == 0 and workouttype == 'water':
if latcoord.std() == 0 and loncoord.std() == 0 and workouttype == 'water': # pragma: no cover
workouttype = 'rower'
except:
except: # pragma: no cover
latcoord = np.zeros(nr_rows)
loncoord = np.zeros(nr_rows)
if workouttype == 'water':
@@ -653,19 +653,19 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
strokelength = strokedata.loc[:,'strokelength']
except:
except: # pragma: no cover
strokelength = np.zeros(nr_rows)
dist2 = 0.1*strokedata.loc[:,'d']
try:
spm = strokedata.loc[:,'spm']
except KeyError:
except KeyError: # pragma: no cover
spm = 0*dist2
try:
hr = strokedata.loc[:,'hr']
except KeyError:
except KeyError: # pragma: no cover
hr = 0*spm
pace = strokedata.loc[:,'p']/10.
pace = np.clip(pace,0,1e4)
@@ -675,7 +675,7 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
power = strokedata.loc[:,'power']
except KeyError:
except KeyError: # pragma: no cover
power = 2.8*velo**3
#if power.std() == 0 and power.mean() == 0:
@@ -734,27 +734,27 @@ def add_workout_from_data(user,importid,data,strokedata,
def workout_strava_upload(user,w, quick=False,asynchron=True):
try:
thetoken = strava_open(user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return "Please connect to Strava first",0
message = "Uploading to Strava"
stravaid=-1
r = Rower.objects.get(user=user)
res = -1
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"
raise NoTokenError("Your hovercraft is full of eels")
if (is_workout_user(user,w)):
if asynchron:
tcxfile, tcxmesg = createstravaworkoutdata(w)
if not tcxfile:
if not tcxfile: # pragma: no cover
return "Failed to create workout data",0
activity_type = r.stravaexportas
if r.stravaexportas == 'match':
try:
activity_type = mytypes.stravamapping[w.workouttype]
except KeyError:
except KeyError: # pragma: no cover
activity_type = 'Rowing'
job = myqueue(queue,
handle_strava_sync,
@@ -771,16 +771,20 @@ def workout_strava_upload(user,w, quick=False,asynchron=True):
if r.stravaexportas == 'match':
try:
activity_type = mytypes.stravamapping[w.workouttype]
except KeyError:
except KeyError: # pragma: no cover
activity_type = 'Rowing'
with open(tcxfile,'rb') as f:
try:
description = w.notes+'\n from '+w.workoutsource+' via rowsandall.com'
except TypeError:
description = ' via rowsandall.com'
res,mes = handle_stravaexport(
f,w.name,
r.stravatoken,
description=w.notes+'\n from '+w.workoutsource+' via rowsandall.com',
description=description,
activity_type=activity_type,quick=quick,asynchron=asynchron)
if res==0:
if res==0: # pragma: no cover
message = mes
w.uploadedtostrava = -1
stravaid = -1
@@ -795,26 +799,26 @@ def workout_strava_upload(user,w, quick=False,asynchron=True):
w.save()
try:
os.remove(tcxfile)
except WindowsError:
except WindowsError: # pragma: no cover
pass
message = mes
stravaid = res
return message,stravaid
else:
else: # pragma: no cover
message = "Strava TCX data error "+tcxmesg
w.uploadedtostrava = -1
stravaid = -1
w.save()
return message, stravaid
except ActivityUploadFailed as e:
except ActivityUploadFailed as e: # pragma: no cover
message = "Strava Upload error: %s" % e
w.uploadedtostrava = -1
stravaid = -1
w.save()
os.remove(tcxfile)
return message,stravaid
return message,stravaid
return message,stravaid # pragma: no cover
@@ -849,75 +853,75 @@ def handle_strava_import_stroke_data(title,
try:
hr = get_strava_stream(r,'heartrate',stravaid)
except JSONDecodeError:
except JSONDecodeError: # pragma: no cover
hr = 0*spm
try:
velo = get_strava_stream(r,'velocity_smooth',stravaid)
except JSONDecodeError:
except JSONDecodeError: # pragma: no cover
velo = 0*t
try:
d = get_strava_stream(r,'distance',stravaid)
except JSONDecodeError:
except JSONDecodeError: # pragma: no cover
d = 0*t
try:
coords = get_strava_stream(r,'latlng',stravaid)
except JSONDecodeError:
except JSONDecodeError: # pragma: no cover
coords = 0*t
try:
power = get_strava_stream(r,'watts',stravaid)
except JSONDecodeError:
except JSONDecodeError: # pragma: no cover
power = 0*t
if t is not None:
nr_rows = len(t)
else:
else: # pragma: no cover
return 0
if nr_rows == 0:
if nr_rows == 0: # pragma: no cover
return 0
if d is None:
if d is None: # pragma: no cover
d = 0*t
if spm is None:
if spm is None: # pragma: no cover
spm = np.zeros(nr_rows)
if power is None:
if power is None: # pragma: no cover
power = np.zeros(nr_rows)
if hr is None:
if hr is None: # pragma: no cover
hr = np.zeros(nr_rows)
if velo is None:
if velo is None: # pragma: no cover
velo = np.zeros(nr_rows)
f = np.diff(t).mean()
if f != 0:
windowsize = 2*(int(10./(f)))+1
else:
else: # pragma: no cover
windowsize = 1
if windowsize > 3 and windowsize < len(velo):
velo2 = savgol_filter(velo,windowsize,3)
else:
else: # pragma: no cover
velo2 = velo
if coords is not None:
try:
lat = coords[:,0]
lon = coords[:,1]
if lat.std() == 0 and lon.std() == 0 and workouttype == 'water':
if lat.std() == 0 and lon.std() == 0 and workouttype == 'water': # pragma: no cover
workouttype = 'rower'
except IndexError:
except IndexError: # pragma: no cover
lat = np.zeros(len(t))
lon = np.zeros(len(t))
if workouttype == 'water':
workouttype = 'rower'
else:
else: # pragma: no cover
lat = np.zeros(len(t))
lon = np.zeros(len(t))
if workouttype == 'water':
@@ -933,7 +937,7 @@ def handle_strava_import_stroke_data(title,
strokedistance = 60.*velo2/spm
if workouttype == 'rower' and pd.Series(power).mean() == 0:
if workouttype == 'rower' and pd.Series(power).mean() == 0: # pragma: no cover
power = 2.8*(velo2**3)
nr_strokes = len(t)
+58 -58
View File
@@ -79,11 +79,11 @@ def update_team(t,name,manager,private,notes,viewing):
def create_team(name,manager,private='open',notes='',viewing='allmembers'):
# needs some error testing
if user_is_basic(manager.rower.user):
if user_is_basic(manager.rower.user): # pragma: no cover
return (0,'You need to upgrade to a paid plan to establish a team')
if not is_coach(manager):
ts = Team.objects.filter(manager=manager)
if len(ts)>=1:
if len(ts)>=1: # pragma: no cover
return (0,'You need to upgrade to the Coach plan to have more than one team')
try:
@@ -102,13 +102,13 @@ def remove_team(id):
send_team_delete_mail(t,r)
return t.delete()
return (1,'Updated rower team expiry')
return (1,'Updated rower team expiry') # pragma: no cover
def add_coach(coach,rower):
# get coaching group
coachgroup = coach.mycoachgroup
if coachgroup is None:
if coachgroup is None: # pragma: no cover
coachgroup = CoachingGroup(name=coach.user.first_name)
coachgroup.save()
coach.mycoachgroup = coachgroup
@@ -118,14 +118,14 @@ def add_coach(coach,rower):
rower.coachinggroups.add(coach.mycoachgroup)
return (1,"Added Coach")
else:
else: # pragma: no cover
return (0,"Maximum number of athletes reached")
def add_member(id,rower):
t= Team.objects.get(id=id)
try:
rower.team.add(t)
except ValidationError as e:
except ValidationError as e: # pragma: no cover
return(0,"Couldn't add member: "+str(e.message))
# code to add all workouts
@@ -135,12 +135,12 @@ def add_member(id,rower):
# code to add plannedsessions
plannedsessions = PlannedSession.objects.filter(team=t,enddate__gte=timezone.now().date())
for ps in plannedsessions:
for ps in plannedsessions: # pragma: no cover
res = ps.rower.add(rower)
# set_teamplanexpires(rower)
# code for Stuck At Home Team (temporary)
if id == 52 and rower.rowerplan == 'basic':
if id == 52 and rower.rowerplan == 'basic': # pragma: no cover
rower.protrialexpires = ddate(2020,9,1)
rower.save()
@@ -157,10 +157,10 @@ def remove_member(id,rower):
# set_teamplanexpires(rower)
return (id,'Member removed')
def remove_coach(coach,rower):
def remove_coach(coach,rower): # pragma: no cover
try:
coachgroup = coach.mycoachgroup
except CoachingGroup.DoesNotExist:
except CoachingGroup.DoesNotExist: # pragma: no cover
coachgroup = CoachingGroup()
coachgroup.save()
coach.mycoachgroup = coachgroup
@@ -195,7 +195,7 @@ def coach_getcoachees(coach):
def coach_remove_athlete(coach,rower):
try:
coachgroup = coach.mycoachgroup
except CoachingGroup.DoesNotExist:
except CoachingGroup.DoesNotExist: # pragma: no cover
coachgroup = CoachingGroup()
coachgroup.save()
coach.mycoachgroup = coachgroup
@@ -211,12 +211,12 @@ def mgr_remove_member(id,manager,rower):
remove_member(id,rower)
send_email_member_dropped(id,rower)
return (id,'Member removed')
else:
else: # pragma: no cover
return (0,'You are not the team manager')
return (0,'')
return (0,'') # pragma: no cover
def count_invites(manager):
def count_invites(manager): # pragma: no cover
ts = Team.objects.filter(manager=manager)
count = 0
for t in ts:
@@ -225,7 +225,7 @@ def count_invites(manager):
return count
def count_club_members(manager):
def count_club_members(manager): # pragma: no cover
ts = Team.objects.filter(manager=manager)
return Rower.objects.filter(team__in=ts).distinct().count()
@@ -233,13 +233,13 @@ def count_club_members(manager):
# Medium level functionality
# request by user to be coached by coach
def create_coaching_request(coach,user):
def create_coaching_request(coach,user): # pragma: no cover
if coach in rower_get_coaches(user.rower):
return (0,'Already coached by that coach')
codes = [i.code for i in CoachRequest.objects.all()]
code = uuid.uuid4().hex[:10].upper()
while code in codes:
while code in codes: # pragma: no cover
code = uuid.uuid4().hex[:10].upper()
if 'coach' in coach.rowerplan:
@@ -250,7 +250,7 @@ def create_coaching_request(coach,user):
return (rekwest.id,'The request was created')
else:
else: # pragma: no cover
return (0,'That person is not a coach')
def send_coachrequest_email(rekwest):
@@ -280,14 +280,14 @@ def send_coacheerequest_email(rekwest):
def create_request(team,user):
r2 = Rower.objects.get(user=user)
r = Rower.objects.get(user=team.manager)
if r2 in Rower.objects.filter(team=team):
if r2 in Rower.objects.filter(team=team): # pragma: no cover
return (0,'Already a member of that team')
# if count_club_members(team.manager)+count_invites(team.manager) <= r.clubsize:
codes = [i.code for i in TeamRequest.objects.all()]
code = uuid.uuid4().hex[:10].upper()
# prevent duplicates
while code in codes:
while code in codes: # pragma: no cover
code = uuid.uuid4().hex[:10].upper()
u = User.objects.get(id=user)
@@ -298,7 +298,7 @@ def create_request(team,user):
return (rekwest.id,'The request was created')
return (0,'Something went wrong in create_request')
return (0,'Something went wrong in create_request') # pragma: no cover
def get_coach_club_size(coach):
rs = Rower.objects.filter(coachinggroups__in=[coach.mycoachgroup])
@@ -313,12 +313,12 @@ def get_coach_club_size(coach):
def create_coaching_offer(coach,user):
r = user.rower
if coach in rower_get_coaches(user.rower):
if coach in rower_get_coaches(user.rower): # pragma: no cover
return (0,'You are already coaching this person.')
codes = [i.code for i in CoachOffer.objects.all()]
code = uuid.uuid4().hex[:10].upper()
while code in codes:
while code in codes: # pragma: no cover
code = uuid.uuid4().hex[:10].upper()
if 'coach' in coach.rowerplan and get_coach_club_size(coach)<coach.clubsize:
@@ -328,10 +328,10 @@ def create_coaching_offer(coach,user):
send_coacheerequest_email(rekwest)
return (rekwest.id,'The request was created')
elif get_coach_club_size(coach)>=coach.clubsize:
elif get_coach_club_size(coach)>=coach.clubsize: # pragma: no cover
return(0,'You have reached the maximum number of athletes')
else:
else: # pragma: no cover
return (0,'You are not a coach')
@@ -345,26 +345,26 @@ def create_invite(team,manager,user=None,email=''):
try:
r2 = Rower.objects.get(user=user)
email = r2.user.email
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
return (0,'Rower does not exist')
if r2 in Rower.objects.filter(team=team):
return (0,'Already member of that team')
elif email==None or email=='':
elif email==None or email=='': # pragma: no cover
return (0,'Invalid request - missing email or user')
else:
try:
r2 = Rower.objects.get(user__email=email)
user = User.objects.get(rower=r2)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
user=None
except Rower.MultipleObjectsReturned:
except Rower.MultipleObjectsReturned: # pragma: no cover
return (0,'There is more than one user with that email address')
# if count_club_members(team.manager)+count_invites(team.manager) <= r.clubsize:
codes = [i.code for i in TeamInvite.objects.all()]
code = uuid.uuid4().hex[:10].upper()
# prevent duplicates
while code in codes:
while code in codes: # pragma: no cover
code = uuid.uuid4().hex[:10].upper()
invite = TeamInvite(team=team,code=code,user=user,email=email)
@@ -372,12 +372,12 @@ def create_invite(team,manager,user=None,email=''):
return (invite.id,'Invitation created')
return (0,'Nothing done')
return (0,'Nothing done') # pragma: no cover
def revoke_request(user,id):
try:
rekwest = TeamRequest.objects.get(id=id)
except TeamRequest.DoesNotExist:
except TeamRequest.DoesNotExist: # pragma: no cover
return (0,'The request is invalid')
t = rekwest.team
@@ -385,13 +385,13 @@ def revoke_request(user,id):
if rekwest.user==user:
rekwest.delete()
return (1,'Request revoked')
else:
else: # pragma: no cover
return (0,'You are not the requestor')
def reject_revoke_coach_offer(user,id):
try:
rekwest = CoachOffer.objects.get(id=id)
except CoachOffer.DoesNotExist:
except CoachOffer.DoesNotExist: # pragma: no cover
return (0,'The request is invalid')
if rekwest.coach.user == user:
@@ -402,13 +402,13 @@ def reject_revoke_coach_offer(user,id):
send_coachoffer_rejected_email(rekwest)
rekwest.delete()
return (1,'Request removed')
else:
else: # pragma: no cover
return (0,'Not permitted')
def reject_revoke_coach_request(user,id):
try:
rekwest = CoachRequest.objects.get(id=id)
except CoachRequest.DoesNotExist:
except CoachRequest.DoesNotExist: # pragma: no cover
return (0,'The request is invalid')
if rekwest.coach.user == user:
@@ -418,59 +418,59 @@ def reject_revoke_coach_request(user,id):
elif rekwest.user == user:
rekwest.delete()
return (1,'Request rejected')
else:
else: # pragma: no cover
return (0,'Not permitted')
def revoke_invite(manager,id):
try:
invite = TeamInvite.objects.get(id=id)
except TeamInvite.DoesNotExist:
except TeamInvite.DoesNotExist: # pragma: no cover
return (0,'The invitation is invalid')
if is_team_manager(manager,invite.team):
invite.delete()
return (1,'Invitation revoked')
else:
else: # pragma: no cover
return (0,'You are not the team manager')
def reject_request(manager,id):
try:
rekwest = TeamRequest.objects.get(id=id)
except TeamRequest.DoesNotExist:
except TeamRequest.DoesNotExist: # pragma: no cover
return (0,'The request is invalid')
if is_team_manager(manager,rekwest.team):
send_request_reject_email(rekwest)
rekwest.delete()
return (1,'Request rejected')
else:
else: # pragma: no cover
return (0,'You are not the manager for this request')
def reject_invitation(user,id):
try:
invite = TeamInvite.objects.get(id=id)
except TeamInvite.DoesNotExist:
except TeamInvite.DoesNotExist: # pragma: no cover
return (0,'The invitation is invalid')
if invite.user==user:
send_invite_reject_email(invite)
invite.delete()
return (1,'Invitation rejected')
else:
else: # pragma: no cover
return (0,'This request was not for you')
def send_invite_email(id):
try:
invitation = TeamInvite.objects.get(id=id)
except TeamInvite.DoesNotExist:
except TeamInvite.DoesNotExist: # pragma: no cover
return (0,'Invitation doesn not exist')
if invitation.user:
email = invitation.user.email
name = invitation.user.first_name + " " + invitation.user.last_name
else:
else: # pragma: no cover
email = invitation.email
name = ''
@@ -510,7 +510,7 @@ def send_email_member_dropped(teamid,rower):
return (1,'Member dropped email sent')
def send_request_accept_email(rekwest):
def send_request_accept_email(rekwest): # pragma: no cover
id = rekwest.id
email = rekwest.user.email
teamname = rekwest.team.name
@@ -542,7 +542,7 @@ def send_invite_reject_email(invitation):
email = invitation.team.manager.email
if invitation.user:
name = invitation.user.first_name+' '+invitation.user.last_name
else:
else: # pragma: no cover
name = invitation.email
teamname = invitation.team.name
@@ -555,7 +555,7 @@ def send_invite_reject_email(invitation):
return (1,'Invitation email sent')
def send_invite_accept_email(invitation):
def send_invite_accept_email(invitation): # pragma: no cover
id = invitation.id
email = invitation.team.manager.email
if invitation.user:
@@ -572,7 +572,7 @@ def send_invite_accept_email(invitation):
return (1,'Invitation email sent')
def send_team_message(team,message):
def send_team_message(team,message): # pragma: no cover
rowers = team.rower.all()
managername = team.manager.first_name + " " + team.manager.last_name
@@ -598,7 +598,7 @@ def send_request_email(rekwest):
return (1,'Invitation email sent')
def process_request_code(manager,code):
def process_request_code(manager,code): # pragma: no cover
code = code.upper()
try:
@@ -623,7 +623,7 @@ def process_request_code(manager,code):
rekwest.delete()
return (result,'The member was added')
def process_invite_code(user,code):
def process_invite_code(user,code): # pragma: no cover
code = code.upper()
try:
invitation = TeamInvite.objects.get(code=code)
@@ -646,7 +646,7 @@ def process_invite_code(user,code):
invitation.delete()
return (result,'You were added to the team')
def remove_expired_invites():
def remove_expired_invites(): # pragma: no cover
issuedate = timezone.now()-timedelta(days=inviteduration)
issuedate = datetime.date(issuedate)
invitations = TeamInvite.objects.filter(issuedate__lt=issuedate)
@@ -660,14 +660,14 @@ def process_coachrequest_code(coach,code):
try:
rekwest = CoachRequest.objects.get(code=code)
except CoachRequest.DoesNotExist:
except CoachRequest.DoesNotExist: # pragma: no cover
return (0,'The request has been revoked or is invalid')
if rekwest.coach != coach:
if rekwest.coach != coach: # pragma: no cover
return (0,'The request is invalid')
result = add_coach(coach,rekwest.user.rower)
if not result:
if not result: # pragma: no cover
return result
else:
send_coachrequest_accepted_email(rekwest)
@@ -681,14 +681,14 @@ def process_coachoffer_code(user,code):
try:
rekwest = CoachOffer.objects.get(code=code)
except CoachOffer.DoesNotExist:
except CoachOffer.DoesNotExist: # pragma: no cover
return (0,'The request has been revoked or is invalid')
if rekwest.user != user:
if rekwest.user != user: # pragma: no cover
return (0,'The request is invalid')
result = add_coach(rekwest.coach,rekwest.user.rower)
if not result:
if not result: # pragma: no cover
return result
else:
send_coachoffer_accepted_email(rekwest)
+3 -3
View File
@@ -533,7 +533,7 @@
"time": [3200, 6700, 10099],
"spm": [16.4, 21.2, 19.8],
"pace": [155068, 144402, 138830],
"power": [84,6, 117.2, 141.3],
"power": [84.6, 117.2, 141.3],
"hr": [85, 91, 95]
}
</pre>
@@ -586,7 +586,7 @@
</td>
<td>GET, POST</td>
<td>
<pre>[
<pre>{
"data": [
{
"time": 3200.0000476837,
@@ -613,7 +613,7 @@
"spm": 19.8095238095
}
]
]
}
</pre>
You can only post stroke data to an existing workout with
workout number {id}. If the workout already has stroke data, you
+1 -1
View File
@@ -74,7 +74,7 @@
choice or to renew the authorization.</p>
<p><a href="/rowers/me/stravaauthorize/"><img src="/static/img/ConnectWithStrava.png" alt="connect with strava" width="120"></a></p>
<p><a href="/rowers/me/c2authorize/"><img src="/static/img/blueC2logo.png" alt="connect with Concept2" width="120"></a></p>
<p><a href="/rowers/me/nkauthorize/"><img src="/static/img/NKLiNK.jpg" alt="connect with NK Logbook" width="120"></a></p>
<p><a href="/rowers/me/nkauthorize/"><img src="/static/img/NKLiNKLogbook.png" alt="connect with NK Logbook" width="120"></a></p>
<p><a href="/rowers/me/sporttracksauthorize/"><img src="/static/img/sporttracks-button.png" alt="connect with SportTracks" width="120"></a></p>
<p><a href="/rowers/me/runkeeperauthorize/"><img src="/static/img/rk-logo.png" alt="connect with RunKeeper" width="120"></a></p>
<p><a href="/rowers/me/underarmourauthorize/"><img src="/static/img/UAbtn.png" alt="connect with Under Armour" width="120"></a></p>
+66 -66
View File
@@ -47,11 +47,11 @@ from six import string_types
@register.filter
def isfollower(user,id):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return True
try:
race = VirtualRace.objects.get(id=id)
except VirtualRace.DoesNotExist:
except VirtualRace.DoesNotExist: # pragma: no cover
return False
followers = VirtualRaceFollower.objects.filter(race=race,user=user)
@@ -83,18 +83,18 @@ def steptostring(steps):
def verbose(s):
try:
return favanalysisdict[s]
except KeyError:
except KeyError: # pragma: no cover
return ''
@register.filter
def icon(s):
try:
return favanalysisicons[s]
except KeyError:
except KeyError: # pragma: no cover
return 'fa-chart-line'
@register.filter
def datarows(data):
def datarows(data): # pragma: no cover
return range(len(data))
@register.filter
@@ -109,7 +109,7 @@ def adaptive(s):
return u
@register.filter
def nkviewerlink(workout):
def nkviewerlink(workout): # pragma: no cover
url = "{nkviewer}{nkid}".format(
nkid=workout.uploadedtonk,
nkviewer=NK_VIEWER_LOCATION)
@@ -168,23 +168,23 @@ def weight(s):
def sigdig(value, digits = 3):
try:
order = int(math.floor(math.log10(math.fabs(value))))
except (ValueError,TypeError):
except (ValueError,TypeError): # pragma: no cover
return value
# return integers as is
if value % 1 == 0:
return value
places = digits - order - 1
places = digits - order - 1 # pragma: no cover
if places > 0:
if places > 0: # pragma: no cover
fmtstr = "%%.%df" % (places)
else:
else: # pragma: no cover
fmtstr = "%.0f"
return fmtstr % (round(value, places))
return fmtstr % (round(value, places)) # pragma: no cover
@register.filter
def pickle(dc):
def pickle(dc): # pragma: no cover
s = dict()
for key, value in dc.items():
s[key] = value
@@ -223,25 +223,25 @@ def strfdelta(tdelta):
from rowers.teams import rower_get_managers
@register.filter
def alertstatspercentage(list,i):
def alertstatspercentage(list,i): # pragma: no cover
alertstats = list[i-1]
return alertstats["percentage"]
@register.filter
def alertstartdate(list,i):
def alertstartdate(list,i): # pragma: no cover
alertstats = list[i-1]
return alertstats["startdate"]
@register.filter
def alertnperiod(list,i):
def alertnperiod(list,i): # pragma: no cover
alertstats = list[i-1]
return alertstats["nperiod"]
@register.filter
def alertenddate(list,i):
def alertenddate(list,i): # pragma: no cover
alertstats = list[i-1]
return alertstats["enddate"]
@@ -255,27 +255,27 @@ def is_coach(rower,rowers):
return True
@register.filter
def waterpower(x,rower):
def waterpower(x,rower): # pragma: no cover
if rower is not None:
return int(x*(100-rower.otwslack)/100.)
return int(x)
@register.filter
def round20(x):
def round20(x): # pragma: no cover
try:
return int(20.*(1+int(int(x)/20)))
except ValueError:
return 20
@register.filter
def round100(x):
def round100(x): # pragma: no cover
try:
return int(100.*(1+int(int(x)/100)))
except ValueError:
return 100
@register.filter
def majorticks(maxval):
def majorticks(maxval): # pragma: no cover
ticks = range(1+int(maxval/100.))
newticks =[]
for t in ticks:
@@ -284,7 +284,7 @@ def majorticks(maxval):
return newticks
@register.filter
def hrmajorticks(maxval,minval):
def hrmajorticks(maxval,minval): # pragma: no cover
ticks = range(int((maxval-minval)/20.)-1)
newticks =[]
for t in ticks:
@@ -319,7 +319,7 @@ def secondstotimestring(tdelta):
@register.filter
def existing_customer(user):
if user.is_anonymous:
if user.is_anonymous: # pragma: no cover
return False
else:
return payments.is_existing_customer(user.rower)
@@ -328,7 +328,7 @@ def existing_customer(user):
def aantalcomments(workout):
try:
comments = WorkoutComment.objects.filter(workout=workout)
except:
except: # pragma: no cover
return 0
aantalcomments = len(comments)
@@ -347,7 +347,7 @@ def encode(id):
def water(workout):
try:
return workout.workouttype in otwtypes
except AttributeError:
except AttributeError: # pragma: no cover
return False
@register.filter
@@ -360,7 +360,7 @@ def spacetohtml(t):
@register.filter
def durationprint(d,dstring):
if (d == None):
if (d == None): # pragma: no cover
return d
else:
try:
@@ -421,13 +421,13 @@ def previousperiodstart(timeperiod):
@register.filter
def paceprint(d):
if (d == None):
if (d == None): # pragma: no cover
return d
else:
return strfdelta(d)
@register.filter
def deltatimeprint(d):
def deltatimeprint(d): # pragma: no cover
if (d == None):
return d
else:
@@ -437,7 +437,7 @@ def deltatimeprint(d):
def c2userid(user):
try:
thetoken = c2_open(user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return 0
c2userid = c2stuff.get_userid(thetoken)
@@ -448,7 +448,7 @@ def c2userid(user):
def currency(word):
try:
amount = float(word)
except ValueError:
except ValueError: # pragma: no cover
return word
return '{amount:.2f}'.format(amount=amount)
@@ -457,7 +457,7 @@ def currency(word):
def rkuserid(user):
try:
thetoken = runkeeper_open(user)
except NoTokenError:
except NoTokenError: # pragma: no cover
return 0
rkuserid = runkeeperstuff.get_userid(thetoken)
@@ -465,11 +465,11 @@ def rkuserid(user):
return rkuserid
@register.filter
def courselength(course):
def courselength(course): # pragma: no cover
return course_length(course)
@register.filter(is_safe=True)
def jsdict(dict,key):
def jsdict(dict,key): # pragma: no cover
s = dict.get(key)
return mark_safe(json.dumps(s))
@@ -479,7 +479,7 @@ def jsdict(dict,key):
def lookup(dict, key):
try:
s = dict.get(key)
except KeyError:
except KeyError: # pragma: no cover
return None
if isinstance(s,string_types) and len(s) > 22:
@@ -490,7 +490,7 @@ def lookup(dict, key):
def lookuplong(dict, key):
try:
s = dict.get(key)
except KeyError:
except KeyError: # pragma: no cover
return None
return s
@@ -516,7 +516,7 @@ from rowers.models import PlannedSession
def is_session_manager(id,user):
try:
ps = PlannedSession.objects.get(id=id)
except PlannedSession.DoesNotExist:
except PlannedSession.DoesNotExist: # pragma: no cover
return False
return ps.manager == user
@@ -537,7 +537,7 @@ def may_edit(workout,request):
@register.filter
def mayeditplan(obj,request):
if obj is None:
if obj is None: # pragma: no cover
return False
if hasattr(obj,'plan'):
@@ -547,15 +547,15 @@ def mayeditplan(obj,request):
if obj.manager is not None:
return request.user == obj.manager.user
rr = Rower.objects.get(user=request.user)
if is_coach_user(request.user,obj.rower) and rr.rowerplan not in ['basic','pro']:
rr = Rower.objects.get(user=request.user) # pragma: no cover
if is_coach_user(request.user,obj.rower) and rr.rowerplan not in ['basic','pro']: # pragma: no cover
mayedit = True
return mayedit
return mayedit # pragma: no cover
@register.filter
def iterrows(df):
def iterrows(df): # pragma: no cover
return df.iterrows()
@register.filter(name='times')
@@ -563,7 +563,7 @@ def times(number):
return range(number)
@register.simple_tag
def get_df_iloc(data,i,j):
def get_df_iloc(data,i,j): # pragma: no cover
return data.iloc(i,j)
@register.simple_tag
@@ -589,7 +589,7 @@ def is_planmember(user):
return isplanmember(user)
@register.filter
def get_age(r):
def get_age(r): # pragma: no cover
return calculate_age(r.birthdate)
@@ -612,7 +612,7 @@ def user_team1(user):
teams1 = therower.team.all()
teams2 = Team.objects.filter(manager=user)
teams = list(set(teams1).union(set(teams2)))
except TypeError:
except TypeError: # pragma: no cover
teams = []
return teams[0].id
@@ -628,7 +628,7 @@ def announcements(request):
return announcements[0:4]
@register.filter
def has_teams(user):
def has_teams(user): # pragma: no cover
try:
therower = Rower.objects.get(user=user)
teams1 = therower.team.all()
@@ -644,7 +644,7 @@ def has_teams(user):
def team_members(user):
try:
therower = Rower.objects.get(user=user)
if therower.rowerplan == 'basic':
if therower.rowerplan == 'basic': # pragma: no cover
return []
teams = Team.objects.filter(manager=user)
members = Rower.objects.filter(
@@ -653,10 +653,10 @@ def team_members(user):
"user__last_name","user__first_name"
).exclude(rowerplan='freecoach')
return [rower.user for rower in members]
except TypeError:
except TypeError: # pragma: no cover
return []
return []
return [] # pragma: no cover
@register.filter
def openactions(user):
@@ -675,7 +675,7 @@ def openactions(user):
@register.filter
def team_rowers(user):
def team_rowers(user): # pragma: no cover
try:
therower = Rower.objects.get(user=user)
if therower.rowerplan == 'basic':
@@ -696,13 +696,13 @@ from rowers.teams import coach_getcoachees
def coach_rowers(user):
if user.rower.rowerplan != 'freecoach':
thelist = [user.rower]+[c for c in coach_getcoachees(user.rower)]
else:
else: # pragma: no cover
thelist = [c for c in coach_getcoachees(user.rower)]
return thelist
@register.filter
def verbosetimeperiod(timeperiod):
def verbosetimeperiod(timeperiod): # pragma: no cover
table = {
'today':'Today',
'thisweek': 'This Week',
@@ -723,7 +723,7 @@ def verbosetimeperiod(timeperiod):
from datetime import date
@ register.filter
def future_date_only(the_date):
def future_date_only(the_date): # pragma: no cover
if the_date > date.today():
return the_date
else:
@@ -747,7 +747,7 @@ def date_dif(the_date):
return 1
if the_date:
return the_date - date.today()
else:
else: # pragma: no cover
return 1
@@ -756,38 +756,38 @@ def can_register(race,r):
return race_can_register(r,race)
@register.filter
def can_submit(race,r):
def can_submit(race,r): # pragma: no cover
return race_can_submit(r,race)
@register.filter
def race_complete(race,r):
def race_complete(race,r): # pragma: no cover
is_complete,has_registered = race_rower_status(r,race)
return is_complete
@register.filter
def past_not_registered(race,r):
def past_not_registered(race,r): # pragma: no cover
is_complete,has_registered = race_rower_status(r,race)
return not has_registered
@register.filter
def future_registered(race,r):
def future_registered(race,r): # pragma: no cover
is_complete, has_registered = race_rower_status(r,race)
is_open = race.evaluation_closure > timezone.now()
return has_registered and not is_complete and is_open
@property
def is_past_due(self):
def is_past_due(self): # pragma: no cover
return datetime.date.today() > self.date
@property
def is_not_past_due(self):
def is_not_past_due(self): # pragma: no cover
return datetime.date.today() <= self.date
@register.filter
def is_closed(race):
def is_closed(race): # pragma: no cover
return race.evaluation_closure < timezone.now()
@register.filter
def is_final(race):
def is_final(race): # pragma: no cover
return race.evaluation_closure < timezone.now()-datetime.timedelta(hours=1)
@register.filter
@@ -827,7 +827,7 @@ def teamurl(path,team):
return replaced
@register.filter
def timeurl(path,timestring):
def timeurl(path,timestring): # pragma: no cover
pattern = re.compile('\?when=w.*')
timeurl = '?when=%s' % timestring
replaced = ''
@@ -852,7 +852,7 @@ def trainingplans(rower):
return plans
@register.filter
def mesomacroid(id):
def mesomacroid(id): # pragma: no cover
try:
thismeso = TrainingMesoCycle.objects.get(id=id)
except TrainingMesoCycle.DoesNotExist:
@@ -863,7 +863,7 @@ def mesomacroid(id):
return str(theid)
@register.filter
def micromesoid(id):
def micromesoid(id): # pragma: no cover
try:
thismicro = TrainingMicroCycle.objects.get(id=id)
except TrainingMicroCycle.DoesNotExist:
@@ -875,7 +875,7 @@ def micromesoid(id):
@register.filter
def micromacroid(id):
def micromacroid(id): # pragma: no cover
try:
thismicro = TrainingMicroCycle.objects.get(id=id)
except TrainingMicroCycle.DoesNotExist:
@@ -905,7 +905,7 @@ def nextworkout(workout,user):
).order_by(
"startdatetime"
).exclude(id=workout.id)
except ValueError:
except ValueError: # pragma: no cover
return 0
if ws:
@@ -935,7 +935,7 @@ def previousworkout(workout,user):
).order_by(
"-startdatetime"
).exclude(id=workout.id)
except ValueError:
except ValueError: # pragma: no cover
return 0
+88 -5
View File
@@ -512,7 +512,7 @@ class gatewayresult():
self.transaction = vtransaction()
self.payment_method = vpayment_method()
self.subscription = vsubscription()
self.customer = customer()
self.customer = kwargs.pop('customer',customer())
def __unicode__():
return "mockedgatewayresult"
@@ -526,12 +526,18 @@ class paypal_account():
def __init__(self, *args, **kwargs):
self.subscriptions = [vsubscription(),vsubscription()]
class customercreateresult:
def __init__(self, *args, **kwargs):
self.customer = kwargs.pop('customer',customer())
self.is_success = kwargs.pop('is_success',True)
self.customer_id = 1
class customer():
def find(*arg, **kwargs):
return self
def create(*args, **kwargs):
return gatewayresult(is_success=True)
return customercreateresult(is_success=True)
def __init__(self, *args, **kwargs):
self.credit_cards = [credit_card(),credit_card()]
@@ -627,6 +633,16 @@ class payment_method():
def __init__(self, *args, **kwargs):
self.token = 'liesjeleerdelotje'
class notification():
def __init__(self, *args, **kwargs):
print('notifucation')
self.kind = 'subscription_canceled'
class webhook_notification():
def parse(*args, **kwargs):
print(args,kwargs,'parse')
return notification()
# mock braintree gateway
class MockBraintreeGateway:
def __init__(self,*args, **kwargs):
@@ -636,10 +652,10 @@ class MockBraintreeGateway:
self.transaction = transaction()
self.subscription = subscription()
self.payment_method = payment_method()
self.webhook_notification = webhook_notification()
def mocked_gateway(*args, **kwargs):
return MockBraintreeGateway()
@@ -817,7 +833,7 @@ def mocked_requests(*args, **kwargs):
self.status_code = status_code
self.ok = True
class MockOAuth1Session():
class MockOAuth1Session:
def __init__(self,*args, **kwargs):
pass
@@ -851,18 +867,46 @@ def mocked_requests(*args, **kwargs):
return MockResponse(json_data,200)
if 'garmin' in args:
return MockOAuth1Session()
if 'url' in kwargs:
if 'rp3' in kwargs['url']:
args = [kwargs['url']]
if "tofit" in kwargs['url']:
args = [kwargs['url']]
if not args:
return MockSession()
if "tofit" in args[0]:
jsonresponse = {
'name': '',
'sport': 'rowing',
'filename': '/home/sander/python/rowsandall/media/630a9e78-6d34-4eb3-8d53-4c02b2e95fff.fit',
'steps': [
{
'wkt_step_name': '0',
'stepId': 0,
'durationType': 'Distance',
'durationValue': 100000,
'intensity': 'Active'
},
{
'wkt_step_name': '1',
'stepId': 1,
'durationType': 'RepeatUntilStepsCmplt',
'targetValue': 4,
'durationValue': 0
}
]
}
return MockResponse(jsonresponse,200)
polartester = re.compile('.*?polaraccesslink\.com')
c2tester = re.compile('.*?log\.concept2\.com')
stravatester = re.compile('.*?strava\.com')
@@ -873,6 +917,7 @@ def mocked_requests(*args, **kwargs):
nktester = re.compile('.*?nkrowlink\.com')
rp3tester = re.compile('.*?rp3rowing-app\.com')
garmintester = re.compile('.*?garmin\.com')
fakturoidtester = re.compile('.*?fakturoid\.cz')
c2importregex = '.*?concept2.com\/api\/users\/me\/results\/\d+'
c2importtester = re.compile(c2importregex)
@@ -1163,6 +1208,22 @@ def mocked_requests(*args, **kwargs):
else:
return MockResponse(c2workoutdata,200)
if fakturoidtester.match(args[0]):
if 'invoices' in args[0]:
response = {
'url':'aap',
'id':1,
}
return MockResponse(response,200)
response = [
{
'id':1,
'url':'aap',
}
]
return MockResponse(response,200)
return MockResponse(None,404)
class MockEmailMessage:
@@ -1171,3 +1232,25 @@ class MockEmailMessage:
def send(self):
return 1
class MockResponse:
def __init__(self, json_data, status_code):
self.json_data = json_data
self.status_code = status_code
self.ok = True
def json(self):
return self.json_data
class MockOAuth1Session:
def __init__(self,*args, **kwargs):
pass
def get(*args,**kwargs):
return MockStreamResponse('rowers/tests/testdata/3x250m.fit',200)
def post(*args, **kwargs):
return MockResponse({},200)
def mocked_invoiceid(*args,**kwargs):
return 1
+5 -1
View File
@@ -15,8 +15,12 @@ except NameError:
import pytest
from pandas.core.common import SettingWithCopyWarning
import warnings
#warnings.filterwarnings("error",category=UserWarning)
warnings.filterwarnings("error",
category=RuntimeWarning
)
pytestmark = pytest.mark.django_db
+1 -1
View File
@@ -176,7 +176,7 @@ class PlannedSessionTests(TestCase):
d1 = startdate.strftime("%Y%m%d"),
d2 = enddate.strftime("%Y%m%d"),
)
self.assertEquals(
self.assertEqual(
response.get('Content-Disposition'),
'attachment; filename="{name}"'.format(name=filename)
)
+185
View File
@@ -0,0 +1,185 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.db import transaction
#from __future__ import print_function
from .statements import *
nu = datetime.datetime.now()
import rowers
from rowers import dataprep
from rowers import tasks
from rowers import c2stuff
from rowers import stravastuff
import urllib
import json
import pandas as pd
from rowers.opaque import encoder
from rest_framework.test import APIRequestFactory, force_authenticate
import json
from rowers.ownapistuff import *
from rowers.views.apiviews import *
class OwnApi(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',subscription_id=1)
workoutsbox = Mailbox.objects.create(name='workouts')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
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.factory = APIRequestFactory()
def test_strokedataform(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
w = self.user_workouts[0]
url = reverse('strokedataform',kwargs={'id':encoder.encode_hex(w.id)})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
url = reverse('strokedatajson',kwargs={'id':w.id})
request = self.factory.get(url)
request.user = self.u
force_authenticate(request, user=self.u)
response = strokedatajson(request,id=w.id)
self.assertEqual(response.status_code,200)
# response must be json
strokedata = json.loads(response.content)
df = pd.DataFrame(strokedata)
self.assertFalse(df.empty)
form_data = {
"distance": [23, 46, 48],
"time": [3200, 6700, 10099],
"spm": [16.4, 21.2, 19.8],
"pace": [155068, 144402, 138830],
"power": [84.6, 117.2, 141.3],
"hr": [85, 91, 95]
}
result = get_random_file(filename='rowers/tests/testdata/thyro.csv')
w2 = Workout.objects.create(
user=self.r,
csvfilename=result['filename'],
duration=result['duration'],
startdatetime=result['startdatetime'],
workouttype='water',
starttime=result['starttime'],
)
url = reverse('strokedatajson',kwargs={'id':w2.id})
request = self.factory.post(url,{'strokedata':form_data},format='json')
request.user = self.u
request.data = json.dumps({'strokedata':form_data})
strokedata = json.loads(request.data)['strokedata']
force_authenticate(request, user=self.u)
with patch('rowers.dataprep.getrowdata_db') as mock_getrowdata:
mock_getrowdata.return_value = (pd.DataFrame(),None)
response = strokedatajson(request,id=w.id)
self.assertEqual(response.status_code,201)
def test_strokedataform_v2(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
w = self.user_workouts[1]
url = reverse('strokedataform_v2',kwargs={'id':encoder.encode_hex(w.id)})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
url = reverse('strokedatajson_v2',kwargs={'id':w.id})
request = self.factory.get(url)
request.user = self.u
force_authenticate(request, user=self.u)
response = strokedatajson_v2(request,id=w.id)
self.assertEqual(response.status_code,200)
# response must be json
strokedata = json.loads(response.content)
df = pd.DataFrame(strokedata)
self.assertFalse(df.empty)
form_data = {
"data": [
{
"time": 3200.0000476837,
"pace": 155068.4885951763,
"hr": 85.7857142857,
"power": 84.6531131591,
"distance": 23,
"spm": 16.380952381
},
{
"time": 6700.0000476837,
"pace" : 144402.6407586741,
"hr": 91.2142857143,
"power": 117.458827834,
"distance": 36,
"spm": 21.1666666667
},
{
"time": 10099.9999046326,
"pace": 138830.8712654931,
"hr": 95.7142857143,
"power": 141.31057207,
"distance": 48,
"spm": 19.8095238095
}
]
}
result = get_random_file(filename='rowers/tests/testdata/thyro.csv')
w2 = Workout.objects.create(
user=self.r,
csvfilename=result['filename'],
duration=result['duration'],
startdatetime=result['startdatetime'],
workouttype='water',
starttime=result['starttime'],
)
url = reverse('strokedatajson_v2',kwargs={'id':w2.id})
request = self.factory.post(url,form_data,format='json')
request.user = self.u
request.data = json.dumps(form_data)
force_authenticate(request, user=self.u)
with patch('rowers.dataprep.getrowdata_db') as mock_getrowdata:
mock_getrowdata.return_value = (pd.DataFrame(),None)
response = strokedatajson_v2(request,id=w.id)
self.assertEqual(response.status_code,200)
+130
View File
@@ -0,0 +1,130 @@
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from django.db import transaction
#from __future__ import print_function
from .statements import *
nu = datetime.datetime.now()
import rowers
from rowers import dataprep
from rowers import tasks
from rowers import c2stuff
from rowers import stravastuff
import urllib
import json
from rowers.braintreestuff import *
class transaction:
def __init__(self,*args, **kwargs):
self.amount = kwargs.get('amount',25)
class subscription:
def __init__(self,*args, **kwargs):
self.id = kwargs.get('id',1)
self.transactions = [transaction(amount=25)]
self.billing_period_end_date = datetime.datetime.now()+datetime.timedelta(days=365)
class notification:
def __init__(self,*args, **kwargs):
self.kind = kwargs.get('kind','subscription_charged_successfully')
self.subscription = subscription(id=1)
class mycustomer:
def __init__(self, *args, **kwargs):
self.id = kwargs.get('id',1)
class mycreatecustomer:
def __init__(self, *args, **kwargs):
self.customer = mycustomer(id=1)
self.is_success = True
self.customer_id = 1
class myupgraderesult:
def __init__(self, *args, **kwargs):
self.subscription = subscription()
self.is_success = True
class paymentmethod:
def __init__(self, *args, **kwargs):
self.token = 'aa'
class mypaymentmethod:
def __init__(self, *args, **kwargs):
self.is_success = True
self.payment_method = paymentmethod()
class BraintreeUnits(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',subscription_id=1)
workoutsbox = Mailbox.objects.create(name='workouts')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
self.pp = PaidPlan.objects.create(price=0,paymentprocessor='braintree')
self.p2 = PaidPlan.objects.create(price=25,paymentprocessor='braintree')
@patch('rowers.fakturoid.requests.get',side_effect=mocked_requests)
@patch('rowers.fakturoid.requests.post',side_effect=mocked_requests)
@patch('rowers.braintreestuff.gateway', side_effect=MockBraintreeGateway)
@patch('rowers.braintreestuff.myqueue')
def test_process_webhook(self,mock_get,mockpost,mocked_gateway,mocked_myqueue):
n = notification()
res = process_webhook(n)
self.assertEqual(res,1)
n = notification(kind='subscription_canceled')
res = process_webhook(n)
self.assertEqual(res,1)
def test_create_customer(self):
with patch('rowers.braintreestuff.gateway') as mocked_gateway:
mocked_gateway.customer.create.return_value = mycreatecustomer()
self.r.customer_id = 0
self.r.save()
res = create_customer(self.r)
self.assertEqual(res,1)
@patch('rowers.braintreestuff.myqueue')
def test_update_subscription(self, mocked_myqueue):
data = {
'plan':self.pp.id,
'payment_method_nonce':'aap',
'amount':24,
}
with patch('rowers.braintreestuff.gateway') as mocked_gateway:
mocked_gateway.subscription.update.return_value = myupgraderesult()
success,amount = update_subscription(self.r,data)
self.assertTrue(success)
self.assertEqual(amount,25)
@patch('rowers.braintreestuff.myqueue')
def test_create_subscription(self, mocked_myqueue):
data = {
'plan':self.p2.id,
'payment_method_nonce':'aap',
'amount':24,
}
with patch('rowers.braintreestuff.gateway') as mocked_gateway:
mocked_gateway.subscription.create.return_value = myupgraderesult()
mocked_gateway.payment_method.create.return_value = mypaymentmethod()
success,amount = create_subscription(self.r,data)
self.assertTrue(success)
self.assertEqual(amount,25)
+129 -12
View File
@@ -4,6 +4,123 @@ from __future__ import print_function
from __future__ import unicode_literals
from .statements import *
import rowers.courses as courses
import rowers.dataprep as dataprep
from rowers.courseutils import *
from rowingdata import rowingdata as rdata
from rowers.models import polygon_to_path
class CourseUnitTest(TestCase):
def setUp(self):
self.c = Client()
self.u = User.objects.create_user('john',
'sander@ds.ds',
'koeinsloot')
self.r = Rower.objects.create(user=self.u,gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',
)
self.nu = datetime.datetime.now()
with open('rowers/tests/testdata/thyro.kml') as f:
cs = courses.kmltocourse(f)
course = cs[0]
cname = course['name']
cnotes = course['description']
self.polygons = course['polygons']
pstart = self.polygons[0]
self.ThyroBaantje = courses.createcourse(self.r,cname,self.polygons,notes=cnotes)
self.start = GeoPolygon.objects.filter(course=self.ThyroBaantje,order_in_course=0)[0]
self.ThyroBaantje.save()
result = get_random_file(filename='rowers/tests/testdata/thyro.csv')
self.wthyro = WorkoutFactory(user=self.r,
csvfilename=result['filename'],
starttime=result['starttime'],
startdatetime=result['startdatetime'],
duration=result['duration'],
distance=result['totaldist'],
workouttype = 'water',
)
self.wthyro.startdatetime = arrow.get(self.nu).datetime
self.wthyro.date = self.nu.date()
self.wthyro.save()
def test_time_in_path(self):
row = rdata(csvfile='rowers/tests/testdata/thyro.csv')
time = row.df['TimeStamp (sec)']
lat = row.df[' latitude']
lon = row.df[' longitude']
cum_dist = row.df['cum_dist']
data = pd.DataFrame(
{
'time':time,
'latitude':lat,
'longitude':lon,
'cum_dist':cum_dist,
}
)
startpath = polygon_to_path(self.start)
mintime,mindist = time_in_path(data,startpath)
self.assertEqual(mintime,78)
self.assertEqual(mindist,207.1)
def test_coursetime_first(self):
row = rdata(csvfile='rowers/tests/testdata/thyro.csv')
time = row.df['TimeStamp (sec)']
lat = row.df[' latitude']
lon = row.df[' longitude']
cum_dist = row.df['cum_dist']
data = pd.DataFrame(
{
'time':time,
'latitude':lat,
'longitude':lon,
'cum_dist':cum_dist,
}
)
paths = []
polygons = GeoPolygon.objects.filter(course=self.ThyroBaantje).order_by("order_in_course")
for p in polygons:
paths.append(polygon_to_path(p))
entrytime,entrydistance,coursecompleted = coursetime_first(data,paths)
self.assertEqual(entrytime,78)
self.assertEqual(entrydistance,207.1)
self.assertTrue(coursecompleted)
def test_coursetime_paths(self):
row = rdata(csvfile='rowers/tests/testdata/thyro.csv')
time = row.df['TimeStamp (sec)']
lat = row.df[' latitude']
lon = row.df[' longitude']
cum_dist = row.df['cum_dist']
data = pd.DataFrame(
{
'time':time,
'latitude':lat,
'longitude':lon,
'cum_dist':cum_dist,
}
)
paths = []
polygons = GeoPolygon.objects.filter(course=self.ThyroBaantje).order_by("order_in_course")
for p in polygons:
paths.append(polygon_to_path(p))
entrytime,entrydistance,coursecompleted = coursetime_paths(data,paths)
self.assertEqual(entrytime,435)
self.assertEqual(entrydistance,1348.8)
self.assertTrue(coursecompleted)
class CoursesTest(TestCase):
def setUp(self):
@@ -23,23 +140,23 @@ class CoursesTest(TestCase):
self.assertTrue(login)
filename = 'rowers/tests/testdata/Courses.kml'
f = open(filename,'rb')
file_data = {'file': f}
form_data = {
'name': 'test courses',
'notes': 'aap nn',
'file':f,
with open(filename,'rb') as f:
file_data = {'file': f}
form_data = {
'name': 'test courses',
'notes': 'aap nn',
'file':f,
}
courseform = CourseForm(form_data)
self.assertTrue(courseform.is_valid())
courseform = CourseForm(form_data)
self.assertTrue(courseform.is_valid())
response = self.c.get('/rowers/courses/upload/')
self.assertTrue(response.status_code,200)
response = self.c.get('/rowers/courses/upload/')
self.assertTrue(response.status_code,200)
response = self.c.post('/rowers/courses/upload/', form_data, follow=True)
response = self.c.post('/rowers/courses/upload/', form_data, follow=True)
f.close()
self.assertRedirects(response, expected_url='/rowers/list-courses/',
status_code=302,target_status_code=200)
+11 -1
View File
@@ -450,7 +450,8 @@ class NKObjects(DjangoTestCase):
self.assertEqual(response.status_code,200)
@patch('rowers.tasks.requests.get', side_effect=mocked_requests)
def test_handle_nk_get_workouts(self, mock_get):
@patch('rowers.tasks.requests.post', side_effect=mocked_requests)
def test_handle_nk_get_workouts(self, mock_get,mockpost):
with open('rowers/tests/testdata/nk_list.json','r') as f:
data = json.load(f)
@@ -739,7 +740,16 @@ class StravaObjects(DjangoTestCase):
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_workout_strava_upload(self, mock_get, mock_post,MockStravalibClient):
w = Workout.objects.get(id=1)
res = stravastuff.workout_strava_upload(self.r.user,w,asynchron=True)
self.assertEqual(res[1],-1)
res = stravastuff.workout_strava_upload(self.r.user,w,asynchron=False)
self.assertEqual(len(res[0]),43)
@patch('rowers.stravastuff.requests.post', side_effect=mocked_requests)
@patch('rowers.stravastuff.requests.get', side_effect=mocked_requests)
+25 -1
View File
@@ -13,11 +13,35 @@ from rowers.models import update_records
class MiscTests(TestCase):
def setUp(self):
pass
self.u = UserFactory(is_staff=True)
self.r = Rower.objects.create(user=self.u,
birthdate=faker.profile()['birthdate'],
gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='coach',subscription_id=1)
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()
def test_c2records(self):
update_records(verbose=False)
def test_failed_que(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
url = reverse('failed_queue_view')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
url2 = reverse('failed_queue_empty')
response = self.c.get(url2,follow=True)
self.assertRedirects(response,expected_url=url,status_code=302,target_status_code=200)
#@pytest.mark.django_db
class WorkoutTests(TestCase):
def setUp(self):
+235 -12
View File
@@ -11,6 +11,8 @@ from django_countries import countries
from rowers.braintreestuff import mocktest
import urllib
class PaymentTest(TestCase):
def setUp(self):
@@ -55,12 +57,127 @@ class PaymentTest(TestCase):
self.c = Client()
self.password = faker.word()
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):
# settings.DEBUG = False
@patch('rowers.braintreestuff.gateway',side_effect=MockBraintreeGateway)
@patch('rowers.braintreestuff.myqueue')
def test_braintree_webhook(self,mocked_gateway,mocked_myqueue):
url = reverse('braintree_webhook_view')
response = self.c.get(url)
self.assertEqual(response.status_code,200)
form_data = {
'bt_signature':'aap',
'bt_payload':'noot,'
}
response = self.c.post(url,form_data)
self.assertEqual(response.status_code,200)
@patch('rowers.views.braintreestuff.create_customer',side_effect=mock_create_customer)
@patch('rowers.views.braintreestuff.gateway',side_effect=MockBraintreeGateway)
def test_billing_view(self,mocked_create_customer,mocked_gateway):
@patch('rowers.braintreestuff.myqueue')
def test_billing_view(self,mocked_create_customer,mocked_gateway,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -118,7 +235,8 @@ class PaymentTest(TestCase):
status_code=302,target_status_code=200)
@patch('rowers.views.braintreestuff.gateway',side_effect=MockBraintreeGateway)
def test_upgrade_view(self,mocked_gateway):
@patch('rowers.braintreestuff.myqueue')
def test_upgrade_view(self,mocked_gateway,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -181,7 +299,8 @@ class PaymentTest(TestCase):
status_code=302,target_status_code=200)
@patch('rowers.views.braintreestuff.gateway',side_effect=MockBraintreeGateway)
def test_down_view(self,mocked_gateway):
@patch('rowers.braintreestuff.myqueue')
def test_down_view(self,mocked_gateway,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -247,7 +366,8 @@ class PaymentTest(TestCase):
status_code=302,target_status_code=200)
@patch('rowers.views.braintreestuff.gateway',side_effect=MockBraintreeGateway)
def test_planstop_view(self,mocked_gateway):
@patch('rowers.braintreestuff.myqueue')
def test_planstop_view(self,mocked_gateway,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -284,8 +404,104 @@ class PaymentTest(TestCase):
self.assertEqual(response.status_code,200)
@patch('rowers.views.braintreestuff.gateway', side_effect=MockBraintreeGateway)
@patch('rowers.fakturoid.create_invoice',side_effect=mocked_invoiceid)
@patch('rowers.braintreestuff.myqueue')
def test_purchase_trainingplan_view(self, mocked_gateway,mocked_invoiceid,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
gdproptin=True,surveydone=True,
gdproptindate=timezone.now(),
rowerplan='plan',
paymentprocessor='braintree',
street_address = faker.street_address(),
city = faker.city(),
postal_code = faker.postalcode(),
country = faker.country(),
)
r.save()
r.country = 'NL'
r.customer_id = 34
r.subscription_id = 34
r.save()
u.set_password(self.password)
u.save()
login = self.c.login(username=u.username, password=self.password)
self.assertTrue(login)
url = reverse('buy_trainingplan_view',kwargs={'id':self.instantplan.id})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
enddate = datetime.datetime.now()+datetime.timedelta(days=30)
startdate = datetime.datetime.now()
form_data = {
'enddate':enddate.strftime('%Y-%m-%d'),
'startdate':startdate.strftime('%Y-%m-%d'),
'notes':'no notes',
'datechoice':'enddate',
'name':'no name',
}
response = self.c.post(url,form_data)
pars = {
'name':'no name',
'enddate':enddate.strftime('%Y-%m-%d'),
'notes':'no notes',
'status':True,
'rower':r.id,
}
params = urllib.parse.urlencode(pars)
expected_url = reverse('confirm_trainingplan_purchase_view',kwargs={'id':self.instantplan.id})
expected_url = expected_url + "?%s" % params
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
url = expected_url
response = self.c.get(url)
self.assertEqual(response.status_code,200)
url = reverse('purchase_checkouts_view')
form_data = {
'amount':'25.00',
'plan': self.instantplan.id,
'payment_method_nonce': 'aap',
'tac':'tac',
'paymenttype': 'CreditCard',
'notes':'no notes',
'enddate':enddate.strftime('%Y-%m-%d'),
'status':True,
}
form = TrainingPlanBillingForm(form_data)
if not form.is_valid():
print(form.errors)
self.assertTrue(form.is_valid())
response = self.c.post(url,form_data,follow=True)
self.assertEqual(response.status_code,200)
expected_url = reverse('plannedsessions_view')
startdate = enddate-datetime.timedelta(days=self.instantplan.duration)
timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
expected_url = expected_url+'?when='+timeperiod
self.assertRedirects(response,
expected_url = expected_url,
status_code=302,target_status_code=200)
@patch('rowers.views.braintreestuff.gateway',side_effect=MockBraintreeGateway)
def test_planstobasic_view(self,mocked_gateway):
@patch('rowers.braintreestuff.myqueue')
def test_planstobasic_view(self,mocked_gateway,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -325,7 +541,8 @@ class PaymentTest(TestCase):
status_code=302,target_status_code=200)
@patch('rowers.tests.test_payments.mocktest', side_effect=mock_mocktest)
def test_patch(self, mock_mocktest):
@patch('rowers.braintreestuff.myqueue')
def test_patch(self, mock_mocktest,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -346,7 +563,8 @@ class PaymentTest(TestCase):
self.assertEqual(result,'121')
@patch('rowers.views.braintreestuff.create_subscription', side_effect=mock_create_subscription)
def test_checkouts_view(self,mock_subscription):
@patch('rowers.braintreestuff.myqueue')
def test_checkouts_view(self,mock_subscription,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -392,7 +610,8 @@ class PaymentTest(TestCase):
@patch('rowers.views.braintreestuff.update_subscription', side_effect=mock_update_subscription)
def test_upgrade_checkouts_view(self,mock_subscription):
@patch('rowers.braintreestuff.myqueue')
def test_upgrade_checkouts_view(self,mock_subscription,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -437,7 +656,8 @@ class PaymentTest(TestCase):
status_code=302,target_status_code=200)
@patch('rowers.views.braintreestuff.update_subscription', side_effect=mock_update_subscription)
def test_downgrade_checkouts_view(self,mock_subscription):
@patch('rowers.braintreestuff.myqueue')
def test_downgrade_checkouts_view(self,mock_subscription,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -482,7 +702,8 @@ class PaymentTest(TestCase):
status_code=302,target_status_code=200)
@patch('rowers.views.braintreestuff.create_subscription', side_effect=mock_create_subscription)
def test_checkouts_view(self,mock_subscription):
@patch('rowers.braintreestuff.myqueue')
def test_checkouts_view(self,mock_subscription,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -532,7 +753,8 @@ class PaymentTest(TestCase):
@patch('rowers.views.braintreestuff.update_subscription', side_effect=mock_update_subscription)
def test_upgrade_checkouts_view(self,mock_subscription):
@patch('rowers.braintreestuff.myqueue')
def test_upgrade_checkouts_view(self,mock_subscription,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
@@ -577,7 +799,8 @@ class PaymentTest(TestCase):
status_code=302,target_status_code=200)
@patch('rowers.views.braintreestuff.update_subscription', side_effect=mock_update_subscription)
def test_downgrade_checkouts_view(self,mock_subscription):
@patch('rowers.braintreestuff.myqueue')
def test_downgrade_checkouts_view(self,mock_subscription,mocked_myqueue):
u = UserFactory()
r = Rower.objects.create(user=u,
birthdate=faker.profile()['birthdate'],
+63 -2
View File
@@ -8,12 +8,17 @@ from .statements import *
nu = datetime.datetime.now()
from rowers.utils import allmonths,allsundays
from rowers import garmin_stuff
import rowers.plannedsessions as plannedsessions
from django.db import transaction
from rowers.views.workoutviews import plannedsession_compare_view
from rowers.views.otherviews import download_fit
from rowers.opaque import encoder
from django.utils.crypto import get_random_string
from django.http.response import Http404
@override_settings(TESTING=True)
class TrainingPlanTest(TestCase):
@@ -93,7 +98,7 @@ class TrainingPlanTest(TestCase):
for url in urls:
if 'macrocycle' in url and 'delete' not in url:
macrourl = url
print(macrourl)
response = self.c.get(macrourl)
self.assertEqual(response.status_code,200)
@@ -121,7 +126,7 @@ class TrainingPlanTest(TestCase):
for url in urls:
if 'planbymonths' in url:
print(url)
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
@@ -1852,6 +1857,62 @@ description: ""
response = self.c.get(url)
self.assertEqual(response.status_code,200)
url = reverse('plannedsessions_print_view',kwargs={
'userid':self.r.user.id,
'startdatestring':self.ps_trimp.startdate.strftime("%Y-%m-%d"),
'enddatestring':self.ps_trimp.enddate.strftime("%Y-%m-%d"),
})
response = self.c.get(url)
self.assertEqual(response.status_code,200)
# create shareable link
form_data = {
'url': url,
'ndays': '7'
}
urlshare = '/rowers/access/share/'
response = self.c.post(urlshare,form_data)
self.assertEqual(response.status_code,200)
key = ShareKey.objects.create(pk=get_random_string(40),
expiration_seconds=60,
location=url
)
key.save()
url = '/rowers/access/'+key.token
response = self.c.get(url,follow=True)
self.assertEqual(response.status_code,200)
@patch('rowers.garmin_stuff.requests.post', side_effect=mocked_requests)
@patch('rowers.utils.requests.post', side_effect=mocked_requests)
@patch('rowers.garmin_stuff.OAuth1Session', side_effect=MockOAuth1Session)
def test_plannedsession_steps(self,mockpost,mock_post,MockOAuth1Session):
self.ps_trimp.interval_string = '4x1000m'
self.ps_trimp.save()
stepsdict = self.ps_trimp.steps['steps']
self.assertEqual(len(stepsdict),2)
response = garmin_stuff.ps_to_garmin(self.ps_trimp,self.r)
self.assertEqual(response.status_code,200)
url = '0'
request = self.factory.get(url)
request.user = self.u
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
with self.assertRaises(Http404) as context:
response = download_fit(request,filename=self.ps_trimp.fitfile)
self.assertTrue('File not found' in context.exception)
def test_plannedsessions_dateform_view(self):
login = self.c.login(username=self.u.username, password=self.password)
self.assertTrue(login)
+36
View File
@@ -49,6 +49,12 @@ class DataTest(TestCase):
'tr':167,
'an':180,
'weightcategory':'lwt',
'hrrestname':'rest',
'hrut2name':'ut2',
'hrut1name':'ut1',
'hrtrname':'tr',
'hranname':'an',
'hrmaxname':'max',
}
form = RowerForm(data=form_data)
self.assertTrue(form.is_valid())
@@ -64,6 +70,12 @@ class DataTest(TestCase):
'an':180,
'tr':167,
'weightcategory':'lwt',
'hrrestname':'rest',
'hrut2name':'ut2',
'hrut1name':'ut1',
'hrtrname':'tr',
'hranname':'an',
'hrmaxname':'max',
}
form = RowerForm(data=form_data)
self.assertFalse(form.is_valid())
@@ -78,6 +90,12 @@ class DataTest(TestCase):
'an':180,
'tr':167,
'weightcategory':'lwt',
'hrrestname':'rest',
'hrut2name':'ut2',
'hrut1name':'ut1',
'hrtrname':'tr',
'hranname':'an',
'hrmaxname':'max',
}
form = RowerForm(data=form_data)
self.assertFalse(form.is_valid())
@@ -92,6 +110,12 @@ class DataTest(TestCase):
'an':180,
'tr':167,
'weightcategory':'lwt',
'hrrestname':'rest',
'hrut2name':'ut2',
'hrut1name':'ut1',
'hrtrname':'tr',
'hranname':'an',
'hrmaxname':'max',
}
form = RowerForm(data=form_data)
self.assertFalse(form.is_valid())
@@ -106,6 +130,12 @@ class DataTest(TestCase):
'an':180,
'tr':167,
'weightcategory':'lwt',
'hrrestname':'rest',
'hrut2name':'ut2',
'hrut1name':'ut1',
'hrtrname':'tr',
'hranname':'an',
'hrmaxname':'max',
}
form = RowerForm(data=form_data)
self.assertFalse(form.is_valid())
@@ -120,6 +150,12 @@ class DataTest(TestCase):
'an':180,
'tr':167,
'weightcategory':'lwt',
'hrrestname':'rest',
'hrut2name':'ut2',
'hrut1name':'ut1',
'hrtrname':'tr',
'hranname':'an',
'hrmaxname':'max',
}
form = RowerForm(data=form_data)
self.assertFalse(form.is_valid())
+19
View File
@@ -114,6 +114,25 @@ class TeamTest(TestCase):
except (IOError, FileNotFoundError,OSError):
pass
def test_team_leave_view(self):
res = add_member(self.t.id,self.users[1].rower)
login = self.c.login(username=self.u.username, password = self.password)
self.assertTrue(login)
url = reverse('team_leave_view',kwargs={'id':self.t.id})
response = self.c.get(url,follow=True)
expected_url = reverse('rower_teams_view')
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
def test_team_delete_view(self):
login = self.c.login(username=self.u.username, password = self.password)
self.assertTrue(login)
url = reverse('team_delete_view',kwargs={'team_id':self.t.id})
response = self.c.get(url,follow=True)
expected_url = reverse('rower_teams_view')
self.assertRedirects(response,expected_url=expected_url,status_code=302,target_status_code=200)
def test_manager_drop_member(self):
res = add_member(self.t.id,self.users[1].rower)
login = self.c.login(username=self.u.username, password = self.password)
+53 -5
View File
@@ -15,12 +15,54 @@ nu = datetime.datetime.now()
# interactive plots
from rowers import interactiveplots
from rowers import dataprep
from rowers import plannedsessions
from rowers.views.workoutviews import get_video_id
from rowers import stravastuff
class OtherUnitTests(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')
workoutsbox = Mailbox.objects.create(name='workouts')
workoutsbox.save()
failbox = Mailbox.objects.create(name='Failed')
failbox.save()
@patch('rowers.tasks.requests.get',side_effect=mocked_requests)
def test_strava_asyncworkout(self,mock_get):
with open('rowers/tests/testdata/stravaworkoutlist.txt','r') as f:
s = f.read()
jsondata = json.loads(s)
alldata = {}
for item in jsondata:
alldata[item['id']] = item
theid = jsondata[0]['id']
workoutid = stravastuff.create_async_workout(alldata,self.r.user,theid)
self.assertEqual(workoutid,1)
def test_summaryfromsplitdata(self):
with open('rowers/tests/testdata/c2splits.json','r') as f:
s = f.read()
data = json.loads(s)
splitdata = data['workout']['intervals']
summary = c2stuff.summaryfromsplitdata(splitdata,data,'aap.txt')
self.assertEqual(len(summary),3)
sums = summary[0]
self.assertEqual(len(sums),631)
def test_get_video_id(self):
url1 = 'http://youtu.be/_lOT2p_FCvA'
url2 = 'www.youtube.com/watch?v=_lOT2p_FCvA&feature=feedu'
@@ -351,20 +393,26 @@ class DataPrepTests(TestCase):
for obj in data:
m = obj['fields']
record = CalcAgePerformance(**m)
#print(record.sex,record.age,record.weightcategory,record.duration,record.power)
record.save()
def tearDown(self):
pass
def test_goldmedalstandard(self):
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_uh)
def test_goldmedalstandard(self,mocked_getsmallrowdata_uh):
maxvalue, delta = dataprep.calculate_goldmedalstandard(self.r,self.wuh_otw)
records = CalcAgePerformance.objects.filter(
age=dataprep.calculate_age(self.r.birthdate),
weightcategory=self.r.weightcategory,
sex=self.r.sex)
self.assertEqual(int(maxvalue),9)
self.assertEqual(delta,6)
self.assertTrue(maxvalue > 0)
self.assertTrue(delta > 0)
def test_getagegrouprecord(self):
records = C2WorldClassAgePerformance.objects.filter(distance=2000,sex=self.r.sex,weightcategory=self.r.weightcategory)
result = c2stuff.getagegrouprecord(25)
self.assertEqual(int(result),590)
@patch('rowers.dataprep.getsmallrowdata_db',side_effect=mocked_getsmallrowdata_uh)
def test_get_videodata(self,mocked_getsmallrowdata_uh):
+11 -1
View File
@@ -204,12 +204,22 @@ class UserPreferencesTest(TestCase):
'tr':170,
'at':160,
'an':175,
'rest':50
'rest':50,
'hrrestname':'rest',
'hrut2name':'ut2',
'hrut1name':'ut1',
'hratname':'at',
'hrtrname':'tr',
'hranname':'an',
'hrmaxname':'max',
}
form = RowerForm(form_data)
self.assertTrue(form.is_valid())
form = RowerHRZonesForm(form_data)
self.assertTrue(form.is_valid())
url = '/rowers/me/preferences/'
response = self.c.get(url)
+1081
View File
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -78,7 +78,7 @@ def get_token(code):
thetoken = token_json['access_token']
expires_in = token_json['expires_in']
refresh_token = token_json['refresh_token']
except KeyError:
except KeyError: # pragma: no cover
thetoken = 0
expires_in = 0
refresh_token = 0
@@ -86,11 +86,11 @@ def get_token(code):
return thetoken,expires_in,refresh_token
# Make authorization URL including random string
def make_authorization_url(request):
def make_authorization_url(request): # pragma: no cover
return imports_make_authorization_url(oauth_data)
def getidfromresponse(response):
def getidfromresponse(response): # pragma: no cover
t = json.loads(response.text)
links = t["_links"]
@@ -113,7 +113,7 @@ def createtpworkoutdata(w):
return tcxfilename
def tp_check(access_token):
def tp_check(access_token): # pragma: no cover
headers = {
"Content-Type": "application/json",
'Accept': 'application/json',
@@ -157,15 +157,15 @@ def uploadactivity(access_token,filename,description='',
data = json.dumps(data),
headers=headers,verify=False)
if resp.status_code != 200:
if resp.status_code != 200: # pragma: no cover
return 0,resp.reason,resp.status_code,headers
else:
return resp.json()[0]["Id"],"ok",200,""
return 0,0,0,0
return 0,0,0,0 # pragma: no cover
def workout_tp_upload(user,w):
def workout_tp_upload(user,w): # pragma: no cover
message = "Uploading to TrainingPeaks"
tpid = 0
r = w.user
+19 -19
View File
@@ -47,7 +47,7 @@ def get_token(code):
# Make authorization URL including random string
def make_authorization_url(request):
return imports_make_authorization_url(oauth_data)
return imports_make_authorization_url(oauth_data) # pragma: no cover
# Get list of workouts available on Underarmour
def get_underarmour_workout_list(user):
@@ -72,7 +72,7 @@ def get_underarmour_workout_list(user):
# Get workout summary data by Underarmour ID
def get_workout(user,underarmourid,do_async=False):
r = Rower.objects.get(user=user)
if (r.underarmourtoken == '') or (r.underarmourtoken is None):
if (r.underarmourtoken == '') or (r.underarmourtoken is None): # pragma: no cover
return custom_exception_handler(401,s)
s = "Token doesn't exist. Need to authorize"
else:
@@ -99,7 +99,7 @@ def createunderarmourworkoutdata(w):
filename = w.csvfilename
try:
row = rowingdata(csvfile=filename)
except:
except: # pragma: no cover
return 0
st = w.startdatetime.astimezone(pytz.timezone(w.timezone))
@@ -151,7 +151,7 @@ def createunderarmourworkoutdata(w):
haslatlon=1
try:
try: # pragma: no cover
lat = row.df[' latitude']
lon = row.df[' longitude']
if not lat.std() and not lon.std():
@@ -161,7 +161,7 @@ def createunderarmourworkoutdata(w):
# path data
if haslatlon:
if haslatlon: # pragma: no cover
locdata = []
for e in zip(t,lat.values,lon.values):
point = {
@@ -214,7 +214,7 @@ def createunderarmourworkoutdata(w):
}
if haslatlon:
if haslatlon: # pragma: no cover
timeseries["position"] = locdata
data = {
@@ -248,7 +248,7 @@ def getidfromresponse(response):
return int(id)
def refresh_ua_actlist(user):
def refresh_ua_actlist(user): # pragma: no cover
r = Rower.objects.get(user=user)
authorizationstring = str('Bearer ' + r.underarmourtoken)
headers = {'Authorization': authorizationstring,
@@ -268,7 +268,7 @@ def refresh_ua_actlist(user):
try:
activities = pd.read_csv('static/rigging/ua2.csv',index_col='id')
actdict = activities.to_dict()['Name']
except:
except: # pragma: no cover
actdict = {}
@@ -276,7 +276,7 @@ def get_typefromid(typeid,user):
r = Rower.objects.get(user=user)
try:
res = actdict[int(typeid)]
except KeyError:
except KeyError: # pragma: no cover
authorizationstring = str('Bearer ' + r.underarmourtoken)
headers = {'Authorization': authorizationstring,
'Api-Key': UNDERARMOUR_CLIENT_KEY,
@@ -312,17 +312,17 @@ def get_userid(access_token):
try:
res = me_json['id']
except KeyError:
except KeyError: # pragma: no cover
res = 0
return res
def default(o):
def default(o): # pragma: no cover
if isinstance(o, numpy.int64): return int(o)
raise TypeError
def workout_ua_upload(user,w):
def workout_ua_upload(user,w): # pragma: no cover
message = "Uploading to MapMyFitness"
uaid = 0
@@ -383,7 +383,7 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
comments = data['notes']
except:
except: # pragma: no cover
comments = ''
try:
@@ -394,7 +394,7 @@ def add_workout_from_data(user,importid,data,strokedata,
r = Rower.objects.get(user=user)
try:
rowdatetime = iso8601.parse_date(data['start_datetime'])
except iso8601.ParseError:
except iso8601.ParseError: # pragma: no cover
try:
rowdatetime = datetime.strptime(data['start_datetime'],"%Y-%m-%d %H:%M:%S")
rowdatetime = thetimezone.localize(rowdatetime).astimezone(utc)
@@ -410,7 +410,7 @@ def add_workout_from_data(user,importid,data,strokedata,
try:
title = data['name']
except:
except: # pragma: no cover
title = "Imported data"
timeseries = data['time_series']
@@ -421,7 +421,7 @@ def add_workout_from_data(user,importid,data,strokedata,
res = splituadata(timeseries['distance'])
distance = res[1]
times_distance = res[0]
except KeyError:
except KeyError: # pragma: no cover
message = "Error. No distance data"
return (0,message)
@@ -440,7 +440,7 @@ def add_workout_from_data(user,importid,data,strokedata,
lon = coord['lng']
latcoord.append(lat)
loncoord.append(lon)
except:
except: # pragma: no cover
times_location = times_distance
latcoord = np.zeros(len(times_distance))
loncoord = np.zeros(len(times_distance))
@@ -451,7 +451,7 @@ def add_workout_from_data(user,importid,data,strokedata,
res = splituadata(timeseries['cadence'])
times_spm = res[0]
spm = res[1]
except KeyError:
except KeyError: # pragma: no cover
times_spm = times_distance
spm = 0*times_distance
@@ -459,7 +459,7 @@ def add_workout_from_data(user,importid,data,strokedata,
res = splituadata(timeseries['heartrate'])
hr = res[1]
times_hr = res[0]
except KeyError:
except KeyError: # pragma: no cover
times_hr = times_distance
hr = 0*times_distance
+43 -43
View File
@@ -50,7 +50,7 @@ from rowers.utils import (
def cleanbody(body):
try:
body = body.decode('utf-8')
except AttributeError:
except AttributeError: # pragma: no cover
pass
regex = r".*---\n([\s\S]*?)\.\.\..*"
@@ -72,7 +72,7 @@ def matchsource(line):
testert = '^source.*(%s)' % s
tester = re.compile(testert)
if tester.match(line.lower()):
if tester.match(line.lower()): # pragma: no cover
return tester.match(line.lower()).group(1)
# currently only matches one chart
@@ -88,7 +88,7 @@ def matchchart(line):
tester3 = re.compile(tester3t)
tester4 = re.compile(tester4t)
if tester.match(line.lower()):
if tester.match(line.lower()): # pragma: no cover
if tester2.match(line.lower()):
return 'distanceplot'
if tester3.match(line.lower()):
@@ -112,7 +112,7 @@ def matchrace(line):
words = line.split()
try:
return int(words[1])
except:
except: # pragma: no cover
return None
return None
@@ -129,7 +129,7 @@ def matchsync(line):
tester = re.compile(tester)
if tester.match(line.lower()):
if tester.match(line.lower()): # pragma: no cover
testers = [
('upload_to_C2',re.compile(tester2)),
('upload_totp',re.compile(tester3)),
@@ -148,7 +148,7 @@ def getstravaid(uploadoptions,body):
stravaid = 0
tester = re.compile('^(stravaid)(.*?)(\d+)')
for line in body.splitlines():
if tester.match(line.lower()):
if tester.match(line.lower()): # pragma: no cover
stravaid = tester.match(line.lower()).group(3)
uploadoptions['stravaid'] = int(stravaid)
@@ -183,7 +183,7 @@ def gettypeoptions_body2(uploadoptions,body):
def getprivateoptions_body2(uploadoptions,body):
tester = re.compile('^(priva)')
for line in body.splitlines():
if tester.match(line.lower()):
if tester.match(line.lower()): # pragma: no cover
v = True
negs = ['false','False','None','no']
for neg in negs:
@@ -199,7 +199,7 @@ def getprivateoptions_body2(uploadoptions,body):
def getworkoutsources(uploadoptions,body):
for line in body.splitlines():
workoutsource = matchsource(line)
if workoutsource:
if workoutsource: # pragma: no cover
uploadoptions['workoutsource'] = workoutsource
return uploadoptions
@@ -207,7 +207,7 @@ def getworkoutsources(uploadoptions,body):
def getplotoptions_body2(uploadoptions,body):
for line in body.splitlines():
chart = matchchart(line)
if chart:
if chart: # pragma: no cover
uploadoptions['make_plot'] = True
uploadoptions['plottype'] = chart
@@ -236,12 +236,12 @@ def getsyncoptions_body2(uploadoptions,body):
result = list(set(result))
for r in result:
for r in result: # pragma: no cover
uploadoptions[r] = True
return uploadoptions
def getsyncoptions(uploadoptions,values):
def getsyncoptions(uploadoptions,values): # pragma: no cover
try:
value = values.lower()
values = [values]
@@ -269,7 +269,7 @@ def getsyncoptions(uploadoptions,values):
return uploadoptions
def getplotoptions(uploadoptions,value):
def getplotoptions(uploadoptions,value): # pragma: no cover
try:
v = value.lower()
if v in ['pieplot','timeplot','distanceplot']:
@@ -290,7 +290,7 @@ def getplotoptions(uploadoptions,value):
return uploadoptions
def gettype(uploadoptions,value,key):
def gettype(uploadoptions,value,key): # pragma: no cover
workouttype = 'rower'
for typ,verb in workouttypes_ordered.items():
if value == typ:
@@ -304,7 +304,7 @@ def gettype(uploadoptions,value,key):
return uploadoptions
def getboattype(uploadoptions,value,key):
def getboattype(uploadoptions,value,key): # pragma: no cover
boattype = '1x'
for type,verb in boattypes:
if value == type:
@@ -316,12 +316,12 @@ def getboattype(uploadoptions,value,key):
return uploadoptions
def getuser(uploadoptions,value,key):
def getuser(uploadoptions,value,key): # pragma: no cover
uploadoptions['username'] = value
return uploadoptions
def getrace(uploadoptions,value,key):
def getrace(uploadoptions,value,key): # pragma: no cover
try:
raceid = int(value)
uploadoptions['raceid'] = raceid
@@ -330,7 +330,7 @@ def getrace(uploadoptions,value,key):
return uploadoptions
def getsource(uploadoptions,value,key):
def getsource(uploadoptions,value,key): # pragma: no cover
workoutsource = 'unknown'
for type,verb in workoutsources:
if value == type:
@@ -342,7 +342,7 @@ def getsource(uploadoptions,value,key):
return uploadoptions
def getboolean(uploadoptions,value,key):
def getboolean(uploadoptions,value,key): # pragma: no cover
b = True
if not value:
b = False
@@ -361,10 +361,10 @@ def upload_options(body):
body = cleanbody(body)
try:
yml = (yaml.safe_load(body))
if yml and 'fromuploadform' in yml:
if yml and 'fromuploadform' in yml: # pragma: no cover
return yml
try:
for key, value in yml.iteritems():
for key, value in yml.iteritems(): # pragma: no cover
lowkey = key.lower()
if lowkey == 'sync' or lowkey == 'synchronization' or lowkey == 'export':
uploadoptions = getsyncoptions(uploadoptions,value)
@@ -395,7 +395,7 @@ def upload_options(body):
uploadoptions = getworkoutsources(uploadoptions,body)
uploadoptions = getuseroptions_body2(uploadoptions,body)
uploadoptions = getraceoptions_body2(uploadoptions,body)
except IOError:
except IOError: # pragma: no cover
pm = exc.problem_mark
strpm = str(pm)
pbm = "Your email has an issue on line {} at position {}. The error is: ".format(
@@ -404,7 +404,7 @@ def upload_options(body):
)+strpm
return {'error':pbm}
if uploadoptions == {}:
if uploadoptions == {}: # pragma: no cover
uploadoptions['message'] = 'No parsing issue. No valid commands detected'
return uploadoptions
@@ -445,7 +445,7 @@ def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0):
}
axis = r.staticgrids
if axis == None:
if axis == None: # pragma: no cover
gridtrue = False
axis = 'both'
else:
@@ -482,7 +482,7 @@ def make_plot(r,w,f1,f2,plottype,title,imagename='',plotnr=0):
width=width,height=height)
i.save()
else:
else: # pragma: no cover
return 0,'You have reached the maximum number of static images for this workout. Delete an image first'
return i.id,job.id
@@ -500,24 +500,24 @@ def set_workouttype(w,options):
try:
w.workouttype = options['workouttype']
w.save()
except KeyError:
except KeyError: # pragma: no cover
pass
try:
w.boattype = options['boattype']
w.save()
except KeyError:
except KeyError: # pragma: no cover
pass
return 1
def set_workoutsource(w,options):
def set_workoutsource(w,options): # pragma: no cover
try:
w.workoutsource = options['workoutsource']
w.save()
except KeyError:
except KeyError: # pragma: no cover
pass
def make_private(w,options):
def make_private(w,options): # pragma: no cover
if 'makeprivate' in options and options['makeprivate']:
w.privacy = 'hidden'
w.save()
@@ -533,7 +533,7 @@ def do_sync(w,options, quick=False):
upload_to_strava = False
try:
if options['stravaid'] != 0 and options['stravaid'] != '':
if options['stravaid'] != 0 and options['stravaid'] != '': # pragma: no cover
w.uploadedtostrava = options['stravaid']
upload_to_strava = False
do_strava_export = False
@@ -542,27 +542,27 @@ def do_sync(w,options, quick=False):
pass
try:
if options['nkid'] != 0 and options['nkid'] != '':
if options['nkid'] != 0 and options['nkid'] != '': # pragma: no cover
w.uploadedtonk = options['nkid']
w.save()
except KeyError:
pass
try:
if options['inboard'] != 0 and options['inboard'] != '':
if options['inboard'] != 0 and options['inboard'] != '': # pragma: no cover
w.inboard = options['inboard']
except KeyError:
pass
try:
if options['oarlength'] != 0 and options['oarlength'] != '':
if options['oarlength'] != 0 and options['oarlength'] != '': # pragma: no cover
w.oarlength = options['oarlength']
except KeyError:
pass
try:
if options['garminid'] != 0 and options['garminid'] != '':
if options['garminid'] != 0 and options['garminid'] != '': # pragma: no cover
w.uploadedtogarmin = options['garminid']
w.save()
except KeyError:
@@ -575,7 +575,7 @@ def do_sync(w,options, quick=False):
upload_to_c2 = False
try:
if options['c2id'] != 0 and options['c2id'] != '':
if options['c2id'] != 0 and options['c2id'] != '': # pragma: no cover
w.uploadedtoc2 = options['c2id']
upload_to_c2 = False
do_c2_export = False
@@ -584,7 +584,7 @@ def do_sync(w,options, quick=False):
pass
try:
if options['rp3id'] != 0 and options['rp3id'] != '':
if options['rp3id'] != 0 and options['rp3id'] != '': # pragma: no cover
w.uploadedtorp3 = options['rp3id']
w.save()
except KeyError:
@@ -599,15 +599,15 @@ def do_sync(w,options, quick=False):
except NoTokenError:
id = 0
message = "Something went wrong with the Concept2 sync"
except:
except: # pragma: no cover
pass
if do_strava_export:
if do_strava_export: # pragma: no cover
try:
message,id = stravastuff.workout_strava_upload(
w.user.user,w,quick=quick,asynchron=True,
)
except NoTokenError:
except NoTokenError: # pragma: no cover
id = 0
message = "Please connect to Strava first"
except:
@@ -626,7 +626,7 @@ def do_sync(w,options, quick=False):
message,id = sporttracksstuff.workout_sporttracks_upload(
w.user.user,w,asynchron=True,
)
with open('st_export.log','a') as logfile:
with open('st_export.log','a') as logfile: # pragma: no cover
logfile.write(str(timezone.now())+': ')
logfile.write('Workout uploaded '+str(w.id)+'\n')
except NoTokenError:
@@ -637,7 +637,7 @@ def do_sync(w,options, quick=False):
id = 0
if ('upload_to_RunKeeper' in options and options['upload_to_RunKeeper']) or (w.user.runkeeper_auto_export):
if ('upload_to_RunKeeper' in options and options['upload_to_RunKeeper']) or (w.user.runkeeper_auto_export): # pragma: no cover
try:
message,id = runkeeperstuff.workout_runkeeper_upload(
w.user.user,w,asynchron=True,
@@ -646,7 +646,7 @@ def do_sync(w,options, quick=False):
message = "Please connect to Runkeeper first"
id = 0
if ('upload_to_MapMyFitness' in options and options['upload_to_MapMyFitness']) or (w.user.mapmyfitness_auto_export):
if ('upload_to_MapMyFitness' in options and options['upload_to_MapMyFitness']) or (w.user.mapmyfitness_auto_export): # pragma: no cover
try:
message,id = underarmourstuff.workout_ua_upload(
w.user.user,w
@@ -656,7 +656,7 @@ def do_sync(w,options, quick=False):
id = 0
if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export):
if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export): # pragma: no cover
try:
message,id = tpstuff.workout_tp_upload(
w.user.user,w
+22 -18
View File
@@ -55,7 +55,7 @@ class PlannedSessionViewSet(viewsets.ModelViewSet):
model = PlannedSession
serializer_class = PlannedSessionSerializer
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
r = Rower.objects.get(user=self.request.user)
if r.rowerplan not in ['basic','pro']:
@@ -75,7 +75,7 @@ class WorkoutViewSet(viewsets.ModelViewSet):
#queryset = Workout.objects.all().order_by("-date", "-starttime")
serializer_class = WorkoutSerializer
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
r = Rower.objects.get(user=self.request.user)
return Workout.objects.filter(user=r).order_by("-date","-starttime")
@@ -94,7 +94,7 @@ class RowerViewSet(viewsets.ModelViewSet):
serializer_class = RowerSerializer
#queryset = Rower.objects.all()
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
r = Rower.objects.filter(user=self.request.user)
return r
@@ -113,7 +113,7 @@ class FavoriteChartViewSet(viewsets.ModelViewSet):
serializer_class = FavoriteChartSerializer
#queryset = FavoriteChart.objects.all()
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
r = Rower.objects.get(user=self.request.user)
return FavoriteChart.objects.filter(user=r)
@@ -130,7 +130,7 @@ class EntryViewSet(viewsets.ModelViewSet):
model = VirtualRaceResult
serializer_class = EntrySerializer
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
return VirtualRaceResult.objects.filter(userid=self.request.user.id)
except TypeError:
@@ -146,7 +146,7 @@ class VirtualRaceViewSet(viewsets.ModelViewSet):
model = VirtualRace
serializer_class = VirtualRaceSerializer
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
return VirtualRace.objects.all()
except TypeError:
@@ -158,7 +158,7 @@ class CourseStandardViewSet(viewsets.ModelViewSet):
model = CourseStandard
serializer_class = CourseStandardSerializer
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
return CourseStandard.objects.all()
except TypeError:
@@ -171,7 +171,7 @@ class StandardCollectionViewSet(viewsets.ModelViewSet):
serializer_class = StandardCollectionSerializer
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
return StandardCollection.objects.all()
except TypeError:
@@ -183,7 +183,7 @@ class GeoCourseViewSet(viewsets.ModelViewSet):
model = GeoCourse,
serializer_class = GeoCourseSerializer
def get_queryset(self):
def get_queryset(self): # pragma: no cover
try:
return GeoCourse.objects.all()
except TypeError:
@@ -205,18 +205,18 @@ router.register(r'api/standards',CourseStandardViewSet,'standards')
router.register(r'api/standardcollections',StandardCollectionViewSet,'standardcollections')
router.register(r'api/geocourses',GeoCourseViewSet,'geocourses')
def permissiondenied_view(request):
def permissiondenied_view(request): # pragma: no cover
raise PermissionDenied
def filenotfound_view(request):
def filenotfound_view(request): # pragma: no cover
return rowers.views.error403_view(request)
def response_error_handler(request, exception=None):
def response_error_handler(request, exception=None): # pragma: no cover
return HttpResponse('Error handler content', status=403)
def filenotfound_handler(request, exception=None):
def filenotfound_handler(request, exception=None): # pragma: no cover
return HttpResponse('Error handler content', status=404)
handler403 = views.error403_view
@@ -234,8 +234,10 @@ urlpatterns = [
re_path(r'^', include(router.urls)),
re_path(r'^api-docs/$', views.schema_view,name='schema_view'),
re_path(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
re_path(r'^api/workouts/(?P<id>\b[0-9A-Fa-f]+\b)/strokedata/$',views.strokedatajson,name='strokedatajson'),
re_path(r'^api/v2/workouts/(?P<id>\b[0-9A-Fa-f]+\b)/strokedata/$',views.strokedatajson_v2,name='strokedatajson_v2'),
re_path(r'^api/workouts/(?P<id>\b[0-9A-Fa-f]+\b)/strokedata/$',views.strokedatajson,
name='strokedatajson'),
re_path(r'^api/v2/workouts/(?P<id>\b[0-9A-Fa-f]+\b)/strokedata/$',views.strokedatajson_v2,
name='strokedatajson_v2'),
re_path(r'^500v/$',views.error500_view,name='error500_view'),
path('502/', TemplateView.as_view(template_name='502.html'),name='502'),
path('500/', TemplateView.as_view(template_name='500.html'),name='500'),
@@ -714,8 +716,10 @@ urlpatterns = [
re_path(r'^edittarget/(?P<pk>\d+)/$',login_required(
views.TrainingTargetUpdate.as_view()),
name='trainingtarget_update_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/test\_strokedata/$',views.strokedataform),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/v2/test\_strokedata/$',views.strokedataform_v2),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/test\_strokedata/$',views.strokedataform,
name='strokedataform'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/v2/test\_strokedata/$',views.strokedataform_v2,
name='strokedataform_v2'),
re_path(r'^sessions/library/$',views.template_library_view,name="template_library_view"),
re_path(r'^sessions/teamcreate/user/(?P<userid>\d+)/$',views.plannedsession_teamcreate_view,
name='plannedsession_teamcreate_view'),
@@ -849,7 +853,7 @@ urlpatterns = [
re_path(r'^braintree/$',views.braintree_webhook_view,name="braintree_webhook_view"),
]
if settings.DEBUG:
if settings.DEBUG: # pragma: no cover
urlpatterns += [
re_path(r'^c2listug/(?P<page>\d+)/$',views.c2listdebug_view),
re_path(r'^c2listug/$',views.c2listdebug_view),
+59 -68
View File
@@ -178,20 +178,11 @@ rankingdurations.append(datetime.time(minute=30))
rankingdurations.append(datetime.time(hour=1,minute=15))
rankingdurations.append(datetime.time(hour=1))
def is_ranking_piece(workout):
if workout.distance in rankingdistances:
return True
elif workout.duration in rankingdurations:
return True
return False
def range_to_color_hex(groupcols,palette='monochrome_blue'):
try:
plt = palettes[palette]
except KeyError:
except KeyError: # pragma: no cover
plt = palettes['monochrome_blue']
rgb = [colorsys.hsv_to_rgb((plt[0]+plt[1]*x)/360.,
@@ -203,7 +194,7 @@ def range_to_color_hex(groupcols,palette='monochrome_blue'):
return colors
def str2bool(v):
def str2bool(v): # pragma: no cover
return v.lower() in ("yes", "true", "t", "1")
def uniqify(seq, idfun=None):
@@ -222,11 +213,11 @@ def uniqify(seq, idfun=None):
result.append(item)
return result
def serialize_list(value,token=','):
def serialize_list(value,token=','): # pragma: no cover
assert(isinstance(value, list) or isinstance(value, tuple) or isinstance(value,np.ndarray))
return token.join([str(s) for s in value])
def deserialize_list(value,token=','):
def deserialize_list(value,token=','): # pragma: no cover
if isinstance(value, list):
return value
elif isinstance(value, np.ndarray):
@@ -316,15 +307,15 @@ def myqueue(queue,function,*args,**kwargs):
self.result = 1
self.id = 1
def revoke(self):
def revoke(self): # pragma: no cover
return 1
if settings.TESTING:
return MockJob()
elif settings.CELERY:
elif settings.CELERY: # pragma: no cover
kwargs['debug'] = True
job = function.delay(*args,**kwargs)
else:
else: # pragma: no cover
if settings.DEBUG:
kwargs['debug'] = True
@@ -335,7 +326,7 @@ def myqueue(queue,function,*args,**kwargs):
job = queue.enqueue(function,*args,**kwargs)
return job
return job # pragma: no cover
from datetime import date
@@ -361,7 +352,7 @@ def my_dict_from_instance(instance,model):
try:
verbosename = f.verbose_name
except:
except: # pragma: no cover
verbosename = f.name
get_choice = 'get_'+fname+'_display'
@@ -370,7 +361,7 @@ def my_dict_from_instance(instance,model):
else:
try:
value = getattr(instance,fname)
except AttributeError:
except AttributeError: # pragma: no cover
value = None
if f.editable and value:
@@ -390,33 +381,33 @@ def wavg(group, avg_name, weight_name):
return d.mean()
try:
return (d * w).sum() / w.sum()
except ZeroDivisionError:
except ZeroDivisionError: # pragma: no cover
return d.mean()
def totaltime_sec_to_string(totaltime,shorten=False):
if np.isnan(totaltime):
return ''
hours = int(totaltime / 3600.)
if hours > 23:
if hours > 23: # pragma: no cover
message = 'Warning: The workout duration was longer than 23 hours. '
hours = 23
minutes = int((totaltime - 3600. * hours) / 60.)
if minutes > 59:
if minutes > 59: # pragma: no cover
minutes = 59
if not message:
if not message: # pragma: no cover
message = 'Warning: there is something wrong with the workout duration'
seconds = int(totaltime - 3600. * hours - 60. * minutes)
if seconds > 59:
if seconds > 59: # pragma: no cover
seconds = 59
if not message:
if not message: # pragma: no cover
message = 'Warning: there is something wrong with the workout duration'
tenths = int(10 * (totaltime - 3600. * hours - 60. * minutes - seconds))
if tenths > 9:
if tenths > 9: # pragma: no cover
tenths = 9
if not message:
if not message: # pragma: no cover
message = 'Warning: there is something wrong with the workout duration'
duration = ""
@@ -428,7 +419,7 @@ def totaltime_sec_to_string(totaltime,shorten=False):
tenths=tenths
)
else:
if hours != 0:
if hours != 0: # pragma: no cover
duration = "{hours}:{minutes:02d}:{seconds:02d}".format(
hours=hours,
minutes=minutes,
@@ -446,7 +437,7 @@ def totaltime_sec_to_string(totaltime,shorten=False):
return duration
def iscoach(m,r):
def iscoach(m,r): # pragma: no cover
result = False
result = m in r.coaches
@@ -468,7 +459,7 @@ def ewmovingaverage(interval,window_size):
interval2 = np.vstack((i_ewma1,i_ewma2[::-1]))
interval2 = np.mean( interval2, axis=0) # average
except ValueError:
except ValueError: # pragma: no cover
interval2 = interval
return interval2
@@ -479,10 +470,10 @@ class NoTokenError(Exception):
def __init__(self,value):
self.value=value
def __str__(self):
def __str__(self): # pragma: no cover
return repr(self.value)
class ProcessorCustomerError(Exception):
class ProcessorCustomerError(Exception): # pragma: no cover
def __init__(self, value):
self.value=value
@@ -516,7 +507,7 @@ def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high
'Content-Type': 'application/json',
'resolution': 'medium',}
if metric == 'power':
if metric == 'power': # pragma: no cover
metric = 'watts'
url = "https://www.strava.com/api/v3/activities/{stravaid}/streams/{metric}?resolution={fetchresolution}&series_type={series_type}".format(
@@ -530,7 +521,7 @@ def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high
s = requests.get(url,headers=headers)
if metric=='power':
if metric=='power': # pragma: no cover
with open('data.txt', 'w') as outfile:
json.dump(s.json(), outfile)
print('saved to file')
@@ -540,7 +531,7 @@ def get_strava_stream(r,metric,stravaid,series_type='time',fetchresolution='high
try:
if data['type'] == metric:
return np.array(data['data'])
except TypeError:
except TypeError: # pragma: no cover
return None
return None
@@ -565,13 +556,13 @@ def steps_read_fit(filename,name='',sport='Custom'):
response = requests.post(url=url,headers=headers,json={'filename':filename})
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
return None
w = response.json()
try:
d = w['workout']
except KeyError:
except KeyError: # pragma: no cover
return None
return d
@@ -583,13 +574,13 @@ def steps_write_fit(steps):
response = requests.post(url=url,headers=headers,json=steps)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
return None
w = response.json()
try:
filename = w['filename']
except KeyError:
except KeyError: # pragma: no cover
return None
return filename
@@ -599,12 +590,12 @@ def step_to_time_dist(step,avgspeed = 3.7):
distance = 0
durationtype = step['durationType']
if step['durationValue'] == 0:
if step['durationValue'] == 0: # pragma: no cover
return 0,0
try:
targettype = step['targetType']
except KeyError:
except KeyError: # pragma: no cover
targettype = 0
@@ -620,13 +611,13 @@ def step_to_time_dist(step,avgspeed = 3.7):
valuelow = step['targetValueLow']
valuehigh = step['targetValueHigh']
if value != 0:
if value != 0: # pragma: no cover
distance = seconds*value
elif valuelow != 0 and valuehigh != 0:
elif valuelow != 0 and valuehigh != 0: # pragma: no cover
distance = seconds*(valuelow+valuehigh)/2.
return seconds,distance
elif durationtype == 'Distance':
elif durationtype == 'Distance': # pragma: no cover
value = step['durationValue']
distance = value/100.
seconds = distance/avgspeed
@@ -636,21 +627,21 @@ def step_to_time_dist(step,avgspeed = 3.7):
valuelow = step['targetValueLow']
valuehigh = step['targetValueHigh']
if value != 0:
if value != 0: # pragma: no cover
seconds = distance/value
elif valuelow != 0 and valuehigh != 0:
elif valuelow != 0 and valuehigh != 0: # pragma: no cover
midspeed = (valuelow+valuehigh)/2.
seconds = distance/midspeed
return seconds, distance
elif durationtype in ['PowerLessThan','PowerGreaterThan','HrLessThan','HrGreaterThan']:
elif durationtype in ['PowerLessThan','PowerGreaterThan','HrLessThan','HrGreaterThan']: # pragma: no cover
seconds = 600
distance = seconds*avgspeed
return seconds,distance
return seconds,distance
def get_step_type(step):
def get_step_type(step): # pragma: no cover
t = 'WorkoutStep'
if step['durationType'] in ['RepeatUntilStepsCmplt','RepeatUntilHrLessThan','RepeatUntilHrGreaterThan']:
@@ -659,7 +650,7 @@ def get_step_type(step):
return t
def peel(l):
if len(l)==0:
if len(l)==0: # pragma: no cover
return None,None
if len(l)==1:
return l[0],None
@@ -667,7 +658,7 @@ def peel(l):
first = l[0]
rest = l[1:]
if first['type'] == 'Step':
if first['type'] == 'Step': # pragma: no cover
return first, rest
# repeatstep
theID = -1
@@ -765,7 +756,7 @@ def ps_dict_order(d,short=False):
factor /= multiplier.pop()
spaces = spaces[:-18]
holduntil.pop()
else:
else: # pragma: no cover
prevstep = sdict3.pop()
prevstep['string'] = prevstep['string'][18:]
prevprevstep = sdict3.pop()
@@ -799,13 +790,13 @@ def step_to_string(step,short=False):
durationtype = step['durationType']
if step['durationValue'] == 0:
if durationtype not in ['RepeatUntilStepsCmplt','RepeatUntilHrLessThan','RepeatUntilHrGreaterThan']:
if durationtype not in ['RepeatUntilStepsCmplt','RepeatUntilHrLessThan','RepeatUntilHrGreaterThan']: # pragma: no cover
return '',type, -1, -1,1
if durationtype == 'Time':
unit = 'min'
value = step['durationValue']
if value/1000. >= 3600:
if value/1000. >= 3600: # pragma: no cover
unit = 'h'
dd = timedelta(seconds=value/1000.)
#duration = humanize.naturaldelta(dd, minimum_unit="seconds")
@@ -814,7 +805,7 @@ def step_to_string(step,short=False):
unit = 'm'
value = step['durationValue']/100.
duration = int(value)
elif durationtype == 'HrLessThan':
elif durationtype == 'HrLessThan': # pragma: no cover
value = step['durationValue']
if value <= 100:
duration = 'until heart rate lower than {v}% of max'.format(v=value)
@@ -824,7 +815,7 @@ def step_to_string(step,short=False):
duration = 'until heart rate lower than {v}'.format(v=value-100)
if short:
duration = 'until HR<{v}'.format(v=value-100)
elif durationtype == 'HrGreaterThan':
elif durationtype == 'HrGreaterThan': # pragma: no cover
value = step['durationValue']
if value <= 100:
duration = 'until heart rate greater than {v}% of max'.format(v=value)
@@ -834,7 +825,7 @@ def step_to_string(step,short=False):
duration = 'until heart rate greater than {v}'.format(v=value-100)
if short:
duration = 'until HR>{v}'.format(v=value/100)
elif durationtype == 'PowerLessThan':
elif durationtype == 'PowerLessThan': # pragma: no cover
value = step['durationValue']
targetvalue = step['targetvalue']
if value <= 1000:
@@ -849,7 +840,7 @@ def step_to_string(step,short=False):
)
if short:
'until < {targetvalue} W'.format(targetvalue=targetvalue-1000)
elif durationtype == 'PowerGreaterThan':
elif durationtype == 'PowerGreaterThan': # pragma: no cover
value = step['durationValue']
targetvalue = step['targetvalue']
if value <= 1000:
@@ -864,13 +855,13 @@ def step_to_string(step,short=False):
)
if short:
duration = 'until > {targetvalue} W'.format(targetvalue=targetvalue)
elif durationtype == 'RepeatUntilStepsCmplt':
elif durationtype == 'RepeatUntilStepsCmplt': # pragma: no cover
type = 'RepeatStep'
ntimes = ': {v}x'.format(v=step['targetValue'])
repeatID = step['durationValue']
duration =ntimes
repeatValue = step['targetValue']
elif durationtype == 'RepeatUntilHrGreaterThan':
elif durationtype == 'RepeatUntilHrGreaterThan': # pragma: no cover
type = 'RepeatStep'
targetvalue = step['targetValue']
if targetvalue <= 100:
@@ -886,7 +877,7 @@ def step_to_string(step,short=False):
if short:
duration = ': untl HR>{targetvalue}'.format(targetvalue=targetvalue-100)
repeatID = step['durationValue']
elif durationtype == 'RepeatUntilHrLessThan':
elif durationtype == 'RepeatUntilHrLessThan': # pragma: no cover
type = 'RepeatStep'
targetvalue = step['targetValue']
if targetvalue <= 100:
@@ -911,7 +902,7 @@ def step_to_string(step,short=False):
except KeyError:
targettype = None
if targettype == 'HeartRate':
if targettype == 'HeartRate': # pragma: no cover
try:
value = step['targetValue']
except KeyError:
@@ -938,7 +929,7 @@ def step_to_string(step,short=False):
l = valuelow - 100,
h = valuehigh - 100,
)
elif targettype == 'Power':
elif targettype == 'Power': # pragma: no cover
try:
value = step['targetValue']
except KeyError:
@@ -969,7 +960,7 @@ def step_to_string(step,short=False):
l = valuelow-1000,
h = valuehigh-1000,
)
elif targettype == 'Speed':
elif targettype == 'Speed': # pragma: no cover
try:
value = step['targetValue']
except KeyError:
@@ -990,9 +981,9 @@ def step_to_string(step,short=False):
target = '@ {v} m/s {p}, per 500m'.format(
v=value/1000.,
p=pacestring)
if short:
if short: # pragma: no cover
target = '@ {p}'.format(p=pacestring)
elif valuelow != 0 and valuehigh != 0:
elif valuelow != 0 and valuehigh != 0: # pragma: no cover
v = valuelow/1000.
pace = 500./v
pacestringlow = to_pace(pace)
@@ -1012,7 +1003,7 @@ def step_to_string(step,short=False):
pl = pacestringlow,
ph = pacestringhigh,
)
elif targettype == 'Cadence':
elif targettype == 'Cadence': # pragma: no cover
try:
value = step['targetValue']
except KeyError:
@@ -1041,7 +1032,7 @@ def step_to_string(step,short=False):
notes = ''
try:
if len(step['description']):
if len(step['description']): # pragma: no cover
notes = ' - '+step['description']
except KeyError:
notes = ''
@@ -1093,7 +1084,7 @@ def step_to_string(step,short=False):
return s,type, nr, repeatID, repeatValue
def strfdelta(tdelta):
def strfdelta(tdelta): # pragma: no cover
try:
minutes, seconds = divmod(tdelta.seconds, 60)
tenths = int(tdelta.microseconds / 1e5)
+4 -4
View File
@@ -433,12 +433,12 @@ def trendflexdata(workouts, options,userid=0):
if groupby != 'date':
try:
df['groupval'] = groups.mean()[groupby]
df['groupval'].loc[mask] = np.nan
df.loc[mask,'groupval'] = np.nan
groupcols = df['groupval']
except (ValueError, AttributeError): # pragma: no cover
df['groupval'] = groups.mean()[groupby].fillna(value=0)
df['groupval'].loc[mask] = np.nan
df.loc[mask,'groupval'] = np.nan
groupcols = df['groupval']
except KeyError: # pragma: no cover
messages.error(request,'Data selection error')
@@ -1101,7 +1101,7 @@ def performancemanager_view(request,userid=0,mode='rower',
showtests = True,
)
ids = pd.Series(ids).dropna().values
ids = pd.Series(ids,dtype='int').dropna().values
bestworkouts = Workout.objects.filter(id__in=ids).order_by('-date')
@@ -1411,7 +1411,7 @@ def rankings_view2(request,userid=0,
p1 = res[4]
message = res[5]
try:
testcalc = pd.Series(res[6])*3
testcalc = pd.Series(res[6],dtype='float')*3
except TypeError: # pragma: no cover
age = 0
+47 -43
View File
@@ -6,6 +6,7 @@ from __future__ import unicode_literals
from rowers.views.statements import *
from rowers.tasks import handle_calctrimp
from rowers.mailprocessing import send_confirm
from rowers.opaque import encoder
import sys
import arrow
@@ -14,14 +15,11 @@ import arrow
@login_required()
def strokedataform(request,id=0):
try:
id=int(id)
except ValueError:
id = 0
id = encoder.decode_hex(id)
try:
w = Workout.objects.get(id=id)
except Workout.DoesNotExist:
except Workout.DoesNotExist: # pragma: no cover
raise Http404("Workout doesn't exist")
if request.method == 'GET':
@@ -33,7 +31,7 @@ def strokedataform(request,id=0):
'id':id,
'workout':w,
})
elif request.method == 'POST':
elif request.method == 'POST': # pragma: no cover
form = StrokeDataForm()
return render(request, 'strokedata_form.html',
@@ -42,19 +40,17 @@ def strokedataform(request,id=0):
'teams':get_my_teams(request.user),
'id':id,
'workout':w,
})
}) # pragma: no cover
@login_required()
def strokedataform_v2(request,id=0):
try:
id=int(id)
except ValueError:
id = 0
id = encoder.decode_hex(id)
try:
w = Workout.objects.get(id=id)
except Workout.DoesNotExist:
except Workout.DoesNotExist: # pragma: no cover
raise Http404("Workout doesn't exist")
if request.method == 'GET':
@@ -66,7 +62,7 @@ def strokedataform_v2(request,id=0):
'id':id,
'workout':w,
})
elif request.method == 'POST':
elif request.method == 'POST': # pragma: no cover
form = StrokeDataForm()
return render(request, 'strokedata_form_v2.html',
@@ -75,7 +71,7 @@ def strokedataform_v2(request,id=0):
'teams':get_my_teams(request.user),
'id':id,
'workout':w,
})
}) # pragma: no cover
# Process the POSTed stroke data according to the API definition
@@ -95,12 +91,12 @@ def strokedatajson_v2(request,id):
"""
row = get_object_or_404(Workout,pk=id)
if row.user != request.user.rower:
if row.user != request.user.rower: # pragma: no cover
return HttpResponse("You do not have permission to perform this action",status=403)
try:
id = int(id)
except ValueError:
except ValueError: # pragma: no cover
return HttpResponse("Not a valid workout number",status=404)
if request.method == 'GET':
@@ -124,24 +120,24 @@ def strokedatajson_v2(request,id):
for d in request.data['data']:
logfile.write(json.dumps(d))
logfile.write("\n")
except KeyError:
except KeyError: # pragma: no cover
try:
for d in request.data['strokedata']:
logfile.write(json.dumps(d))
logfile.write("\n")
except KeyError:
logfile.write("No data in request.data\n")
except (AttributeError,TypeError):
except (AttributeError,TypeError): # pragma: no cover
logfile.write("No data in request\n")
checkdata, r = dataprep.getrowdata_db(id=row.id)
if not checkdata.empty:
if not checkdata.empty: # pragma: no cover
return HttpResponse("Duplicate Error",status=409)
df = pd.DataFrame()
try:
df = pd.DataFrame(request.data['data'])
except KeyError:
except KeyError: # pragma: no cover
try:
df = pd.DataFrame(request.data['strokedata'])
except:
@@ -154,7 +150,7 @@ def strokedatajson_v2(request,id):
#time, pace, distance,spm
try:
time = df['time']/1.e3
except KeyError:
except KeyError: # pragma: no cover
try:
time = df['t']/10.
except KeyError:
@@ -162,12 +158,12 @@ def strokedatajson_v2(request,id):
try:
spm = df['spm']
except KeyError:
except KeyError: # pragma: no cover
return HttpResponse("Missing spm",status=400)
try:
distance = df['distance']
except KeyError:
except KeyError: # pragma: no cover
try:
distance = df['d']/10.
except KeyError:
@@ -175,7 +171,7 @@ def strokedatajson_v2(request,id):
try:
pace = df['pace']/1.e3
except KeyError:
except KeyError: # pragma: no cover
try:
pace = df['p']/10.
except KeyError:
@@ -185,7 +181,7 @@ def strokedatajson_v2(request,id):
try:
power = df['power']
except KeyError:
except KeyError: # pragma: no cover
power = 0*time
try:
drivelength = df['drivelength']
@@ -245,7 +241,7 @@ def strokedatajson_v2(request,id):
lapidx = 0*time
try:
hr = df['hr']
except KeyError:
except KeyError: # pragma: no cover
hr = 0*df['time']
try:
@@ -331,7 +327,7 @@ def strokedatajson_v2(request,id):
isbreakthrough, ishard = dataprep.checkbreakthrough(row, r)
if r.getemailnotifications and not r.emailbounced:
if r.getemailnotifications and not r.emailbounced: # pragma: no cover
link = settings.SITE_URL+reverse(
r.defaultlandingpage,
kwargs = {
@@ -354,7 +350,7 @@ def strokedatajson_v2(request,id):
}))
#return(HttpResponse(encoder.encode_hex(row.id),status=201))
return HttpResponseNotAllowed("Method not supported")
return HttpResponseNotAllowed("Method not supported") # pragma: no cover
@@ -362,18 +358,19 @@ def strokedatajson_v2(request,id):
@login_required()
@api_view(['GET','POST'])
@permission_classes([IsAuthenticated])
def strokedatajson(request,id):
def strokedatajson(request,id=0):
"""
POST: Add Stroke data to workout
GET: Get stroke data of workout
"""
row = get_object_or_404(Workout,pk=id)
if row.user != request.user.rower:
if row.user != request.user.rower: # pragma: no cover
raise PermissionDenied("You have no access to this workout")
try:
id = int(id)
except ValueError:
except ValueError: # pragma: no cover
return HttpResponse("Not a valid workout number",status=403)
@@ -389,39 +386,46 @@ def strokedatajson(request,id):
if request.method == 'POST':
with open('apilog.log','a') as logfile:
logfile.write(str(timezone.now())+": ")
logfile.write(request.user.username+"(strokedatjson POST) \n")
logfile.write(request.user.username+"(strokedatajson POST) \n")
checkdata,r = dataprep.getrowdata_db(id=row.id)
if not checkdata.empty:
if not checkdata.empty: # pragma: no cover
return HttpResponse("Duplicate Error",status=409)
# strokedata = request.POST['strokedata']
# checking/validating and cleaning
try:
strokedata = json.loads(request.data['strokedata'])
except:
return HttpResponse("No JSON object could be decoded",status=400)
strokedata = json.loads(request.data)['strokedata']
except: # pragma: no cover
try:
s = json.dumps(request.data)
strokedata = json.loads(s)['strokedata']
except: # pragma: no cover
return HttpResponse("No JSON object could be decoded",status=400)
df = pd.DataFrame(strokedata)
try:
df = pd.DataFrame(strokedata)
except ValueError: # pragma: no cover
return HttpResponse("Arrays must all be same length",status=400)
df.index = df.index.astype(int)
df.sort_index(inplace=True)
# time, hr, pace, spm, power, drivelength, distance, drivespeed, dragfactor, strokerecoverytime, averagedriveforce, peakdriveforce, lapidx
try:
time = df['time']/1.e3
except KeyError:
except KeyError: # pragma: no cover
return HttpResponse("There must be time values",status=400)
aantal = len(time)
pace = df['pace']/1.e3
if len(pace) != aantal:
if len(pace) != aantal: # pragma: no cover
return HttpResponse("Pace array has incorrect length",status=400)
distance = df['distance']
if len(distance) != aantal:
if len(distance) != aantal: # pragma: no cover
return HttpResponse("Distance array has incorrect length",status=400)
spm = df['spm']
if len(spm) != aantal:
if len(spm) != aantal: # pragma: no cover
return HttpResponse("SPM array has incorrect length",status=400)
res = dataprep.testdata(time,distance,pace,spm)
if not res:
if not res: # pragma: no cover
return HttpResponse("Data are not numerical",status=400)
power = trydf(df,aantal,'power')
@@ -503,4 +507,4 @@ def strokedatajson(request,id):
return HttpResponse(encoder.encode_hex(row.id),status=201)
#Method not supported
return HttpResponseNotAllowed("Method not supported")
return HttpResponseNotAllowed("Method not supported") # pragma: no cover
+2 -2
View File
@@ -11,7 +11,7 @@ from django.test import SimpleTestCase, override_settings
from django.urls import path
def servererror_view(request):
def servererror_view(request): # pragma: no cover
raise ValueError
# Custom error pages with Rowsandall headers
@@ -36,7 +36,7 @@ def error400_view(request, exception):
response.status_code = 400
return response
def error403_view(request,*args, **kwargs):
def error403_view(request,*args, **kwargs): # pragma: no cover
response = render(request,'403.html', {},status=403)
# context_instance = RequestContext(request))
+7 -7
View File
@@ -74,16 +74,16 @@ def plannedsessions_coach_icsemail_view(request,userid=0):
sps = get_sessions_manager(request.user,teamid=0,
enddate=enddate,
startdate=startdate)
else:
else: # pragma: no cover
rteams = therower.team.filter(viewing='allmembers')
sps = get_sessions(therower,startdate=startdate,enddate=enddate)
if therower.rowerplan != 'freecoach':
rowers = [therower]
else:
else: # pragma: no cover
rowers = []
for ps in sps:
for ps in sps: # pragma: no cover
if 'coach' in request.user.rower.rowerplan:
rowers += ps.rower.all().exclude(rowerplan='freecoach')
else:
@@ -95,7 +95,7 @@ def plannedsessions_coach_icsemail_view(request,userid=0):
cal.add('prodid','rowsandall')
cal.add('version','1.0')
for ps in sps:
for ps in sps: # pragma: no cover
event = Event()
comment = '{d} {u} {c}'.format(
d=ps.sessionvalue,
@@ -138,7 +138,7 @@ def plannedsessions_coach_icsemail_view(request,userid=0):
@login_required()
def course_kmldownload_view(request,id=0):
r = getrower(request.user)
if r.emailbounced:
if r.emailbounced: # pragma: no cover
message = "Please check your email address first. Email to this address bounced."
messages.error(request,message)
return HttpResponseRedirect(
@@ -190,7 +190,7 @@ def workout_gpxemail_view(request,id=0):
@login_required()
def workouts_summaries_email_view(request):
r = getrower(request.user)
if r.emailbounced:
if r.emailbounced: # pragma: no cover
message = "Please check your email address first. Email to this address bounced."
messages.error(request, message)
return HttpResponseRedirect(
@@ -259,7 +259,7 @@ def workout_csvemail_view(request,id=0):
# Get Workout CSV file and send it to user's email address
@login_required()
@permission_required('rower.is_staff',fn=get_user_by_userid,raise_exception=True)
def workout_csvtoadmin_view(request,id=0):
def workout_csvtoadmin_view(request,id=0): # pragma: no cover
message = ""
r = getrower(request.user)
w = get_workout(id)
+2 -1
View File
@@ -11,6 +11,7 @@ def default(o): # pragma: no cover
if isinstance(o, numpy.int64): return int(o)
raise TypeError
from rowsandall_app.settings import NK_OAUTH_LOCATION
# Send workout to TP
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
@@ -407,7 +408,7 @@ def rower_nk_authorize(request): # pragma: no cover
"redirect_uri": NK_REDIRECT_URI,
}
url = "https://oauth-stage.nkrowlink.com/oauth/authorize?"+urllib.parse.urlencode(params)
url = NK_OAUTH_LOCATION+"/oauth/authorize?"+urllib.parse.urlencode(params)
return HttpResponseRedirect(url)
+16 -12
View File
@@ -16,7 +16,7 @@ def download_fit(request,filename=''):
pss = PlannedSession.objects.filter(fitfile=filename)
if len(pss) != 1:
if len(pss) != 1: # pragma: no cover
raise Http404("Could not find the required file")
ps = pss[0]
@@ -24,26 +24,30 @@ def download_fit(request,filename=''):
if ps.manager == request.user or request.user.rower in ps.rower.all():
owns = True
if not owns:
if not owns: # pragma: no cover
raise PermissionDenied("You are not allowed to download this file")
fitfile = ps.fitfile
response = HttpResponse(fitfile)
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
response['Content-Type'] = 'application/octet-stream'
try:
response = HttpResponse(fitfile)
except FileNotFoundError:
raise Http404("File not found")
return response
response['Content-Disposition'] = 'attachment; filename="%s"' % filename # pragma: no cover
response['Content-Type'] = 'application/octet-stream' # pragma: no cover
return response # pragma: no cover
@login_required()
def failed_queue_view(request):
if not request.user.is_staff:
if not request.user.is_staff: # pragma: no cover
raise PermissionDenied("Not Allowed")
q = Queue('failed', connection=Redis())
resultslist = []
for job in q.jobs:
for job in q.jobs: # pragma: no cover
traceback = str(job.exc_info)
@@ -66,7 +70,7 @@ def failed_queue_view(request):
@login_required()
def failed_queue_empty(request):
if not request.user.is_staff:
if not request.user.is_staff: # pragma: no cover
raise PermissionDenied("Not Allowed")
q = Queue('failed', connection=Redis())
@@ -77,8 +81,8 @@ def failed_queue_empty(request):
@login_required()
def failed_job_view(request,id=0):
if not request.user.is_staff:
def failed_job_view(request,id=0): # pragma: no cover
if not request.user.is_staff:
raise PermissionDenied("Not Allowed")
q = Queue('failed', connection=Redis())
@@ -90,7 +94,7 @@ def failed_job_view(request,id=0):
@login_required()
def errormessage_view(request,errormessage='aap'):
def errormessage_view(request,errormessage='aap'): # pragma: no cover
if (errormessage=='3dsecure'):
errormessage = '3D Secure Card Verification Error. Please check your card details.'
messages.error(request,errormessage)
+78 -78
View File
@@ -15,7 +15,7 @@ def braintree_webhook_view(request):
f.write(timestamp+' /rowers/braintree/\n')
if request.method == 'POST':
result = braintreestuff.webhook(request)
if result == 4:
if result == 4: # pragma: no cover
raise PermissionDenied("Not allowed")
return HttpResponse('')
@@ -23,7 +23,7 @@ def braintree_webhook_view(request):
def paidplans_view(request):
if not request.user.is_anonymous:
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
else:
r = None
@@ -36,16 +36,16 @@ def paidplans_view(request):
@login_required()
def billing_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
if payments.is_existing_customer(r):
if payments.is_existing_customer(r): # pragma: no cover
url = reverse(upgrade_view)
return HttpResponseRedirect(url)
@@ -63,7 +63,7 @@ def billing_view(request):
plan = planselectform.cleaned_data['plan']
try:
customer_id = braintreestuff.create_customer(r)
except ProcessorCustomerError:
except ProcessorCustomerError: # pragma: no cover
messages.error(request,"Something went wrong registering you as a customer.")
url = reverse(billing_view)
return HttpResponseRedirect(url)
@@ -89,7 +89,7 @@ def billing_view(request):
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
def buy_trainingplan_view(request,id=0):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
@@ -97,10 +97,10 @@ def buy_trainingplan_view(request,id=0):
plan = get_object_or_404(InstantPlan,pk=id)
if r.paymentprocessor != 'braintree':
if r.paymentprocessor != 'braintree': # pragma: no cover
messages.error(request,"This purchase is currently only available through BrainTree (by PayPal)")
if id == 0 or id is None:
if id == 0 or id is None: # pragma: no cover
messages.error(request,"There was an error accessing this plan")
url = reverse('rower_view_instantplan',kwargs={
'id':plan.uuid,
@@ -111,7 +111,7 @@ def buy_trainingplan_view(request,id=0):
if request.method == 'POST':
billingaddressform = RowerBillingAddressForm(instance=r)
form = InstantPlanSelectForm(request.POST)
if billingaddressform.is_valid():
if billingaddressform.is_valid(): # pragma: no cover
cd = billingaddressform.cleaned_data
for attr, value in cd.items():
setattr(r, attr, value)
@@ -134,16 +134,16 @@ def buy_trainingplan_view(request,id=0):
try:
targetid = request.POST['target']
if targetid != '':
if targetid != '': # pragma: no cover
target = TrainingTarget.objects.get(id=int(targetid))
else:
else: # pragma: no cover
target = None
except KeyError:
target = None
if target and datechoice == 'target':
if target and datechoice == 'target': # pragma: no cover
enddate = target.date
elif datechoice == 'startdate':
elif datechoice == 'startdate': # pragma: no cover
enddate = startdate+datetime.timedelta(days=plan.duration)
else:
startdate = enddate-datetime.timedelta(days=plan.duration)
@@ -177,13 +177,13 @@ def buy_trainingplan_view(request,id=0):
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
def purchase_checkouts_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if request.method != 'POST':
if request.method != 'POST': # pragma: no cover
url = reverse('rower_view_instantplan',kwargs={
'id':plan.uuid,
})
@@ -199,7 +199,7 @@ def purchase_checkouts_view(request):
url = settings.WORKOUTS_FIT_URL+"/trainingplan/"+str(plan.uuid)
headers = {'Authorization':authorizationstring}
response = requests.get(url=url,headers=headers)
if response.status_code != 200:
if response.status_code != 200: # pragma: no cover
messages.error(request,"Could not connect to the training plan server")
return HttpResponseRedirect(reverse('rower_select_instantplan'))
@@ -233,13 +233,13 @@ def purchase_checkouts_view(request):
url = url+'?when='+timeperiod
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
messages.error(request,"There was a problem with your payment")
url = reverse('rower_view_instantplan',kwargs={
'id':plan.uuid,
})
return HttpResponseRedirect(url)
elif 'tac' not in request.POST:
elif 'tac' not in request.POST: # pragma: no cover
try:
planid=int(request.POST['plan'])
enddate = request.POST['enddate']
@@ -250,19 +250,19 @@ def purchase_checkouts_view(request):
url = reverse("purchase_checkouts_view")
return HttpResponseRedirect(url)
url = reverse('rower_select_instantplan')
if 'plan' in request.POST:
url = reverse('rower_select_instantplan') # pragma: no cover
if 'plan' in request.POST: # pragma: no cover
plan = plan = InstantPlan.objects.get(id=request.POST['plan'])
url = reverse('rower_view_instantplan',kwargs={
'id':plan.uuid,
})
return HttpResponseRedirect(url)
return HttpResponseRedirect(url) # pragma: no cover
@user_passes_test(can_plan,login_url="/rowers/paidplans",
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
def confirm_trainingplan_purchase_view(request,id = 0):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
@@ -270,10 +270,10 @@ def confirm_trainingplan_purchase_view(request,id = 0):
plan = get_object_or_404(InstantPlan,pk=id)
if r.paymentprocessor != 'braintree':
if r.paymentprocessor != 'braintree': # pragma: no cover
messages.error(request,"This purchase is currently only available through BrainTree (by PayPal)")
if id == 0 or id is None:
if id == 0 or id is None: # pragma: no cover
messages.error(request,"There was an error accessing this plan")
url = reverse('rower_view_instantplan',kwargs={
'id':plan.uuid,
@@ -287,7 +287,7 @@ def confirm_trainingplan_purchase_view(request,id = 0):
name = request.GET.get('name','')
status = request.GET.get('status',True)
notes = request.GET.get('notes','')
if enddate is None:
if enddate is None: # pragma: no cover
messages.error(request,"There was an error accessing this plan")
url = reverse('rower_view_instantplan',kwargs={
'id':plan.uuid,
@@ -307,16 +307,16 @@ def confirm_trainingplan_purchase_view(request,id = 0):
@login_required()
def upgrade_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
if r.subscription_id is None or r.subscription_id == '':
if r.subscription_id is None or r.subscription_id == '': # pragma: no cover
url = reverse(billing_view)
return HttpResponseRedirect(url)
@@ -352,16 +352,16 @@ def upgrade_view(request):
@login_required()
def downgrade_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
if r.subscription_id is None or r.subscription_id == '':
if r.subscription_id is None or r.subscription_id == '': # pragma: no cover
url = reverse(billing_view)
return HttpResponseRedirect(url)
@@ -378,9 +378,9 @@ def downgrade_view(request):
if planselectform.is_valid():
plan = planselectform.cleaned_data['plan']
if plan.price > r.paidplan.price:
if plan.price > r.paidplan.price: # pragma: no cover
nextview = upgrade_confirm_view
elif plan.price == r.paidplan.price:
elif plan.price == r.paidplan.price: # pragma: no cover
messages.info(request,'You did not select a new plan')
url = reverse(downgrade_view)
return HttpResponseRedirect(url)
@@ -409,7 +409,7 @@ def downgrade_view(request):
@login_required()
def plan_stop_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
@@ -417,13 +417,13 @@ def plan_stop_view(request):
subscriptions = []
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
try:
subscriptions = braintreestuff.find_subscriptions(r)
except ProcessorCustomerError:
except ProcessorCustomerError: # pragma: no cover
r.paymentprocessor = None
r.save()
@@ -437,13 +437,13 @@ def plan_stop_view(request):
@login_required()
def plan_tobasic_view(request,id=0):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if r.paidplan.paymentprocessor == 'braintree':
if r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
success, themessages,errormessages = braintreestuff.cancel_subscription(r,id)
for message in themessages:
messages.info(request,message)
@@ -459,20 +459,20 @@ def plan_tobasic_view(request,id=0):
@login_required()
def upgrade_confirm_view(request,planid = 0):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
try:
plan = PaidPlan.objects.get(id=planid)
except PaidPlan.DoesNotExist:
except PaidPlan.DoesNotExist: # pragma: no cover
messages.error(request,"Something went wrong. Please try again.")
url = reverse(billing_view)
return HttpResponseRedirect(url)
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
client_token = braintreestuff.get_client_token(r)
@@ -487,13 +487,13 @@ def upgrade_confirm_view(request,planid = 0):
@login_required()
def downgrade_confirm_view(request,planid = 0):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
try:
plan = PaidPlan.objects.get(id=planid)
except PaidPlan.DoesNotExist:
except PaidPlan.DoesNotExist: # pragma: no cover
messages.error(request,"Something went wrong. Please try again.")
url = reverse(billing_view)
return HttpResponseRedirect(url)
@@ -513,20 +513,20 @@ def downgrade_confirm_view(request,planid = 0):
@login_required()
def payment_confirm_view(request,planid = 0):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
try:
plan = PaidPlan.objects.get(id=planid)
except PaidPlan.DoesNotExist:
except PaidPlan.DoesNotExist: # pragma: no cover
messages.error(request,"Something went wrong. Please try again.")
url = reverse(billing_view)
return HttpResponseRedirect(url)
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
client_token = braintreestuff.get_client_token(r)
@@ -542,17 +542,17 @@ def payment_confirm_view(request,planid = 0):
@login_required()
def checkouts_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
if request.method != 'POST':
if request.method != 'POST': # pragma: no cover
url = reverse(paidplans_view)
return HttpResponseRedirect(url)
@@ -566,11 +566,11 @@ def checkouts_view(request):
baseurl = reverse(payment_completed_view),
amount = amount)
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
messages.error(request,"There was a problem with your payment")
url = reverse(billing_view)
return HttpResponseRedirect(url)
elif 'tac' not in request.POST:
elif 'tac' not in request.POST: # pragma: no cover
try:
planid = int(request.POST['plan'])
url = reverse('payment_confirm_view',kwargs={'planid':planid})
@@ -580,24 +580,24 @@ def checkouts_view(request):
messages.error(request,"There was an error in the payment form")
url = reverse('billing_view')
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
messages.error(request,"There was an error in the payment form")
url = reverse(billing_view)
return HttpResponseRedirect(url)
url = reverse(paidplans_view)
return HttpResponseRedirect(url)
url = reverse(paidplans_view) # pragma: no cover
return HttpResponseRedirect(url) # pragma: no cover
@login_required()
def upgrade_checkouts_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if request.method != 'POST':
if request.method != 'POST': # pragma: no cover
url = reverse(paidplans_view)
return HttpResponseRedirect(url)
@@ -611,12 +611,12 @@ def upgrade_checkouts_view(request):
baseurl = reverse(payment_completed_view),
amount = amount)
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
messages.error(request,"There was a problem with your payment")
url = reverse(upgrade_view)
return HttpResponseRedirect(url)
elif 'tac' not in request.POST:
elif 'tac' not in request.POST: # pragma: no cover
try:
planid = int(request.POST['plan'])
url = reverse('upgrade_confirm_view',kwargs={'planid':planid})
@@ -626,24 +626,24 @@ def upgrade_checkouts_view(request):
messages.error(request,"There was an error in the payment form")
url = reverse('billing_view')
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
messages.error(request,"There was an error in the payment form")
url = reverse(upgrade_view)
return HttpResponseRedirect(url)
url = reverse(paidplans_view)
return HttpResponseRedirect(url)
url = reverse(paidplans_view) # pragma: no cover
return HttpResponseRedirect(url) # pragma: no cover
@login_required()
def downgrade_checkouts_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
r = request.user.rower
if request.method != 'POST':
if request.method != 'POST': # pragma: no cover
url = reverse(paidplans_view)
return HttpResponseRedirect(url)
@@ -655,11 +655,11 @@ def downgrade_checkouts_view(request):
messages.info(request,"Your plan has been updated")
url = reverse(downgrade_completed_view)
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
messages.error(request,"There was a problem with your transaction")
url = reverse(upgrade_view)
return HttpResponseRedirect(url)
elif 'tac' not in request.POST:
elif 'tac' not in request.POST: # pragma: no cover
try:
planid = int(request.POST['plan'])
url = reverse('downgrade_confirm_view',kwargs={'planid':planid})
@@ -670,18 +670,18 @@ def downgrade_checkouts_view(request):
url = reverse('billing_view')
return HttpResponseRedirect(url)
else:
else: # pragma: no cover
messages.error(request,"There was an error in the payment form")
url = reverse(upgrade_view)
return HttpResponseRedirect(url)
url = reverse(paidplans_view)
return HttpResponseRedirect(url)
url = reverse(paidplans_view) # pragma: no cover
return HttpResponseRedirect(url) # pragma: no cover
@login_required()
def payment_completed_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
@@ -699,7 +699,7 @@ def payment_completed_view(request):
@login_required()
def downgrade_completed_view(request):
if not PAYMENT_PROCESSING_ON:
if not PAYMENT_PROCESSING_ON: # pragma: no cover
url = reverse('promembership')
return HttpResponseRedirect(url)
@@ -716,7 +716,7 @@ from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib.sites.shortcuts import get_current_site
from rowers.tokens import account_activation_token
# Email activation
def useractivate(request, uidb64, token):
def useractivate(request, uidb64, token): # pragma: no cover
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = User.objects.get(id=uid)
@@ -768,7 +768,7 @@ def useractivate(request, uidb64, token):
def rower_register_view(request):
nextpage = request.GET.get('next','/rowers/list-workouts/')
if nextpage == '':
if nextpage == '': # pragma: no cover
nextpage = '/rowers/list-workouts/'
if request.method == 'POST':
@@ -848,7 +848,7 @@ def rower_register_view(request):
return HttpResponseRedirect(nextpage)
# '/rowers/register/thankyou/')
else:
else: # pragma: no cover
return render(request,
"registration_form.html",
{'form':form,
@@ -861,10 +861,10 @@ def rower_register_view(request):
'next':nextpage,})
# User registration
def freecoach_register_view(request):
def freecoach_register_view(request): # pragma: no cover
nextpage = request.GET.get('next','/rowers/me/teams/')
if nextpage == '':
if nextpage == '': # pragma: no cover
nextpage = '/rowers/me/teams/'
if request.method == 'POST':
@@ -924,7 +924,7 @@ def freecoach_register_view(request):
return HttpResponseRedirect(nextpage)
else:
else: # pragma: no cover
return render(request,
"freecoach_registration_form.html",
{'form':form,
@@ -941,7 +941,7 @@ def freecoach_register_view(request):
@login_required()
@permission_required('rower.is_staff',fn=get_user_by_userid,raise_exception=True)
def transactions_view(request):
def transactions_view(request): # pragma: no cover
if not request.user.is_staff:
raise PermissionDenied("Not Allowed")
+1 -1
View File
@@ -1821,7 +1821,7 @@ def plannedsession_teamclone_view(request,id=0):
startdate__lte = startdate,
rowers = r,
enddate__gte = enddate)[0]
except IndexError:
except IndexError: # pragma: no cover
trainingplan = None
ps = get_object_or_404(PlannedSession,pk=id)
+73 -73
View File
@@ -293,7 +293,7 @@ def get_totals(workouts):
def allow_shares(view_func):
def sharify(request, *args, **kwargs):
shared = kwargs.get('__shared', None)
if shared is not None:
if shared is not None: # pragma: no cover
del kwargs["__shared"]
request.session['shared'] = True
return view_func(request, *args, **kwargs)
@@ -307,14 +307,14 @@ def sharedPage(request, key):
try:
try:
shareKey = ShareKey.objects.get(pk=key)
except:
except: # pragma: no cover
raise SharifyError
if shareKey.expired:
if shareKey.expired: # pragma: no cover
raise SharifyError
func, args, kwargs = resolve(shareKey.location)
kwargs["__shared"] = True
return func(request, *args, **kwargs)
except SharifyError:
except SharifyError: # pragma: no cover
raise Http404 # or add a more detailed error page. This either means that the key doesnt exist or is expired.
def createShareURL(request):
@@ -326,10 +326,10 @@ def createShareURL(request):
location = url)
key.save()
return render(request, 'share.html', {"key":key})
else:
else: # pragma: no cover
raise Http404
def createShareModel(request, model_id):
def createShareModel(request, model_id): # pragma: no cover
task = MyModel.objects.get(pk=model_id)
key = ShareKey.objects.create(pk=get_random_string(40),
expiration_seconds=60*60*24, # 1 day
@@ -353,7 +353,7 @@ def getfavorites(r,row):
matchworkouttypes = [workouttype,'all']
workoutsource = row.workoutsource
if 'speedcoach2' in row.workoutsource:
if 'speedcoach2' in row.workoutsource: # pragma: no cover
workoutsource = 'speedcoach2'
favorites = FavoriteChart.objects.filter(user=r,
@@ -370,7 +370,7 @@ def getfavorites(r,row):
return favorites,maxfav
def get_logo_by_pk(request,*args,**kwargs):
def get_logo_by_pk(request,*args,**kwargs): # pragma: no cover
id = kwargs['id']
return get_object_or_404(RaceLogo,pk=id)
@@ -378,7 +378,7 @@ def get_virtualevent_by_pk(request,*args,**kwargs):
id = kwargs['id']
return get_object_or_404(VirtualRace,pk=id)
def get_promember(request,*args,**kwargs):
def get_promember(request,*args,**kwargs): # pragma: no cover
return request.user
def get_course_by_pk(request,*args,**kwargs):
@@ -401,15 +401,15 @@ def get_plan_by_pk(request,*args,**kwargs):
id = kwargs['id']
return get_object_or_404(TrainingPlan,pk=id)
def get_macro_by_pk(request,*args,**kwargs):
def get_macro_by_pk(request,*args,**kwargs): # pragma: no cover
id = kwargs['id']
return get_object_or_404(TrainingMacroCycle,pk=id)
def get_meso_by_pk(request,*args,**kwargs):
def get_meso_by_pk(request,*args,**kwargs): # pragma: no cover
id = kwargs['id']
return get_object_or_404(TrainingMesoCycle,pk=id)
def get_micro_by_pk(request,*args,**kwargs):
def get_micro_by_pk(request,*args,**kwargs): # pragma: no cover
id = kwargs['id']
return get_object_or_404(TrainingMicroCycle,pk=id)
@@ -420,7 +420,7 @@ def get_workout_default_page(request,id):
r = Rower.objects.get(user=request.user)
if r.defaultlandingpage == 'workout_edit_view':
return reverse('workout_edit_view',kwargs={'id':id})
else:
else: # pragma: no cover
return reverse('workout_workflow_view',kwargs={'id':id})
def get_user_by_userid(*args,**kwargs):
@@ -436,7 +436,7 @@ def get_user_by_userid(*args,**kwargs):
u = get_object_or_404(User,pk=id)
return u
def get_user_by_id(*args,**kwargs):
def get_user_by_id(*args,**kwargs): # pragma: no cover
request = args[0]
try:
id = args[1]
@@ -448,7 +448,7 @@ def get_user_by_id(*args,**kwargs):
return get_object_or_404(User,pk=id)
def get_rower_by_id(request,id):
def get_rower_by_id(request,id): # pragma: no cover
u = User.objects.get(id=id)
return u.rower
@@ -474,14 +474,14 @@ def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
elif userid != 0:
u = User.objects.get(id=userid)
r = getrower(u)
elif request.user.is_anonymous:
elif request.user.is_anonymous: # pragma: no cover
return None
else:
r = getrower(request.user)
u = r.user
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover: # pragma: no cover
raise Http404("Rower doesn't exist")
if r.user == request.user:
@@ -520,21 +520,21 @@ def getrequestrowercoachee(request,rowerid=0,userid=0,notpermanent=False):
elif userid != 0:
u = User.objects.get(id=userid)
r = getrower(u)
elif request.user.is_anonymous:
elif request.user.is_anonymous: # pragma: no cover
return None
else:
r = getrower(request.user)
u = r.user
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover: # pragma: no cover
raise Http404("Rower doesn't exist")
if r.user == request.user:
request.session['rowerid'] = r.id
return r
if userid != 0 and not is_coach_user(request.user,u):
if userid != 0 and not is_coach_user(request.user,u): # pragma: no cover
request.session['rowerid'] = request.user.rower.id
raise PermissionDenied("You have no access to this user")
@@ -563,16 +563,16 @@ def getrequestplanrower(request,rowerid=0,userid=0,notpermanent=False):
elif userid != 0:
try:
u = User.objects.get(id=userid)
except User.DoesNotExist:
except User.DoesNotExist: # pragma: no cover: # pragma: no cover
raise Http404("User does not exist")
r = getrower(u)
else:
r = getrower(request.user)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover: # pragma: no cover
raise Http404("Rower doesn't exist")
if 'shared' in request.session and request.session['shared']:
if 'shared' in request.session and request.session['shared']: # pragma: no cover
return r
if r.user != request.user and not can_plan_user(request.user,r ):
@@ -589,12 +589,12 @@ def getrower(user):
try:
if user is None or user.is_anonymous:
return None
except AttributeError:
except AttributeError: # pragma: no cover
if User.objects.get(id=user).is_anonymous:
return None
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover:
r = Rower(user=user)
r.save()
@@ -605,7 +605,7 @@ def get_workout(id):
try:
id = encoder.decode_hex(id)
w = Workout.objects.get(id=id)
except Workout.DoesNotExist:
except Workout.DoesNotExist: # pragma: no cover:
raise Http404("Workout doesn't exist")
return w
@@ -614,15 +614,15 @@ def get_workoutuser(id,request):
try:
id = encoder.decode_hex(id)
w = Workout.objects.get(id=id)
except Workout.DoesNotExist:
except Workout.DoesNotExist: # pragma: no cover:
raise Http404("Workout doesn't exist")
if not is_workout_user(request.user,w):
if not is_workout_user(request.user,w): # pragma: no cover
raise PermissionDenied
return w
def getvalue(data):
def getvalue(data): # pragma: no cover
perc = 0
total = 1
done = 0
@@ -640,7 +640,7 @@ def getvalue(data):
return total,done,id,session_key
class SessionTaskListener(threading.Thread):
class SessionTaskListener(threading.Thread): # pragma: no cover
def __init__(self, r, channels):
threading.Thread.__init__(self)
self.redis = r
@@ -685,7 +685,7 @@ from rq.job import Job
try:
from rest_framework_swagger.views import get_swagger_view
except ImportError:
except ImportError: # pragma: no cover
pass
from rest_framework.renderers import JSONRenderer
@@ -694,7 +694,7 @@ from rest_framework.response import Response
from rowers.serializers import RowerSerializer,WorkoutSerializer
try:
from rest_framework import status,permissions,generics
except ImportError:
except ImportError: # pragma: no cover
pass
from rest_framework.decorators import api_view, renderer_classes, permission_classes
@@ -723,10 +723,10 @@ from rowers.celery import result as celery_result
# Define the API documentation
try:
schema_view = get_swagger_view(title='Rowsandall API')
except NameError:
except NameError: # pragma: no cover
pass
def remove_asynctask(request,id):
def remove_asynctask(request,id): # pragma: no cover
try:
oldtasks = request.session['async_tasks']
except KeyError:
@@ -739,7 +739,7 @@ def remove_asynctask(request,id):
request.session['async_tasks'] = newtasks
def get_job_result(jobid):
def get_job_result(jobid): # pragma: no cover
if settings.TESTING:
return None
elif settings.CELERY:
@@ -771,7 +771,7 @@ verbose_job_status = {
'submit_race': 'Checking Race Course Result',
}
def get_job_status(jobid):
def get_job_status(jobid): # pragma: no cover
if settings.TESTING:
summary = {
'status': 'failed',
@@ -836,7 +836,7 @@ def get_job_status(jobid):
return summary
def kill_async_job(request,id='aap'):
def kill_async_job(request,id='aap'): # pragma: no cover
if settings.CELERY:
job = celery_result.AsyncResult(id)
job.revoke()
@@ -853,7 +853,7 @@ def kill_async_job(request,id='aap'):
return HttpResponseRedirect(url)
@login_required()
def raise_500(request):
def raise_500(request): # pragma: no cover
if request.user.is_superuser:
raise ValueError
else:
@@ -895,7 +895,7 @@ def raise_500(request):
# return HttpResponseRedirect(url)
@csrf_exempt
def post_progress(request,id=None,value=0):
def post_progress(request,id=None,value=0): # pragma: no cover
if request.method == 'POST':
try:
secret = request.POST['secret']
@@ -924,7 +924,7 @@ def post_progress(request,id=None,value=0):
else: # request method is not POST
return HttpResponse('GET method not allowed',status=405)
def get_all_queued_jobs(userid=0):
def get_all_queued_jobs(userid=0): # pragma: no cover
r = StrictRedis()
jobs = []
@@ -969,7 +969,7 @@ def get_stored_tasks_status(request):
taskids = []
taskstatus = []
for id,func_name in reversed(taskids):
for id,func_name in reversed(taskids): # pragma: no cover
progress = 0
try:
cached_progress = cache.get(id)
@@ -1027,13 +1027,13 @@ def get_thumbnails(request,id):
try:
if charts[0]['script'] == '':
charts = []
except IndexError:
except IndexError: # pragma: no cover
charts = []
return JSONResponse(charts)
def get_blog_posts(request):
def get_blog_posts(request): # pragma: no cover
blogposts = BlogPost.objects.all().order_by("-date")
jsondata = []
@@ -1049,7 +1049,7 @@ def get_blog_posts(request):
return JSONResponse(jsondata)
def get_blog_posts_old(request):
def get_blog_posts_old(request): # pragma: no cover
try:
response = requests.get(
'https://analytics.rowsandall.com/wp-json/wp/v2/posts?per_page=3')
@@ -1116,12 +1116,12 @@ def rowhascoordinates(row):
try:
latitude = rowdata.df[' latitude']
if not latitude.std():
if not latitude.std(): # pragma: no cover
hascoordinates = 0
except (KeyError,AttributeError):
hascoordinates = 0
else:
else: # pragma: no cover
hascoordinates = 0
return hascoordinates
@@ -1130,13 +1130,13 @@ def rowhascoordinates(row):
# Wrapper around the rowingdata call to catch some exceptions
# Checks for CSV file, then for gzipped CSV file, and if all fails, returns 0
def rdata(csvfile=None,rower=rrower()):
if csvfile is None:
if csvfile is None: # pragma: no cover
return 0
try:
res = rrdata(csvfile=csvfile,rower=rower)
except pd.errors.EmptyDataError:
except pd.errors.EmptyDataError: # pragma: no cover
res = 0
except (IOError, IndexError, EOFError,FileNotFoundError):
except (IOError, IndexError, EOFError,FileNotFoundError): # pragma: no cover
try:
res = rrdata(csvfile=file+'.gz',rower=rower)
except (IOError, IndexError, EOFError,FileNotFoundError):
@@ -1150,7 +1150,7 @@ def get_my_teams(user):
therower = Rower.objects.get(user=user)
try:
teams1 = therower.team.all()
except AttributeError:
except AttributeError: # pragma: no cover
teams1 = []
teams2 = Team.objects.filter(manager=user)
@@ -1167,7 +1167,7 @@ def get_time(second):
minutes=0
sec=0
microsecond = 0
elif math.isnan(second):
elif math.isnan(second): # pragma: no cover
hours = 0
minutes=0
sec=0
@@ -1182,12 +1182,12 @@ def get_time(second):
# get the workout ID from the SportTracks URI
def getidfromsturi(uri,length=8):
def getidfromsturi(uri,length=8): # pragma: no cover
return uri[len(uri)-length:]
import re
def getidfromuri(uri):
def getidfromuri(uri): # pragma: no cover
m = re.search('/(\w.*)\/(\d+)',uri)
return m.group(2)
@@ -1197,7 +1197,7 @@ from rowers.utils import (
geo_distance,serialize_list,deserialize_list,uniqify,
str2bool,range_to_color_hex,absolute,myqueue,get_call,
calculate_age,rankingdistances,rankingdurations,
is_ranking_piece,my_dict_from_instance,wavg,NoTokenError,
my_dict_from_instance,wavg,NoTokenError,
request_is_ajax
)
@@ -1208,12 +1208,12 @@ def iscoachmember(user):
if not user.is_anonymous:
try:
r = Rower.objects.get(user=user)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover:
r = Rower(user=user)
r.save()
result = user.is_authenticated and ('coach' in r.rowerplan)
else:
else: # pragma: no cover
result = False
return result
@@ -1256,7 +1256,7 @@ def sendmail(request):
success = response.json().get('success')
form = EmailForm(request.POST)
if form.is_valid() and success:
if form.is_valid() and success: # pragma: no cover
firstname = form.cleaned_data['firstname']
lastname = form.cleaned_data['lastname']
email = form.cleaned_data['email']
@@ -1271,7 +1271,7 @@ def sendmail(request):
else:
if not success:
messages.error(request,'Bots are not welcome')
else:
else: # pragma: no cover
messages.error(request,'Something went wrong. Please try again')
return HttpResponseRedirect('/rowers/email/')
else:
@@ -1285,41 +1285,41 @@ def add_workout_from_strokedata(user,importid,data,strokedata,
workoutsource='concept2'):
try:
workouttype = data['type']
except KeyError:
except KeyError: # pragma: no cover
workouttype = 'rower'
if workouttype not in [x[0] for x in Workout.workouttypes]:
if workouttype not in [x[0] for x in Workout.workouttypes]: # pragma: no cover
workouttype = 'other'
try:
comments = data['comments']
except:
except: # pragma: no cover
comments = ' '
# comments = "Imported data \n %s" % comments
# comments = "Imported data \n"+comments # str(comments)
try:
thetimezone = tz(data['timezone'])
except:
except: # pragma: no cover
thetimezone = 'UTC'
r = getrower(user)
try:
rowdatetime = iso8601.parse_date(data['date_utc'])
except KeyError:
except KeyError: # pragma: no cover
rowdatetime = iso8601.parse_date(data['start_date'])
except ParseError:
except ParseError: # pragma: no cover
rowdatetime = iso8601.parse_date(data['date'])
try:
c2intervaltype = data['workout_type']
except KeyError:
except KeyError: # pragma: no cover
c2intervaltype = ''
try:
title = data['name']
except KeyError:
except KeyError: # pragma: no cover
title = ""
try:
t = data['comments'].split('\n', 1)[0]
@@ -1339,7 +1339,7 @@ def add_workout_from_strokedata(user,importid,data,strokedata,
nr_rows = len(unixtime)
try:
try: # pragma: no cover
latcoord = strokedata.loc[:,'lat']
loncoord = strokedata.loc[:,'lon']
except:
@@ -1356,7 +1356,7 @@ def add_workout_from_strokedata(user,importid,data,strokedata,
try:
spm = strokedata.loc[:,'spm']
except KeyError:
except KeyError: # pragma: no cover
spm = 0*dist2
try:
@@ -1413,10 +1413,10 @@ def add_workout_from_strokedata(user,importid,data,strokedata,
try:
totaldist = data['distance']
totaltime = data['time']/10.
except KeyError:
except KeyError: # pragma: no cover
totaldist = 0
totaltime = 0
else:
else: # pragma: no cover
totaldist = 0
totaltime = 0
@@ -1438,7 +1438,7 @@ def add_workout_from_strokedata(user,importid,data,strokedata,
def keyvalue_get_default(key,options,def_options):
def keyvalue_get_default(key,options,def_options): # pragma: no cover
try:
return options[key]
@@ -1449,14 +1449,14 @@ def keyvalue_get_default(key,options,def_options):
# Creates unix time stamp from a datetime object
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))):
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))): # pragma: no cover
td = dt - epoch
# return td.total_seconds()
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
# Check if a column of a dataframe has the required (aantal)
# number of elements. Also checks if the column is a numerical type
# Replaces any faulty columns with zeros
def trydf(df,aantal,column):
def trydf(df,aantal,column): # pragma: no cover
try:
s = df[column]
if len(s) != aantal:
+34 -34
View File
@@ -49,11 +49,11 @@ def team_view(request,team_id=0,userid=0):
teams.send_invite_email(inviteid)
successmessage = text
messages.info(request,successmessage)
else:
else: # pragma: no cover
message = text
messages.error(request,message)
groupmessageform = TeamMessageForm()
elif request.method == 'POST' and request.user == t.manager and 'message' in request.POST:
elif request.method == 'POST' and request.user == t.manager and 'message' in request.POST: # pragma: no cover
groupmessageform = TeamMessageForm(request.POST)
inviteform = TeamInviteForm()
if groupmessageform.is_valid():
@@ -110,7 +110,7 @@ def team_view(request,team_id=0,userid=0):
def team_leaveconfirm_view(request,id=0):
try:
t = Team.objects.get(id=id)
except Team.DoesNotExist:
except Team.DoesNotExist: # pragma: no cover # pragma: no cover
raise Http404("Team doesn't exist")
myteams, memberteams, otherteams = get_teams(request)
@@ -181,7 +181,7 @@ def get_teams(request):
return myteams, memberteams, otherteams
@login_required()
def rower_teams_view(request):
def rower_teams_view(request): # pragma: no cover
if request.method == 'POST':
form = TeamInviteCodeForm(request.POST)
if form.is_valid():
@@ -239,7 +239,7 @@ def rower_teams_view(request):
user__in=invitedathletes).exclude(
user=request.user
).exclude(coachinggroups__in=[request.user.rower.mycoachgroup])
elif request.user.rower.rowerplan == 'freecoach':
elif request.user.rower.rowerplan == 'freecoach': # pragma: no cover
potentialathletes = Rower.objects.filter(
team__in=myteams).exclude(
user__in=invitedathletes).exclude(
@@ -295,7 +295,7 @@ def invitation_revoke_view(request,id):
if res:
messages.info(request,text)
successmessage = text
else:
else: # pragma: no cover
message = text
messages.error(request,text)
@@ -310,7 +310,7 @@ def manager_member_drop_view(request,teamid,userid,
res, text = teams.mgr_remove_member(teamid,request.user,rower)
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse(rower_teams_view)
@@ -321,7 +321,7 @@ def manager_member_drop_view(request,teamid,userid,
def manager_requests_view(request,code=None):
if code:
res,text = teams.process_request_code(request.user,code)
if res:
if res: # pragma: no cover
messages.info(request,text)
else:
messages.error(request,text)
@@ -335,9 +335,9 @@ def athlete_drop_coach_confirm_view(request,id):
r = getrower(request.user)
try:
coach = Rower.objects.get(id=id)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover # pragma: no cover
raise Http404("This rower doesn't exist")
if coach not in teams.rower_get_coaches(r):
if coach not in teams.rower_get_coaches(r): # pragma: no cover
raise PermissionDenied("You are not allowed to do this")
breadcrumbs = [
@@ -362,9 +362,9 @@ def coach_drop_athlete_confirm_view(request,id):
r = getrower(request.user)
try:
rower = Rower.objects.get(id=id)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover # pragma: no cover
raise Http404("This rower doesn't exist")
if rower not in teams.coach_getcoachees(r):
if rower not in teams.coach_getcoachees(r): # pragma: no cover
raise PermissionDenied("You are not allowed to do this")
breadcrumbs = [
@@ -389,16 +389,16 @@ def coach_drop_athlete_view(request,id):
r = getrower(request.user)
try:
rower = Rower.objects.get(id=id)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
raise Http404("This rower doesn't exist")
if rower not in teams.coach_getcoachees(r):
if rower not in teams.coach_getcoachees(r): # pragma: no cover
raise PermissionDenied("You are not allowed to do this")
res,text = teams.coach_remove_athlete(r,rower)
if res:
messages.info(request,'You are not coaching this athlete any more')
else:
else: # pragma: no cover
messages.error(request,'There was an error dropping the athlete from your list')
url = reverse('rower_teams_view')
@@ -410,16 +410,16 @@ def athlete_drop_coach_view(request,id):
r = getrower(request.user)
try:
coach = Rower.objects.get(id=id)
except Rower.DoesNotExist:
except Rower.DoesNotExist: # pragma: no cover
raise Http404("This coach doesn't exist")
if coach not in teams.rower_get_coaches(r):
if coach not in teams.rower_get_coaches(r): # pragma: no cover
raise PermissionDenied("You are not allowed to do this")
res,text = teams.coach_remove_athlete(coach,r)
if res:
messages.info(request,'Removal successful')
else:
else: # pragma: no cover
messages.error(request,'There was an error dropping the coach from your list')
url = reverse('rower_teams_view')
@@ -430,7 +430,7 @@ def athlete_drop_coach_view(request,id):
def team_requestmembership_view(request,teamid,userid):
try:
t = Team.objects.get(id=teamid)
except Team.DoesNotExist:
except Team.DoesNotExist: # pragma: no cover
raise Http404("Team doesn't exist")
r = getrequestrower(request,userid=userid)
@@ -446,7 +446,7 @@ def team_requestmembership_view(request,teamid,userid):
res,text = teams.create_request(t,userid)
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
@@ -467,9 +467,9 @@ def request_coaching_view(request,coachid):
res,text = teams.create_coaching_request(coach,request.user)
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
else:
else: # pragma: no cover
messages.error(request,'That person is not a coach')
url = reverse('rower_teams_view')
@@ -480,7 +480,7 @@ def request_coaching_view(request,coachid):
def offer_coaching_view(request,userid):
try:
u = User.objects.get(id=userid)
except User.DoesNotExist:
except User.DoesNotExist: # pragma: no cover
raise Http404("This user doesn't exist")
coach = getrequestrower(request)
@@ -489,7 +489,7 @@ def offer_coaching_view(request,userid):
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse('rower_teams_view')
@@ -502,7 +502,7 @@ def reject_revoke_coach_request(request,id=0):
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse('rower_teams_view')
@@ -515,7 +515,7 @@ def reject_revoke_coach_offer(request,id=0):
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse('rower_teams_view')
@@ -529,7 +529,7 @@ def request_revoke_view(request,id=0):
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse(rower_teams_view)
@@ -542,7 +542,7 @@ def request_reject_view(request,id=0):
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse(rower_teams_view)
@@ -555,7 +555,7 @@ def invitation_reject_view(request,id=0):
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse(rower_teams_view)
@@ -568,7 +568,7 @@ def rower_invitations_view(request,code=None,message='',successmessage=''):
if code:
teams.remove_expired_invites()
res,text = teams.process_invite_code(request.user,code)
if res:
if res: # pragma: no cover
messages.info(request,text)
teamid=res
url = reverse(team_view,kwargs={
@@ -591,7 +591,7 @@ def team_edit_view(request, team_id=0):
t = get_object_or_404(Team,pk=team_id)
if request.method == 'POST':
if request.method == 'POST': # pragma: no cover
teamcreateform = TeamForm(request.POST,instance=t)
if teamcreateform.is_valid():
cd = teamcreateform.cleaned_data
@@ -666,7 +666,7 @@ def team_create_view(request):
res,message=teams.create_team(name,manager,private,notes,
viewing)
if not res:
if not res: # pragma: no cover
messages.error(request,message)
url = reverse('paidplans_view')
return HttpResponseRedirect(url)
@@ -792,7 +792,7 @@ def rower_accept_coachoffer_view(request,code=None):
res, text = teams.process_coachoffer_code(request.user,code)
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse('rower_teams_view')
@@ -804,7 +804,7 @@ def coach_accept_coachrequest_view(request,code=None):
res, text = teams.process_coachrequest_code(request.user.rower,code)
if res:
messages.info(request,text)
else:
else: # pragma: no cover
messages.error(request,text)
url = reverse('rower_teams_view')
+21 -21
View File
@@ -16,7 +16,7 @@ def deactivate_user(request):
if user_form.is_valid():
if not user_form.cleaned_data['is_active']:
r = Rower.objects.get(user=user)
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
try:
subscriptions = braintreestuff.find_subscriptions(r)
for subscription in subscriptions:
@@ -44,7 +44,7 @@ def deactivate_user(request):
return render(request, "userprofile_deactivate.html", {
"user_form": user_form,
})
else:
else: # pragma: no cover
raise PermissionDenied
@login_required()
@@ -54,7 +54,7 @@ def user_gdpr_optin(request):
r.gdproptindate = None
r.save()
nexturl = request.GET.get('next','/rowers/list-workouts/')
if r.gdproptin:
if r.gdproptin: # pragma: no cover
return HttpResponseRedirect(nexturl)
return render(request,'gdpr_optin.html',{
@@ -88,7 +88,7 @@ def remove_user(request):
email = user.email
r = Rower.objects.get(user=user)
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
try:
subscriptions = braintreestuff.find_subscriptions(r)
for subscription in subscriptions:
@@ -115,12 +115,12 @@ def remove_user(request):
return render(request, "userprofile_delete.html", {
"user_form": user_form,
})
else:
else: # pragma: no cover
raise PermissionDenied
@login_required()
def survey(request):
def survey(request): # pragma: no cover
r = getrower(request.user)
@@ -148,7 +148,7 @@ def survey(request):
def start_trial_view(request):
r = getrower(request.user)
if not can_start_trial(request.user):
if not can_start_trial(request.user): # pragma: no cover
messages.error(request,'You do not qualify for a trial')
url = '/rowers/paidplans'
return HttpResponseRedirect(url)
@@ -182,7 +182,7 @@ def start_trial_view(request):
def start_plantrial_view(request):
r = getrower(request.user)
if not can_start_plantrial(request.user):
if not can_start_plantrial(request.user): # pragma: no cover
messages.error(request,'You do not qualify for a trial')
url = '/rowers/paidplans'
return HttpResponseRedirect(url)
@@ -239,7 +239,7 @@ def rower_favoritecharts_view(request,userid=0):
if aantal==0:
FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=1)
if request.method == 'POST' and 'staticgrids' in request.POST:
if request.method == 'POST' and 'staticgrids' in request.POST: # pragma: no cover
staticchartform = StaticChartRowerForm(request.POST,instance=r)
if staticchartform.is_valid():
r.staticgrids = staticchartform.cleaned_data.get('staticgrids')
@@ -252,7 +252,7 @@ def rower_favoritecharts_view(request,userid=0):
r.usersmooth = staticchartform.cleaned_data.get('usersmooth')
r.save()
if request.method == 'POST' and 'save_data' in request.POST:
if request.method == 'POST' and 'save_data' in request.POST: # pragma: no cover
datasettingsform = DataRowerForm(request.POST,instance=r)
if datasettingsform.is_valid():
cd = datasettingsform.cleaned_data
@@ -262,7 +262,7 @@ def rower_favoritecharts_view(request,userid=0):
r.save()
messages.info(request,"We have updated your data settings")
if request.method == 'POST' and 'defaults_data' in request.POST:
if request.method == 'POST' and 'defaults_data' in request.POST: # pragma: no cover
defaultsmooth = Rower._meta.get_field('dosmooth').get_default()
defaultautojoin = Rower._meta.get_field('autojoin').get_default()
defaultergcalcpower = Rower._meta.get_field('erg_recalculatepower').get_default()
@@ -273,7 +273,7 @@ def rower_favoritecharts_view(request,userid=0):
datasettingsform = DataRowerForm(instance=r)
messages.info(request,"We have reset your data settings to the default values")
if request.method == 'POST' and 'form-TOTAL_FORMS' in request.POST:
if request.method == 'POST' and 'form-TOTAL_FORMS' in request.POST: # pragma: no cover
favorites_formset = FavoriteChartFormSet(request.POST)
if favorites_formset.is_valid():
new_instances = []
@@ -344,7 +344,7 @@ def rower_exportsettings_view(request,userid=0):
form = RowerExportForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
if r.rowerplan == 'basic':
if r.rowerplan == 'basic': # pragma: no cover
messages.error(request,'These settings can only be set if you are a user on one of the <a href="/rowers/paidplans">paid plans</a>.')
for attr, value in cd.items():
@@ -355,7 +355,7 @@ def rower_exportsettings_view(request,userid=0):
doset = False
except KeyError:
doset = True
if r.rowerplan == 'basic':
if r.rowerplan == 'basic': # pragma: no cover
doset = False
if not doset:
before = getattr(r,attr)
@@ -426,7 +426,7 @@ def rower_edit_view(request,rowerid=0,userid=0,message=""):
sex = cd['sex']
try:
offercoaching = cd['offercoaching']
except KeyError:
except KeyError: # pragma: no cover
offercoaching = False
autojoin = cd['autojoin']
adaptiveclass = cd['adaptiveclass']
@@ -440,7 +440,7 @@ def rower_edit_view(request,rowerid=0,userid=0,message=""):
fav_analysis = cd['fav_analysis']
usersmooth = cd['usersmooth']
u = r.user
if u.email != email and len(email):
if u.email != email and len(email): # pragma: no cover
resetbounce = True
else:
resetbounce = False
@@ -470,7 +470,7 @@ def rower_edit_view(request,rowerid=0,userid=0,message=""):
r.usersmooth = usersmooth
if resetbounce and r.emailbounced:
if resetbounce and r.emailbounced: # pragma: no cover
r.emailbounced = False
r.save()
@@ -559,7 +559,7 @@ def rower_prefs_view(request,userid=0,message=""):
if powerform.is_valid():
cd = powerform.cleaned_data
hrftp = cd['hrftp']
if hrftp == 0:
if hrftp == 0: # pragma: no cover
hrftp = int((r.an+r.tr)/2.)
ftp = cd['ftp']
otwslack = cd['otwslack']
@@ -607,7 +607,7 @@ def rower_prefs_view(request,userid=0,message=""):
r.save()
successmessage = "Your Power Zone data were changed"
messages.info(request,successmessage)
elif request.method == 'POST' and 'cprange' in request.POST:
elif request.method == 'POST' and 'cprange' in request.POST: # pragma: no cover
cpform = RowerCPForm(request.POST)
if cpform.is_valid():
cd = cpform.cleaned_data
@@ -638,7 +638,7 @@ def rower_prefs_view(request,userid=0,message=""):
# this views is called when you press a button on the User edit page
# the button is only there when you have granted access to an app
@login_required()
def rower_revokeapp_view(request,id=0):
def rower_revokeapp_view(request,id=0): # pragma: no cover
try:
tokens = AccessToken.objects.filter(user=request.user,application=id)
refreshtokens = AccessToken.objects.filter(user=request.user,application=id)
@@ -662,7 +662,7 @@ def rower_update_empower_view(
request,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now()
):
): # pragma: no cover
try:
r = getrower(request.user)
except Rower.DoesNotExist:
+8 -8
View File
@@ -35,12 +35,12 @@ def get_weather_data(long,lat,unixtime):
try:
s = requests.get(url)
except ConnectionError:
except ConnectionError: # pragma: no cover
return 0
if s.ok:
return s.json()
else:
else: # pragma: no cover
return 0
# Get Metar data
@@ -56,12 +56,12 @@ def get_metar_data(airportcode,unixtime):
try:
s = requests.get(url)
except:
except: # pragma: no cover
message = 'Failed to download METAR data'
return [0,0,message,'','']
if s.ok:
if s.ok: # pragma: no cover
try:
doc = etree.fromstring(s.content)
except AttributeError:
@@ -99,8 +99,8 @@ def get_metar_data(airportcode,unixtime):
return [wind_ms,windbearing,message,rawtext,timestamp]
message = 'Failed to download METAR data'
return [0,0,message,'',timestamp]
message = 'Failed to download METAR data' # pragma: no cover
return [0,0,message,'',timestamp] # pragma: no cover
# Get wind data (and translate from knots to m/s)
@@ -108,7 +108,7 @@ def get_wind_data(lat,long,unixtime):
data = get_weather_data(lat,long,unixtime)
summary = ''
temperature = 20
if data:
if data: # pragma: no cover
try:
# we are getting wind in mph
windspeed = data['currently']['windSpeed']*0.44704
@@ -157,7 +157,7 @@ def get_wind_data(lat,long,unixtime):
message = 'Summary for your location at '+timestamp+': '+summary
message += '. Temperature '+str(temperature)+'F/'+str(temperaturec)+'C'
if data:
if data: # pragma: no cover
message += '. Wind: '+str(windspeed)+' m/s. Wind Bearing: '+str(windbearing)+' degrees'
+21 -20
View File
@@ -60,8 +60,8 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'suit',
'suit_rq',
# 'suit',
# 'suit_rq',
'leaflet',
'django_rq',
# 'django_rq_dashboard',
@@ -98,7 +98,7 @@ MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
# 'django.middleware.locale.LocaleMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
@@ -265,11 +265,11 @@ LOGOUT_REDIRECT_URL = '/'
PROGRESS_CACHE_SECRET = CFG['progress_cache_secret']
try:
UPLOAD_SERVICE_URL = CFG['upload_service_url']
except KeyError:
except KeyError: # pragma: no cover
UPLOAD_SERVICE_URL = "http://localhost:8000/rowers/workout/api/upload/"
try:
UPLOAD_SERVICE_SECRET = CFG['upload_service_secret']
except KeyError:
except KeyError: # pragma: no cover
UPLOAD_SERVICE_SECRET = "FoYezZWLSyfAVimumpHEeYsJjsNCerxV"
# Concept 2
@@ -333,6 +333,7 @@ NK_CLIENT_ID = CFG["nk_client_id"]
NK_CLIENT_SECRET = CFG["nk_client_secret"]
NK_REDIRECT_URI = CFG["nk_redirect_uri"]
NK_API_LOCATION = CFG["nk_api_location"]
NK_OAUTH_LOCATION = CFG["nk_oauth_location"]
NK_VIEWER_LOCATION = CFG["nk_viewer_location"]
# Full Site URL
@@ -507,75 +508,75 @@ except KeyError:
try:
BRAINTREE_MERCHANT_ID = CFG['braintree_merchant_id']
except KeyError:
except KeyError: # pragma: no cover
BRAINTREE_MERCHANT_ID = ''
try:
BRAINTREE_MERCHANT_ACCOUNT_ID = CFG['braintree_merchant_account_id']
except KeyError:
except KeyError: # pragma: no cover
BRAINTREE_MERCHANT_ACCOUNT_ID = 'rowsandallEUR'
try:
BRAINTREE_PUBLIC_KEY = CFG['braintree_public_key']
except KeyError:
except KeyError: # pragma: no cover
BRAINTREE_PUBLIC_KEY = ''
try:
BRAINTREE_PRIVATE_KEY = CFG['braintree_private_key']
except KeyError:
except KeyError: # pragma: no cover
BRAINTREE_PRIVATE_KEY = ''
try:
BRAINTREE_SANDBOX_MERCHANT_ID = CFG['braintree_sandbox_merchant_id']
except KeyError:
except KeyError: # pragma: no cover
BRAINTREE_SANDBOX_MERCHANT_ID = ''
try:
BRAINTREE_SANDBOX_PUBLIC_KEY = CFG['braintree_sandbox_public_key']
except KeyError:
except KeyError: # pragma: no cover
BRAINTREE_SANDBOX_PUBLIC_KEY = ''
try:
BRAINTREE_SANDBOX_PRIVATE_KEY = CFG['braintree_sandbox_private_key']
except KeyError:
except KeyError: # pragma: no cover
BRAINTREE_SANDBOX_PRIVATE_KEY = ''
try:
PAYMENT_PROCESSING_ON = CFG['payment_processing_on']
except KeyError:
except KeyError: # pragma: no cover
PAYMENT_PROCESSING_ON = False
try:
FAKTUROID_API_KEY = CFG['fakturoid_api_key']
except KeyError:
except KeyError: # pragma: no cover
FAKTUROID_API_KEY = ''
try:
FAKTUROID_EMAIL = CFG['fakturoid_email']
except KeyError:
except KeyError: # pragma: no cover
FAKTUROID_EMAIL = ''
try:
FAKTUROID_SLUG = CFG['fakturoid_slug']
except KeyError:
except KeyError: # pragma: no cover
FAKTUROID_SLUG = ''
# ID obfuscation
try:
OPAQUE_SECRET_KEY = CFG['opaque_secret_key']
except KeyError:
except KeyError: # pragma: no cover
OPAQUE_SECRET_KEY = 0xa193443a
# Celery or RQ
try:
CELERY = CFG['use_celery']
except KeyError:
except KeyError: # pragma: no cover
CELERY = False
try:
WORKOUTS_FIT_TOKEN = CFG['workouts_fit_token']
WORKOUTS_FIT_URL = CFG['workouts_fit_url']
except KeyError:
except KeyError: # pragma: no cover
WORKOUTS_FIT_TOKEN = 'aapnootmies'
WORKOUTS_FIT_URL = 'http://localhost:50053/tojson'
@@ -584,7 +585,7 @@ except KeyError:
try:
RECAPTCHA_SITE_KEY = CFG['recaptcha_site_key']
RECAPTCHA_SITE_SECRET = CFG['recaptcha_site_secret']
except KeyError:
except KeyError: # pragma: no cover
RECAPTCHA_SITE_KEY = ''
RECAPTCHA_SITE_SECRET = ''
+1 -1
View File
@@ -14,7 +14,7 @@ import sys
try:
use_sqlite = CFG['use_sqlite']
except KeyError:
except KeyError: # pragma: no cover
use_sqlite = False
if 'test' in sys.argv:
+1 -1
View File
@@ -100,7 +100,7 @@ urlpatterns += [
# monkey patch workaround for bug in recurrence library
django.views.i18n.javascript_catalog = None
if settings.DEBUG:
if settings.DEBUG: # pragma: no cover
import debug_toolbar
import django
urlpatterns += [
+2 -2
View File
@@ -16,12 +16,12 @@ def landingview(request):
'landingpage.html',
)
def logoview(request):
def logoview(request): # pragma: no cover
image_data = open(settings.STATIC_ROOT+"/img/apple-icon-144x144.png", "rb").read()
return HttpResponse(image_data, content_type="image/png")
def rootview(request):
def rootview(request): # pragma: no cover
magicsentence = rmain()
loginform = LoginForm()
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

+1 -1
View File
@@ -9,7 +9,7 @@ from django.utils import timezone
from rowers.database import *
import datetime
def current_day():
def current_day(): # pragma: no cover
return (datetime.datetime.now(tz=timezone.utc)).date()
class Response(models.Model):