Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-proctoring
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
edx-proctoring
Commits
45b715b3
Commit
45b715b3
authored
Jul 31, 2015
by
chrisndodge
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #51 from edx/cdodge/update-timeout-status
Cdodge/update timeout status
parents
dd9d8b51
e71f7188
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
70 additions
and
17 deletions
+70
-17
edx_proctoring/api.py
+44
-15
edx_proctoring/tests/test_api.py
+26
-2
No files found.
edx_proctoring/api.py
View file @
45b715b3
...
@@ -168,13 +168,53 @@ def remove_allowance_for_user(exam_id, user_id, key):
...
@@ -168,13 +168,53 @@ def remove_allowance_for_user(exam_id, user_id, key):
student_allowance
.
delete
()
student_allowance
.
delete
()
def
_update_exam_attempt_status
(
attempt
):
"""
Helper method to see if the status of an
exam needs to be updated, e.g. timeout
"""
if
not
attempt
:
return
attempt
# right now the only adjustment to
# status is transitioning to timeout
has_started_exam
=
(
attempt
and
attempt
.
get
(
'started_at'
)
and
attempt
.
get
(
'status'
)
==
ProctoredExamStudentAttemptStatus
.
started
)
if
has_started_exam
:
now_utc
=
datetime
.
now
(
pytz
.
UTC
)
expires_at
=
attempt
[
'started_at'
]
+
timedelta
(
minutes
=
attempt
[
'allowed_time_limit_mins'
])
has_time_expired
=
now_utc
>
expires_at
if
has_time_expired
:
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt_by_id
(
attempt
[
'id'
])
exam_attempt_obj
.
status
=
ProctoredExamStudentAttemptStatus
.
timed_out
exam_attempt_obj
.
save
()
attempt
=
ProctoredExamStudentAttemptSerializer
(
exam_attempt_obj
)
.
data
return
attempt
def
_get_exam_attempt
(
exam_attempt_obj
):
"""
Helper method to commonalize the two query patterns
"""
serialized_attempt_obj
=
ProctoredExamStudentAttemptSerializer
(
exam_attempt_obj
)
attempt
=
serialized_attempt_obj
.
data
if
exam_attempt_obj
else
None
attempt
=
_update_exam_attempt_status
(
attempt
)
return
attempt
def
get_exam_attempt
(
exam_id
,
user_id
):
def
get_exam_attempt
(
exam_id
,
user_id
):
"""
"""
Return an existing exam attempt for the given student
Return an existing exam attempt for the given student
"""
"""
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt
(
exam_id
,
user_id
)
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt
(
exam_id
,
user_id
)
serialized_attempt_obj
=
ProctoredExamStudentAttemptSerializer
(
exam_attempt_obj
)
return
_get_exam_attempt
(
exam_attempt_obj
)
return
serialized_attempt_obj
.
data
if
exam_attempt_obj
else
None
def
get_exam_attempt_by_id
(
attempt_id
):
def
get_exam_attempt_by_id
(
attempt_id
):
...
@@ -182,8 +222,7 @@ def get_exam_attempt_by_id(attempt_id):
...
@@ -182,8 +222,7 @@ def get_exam_attempt_by_id(attempt_id):
Return an existing exam attempt for the given student
Return an existing exam attempt for the given student
"""
"""
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt_by_id
(
attempt_id
)
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt_by_id
(
attempt_id
)
serialized_attempt_obj
=
ProctoredExamStudentAttemptSerializer
(
exam_attempt_obj
)
return
_get_exam_attempt
(
exam_attempt_obj
)
return
serialized_attempt_obj
.
data
if
exam_attempt_obj
else
None
def
update_exam_attempt
(
attempt_id
,
**
kwargs
):
def
update_exam_attempt
(
attempt_id
,
**
kwargs
):
...
@@ -551,20 +590,10 @@ def get_student_view(user_id, course_id, content_id,
...
@@ -551,20 +590,10 @@ def get_student_view(user_id, course_id, content_id,
attempt
=
get_exam_attempt
(
exam_id
,
user_id
)
attempt
=
get_exam_attempt
(
exam_id
,
user_id
)
has_started_exam
=
attempt
and
attempt
.
get
(
'started_at'
)
has_started_exam
=
attempt
and
attempt
.
get
(
'started_at'
)
has_time_expired
=
False
if
has_started_exam
:
if
has_started_exam
:
if
attempt
.
get
(
'status'
)
==
'error'
:
if
attempt
.
get
(
'status'
)
==
'error'
:
student_view_template
=
'proctoring/seq_proctored_exam_error.html'
student_view_template
=
'proctoring/seq_proctored_exam_error.html'
else
:
now_utc
=
datetime
.
now
(
pytz
.
UTC
)
expires_at
=
attempt
[
'started_at'
]
+
timedelta
(
minutes
=
attempt
[
'allowed_time_limit_mins'
])
has_time_expired
=
now_utc
>
expires_at
# make sure the attempt has been marked as timed_out, if need be
if
has_time_expired
and
attempt
[
'status'
]
==
ProctoredExamStudentAttemptStatus
.
started
:
mark_exam_attempt_timeout
(
exam_id
,
user_id
)
# refetch since we are transitioning state
attempt
=
get_exam_attempt
(
exam_id
,
user_id
)
if
not
has_started_exam
:
if
not
has_started_exam
:
# determine whether to show a timed exam only entrance screen
# determine whether to show a timed exam only entrance screen
...
...
edx_proctoring/tests/test_api.py
View file @
45b715b3
"""
"""
All tests for the models.py
All tests for the models.py
"""
"""
from
datetime
import
datetime
from
datetime
import
datetime
,
timedelta
from
mock
import
patch
from
mock
import
patch
import
pytz
import
pytz
from
freezegun
import
freeze_time
from
edx_proctoring.api
import
(
from
edx_proctoring.api
import
(
create_exam
,
create_exam
,
...
@@ -703,6 +703,30 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -703,6 +703,30 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
)
self
.
assertIsNone
(
rendered_response
)
self
.
assertIsNone
(
rendered_response
)
def
test_get_studentview_timedout
(
self
):
"""
Verifies that if we call get_studentview when the timer has expired
it will automatically state transition into timed_out
"""
attempt_obj
=
self
.
_create_started_exam_attempt
()
reset_time
=
datetime
.
now
(
pytz
.
UTC
)
+
timedelta
(
days
=
1
)
with
freeze_time
(
reset_time
):
get_student_view
(
user_id
=
self
.
user_id
,
course_id
=
self
.
course_id
,
content_id
=
self
.
content_id
,
context
=
{
'is_proctored'
:
True
,
'display_name'
:
self
.
exam_name
,
'default_time_limit_mins'
:
90
}
)
attempt
=
get_exam_attempt_by_id
(
attempt_obj
.
id
)
self
.
assertEqual
(
attempt
[
'status'
],
'timed_out'
)
def
test_get_studentview_submitted_status
(
self
):
# pylint: disable=invalid-name
def
test_get_studentview_submitted_status
(
self
):
# pylint: disable=invalid-name
"""
"""
Test for get_student_view proctored exam which has been submitted.
Test for get_student_view proctored exam which has been submitted.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment