Commit 4dc96948 by Fred Smith

Merge pull request #460 from edx-solutions/rc/2015-07-01

Rc/2015 07 01
parents 44b09dd8 0166729a
""" Users API URI specification """
from django.conf import settings
from django.conf.urls import patterns, url
from rest_framework.urlpatterns import format_suffix_patterns
from api_manager.users import views as users_views
COURSE_ID_PATTERN = settings.COURSE_ID_PATTERN
urlpatterns = patterns(
'',
url(r'^metrics/cities/$', users_views.UsersMetricsCitiesList.as_view(), name='apimgr-users-metrics-cities-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/grades$', users_views.UsersCoursesGradesList.as_view(), name='users-courses-grades-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/grades$', users_views.UsersCoursesGradesDetail.as_view(), name='users-courses-grades-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/metrics/social/$', users_views.UsersSocialMetrics.as_view(), name='users-social-metrics'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/completions/$', users_views.UsersCoursesCompletionsList.as_view(), name='users-courses-completions-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)$', users_views.UsersCoursesDetail.as_view(), name='users-courses-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[a-zA-Z0-9_+\/:]+)/grades$', users_views.UsersCoursesGradesDetail.as_view(), name='users-courses-grades-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[a-zA-Z0-9_+\/:]+)/metrics/social/$', users_views.UsersSocialMetrics.as_view(), name='users-social-metrics'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[a-zA-Z0-9_+\/:]+)/completions/$', users_views.UsersCoursesCompletionsList.as_view(), name='users-courses-completions-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/(?P<course_id>[a-zA-Z0-9_+\/:]+)$', users_views.UsersCoursesDetail.as_view(), name='users-courses-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}/grades$'.format(COURSE_ID_PATTERN), users_views.UsersCoursesGradesDetail.as_view(), name='users-courses-grades-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}/metrics/social/$'.format(COURSE_ID_PATTERN), users_views.UsersSocialMetrics.as_view(), name='users-social-metrics'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}/completions/$'.format(COURSE_ID_PATTERN), users_views.UsersCoursesCompletionsList.as_view(), name='users-courses-completions-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}$'.format(COURSE_ID_PATTERN), users_views.UsersCoursesDetail.as_view(), name='users-courses-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}/grades$'.format(COURSE_ID_PATTERN), users_views.UsersCoursesGradesDetail.as_view(), name='users-courses-grades-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}/metrics/social/$'.format(COURSE_ID_PATTERN), users_views.UsersSocialMetrics.as_view(), name='users-social-metrics'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}/completions/$'.format(COURSE_ID_PATTERN), users_views.UsersCoursesCompletionsList.as_view(), name='users-courses-completions-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/{0}$'.format(COURSE_ID_PATTERN), users_views.UsersCoursesDetail.as_view(), name='users-courses-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/courses/*$', users_views.UsersCoursesList.as_view(), name='users-courses-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/groups/*$', users_views.UsersGroupsList.as_view(), name='users-groups-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/groups/(?P<group_id>[0-9]+)$', users_views.UsersGroupsDetail.as_view(), name='users-groups-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/preferences$', users_views.UsersPreferences.as_view(), name='users-preferences-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/preferences/(?P<preference_id>[a-zA-Z0-9_]+)$', users_views.UsersPreferencesDetail.as_view(), name='users-preferences-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/organizations/$', users_views.UsersOrganizationsList.as_view(), name='users-organizations-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/roles/(?P<role>[a-z_]+)/courses/(?P<course_id>[a-zA-Z0-9_+\/:]+)$', users_views.UsersRolesCoursesDetail.as_view(), name='users-roles-courses-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/roles/(?P<role>[a-z_]+)/courses/{0}$'.format(COURSE_ID_PATTERN), users_views.UsersRolesCoursesDetail.as_view(), name='users-roles-courses-detail'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/roles/*$', users_views.UsersRolesList.as_view(), name='users-roles-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/workgroups/$', users_views.UsersWorkgroupsList.as_view(), name='users-workgroups-list'),
url(r'^(?P<user_id>[a-zA-Z0-9]+)/notifications/(?P<msg_id>[0-9]+)/$', users_views.UsersNotificationsDetail.as_view(), name='users-notifications-detail'),
......
......@@ -20,6 +20,11 @@ import django_comment_client.utils as utils
from xmodule.modulestore.django import modulestore
class MissingCohortedConfigCommandError(CommandError): #pylint: disable=no-init
""" Raised when a command requires cohorted discussions configured, but none are found """
pass
class DiscussionExportFields(object):
""" Container class for field names """
USER_ID = u"id"
......@@ -153,7 +158,10 @@ class Command(BaseCommand):
raw_course_key,
dir_name / self.get_default_file_location(raw_course_key)
]
self.dump_one(*args, **options)
try:
self.dump_one(*args, **options)
except MissingCohortedConfigCommandError as e:
print('Error generating CSV for course {}: {}'.format(raw_course_key, e.message))
def dump_one(self, *args, **options):
if not args:
......@@ -180,8 +188,9 @@ class Command(BaseCommand):
if options.get(self.COHORTED_ONLY_PARAMETER, False):
cohorted_discussions = course.cohort_config.get('cohorted_inline_discussions', None)
if not cohorted_discussions:
raise CommandError("Only cohorted discussions are marked for export, "
"but no cohorted discussions found for the course")
raise MissingCohortedConfigCommandError(
"Only cohorted discussions are marked for export, "
"but no cohorted discussions found for the course")
else:
target_discussion_ids = cohorted_discussions
......
......@@ -96,6 +96,29 @@ class CommandTest(TestCase):
self.assertIn('test_dir/social_stats_course-v1SandboxSandboxSandbox', calls[1][0][1])
self.assertIn('test_dir/social_stats_course-v1TestTestyTestify', calls[2][0][1])
def test_all_cohortedonly_options_together(self, patched_get_course):
""" Ensure the 'all' option doesn't stop when one of the course doesn't have cohorted discussions """
self.set_up_default_mocks(patched_get_course)
type(patched_get_course.return_value).cohort_config = mock.PropertyMock(
return_value={'cohorted_inline_discussions': []}
)
self.command.get_all_courses = mock.Mock()
course_list = [mock.Mock() for __ in range(0, 3)]
locator_list = [
CourseLocator(org="edX", course="demoX", run="now"),
CourseLocator(org="Sandbox", course="Sandbox", run="Sandbox"),
CourseLocator(org="Test", course="Testy", run="Testify"),
]
for index, course in enumerate(course_list):
course.location.course_key = locator_list[index]
self.command.get_all_courses.return_value = course_list
self.command.handle("test_dir", all=True, cohorted_only=True, dummy='test')
calls = patched_get_course.call_args_list
self.assertEqual(len(calls), 3)
self.assertEqual(calls[0][0][0], locator_list[0])
self.assertEqual(calls[1][0][0], locator_list[1])
self.assertEqual(calls[2][0][0], locator_list[2])
@ddt.data("edX/demoX/now", "otherX/CourseX/later")
def test_handle_writes_to_correct_location_when_output_file_not_specified(self, course_key, patched_get_course):
""" Tests that when no explicit filename is given data is exported to default location """
......
# Custom requirements to be customized by individual OpenEdX instances
-e git+https://github.com/edx/xblock-utils.git@a0e77eeb4eb971ac57243fe1056dd8db6806f514#egg=xblock-utils
-e git+https://github.com/edx-solutions/xblock-mentoring.git@82a4219b865d12db80ac57bda43fef9e30bec3f1#egg=xblock-mentoring
-e git+https://github.com/edx-solutions/xblock-mentoring.git@bd0b3f413ae7e8274985555adfd7de7af3eca84c#egg=xblock-mentoring
-e git+https://github.com/edx-solutions/xblock-image-explorer.git@21b9bcc4f2c7917463ab18a596161ac6c58c9c4a#egg=xblock-image-explorer
-e git+https://github.com/edx-solutions/xblock-drag-and-drop.git@92ee2055a16899090a073e1df81e35d5293ad767#egg=xblock-drag-and-drop
-e git+https://github.com/edx-solutions/xblock-drag-and-drop-v2.git@5736ed8774b92c8b8396b5bd455f8a8fb80295fb#egg=xblock-drag-and-drop-v2
-e git+https://github.com/edx-solutions/xblock-ooyala.git@ac49b30452aff0cc34cace6a34b788e100490f24#egg=xblock-ooyala
-e git+https://github.com/edx-solutions/xblock-group-project.git@dd8eaf16b3bc7b7be3fb392d588328dadef56c00#egg=xblock-group-project
-e git+https://github.com/edx-solutions/xblock-group-project.git@74477db1e478e6a055383f1ab1add3bd443a578f#egg=xblock-group-project
-e git+https://github.com/edx-solutions/xblock-adventure.git@effa22006bb6528bc6d3788787466eb4e74e1161#egg=xblock-adventure
-e git+https://github.com/mckinseyacademy/xblock-poll.git@ca0e6eb4ef10c128d573c3cec015dcfee7984730#egg=xblock-poll
-e git+https://github.com/OfficeDev/xblock-officemix/@86238f5968a08db005717dbddc346808f1ed3716#egg=xblock_officemix-master
-e git+https://github.com/edx/edx-notifications.git@4e3323da6775a101da5d8beab80c231278df69d2#egg=edx-notifications
-e git+https://github.com/open-craft/problem-builder.git@42901b107b8b1482891027a97dda9ae29e66388a#egg=problem-builder
-e git+https://github.com/open-craft/problem-builder.git@f42c7c572c7c9e5155062f3f1874714abf63e92a#egg=problem-builder
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment