Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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
edx
edx-platform
Commits
ff119265
Commit
ff119265
authored
Nov 19, 2012
by
Victor Shnayder
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial impl and basic access tests for staff grading service
parent
055aeae0
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
175 additions
and
17 deletions
+175
-17
lms/djangoapps/courseware/tests/tests.py
+12
-2
lms/djangoapps/instructor/staff_grading_service.py
+113
-7
lms/djangoapps/instructor/tests.py
+46
-8
lms/envs/common.py
+4
-0
No files found.
lms/djangoapps/courseware/tests/tests.py
View file @
ff119265
...
...
@@ -221,8 +221,7 @@ class PageLoader(ActivateLoginTestCase):
def
check_for_get_code
(
self
,
code
,
url
):
"""
Check that we got the expected code. Hacks around our broken 404
handling.
Check that we got the expected code when accessing url via GET.
"""
resp
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
resp
.
status_code
,
code
,
...
...
@@ -230,6 +229,17 @@ class PageLoader(ActivateLoginTestCase):
.
format
(
resp
.
status_code
,
url
,
code
))
def
check_for_post_code
(
self
,
code
,
url
,
data
=
{}):
"""
Check that we got the expected code when accessing url via POST.
"""
resp
=
self
.
client
.
post
(
url
,
data
)
self
.
assertEqual
(
resp
.
status_code
,
code
,
"got code {0} for url '{1}'. Expected code {2}"
.
format
(
resp
.
status_code
,
url
,
code
))
def
check_pages_load
(
self
,
course_name
,
data_dir
,
modstore
):
"""Make all locations in course load"""
print
"Checking course {0} in {1}"
.
format
(
course_name
,
data_dir
)
...
...
lms/djangoapps/instructor/staff_grading_service.py
View file @
ff119265
...
...
@@ -3,14 +3,20 @@ This module provides views that proxy to the staff grading backend service.
"""
import
json
import
logging
import
requests
import
sys
from
django.conf
import
settings
from
django.http
import
Http404
from
django.http
import
HttpResponse
from
courseware.access
import
has_access
from
util.json_request
import
expect_json
from
xmodule.course_module
import
CourseDescriptor
log
=
logging
.
getLogger
(
"mitx.courseware"
)
class
GradingServiceError
(
Exception
):
pass
...
...
@@ -37,21 +43,121 @@ class StaffGradingService(object):
return
r
.
text
def
save_grade
(
course_id
,
submission_id
,
score
,
feedback
):
"""
Save a grade.
TODO: what is data?
Returns json, or raises GradingServiceError if there's a problem.
"""
try
:
r
=
self
.
session
.
get
(
url
+
'save_grade'
)
except
requests
.
exceptions
.
ConnectionError
as
err
:
# reraise as promised GradingServiceError, but preserve stacktrace.
raise
GradingServiceError
,
str
(
err
),
sys
.
exc_info
()[
2
]
return
r
.
text
_service
=
StaffGradingService
(
settings
.
STAFF_GRADING_BACKEND_URL
)
def
_err_response
(
msg
):
"""
Return a HttpResponse with a json dump with success=False, and the given error message.
"""
return
HttpResponse
(
json
.
dumps
({
'success'
:
False
,
'error'
:
msg
}))
def
_check_access
(
user
,
course_id
):
"""
Raise 404 if user doesn't have staff access to course_id
"""
course_location
=
CourseDescriptor
.
id_to_location
(
course_id
)
if
not
has_access
(
user
,
course_location
,
'staff'
):
raise
Http404
return
#@login_required
def
get_next
(
request
,
course_id
):
"""
Get the next thing to grade for course_id.
Returns a json dict with the following keys:
'success': bool
'submission_id': a unique identifier for the submission, to be passed back
with the grade.
'submission': the submission, rendered as read-only html for grading
'rubric': the rubric, also rendered as html.
'message': if there was no submission available, but nothing went wrong,
there will be a message field.
'error': if success is False, will have an error message with more info.
"""
_check_access
(
request
.
user
,
course_id
)
return
HttpResponse
(
_get_next
(
course_id
))
def
_get_next
(
course_id
):
"""
Implementation of get_next (also called from save_grade) -- returns a json string
"""
d
=
{
'success'
:
False
}
return
HttpResponse
(
json
.
dumps
(
d
))
try
:
return
_service
.
get_next
(
course_id
)
except
GradingServiceError
:
log
.
exception
(
"Error from grading service"
)
return
json
.
dumps
({
'success'
:
False
,
'error'
:
'Could not connect to grading service'
})
#@login_required
@expect_json
def
save_grade
(
request
,
course_id
):
"""
Save the grade and feedback for a submission, and, if all goes well, return
the next thing to grade.
Expects the following POST parameters:
'score': int
'feedback': string
'submission_id': int
Returns the same thing as get_next, except that additional error messages
are possible if something goes wrong with saving the grade.
"""
d
=
{
'success'
:
False
}
return
HttpResponse
(
json
.
dumps
(
d
))
_check_access
(
request
.
user
,
course_id
)
if
request
.
method
!=
'POST'
:
raise
Http404
required
=
(
'score'
,
'feedback'
,
'submission_id'
)
for
k
in
required
:
if
k
not
in
request
.
POST
.
keys
():
return
_err_response
(
'Missing required key {0}'
.
format
(
k
))
p
=
request
.
POST
try
:
result_json
=
_service
.
save_grade
(
course_id
,
p
[
'submission_id'
],
p
[
'score'
],
p
[
'feedback'
])
except
GradingServiceError
:
log
.
exception
(
"Error saving grade"
)
return
_err_response
(
'Could not connect to grading service'
)
try
:
result
=
json
.
loads
(
result_json
)
except
ValueError
:
return
_err_response
(
'Grading service returned mal-formatted data.'
)
if
not
result
.
get
(
'success'
,
False
):
log
.
warning
(
'Got success=False from grading service. Response:
%
s'
,
result_json
)
return
_err_response
(
'Grading service failed'
)
# Ok, save_grade seemed to work. Get the next submission to grade.
return
HttpResponse
(
_get_next
(
course_id
))
lms/djangoapps/instructor/tests.py
View file @
ff119265
...
...
@@ -31,7 +31,6 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
def
setUp
(
self
):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
courses
=
modulestore
()
.
get_courses
()
self
.
full
=
modulestore
()
.
get_course
(
"edX/full/6.002_Spring_2012"
)
self
.
toy
=
modulestore
()
.
get_course
(
"edX/toy/2012_Fall"
)
...
...
@@ -79,6 +78,7 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
"2","u2","Fred Weasley","view2@test.com","","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0.0","0.0"
'''
self
.
assertEqual
(
body
,
expected_body
,
msg
)
FORUM_ROLES
=
[
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
]
FORUM_ADMIN_ACTION_SUFFIX
=
{
FORUM_ROLE_ADMINISTRATOR
:
'admin'
,
FORUM_ROLE_MODERATOR
:
'moderator'
,
FORUM_ROLE_COMMUNITY_TA
:
'community TA'
}
...
...
@@ -90,22 +90,19 @@ def action_name(operation, rolename):
else
:
return
'{0} forum {1}'
.
format
(
operation
,
FORUM_ADMIN_ACTION_SUFFIX
[
rolename
])
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestInstructorDashboardForumAdmin
(
ct
.
PageLoader
):
'''
Check for change in forum admin role memberships
'''
def
setUp
(
self
):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
courses
=
modulestore
()
.
get_courses
()
def
find_course
(
name
):
"""Assumes the course is present"""
return
[
c
for
c
in
courses
if
c
.
location
.
course
==
name
][
0
]
self
.
full
=
find_course
(
"full"
)
self
.
toy
=
find_course
(
"toy"
)
self
.
full
=
modulestore
()
.
get_course
(
"edX/full/6.002_Spring_2012"
)
self
.
toy
=
modulestore
()
.
get_course
(
"edX/toy/2012_Fall"
)
# Create two accounts
self
.
student
=
'view@test.com'
...
...
@@ -124,6 +121,8 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
self
.
login
(
self
.
instructor
,
self
.
password
)
self
.
enroll
(
self
.
toy
)
def
initialize_roles
(
self
,
course_id
):
self
.
admin_role
=
Role
.
objects
.
get_or_create
(
name
=
FORUM_ROLE_ADMINISTRATOR
,
course_id
=
course_id
)[
0
]
self
.
moderator_role
=
Role
.
objects
.
get_or_create
(
name
=
FORUM_ROLE_MODERATOR
,
course_id
=
course_id
)[
0
]
...
...
@@ -210,3 +209,42 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
added_roles
.
sort
()
roles
=
', '
.
join
(
added_roles
)
self
.
assertTrue
(
response
.
content
.
find
(
'<td>{0}</td>'
.
format
(
roles
))
>=
0
,
'not finding roles "{0}"'
.
format
(
roles
))
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestStaffGradingService
(
ct
.
PageLoader
):
'''
Check that staff grading service proxy works. Basically just checking the
access control and error handling logic -- all the actual work is on the
backend.
'''
def
setUp
(
self
):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
self
.
course_id
=
"edX/toy/2012_Fall"
self
.
toy
=
modulestore
()
.
get_course
(
self
.
course_id
)
def
make_instructor
(
course
):
group_name
=
_course_staff_group_name
(
course
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
ct
.
user
(
self
.
instructor
))
make_instructor
(
self
.
toy
)
self
.
logout
()
def
test_access
(
self
):
"""
Make sure only staff have access.
"""
self
.
login
(
self
.
student
,
self
.
password
)
self
.
enroll
(
self
.
toy
)
# both get and post should return 404
for
view_name
in
(
'staff_grading_get_next'
,
'staff_grading_save_grade'
):
url
=
reverse
(
view_name
,
kwargs
=
{
'course_id'
:
self
.
course_id
})
self
.
check_for_get_code
(
404
,
url
)
self
.
check_for_post_code
(
404
,
url
)
lms/envs/common.py
View file @
ff119265
...
...
@@ -322,6 +322,10 @@ WIKI_USE_BOOTSTRAP_SELECT_WIDGET = False
WIKI_LINK_LIVE_LOOKUPS
=
False
WIKI_LINK_DEFAULT_LEVEL
=
2
################################# Staff grading config #####################
STAFF_GRADING_BACKEND_URL
=
None
################################# Jasmine ###################################
JASMINE_TEST_DIRECTORY
=
PROJECT_ROOT
+
'/static/coffee'
...
...
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