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
b4d47eb1
Commit
b4d47eb1
authored
Nov 13, 2015
by
Muhammad Shoaib
Committed by
Chris Dodge
Dec 08, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PHX-161 added the new helper methods to create/update/remove review policy for proctored exams
parent
67516498
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
283 additions
and
3 deletions
+283
-3
edx_proctoring/api.py
+103
-0
edx_proctoring/exceptions.py
+12
-0
edx_proctoring/serializers.py
+23
-1
edx_proctoring/tests/test_api.py
+144
-1
setup.py
+1
-1
No files found.
edx_proctoring/api.py
View file @
b4d47eb1
...
@@ -26,6 +26,8 @@ from edx_proctoring.exceptions import (
...
@@ -26,6 +26,8 @@ from edx_proctoring.exceptions import (
ProctoredExamIllegalStatusTransition
,
ProctoredExamIllegalStatusTransition
,
ProctoredExamPermissionDenied
,
ProctoredExamPermissionDenied
,
ProctoredExamNotActiveException
,
ProctoredExamNotActiveException
,
ProctoredExamReviewPolicyNotFoundException
,
ProctoredExamReviewPolicyAlreadyExists
)
)
from
edx_proctoring.models
import
(
from
edx_proctoring.models
import
(
ProctoredExam
,
ProctoredExam
,
...
@@ -38,6 +40,7 @@ from edx_proctoring.serializers import (
...
@@ -38,6 +40,7 @@ from edx_proctoring.serializers import (
ProctoredExamSerializer
,
ProctoredExamSerializer
,
ProctoredExamStudentAttemptSerializer
,
ProctoredExamStudentAttemptSerializer
,
ProctoredExamStudentAllowanceSerializer
,
ProctoredExamStudentAllowanceSerializer
,
ProctoredExamReviewPolicySerializer
)
)
from
edx_proctoring.utils
import
(
from
edx_proctoring.utils
import
(
humanized_time
,
humanized_time
,
...
@@ -96,6 +99,106 @@ def create_exam(course_id, content_id, exam_name, time_limit_mins, due_date=None
...
@@ -96,6 +99,106 @@ def create_exam(course_id, content_id, exam_name, time_limit_mins, due_date=None
return
proctored_exam
.
id
return
proctored_exam
.
id
def
create_exam_review_policy
(
exam_id
,
set_by_user_id
,
review_policy
):
"""
Creates a new exam_review_policy entity, if the review_policy
for exam_id does not already exist. If it exists, then raise exception.
Returns: id (PK)
"""
exam_review_policy
=
ProctoredExamReviewPolicy
.
get_review_policy_for_exam
(
exam_id
)
if
exam_review_policy
is
not
None
:
raise
ProctoredExamReviewPolicyAlreadyExists
exam_review_policy
=
ProctoredExamReviewPolicy
.
objects
.
create
(
proctored_exam_id
=
exam_id
,
set_by_user_id
=
set_by_user_id
,
review_policy
=
review_policy
)
log_msg
=
(
u'Created ProctoredExamReviewPolicy ({review_policy}) with parameters: exam_id={exam_id}, '
u'set_by_user_id={set_by_user_id}'
.
format
(
exam_id
=
exam_id
,
review_policy
=
review_policy
,
set_by_user_id
=
set_by_user_id
)
)
log
.
info
(
log_msg
)
return
exam_review_policy
.
id
def
update_review_policy
(
exam_id
,
set_by_user_id
,
review_policy
):
"""
Given a exam id, update/remove the existing record, otherwise raise exception if not found.
Returns: review_policy_id
"""
log_msg
=
(
u'Updating exam review policy with exam_id {exam_id}'
u'set_by_user_id={set_by_user_id}, review_policy={review_policy}'
.
format
(
exam_id
=
exam_id
,
set_by_user_id
=
set_by_user_id
,
review_policy
=
review_policy
,
)
)
log
.
info
(
log_msg
)
exam_review_policy
=
ProctoredExamReviewPolicy
.
get_review_policy_for_exam
(
exam_id
)
if
exam_review_policy
is
None
:
raise
ProctoredExamReviewPolicyNotFoundException
if
review_policy
:
exam_review_policy
.
set_by_user_id
=
set_by_user_id
exam_review_policy
.
review_policy
=
review_policy
exam_review_policy
.
save
()
msg
=
'Updated exam review policy with {exam_id}'
.
format
(
exam_id
=
exam_id
)
log
.
info
(
msg
)
else
:
exam_review_policy
.
delete
()
msg
=
'removed exam review policy with {exam_id}'
.
format
(
exam_id
=
exam_id
)
log
.
info
(
msg
)
def
remove_review_policy
(
exam_id
):
"""
Given a exam id, remove the existing record, otherwise raise exception if not found.
"""
log_msg
=
(
u'removing exam review policy with exam_id {exam_id}'
.
format
(
exam_id
=
exam_id
)
)
log
.
info
(
log_msg
)
exam_review_policy
=
ProctoredExamReviewPolicy
.
get_review_policy_for_exam
(
exam_id
)
if
exam_review_policy
is
None
:
raise
ProctoredExamReviewPolicyNotFoundException
exam_review_policy
.
delete
()
def
get_review_policy_by_exam_id
(
exam_id
):
"""
Looks up exam by the Primary Key. Raises exception if not found.
Returns dictionary version of the Django ORM object
e.g.
{
"id": 1
"proctored_exam": "{object}",
"set_by_user": "{object}",
"exam_review_rules": "review rules value"
"created": "datetime",
"modified": "datetime"
}
"""
exam_review_policy
=
ProctoredExamReviewPolicy
.
get_review_policy_for_exam
(
exam_id
)
if
exam_review_policy
is
None
:
raise
ProctoredExamReviewPolicyNotFoundException
return
ProctoredExamReviewPolicySerializer
(
exam_review_policy
)
.
data
def
update_exam
(
exam_id
,
exam_name
=
None
,
time_limit_mins
=
None
,
due_date
=
constants
.
MINIMUM_TIME
,
def
update_exam
(
exam_id
,
exam_name
=
None
,
time_limit_mins
=
None
,
due_date
=
constants
.
MINIMUM_TIME
,
is_proctored
=
None
,
is_practice_exam
=
None
,
external_id
=
None
,
is_active
=
None
):
is_proctored
=
None
,
is_practice_exam
=
None
,
external_id
=
None
,
is_active
=
None
):
"""
"""
...
...
edx_proctoring/exceptions.py
View file @
b4d47eb1
...
@@ -21,6 +21,18 @@ class ProctoredExamNotFoundException(ProctoredBaseException):
...
@@ -21,6 +21,18 @@ class ProctoredExamNotFoundException(ProctoredBaseException):
"""
"""
class
ProctoredExamReviewPolicyNotFoundException
(
ProctoredBaseException
):
"""
Raised when a look up fails.
"""
class
ProctoredExamReviewPolicyAlreadyExists
(
ProctoredBaseException
):
"""
Raised when trying to create an ProctoredExamReviewPolicy that already exists.
"""
class
ProctoredExamNotActiveException
(
ProctoredBaseException
):
class
ProctoredExamNotActiveException
(
ProctoredBaseException
):
"""
"""
Raised when a look up fails.
Raised when a look up fails.
...
...
edx_proctoring/serializers.py
View file @
b4d47eb1
...
@@ -2,7 +2,12 @@
...
@@ -2,7 +2,12 @@
from
rest_framework
import
serializers
from
rest_framework
import
serializers
from
rest_framework.fields
import
DateTimeField
from
rest_framework.fields
import
DateTimeField
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
from
edx_proctoring.models
import
ProctoredExam
,
ProctoredExamStudentAttempt
,
ProctoredExamStudentAllowance
from
edx_proctoring.models
import
(
ProctoredExam
,
ProctoredExamStudentAttempt
,
ProctoredExamStudentAllowance
,
ProctoredExamReviewPolicy
)
class
ProctoredExamSerializer
(
serializers
.
ModelSerializer
):
class
ProctoredExamSerializer
(
serializers
.
ModelSerializer
):
...
@@ -95,3 +100,20 @@ class ProctoredExamStudentAllowanceSerializer(serializers.ModelSerializer):
...
@@ -95,3 +100,20 @@ class ProctoredExamStudentAllowanceSerializer(serializers.ModelSerializer):
fields
=
(
fields
=
(
"id"
,
"created"
,
"modified"
,
"user"
,
"key"
,
"value"
,
"proctored_exam"
"id"
,
"created"
,
"modified"
,
"user"
,
"key"
,
"value"
,
"proctored_exam"
)
)
class
ProctoredExamReviewPolicySerializer
(
serializers
.
ModelSerializer
):
"""
Serializer for the ProctoredExamStudentAllowance Model.
"""
proctored_exam
=
ProctoredExamSerializer
()
set_by_user
=
UserSerializer
()
class
Meta
:
"""
Meta Class
"""
model
=
ProctoredExamReviewPolicy
fields
=
(
"id"
,
"created"
,
"modified"
,
"set_by_user"
,
"proctored_exam"
,
"review_policy"
)
edx_proctoring/tests/test_api.py
View file @
b4d47eb1
...
@@ -39,6 +39,10 @@ from edx_proctoring.api import (
...
@@ -39,6 +39,10 @@ from edx_proctoring.api import (
_check_for_attempt_timeout
,
_check_for_attempt_timeout
,
_get_ordered_prerequisites
,
_get_ordered_prerequisites
,
_are_prerequirements_satisfied
,
_are_prerequirements_satisfied
,
create_exam_review_policy
,
get_review_policy_by_exam_id
,
update_review_policy
,
remove_review_policy
,
)
)
from
edx_proctoring.exceptions
import
(
from
edx_proctoring.exceptions
import
(
ProctoredExamAlreadyExists
,
ProctoredExamAlreadyExists
,
...
@@ -49,7 +53,9 @@ from edx_proctoring.exceptions import (
...
@@ -49,7 +53,9 @@ from edx_proctoring.exceptions import (
UserNotFoundException
,
UserNotFoundException
,
ProctoredExamIllegalStatusTransition
,
ProctoredExamIllegalStatusTransition
,
ProctoredExamPermissionDenied
,
ProctoredExamPermissionDenied
,
AllowanceValueNotAllowedException
AllowanceValueNotAllowedException
,
ProctoredExamReviewPolicyAlreadyExists
,
ProctoredExamReviewPolicyNotFoundException
)
)
from
edx_proctoring.models
import
(
from
edx_proctoring.models
import
(
ProctoredExam
,
ProctoredExam
,
...
@@ -417,6 +423,143 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -417,6 +423,143 @@ class ProctoredExamApiTests(LoggedInTestCase):
exams
=
get_all_exams_for_course
(
self
.
course_id
,
False
)
exams
=
get_all_exams_for_course
(
self
.
course_id
,
False
)
self
.
assertEqual
(
len
(
exams
),
4
)
self
.
assertEqual
(
len
(
exams
),
4
)
def
test_create_exam_review_policy
(
self
):
"""
Test to create a new exam review policy for
proctored exam and tests that it stores in the
db correctly
"""
proctored_exam
=
get_exam_by_id
(
self
.
proctored_exam_id
)
create_exam_review_policy
(
exam_id
=
proctored_exam
[
'id'
],
set_by_user_id
=
self
.
user_id
,
review_policy
=
u'allow use of paper'
)
# now get the exam review policy for the proctored exam
exam_review_policy
=
get_review_policy_by_exam_id
(
proctored_exam
[
'id'
])
self
.
assertEqual
(
exam_review_policy
[
'proctored_exam'
][
'id'
],
proctored_exam
[
'id'
])
self
.
assertEqual
(
exam_review_policy
[
'set_by_user'
][
'id'
],
self
.
user_id
)
self
.
assertEqual
(
exam_review_policy
[
'review_policy'
],
u'allow use of paper'
)
def
test_update_exam_review_policy
(
self
):
"""
Test to update existing exam review policy for
proctored exam and tests that it stores in the
db correctly and set the exam review policy to ''
will remove the entry from the database.
"""
proctored_exam
=
get_exam_by_id
(
self
.
proctored_exam_id
)
create_exam_review_policy
(
exam_id
=
proctored_exam
[
'id'
],
set_by_user_id
=
self
.
user_id
,
review_policy
=
u'allow use of paper'
)
# now update the exam review policy for the proctored exam
update_review_policy
(
exam_id
=
proctored_exam
[
'id'
],
set_by_user_id
=
self
.
user_id
,
review_policy
=
u'allow use of calculator'
)
# now get the updated exam review policy for the proctored exam
exam_review_policy
=
get_review_policy_by_exam_id
(
proctored_exam
[
'id'
])
self
.
assertEqual
(
exam_review_policy
[
'proctored_exam'
][
'id'
],
proctored_exam
[
'id'
])
self
.
assertEqual
(
exam_review_policy
[
'set_by_user'
][
'id'
],
self
.
user_id
)
self
.
assertEqual
(
exam_review_policy
[
'review_policy'
],
u'allow use of calculator'
)
# now update the exam review policy for the proctored exam
# with review_policy value to "". This will delete the exam
# review policy object from the database.
update_review_policy
(
exam_id
=
proctored_exam
[
'id'
],
set_by_user_id
=
self
.
user_id
,
review_policy
=
u''
)
with
self
.
assertRaises
(
ProctoredExamReviewPolicyNotFoundException
):
get_review_policy_by_exam_id
(
proctored_exam
[
'id'
])
def
test_remove_existing_exam_review_policy
(
self
):
"""
Test to remove existing exam review policy for
proctored exam
"""
proctored_exam
=
get_exam_by_id
(
self
.
proctored_exam_id
)
create_exam_review_policy
(
exam_id
=
proctored_exam
[
'id'
],
set_by_user_id
=
self
.
user_id
,
review_policy
=
u'allow use of paper'
)
# now remove the exam review policy for the proctored exam
remove_review_policy
(
exam_id
=
proctored_exam
[
'id'
]
)
# now get the exam review policy for the proctored exam
# which will raise the exception because the exam review
# policy has been removed.
with
self
.
assertRaises
(
ProctoredExamReviewPolicyNotFoundException
):
get_review_policy_by_exam_id
(
proctored_exam
[
'id'
])
def
test_remove_non_existing_exam_review_policy
(
self
):
"""
Test to remove non existing exam review policy for
proctored exam which will raise exception
"""
proctored_exam
=
get_exam_by_id
(
self
.
proctored_exam_id
)
# now try to remove the non-existing exam review policy
# for the proctored exam which will raise exception
with
self
.
assertRaises
(
ProctoredExamReviewPolicyNotFoundException
):
remove_review_policy
(
exam_id
=
proctored_exam
[
'id'
]
)
def
test_update_non_existing_exam_review_policy
(
self
):
"""
Test to update non existing exam review policy for
proctored exam and it will raises exception
"""
# update the non existing exam review policy for the proctored exam
with
self
.
assertRaises
(
ProctoredExamReviewPolicyNotFoundException
):
update_review_policy
(
exam_id
=
self
.
practice_exam_id
,
set_by_user_id
=
10
,
review_policy
=
u'allow use of calculator'
)
def
test_create_exam_review_policy_with_same_exam_id
(
self
):
"""
Test to create a same exam review policy will raise exception
"""
proctored_exam
=
get_exam_by_id
(
self
.
proctored_exam_id
)
create_exam_review_policy
(
exam_id
=
proctored_exam
[
'id'
],
set_by_user_id
=
self
.
user_id
,
review_policy
=
u'allow use of paper'
)
# create the same review policy again will raise exception
with
self
.
assertRaises
(
ProctoredExamReviewPolicyAlreadyExists
):
create_exam_review_policy
(
exam_id
=
proctored_exam
[
'id'
],
set_by_user_id
=
self
.
user_id
,
review_policy
=
u'allow use of paper'
)
def
test_get_non_existing_review_policy_raises_exception
(
self
):
"""
Test to get the non-existing review policy raises exception
"""
with
self
.
assertRaises
(
ProctoredExamReviewPolicyNotFoundException
):
# now get the exam review policy for the proctored exam
get_review_policy_by_exam_id
(
self
.
practice_exam_id
)
def
test_get_timed_exam
(
self
):
def
test_get_timed_exam
(
self
):
"""
"""
test to get the exam by the exam_id and
test to get the exam by the exam_id and
...
...
setup.py
View file @
b4d47eb1
...
@@ -34,7 +34,7 @@ def load_requirements(*requirements_paths):
...
@@ -34,7 +34,7 @@ def load_requirements(*requirements_paths):
setup
(
setup
(
name
=
'edx-proctoring'
,
name
=
'edx-proctoring'
,
version
=
'0.11.
2
'
,
version
=
'0.11.
8
'
,
description
=
'Proctoring subsystem for Open edX'
,
description
=
'Proctoring subsystem for Open edX'
,
long_description
=
open
(
'README.md'
)
.
read
(),
long_description
=
open
(
'README.md'
)
.
read
(),
author
=
'edX'
,
author
=
'edX'
,
...
...
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