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
79a2b6e2
Commit
79a2b6e2
authored
May 16, 2017
by
Gregory Martin
Committed by
Sanford Student
May 31, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Eventing for grading policy change
parent
aac143e6
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
138 additions
and
25 deletions
+138
-25
cms/djangoapps/contentstore/signals/handlers.py
+6
-1
cms/djangoapps/contentstore/tests/test_course_settings.py
+90
-10
cms/djangoapps/models/settings/course_grading.py
+36
-14
lms/djangoapps/grades/tasks.py
+6
-0
No files found.
cms/djangoapps/contentstore/signals/handlers.py
View file @
79a2b6e2
...
@@ -11,6 +11,7 @@ from contentstore.proctoring import register_special_exams
...
@@ -11,6 +11,7 @@ from contentstore.proctoring import register_special_exams
from
lms.djangoapps.grades.tasks
import
compute_all_grades_for_course
from
lms.djangoapps.grades.tasks
import
compute_all_grades_for_course
from
openedx.core.djangoapps.credit.signals
import
on_course_publish
from
openedx.core.djangoapps.credit.signals
import
on_course_publish
from
openedx.core.lib.gating
import
api
as
gating_api
from
openedx.core.lib.gating
import
api
as
gating_api
from
track.event_transaction_utils
import
get_event_transaction_id
,
get_event_transaction_type
from
util.module_utils
import
yield_dynamic_descriptor_descendants
from
util.module_utils
import
yield_dynamic_descriptor_descendants
from
.signals
import
GRADING_POLICY_CHANGED
from
.signals
import
GRADING_POLICY_CHANGED
from
xmodule.modulestore.django
import
SignalHandler
,
modulestore
from
xmodule.modulestore.django
import
SignalHandler
,
modulestore
...
@@ -95,7 +96,11 @@ def handle_grading_policy_changed(sender, **kwargs):
...
@@ -95,7 +96,11 @@ def handle_grading_policy_changed(sender, **kwargs):
Receives signal and kicks off celery task to recalculate grades
Receives signal and kicks off celery task to recalculate grades
"""
"""
course_key
=
kwargs
.
get
(
'course_key'
)
course_key
=
kwargs
.
get
(
'course_key'
)
result
=
compute_all_grades_for_course
.
apply_async
(
course_key
=
course_key
)
result
=
compute_all_grades_for_course
.
apply_async
(
course_key
=
course_key
,
event_transaction_id
=
get_event_transaction_id
(),
event_transaction_type
=
get_event_transaction_type
(),
)
log
.
info
(
"Grades: Created {task_name}[{task_id}] with arguments {kwargs}"
.
format
(
log
.
info
(
"Grades: Created {task_name}[{task_id}] with arguments {kwargs}"
.
format
(
task_name
=
compute_all_grades_for_course
.
name
,
task_name
=
compute_all_grades_for_course
.
name
,
task_id
=
result
.
task_id
,
task_id
=
result
.
task_id
,
...
...
cms/djangoapps/contentstore/tests/test_course_settings.py
View file @
79a2b6e2
...
@@ -15,7 +15,7 @@ from milestones.tests.utils import MilestonesTestCaseMixin
...
@@ -15,7 +15,7 @@ from milestones.tests.utils import MilestonesTestCaseMixin
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
from
contentstore.utils
import
reverse_course_url
,
reverse_usage_url
from
contentstore.utils
import
reverse_course_url
,
reverse_usage_url
from
models.settings.course_grading
import
CourseGradingModel
from
models.settings.course_grading
import
CourseGradingModel
,
GRADING_POLICY_CHANGED_EVENT_TYPE
,
hash_grading_policy
from
models.settings.course_metadata
import
CourseMetadata
from
models.settings.course_metadata
import
CourseMetadata
from
models.settings.encoder
import
CourseSettingsEncoder
from
models.settings.encoder
import
CourseSettingsEncoder
from
openedx.core.djangoapps.models.course_details
import
CourseDetails
from
openedx.core.djangoapps.models.course_details
import
CourseDetails
...
@@ -418,19 +418,21 @@ class CourseGradingTest(CourseTestCase):
...
@@ -418,19 +418,21 @@ class CourseGradingTest(CourseTestCase):
subgrader
=
CourseGradingModel
.
fetch_grader
(
self
.
course
.
id
,
i
)
subgrader
=
CourseGradingModel
.
fetch_grader
(
self
.
course
.
id
,
i
)
self
.
assertDictEqual
(
grader
,
subgrader
,
str
(
i
)
+
"th graders not equal"
)
self
.
assertDictEqual
(
grader
,
subgrader
,
str
(
i
)
+
"th graders not equal"
)
@mock.patch
(
'track.event_transaction_utils.uuid4'
)
@mock.patch
(
'models.settings.course_grading.tracker'
)
@mock.patch
(
'contentstore.signals.signals.GRADING_POLICY_CHANGED.send'
)
@mock.patch
(
'contentstore.signals.signals.GRADING_POLICY_CHANGED.send'
)
@ddt.data
(
ModuleStoreEnum
.
Type
.
mongo
,
ModuleStoreEnum
.
Type
.
split
)
@ddt.data
(
ModuleStoreEnum
.
Type
.
mongo
,
ModuleStoreEnum
.
Type
.
split
)
def
test_update_from_json
(
self
,
store
,
send_signal
):
def
test_update_from_json
(
self
,
store
,
send_signal
,
tracker
,
uuid
):
uuid
.
return_value
=
"mockUUID"
self
.
course
=
CourseFactory
.
create
(
default_store
=
store
)
self
.
course
=
CourseFactory
.
create
(
default_store
=
store
)
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"Noop update"
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"Noop update"
)
grading_policy_1
=
self
.
_grading_policy_hash_for_course
()
test_grader
.
graders
[
0
][
'weight'
]
=
test_grader
.
graders
[
0
]
.
get
(
'weight'
)
*
2
test_grader
.
graders
[
0
][
'weight'
]
=
test_grader
.
graders
[
0
]
.
get
(
'weight'
)
*
2
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"Weight[0] * 2"
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"Weight[0] * 2"
)
grading_policy_2
=
self
.
_grading_policy_hash_for_course
()
# test for bug LMS-11485
# test for bug LMS-11485
with
modulestore
()
.
bulk_operations
(
self
.
course
.
id
):
with
modulestore
()
.
bulk_operations
(
self
.
course
.
id
):
new_grader
=
test_grader
.
graders
[
0
]
.
copy
()
new_grader
=
test_grader
.
graders
[
0
]
.
copy
()
...
@@ -442,11 +444,11 @@ class CourseGradingTest(CourseTestCase):
...
@@ -442,11 +444,11 @@ class CourseGradingTest(CourseTestCase):
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
)
grading_policy_3
=
self
.
_grading_policy_hash_for_course
()
test_grader
.
grade_cutoffs
[
'D'
]
=
0.3
test_grader
.
grade_cutoffs
[
'D'
]
=
0.3
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"cutoff add D"
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"cutoff add D"
)
grading_policy_4
=
self
.
_grading_policy_hash_for_course
()
test_grader
.
grace_period
=
{
'hours'
:
4
,
'minutes'
:
5
,
'seconds'
:
0
}
test_grader
.
grace_period
=
{
'hours'
:
4
,
'minutes'
:
5
,
'seconds'
:
0
}
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
altered_grader
=
CourseGradingModel
.
update_from_json
(
self
.
course
.
id
,
test_grader
.
__dict__
,
self
.
user
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"4 hour grace period"
)
self
.
assertDictEqual
(
test_grader
.
__dict__
,
altered_grader
.
__dict__
,
"4 hour grace period"
)
...
@@ -460,23 +462,46 @@ class CourseGradingTest(CourseTestCase):
...
@@ -460,23 +462,46 @@ class CourseGradingTest(CourseTestCase):
mock
.
call
(
sender
=
CourseGradingModel
,
user_id
=
self
.
user
.
id
,
course_id
=
self
.
course
.
id
),
mock
.
call
(
sender
=
CourseGradingModel
,
user_id
=
self
.
user
.
id
,
course_id
=
self
.
course
.
id
),
])
])
# one for each of the calls to update_from_json(); the last update doesn't actually change the parts of the
# policy that get hashed
tracker
.
emit
.
assert_has_calls
([
mock
.
call
(
GRADING_POLICY_CHANGED_EVENT_TYPE
,
{
'course_id'
:
unicode
(
self
.
course
.
id
),
'event_transaction_type'
:
'edx.grades.grading_policy_changed'
,
'grading_policy_hash'
:
policy_hash
,
'user_id'
:
unicode
(
self
.
user
.
id
),
'event_transaction_id'
:
'mockUUID'
,
}
)
for
policy_hash
in
(
grading_policy_1
,
grading_policy_2
,
grading_policy_3
,
grading_policy_4
,
grading_policy_4
)
])
@mock.patch
(
'track.event_transaction_utils.uuid4'
)
@mock.patch
(
'models.settings.course_grading.tracker'
)
@mock.patch
(
'contentstore.signals.signals.GRADING_POLICY_CHANGED.send'
)
@mock.patch
(
'contentstore.signals.signals.GRADING_POLICY_CHANGED.send'
)
def
test_update_grader_from_json
(
self
,
send_signal
):
def
test_update_grader_from_json
(
self
,
send_signal
,
tracker
,
uuid
):
uuid
.
return_value
=
'mockUUID'
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
altered_grader
=
CourseGradingModel
.
update_grader_from_json
(
altered_grader
=
CourseGradingModel
.
update_grader_from_json
(
self
.
course
.
id
,
test_grader
.
graders
[
1
],
self
.
user
self
.
course
.
id
,
test_grader
.
graders
[
1
],
self
.
user
)
)
self
.
assertDictEqual
(
test_grader
.
graders
[
1
],
altered_grader
,
"Noop update"
)
self
.
assertDictEqual
(
test_grader
.
graders
[
1
],
altered_grader
,
"Noop update"
)
grading_policy_1
=
self
.
_grading_policy_hash_for_course
()
test_grader
.
graders
[
1
][
'min_count'
]
=
test_grader
.
graders
[
1
]
.
get
(
'min_count'
)
+
2
test_grader
.
graders
[
1
][
'min_count'
]
=
test_grader
.
graders
[
1
]
.
get
(
'min_count'
)
+
2
altered_grader
=
CourseGradingModel
.
update_grader_from_json
(
altered_grader
=
CourseGradingModel
.
update_grader_from_json
(
self
.
course
.
id
,
test_grader
.
graders
[
1
],
self
.
user
)
self
.
course
.
id
,
test_grader
.
graders
[
1
],
self
.
user
)
self
.
assertDictEqual
(
test_grader
.
graders
[
1
],
altered_grader
,
"min_count[1] + 2"
)
self
.
assertDictEqual
(
test_grader
.
graders
[
1
],
altered_grader
,
"min_count[1] + 2"
)
grading_policy_2
=
self
.
_grading_policy_hash_for_course
()
test_grader
.
graders
[
1
][
'drop_count'
]
=
test_grader
.
graders
[
1
]
.
get
(
'drop_count'
)
+
1
test_grader
.
graders
[
1
][
'drop_count'
]
=
test_grader
.
graders
[
1
]
.
get
(
'drop_count'
)
+
1
altered_grader
=
CourseGradingModel
.
update_grader_from_json
(
altered_grader
=
CourseGradingModel
.
update_grader_from_json
(
self
.
course
.
id
,
test_grader
.
graders
[
1
],
self
.
user
)
self
.
course
.
id
,
test_grader
.
graders
[
1
],
self
.
user
)
self
.
assertDictEqual
(
test_grader
.
graders
[
1
],
altered_grader
,
"drop_count[1] + 2"
)
self
.
assertDictEqual
(
test_grader
.
graders
[
1
],
altered_grader
,
"drop_count[1] + 2"
)
grading_policy_3
=
self
.
_grading_policy_hash_for_course
()
# one for each of the calls to update_grader_from_json()
# one for each of the calls to update_grader_from_json()
send_signal
.
assert_has_calls
([
send_signal
.
assert_has_calls
([
...
@@ -485,23 +510,57 @@ class CourseGradingTest(CourseTestCase):
...
@@ -485,23 +510,57 @@ class CourseGradingTest(CourseTestCase):
mock
.
call
(
sender
=
CourseGradingModel
,
user_id
=
self
.
user
.
id
,
course_id
=
self
.
course
.
id
),
mock
.
call
(
sender
=
CourseGradingModel
,
user_id
=
self
.
user
.
id
,
course_id
=
self
.
course
.
id
),
])
])
def
test_update_cutoffs_from_json
(
self
):
# one for each of the calls to update_grader_from_json()
tracker
.
emit
.
assert_has_calls
([
mock
.
call
(
GRADING_POLICY_CHANGED_EVENT_TYPE
,
{
'course_id'
:
unicode
(
self
.
course
.
id
),
'event_transaction_type'
:
'edx.grades.grading_policy_changed'
,
'grading_policy_hash'
:
policy_hash
,
'user_id'
:
unicode
(
self
.
user
.
id
),
'event_transaction_id'
:
'mockUUID'
,
}
)
for
policy_hash
in
{
grading_policy_1
,
grading_policy_2
,
grading_policy_3
}
])
@mock.patch
(
'track.event_transaction_utils.uuid4'
)
@mock.patch
(
'models.settings.course_grading.tracker'
)
def
test_update_cutoffs_from_json
(
self
,
tracker
,
uuid
):
uuid
.
return_value
=
'mockUUID'
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
CourseGradingModel
.
update_cutoffs_from_json
(
self
.
course
.
id
,
test_grader
.
grade_cutoffs
,
self
.
user
)
CourseGradingModel
.
update_cutoffs_from_json
(
self
.
course
.
id
,
test_grader
.
grade_cutoffs
,
self
.
user
)
# Unlike other tests, need to actually perform a db fetch for this test since update_cutoffs_from_json
# Unlike other tests, need to actually perform a db fetch for this test since update_cutoffs_from_json
# simply returns the cutoffs you send into it, rather than returning the db contents.
# simply returns the cutoffs you send into it, rather than returning the db contents.
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
self
.
assertDictEqual
(
test_grader
.
grade_cutoffs
,
altered_grader
.
grade_cutoffs
,
"Noop update"
)
self
.
assertDictEqual
(
test_grader
.
grade_cutoffs
,
altered_grader
.
grade_cutoffs
,
"Noop update"
)
grading_policy_1
=
self
.
_grading_policy_hash_for_course
()
test_grader
.
grade_cutoffs
[
'D'
]
=
0.3
test_grader
.
grade_cutoffs
[
'D'
]
=
0.3
CourseGradingModel
.
update_cutoffs_from_json
(
self
.
course
.
id
,
test_grader
.
grade_cutoffs
,
self
.
user
)
CourseGradingModel
.
update_cutoffs_from_json
(
self
.
course
.
id
,
test_grader
.
grade_cutoffs
,
self
.
user
)
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
self
.
assertDictEqual
(
test_grader
.
grade_cutoffs
,
altered_grader
.
grade_cutoffs
,
"cutoff add D"
)
self
.
assertDictEqual
(
test_grader
.
grade_cutoffs
,
altered_grader
.
grade_cutoffs
,
"cutoff add D"
)
grading_policy_2
=
self
.
_grading_policy_hash_for_course
()
test_grader
.
grade_cutoffs
[
'Pass'
]
=
0.75
test_grader
.
grade_cutoffs
[
'Pass'
]
=
0.75
CourseGradingModel
.
update_cutoffs_from_json
(
self
.
course
.
id
,
test_grader
.
grade_cutoffs
,
self
.
user
)
CourseGradingModel
.
update_cutoffs_from_json
(
self
.
course
.
id
,
test_grader
.
grade_cutoffs
,
self
.
user
)
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
altered_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
self
.
assertDictEqual
(
test_grader
.
grade_cutoffs
,
altered_grader
.
grade_cutoffs
,
"cutoff change 'Pass'"
)
self
.
assertDictEqual
(
test_grader
.
grade_cutoffs
,
altered_grader
.
grade_cutoffs
,
"cutoff change 'Pass'"
)
grading_policy_3
=
self
.
_grading_policy_hash_for_course
()
# one for each of the calls to update_cutoffs_from_json()
tracker
.
emit
.
assert_has_calls
([
mock
.
call
(
GRADING_POLICY_CHANGED_EVENT_TYPE
,
{
'course_id'
:
unicode
(
self
.
course
.
id
),
'event_transaction_type'
:
'edx.grades.grading_policy_changed'
,
'grading_policy_hash'
:
policy_hash
,
'user_id'
:
unicode
(
self
.
user
.
id
),
'event_transaction_id'
:
'mockUUID'
,
}
)
for
policy_hash
in
(
grading_policy_1
,
grading_policy_2
,
grading_policy_3
)
])
def
test_delete_grace_period
(
self
):
def
test_delete_grace_period
(
self
):
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
test_grader
=
CourseGradingModel
.
fetch
(
self
.
course
.
id
)
...
@@ -526,8 +585,11 @@ class CourseGradingTest(CourseTestCase):
...
@@ -526,8 +585,11 @@ class CourseGradingTest(CourseTestCase):
# Once deleted, the grace period should simply be None
# Once deleted, the grace period should simply be None
self
.
assertEqual
(
None
,
altered_grader
.
grace_period
,
"Delete grace period"
)
self
.
assertEqual
(
None
,
altered_grader
.
grace_period
,
"Delete grace period"
)
@mock.patch
(
'track.event_transaction_utils.uuid4'
)
@mock.patch
(
'models.settings.course_grading.tracker'
)
@mock.patch
(
'contentstore.signals.signals.GRADING_POLICY_CHANGED.send'
)
@mock.patch
(
'contentstore.signals.signals.GRADING_POLICY_CHANGED.send'
)
def
test_update_section_grader_type
(
self
,
send_signal
):
def
test_update_section_grader_type
(
self
,
send_signal
,
tracker
,
uuid
):
uuid
.
return_value
=
'mockUUID'
# Get the descriptor and the section_grader_type and assert they are the default values
# Get the descriptor and the section_grader_type and assert they are the default values
descriptor
=
modulestore
()
.
get_item
(
self
.
course
.
location
)
descriptor
=
modulestore
()
.
get_item
(
self
.
course
.
location
)
section_grader_type
=
CourseGradingModel
.
get_section_grader_type
(
self
.
course
.
location
)
section_grader_type
=
CourseGradingModel
.
get_section_grader_type
(
self
.
course
.
location
)
...
@@ -540,6 +602,7 @@ class CourseGradingTest(CourseTestCase):
...
@@ -540,6 +602,7 @@ class CourseGradingTest(CourseTestCase):
CourseGradingModel
.
update_section_grader_type
(
self
.
course
,
'Homework'
,
self
.
user
)
CourseGradingModel
.
update_section_grader_type
(
self
.
course
,
'Homework'
,
self
.
user
)
descriptor
=
modulestore
()
.
get_item
(
self
.
course
.
location
)
descriptor
=
modulestore
()
.
get_item
(
self
.
course
.
location
)
section_grader_type
=
CourseGradingModel
.
get_section_grader_type
(
self
.
course
.
location
)
section_grader_type
=
CourseGradingModel
.
get_section_grader_type
(
self
.
course
.
location
)
grading_policy_1
=
self
.
_grading_policy_hash_for_course
()
self
.
assertEqual
(
'Homework'
,
section_grader_type
[
'graderType'
])
self
.
assertEqual
(
'Homework'
,
section_grader_type
[
'graderType'
])
self
.
assertEqual
(
'Homework'
,
descriptor
.
format
)
self
.
assertEqual
(
'Homework'
,
descriptor
.
format
)
...
@@ -549,6 +612,7 @@ class CourseGradingTest(CourseTestCase):
...
@@ -549,6 +612,7 @@ class CourseGradingTest(CourseTestCase):
CourseGradingModel
.
update_section_grader_type
(
self
.
course
,
'notgraded'
,
self
.
user
)
CourseGradingModel
.
update_section_grader_type
(
self
.
course
,
'notgraded'
,
self
.
user
)
descriptor
=
modulestore
()
.
get_item
(
self
.
course
.
location
)
descriptor
=
modulestore
()
.
get_item
(
self
.
course
.
location
)
section_grader_type
=
CourseGradingModel
.
get_section_grader_type
(
self
.
course
.
location
)
section_grader_type
=
CourseGradingModel
.
get_section_grader_type
(
self
.
course
.
location
)
grading_policy_2
=
self
.
_grading_policy_hash_for_course
()
self
.
assertEqual
(
'notgraded'
,
section_grader_type
[
'graderType'
])
self
.
assertEqual
(
'notgraded'
,
section_grader_type
[
'graderType'
])
self
.
assertEqual
(
None
,
descriptor
.
format
)
self
.
assertEqual
(
None
,
descriptor
.
format
)
...
@@ -560,6 +624,19 @@ class CourseGradingTest(CourseTestCase):
...
@@ -560,6 +624,19 @@ class CourseGradingTest(CourseTestCase):
mock
.
call
(
sender
=
CourseGradingModel
,
user_id
=
self
.
user
.
id
,
course_id
=
self
.
course
.
id
),
mock
.
call
(
sender
=
CourseGradingModel
,
user_id
=
self
.
user
.
id
,
course_id
=
self
.
course
.
id
),
])
])
tracker
.
emit
.
assert_has_calls
([
mock
.
call
(
GRADING_POLICY_CHANGED_EVENT_TYPE
,
{
'course_id'
:
unicode
(
self
.
course
.
id
),
'event_transaction_type'
:
'edx.grades.grading_policy_changed'
,
'grading_policy_hash'
:
policy_hash
,
'user_id'
:
unicode
(
self
.
user
.
id
),
'event_transaction_id'
:
'mockUUID'
,
}
)
for
policy_hash
in
(
grading_policy_1
,
grading_policy_2
)
])
def
_model_from_url
(
self
,
url_base
):
def
_model_from_url
(
self
,
url_base
):
response
=
self
.
client
.
get_json
(
url_base
)
response
=
self
.
client
.
get_json
(
url_base
)
return
json
.
loads
(
response
.
content
)
return
json
.
loads
(
response
.
content
)
...
@@ -652,6 +729,9 @@ class CourseGradingTest(CourseTestCase):
...
@@ -652,6 +729,9 @@ class CourseGradingTest(CourseTestCase):
response
=
self
.
client
.
get_json
(
grade_type_url
+
'?fields=graderType'
)
response
=
self
.
client
.
get_json
(
grade_type_url
+
'?fields=graderType'
)
self
.
assertEqual
(
json
.
loads
(
response
.
content
)
.
get
(
'graderType'
),
u'notgraded'
)
self
.
assertEqual
(
json
.
loads
(
response
.
content
)
.
get
(
'graderType'
),
u'notgraded'
)
def
_grading_policy_hash_for_course
(
self
):
return
hash_grading_policy
(
modulestore
()
.
get_course
(
self
.
course
.
id
)
.
grading_policy
)
@ddt.ddt
@ddt.ddt
class
CourseMetadataEditingTest
(
CourseTestCase
):
class
CourseMetadataEditingTest
(
CourseTestCase
):
...
...
cms/djangoapps/models/settings/course_grading.py
View file @
79a2b6e2
from
base64
import
b64encode
from
datetime
import
timedelta
from
datetime
import
timedelta
from
hashlib
import
sha1
import
json
from
contentstore.signals.signals
import
GRADING_POLICY_CHANGED
from
contentstore.signals.signals
import
GRADING_POLICY_CHANGED
from
eventtracking
import
tracker
from
track.event_transaction_utils
import
create_new_event_transaction_id
,
set_event_transaction_type
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
GRADING_POLICY_CHANGED_EVENT_TYPE
=
'edx.grades.grading_policy_changed'
class
CourseGradingModel
(
object
):
class
CourseGradingModel
(
object
):
"""
"""
...
@@ -66,8 +73,7 @@ class CourseGradingModel(object):
...
@@ -66,8 +73,7 @@ class CourseGradingModel(object):
CourseGradingModel
.
update_grace_period_from_json
(
course_key
,
jsondict
[
'grace_period'
],
user
)
CourseGradingModel
.
update_grace_period_from_json
(
course_key
,
jsondict
[
'grace_period'
],
user
)
CourseGradingModel
.
update_minimum_grade_credit_from_json
(
course_key
,
jsondict
[
'minimum_grade_credit'
],
user
)
CourseGradingModel
.
update_minimum_grade_credit_from_json
(
course_key
,
jsondict
[
'minimum_grade_credit'
],
user
)
_grading_event_and_signal
(
course_key
,
user
.
id
)
GRADING_POLICY_CHANGED
.
send
(
sender
=
CourseGradingModel
,
user_id
=
user
.
id
,
course_id
=
course_key
)
return
CourseGradingModel
.
fetch
(
course_key
)
return
CourseGradingModel
.
fetch
(
course_key
)
...
@@ -89,8 +95,7 @@ class CourseGradingModel(object):
...
@@ -89,8 +95,7 @@ class CourseGradingModel(object):
descriptor
.
raw_grader
.
append
(
grader
)
descriptor
.
raw_grader
.
append
(
grader
)
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
_grading_event_and_signal
(
course_key
,
user
.
id
)
GRADING_POLICY_CHANGED
.
send
(
sender
=
CourseGradingModel
,
user_id
=
user
.
id
,
course_id
=
course_key
)
return
CourseGradingModel
.
jsonize_grader
(
index
,
descriptor
.
raw_grader
[
index
])
return
CourseGradingModel
.
jsonize_grader
(
index
,
descriptor
.
raw_grader
[
index
])
...
@@ -104,7 +109,7 @@ class CourseGradingModel(object):
...
@@ -104,7 +109,7 @@ class CourseGradingModel(object):
descriptor
.
grade_cutoffs
=
cutoffs
descriptor
.
grade_cutoffs
=
cutoffs
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
_grading_event_and_signal
(
course_key
,
user
.
id
)
return
cutoffs
return
cutoffs
@staticmethod
@staticmethod
...
@@ -160,8 +165,7 @@ class CourseGradingModel(object):
...
@@ -160,8 +165,7 @@ class CourseGradingModel(object):
descriptor
.
raw_grader
=
descriptor
.
raw_grader
descriptor
.
raw_grader
=
descriptor
.
raw_grader
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
_grading_event_and_signal
(
course_key
,
user
.
id
)
GRADING_POLICY_CHANGED
.
send
(
sender
=
CourseGradingModel
,
user_id
=
user
.
id
,
course_id
=
course_key
)
@staticmethod
@staticmethod
def
delete_grace_period
(
course_key
,
user
):
def
delete_grace_period
(
course_key
,
user
):
...
@@ -192,13 +196,7 @@ class CourseGradingModel(object):
...
@@ -192,13 +196,7 @@ class CourseGradingModel(object):
del
descriptor
.
graded
del
descriptor
.
graded
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
modulestore
()
.
update_item
(
descriptor
,
user
.
id
)
_grading_event_and_signal
(
descriptor
.
location
.
course_key
,
user
.
id
)
GRADING_POLICY_CHANGED
.
send
(
sender
=
CourseGradingModel
,
user_id
=
user
.
id
,
course_id
=
descriptor
.
location
.
course_key
)
return
{
'graderType'
:
grader_type
}
return
{
'graderType'
:
grader_type
}
@staticmethod
@staticmethod
...
@@ -253,3 +251,27 @@ class CourseGradingModel(object):
...
@@ -253,3 +251,27 @@ class CourseGradingModel(object):
"short_label"
:
grader
.
get
(
'short_label'
,
""
),
"short_label"
:
grader
.
get
(
'short_label'
,
""
),
"weight"
:
grader
.
get
(
'weight'
,
0
)
*
100
,
"weight"
:
grader
.
get
(
'weight'
,
0
)
*
100
,
}
}
def
_grading_event_and_signal
(
course_key
,
user_id
):
name
=
GRADING_POLICY_CHANGED_EVENT_TYPE
course
=
modulestore
()
.
get_course
(
course_key
)
data
=
{
"course_id"
:
unicode
(
course_key
),
"user_id"
:
unicode
(
user_id
),
"grading_policy_hash"
:
unicode
(
hash_grading_policy
(
course
.
grading_policy
)),
"event_transaction_id"
:
unicode
(
create_new_event_transaction_id
()),
"event_transaction_type"
:
GRADING_POLICY_CHANGED_EVENT_TYPE
,
}
tracker
.
emit
(
name
,
data
)
GRADING_POLICY_CHANGED
.
send
(
sender
=
CourseGradingModel
,
user_id
=
user_id
,
course_id
=
course_key
)
def
hash_grading_policy
(
grading_policy
):
ordered_policy
=
json
.
dumps
(
grading_policy
,
separators
=
(
','
,
':'
),
# Remove spaces from separators for more compact representation
sort_keys
=
True
,
)
return
b64encode
(
sha1
(
ordered_policy
)
.
digest
())
lms/djangoapps/grades/tasks.py
View file @
79a2b6e2
...
@@ -91,6 +91,12 @@ def compute_grades_for_course_v2(self, **kwargs):
...
@@ -91,6 +91,12 @@ def compute_grades_for_course_v2(self, **kwargs):
waffle switch. If false or not provided, use the global value of
waffle switch. If false or not provided, use the global value of
the ESTIMATE_FIRST_ATTEMPTED waffle switch.
the ESTIMATE_FIRST_ATTEMPTED waffle switch.
"""
"""
if
'event_transaction_id'
in
kwargs
:
set_event_transaction_id
(
kwargs
[
'event_transaction_id'
])
if
'event_transaction_type'
in
kwargs
:
set_event_transaction_type
(
kwargs
[
'event_transaction_type'
])
course_key
=
kwargs
.
pop
(
'course_key'
)
course_key
=
kwargs
.
pop
(
'course_key'
)
offset
=
kwargs
.
pop
(
'offset'
)
offset
=
kwargs
.
pop
(
'offset'
)
batch_size
=
kwargs
.
pop
(
'batch_size'
)
batch_size
=
kwargs
.
pop
(
'batch_size'
)
...
...
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