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
3d8f221a
Commit
3d8f221a
authored
Aug 06, 2015
by
Chris Dodge
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add more logging in api.py
parent
6a1a6b7a
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
121 additions
and
4 deletions
+121
-4
edx_proctoring/api.py
+91
-3
edx_proctoring/tests/test_api.py
+30
-1
No files found.
edx_proctoring/api.py
View file @
3d8f221a
...
@@ -23,6 +23,7 @@ from edx_proctoring.exceptions import (
...
@@ -23,6 +23,7 @@ from edx_proctoring.exceptions import (
StudentExamAttemptDoesNotExistsException
,
StudentExamAttemptDoesNotExistsException
,
StudentExamAttemptedAlreadyStarted
,
StudentExamAttemptedAlreadyStarted
,
ProctoredExamIllegalStatusTransition
,
ProctoredExamIllegalStatusTransition
,
ProctoredExamPermissionDenied
,
)
)
from
edx_proctoring.models
import
(
from
edx_proctoring.models
import
(
ProctoredExam
,
ProctoredExam
,
...
@@ -59,6 +60,7 @@ def create_exam(course_id, content_id, exam_name, time_limit_mins,
...
@@ -59,6 +60,7 @@ def create_exam(course_id, content_id, exam_name, time_limit_mins,
Returns: id (PK)
Returns: id (PK)
"""
"""
if
ProctoredExam
.
get_exam_by_content_id
(
course_id
,
content_id
)
is
not
None
:
if
ProctoredExam
.
get_exam_by_content_id
(
course_id
,
content_id
)
is
not
None
:
raise
ProctoredExamAlreadyExists
raise
ProctoredExamAlreadyExists
...
@@ -72,6 +74,21 @@ def create_exam(course_id, content_id, exam_name, time_limit_mins,
...
@@ -72,6 +74,21 @@ def create_exam(course_id, content_id, exam_name, time_limit_mins,
is_practice_exam
=
is_practice_exam
,
is_practice_exam
=
is_practice_exam
,
is_active
=
is_active
is_active
=
is_active
)
)
log_msg
=
(
'Created exam ({exam_id}) with parameters: course_id={course_id}, '
'content_id={content_id}, exam_name={exam_name}, time_limit_mins={time_limit_mins}, '
'is_proctored={is_proctored}, is_practice_exam={is_practice_exam}, '
'external_id={external_id}, is_active={is_active}'
.
format
(
exam_id
=
proctored_exam
.
id
,
course_id
=
course_id
,
content_id
=
content_id
,
exam_name
=
exam_name
,
time_limit_mins
=
time_limit_mins
,
is_proctored
=
is_proctored
,
is_practice_exam
=
is_practice_exam
,
external_id
=
external_id
,
is_active
=
is_active
)
)
log
.
info
(
log_msg
)
return
proctored_exam
.
id
return
proctored_exam
.
id
...
@@ -83,6 +100,19 @@ def update_exam(exam_id, exam_name=None, time_limit_mins=None,
...
@@ -83,6 +100,19 @@ def update_exam(exam_id, exam_name=None, time_limit_mins=None,
Returns: id
Returns: id
"""
"""
log_msg
=
(
'Updating exam_id {exam_id} with parameters '
'exam_name={exam_name}, time_limit_mins={time_limit_mins}, '
'is_proctored={is_proctored}, is_practice_exam={is_practice_exam}, '
'external_id={external_id}, is_active={is_active}'
.
format
(
exam_id
=
exam_id
,
exam_name
=
exam_name
,
time_limit_mins
=
time_limit_mins
,
is_proctored
=
is_proctored
,
is_practice_exam
=
is_practice_exam
,
external_id
=
external_id
,
is_active
=
is_active
)
)
log
.
info
(
log_msg
)
proctored_exam
=
ProctoredExam
.
get_exam_by_id
(
exam_id
)
proctored_exam
=
ProctoredExam
.
get_exam_by_id
(
exam_id
)
if
proctored_exam
is
None
:
if
proctored_exam
is
None
:
raise
ProctoredExamNotFoundException
raise
ProctoredExamNotFoundException
...
@@ -155,6 +185,15 @@ def add_allowance_for_user(exam_id, user_info, key, value):
...
@@ -155,6 +185,15 @@ def add_allowance_for_user(exam_id, user_info, key, value):
"""
"""
Adds (or updates) an allowance for a user within a given exam
Adds (or updates) an allowance for a user within a given exam
"""
"""
log_msg
=
(
'Adding allowance "{key}" with value "{value}" for exam_id {exam_id} '
'for user {user_info} '
.
format
(
key
=
key
,
value
=
value
,
exam_id
=
exam_id
,
user_info
=
user_info
)
)
log
.
info
(
log_msg
)
ProctoredExamStudentAllowance
.
add_allowance_for_user
(
exam_id
,
user_info
,
key
,
value
)
ProctoredExamStudentAllowance
.
add_allowance_for_user
(
exam_id
,
user_info
,
key
,
value
)
...
@@ -170,6 +209,13 @@ def remove_allowance_for_user(exam_id, user_id, key):
...
@@ -170,6 +209,13 @@ def remove_allowance_for_user(exam_id, user_id, key):
"""
"""
Deletes an allowance for a user within a given exam.
Deletes an allowance for a user within a given exam.
"""
"""
log_msg
=
(
'Removing allowance "{key}" for exam_id {exam_id} for user_id {user_id} '
.
format
(
key
=
key
,
exam_id
=
exam_id
,
user_id
=
user_id
)
)
log
.
info
(
log_msg
)
student_allowance
=
ProctoredExamStudentAllowance
.
get_allowance_for_user
(
exam_id
,
user_id
,
key
)
student_allowance
=
ProctoredExamStudentAllowance
.
get_allowance_for_user
(
exam_id
,
user_id
,
key
)
if
student_allowance
is
not
None
:
if
student_allowance
is
not
None
:
student_allowance
.
delete
()
student_allowance
.
delete
()
...
@@ -240,6 +286,14 @@ def update_exam_attempt(attempt_id, **kwargs):
...
@@ -240,6 +286,14 @@ def update_exam_attempt(attempt_id, **kwargs):
"""
"""
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt_by_id
(
attempt_id
)
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt_by_id
(
attempt_id
)
for
key
,
value
in
kwargs
.
items
():
for
key
,
value
in
kwargs
.
items
():
# only allow a limit set of fields to update
# namely because status transitions can trigger workflow
if
key
not
in
[
'last_poll_timestamp'
,
'last_poll_ipaddr'
]:
err_msg
=
(
'You cannot call into update_exam_attempt to change '
'field {key}'
.
format
(
key
=
key
)
)
raise
ProctoredExamPermissionDenied
(
err_msg
)
setattr
(
exam_attempt_obj
,
key
,
value
)
setattr
(
exam_attempt_obj
,
key
,
value
)
exam_attempt_obj
.
save
()
exam_attempt_obj
.
save
()
...
@@ -263,6 +317,14 @@ def create_exam_attempt(exam_id, user_id, taking_as_proctored=False):
...
@@ -263,6 +317,14 @@ def create_exam_attempt(exam_id, user_id, taking_as_proctored=False):
"""
"""
# for now the student is allowed the exam default
# for now the student is allowed the exam default
log_msg
=
(
'Creating exam attempt for exam_id {exam_id} for '
'user_id {user_id} with taking as proctored = {taking_as_proctored}'
.
format
(
exam_id
=
exam_id
,
user_id
=
user_id
,
taking_as_proctored
=
taking_as_proctored
)
)
log
.
info
(
log_msg
)
exam
=
get_exam_by_id
(
exam_id
)
exam
=
get_exam_by_id
(
exam_id
)
existing_attempt
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt
(
exam_id
,
user_id
)
existing_attempt
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt
(
exam_id
,
user_id
)
if
existing_attempt
:
if
existing_attempt
:
...
@@ -332,6 +394,22 @@ def create_exam_attempt(exam_id, user_id, taking_as_proctored=False):
...
@@ -332,6 +394,22 @@ def create_exam_attempt(exam_id, user_id, taking_as_proctored=False):
exam
[
'is_practice_exam'
],
exam
[
'is_practice_exam'
],
external_id
external_id
)
)
log_msg
=
(
'Created exam attempt ({attempt_id}) for exam_id {exam_id} for '
'user_id {user_id} with taking as proctored = {taking_as_proctored} '
'with allowed time limit minutes of {allowed_time_limit_mins}. '
'Attempt_code {attempt_code} was generated which has a '
'external_id of {external_id}'
.
format
(
attempt_id
=
attempt
.
id
,
exam_id
=
exam_id
,
user_id
=
user_id
,
taking_as_proctored
=
taking_as_proctored
,
allowed_time_limit_mins
=
allowed_time_limit_mins
,
attempt_code
=
attempt_code
,
external_id
=
external_id
)
)
log
.
info
(
log_msg
)
return
attempt
.
id
return
attempt
.
id
...
@@ -424,6 +502,14 @@ def update_attempt_status(exam_id, user_id, to_status):
...
@@ -424,6 +502,14 @@ def update_attempt_status(exam_id, user_id, to_status):
Internal helper to handle state transitions of attempt status
Internal helper to handle state transitions of attempt status
"""
"""
log_msg
=
(
'Updating attempt status for exam_id {exam_id} '
'for user_id {user_id} to status {to_status}'
.
format
(
exam_id
=
exam_id
,
user_id
=
user_id
,
to_status
=
to_status
)
)
log
.
info
(
log_msg
)
# In some configuration we may treat timeouts the same
# In some configuration we may treat timeouts the same
# as the user saying he/she wises to submit the exam
# as the user saying he/she wises to submit the exam
alias_timeout
=
(
alias_timeout
=
(
...
@@ -521,6 +607,11 @@ def remove_exam_attempt(attempt_id):
...
@@ -521,6 +607,11 @@ def remove_exam_attempt(attempt_id):
Removes an exam attempt given the attempt id.
Removes an exam attempt given the attempt id.
"""
"""
log_msg
=
(
'Removing exam attempt {attempt_id}'
.
format
(
attempt_id
=
attempt_id
)
)
log
.
info
(
log_msg
)
existing_attempt
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt_by_id
(
attempt_id
)
existing_attempt
=
ProctoredExamStudentAttempt
.
objects
.
get_exam_attempt_by_id
(
attempt_id
)
if
not
existing_attempt
:
if
not
existing_attempt
:
err_msg
=
(
err_msg
=
(
...
@@ -807,9 +898,6 @@ def get_student_view(user_id, course_id, content_id,
...
@@ -807,9 +898,6 @@ def get_student_view(user_id, course_id, content_id,
expires_at
=
attempt
[
'started_at'
]
+
timedelta
(
minutes
=
attempt
[
'allowed_time_limit_mins'
])
expires_at
=
attempt
[
'started_at'
]
+
timedelta
(
minutes
=
attempt
[
'allowed_time_limit_mins'
])
does_time_remain
=
datetime
.
now
(
pytz
.
UTC
)
<
expires_at
does_time_remain
=
datetime
.
now
(
pytz
.
UTC
)
<
expires_at
if
attempt
:
print
'*** status = {}'
.
format
(
attempt
[
'status'
])
if
not
attempt
:
if
not
attempt
:
# determine whether to show a timed exam only entrance screen
# determine whether to show a timed exam only entrance screen
# or a screen regarding proctoring
# or a screen regarding proctoring
...
...
edx_proctoring/tests/test_api.py
View file @
3d8f221a
...
@@ -34,6 +34,7 @@ from edx_proctoring.api import (
...
@@ -34,6 +34,7 @@ from edx_proctoring.api import (
mark_exam_attempt_as_ready
,
mark_exam_attempt_as_ready
,
update_attempt_status
,
update_attempt_status
,
get_attempt_status_summary
,
get_attempt_status_summary
,
update_exam_attempt
)
)
from
edx_proctoring.exceptions
import
(
from
edx_proctoring.exceptions
import
(
ProctoredExamAlreadyExists
,
ProctoredExamAlreadyExists
,
...
@@ -42,7 +43,8 @@ from edx_proctoring.exceptions import (
...
@@ -42,7 +43,8 @@ from edx_proctoring.exceptions import (
StudentExamAttemptDoesNotExistsException
,
StudentExamAttemptDoesNotExistsException
,
StudentExamAttemptedAlreadyStarted
,
StudentExamAttemptedAlreadyStarted
,
UserNotFoundException
,
UserNotFoundException
,
ProctoredExamIllegalStatusTransition
ProctoredExamIllegalStatusTransition
,
ProctoredExamPermissionDenied
)
)
from
edx_proctoring.models
import
(
from
edx_proctoring.models
import
(
ProctoredExam
,
ProctoredExam
,
...
@@ -1298,3 +1300,30 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -1298,3 +1300,30 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
)
self
.
assertIsNone
(
summary
)
self
.
assertIsNone
(
summary
)
def
test_update_exam_attempt
(
self
):
"""
Make sure we restrict which fields we can update
"""
exam_attempt
=
self
.
_create_started_exam_attempt
()
with
self
.
assertRaises
(
ProctoredExamPermissionDenied
):
update_exam_attempt
(
exam_attempt
.
id
,
last_poll_timestamp
=
datetime
.
utcnow
(),
last_poll_ipaddr
=
'1.1.1.1'
,
status
=
'foo'
)
now
=
datetime
.
now
(
pytz
.
UTC
)
update_exam_attempt
(
exam_attempt
.
id
,
last_poll_timestamp
=
now
,
last_poll_ipaddr
=
'1.1.1.1'
,
)
attempt
=
get_exam_attempt_by_id
(
exam_attempt
.
id
)
self
.
assertEquals
(
attempt
[
'last_poll_timestamp'
],
now
)
self
.
assertEquals
(
attempt
[
'last_poll_ipaddr'
],
'1.1.1.1'
)
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