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):
...
@@ -152,6 +152,7 @@ class CapaFields(object):
scope
=
Scope
.
settings
scope
=
Scope
.
settings
)
)
class
CapaModule
(
CapaFields
,
XModule
):
class
CapaModule
(
CapaFields
,
XModule
):
"""
"""
An XModule implementing LonCapa format problems, implemented by way of
An XModule implementing LonCapa format problems, implemented by way of
...
@@ -552,6 +553,16 @@ class CapaModule(CapaFields, XModule):
...
@@ -552,6 +553,16 @@ class CapaModule(CapaFields, XModule):
'ungraded_response'
:
self
.
handle_ungraded_response
'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
:
if
dispatch
not
in
handlers
:
return
'Error'
return
'Error'
...
@@ -559,9 +570,14 @@ class CapaModule(CapaFields, XModule):
...
@@ -559,9 +570,14 @@ class CapaModule(CapaFields, XModule):
try
:
try
:
result
=
handlers
[
dispatch
](
data
)
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
:
except
Exception
as
err
:
_
,
_
,
traceback_obj
=
sys
.
exc_info
()
_
,
_
,
traceback_obj
=
sys
.
exc_info
()
raise
ProcessingError
(
err
.
message
,
traceback_obj
)
raise
ProcessingError
,
(
generic_error_message
,
err
),
traceback_obj
after
=
self
.
get_progress
()
after
=
self
.
get_progress
()
...
@@ -1125,7 +1141,6 @@ class CapaDescriptor(CapaFields, RawDescriptor):
...
@@ -1125,7 +1141,6 @@ class CapaDescriptor(CapaFields, RawDescriptor):
problem
.
rerandomize
=
"always"
problem
.
rerandomize
=
"always"
return
problem
return
problem
@property
@property
def
non_editable_metadata_fields
(
self
):
def
non_editable_metadata_fields
(
self
):
non_editable_fields
=
super
(
CapaDescriptor
,
self
)
.
non_editable_metadata_fields
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
...
@@ -10,7 +10,7 @@ from django.core.cache import cache
from
django.core.exceptions
import
PermissionDenied
from
django.core.exceptions
import
PermissionDenied
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.http
import
Http404
from
django.http
import
Http404
from
django.http
import
HttpResponse
,
HttpResponseBadRequest
from
django.http
import
HttpResponse
from
django.views.decorators.csrf
import
csrf_exempt
from
django.views.decorators.csrf
import
csrf_exempt
import
pyparsing
import
pyparsing
...
@@ -38,6 +38,7 @@ from courseware.masquerade import setup_masquerade
...
@@ -38,6 +38,7 @@ from courseware.masquerade import setup_masquerade
from
courseware.model_data
import
LmsKeyValueStore
,
LmsUsage
,
ModelDataCache
from
courseware.model_data
import
LmsKeyValueStore
,
LmsUsage
,
ModelDataCache
from
courseware.models
import
StudentModule
from
courseware.models
import
StudentModule
from
util.sandboxing
import
can_execute_unsafe_code
from
util.sandboxing
import
can_execute_unsafe_code
from
util.json_request
import
JsonResponse
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -509,11 +510,11 @@ def modx_dispatch(request, dispatch, location, course_id):
...
@@ -509,11 +510,11 @@ def modx_dispatch(request, dispatch, location, course_id):
log
.
exception
(
"Module indicating to user that request doesn't exist"
)
log
.
exception
(
"Module indicating to user that request doesn't exist"
)
raise
Http404
raise
Http404
# For XModule-specific errors, we
respond with 400
# For XModule-specific errors, we
log the error and respond with an error message
except
ProcessingError
:
except
ProcessingError
as
err
:
log
.
warning
(
"Module encountered an error while prcessing AJAX call"
,
log
.
warning
(
"Module encountered an error while pr
o
cessing AJAX call"
,
exc_info
=
True
)
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
# If any other error occurred, re-raise it to trigger a 500 response
except
:
except
:
...
...
lms/djangoapps/courseware/tests/test_submitting_problems.py
View file @
dfa43501
...
@@ -107,6 +107,15 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -107,6 +107,15 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
resp
=
self
.
client
.
post
(
modx_url
)
resp
=
self
.
client
.
post
(
modx_url
)
return
resp
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
):
def
add_dropdown_to_section
(
self
,
section_location
,
name
,
num_inputs
=
2
):
"""
"""
Create and return a dropdown problem.
Create and return a dropdown problem.
...
@@ -131,7 +140,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -131,7 +140,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
parent_location
=
section_location
,
parent_location
=
section_location
,
category
=
'problem'
,
category
=
'problem'
,
data
=
prob_xml
,
data
=
prob_xml
,
metadata
=
{
'randomize'
:
'always'
},
metadata
=
{
'r
er
andomize'
:
'always'
},
display_name
=
name
display_name
=
name
)
)
...
@@ -139,7 +148,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -139,7 +148,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
self
.
refresh_course
()
self
.
refresh_course
()
return
problem
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.
Creates a graded homework section within a chapter and returns the section.
"""
"""
...
@@ -151,12 +160,44 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
...
@@ -151,12 +160,44 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
category
=
'chapter'
category
=
'chapter'
)
)
section
=
ItemFactory
.
create
(
if
late
:
parent_location
=
self
.
chapter
.
location
,
section
=
ItemFactory
.
create
(
display_name
=
name
,
parent_location
=
self
.
chapter
.
location
,
category
=
'sequential'
,
display_name
=
name
,
metadata
=
{
'graded'
:
True
,
'format'
:
section_format
}
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
# now that we've added the problem and section to the course
# we fetch the course from the database so the object we are
# we fetch the course from the database so the object we are
...
@@ -257,7 +298,7 @@ class TestCourseGrader(TestSubmittingProblems):
...
@@ -257,7 +298,7 @@ class TestCourseGrader(TestSubmittingProblems):
hw_section
=
next
(
section
for
section
in
sections_list
if
section
.
get
(
'url_name'
)
==
hw_url_name
)
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'
]]
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.
Set up a simple course for testing basic grading functionality.
"""
"""
...
@@ -278,7 +319,7 @@ class TestCourseGrader(TestSubmittingProblems):
...
@@ -278,7 +319,7 @@ class TestCourseGrader(TestSubmittingProblems):
self
.
add_grading_policy
(
grading_policy
)
self
.
add_grading_policy
(
grading_policy
)
# set up a simple course with four problems
# 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
,
'p1'
,
1
)
self
.
add_dropdown_to_section
(
self
.
homework
.
location
,
'p2'
,
1
)
self
.
add_dropdown_to_section
(
self
.
homework
.
location
,
'p2'
,
1
)
self
.
add_dropdown_to_section
(
self
.
homework
.
location
,
'p3'
,
1
)
self
.
add_dropdown_to_section
(
self
.
homework
.
location
,
'p3'
,
1
)
...
@@ -346,6 +387,41 @@ class TestCourseGrader(TestSubmittingProblems):
...
@@ -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
[
0
],
1
)
self
.
add_dropdown_to_section
(
self
.
homework3
.
location
,
self
.
hw3_names
[
1
],
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
):
def
test_none_grade
(
self
):
"""
"""
Check grade is 0 to begin with.
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