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
88c655c1
Commit
88c655c1
authored
Jun 26, 2015
by
Afzal Wali
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Some Quality fixes
parent
17f93b7d
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
62 additions
and
54 deletions
+62
-54
edx_proctoring/api.py
+3
-3
edx_proctoring/exceptions.py
+9
-6
edx_proctoring/serializers.py
+6
-0
edx_proctoring/tests/test_api.py
+10
-4
edx_proctoring/urls.py
+2
-1
edx_proctoring/views.py
+32
-40
No files found.
edx_proctoring/api.py
View file @
88c655c1
...
@@ -9,8 +9,8 @@ API which is in the views.py file, per edX coding standards
...
@@ -9,8 +9,8 @@ API which is in the views.py file, per edX coding standards
import
pytz
import
pytz
from
datetime
import
datetime
from
datetime
import
datetime
from
edx_proctoring.exceptions
import
(
from
edx_proctoring.exceptions
import
(
ProctoredExamAlreadyExists
,
ProctoredExamNotFoundException
,
StudentExamAttemptAlreadyExistsException
ProctoredExamAlreadyExists
,
ProctoredExamNotFoundException
,
StudentExamAttemptAlreadyExistsException
,
)
StudentExamAttemptDoesNotExistsException
)
from
edx_proctoring.models
import
(
from
edx_proctoring.models
import
(
ProctoredExam
,
ProctoredExamStudentAllowance
,
ProctoredExamStudentAttempt
ProctoredExam
,
ProctoredExamStudentAllowance
,
ProctoredExamStudentAttempt
)
)
...
@@ -150,7 +150,7 @@ def stop_exam_attempt(exam_id, user_id):
...
@@ -150,7 +150,7 @@ def stop_exam_attempt(exam_id, user_id):
"""
"""
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
get_student_exam_attempt
(
exam_id
,
user_id
)
exam_attempt_obj
=
ProctoredExamStudentAttempt
.
get_student_exam_attempt
(
exam_id
,
user_id
)
if
exam_attempt_obj
is
None
:
if
exam_attempt_obj
is
None
:
raise
StudentExamAttempt
Already
ExistsException
raise
StudentExamAttempt
DoesNot
ExistsException
else
:
else
:
exam_attempt_obj
.
completed_at
=
datetime
.
now
(
pytz
.
UTC
)
exam_attempt_obj
.
completed_at
=
datetime
.
now
(
pytz
.
UTC
)
exam_attempt_obj
.
save
()
exam_attempt_obj
.
save
()
...
...
edx_proctoring/exceptions.py
View file @
88c655c1
...
@@ -5,20 +5,23 @@ Specialized exceptions for the Notification subsystem
...
@@ -5,20 +5,23 @@ Specialized exceptions for the Notification subsystem
class
ProctoredExamAlreadyExists
(
Exception
):
class
ProctoredExamAlreadyExists
(
Exception
):
"""
"""
Generic exception when a look up fails. Since we are abstracting away the backends
Raised when trying to create an Exam that already exists.
we need to catch any native exceptions and re-throw as a generic exception
"""
"""
class
ProctoredExamNotFoundException
(
Exception
):
class
ProctoredExamNotFoundException
(
Exception
):
"""
"""
Generic exception when a look up fails. Since we are abstracting away the backends
Raised when a look up fails.
we need to catch any native exceptions and re-throw as a generic exception
"""
"""
class
StudentExamAttemptAlreadyExistsException
(
Exception
):
class
StudentExamAttemptAlreadyExistsException
(
Exception
):
"""
"""
Generic exception when a look up fails. Since we are abstracting away the backends
Raised when trying to start an exam when an Exam Attempt already exists.
we need to catch any native exceptions and re-throw as a generic exception
"""
"""
class
StudentExamAttemptDoesNotExistsException
(
Exception
):
"""
Raised when trying to stop an exam attempt where the Exam Attempt doesn't exist.
"""
edx_proctoring/serializers.py
View file @
88c655c1
...
@@ -4,7 +4,13 @@ from edx_proctoring.models import ProctoredExam
...
@@ -4,7 +4,13 @@ from edx_proctoring.models import ProctoredExam
class
ProctoredExamSerializer
(
serializers
.
ModelSerializer
):
class
ProctoredExamSerializer
(
serializers
.
ModelSerializer
):
"""
Serializer for the ProctoredExam Model.
"""
class
Meta
:
class
Meta
:
"""
Meta Class
"""
model
=
ProctoredExam
model
=
ProctoredExam
fields
=
(
fields
=
(
"course_id"
,
"content_id"
,
"external_id"
,
"exam_name"
,
"course_id"
,
"content_id"
,
"external_id"
,
"exam_name"
,
...
...
edx_proctoring/tests/test_api.py
View file @
88c655c1
...
@@ -3,12 +3,11 @@ All tests for the models.py
...
@@ -3,12 +3,11 @@ All tests for the models.py
"""
"""
from
datetime
import
datetime
from
datetime
import
datetime
import
pytz
import
pytz
from
edx_proctoring.api
import
create_exam
,
update_exam
,
get_exam_by_id
,
get_exam_by_content_id
,
add_allowance_for_user
,
\
from
edx_proctoring.api
import
create_exam
,
update_exam
,
get_exam_by_id
,
get_exam_by_content_id
,
\
remove_allowance_for_user
,
start_exam_attempt
,
stop_exam_attempt
add_allowance_for_user
,
remove_allowance_for_user
,
start_exam_attempt
,
stop_exam_attempt
from
edx_proctoring.exceptions
import
ProctoredExamAlreadyExists
,
ProctoredExamNotFoundException
,
\
from
edx_proctoring.exceptions
import
ProctoredExamAlreadyExists
,
ProctoredExamNotFoundException
,
\
StudentExamAttemptAlreadyExistsException
StudentExamAttemptAlreadyExistsException
from
edx_proctoring.models
import
ProctoredExam
,
ProctoredExamStudentAllowance
,
ProctoredExamStudentAllowanceHistory
,
\
from
edx_proctoring.models
import
ProctoredExam
,
ProctoredExamStudentAllowance
,
ProctoredExamStudentAttempt
ProctoredExamStudentAttempt
from
.utils
import
(
from
.utils
import
(
LoggedInTestCase
LoggedInTestCase
...
@@ -35,6 +34,9 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -35,6 +34,9 @@ class ProctoredExamApiTests(LoggedInTestCase):
self
.
external_id
=
'test_external_id'
self
.
external_id
=
'test_external_id'
def
_create_proctored_exam
(
self
):
def
_create_proctored_exam
(
self
):
"""
Calls the api's create_exam to create an exam object.
"""
return
create_exam
(
return
create_exam
(
course_id
=
self
.
course_id
,
course_id
=
self
.
course_id
,
content_id
=
self
.
content_id
,
content_id
=
self
.
content_id
,
...
@@ -43,6 +45,10 @@ class ProctoredExamApiTests(LoggedInTestCase):
...
@@ -43,6 +45,10 @@ class ProctoredExamApiTests(LoggedInTestCase):
)
)
def
_create_student_exam_attempt_entry
(
self
):
def
_create_student_exam_attempt_entry
(
self
):
"""
Creates the ProctoredExamStudentAttempt object.
"""
proctored_exam_id
=
self
.
_create_proctored_exam
()
proctored_exam_id
=
self
.
_create_proctored_exam
()
return
ProctoredExamStudentAttempt
.
objects
.
create
(
return
ProctoredExamStudentAttempt
.
objects
.
create
(
proctored_exam_id
=
proctored_exam_id
,
proctored_exam_id
=
proctored_exam_id
,
...
...
edx_proctoring/urls.py
View file @
88c655c1
...
@@ -19,7 +19,8 @@ urlpatterns = patterns( # pylint: disable=invalid-name
...
@@ -19,7 +19,8 @@ urlpatterns = patterns( # pylint: disable=invalid-name
name
=
'edx_proctoring.proctored_exam.exam'
name
=
'edx_proctoring.proctored_exam.exam'
),
),
url
(
url
(
r'edx_proctoring/v1/proctored_exam/exam/course_id/{}/content_id/(?P<content_id>\d+)$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
r'edx_proctoring/v1/proctored_exam/exam/course_id/{}/content_id/(?P<content_id>\d+)$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
views
.
ProctoredExamView
.
as_view
(),
views
.
ProctoredExamView
.
as_view
(),
name
=
'edx_proctoring.proctored_exam.exam'
name
=
'edx_proctoring.proctored_exam.exam'
),
),
...
...
edx_proctoring/views.py
View file @
88c655c1
...
@@ -7,7 +7,8 @@ from rest_framework import status
...
@@ -7,7 +7,8 @@ from rest_framework import status
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
edx_proctoring.api
import
create_exam
,
update_exam
,
get_exam_by_id
,
get_exam_by_content_id
,
start_exam_attempt
,
\
from
edx_proctoring.api
import
create_exam
,
update_exam
,
get_exam_by_id
,
get_exam_by_content_id
,
start_exam_attempt
,
\
stop_exam_attempt
,
add_allowance_for_user
,
remove_allowance_for_user
,
get_active_exams_for_user
stop_exam_attempt
,
add_allowance_for_user
,
remove_allowance_for_user
,
get_active_exams_for_user
from
edx_proctoring.exceptions
import
ProctoredExamNotFoundException
,
ProctoredExamAlreadyExists
from
edx_proctoring.exceptions
import
ProctoredExamNotFoundException
,
ProctoredExamAlreadyExists
,
\
StudentExamAttemptAlreadyExistsException
,
StudentExamAttemptDoesNotExistsException
from
edx_proctoring.serializers
import
ProctoredExamSerializer
from
edx_proctoring.serializers
import
ProctoredExamSerializer
from
.utils
import
AuthenticatedAPIView
from
.utils
import
AuthenticatedAPIView
...
@@ -115,13 +116,13 @@ class ProctoredExamView(AuthenticatedAPIView):
...
@@ -115,13 +116,13 @@ class ProctoredExamView(AuthenticatedAPIView):
is_active
=
request
.
DATA
.
get
(
'is_active'
,
False
),
is_active
=
request
.
DATA
.
get
(
'is_active'
,
False
),
)
)
return
Response
({
'exam_id'
:
exam_id
})
return
Response
({
'exam_id'
:
exam_id
})
except
:
except
ProctoredExamNotFoundException
:
return
Response
(
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"detail"
:
"The exam_id does not exist."
}
data
=
{
"detail"
:
"The exam_id does not exist."
}
)
)
def
get
(
self
,
request
,
exam_id
=
None
,
course_id
=
None
,
content_id
=
None
):
def
get
(
self
,
request
,
exam_id
=
None
,
course_id
=
None
,
content_id
=
None
):
# pylint: disable=unused-argument
"""
"""
HTTP GET handler.
HTTP GET handler.
Scenarios:
Scenarios:
...
@@ -198,10 +199,10 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
...
@@ -198,10 +199,10 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
)
)
return
Response
({
'exam_attempt_id'
:
exam_attempt_id
})
return
Response
({
'exam_attempt_id'
:
exam_attempt_id
})
except
Exception
:
except
StudentExamAttemptAlreadyExists
Exception
:
return
Response
(
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"detail"
:
"E
xam
already started."
}
data
=
{
"detail"
:
"E
rror. Trying to start an exam that has
already started."
}
)
)
def
put
(
self
,
request
):
def
put
(
self
,
request
):
...
@@ -215,66 +216,57 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
...
@@ -215,66 +216,57 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
)
)
return
Response
({
"exam_attempt_id"
:
exam_attempt_id
})
return
Response
({
"exam_attempt_id"
:
exam_attempt_id
})
except
Exception
:
except
StudentExamAttemptDoesNotExists
Exception
:
return
Response
(
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"detail"
:
"E
xam N
ot in progress."
}
data
=
{
"detail"
:
"E
rror. Trying to stop an exam that is n
ot in progress."
}
)
)
class
ExamAllowanceView
(
AuthenticatedAPIView
):
class
ExamAllowanceView
(
AuthenticatedAPIView
):
"""
"""
Endpoint for the ExamAlloawnce
/edx_proctoring/v1/proctored_exam/allowance
Supports:
HTTP PUT: Creates or Updates the allowance for a user.
HTTP DELETE: Removed an allowance for a user.
"""
"""
def
put
(
self
,
request
):
def
put
(
self
,
request
):
"""
"""
HTTP GET handler. Adds or updates Allowance
HTTP GET handler. Adds or updates Allowance
"""
"""
try
:
return
Response
(
add_allowance_for_user
(
return
Response
(
add_allowance_for_user
(
exam_id
=
request
.
DATA
.
get
(
'exam_id'
,
""
),
exam_id
=
request
.
DATA
.
get
(
'exam_id'
,
""
),
user_id
=
request
.
DATA
.
get
(
'user_id'
,
""
),
user_id
=
request
.
DATA
.
get
(
'user_id'
,
""
),
key
=
request
.
DATA
.
get
(
'key'
,
""
),
key
=
request
.
DATA
.
get
(
'key'
,
""
),
value
=
request
.
DATA
.
get
(
'value'
,
""
)
value
=
request
.
DATA
.
get
(
'value'
,
""
)
))
))
except
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"detail"
:
"Could not add Allowance."
}
)
def
delete
(
self
,
request
):
def
delete
(
self
,
request
):
"""
"""
HTTP DELETE handler. Removes Allowance.
HTTP DELETE handler. Removes Allowance.
"""
"""
try
:
return
Response
(
remove_allowance_for_user
(
return
Response
(
remove_allowance_for_user
(
exam_id
=
request
.
DATA
.
get
(
'exam_id'
,
""
),
exam_id
=
request
.
DATA
.
get
(
'exam_id'
,
""
),
user_id
=
request
.
DATA
.
get
(
'user_id'
,
""
),
user_id
=
request
.
DATA
.
get
(
'user_id'
,
""
),
key
=
request
.
DATA
.
get
(
'key'
,
""
)
key
=
request
.
DATA
.
get
(
'key'
,
""
)
))
))
except
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"detail"
:
"Could not remove Allowance."
}
)
class
ActiveExamsForUserView
(
AuthenticatedAPIView
):
class
ActiveExamsForUserView
(
AuthenticatedAPIView
):
"""
"""
Endpoint for the Active Exams for a user.
/edx_proctoring/v1/proctored_exam/active_exams_for_user
Supports:
HTTP GET: returns a list of active exams for the user
"""
"""
def
get
(
self
,
request
):
def
get
(
self
,
request
):
"""
"""
returns the get_active_exams_for_user
returns the get_active_exams_for_user
"""
"""
try
:
return
Response
(
get_active_exams_for_user
(
return
Response
(
get_active_exams_for_user
(
user_id
=
request
.
DATA
.
get
(
'user_id'
,
""
),
user_id
=
request
.
DATA
.
get
(
'user_id'
,
""
),
course_id
=
request
.
DATA
.
get
(
'course_id'
,
""
)
course_id
=
request
.
DATA
.
get
(
'course_id'
,
""
)
))
))
except
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
"detail"
:
"Error."
}
)
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