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
dfa43501
Commit
dfa43501
authored
Jul 03, 2013
by
Adam Palay
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
notify students for NotFoundErrors from capa_module, improve error logging
parent
d3993653
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
109 additions
and
17 deletions
+109
-17
common/lib/xmodule/xmodule/capa_module.py
+17
-2
lms/djangoapps/courseware/module_render.py
+6
-5
lms/djangoapps/courseware/tests/test_submitting_problems.py
+86
-10
No files found.
common/lib/xmodule/xmodule/capa_module.py
View file @
dfa43501
...
...
@@ -152,6 +152,7 @@ class CapaFields(object):
scope
=
Scope
.
settings
)
class
CapaModule
(
CapaFields
,
XModule
):
"""
An XModule implementing LonCapa format problems, implemented by way of
...
...
@@ -552,6 +553,16 @@ class CapaModule(CapaFields, XModule):
'ungraded_response'
:
self
.
handle_ungraded_response
}
generic_error_message
=
(
"We're sorry, there was an error with processing your request. "
"Please try reloading your page and trying again."
)
not_found_error_message
=
(
"The state of this problem has changed since you loaded this page. "
"Please refresh your page."
)
if
dispatch
not
in
handlers
:
return
'Error'
...
...
@@ -559,9 +570,14 @@ class CapaModule(CapaFields, XModule):
try
:
result
=
handlers
[
dispatch
](
data
)
except
NotFoundError
as
err
:
_
,
_
,
traceback_obj
=
sys
.
exc_info
()
raise
ProcessingError
,
(
not_found_error_message
,
err
),
traceback_obj
except
Exception
as
err
:
_
,
_
,
traceback_obj
=
sys
.
exc_info
()
raise
ProcessingError
(
err
.
message
,
traceback_obj
)
raise
ProcessingError
,
(
generic_error_message
,
err
),
traceback_obj
after
=
self
.
get_progress
()
...
...
@@ -1125,7 +1141,6 @@ class CapaDescriptor(CapaFields, RawDescriptor):
problem
.
rerandomize
=
"always"
return
problem
@property
def
non_editable_metadata_fields
(
self
):
non_editable_fields
=
super
(
CapaDescriptor
,
self
)
.
non_editable_metadata_fields
...
...
lms/djangoapps/courseware/module_render.py
View file @
dfa43501
...
...
@@ -10,7 +10,7 @@ from django.core.cache import cache
from
django.core.exceptions
import
PermissionDenied
from
django.core.urlresolvers
import
reverse
from
django.http
import
Http404
from
django.http
import
HttpResponse
,
HttpResponseBadRequest
from
django.http
import
HttpResponse
from
django.views.decorators.csrf
import
csrf_exempt
import
pyparsing
...
...
@@ -38,6 +38,7 @@ from courseware.masquerade import setup_masquerade
from
courseware.model_data
import
LmsKeyValueStore
,
LmsUsage
,
ModelDataCache
from
courseware.models
import
StudentModule
from
util.sandboxing
import
can_execute_unsafe_code
from
util.json_request
import
JsonResponse
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -509,11 +510,11 @@ def modx_dispatch(request, dispatch, location, course_id):
log
.
exception
(
"Module indicating to user that request doesn't exist"
)
raise
Http404
# For XModule-specific errors, we
respond with 400
except
ProcessingError
:
log
.
warning
(
"Module encountered an error while prcessing AJAX call"
,
# For XModule-specific errors, we
log the error and respond with an error message
except
ProcessingError
as
err
:
log
.
warning
(
"Module encountered an error while pr
o
cessing AJAX call"
,
exc_info
=
True
)
return
HttpResponseBadRequest
(
)
return
JsonResponse
(
object
=
{
'success'
:
err
.
args
[
0
]},
status
=
200
)
# If any other error occurred, re-raise it to trigger a 500 response
except
:
...
...
lms/djangoapps/courseware/tests/test_submitting_problems.py
View file @
dfa43501
...
...
@@ -107,6 +107,15 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
resp
=
self
.
client
.
post
(
modx_url
)
return
resp
def
show_question_answer
(
self
,
problem_url_name
):
"""
Shows the answer to the current student.
"""
problem_location
=
self
.
problem_location
(
problem_url_name
)
modx_url
=
self
.
modx_url
(
problem_location
,
'problem_show'
)
resp
=
self
.
client
.
post
(
modx_url
)
return
resp
def
add_dropdown_to_section
(
self
,
section_location
,
name
,
num_inputs
=
2
):
"""
Create and return a dropdown problem.
...
...
@@ -131,7 +140,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
parent_location
=
section_location
,
category
=
'problem'
,
data
=
prob_xml
,
metadata
=
{
'randomize'
:
'always'
},
metadata
=
{
'r
er
andomize'
:
'always'
},
display_name
=
name
)
...
...
@@ -139,7 +148,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
self
.
refresh_course
()
return
problem
def
add_graded_section_to_course
(
self
,
name
,
section_format
=
'Homework'
):
def
add_graded_section_to_course
(
self
,
name
,
section_format
=
'Homework'
,
late
=
False
,
reset
=
False
,
showanswer
=
False
):
"""
Creates a graded homework section within a chapter and returns the section.
"""
...
...
@@ -151,12 +160,44 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
category
=
'chapter'
)
section
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter
.
location
,
display_name
=
name
,
category
=
'sequential'
,
metadata
=
{
'graded'
:
True
,
'format'
:
section_format
}
)
if
late
:
section
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter
.
location
,
display_name
=
name
,
category
=
'sequential'
,
metadata
=
{
'graded'
:
True
,
'format'
:
section_format
,
'due'
:
'2013-05-20T23:30'
}
)
elif
reset
:
section
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter
.
location
,
display_name
=
name
,
category
=
'sequential'
,
rerandomize
=
'always'
,
metadata
=
{
'graded'
:
True
,
'format'
:
section_format
,
}
)
elif
showanswer
:
section
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter
.
location
,
display_name
=
name
,
category
=
'sequential'
,
showanswer
=
'never'
,
metadata
=
{
'graded'
:
True
,
'format'
:
section_format
,
}
)
else
:
section
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter
.
location
,
display_name
=
name
,
category
=
'sequential'
,
metadata
=
{
'graded'
:
True
,
'format'
:
section_format
}
)
# now that we've added the problem and section to the course
# we fetch the course from the database so the object we are
...
...
@@ -257,7 +298,7 @@ class TestCourseGrader(TestSubmittingProblems):
hw_section
=
next
(
section
for
section
in
sections_list
if
section
.
get
(
'url_name'
)
==
hw_url_name
)
return
[
s
.
earned
for
s
in
hw_section
[
'scores'
]]
def
basic_setup
(
self
):
def
basic_setup
(
self
,
late
=
False
,
reset
=
False
,
showanswer
=
False
):
"""
Set up a simple course for testing basic grading functionality.
"""
...
...
@@ -278,7 +319,7 @@ class TestCourseGrader(TestSubmittingProblems):
self
.
add_grading_policy
(
grading_policy
)
# set up a simple course with four problems
self
.
homework
=
self
.
add_graded_section_to_course
(
'homework'
)
self
.
homework
=
self
.
add_graded_section_to_course
(
'homework'
,
late
=
late
,
reset
=
reset
,
showanswer
=
showanswer
)
self
.
add_dropdown_to_section
(
self
.
homework
.
location
,
'p1'
,
1
)
self
.
add_dropdown_to_section
(
self
.
homework
.
location
,
'p2'
,
1
)
self
.
add_dropdown_to_section
(
self
.
homework
.
location
,
'p3'
,
1
)
...
...
@@ -346,6 +387,41 @@ class TestCourseGrader(TestSubmittingProblems):
self
.
add_dropdown_to_section
(
self
.
homework3
.
location
,
self
.
hw3_names
[
0
],
1
)
self
.
add_dropdown_to_section
(
self
.
homework3
.
location
,
self
.
hw3_names
[
1
],
1
)
def
test_submission_late
(
self
):
"""Test problem for due date in the past"""
self
.
basic_setup
(
late
=
True
)
resp
=
self
.
submit_question_answer
(
'p1'
,
{
'2_1'
:
'Correct'
})
self
.
assertEqual
(
resp
.
status_code
,
200
)
err_msg
=
(
"The state of this problem has changed since you loaded this page. "
"Please refresh your page."
)
self
.
assertEqual
(
json
.
loads
(
resp
.
content
)
.
get
(
"success"
),
err_msg
)
def
test_submission_reset
(
self
):
"""Test problem ProcessingErrors due to resets"""
self
.
basic_setup
(
reset
=
True
)
resp
=
self
.
submit_question_answer
(
'p1'
,
{
'2_1'
:
'Correct'
})
# submit a second time to draw NotFoundError
resp
=
self
.
submit_question_answer
(
'p1'
,
{
'2_1'
:
'Correct'
})
self
.
assertEqual
(
resp
.
status_code
,
200
)
err_msg
=
(
"The state of this problem has changed since you loaded this page. "
"Please refresh your page."
)
self
.
assertEqual
(
json
.
loads
(
resp
.
content
)
.
get
(
"success"
),
err_msg
)
def
test_submission_show_answer
(
self
):
"""Test problem for ProcessingErrors due to showing answer"""
self
.
basic_setup
(
showanswer
=
True
)
resp
=
self
.
show_question_answer
(
'p1'
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
err_msg
=
(
"The state of this problem has changed since you loaded this page. "
"Please refresh your page."
)
self
.
assertEqual
(
json
.
loads
(
resp
.
content
)
.
get
(
"success"
),
err_msg
)
def
test_none_grade
(
self
):
"""
Check grade is 0 to begin with.
...
...
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