Merge remote-tracking branch 'edx/master' into opaque-keys-merge-master

Conflicts:
	cms/djangoapps/contentstore/views/item.py
	cms/djangoapps/contentstore/views/tests/test_container.py
	cms/djangoapps/contentstore/views/tests/test_tabs.py
	common/lib/xmodule/xmodule/modulestore/mongo/draft.py
	lms/djangoapps/certificates/management/commands/gen_cert_report.py
	lms/djangoapps/certificates/queue.py
	lms/djangoapps/certificates/views.py
	lms/djangoapps/courseware/module_render.py
	lms/djangoapps/courseware/tests/test_module_render.py
	lms/djangoapps/instructor/views/api.py
	lms/djangoapps/instructor/views/instructor_dashboard.py
	lms/djangoapps/instructor/views/legacy.py
	lms/djangoapps/shoppingcart/tests/test_models.py
	lms/djangoapps/verify_student/views.py
This commit is contained in:
Calen Pennington
2014-05-09 15:29:32 -04:00
577 changed files with 153911 additions and 12180 deletions

View File

@@ -65,6 +65,13 @@ XQUEUE_INTERFACE = XQueueInterface(
# This should be fixed after the jellyfish merge, before merge into master.
class LmsModuleRenderError(Exception):
"""
An exception class for exceptions thrown by module_render that don't fit well elsewhere
"""
pass
def make_track_function(request):
'''
Make a tracking function that logs what happened.
@@ -214,25 +221,39 @@ def get_module_for_descriptor(user, request, descriptor, field_data_cache, cours
static_asset_path)
def get_module_for_descriptor_internal(user, descriptor, field_data_cache, course_id,
track_function, xqueue_callback_url_prefix,
position=None, wrap_xmodule_display=True, grade_bucket_type=None,
static_asset_path=''):
def get_module_system_for_user(user, field_data_cache,
# Arguments preceding this comment have user binding, those following don't
descriptor, course_id, track_function, xqueue_callback_url_prefix,
position=None, wrap_xmodule_display=True, grade_bucket_type=None,
static_asset_path=''):
"""
Actually implement get_module, without requiring a request.
Helper function that returns a module system and student_data bound to a user and a descriptor.
See get_module() docstring for further details.
"""
The purpose of this function is to factor out everywhere a user is implicitly bound when creating a module,
to allow an existing module to be re-bound to a user. Most of the user bindings happen when creating the
closures that feed the instantiation of ModuleSystem.
<<<<<<< HEAD
# Do not check access when it's a noauth request.
if getattr(user, 'known', True):
# Short circuit--if the user shouldn't have access, bail without doing any work
if not has_access(user, 'load', descriptor, course_id):
return None
=======
The arguments fall into two categories: those that have explicit or implicit user binding, which are user
and field_data_cache, and those don't and are just present so that ModuleSystem can be instantiated, which
are all the other arguments. Ultimately, this isn't too different than how get_module_for_descriptor_internal
was before refactoring.
>>>>>>> edx/master
Arguments:
see arguments for get_module()
Returns:
(LmsModuleSystem, KvsFieldData): (module system, student_data) bound to, primarily, the user and descriptor
"""
student_data = KvsFieldData(DjangoKeyValueStore(field_data_cache))
def make_xqueue_callback(dispatch='score_update'):
# Fully qualified callback URL for external queueing system
relative_xqueue_callback_url = reverse(
@@ -335,6 +356,49 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
else:
track_function(event_type, event)
def rebind_noauth_module_to_user(module, real_user):
"""
A function that allows a module to get re-bound to a real user if it was previously bound to an AnonymousUser.
Will only work within a module bound to an AnonymousUser, e.g. one that's instantiated by the noauth_handler.
Arguments:
module (any xblock type): the module to rebind
real_user (django.contrib.auth.models.User): the user to bind to
Returns:
nothing (but the side effect is that module is re-bound to real_user)
"""
if user.is_authenticated():
err_msg = ("rebind_noauth_module_to_user can only be called from a module bound to "
"an anonymous user")
log.error(err_msg)
raise LmsModuleRenderError(err_msg)
field_data_cache_real_user = FieldDataCache.cache_for_descriptor_descendents(
course_id,
real_user,
module.descriptor
)
(inner_system, inner_student_data) = get_module_system_for_user(
real_user, field_data_cache_real_user, # These have implicit user bindings, rest of args considered not to
module.descriptor, course_id, track_function, xqueue_callback_url_prefix, position, wrap_xmodule_display,
grade_bucket_type, static_asset_path
)
# rebinds module to a different student. We'll change system, student_data, and scope_ids
module.descriptor.bind_for_student(
inner_system,
LmsFieldData(module.descriptor._field_data, inner_student_data) # pylint: disable=protected-access
)
module.descriptor.scope_ids = (
module.descriptor.scope_ids._replace(user_id=real_user.id) # pylint: disable=protected-access
)
module.scope_ids = module.descriptor.scope_ids # this is needed b/c NamedTuples are immutable
# now bind the module to the new ModuleSystem instance and vice-versa
module.runtime = inner_system
inner_system.xmodule_instance = module
# Build a list of wrapping functions that will be applied in order
# to the Fragment content coming out of the xblocks that are about to be rendered.
block_wrappers = []
@@ -439,6 +503,7 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
},
get_user_role=lambda: get_user_role(user, course_id),
descriptor_runtime=descriptor.runtime,
rebind_noauth_module_to_user=rebind_noauth_module_to_user,
)
# pass position specified in URL to module through ModuleSystem
@@ -457,6 +522,31 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours
else:
system.error_descriptor_class = NonStaffErrorDescriptor
return system, student_data
def get_module_for_descriptor_internal(user, descriptor, field_data_cache, course_id, # pylint: disable=invalid-name
track_function, xqueue_callback_url_prefix,
position=None, wrap_xmodule_display=True, grade_bucket_type=None,
static_asset_path=''):
"""
Actually implement get_module, without requiring a request.
See get_module() docstring for further details.
"""
# Do not check access when it's a noauth request.
if getattr(user, 'known', True):
# Short circuit--if the user shouldn't have access, bail without doing any work
if not has_access(user, descriptor, 'load', course_id):
return None
(system, student_data) = get_module_system_for_user(
user, field_data_cache, # These have implicit user bindings, the rest of args are considered not to
descriptor, course_id, track_function, xqueue_callback_url_prefix, position, wrap_xmodule_display,
grade_bucket_type, static_asset_path
)
descriptor.bind_for_student(system, LmsFieldData(descriptor._field_data, student_data)) # pylint: disable=protected-access
descriptor.scope_ids = descriptor.scope_ids._replace(user_id=user.id) # pylint: disable=protected-access
return descriptor