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
1ab18803
Commit
1ab18803
authored
Aug 09, 2017
by
Tyler Hallada
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove override behavior and log instead
This will break tests.
parent
537966ab
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
25 additions
and
120 deletions
+25
-120
lms/djangoapps/grades/models.py
+1
-32
lms/djangoapps/grades/services.py
+23
-55
lms/djangoapps/grades/tests/test_services.py
+1
-33
No files found.
lms/djangoapps/grades/models.py
View file @
1ab18803
...
@@ -412,38 +412,7 @@ class PersistentSubsectionGrade(DeleteGradesMixin, TimeStampedModel):
...
@@ -412,38 +412,7 @@ class PersistentSubsectionGrade(DeleteGradesMixin, TimeStampedModel):
usage_key
=
params
.
pop
(
'usage_key'
)
usage_key
=
params
.
pop
(
'usage_key'
)
# apply grade override if one exists before saving model
# apply grade override if one exists before saving model
try
:
# EDUCTATOR-1127: remove override until this behavior is verified in production
override
=
PersistentSubsectionGradeOverride
.
objects
.
get
(
grade__user_id
=
user_id
,
grade__course_id
=
usage_key
.
course_key
,
grade__usage_key
=
usage_key
,
)
# EDUCTATOR-1127: no-op and log until this behavior is verified in production
# if override.earned_all_override is not None:
# params['earned_all'] = override.earned_all_override
# if override.possible_all_override is not None:
# params['possible_all'] = override.possible_all_override
# if override.earned_graded_override is not None:
# params['earned_graded'] = override.earned_graded_override
# if override.possible_graded_override is not None:
# params['possible_graded'] = override.possible_graded_override
log
.
info
(
u"EDUCATOR-1127: Subsection grade for user {user_id} on subsection {usage_key} in course "
u"{course_key} would be overridden with params: {params}"
.
format
(
user_id
=
unicode
(
user_id
),
usage_key
=
unicode
(
usage_key
),
course_key
=
unicode
(
usage_key
.
course_key
),
params
=
unicode
({
'earned_all'
:
override
.
earned_all_override
,
'possible_all'
:
override
.
possible_all_override
,
'earned_graded'
:
override
.
earned_graded_override
,
'possible_graded'
:
override
.
possible_graded_override
})
)
)
except
PersistentSubsectionGradeOverride
.
DoesNotExist
:
pass
grade
,
_
=
cls
.
objects
.
update_or_create
(
grade
,
_
=
cls
.
objects
.
update_or_create
(
user_id
=
user_id
,
user_id
=
user_id
,
...
...
lms/djangoapps/grades/services.py
View file @
1ab18803
from
datetime
import
datetime
from
datetime
import
datetime
import
logging
import
pytz
import
pytz
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
from
opaque_keys.edx.keys
import
CourseKey
,
UsageKey
...
@@ -11,6 +12,8 @@ from .constants import ScoreDatabaseTableEnum
...
@@ -11,6 +12,8 @@ from .constants import ScoreDatabaseTableEnum
from
.models
import
PersistentSubsectionGrade
,
PersistentSubsectionGradeOverride
from
.models
import
PersistentSubsectionGrade
,
PersistentSubsectionGradeOverride
from
.signals.signals
import
SUBSECTION_OVERRIDE_CHANGED
from
.signals.signals
import
SUBSECTION_OVERRIDE_CHANGED
log
=
logging
.
getLogger
(
__name__
)
def
_get_key
(
key_or_id
,
key_cls
):
def
_get_key
(
key_or_id
,
key_cls
):
"""
"""
...
@@ -70,40 +73,21 @@ class GradesService(object):
...
@@ -70,40 +73,21 @@ class GradesService(object):
Fires off a recalculate_subsection_grade async task to update the PersistentSubsectionGrade table. Will not
Fires off a recalculate_subsection_grade async task to update the PersistentSubsectionGrade table. Will not
override earned_all or earned_graded value if they are None. Both default to None.
override earned_all or earned_graded value if they are None. Both default to None.
"""
"""
# prevent circular imports:
from
.signals.handlers
import
SUBSECTION_OVERRIDE_EVENT_TYPE
course_key
=
_get_key
(
course_key_or_id
,
CourseKey
)
course_key
=
_get_key
(
course_key_or_id
,
CourseKey
)
usage_key
=
_get_key
(
usage_key_or_id
,
UsageKey
)
usage_key
=
_get_key
(
usage_key_or_id
,
UsageKey
)
grade
=
PersistentSubsectionGrade
.
objects
.
get
(
log
.
info
(
user_id
=
user_id
,
u"EDUCATOR-1127: Subsection grade override for user {user_id} on subsection {usage_key} in course "
course_id
=
course_key
,
u"{course_key} would be created with params: {params}"
usage_key
=
usage_key
.
format
(
)
user_id
=
unicode
(
user_id
),
usage_key
=
unicode
(
usage_key
),
# Create override that will prevent any future updates to grade
course_key
=
unicode
(
course_key
),
override
,
_
=
PersistentSubsectionGradeOverride
.
objects
.
update_or_create
(
params
=
unicode
({
grade
=
grade
,
'earned_all'
:
earned_all
,
earned_all_override
=
earned_all
,
'earned_graded'
:
earned_graded
,
earned_graded_override
=
earned_graded
})
)
)
# Cache a new event id and event type which the signal handler will use to emit a tracking log event.
create_new_event_transaction_id
()
set_event_transaction_type
(
SUBSECTION_OVERRIDE_EVENT_TYPE
)
# Signal will trigger subsection recalculation which will call PersistentSubsectionGrade.update_or_create_grade
# which will use the above override to update the grade before writing to the table.
SUBSECTION_OVERRIDE_CHANGED
.
send
(
sender
=
None
,
user_id
=
user_id
,
course_id
=
unicode
(
course_key
),
usage_id
=
unicode
(
usage_key
),
only_if_higher
=
False
,
modified
=
override
.
modified
,
score_deleted
=
False
,
score_db_table
=
ScoreDatabaseTableEnum
.
overrides
)
)
def
undo_override_subsection_grade
(
self
,
user_id
,
course_key_or_id
,
usage_key_or_id
):
def
undo_override_subsection_grade
(
self
,
user_id
,
course_key_or_id
,
usage_key_or_id
):
...
@@ -113,33 +97,17 @@ class GradesService(object):
...
@@ -113,33 +97,17 @@ class GradesService(object):
Fires off a recalculate_subsection_grade async task to update the PersistentSubsectionGrade table. If the
Fires off a recalculate_subsection_grade async task to update the PersistentSubsectionGrade table. If the
override does not exist, no error is raised, it just triggers the recalculation.
override does not exist, no error is raised, it just triggers the recalculation.
"""
"""
# prevent circular imports:
from
.signals.handlers
import
SUBSECTION_OVERRIDE_EVENT_TYPE
course_key
=
_get_key
(
course_key_or_id
,
CourseKey
)
course_key
=
_get_key
(
course_key_or_id
,
CourseKey
)
usage_key
=
_get_key
(
usage_key_or_id
,
UsageKey
)
usage_key
=
_get_key
(
usage_key_or_id
,
UsageKey
)
override
=
self
.
get_subsection_grade_override
(
user_id
,
course_key
,
usage_key
)
log
.
info
(
# Older rejected exam attempts that transition to verified might not have an override created
u"EDUCATOR-1127: Subsection grade override for user {user_id} on subsection {usage_key} in course "
if
override
is
not
None
:
u"{course_key} would be deleted"
override
.
delete
()
.
format
(
user_id
=
unicode
(
user_id
),
# Cache a new event id and event type which the signal handler will use to emit a tracking log event.
usage_key
=
unicode
(
usage_key
),
create_new_event_transaction_id
()
course_key
=
unicode
(
course_key
)
set_event_transaction_type
(
SUBSECTION_OVERRIDE_EVENT_TYPE
)
)
# Signal will trigger subsection recalculation which will call PersistentSubsectionGrade.update_or_create_grade
# which will no longer use the above deleted override, and instead return the grade to the original score from
# the actual problem responses before writing to the table.
SUBSECTION_OVERRIDE_CHANGED
.
send
(
sender
=
None
,
user_id
=
user_id
,
course_id
=
unicode
(
course_key
),
usage_id
=
unicode
(
usage_key
),
only_if_higher
=
False
,
modified
=
datetime
.
now
()
.
replace
(
tzinfo
=
pytz
.
UTC
),
# Not used when score_deleted=True
score_deleted
=
True
,
score_db_table
=
ScoreDatabaseTableEnum
.
overrides
)
)
def
should_override_grade_on_rejected_exam
(
self
,
course_key_or_id
):
def
should_override_grade_on_rejected_exam
(
self
,
course_key_or_id
):
...
...
lms/djangoapps/grades/tests/test_services.py
View file @
1ab18803
...
@@ -171,28 +171,10 @@ class GradesServiceTests(ModuleStoreTestCase):
...
@@ -171,28 +171,10 @@ class GradesServiceTests(ModuleStoreTestCase):
self
.
course
.
id
,
self
.
course
.
id
,
self
.
subsection
.
location
self
.
subsection
.
location
)
)
self
.
assertIsNotNone
(
override_obj
)
self
.
assertIsNone
(
override_obj
)
self
.
assertEqual
(
override_obj
.
earned_all_override
,
override
[
'earned_all'
])
self
.
assertEqual
(
override_obj
.
earned_graded_override
,
override
[
'earned_graded'
])
self
.
assertEqual
(
self
.
mock_signal
.
call_args
,
call
(
sender
=
None
,
user_id
=
self
.
user
.
id
,
course_id
=
unicode
(
self
.
course
.
id
),
usage_id
=
unicode
(
self
.
subsection
.
location
),
only_if_higher
=
False
,
modified
=
override_obj
.
modified
,
score_deleted
=
False
,
score_db_table
=
ScoreDatabaseTableEnum
.
overrides
)
)
@freeze_time
(
'2017-01-01'
)
@freeze_time
(
'2017-01-01'
)
def
test_undo_override_subsection_grade
(
self
):
def
test_undo_override_subsection_grade
(
self
):
override
,
_
=
PersistentSubsectionGradeOverride
.
objects
.
update_or_create
(
grade
=
self
.
grade
)
self
.
service
.
undo_override_subsection_grade
(
self
.
service
.
undo_override_subsection_grade
(
user_id
=
self
.
user
.
id
,
user_id
=
self
.
user
.
id
,
course_key_or_id
=
self
.
course
.
id
,
course_key_or_id
=
self
.
course
.
id
,
...
@@ -202,20 +184,6 @@ class GradesServiceTests(ModuleStoreTestCase):
...
@@ -202,20 +184,6 @@ class GradesServiceTests(ModuleStoreTestCase):
override
=
self
.
service
.
get_subsection_grade_override
(
self
.
user
.
id
,
self
.
course
.
id
,
self
.
subsection
.
location
)
override
=
self
.
service
.
get_subsection_grade_override
(
self
.
user
.
id
,
self
.
course
.
id
,
self
.
subsection
.
location
)
self
.
assertIsNone
(
override
)
self
.
assertIsNone
(
override
)
self
.
assertEqual
(
self
.
mock_signal
.
call_args
,
call
(
sender
=
None
,
user_id
=
self
.
user
.
id
,
course_id
=
unicode
(
self
.
course
.
id
),
usage_id
=
unicode
(
self
.
subsection
.
location
),
only_if_higher
=
False
,
modified
=
datetime
.
now
()
.
replace
(
tzinfo
=
pytz
.
UTC
),
score_deleted
=
True
,
score_db_table
=
ScoreDatabaseTableEnum
.
overrides
)
)
@ddt.data
(
@ddt.data
(
[
'edX/DemoX/Demo_Course'
,
CourseKey
.
from_string
(
'edX/DemoX/Demo_Course'
),
CourseKey
],
[
'edX/DemoX/Demo_Course'
,
CourseKey
.
from_string
(
'edX/DemoX/Demo_Course'
),
CourseKey
],
[
'course-v1:edX+DemoX+Demo_Course'
,
CourseKey
.
from_string
(
'course-v1:edX+DemoX+Demo_Course'
),
CourseKey
],
[
'course-v1:edX+DemoX+Demo_Course'
,
CourseKey
.
from_string
(
'course-v1:edX+DemoX+Demo_Course'
),
CourseKey
],
...
...
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