Closed cewing closed 9 years ago
The traceback in question:
Environment:
Request Method: GET
Request URL: http://localhost:8000/courses/course-v1:edX+DemoX+example_run/instructor/api/gradebook
Django Version: 1.4.20
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.humanize',
'django.contrib.messages',
'django.contrib.sessions',
'django.contrib.sites',
'djcelery',
'south',
'config_models',
'service_status',
'edxmako',
'pipeline',
'staticfiles',
'static_replace',
'circuit',
'courseware',
'student',
'static_template_view',
'staticbook',
'track',
'eventtracking.django',
'util',
'certificates',
'dashboard',
'instructor',
'instructor_task',
'open_ended_grading',
'psychometrics',
'licenses',
'openedx.core.djangoapps.course_groups',
'bulk_email',
'branding',
'external_auth',
'django_openid_auth',
'provider',
'provider.oauth2',
'oauth2_provider',
'oauth_exchange',
'wiki',
'django_notify',
'course_wiki',
'mptt',
'sekizai',
'wiki.plugins.links',
'wiki.plugins.notifications',
'course_wiki.plugins.markdownedx',
'foldit',
'django.contrib.admin',
'django_nose',
'debug',
'django_comment_client',
'django_comment_common',
'discussion_api',
'notes',
'edxnotes',
'splash',
'datadog',
'rest_framework',
'openedx.core.djangoapps.user_api',
'shoppingcart',
'notification_prefs',
'notifier_api',
'course_modes',
'enrollment',
'verify_student',
'dark_lang',
'microsite_configuration',
'reverification',
'embargo',
'monitoring',
'course_action_state',
'edx_jsme',
'django_countries',
'mobile_api',
'survey',
'lms.djangoapps.lms_xblock',
'openedx.core.djangoapps.content.course_structures',
'course_structure_api',
'mailing',
'corsheaders',
'cors_csrf',
'commerce',
'django_openid_auth',
'edx_sga',
'submissions',
'openassessment',
'openassessment.assessment',
'openassessment.fileupload',
'openassessment.workflow',
'openassessment.xblock',
'edxval',
'milestones',
'debug_toolbar_mongo',
'ccx')
Installed Middleware:
('request_cache.middleware.RequestCache',
'microsite_configuration.middleware.MicrositeMiddleware',
'django_comment_client.middleware.AjaxExceptionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'cache_toolbox.middleware.CacheBackedAuthenticationMiddleware',
'student.middleware.UserStandingMiddleware',
'contentserver.middleware.StaticContentServer',
'crum.CurrentRequestUserMiddleware',
'openedx.core.djangoapps.user_api.middleware.UserTagsEventContextMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'track.middleware.TrackMiddleware',
'corsheaders.middleware.CorsMiddleware',
'cors_csrf.middleware.CorsCSRFMiddleware',
'cors_csrf.middleware.CsrfCrossDomainCookieMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'splash.middleware.SplashMiddleware',
'dark_lang.middleware.DarkLangMiddleware',
'geoinfo.middleware.CountryMiddleware',
'embargo.middleware.EmbargoMiddleware',
'lang_pref.middleware.LanguagePreferenceMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.transaction.TransactionMiddleware',
'django_comment_client.utils.ViewNameMiddleware',
'codejail.django_integration.ConfigureCodeJailMiddleware',
'ratelimitbackend.middleware.RateLimitMiddleware',
'edxmako.middleware.MakoMiddleware',
'session_inactivity_timeout.middleware.SessionInactivityTimeout',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'courseware.middleware.RedirectUnenrolledMiddleware',
'course_wiki.middleware.WikiAccessMiddleware',
'microsite_configuration.middleware.MicrositeSessionCookieDomainMiddleware',
'ccx.overrides.CcxMiddleware')
Traceback:
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
109. response = callback(request, *callback_args, **callback_kwargs)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/views/decorators/cache.py" in _cache_controlled
75. response = viewfunc(request, *args, **kw)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py" in wrapped
234. return func(*args, **kwargs)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/views/api.py" in spoc_gradebook
2390. for student in enrolled_students
File "/edx/app/edxapp/edx-platform/lms/djangoapps/instructor/offline_gradecalc.py" in student_grades
85. return grades.grade(student, request, course, keep_raw_scores=keep_raw_scores)
File "/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/db/transaction.py" in inner
224. return func(*args, **kwargs)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/grades.py" in grade
131. return _grade(student, request, course, keep_raw_scores)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/grades.py" in _grade
215. course.id, student, module_descriptor, create_module, scores_cache=submissions_scores
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/grades.py" in get_score
450. problem = module_creator(problem_descriptor)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/grades.py" in create_module
210. return get_module_for_descriptor(student, request, descriptor, field_data_cache, course.id)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/module_render.py" in get_module_for_descriptor
277. request_token=request_token(request),
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/module_render.py" in get_module_for_descriptor_internal
704. if not has_access(user, 'load', descriptor, course_id):
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/access.py" in has_access
97. return _has_access_descriptor(user, action, obj, course_key)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/access.py" in _has_access_descriptor
457. return _dispatch(checkers, action, user, descriptor)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/access.py" in _dispatch
538. result = table[action]()
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/access.py" in can_load
418. if descriptor.visible_to_staff_only and not _has_staff_access_to_descriptor(user, descriptor, course_key):
File "/edx/app/edxapp/venvs/edxapp/src/xblock/xblock/fields.py" in __get__
473. if field_data.has(xblock, self.name):
File "/edx/app/edxapp/venvs/edxapp/src/xblock/xblock/field_data.py" in has
174. return self._field_data(block, name).has(block, name)
File "/edx/app/edxapp/venvs/edxapp/src/xblock/xblock/field_data.py" in has
198. return self._source.has(block, name)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/field_overrides.py" in has
120. if self.get_override(ancestor, name) is not NOTSET:
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/field_overrides.py" in get_override
94. value = provider.get(block, name, NOTSET)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/student_field_overrides.py" in get
18. return get_override_for_user(self.user, block, name, default)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/student_field_overrides.py" in get_override_for_user
31. overrides = _get_overrides_for_user(user, block)
File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/student_field_overrides.py" in _get_overrides_for_user
42. course_id=block.runtime.course_id,
File "/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/x_module.py" in __getattr__
1750. return getattr(self._descriptor_system, name)
Exception Type: AttributeError at /courses/course-v1:edX+DemoX+example_run/instructor/api/gradebook
Exception Value: 'CachingDescriptorSystem' object has no attribute ‘course_id'
There was an conversation over e-mail that I will paste in here.
From the email conversation:
This looked to me like a discrepancy between the DescriptorSystems produced by old-mongo and split-mongo (and possibly between ModuleSystem and DescriptorSystem). So, I poked around, and lo-and-behold:
ModuleSystem sets a course_id
attribute: https://github.com/edx/edx-platform/blob/master/common/lib/xmodule/xmodule/x_module.py#L1619
The CachingDescriptorSystem for OldMongo sets a course_id
attribute: https://github.com/edx/edx-platform/blob/master/common/lib/xmodule/xmodule/modulestore/mongo/base.py#L223
The CachingDescriptorSystem for SplitMongo doesn't: https://github.com/edx/edx-platform/blob/master/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py#L42-L79
This is a problem now because student_field_overrides is reading that attribute, but the grading code tries really hard to only give you XBlocks that haven't been bound to a student (and thus only have a DescriptorSystem, not a ModuleSystem).
Student-specific overrides seems incompatible to me with having an un-bound XBlock, but I'm not sure whether to force the XBlock to be bound, or whether there's another option.
Thanks Cris. I would also note this follow-up from Cale:
Yeah, your code just tripped over an API inconsistency.
Probably the easiest thing (immediately) would just be to add course_id to the SplitMongo CachingDescriptorSystem (and possibly to the base DescriptorSystem object).
On May 27, 2015, at 10:38 PM, Cris Ewing notifications@github.com wrote:
From the email conversation:
This looked to me like a discrepancy between the DescriptorSystems produced by old-mongo and split-mongo (and possibly between ModuleSystem and DescriptorSystem). So, I poked around, and lo-and-behold: ModuleSystem sets a course_id attribute: https://github.com/edx/edx-platform/blob/master/common/lib/xmodule/xmodule/x_module.py#L1619 The CachingDescriptorSystem for OldMongo sets a course_id attribute: https://github.com/edx/edx-platform/blob/master/common/lib/xmodule/xmodule/modulestore/mongo/base.py#L223 The CachingDescriptorSystem for SplitMongo doesn't: https://github.com/edx/edx-platform/blob/master/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py#L42-L79 This is a problem now because student_field_overrides is reading that attribute, but the grading code tries really hard to only give you XBlocks that haven't been bound to a student (and thus only have a DescriptorSystem, not a ModuleSystem).
Student-specific overrides seems incompatible to me with having an un-bound XBlock, but I'm not sure whether to force the XBlock to be bound, or whether there's another option.
— Reply to this email directly or view it on GitHub.
I just finished discussing this with @ormsbee
He felt that we should go ahead with the suggestion from @cpennington for now:
Probably the easiest thing (immediately) would just be to add course_id to the SplitMongo CachingDescriptorSystem (and possibly to the base DescriptorSystem object).
But, once the CCX usage keys are in place, we should think about leveraging the more standard grading path in the instructor dashboard, i.e. Instructor > Data Download > Generate Grade report.
I think we avoided that earlier because we didn't want to think about recreating the whole infrastructure for Data Download, but now that we have a unique key for each CCX that wouldn't be necessary.
I'll open a new issue for that investigation (which starts with some research on MIT's part)
This is fixed, but the tests for the gradebook are still failing. We have another issue open (#96) to cover fixing tests, so I will close this.
from an email to @cpennington and @dormsbee:
After updating all the URLs on the coach dashboard to use the new CCXLocator-based urls, the gradebook no longer works. Each time we attempt to access a student’s grades using the “student_grades” method from “instructor.offline_gradecalc” we are seeing the traceback I include below.
At first I thought that this was a problem with the change in how we are getting a course from the CCXLocator-based url, but then I couldn’t see any difference in the course between what we were doing before and what we are doing now. So I went to a course and tried to view the gradebook (using the student gradebook link on the “student admin” section of the “instructor” tab of the course), and got exactly the same traceback.
This peaked my curiosity so I tried again with another course that uses the deprecated form of the course id. Here the traceback did not occur.
So I’m wondering if there’s a bug in how student grades are calculated with new-style course IDs, or if I’m doing something wrong.
Here’s how I got where I am:
paver devstack lms
to get it to checkout my ccx-keys package (https://github.com/jazkarta/ccx-keys)If I check the gradebook for the original demo course (which is using the old-style deprecated org/course/run id format) the same procedure does not result in errors and I see the gradebook just fine.