This commit completes the program_enrollments LMS app
Python API for the time being. It does the following:
* Add bulk-lookup of users by external key in api/reading.py
* Add bulk-writing of program enrollments in api/writing.py
* Move grade-reading to api/grades.py
* Refactor api/linking.py to use api/writing.py
* Refactor signals.py to use api/linking.py
* Update rest_api/v1/views.py to utilize all these changes
* Update linking management command and support tool to use API
* Remove outdated tests from test_models.py
* Misc. cleanup
EDUCATOR-4321
Positive test case and improvements including: requires course id to be correctly encoded in the url params, only checks entitlements of the course in question, better source for the basket url, check enrollment upgrade deadline
Python 3 changed how rounding is performed. In Python 2, .625 rounded to
.63 (as our grading code rounds it, so the test passed). In Python 3,
.625 rounds to .62. This fixes the test by avoiding round() to
calculate the expected value, and instead simply using the value we
expect.
This commit introduces the changes needed for XBlocks in Blockstore to save
their user state into CSM. Before this commit, all student state for Blockstore
blocks was ephemeral (in-process dict store).
Notes:
* The main risk factor of this PR is that it adds non-course keys to the
course_id field in CSM. If any code (like analytics?) reads course keys
directly out of CSM and doesn't have graceful handling for key types it
doesn't recognize, it could cause an issue. With the included changes to
opaque-keys, calling CourseKey.from_string(...) on these values will raise
InvalidKeyError since they're not CourseKeys. (But calling
LearningContextKey.from_string(...) will work for both course and library
keys.)
* This commit introduces a slight regression for the Studio view of XBlocks in
Blockstore content libraries: their state is now lost from request to request.
I have a follow up PR to give them a proper studio-appropriate state store,
but I want to review it separately so it doesn't hold up this PR and we can
test this PR on its own.
Changed <aside> tag to <div> tag according to the accessibility guidelines
mentioned in AXE 3.3
<aside> tag should not be a child of <main> hence replaced the
<aside> tag with the <div> tag.