From 3b57542ab0d97bc9b5c9ec28d2d08fa7c2f4aa97 Mon Sep 17 00:00:00 2001 From: John Eskew <jeskew@edx.org> Date: Tue, 30 May 2017 11:38:03 -0400 Subject: [PATCH] Revert "Merge pull request #15170 from edx/jeskew/PLAT_1316_partitions_inheritance" This reverts commit f97f052591d701aa8fd86b822d7bbeefbeb3dade, reversing changes made to 800bcd8e2019a5451b7bae89242bcdaab7b81cfd. --- .../contentstore/course_group_config.py | 9 +- .../tests/test_course_settings.py | 21 +- .../tests/test_courseware_index.py | 52 ++-- .../contentstore/tests/test_utils.py | 18 +- cms/djangoapps/contentstore/utils.py | 15 +- cms/djangoapps/contentstore/views/course.py | 2 +- cms/djangoapps/contentstore/views/item.py | 4 +- cms/djangoapps/contentstore/views/preview.py | 52 ++-- .../views/tests/test_group_configurations.py | 14 +- .../contentstore/views/tests/test_item.py | 69 +++-- cms/djangoapps/models/settings/encoder.py | 2 +- cms/envs/common.py | 2 +- cms/lib/xblock/test/test_authoring_mixin.py | 13 +- common/lib/xmodule/xmodule/capa_base.py | 25 +- .../xmodule/xmodule/course_metadata_utils.py | 2 +- common/lib/xmodule/xmodule/course_module.py | 7 +- .../lib/xmodule/xmodule}/fields.py | 35 --- .../xmodule/modulestore/inheritance.py | 231 ++++++++++++++++- .../xmodule/xmodule/modulestore/mongo/base.py | 31 +-- .../split_mongo/caching_descriptor_system.py | 18 +- .../xmodule/modulestore/split_mongo/split.py | 63 ++--- .../test_cross_modulestore_import_export.py | 22 +- .../tests/test_mixed_modulestore.py | 71 +++--- .../xmodule/modulestore/tests/test_mongo.py | 70 +++-- .../tests/test_split_modulestore.py | 36 +-- .../tests/test_split_w_old_mongo.py | 11 +- .../modulestore/tests/test_xml_importer.py | 20 +- .../xmodule/modulestore/tests/utils.py | 11 +- .../xmodule/xmodule}/partitions/__init__.py | 0 .../xmodule/xmodule}/partitions/partitions.py | 0 .../xmodule}/partitions/partitions_service.py | 2 +- .../xmodule}/partitions/tests/__init__.py | 0 .../partitions/tests/test_partitions.py | 4 +- common/lib/xmodule/xmodule/seq_module.py | 11 +- .../lib/xmodule/xmodule/split_test_module.py | 22 +- common/lib/xmodule/xmodule/tests/__init__.py | 3 +- .../tests/test_course_metadata_utils.py | 2 +- .../lib/xmodule/xmodule/tests/test_fields.py | 4 +- .../lib/xmodule/xmodule/tests/test_import.py | 27 +- .../xmodule/xmodule/tests/test_lti_unit.py | 14 +- .../xmodule/tests/test_split_test_module.py | 17 +- .../xmodule/xmodule/tests/test_xml_module.py | 29 +-- .../xmodule/xmodule/tests/xml/factories.py | 7 +- common/lib/xmodule/xmodule/timeinfo.py | 38 +++ .../xmodule/video_module/video_handlers.py | 16 +- .../xmodule/video_module/video_xfields.py | 4 +- common/lib/xmodule/xmodule/x_module.py | 45 ++-- .../discussion/test_cohort_management.py | 18 +- common/test/acceptance/tests/helpers.py | 34 +-- .../test_lms_split_test_courseware_search.py | 18 +- .../tests/lms/test_lms_user_preview.py | 12 +- .../tests/studio/test_studio_container.py | 13 +- .../tests/studio/test_studio_settings.py | 15 +- .../tests/studio/test_studio_split_test.py | 14 +- .../course_api/tests/test_serializers.py | 2 +- .../course_blocks/transformers/start_date.py | 2 +- .../transformers/tests/test_split_test.py | 5 +- .../tests/test_user_partitions.py | 8 +- .../transformers/user_partitions.py | 4 +- lms/djangoapps/courseware/access.py | 46 ++-- lms/djangoapps/courseware/access_response.py | 2 +- lms/djangoapps/courseware/field_overrides.py | 8 +- lms/djangoapps/courseware/masquerade.py | 8 +- .../courseware/tests/test_access.py | 50 ++-- .../courseware/tests/test_group_access.py | 10 +- .../courseware/tests/test_masquerade.py | 21 +- .../courseware/tests/test_split_module.py | 13 +- .../tests/test_submitting_problems.py | 27 +- .../discussion_api/tests/test_api.py | 34 +-- lms/djangoapps/instructor/tests/test_api.py | 102 ++++---- lms/djangoapps/instructor/tests/test_tools.py | 13 +- lms/djangoapps/instructor/views/tools.py | 15 +- .../instructor_task/tasks_helper/grades.py | 23 +- .../tests/test_tasks_helper.py | 88 ++++--- lms/djangoapps/lms_xblock/mixin.py | 7 +- lms/djangoapps/lms_xblock/runtime.py | 16 +- lms/djangoapps/mobile_api/users/tests.py | 2 +- .../mobile_api/video_outlines/tests.py | 19 +- lms/envs/common.py | 2 +- lms/lib/xblock/test/test_mixin.py | 9 +- lms/templates/preview_menu.html | 2 +- .../content/course_overviews/models.py | 3 +- .../content/course_overviews/tests.py | 2 +- .../course_groups/partition_scheme.py | 3 +- .../tests/test_partition_scheme.py | 15 +- .../core/djangoapps/models/course_details.py | 8 +- .../djangoapps/user_api/partition_schemes.py | 4 +- .../user_api/tests/test_partition_schemes.py | 6 +- openedx/core/djangoapps/util/testing.py | 8 +- .../partition_scheme.py | 10 +- .../tests/test_partition_scheme.py | 10 +- openedx/core/lib/xblock_fields/__init__.py | 0 .../lib/xblock_fields/inherited_fields.py | 239 ------------------ .../tests/views/test_course_outline.py | 2 +- 94 files changed, 1084 insertions(+), 1059 deletions(-) rename {openedx/core/lib/xblock_fields => common/lib/xmodule/xmodule}/fields.py (86%) rename {openedx/core/lib => common/lib/xmodule/xmodule}/partitions/__init__.py (100%) rename {openedx/core/lib => common/lib/xmodule/xmodule}/partitions/partitions.py (100%) rename {openedx/core/lib => common/lib/xmodule/xmodule}/partitions/partitions_service.py (98%) rename {openedx/core/lib => common/lib/xmodule/xmodule}/partitions/tests/__init__.py (100%) rename {openedx/core/lib => common/lib/xmodule/xmodule}/partitions/tests/test_partitions.py (99%) create mode 100644 common/lib/xmodule/xmodule/timeinfo.py delete mode 100644 openedx/core/lib/xblock_fields/__init__.py delete mode 100644 openedx/core/lib/xblock_fields/inherited_fields.py diff --git a/cms/djangoapps/contentstore/course_group_config.py b/cms/djangoapps/contentstore/course_group_config.py index 7335c16ae22..6bcbee47a7d 100644 --- a/cms/djangoapps/contentstore/course_group_config.py +++ b/cms/djangoapps/contentstore/course_group_config.py @@ -4,12 +4,13 @@ Class for manipulating groups configuration on a course object. import json import logging -from contentstore.utils import reverse_usage_url +from util.db import generate_int_id, MYSQL_MAX_INT + from django.utils.translation import ugettext as _ +from contentstore.utils import reverse_usage_url from openedx.core.djangoapps.course_groups.partition_scheme import get_cohorted_user_partition -from openedx.core.lib.partitions.partitions import MINIMUM_STATIC_PARTITION_ID, UserPartition -from openedx.core.lib.partitions.partitions_service import get_all_partitions_for_course -from util.db import MYSQL_MAX_INT, generate_int_id +from xmodule.partitions.partitions import UserPartition, MINIMUM_STATIC_PARTITION_ID +from xmodule.partitions.partitions_service import get_all_partitions_for_course from xmodule.split_test_module import get_split_user_partitions MINIMUM_GROUP_ID = MINIMUM_STATIC_PARTITION_ID diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index 73f473b9500..5fe8f575e48 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -1,34 +1,35 @@ """ Tests for Studio Course Settings. """ -import copy import datetime +import ddt import json +import copy +import mock +from mock import Mock, patch import unittest -import ddt -import mock -from contentstore.utils import reverse_course_url, reverse_usage_url from django.conf import settings -from django.test.utils import override_settings from django.utils.timezone import UTC -from milestones.tests.utils import MilestonesTestCaseMixin -from mock import Mock, patch +from django.test.utils import override_settings + +from contentstore.utils import reverse_course_url, reverse_usage_url from models.settings.course_grading import CourseGradingModel from models.settings.course_metadata import CourseMetadata from models.settings.encoder import CourseSettingsEncoder -from openedx.core.djangoapps.models.course_details import CourseDetails from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration -from openedx.core.lib.xblock_fields.fields import Date +from openedx.core.djangoapps.models.course_details import CourseDetails from student.roles import CourseInstructorRole, CourseStaffRole from student.tests.factories import UserFactory from xblock_django.models import XBlockStudioConfigurationFlag +from xmodule.fields import Date from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.factories import CourseFactory from xmodule.tabs import InvalidTabsException +from milestones.tests.utils import MilestonesTestCaseMixin -from .utils import AjaxEnabledTestClient, CourseTestCase +from .utils import CourseTestCase, AjaxEnabledTestClient def get_url(course_id, handler_name='settings_handler'): diff --git a/cms/djangoapps/contentstore/tests/test_courseware_index.py b/cms/djangoapps/contentstore/tests/test_courseware_index.py index 0c438ccc163..aaa305f0c3f 100644 --- a/cms/djangoapps/contentstore/tests/test_courseware_index.py +++ b/cms/djangoapps/contentstore/tests/test_courseware_index.py @@ -1,52 +1,52 @@ """ Testing indexing of the courseware as it is changed """ +import ddt import json +from lazy.lazy import lazy import time from datetime import datetime -from unittest import skip +from dateutil.tz import tzutc +from mock import patch +from pytz import UTC from uuid import uuid4 +from unittest import skip -import ddt -from contentstore.courseware_index import ( - CourseAboutSearchIndexer, - CoursewareSearchIndexer, - LibrarySearchIndexer, - SearchIndexingError -) -from contentstore.signals.handlers import listen_for_course_publish, listen_for_library_update -from contentstore.tests.utils import CourseTestCase -from contentstore.utils import reverse_course_url, reverse_usage_url -from course_modes.models import CourseMode -from dateutil.tz import tzutc from django.conf import settings -from lazy.lazy import lazy -from mock import patch + +from course_modes.models import CourseMode from openedx.core.djangoapps.models.course_details import CourseDetails -from openedx.core.lib.partitions.partitions import UserPartition -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from pytz import UTC -from search.search_engine_base import SearchEngine from xmodule.library_tools import normalize_key_for_search from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import SignalHandler, modulestore from xmodule.modulestore.edit_info import EditInfoMixin +from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.modulestore.mixed import MixedModuleStore from xmodule.modulestore.tests.django_utils import ( TEST_DATA_MONGO_MODULESTORE, TEST_DATA_SPLIT_MODULESTORE, - SharedModuleStoreTestCase -) + SharedModuleStoreTestCase) from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, LibraryFactory -from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM +from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST from xmodule.modulestore.tests.utils import ( - LocationMixin, - MixedSplitTestCase, - MongoContentstoreBuilder, - create_modulestore_instance + create_modulestore_instance, LocationMixin, + MixedSplitTestCase, MongoContentstoreBuilder ) from xmodule.tests import DATA_DIR from xmodule.x_module import XModuleMixin +from xmodule.partitions.partitions import UserPartition + +from search.search_engine_base import SearchEngine + +from contentstore.courseware_index import ( + CoursewareSearchIndexer, + LibrarySearchIndexer, + SearchIndexingError, + CourseAboutSearchIndexer, +) +from contentstore.signals.handlers import listen_for_course_publish, listen_for_library_update +from contentstore.utils import reverse_course_url, reverse_usage_url +from contentstore.tests.utils import CourseTestCase COURSE_CHILD_STRUCTURE = { "course": "chapter", diff --git a/cms/djangoapps/contentstore/tests/test_utils.py b/cms/djangoapps/contentstore/tests/test_utils.py index de8fa67b755..f73447e4b25 100644 --- a/cms/djangoapps/contentstore/tests/test_utils.py +++ b/cms/djangoapps/contentstore/tests/test_utils.py @@ -2,17 +2,19 @@ import collections from datetime import datetime, timedelta -from contentstore import utils -from contentstore.tests.utils import CourseTestCase -from django.test import TestCase -from opaque_keys.edx.locations import SlashSeparatedCourseKey -from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context -from openedx.core.lib.partitions.partitions import Group, UserPartition from pytz import UTC +from django.test import TestCase from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.django import modulestore -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase +from opaque_keys.edx.locations import SlashSeparatedCourseKey +from xmodule.modulestore.django import modulestore +from xmodule.partitions.partitions import UserPartition, Group + +from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context + +from contentstore import utils +from contentstore.tests.utils import CourseTestCase class LMSLinksTestCase(TestCase): diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index cc5079bcb2f..a414f5815ce 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -4,23 +4,26 @@ Common utility functions useful throughout the contentstore import logging from datetime import datetime +from pytz import UTC from django.conf import settings from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ from django_comment_common.models import assign_default_role from django_comment_common.utils import seed_permissions_roles -from opaque_keys.edx.keys import CourseKey, UsageKey + from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.core.djangoapps.site_configuration.models import SiteConfiguration -from openedx.core.lib.partitions.partitions_service import get_all_partitions_for_course -from pytz import UTC -from student import auth -from student.models import CourseEnrollment -from student.roles import CourseInstructorRole, CourseStaffRole +from xmodule.partitions.partitions_service import get_all_partitions_for_course + from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import ItemNotFoundError +from opaque_keys.edx.keys import UsageKey, CourseKey +from student.roles import CourseInstructorRole, CourseStaffRole +from student.models import CourseEnrollment +from student import auth + log = logging.getLogger(__name__) diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index a040e5df71d..35d8ef367c1 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -70,7 +70,6 @@ from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.lib.course_tabs import CourseTabPluginManager from openedx.core.lib.courses import course_image_url -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE from openedx.core.djangolib.js_utils import dump_js_escaped_json from student import auth from student.auth import has_course_author_access, has_studio_write_access, has_studio_read_access @@ -95,6 +94,7 @@ from util.string_utils import _has_non_ascii_characters from xblock_django.api import deprecated_xblocks from xmodule.contentstore.content import StaticContent from xmodule.course_module import CourseFields +from xmodule.course_module import DEFAULT_START_DATE from xmodule.error_module import ErrorDescriptor from xmodule.modulestore import EdxJSONEncoder from xmodule.modulestore.django import modulestore diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index 234dc3e223b..e6510be15aa 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -38,16 +38,16 @@ from contentstore.views.helpers import is_unit, xblock_studio_url, xblock_primar from contentstore.views.preview import get_preview_fragment from contentstore.utils import is_self_paced +from openedx.core.lib.gating import api as gating_api from edxmako.shortcuts import render_to_string from models.settings.course_grading import CourseGradingModel -from openedx.core.lib.gating import api as gating_api from openedx.core.lib.xblock_utils import wrap_xblock, request_token -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE from static_replace import replace_static_urls from student.auth import has_studio_write_access, has_studio_read_access from util.date_utils import get_default_time_display from util.json_request import expect_json, JsonResponse from util.milestones_helpers import is_entrance_exams_enabled +from xmodule.course_module import DEFAULT_START_DATE from xmodule.modulestore import ModuleStoreEnum, EdxJSONEncoder from xmodule.modulestore.django import modulestore from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES diff --git a/cms/djangoapps/contentstore/views/preview.py b/cms/djangoapps/contentstore/views/preview.py index 65694915b3e..1b8b08c2255 100644 --- a/cms/djangoapps/contentstore/views/preview.py +++ b/cms/djangoapps/contentstore/views/preview.py @@ -3,45 +3,45 @@ from __future__ import absolute_import import logging from functools import partial -import static_replace -from cms.lib.xblock.field_data import CmsFieldData -from contentstore.utils import get_visibility_partition_info -from contentstore.views.access import get_user_role from django.conf import settings -from django.contrib.auth.decorators import login_required from django.core.urlresolvers import reverse from django.http import Http404, HttpResponseBadRequest +from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _ from edxmako.shortcuts import render_to_string -from lms.djangoapps.lms_xblock.field_data import LmsFieldData -from opaque_keys.edx.keys import UsageKey -from openedx.core.lib.license import wrap_with_license -from openedx.core.lib.partitions.partitions_service import PartitionService + from openedx.core.lib.xblock_utils import ( - replace_static_urls, - request_token, - wrap_fragment, - wrap_xblock, - wrap_xblock_aside, - xblock_local_resource_url + replace_static_urls, wrap_xblock, wrap_fragment, wrap_xblock_aside, request_token, xblock_local_resource_url, ) -from util.sandboxing import can_execute_unsafe_code, get_python_lib_zip -from xblock.django.request import django_to_webob_request, webob_to_django_response -from xblock.exceptions import NoSuchHandlerError -from xblock.fragment import Fragment -from xblock.runtime import KvsFieldData -from xblock_config.models import StudioConfig -from xblock_django.user_service import DjangoXBlockUserService +from xmodule.x_module import PREVIEW_VIEWS, STUDENT_VIEW, AUTHOR_VIEW from xmodule.contentstore.django import contentstore from xmodule.error_module import ErrorDescriptor from xmodule.exceptions import NotFoundError, ProcessingError -from xmodule.modulestore.django import ModuleI18nService, modulestore -from xmodule.services import SettingsService +from xmodule.partitions.partitions_service import PartitionService from xmodule.studio_editable import has_author_view -from xmodule.x_module import AUTHOR_VIEW, PREVIEW_VIEWS, STUDENT_VIEW, ModuleSystem +from xmodule.services import SettingsService +from xmodule.modulestore.django import modulestore, ModuleI18nService +from openedx.core.lib.license import wrap_with_license +from opaque_keys.edx.keys import UsageKey +from xmodule.x_module import ModuleSystem +from xblock.runtime import KvsFieldData +from xblock.django.request import webob_to_django_response, django_to_webob_request +from xblock.exceptions import NoSuchHandlerError +from xblock.fragment import Fragment +from xblock_django.user_service import DjangoXBlockUserService -from .helpers import render_from_lms +from lms.djangoapps.lms_xblock.field_data import LmsFieldData +from cms.lib.xblock.field_data import CmsFieldData + +from util.sandboxing import can_execute_unsafe_code, get_python_lib_zip + +import static_replace from .session_kv_store import SessionKeyValueStore +from .helpers import render_from_lms + +from contentstore.utils import get_visibility_partition_info +from contentstore.views.access import get_user_role +from xblock_config.models import StudioConfig __all__ = ['preview_handler'] diff --git a/cms/djangoapps/contentstore/views/tests/test_group_configurations.py b/cms/djangoapps/contentstore/views/tests/test_group_configurations.py index f065bf58ed9..ff2710c3ef3 100644 --- a/cms/djangoapps/contentstore/views/tests/test_group_configurations.py +++ b/cms/djangoapps/contentstore/views/tests/test_group_configurations.py @@ -4,17 +4,17 @@ Group Configuration Tests. """ import json - import ddt -from contentstore.course_group_config import CONTENT_GROUP_CONFIGURATION_NAME, GroupConfiguration -from contentstore.tests.utils import CourseTestCase -from contentstore.utils import reverse_course_url, reverse_usage_url from mock import patch -from openedx.core.lib.partitions.partitions import Group, UserPartition -from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.django import modulestore + +from contentstore.utils import reverse_course_url, reverse_usage_url +from contentstore.course_group_config import GroupConfiguration, CONTENT_GROUP_CONFIGURATION_NAME +from contentstore.tests.utils import CourseTestCase +from xmodule.partitions.partitions import Group, UserPartition from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.validation import StudioValidation, StudioValidationMessage +from xmodule.modulestore.django import modulestore +from xmodule.modulestore import ModuleStoreEnum GROUP_CONFIGURATION_JSON = { u'name': u'Test name', diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py index 3c41a7b01c7..11c675b7196 100644 --- a/cms/djangoapps/contentstore/views/tests/test_item.py +++ b/cms/djangoapps/contentstore/views/tests/test_item.py @@ -1,56 +1,53 @@ """Tests for items views.""" import json from datetime import datetime, timedelta - import ddt -from contentstore.tests.utils import CourseTestCase -from contentstore.utils import reverse_course_url, reverse_usage_url -from contentstore.views.component import component_handler, get_component_templates -from contentstore.views.item import ( - ALWAYS, - VisibilityState, - _get_module_info, - _get_source_index, - _xblock_type_and_display_name, - add_container_page_publishing_info, - create_xblock_info -) + +from mock import patch, Mock, PropertyMock +from pytz import UTC +from pyquery import PyQuery +from webob import Response + from django.conf import settings -from django.core.urlresolvers import reverse from django.http import Http404 from django.test import TestCase from django.test.client import RequestFactory -from mock import Mock, PropertyMock, patch +from django.core.urlresolvers import reverse +from contentstore.utils import reverse_usage_url, reverse_course_url + from opaque_keys import InvalidKeyError -from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locations import Location from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration -from openedx.core.lib.partitions.partitions import ( - ENROLLMENT_TRACK_PARTITION_ID, - MINIMUM_STATIC_PARTITION_ID, - Group, - UserPartition +from contentstore.views.component import ( + component_handler, get_component_templates ) -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE -from pyquery import PyQuery -from pytz import UTC + +from contentstore.views.item import ( + create_xblock_info, _get_source_index, _get_module_info, ALWAYS, VisibilityState, _xblock_type_and_display_name, + add_container_page_publishing_info +) +from contentstore.tests.utils import CourseTestCase from student.tests.factories import UserFactory -from webob import Response -from xblock.core import XBlockAside -from xblock.exceptions import NoSuchHandlerError -from xblock.fields import Scope, ScopeIds, String -from xblock.fragment import Fragment -from xblock.runtime import DictKeyValueStore, KvsFieldData -from xblock.test.tools import TestRuntime from xblock_django.models import XBlockConfiguration, XBlockStudioConfiguration, XBlockStudioConfigurationFlag -from xblock_django.user_service import DjangoXBlockUserService from xmodule.capa_module import CapaDescriptor from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import ItemNotFoundError -from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, LibraryFactory, check_mongo_calls -from xmodule.x_module import STUDENT_VIEW, STUDIO_VIEW +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_SPLIT_MODULESTORE +from xmodule.modulestore.tests.factories import ItemFactory, LibraryFactory, check_mongo_calls, CourseFactory +from xmodule.x_module import STUDIO_VIEW, STUDENT_VIEW +from xmodule.course_module import DEFAULT_START_DATE +from xblock.core import XBlockAside +from xblock.fields import Scope, String, ScopeIds +from xblock.fragment import Fragment +from xblock.runtime import DictKeyValueStore, KvsFieldData +from xblock.test.tools import TestRuntime +from xblock.exceptions import NoSuchHandlerError +from xblock_django.user_service import DjangoXBlockUserService +from opaque_keys.edx.keys import UsageKey, CourseKey +from opaque_keys.edx.locations import Location +from xmodule.partitions.partitions import ( + Group, UserPartition, ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID +) class AsideTest(XBlockAside): diff --git a/cms/djangoapps/models/settings/encoder.py b/cms/djangoapps/models/settings/encoder.py index f048d3c15f1..36b6e1fb441 100644 --- a/cms/djangoapps/models/settings/encoder.py +++ b/cms/djangoapps/models/settings/encoder.py @@ -7,7 +7,7 @@ from json.encoder import JSONEncoder from opaque_keys.edx.locations import Location from openedx.core.djangoapps.models.course_details import CourseDetails -from openedx.core.lib.xblock_fields.fields import Date +from xmodule.fields import Date from .course_grading import CourseGradingModel diff --git a/cms/envs/common.py b/cms/envs/common.py index 3eefa42bf67..6a1b70359af 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -434,7 +434,7 @@ P3P_HEADER = 'CP="Open EdX does not have a P3P policy."' ############# XBlock Configuration ########## # Import after sys.path fixup -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin +from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.modulestore import prefer_xmodules from xmodule.x_module import XModuleMixin diff --git a/cms/lib/xblock/test/test_authoring_mixin.py b/cms/lib/xblock/test/test_authoring_mixin.py index a72eba46648..c45270c70a2 100644 --- a/cms/lib/xblock/test/test_authoring_mixin.py +++ b/cms/lib/xblock/test/test_authoring_mixin.py @@ -1,17 +1,16 @@ """ Tests for the Studio authoring XBlock mixin. """ -from course_modes.tests.factories import CourseModeFactory from django.conf import settings from django.test.utils import override_settings -from openedx.core.lib.partitions.partitions import ( - ENROLLMENT_TRACK_PARTITION_ID, - MINIMUM_STATIC_PARTITION_ID, - Group, - UserPartition -) + +from course_modes.tests.factories import CourseModeFactory + from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.partitions.partitions import ( + Group, UserPartition, ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID +) class AuthoringMixinTestCase(ModuleStoreTestCase): diff --git a/common/lib/xmodule/xmodule/capa_base.py b/common/lib/xmodule/xmodule/capa_base.py index 55f2d25dacd..847eed20fc1 100644 --- a/common/lib/xmodule/xmodule/capa_base.py +++ b/common/lib/xmodule/xmodule/capa_base.py @@ -11,27 +11,26 @@ import struct import sys import traceback +from django.conf import settings +# We don't want to force a dependency on datadog, so make the import conditional +try: + import dogstats_wrapper as dog_stats_api +except ImportError: + dog_stats_api = None +from pytz import utc + from capa.capa_problem import LoncapaProblem, LoncapaSystem from capa.inputtypes import Status -from capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError +from capa.responsetypes import StudentInputError, ResponseError, LoncapaProblemError from capa.util import convert_files_to_filenames, get_inner_html_from_xpath -from django.conf import settings -from openedx.core.djangolib.markup import HTML, Text -from openedx.core.lib.xblock_fields.fields import Date, Timedelta -from pytz import utc from xblock.fields import Boolean, Dict, Float, Integer, Scope, String, XMLString from xblock.scorable import ScorableXBlockMixin, Score -from xmodule.capa_base_constants import RANDOMIZATION, SHOW_CORRECTNESS, SHOWANSWER +from xmodule.capa_base_constants import RANDOMIZATION, SHOWANSWER, SHOW_CORRECTNESS from xmodule.exceptions import NotFoundError - +from .fields import Date, Timedelta from .progress import Progress -# We don't want to force a dependency on datadog, so make the import conditional -try: - import dogstats_wrapper as dog_stats_api -except ImportError: - dog_stats_api = None - +from openedx.core.djangolib.markup import HTML, Text log = logging.getLogger("edx.courseware") diff --git a/common/lib/xmodule/xmodule/course_metadata_utils.py b/common/lib/xmodule/xmodule/course_metadata_utils.py index cdf4d48bcdd..e0a2e996edb 100644 --- a/common/lib/xmodule/xmodule/course_metadata_utils.py +++ b/common/lib/xmodule/xmodule/course_metadata_utils.py @@ -12,7 +12,7 @@ from math import exp from pytz import utc -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE +DEFAULT_START_DATE = datetime(2030, 1, 1, tzinfo=utc) def clean_course_key(course_key, padding_char): diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 18e8db2d41f..1097f715689 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -10,15 +10,16 @@ import requests from lazy import lazy from lxml import etree from openedx.core.lib.license import LicenseMixin -from openedx.core.lib.xblock_fields.fields import Date -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE from path import Path as path from pytz import utc -from xblock.fields import Boolean, Dict, Float, Integer, List, Scope, String +from xblock.fields import Scope, List, String, Dict, Boolean, Integer, Float + from xmodule import course_metadata_utils +from xmodule.course_metadata_utils import DEFAULT_START_DATE from xmodule.graders import grader_from_conf from xmodule.seq_module import SequenceDescriptor, SequenceModule from xmodule.tabs import CourseTabList, InvalidTabsException +from .fields import Date log = logging.getLogger(__name__) diff --git a/openedx/core/lib/xblock_fields/fields.py b/common/lib/xmodule/xmodule/fields.py similarity index 86% rename from openedx/core/lib/xblock_fields/fields.py rename to common/lib/xmodule/xmodule/fields.py index fe27225a16f..2b73d5b63f7 100644 --- a/openedx/core/lib/xblock_fields/fields.py +++ b/common/lib/xmodule/xmodule/fields.py @@ -253,38 +253,3 @@ class RelativeTime(JSONField): return value return self.from_json(value) - - -class TimeInfo(object): - """ - This is a simple object that calculates and stores datetime information for an XModule - based on the due date and the grace period string - - So far it parses out three different pieces of time information: - self.display_due_date - the 'official' due date that gets displayed to students - self.grace_period - the length of the grace period - self.close_date - the real due date - - """ - _delta_standin = Timedelta() - - def __init__(self, due_date, grace_period_string_or_timedelta): - if due_date is not None: - self.display_due_date = due_date - - else: - self.display_due_date = None - - if grace_period_string_or_timedelta is not None and self.display_due_date: - if isinstance(grace_period_string_or_timedelta, basestring): - try: - self.grace_period = TimeInfo._delta_standin.from_json(grace_period_string_or_timedelta) - except: - log.error("Error parsing the grace period {0}".format(grace_period_string_or_timedelta)) - raise - else: - self.grace_period = grace_period_string_or_timedelta - self.close_date = self.display_due_date + self.grace_period - else: - self.grace_period = None - self.close_date = self.display_due_date diff --git a/common/lib/xmodule/xmodule/modulestore/inheritance.py b/common/lib/xmodule/xmodule/modulestore/inheritance.py index 351e87c771d..91c2811b35c 100644 --- a/common/lib/xmodule/xmodule/modulestore/inheritance.py +++ b/common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -4,9 +4,236 @@ Support for inheritance of fields down an XBlock hierarchy. from __future__ import absolute_import from django.conf import settings -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from xblock.fields import Scope + +from xmodule.partitions.partitions import UserPartition +from xblock.fields import Scope, Boolean, String, Float, XBlockMixin, Dict, Integer, List from xblock.runtime import KeyValueStore, KvsFieldData +from xmodule.fields import Date, Timedelta +from ..course_metadata_utils import DEFAULT_START_DATE + + +# Make '_' a no-op so we can scrape strings +# Using lambda instead of `django.utils.translation.ugettext_noop` because Django cannot be imported in this file +_ = lambda text: text + + +class UserPartitionList(List): + """Special List class for listing UserPartitions""" + def from_json(self, values): + return [UserPartition.from_json(v) for v in values] + + def to_json(self, values): + return [user_partition.to_json() + for user_partition in values] + + +class InheritanceMixin(XBlockMixin): + """Field definitions for inheritable fields.""" + + graded = Boolean( + help="Whether this module contributes to the final course grade", + scope=Scope.settings, + default=False, + ) + start = Date( + help="Start time when this module is visible", + default=DEFAULT_START_DATE, + scope=Scope.settings + ) + due = Date( + display_name=_("Due Date"), + help=_("Enter the default date by which problems are due."), + scope=Scope.settings, + ) + visible_to_staff_only = Boolean( + help=_("If true, can be seen only by course staff, regardless of start date."), + default=False, + scope=Scope.settings, + ) + course_edit_method = String( + display_name=_("Course Editor"), + help=_("Enter the method by which this course is edited (\"XML\" or \"Studio\")."), + default="Studio", + scope=Scope.settings, + deprecated=True # Deprecated because user would not change away from Studio within Studio. + ) + giturl = String( + display_name=_("GIT URL"), + help=_("Enter the URL for the course data GIT repository."), + scope=Scope.settings + ) + xqa_key = String( + display_name=_("XQA Key"), + help=_("This setting is not currently supported."), scope=Scope.settings, + deprecated=True + ) + annotation_storage_url = String( + help=_("Enter the location of the annotation storage server. The textannotation, videoannotation, and imageannotation advanced modules require this setting."), + scope=Scope.settings, + default="http://your_annotation_storage.com", + display_name=_("URL for Annotation Storage") + ) + annotation_token_secret = String( + help=_("Enter the secret string for annotation storage. The textannotation, videoannotation, and imageannotation advanced modules require this string."), + scope=Scope.settings, + default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + display_name=_("Secret Token String for Annotation") + ) + graceperiod = Timedelta( + help="Amount of time after the due date that submissions will be accepted", + scope=Scope.settings, + ) + group_access = Dict( + help=_("Enter the ids for the content groups this problem belongs to."), + scope=Scope.settings, + ) + + showanswer = String( + display_name=_("Show Answer"), + help=_( + # Translators: DO NOT translate the words in quotes here, they are + # specific words for the acceptable values. + 'Specify when the Show Answer button appears for each problem. ' + 'Valid values are "always", "answered", "attempted", "closed", ' + '"finished", "past_due", "correct_or_past_due", and "never".' + ), + scope=Scope.settings, + default="finished", + ) + + show_correctness = String( + display_name=_("Show Results"), + help=_( + # Translators: DO NOT translate the words in quotes here, they are + # specific words for the acceptable values. + 'Specify when to show answer correctness and score to learners. ' + 'Valid values are "always", "never", and "past_due".' + ), + scope=Scope.settings, + default="always", + ) + + rerandomize = String( + display_name=_("Randomization"), + help=_( + # Translators: DO NOT translate the words in quotes here, they are + # specific words for the acceptable values. + 'Specify the default for how often variable values in a problem are randomized. ' + 'This setting should be set to "never" unless you plan to provide a Python ' + 'script to identify and randomize values in most of the problems in your course. ' + 'Valid values are "always", "onreset", "never", and "per_student".' + ), + scope=Scope.settings, + default="never", + ) + days_early_for_beta = Float( + display_name=_("Days Early for Beta Users"), + help=_("Enter the number of days before the start date that beta users can access the course."), + scope=Scope.settings, + default=None, + ) + static_asset_path = String( + display_name=_("Static Asset Path"), + help=_("Enter the path to use for files on the Files & Uploads page. This value overrides the Studio default, c4x://."), + scope=Scope.settings, + default='', + ) + use_latex_compiler = Boolean( + display_name=_("Enable LaTeX Compiler"), + help=_("Enter true or false. If true, you can use the LaTeX templates for HTML components and advanced Problem components."), + default=False, + scope=Scope.settings + ) + max_attempts = Integer( + display_name=_("Maximum Attempts"), + help=_("Enter the maximum number of times a student can try to answer problems. By default, Maximum Attempts is set to null, meaning that students have an unlimited number of attempts for problems. You can override this course-wide setting for individual problems. However, if the course-wide setting is a specific number, you cannot set the Maximum Attempts for individual problems to unlimited."), + values={"min": 0}, scope=Scope.settings + ) + matlab_api_key = String( + display_name=_("Matlab API key"), + help=_("Enter the API key provided by MathWorks for accessing the MATLAB Hosted Service. " + "This key is granted for exclusive use in this course for the specified duration. " + "Do not share the API key with other courses. Notify MathWorks immediately " + "if you believe the key is exposed or compromised. To obtain a key for your course, " + "or to report an issue, please contact moocsupport@mathworks.com"), + scope=Scope.settings + ) + # This is should be scoped to content, but since it's defined in the policy + # file, it is currently scoped to settings. + user_partitions = UserPartitionList( + display_name=_("Group Configurations"), + help=_("Enter the configurations that govern how students are grouped together."), + default=[], + scope=Scope.settings + ) + video_speed_optimizations = Boolean( + display_name=_("Enable video caching system"), + help=_("Enter true or false. If true, video caching will be used for HTML5 videos."), + default=True, + scope=Scope.settings + ) + video_bumper = Dict( + display_name=_("Video Pre-Roll"), + help=_( + "Identify a video, 5-10 seconds in length, to play before course videos. Enter the video ID from " + "the Video Uploads page and one or more transcript files in the following format: {format}. " + "For example, an entry for a video with two transcripts looks like this: {example}" + ).format( + format='{"video_id": "ID", "transcripts": {"language": "/static/filename.srt"}}', + example=( + '{' + '"video_id": "77cef264-d6f5-4cf2-ad9d-0178ab8c77be", ' + '"transcripts": {"en": "/static/DemoX-D01_1.srt", "uk": "/static/DemoX-D01_1_uk.srt"}' + '}' + ), + ), + scope=Scope.settings + ) + + reset_key = "DEFAULT_SHOW_RESET_BUTTON" + default_reset_button = getattr(settings, reset_key) if hasattr(settings, reset_key) else False + show_reset_button = Boolean( + display_name=_("Show Reset Button for Problems"), + help=_( + "Enter true or false. If true, problems in the course default to always displaying a 'Reset' button. " + "You can override this in each problem's settings. All existing problems are affected when " + "this course-wide setting is changed." + ), + scope=Scope.settings, + default=default_reset_button + ) + edxnotes = Boolean( + display_name=_("Enable Student Notes"), + help=_("Enter true or false. If true, students can use the Student Notes feature."), + default=False, + scope=Scope.settings + ) + edxnotes_visibility = Boolean( + display_name="Student Notes Visibility", + help=_("Indicates whether Student Notes are visible in the course. " + "Students can also show or hide their notes in the courseware."), + default=True, + scope=Scope.user_info + ) + + in_entrance_exam = Boolean( + display_name=_("Tag this module as part of an Entrance Exam section"), + help=_("Enter true or false. If true, answer submissions for problem modules will be " + "considered in the Entrance Exam scoring/gating algorithm."), + scope=Scope.settings, + default=False + ) + + self_paced = Boolean( + display_name=_('Self Paced'), + help=_( + 'Set this to "true" to mark this course as self-paced. Self-paced courses do not have ' + 'due dates for assignments, and students can progress through the course at any rate before ' + 'the course ends.' + ), + default=False, + scope=Scope.settings + ) def compute_inherited_metadata(descriptor): diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/base.py b/common/lib/xmodule/xmodule/modulestore/mongo/base.py index 714d7d09986..aad2b8c2362 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo/base.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo/base.py @@ -13,45 +13,46 @@ structure: """ import copy +from datetime import datetime +from importlib import import_module import logging +import pymongo import re import sys -from datetime import datetime -from importlib import import_module from uuid import uuid4 -import pymongo from bson.son import SON from contracts import contract, new_contract from fs.osfs import OSFS from mongodb_proxy import autoretry_read -from opaque_keys.edx.keys import AssetKey, CourseKey, UsageKey -from opaque_keys.edx.locations import BlockUsageLocator, Location, SlashSeparatedCourseKey +from opaque_keys.edx.keys import UsageKey, CourseKey, AssetKey +from opaque_keys.edx.locations import Location, BlockUsageLocator, SlashSeparatedCourseKey from opaque_keys.edx.locator import CourseLocator, LibraryLocator -from openedx.core.lib.partitions.partitions_service import PartitionService -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin from path import Path as path from pytz import UTC from xblock.core import XBlock from xblock.exceptions import InvalidScopeError -from xblock.fields import Reference, ReferenceList, ReferenceValueDict, Scope, ScopeIds +from xblock.fields import Scope, ScopeIds, Reference, ReferenceList, ReferenceValueDict from xblock.runtime import KvsFieldData + from xmodule.assetstore import AssetMetadata, CourseAssetsFromStorage from xmodule.course_module import CourseSummary from xmodule.error_module import ErrorDescriptor -from xmodule.errortracker import exc_info_to_str, null_error_tracker +from xmodule.errortracker import null_error_tracker, exc_info_to_str from xmodule.exceptions import HeartbeatFailure from xmodule.mako_module import MakoDescriptorSystem -from xmodule.modulestore import BulkOperationsMixin, BulkOpsRecord, ModuleStoreEnum, ModuleStoreWriteBase -from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES, ModuleStoreDraftAndPublished +from xmodule.mongo_utils import connect_to_mongodb, create_collection_index +from xmodule.modulestore import ModuleStoreWriteBase, ModuleStoreEnum, BulkOperationsMixin, BulkOpsRecord +from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished, DIRECT_ONLY_CATEGORIES from xmodule.modulestore.edit_info import EditInfoRuntimeMixin -from xmodule.modulestore.exceptions import DuplicateCourseError, ItemNotFoundError, ReferentialIntegrityError -from xmodule.modulestore.inheritance import InheritanceKeyValueStore, inherit_metadata -from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES +from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateCourseError, ReferentialIntegrityError +from xmodule.modulestore.inheritance import InheritanceMixin, inherit_metadata, InheritanceKeyValueStore +from xmodule.partitions.partitions_service import PartitionService from xmodule.modulestore.xml import CourseLocationManager -from xmodule.mongo_utils import connect_to_mongodb, create_collection_index +from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES from xmodule.services import SettingsService + log = logging.getLogger(__name__) new_contract('CourseKey', CourseKey) diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py index 938b02d655a..2e5d3f7cfed 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/caching_descriptor_system.py @@ -1,25 +1,25 @@ -import logging import sys +import logging from contracts import contract, new_contract from fs.osfs import OSFS from lazy import lazy -from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator, DefinitionLocator, LibraryLocator, LocalId -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from xblock.core import XBlock +from xblock.runtime import KvsFieldData, KeyValueStore from xblock.fields import ScopeIds -from xblock.runtime import KeyValueStore, KvsFieldData -from xmodule.error_module import ErrorDescriptor -from xmodule.errortracker import exc_info_to_str +from xblock.core import XBlock +from opaque_keys.edx.locator import BlockUsageLocator, LocalId, CourseLocator, LibraryLocator, DefinitionLocator + from xmodule.library_tools import LibraryToolsService from xmodule.mako_module import MakoDescriptorSystem +from xmodule.error_module import ErrorDescriptor +from xmodule.errortracker import exc_info_to_str from xmodule.modulestore import BlockData from xmodule.modulestore.edit_info import EditInfoRuntimeMixin from xmodule.modulestore.exceptions import ItemNotFoundError -from xmodule.modulestore.inheritance import inheriting_field_data +from xmodule.modulestore.inheritance import inheriting_field_data, InheritanceMixin from xmodule.modulestore.split_mongo import BlockKey, CourseEnvelope -from xmodule.modulestore.split_mongo.definition_lazy_loader import DefinitionLazyLoader from xmodule.modulestore.split_mongo.id_manager import SplitMongoIdManager +from xmodule.modulestore.split_mongo.definition_lazy_loader import DefinitionLazyLoader from xmodule.modulestore.split_mongo.split_mongo_kvs import SplitMongoKVS from xmodule.x_module import XModuleMixin diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py index 65931b7b2ac..3e1a393f52a 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py @@ -57,56 +57,41 @@ import copy import datetime import hashlib import logging -from collections import defaultdict -from importlib import import_module -from types import NoneType - import six - -from bson.objectid import ObjectId -from ccx_keys.locator import CCXBlockUsageLocator, CCXLocator from contracts import contract, new_contract +from importlib import import_module from mongodb_proxy import autoretry_read -from opaque_keys.edx.keys import CourseKey -from opaque_keys.edx.locator import ( - BlockUsageLocator, - CourseLocator, - DefinitionLocator, - LibraryLocator, - LocalId, - VersionTree -) -from openedx.core.lib.partitions.partitions_service import PartitionService -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin from path import Path as path from pytz import UTC +from bson.objectid import ObjectId + from xblock.core import XBlock -from xblock.fields import Reference, ReferenceList, ReferenceValueDict, Scope -from xmodule.assetstore import AssetMetadata +from xblock.fields import Scope, Reference, ReferenceList, ReferenceValueDict from xmodule.course_module import CourseSummary -from xmodule.error_module import ErrorDescriptor from xmodule.errortracker import null_error_tracker -from xmodule.modulestore import ( - BlockData, - BulkOperationsMixin, - BulkOpsRecord, - ModuleStoreEnum, - ModuleStoreWriteBase, - SortedAssetList +from opaque_keys.edx.keys import CourseKey +from opaque_keys.edx.locator import ( + BlockUsageLocator, DefinitionLocator, CourseLocator, LibraryLocator, VersionTree, LocalId, ) -from xmodule.modulestore.exceptions import ( - DuplicateCourseError, - DuplicateItemError, - InsufficientSpecificationError, - MultipleCourseBlocksFound, - VersionConflictError +from ccx_keys.locator import CCXLocator, CCXBlockUsageLocator +from xmodule.modulestore.exceptions import InsufficientSpecificationError, VersionConflictError, DuplicateItemError, \ + DuplicateCourseError, MultipleCourseBlocksFound +from xmodule.modulestore import ( + inheritance, ModuleStoreWriteBase, ModuleStoreEnum, + BulkOpsRecord, BulkOperationsMixin, SortedAssetList, BlockData ) -from xmodule.modulestore.split_mongo import BlockKey, CourseEnvelope -from xmodule.modulestore.split_mongo.mongo_connection import DuplicateKeyError, MongoConnection -from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES from ..exceptions import ItemNotFoundError from .caching_descriptor_system import CachingDescriptorSystem +from xmodule.partitions.partitions_service import PartitionService +from xmodule.modulestore.split_mongo.mongo_connection import MongoConnection, DuplicateKeyError +from xmodule.modulestore.split_mongo import BlockKey, CourseEnvelope +from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES +from xmodule.error_module import ErrorDescriptor +from collections import defaultdict +from types import NoneType +from xmodule.assetstore import AssetMetadata + log = logging.getLogger(__name__) @@ -2164,7 +2149,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase): else: inherited_settings = parent_xblock.xblock_kvs.inherited_settings.copy() if fields is not None: - for field_name in InheritanceMixin.fields: + for field_name in inheritance.InheritanceMixin.fields: if field_name in fields: inherited_settings[field_name] = fields[field_name] @@ -2713,7 +2698,7 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase): # update the inheriting w/ what should pass to children inheriting_settings = inherited_settings_map[block_key].copy() block_fields = block_data.fields - for field_name in InheritanceMixin.fields: + for field_name in inheritance.InheritanceMixin.fields: if field_name in block_fields: inheriting_settings[field_name] = block_fields[field_name] diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py b/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py index ef40c9d7e6f..042198113fb 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_cross_modulestore_import_export.py @@ -14,25 +14,23 @@ and then for each combination of modulestores, performing the sequence: import itertools import os +from path import Path as path from shutil import rmtree from tempfile import mkdtemp import ddt -from mock import patch from nose.plugins.attrib import attr -from openedx.core.lib.partitions.tests.test_partitions import PartitionTestCase -from path import Path as path +from mock import patch + +from xmodule.tests import CourseComparisonTest +from xmodule.modulestore.xml_importer import import_course_from_xml +from xmodule.modulestore.xml_exporter import export_course_to_xml +from xmodule.modulestore.tests.utils import mock_tab_from_json +from xmodule.partitions.tests.test_partitions import PartitionTestCase from xmodule.modulestore.tests.utils import ( - CONTENTSTORE_SETUPS, - MODULESTORE_SETUPS, - SPLIT_MODULESTORE_SETUP, - TEST_DATA_DIR, - MongoContentstoreBuilder, - mock_tab_from_json + MongoContentstoreBuilder, MODULESTORE_SETUPS, SPLIT_MODULESTORE_SETUP, + CONTENTSTORE_SETUPS, TEST_DATA_DIR ) -from xmodule.modulestore.xml_exporter import export_course_to_xml -from xmodule.modulestore.xml_importer import import_course_from_xml -from xmodule.tests import CourseComparisonTest COURSE_DATA_NAMES = ( 'toy', diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py index 0645e6afb65..59917387f51 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py @@ -1,66 +1,59 @@ """ Unit tests for the Mixed Modulestore, with DDT for the various stores (Split, Draft, XML) """ +from collections import namedtuple import datetime -import itertools import logging +import ddt +import itertools import mimetypes -from collections import namedtuple -from contextlib import contextmanager -from shutil import rmtree -from tempfile import mkdtemp from uuid import uuid4 +from contextlib import contextmanager +from mock import patch, Mock, call -import ddt -import pymongo # Mixed modulestore depends on django, so we'll manually configure some django settings # before importing the module # TODO remove this import and the configuration -- xmodule should not depend on django! from django.conf import settings -from mock import Mock, call, patch -from nose import SkipTest # This import breaks this test file when run separately. Needs to be fixed! (PLAT-449) from nose.plugins.attrib import attr -from opaque_keys.edx.locations import SlashSeparatedCourseKey -from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator, LibraryLocator -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin +from nose import SkipTest +import pymongo from pytz import UTC +from shutil import rmtree +from tempfile import mkdtemp + +from xmodule.x_module import XModuleMixin +from xmodule.modulestore.edit_info import EditInfoMixin +from xmodule.modulestore.inheritance import InheritanceMixin +from xmodule.modulestore.tests.utils import MongoContentstoreBuilder +from xmodule.contentstore.content import StaticContent +from xmodule.modulestore.xml_importer import import_course_from_xml +from xmodule.modulestore.xml_exporter import export_course_to_xml +from xmodule.modulestore.tests.test_asides import AsideTestType from xblock.core import XBlockAside -from xblock.fields import Scope, ScopeIds, String +from xblock.fields import Scope, String, ScopeIds from xblock.fragment import Fragment from xblock.runtime import DictKeyValueStore, KvsFieldData from xblock.test.tools import TestRuntime -from xmodule.contentstore.content import StaticContent + +if not settings.configured: + settings.configure() + +from opaque_keys.edx.locations import SlashSeparatedCourseKey +from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator, LibraryLocator from xmodule.exceptions import InvalidVersionError from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES, UnsupportedRevisionError -from xmodule.modulestore.edit_info import EditInfoMixin -from xmodule.modulestore.exceptions import ( - DuplicateCourseError, - ItemNotFoundError, - NoPathToItem, - ReferentialIntegrityError -) +from xmodule.modulestore.draft_and_published import UnsupportedRevisionError, DIRECT_ONLY_CATEGORIES +from xmodule.modulestore.exceptions import ItemNotFoundError, DuplicateCourseError, ReferentialIntegrityError, NoPathToItem from xmodule.modulestore.mixed import MixedModuleStore -from xmodule.modulestore.search import navigation_index, path_to_location +from xmodule.modulestore.search import path_to_location, navigation_index from xmodule.modulestore.store_utilities import DETACHED_XBLOCK_TYPES -from xmodule.modulestore.tests.factories import check_exact_number_of_calls, check_mongo_calls, mongo_uses_error_check -from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM -from xmodule.modulestore.tests.test_asides import AsideTestType -from xmodule.modulestore.tests.utils import ( - LocationMixin, - MongoContentstoreBuilder, - create_modulestore_instance, - mock_tab_from_json -) -from xmodule.modulestore.xml_exporter import export_course_to_xml -from xmodule.modulestore.xml_importer import import_course_from_xml +from xmodule.modulestore.tests.factories import check_mongo_calls, check_exact_number_of_calls, \ + mongo_uses_error_check +from xmodule.modulestore.tests.utils import create_modulestore_instance, LocationMixin, mock_tab_from_json +from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST from xmodule.tests import DATA_DIR, CourseComparisonTest -from xmodule.x_module import XModuleMixin - -if not settings.configured: - settings.configure() - log = logging.getLogger(__name__) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py index ec17c0d63a3..90b6fd395b2 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py @@ -1,54 +1,52 @@ """ Unit tests for the Mongo modulestore """ - +# pylint: disable=protected-access +# pylint: disable=no-name-in-module +# pylint: disable=bad-continuation +from nose.tools import assert_equals, assert_raises, \ + assert_not_equals, assert_false, assert_true, assert_greater, assert_is_instance, assert_is_none +# pylint: enable=E0611 +from path import Path as path +import pymongo import logging import shutil -import unittest -from datetime import datetime from tempfile import mkdtemp from uuid import uuid4 - -import pymongo -from git.test.lib.asserts import assert_not_none -from mock import patch -# pylint: disable=no-name-in-module -# pylint: disable=bad-continuation -from nose.tools import ( - assert_equals, - assert_false, - assert_greater, - assert_in, - assert_is_instance, - assert_is_none, - assert_not_equals, - assert_raises, - assert_true -) -from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locations import AssetLocation, Location, SlashSeparatedCourseKey -from opaque_keys.edx.locator import CourseLocator, LibraryLocator -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from path import Path as path +from datetime import datetime from pytz import UTC +import unittest +from mock import patch from xblock.core import XBlock -from xblock.exceptions import InvalidScopeError -from xblock.fields import Reference, ReferenceList, ReferenceValueDict, Scope + +from xblock.fields import Scope, Reference, ReferenceList, ReferenceValueDict from xblock.runtime import KeyValueStore -from xmodule.contentstore.mongo import MongoContentStore -from xmodule.exceptions import NotFoundError +from xblock.exceptions import InvalidScopeError + +from xmodule.tests import DATA_DIR +from opaque_keys.edx.keys import CourseKey +from opaque_keys.edx.locations import Location from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.draft import DraftModuleStore -from xmodule.modulestore.edit_info import EditInfoMixin -from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.mongo import MongoKeyValueStore -from xmodule.modulestore.mongo.base import as_draft -from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM -from xmodule.modulestore.tests.utils import LocationMixin, mock_tab_from_json +from xmodule.modulestore.draft import DraftModuleStore +from opaque_keys.edx.locations import SlashSeparatedCourseKey, AssetLocation +from opaque_keys.edx.locator import LibraryLocator, CourseLocator +from opaque_keys.edx.keys import UsageKey from xmodule.modulestore.xml_exporter import export_course_to_xml from xmodule.modulestore.xml_importer import import_course_from_xml, perform_xlint -from xmodule.tests import DATA_DIR +from xmodule.contentstore.mongo import MongoContentStore + +from nose.tools import assert_in +from xmodule.exceptions import NotFoundError +from git.test.lib.asserts import assert_not_none from xmodule.x_module import XModuleMixin +from xmodule.modulestore.mongo.base import as_draft +from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST +from xmodule.modulestore.tests.utils import LocationMixin, mock_tab_from_json +from xmodule.modulestore.edit_info import EditInfoMixin +from xmodule.modulestore.exceptions import ItemNotFoundError +from xmodule.modulestore.inheritance import InheritanceMixin + log = logging.getLogger(__name__) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py index 29025c440cb..42835c42223 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore.py @@ -1,42 +1,42 @@ """ Test split modulestore w/o using any django stuff. """ +from mock import patch import datetime +from importlib import import_module +from path import Path as path import random import re import unittest import uuid -from importlib import import_module import ddt -from ccx_keys.locator import CCXBlockUsageLocator from contracts import contract -from django.core.cache import InvalidCacheBackendError, caches -from mock import patch from nose.plugins.attrib import attr -from opaque_keys.edx.locator import BlockUsageLocator, CourseKey, CourseLocator, LocalId, VersionTree +from django.core.cache import caches, InvalidCacheBackendError + from openedx.core.lib import tempdir -from openedx.core.lib.xblock_fields.fields import Date, Timedelta -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from path import Path as path from xblock.fields import Reference, ReferenceList, ReferenceValueDict from xmodule.course_module import CourseDescriptor from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.edit_info import EditInfoMixin from xmodule.modulestore.exceptions import ( - DuplicateCourseError, - DuplicateItemError, - InsufficientSpecificationError, - ItemNotFoundError, - VersionConflictError + ItemNotFoundError, VersionConflictError, + DuplicateItemError, DuplicateCourseError, + InsufficientSpecificationError ) -from xmodule.modulestore.split_mongo import BlockKey +from opaque_keys.edx.locator import CourseKey, CourseLocator, BlockUsageLocator, VersionTree, LocalId +from ccx_keys.locator import CCXBlockUsageLocator +from xmodule.modulestore.inheritance import InheritanceMixin +from xmodule.x_module import XModuleMixin +from xmodule.fields import Date, Timedelta from xmodule.modulestore.split_mongo.split import SplitMongoModuleStore -from xmodule.modulestore.tests.factories import check_mongo_calls -from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM from xmodule.modulestore.tests.test_modulestore import check_has_course_method +from xmodule.modulestore.split_mongo import BlockKey +from xmodule.modulestore.tests.factories import check_mongo_calls +from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST from xmodule.modulestore.tests.utils import mock_tab_from_json -from xmodule.x_module import XModuleMixin +from xmodule.modulestore.edit_info import EditInfoMixin + BRANCH_NAME_DRAFT = ModuleStoreEnum.BranchName.draft BRANCH_NAME_PUBLISHED = ModuleStoreEnum.BranchName.published diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py index b45ea6d2da4..a9e92b12119 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_w_old_mongo.py @@ -3,16 +3,17 @@ import random import unittest import uuid -import mock from nose.plugins.attrib import attr -from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin +import mock + +from opaque_keys.edx.locator import CourseLocator, BlockUsageLocator from xmodule.modulestore import ModuleStoreEnum +from xmodule.x_module import XModuleMixin +from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.modulestore.mongo import DraftMongoModuleStore from xmodule.modulestore.split_mongo.split import SplitMongoModuleStore -from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM +from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST from xmodule.modulestore.tests.utils import MemoryCache -from xmodule.x_module import XModuleMixin @attr('mongo') diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py b/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py index 93577346c0a..6cc5913374f 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_xml_importer.py @@ -1,21 +1,21 @@ """ Tests for XML importer. """ -import importlib -import unittest -from uuid import uuid4 - import mock -from opaque_keys.edx.locations import Location, SlashSeparatedCourseKey from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from xblock.fields import List, Scope, ScopeIds, String -from xblock.runtime import DictKeyValueStore, KvsFieldData, Runtime +from xblock.fields import String, Scope, ScopeIds, List +from xblock.runtime import Runtime, KvsFieldData, DictKeyValueStore +from xmodule.x_module import XModuleMixin +from opaque_keys.edx.locations import Location from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM +from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.modulestore.xml_importer import _update_and_import_module, _update_module_location +from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST +from opaque_keys.edx.locations import SlashSeparatedCourseKey from xmodule.tests import DATA_DIR -from xmodule.x_module import XModuleMixin +from uuid import uuid4 +import unittest +import importlib class ModuleStoreNoSettings(unittest.TestCase): diff --git a/common/lib/xmodule/xmodule/modulestore/tests/utils.py b/common/lib/xmodule/xmodule/modulestore/tests/utils.py index 4c9f577e6b0..e9666423c72 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/utils.py @@ -2,29 +2,30 @@ Helper classes and methods for running modulestore tests without Django. """ import random + from contextlib import contextmanager, nested from importlib import import_module +from opaque_keys.edx.keys import UsageKey +from path import Path as path from shutil import rmtree from tempfile import mkdtemp from unittest import TestCase -from opaque_keys.edx.keys import UsageKey -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from path import Path as path from xblock.fields import XBlockMixin +from xmodule.x_module import XModuleMixin from xmodule.contentstore.mongo import MongoContentStore from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.draft_and_published import ModuleStoreDraftAndPublished from xmodule.modulestore.edit_info import EditInfoMixin +from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.modulestore.mixed import MixedModuleStore from xmodule.modulestore.mongo.base import ModuleStoreEnum from xmodule.modulestore.mongo.draft import DraftModuleStore from xmodule.modulestore.split_mongo.split_draft import DraftVersioningModuleStore from xmodule.modulestore.tests.factories import ItemFactory -from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM +from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST from xmodule.modulestore.xml import XMLModuleStore from xmodule.tests import DATA_DIR -from xmodule.x_module import XModuleMixin def load_function(path): diff --git a/openedx/core/lib/partitions/__init__.py b/common/lib/xmodule/xmodule/partitions/__init__.py similarity index 100% rename from openedx/core/lib/partitions/__init__.py rename to common/lib/xmodule/xmodule/partitions/__init__.py diff --git a/openedx/core/lib/partitions/partitions.py b/common/lib/xmodule/xmodule/partitions/partitions.py similarity index 100% rename from openedx/core/lib/partitions/partitions.py rename to common/lib/xmodule/xmodule/partitions/partitions.py diff --git a/openedx/core/lib/partitions/partitions_service.py b/common/lib/xmodule/xmodule/partitions/partitions_service.py similarity index 98% rename from openedx/core/lib/partitions/partitions_service.py rename to common/lib/xmodule/xmodule/partitions/partitions_service.py index de5d5b7ab13..39c8dbe9300 100644 --- a/openedx/core/lib/partitions/partitions_service.py +++ b/common/lib/xmodule/xmodule/partitions/partitions_service.py @@ -7,7 +7,7 @@ from django.conf import settings from django.utils.translation import ugettext_lazy as _ import logging -from .partitions import UserPartition, UserPartitionError, ENROLLMENT_TRACK_PARTITION_ID +from xmodule.partitions.partitions import UserPartition, UserPartitionError, ENROLLMENT_TRACK_PARTITION_ID from xmodule.modulestore.django import modulestore diff --git a/openedx/core/lib/partitions/tests/__init__.py b/common/lib/xmodule/xmodule/partitions/tests/__init__.py similarity index 100% rename from openedx/core/lib/partitions/tests/__init__.py rename to common/lib/xmodule/xmodule/partitions/tests/__init__.py diff --git a/openedx/core/lib/partitions/tests/test_partitions.py b/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py similarity index 99% rename from openedx/core/lib/partitions/tests/test_partitions.py rename to common/lib/xmodule/xmodule/partitions/tests/test_partitions.py index 2d3aaf1ee17..3b37bbb4d85 100644 --- a/openedx/core/lib/partitions/tests/test_partitions.py +++ b/common/lib/xmodule/xmodule/partitions/tests/test_partitions.py @@ -8,11 +8,11 @@ from mock import Mock from opaque_keys.edx.locator import CourseLocator from stevedore.extension import Extension, ExtensionManager -from openedx.core.lib.partitions.partitions import ( +from xmodule.partitions.partitions import ( Group, UserPartition, UserPartitionError, NoSuchUserPartitionGroupError, USER_PARTITION_SCHEME_NAMESPACE, ENROLLMENT_TRACK_PARTITION_ID ) -from openedx.core.lib.partitions.partitions_service import ( +from xmodule.partitions.partitions_service import ( PartitionService, get_all_partitions_for_course, FEATURES ) diff --git a/common/lib/xmodule/xmodule/seq_module.py b/common/lib/xmodule/xmodule/seq_module.py index 75e232ffd8e..ecda5cc4503 100644 --- a/common/lib/xmodule/xmodule/seq_module.py +++ b/common/lib/xmodule/xmodule/seq_module.py @@ -4,23 +4,22 @@ xModule implementation of a learning sequence # pylint: disable=abstract-method import collections +from datetime import datetime +from django.utils.timezone import UTC import json import logging -from datetime import datetime - from pkg_resources import resource_string -from django.utils.timezone import UTC from lxml import etree -from openedx.core.lib.xblock_fields.fields import Date from xblock.core import XBlock -from xblock.fields import Boolean, Integer, Scope, String +from xblock.fields import Integer, Scope, Boolean, String from xblock.fragment import Fragment from .exceptions import NotFoundError +from .fields import Date from .mako_module import MakoModuleDescriptor from .progress import Progress -from .x_module import STUDENT_VIEW, XModule +from .x_module import XModule, STUDENT_VIEW from .xml_module import XmlDescriptor log = logging.getLogger(__name__) diff --git a/common/lib/xmodule/xmodule/split_test_module.py b/common/lib/xmodule/xmodule/split_test_module.py index e9cb2a25f6e..58aebaa7f51 100644 --- a/common/lib/xmodule/xmodule/split_test_module.py +++ b/common/lib/xmodule/xmodule/split_test_module.py @@ -2,22 +2,24 @@ Module for running content split tests """ -import json import logging -from operator import itemgetter +import json +from webob import Response from uuid import uuid4 +from operator import itemgetter -from lxml import etree -from openedx.core.lib.xblock_fields.inherited_fields import UserPartitionList -from webob import Response -from xblock.core import XBlock -from xblock.fields import Integer, ReferenceValueDict, Scope, String -from xblock.fragment import Fragment from xmodule.progress import Progress from xmodule.seq_module import SequenceDescriptor -from xmodule.studio_editable import StudioEditableDescriptor, StudioEditableModule +from xmodule.studio_editable import StudioEditableModule, StudioEditableDescriptor +from xmodule.x_module import XModule, module_attr, STUDENT_VIEW from xmodule.validation import StudioValidation, StudioValidationMessage -from xmodule.x_module import STUDENT_VIEW, XModule, module_attr +from xmodule.modulestore.inheritance import UserPartitionList + +from lxml import etree + +from xblock.core import XBlock +from xblock.fields import Scope, Integer, String, ReferenceValueDict +from xblock.fragment import Fragment log = logging.getLogger('edx.' + __name__) diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index e34e2709149..498e145479c 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -25,13 +25,12 @@ from path import Path as path from opaque_keys.edx.locations import SlashSeparatedCourseKey from xblock.field_data import DictFieldData from xblock.fields import ScopeIds, Scope, Reference, ReferenceList, ReferenceValueDict -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin from xmodule.assetstore import AssetMetadata from xmodule.error_module import ErrorDescriptor from xmodule.mako_module import MakoDescriptorSystem from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES, ModuleStoreDraftAndPublished -from xmodule.modulestore.inheritance import own_metadata +from xmodule.modulestore.inheritance import InheritanceMixin, own_metadata from xmodule.modulestore.mongo.draft import DraftModuleStore from xmodule.modulestore.xml import CourseLocationManager from xmodule.x_module import ModuleSystem, XModuleDescriptor, XModuleMixin diff --git a/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py b/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py index 3074fea4f2b..06014a9bd71 100644 --- a/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py +++ b/common/lib/xmodule/xmodule/tests/test_course_metadata_utils.py @@ -6,7 +6,6 @@ from datetime import timedelta, datetime from unittest import TestCase from pytz import utc -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE from xmodule.block_metadata_utils import ( url_name_for_block, display_name_with_default, @@ -17,6 +16,7 @@ from xmodule.course_metadata_utils import ( number_for_course_location, has_course_started, has_course_ended, + DEFAULT_START_DATE, course_start_date_is_default, may_certify_for_course, ) diff --git a/common/lib/xmodule/xmodule/tests/test_fields.py b/common/lib/xmodule/xmodule/tests/test_fields.py index 5cd03c32f2d..4464470eab9 100644 --- a/common/lib/xmodule/xmodule/tests/test_fields.py +++ b/common/lib/xmodule/xmodule/tests/test_fields.py @@ -4,7 +4,9 @@ import datetime import unittest from django.utils.timezone import UTC -from openedx.core.lib.xblock_fields.fields import Date, RelativeTime, Timedelta, TimeInfo + +from xmodule.fields import Date, Timedelta, RelativeTime +from xmodule.timeinfo import TimeInfo class DateTest(unittest.TestCase): diff --git a/common/lib/xmodule/xmodule/tests/test_import.py b/common/lib/xmodule/xmodule/tests/test_import.py index b2e373b3dc6..f557d7959ae 100644 --- a/common/lib/xmodule/xmodule/tests/test_import.py +++ b/common/lib/xmodule/xmodule/tests/test_import.py @@ -1,25 +1,30 @@ # -*- coding: utf-8 -*- import datetime +import ddt import unittest -import ddt -from django.utils.timezone import UTC from fs.memoryfs import MemoryFS from lxml import etree from mock import Mock, patch -from opaque_keys.edx.locations import Location, SlashSeparatedCourseKey -from openedx.core.lib.xblock_fields.fields import Date -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from xblock.core import XBlock -from xblock.fields import Integer, Scope, String -from xblock.runtime import DictKeyValueStore, KvsFieldData + +from django.utils.timezone import UTC + +from xmodule.xml_module import is_pointer_tag +from opaque_keys.edx.locations import Location from xmodule.modulestore import only_xmodules +from xmodule.modulestore.xml import ImportSystem, XMLModuleStore, LibraryXMLModuleStore from xmodule.modulestore.inheritance import compute_inherited_metadata -from xmodule.modulestore.xml import ImportSystem, LibraryXMLModuleStore, XMLModuleStore -from xmodule.tests import DATA_DIR from xmodule.x_module import XModuleMixin -from xmodule.xml_module import is_pointer_tag +from xmodule.fields import Date +from xmodule.tests import DATA_DIR +from xmodule.modulestore.inheritance import InheritanceMixin +from opaque_keys.edx.locations import SlashSeparatedCourseKey + +from xblock.core import XBlock +from xblock.fields import Scope, String, Integer +from xblock.runtime import KvsFieldData, DictKeyValueStore + ORG = 'test_org' COURSE = 'test_course' diff --git a/common/lib/xmodule/xmodule/tests/test_lti_unit.py b/common/lib/xmodule/xmodule/tests/test_lti_unit.py index a3d05050c49..ce83fed6031 100644 --- a/common/lib/xmodule/xmodule/tests/test_lti_unit.py +++ b/common/lib/xmodule/xmodule/tests/test_lti_unit.py @@ -2,17 +2,17 @@ """Test for LTI Xmodule functional logic.""" import datetime -import textwrap -import urllib -from copy import copy - from django.utils.timezone import UTC +from mock import Mock, patch, PropertyMock +import textwrap from lxml import etree -from mock import Mock, PropertyMock, patch -from openedx.core.lib.xblock_fields.fields import Timedelta from webob.request import Request -from xmodule.lti_2_util import LTIError +from copy import copy +import urllib + +from xmodule.fields import Timedelta from xmodule.lti_module import LTIDescriptor +from xmodule.lti_2_util import LTIError from . import LogicTest diff --git a/common/lib/xmodule/xmodule/tests/test_split_test_module.py b/common/lib/xmodule/xmodule/tests/test_split_test_module.py index 043edc1078a..ba23497d85b 100644 --- a/common/lib/xmodule/xmodule/tests/test_split_test_module.py +++ b/common/lib/xmodule/xmodule/tests/test_split_test_module.py @@ -3,20 +3,17 @@ Tests for the Split Testing Module """ import ddt import lxml -from fs.memoryfs import MemoryFS from mock import Mock, patch -from openedx.core.lib.partitions.partitions import MINIMUM_STATIC_PARTITION_ID, Group, UserPartition -from openedx.core.lib.partitions.tests.test_partitions import ( - MockPartitionService, - MockUserPartitionScheme, - PartitionTestCase -) -from xmodule.split_test_module import SplitTestDescriptor, SplitTestFields, get_split_user_partitions -from xmodule.tests import get_test_system +from fs.memoryfs import MemoryFS + +from xmodule.partitions.tests.test_partitions import MockPartitionService, PartitionTestCase, MockUserPartitionScheme from xmodule.tests.xml import factories as xml from xmodule.tests.xml import XModuleXmlImportTest -from xmodule.validation import StudioValidationMessage +from xmodule.tests import get_test_system from xmodule.x_module import AUTHOR_VIEW, STUDENT_VIEW +from xmodule.validation import StudioValidationMessage +from xmodule.split_test_module import SplitTestDescriptor, SplitTestFields, get_split_user_partitions +from xmodule.partitions.partitions import Group, UserPartition, MINIMUM_STATIC_PARTITION_ID class SplitTestModuleFactory(xml.XmlImportFactory): diff --git a/common/lib/xmodule/xmodule/tests/test_xml_module.py b/common/lib/xmodule/xmodule/tests/test_xml_module.py index 86dc651cf8f..290d5b1000f 100644 --- a/common/lib/xmodule/xmodule/tests/test_xml_module.py +++ b/common/lib/xmodule/xmodule/tests/test_xml_module.py @@ -4,29 +4,24 @@ import unittest from mock import Mock -from nose.tools import ( # pylint: disable=no-name-in-module - assert_equals, - assert_false, - assert_in, - assert_not_equals, - assert_not_in, - assert_true -) +from nose.tools import assert_equals, assert_not_equals, assert_true, assert_false, assert_in, assert_not_in # pylint: disable=no-name-in-module from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator -from openedx.core.lib.xblock_fields.fields import Date, RelativeTime, Timedelta -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin + from xblock.field_data import DictFieldData -from xblock.fields import Any, Boolean, Dict, Float, Integer, List, Scope, String -from xblock.runtime import DictKeyValueStore, KvsFieldData -from xmodule.course_module import CourseDescriptor -from xmodule.modulestore.inheritance import InheritanceKeyValueStore, InheritingFieldData +from xblock.fields import Scope, String, Dict, Boolean, Integer, Float, Any, List +from xblock.runtime import KvsFieldData, DictKeyValueStore + +from xmodule.fields import Date, Timedelta, RelativeTime +from xmodule.modulestore.inheritance import InheritanceKeyValueStore, InheritanceMixin, InheritingFieldData from xmodule.modulestore.split_mongo.split_mongo_kvs import SplitMongoKVS +from xmodule.xml_module import XmlDescriptor, serialize_field, deserialize_field +from xmodule.course_module import CourseDescriptor from xmodule.seq_module import SequenceDescriptor +from xmodule.x_module import XModuleMixin + from xmodule.tests import get_test_descriptor_system from xmodule.tests.xml import XModuleXmlImportTest -from xmodule.tests.xml.factories import CourseFactory, ProblemFactory, SequenceFactory -from xmodule.x_module import XModuleMixin -from xmodule.xml_module import XmlDescriptor, deserialize_field, serialize_field +from xmodule.tests.xml.factories import CourseFactory, SequenceFactory, ProblemFactory class CrazyJsonString(String): diff --git a/common/lib/xmodule/xmodule/tests/xml/factories.py b/common/lib/xmodule/xmodule/tests/xml/factories.py index a9067134727..903f2d925ea 100644 --- a/common/lib/xmodule/xmodule/tests/xml/factories.py +++ b/common/lib/xmodule/xmodule/tests/xml/factories.py @@ -4,13 +4,14 @@ Factories for generating edXML for testing XModule import import inspect -from factory import Factory, Sequence, lazy_attribute, post_generation from fs.memoryfs import MemoryFS +from factory import Factory, lazy_attribute, post_generation, Sequence from lxml import etree -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin + from xblock.mixins import HierarchyMixin -from xmodule.modulestore import only_xmodules +from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.x_module import XModuleMixin +from xmodule.modulestore import only_xmodules class XmlImportData(object): diff --git a/common/lib/xmodule/xmodule/timeinfo.py b/common/lib/xmodule/xmodule/timeinfo.py new file mode 100644 index 00000000000..17ac38de52f --- /dev/null +++ b/common/lib/xmodule/xmodule/timeinfo.py @@ -0,0 +1,38 @@ +import logging +from xmodule.fields import Timedelta +log = logging.getLogger(__name__) + + +class TimeInfo(object): + """ + This is a simple object that calculates and stores datetime information for an XModule + based on the due date and the grace period string + + So far it parses out three different pieces of time information: + self.display_due_date - the 'official' due date that gets displayed to students + self.grace_period - the length of the grace period + self.close_date - the real due date + + """ + _delta_standin = Timedelta() + + def __init__(self, due_date, grace_period_string_or_timedelta): + if due_date is not None: + self.display_due_date = due_date + + else: + self.display_due_date = None + + if grace_period_string_or_timedelta is not None and self.display_due_date: + if isinstance(grace_period_string_or_timedelta, basestring): + try: + self.grace_period = TimeInfo._delta_standin.from_json(grace_period_string_or_timedelta) + except: + log.error("Error parsing the grace period {0}".format(grace_period_string_or_timedelta)) + raise + else: + self.grace_period = grace_period_string_or_timedelta + self.close_date = self.display_due_date + self.grace_period + else: + self.grace_period = None + self.close_date = self.display_due_date diff --git a/common/lib/xmodule/xmodule/video_module/video_handlers.py b/common/lib/xmodule/xmodule/video_module/video_handlers.py index a6809ec1c91..be70ef0a757 100644 --- a/common/lib/xmodule/xmodule/video_module/video_handlers.py +++ b/common/lib/xmodule/xmodule/video_module/video_handlers.py @@ -8,24 +8,26 @@ StudioViewHandlers are handlers for video descriptor instance. import json import logging from datetime import datetime - -from opaque_keys.edx.locator import CourseLocator -from openedx.core.lib.xblock_fields.fields import RelativeTime from webob import Response + from xblock.core import XBlock + from xmodule.exceptions import NotFoundError +from xmodule.fields import RelativeTime +from opaque_keys.edx.locator import CourseLocator from .transcripts_utils import ( - Transcript, + get_or_create_sjson, TranscriptException, TranscriptsGenerationException, generate_sjson_for_all_speeds, - get_or_create_sjson, + youtube_speed_dict, + Transcript, save_to_store, - subs_filename, - youtube_speed_dict + subs_filename ) + log = logging.getLogger(__name__) diff --git a/common/lib/xmodule/xmodule/video_module/video_xfields.py b/common/lib/xmodule/xmodule/video_module/video_xfields.py index bf358aaeb18..cec00363918 100644 --- a/common/lib/xmodule/xmodule/video_module/video_xfields.py +++ b/common/lib/xmodule/xmodule/video_module/video_xfields.py @@ -3,8 +3,8 @@ XFields for video module. """ import datetime -from openedx.core.lib.xblock_fields.fields import RelativeTime -from xblock.fields import Boolean, DateTime, Dict, Float, List, Scope, String +from xblock.fields import Scope, String, Float, Boolean, List, Dict, DateTime +from xmodule.fields import RelativeTime # Make '_' a no-op so we can scrape strings. Using lambda instead of # `django.utils.translation.ugettext_noop` because Django cannot be imported in this file diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index f8dc7fdd9ac..7e707f48848 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -2,42 +2,41 @@ import logging import os import sys import time -from collections import namedtuple -from functools import partial - -from pkg_resources import resource_exists, resource_isdir, resource_listdir, resource_string - -import dogstats_wrapper as dog_stats_api import yaml + from contracts import contract, new_contract -from lazy import lazy +from functools import partial from lxml import etree -from opaque_keys.edx.asides import AsideDefinitionKeyV2, AsideUsageKeyV2 -from opaque_keys.edx.keys import UsageKey -from openedx.core.lib.xblock_fields.fields import RelativeTime +from collections import namedtuple +from pkg_resources import ( + resource_exists, + resource_listdir, + resource_string, + resource_isdir, +) from webob import Response from webob.multidict import MultiDict +from lazy import lazy + from xblock.core import XBlock, XBlockAside from xblock.fields import ( - Dict, - Float, - Integer, - List, - Reference, - ReferenceList, - ReferenceValueDict, - Scope, - ScopeIds, - String, - UserScope + Scope, Integer, Float, List, + String, Dict, ScopeIds, Reference, ReferenceList, + ReferenceValueDict, UserScope ) + from xblock.fragment import Fragment -from xblock.runtime import IdGenerator, IdReader, Runtime +from xblock.runtime import Runtime, IdReader, IdGenerator from xmodule import block_metadata_utils +from xmodule.fields import RelativeTime from xmodule.errortracker import exc_info_to_str -from xmodule.exceptions import UndefinedContext from xmodule.modulestore.exceptions import ItemNotFoundError +from opaque_keys.edx.keys import UsageKey +from opaque_keys.edx.asides import AsideUsageKeyV2, AsideDefinitionKeyV2 +from xmodule.exceptions import UndefinedContext +import dogstats_wrapper as dog_stats_api + log = logging.getLogger(__name__) XMODULE_METRIC_NAME = 'edxapp.xmodule' diff --git a/common/test/acceptance/tests/discussion/test_cohort_management.py b/common/test/acceptance/tests/discussion/test_cohort_management.py index 2c93172ab48..5d0319ea901 100644 --- a/common/test/acceptance/tests/discussion/test_cohort_management.py +++ b/common/test/acceptance/tests/discussion/test_cohort_management.py @@ -3,22 +3,22 @@ End-to-end tests related to the cohort management on the LMS Instructor Dashboard """ -import os -import uuid from datetime import datetime -import unicodecsv +from pytz import UTC, utc from bok_choy.promise import EmptyPromise from nose.plugins.attrib import attr -from pytz import UTC, utc - +from common.test.acceptance.tests.discussion.helpers import CohortTestMixin +from common.test.acceptance.tests.helpers import UniqueCourseTest, EventsTestMixin, create_user_partition_json +from xmodule.partitions.partitions import Group from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage -from common.test.acceptance.pages.lms.instructor_dashboard import DataDownloadPage, InstructorDashboardPage +from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage, DataDownloadPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage -from common.test.acceptance.tests.discussion.helpers import CohortTestMixin -from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest, create_user_partition_json -from openedx.core.lib.partitions.partitions import Group + +import os +import unicodecsv +import uuid @attr(shard=8) diff --git a/common/test/acceptance/tests/helpers.py b/common/test/acceptance/tests/helpers.py index 174b9fd4ce5..da988ec6a37 100644 --- a/common/test/acceptance/tests/helpers.py +++ b/common/test/acceptance/tests/helpers.py @@ -2,40 +2,42 @@ Test helper functions and base classes. """ -import functools import inspect import json +import unittest +import functools import operator -import os import pprint -import unittest +import requests +import os import urlparse from contextlib import contextmanager from datetime import datetime -from unittest import TestCase +from path import Path as path -import requests from bok_choy.javascript import js_defined -from bok_choy.page_object import XSS_INJECTION -from bok_choy.promise import EmptyPromise, Promise from bok_choy.web_app_test import WebAppTest +from bok_choy.promise import EmptyPromise, Promise +from bok_choy.page_object import XSS_INJECTION +from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory +from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage +from common.test.acceptance.fixtures.course import XBlockFixtureDesc from opaque_keys.edx.locator import CourseLocator -from path import Path as path -from pymongo import ASCENDING, MongoClient +from pymongo import MongoClient, ASCENDING +from openedx.core.lib.tests.assertions.events import assert_event_matches, is_matching_event, EventMatchTolerates +from xmodule.partitions.partitions import UserPartition from selenium.common.exceptions import StaleElementReferenceException from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.webdriver.common.keys import Keys -from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.select import Select from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from unittest import TestCase + +from openedx.core.release import doc_version, RELEASE_LINE -from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory -from common.test.acceptance.fixtures.course import XBlockFixtureDesc from common.test.acceptance.pages.common import BASE_URL -from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage -from openedx.core.lib.partitions.partitions import UserPartition -from openedx.core.lib.tests.assertions.events import EventMatchTolerates, assert_event_matches, is_matching_event -from openedx.core.release import RELEASE_LINE, doc_version + MAX_EVENTS_IN_FAILURE_OUTPUT = 20 diff --git a/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py b/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py index 5b7c1a40350..265f2874a0e 100644 --- a/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py +++ b/common/test/acceptance/tests/lms/test_lms_split_test_courseware_search.py @@ -4,16 +4,20 @@ Test courseware search import json -from nose.plugins.attrib import attr - -from common.test.acceptance.fixtures.course import XBlockFixtureDesc +from common.test.acceptance.tests.helpers import remove_file from common.test.acceptance.pages.common.logout import LogoutPage -from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage -from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage from common.test.acceptance.pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage -from common.test.acceptance.tests.helpers import create_user_partition_json, remove_file +from common.test.acceptance.pages.lms.courseware_search import CoursewareSearchPage +from common.test.acceptance.fixtures.course import XBlockFixtureDesc +from common.test.acceptance.tests.helpers import create_user_partition_json + +from xmodule.partitions.partitions import Group + +from nose.plugins.attrib import attr + from common.test.acceptance.tests.studio.base_studio_test import ContainerBase -from openedx.core.lib.partitions.partitions import Group + +from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage as StudioAutoAuthPage @attr(shard=1) diff --git a/common/test/acceptance/tests/lms/test_lms_user_preview.py b/common/test/acceptance/tests/lms/test_lms_user_preview.py index 7939ada94eb..e7ad6484eee 100644 --- a/common/test/acceptance/tests/lms/test_lms_user_preview.py +++ b/common/test/acceptance/tests/lms/test_lms_user_preview.py @@ -4,17 +4,17 @@ Tests the "preview" selector in the LMS that allows changing between Staff, Lear """ -from textwrap import dedent - from nose.plugins.attrib import attr -from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc +from common.test.acceptance.tests.helpers import UniqueCourseTest, create_user_partition_json +from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.instructor_dashboard import InstructorDashboardPage from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage -from common.test.acceptance.pages.studio.auto_auth import AutoAuthPage -from common.test.acceptance.tests.helpers import UniqueCourseTest, create_user_partition_json -from openedx.core.lib.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID, Group +from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc +from bok_choy.promise import EmptyPromise +from xmodule.partitions.partitions import (Group, ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID) +from textwrap import dedent @attr(shard=10) diff --git a/common/test/acceptance/tests/studio/test_studio_container.py b/common/test/acceptance/tests/studio/test_studio_container.py index 00b71d1b583..8ba505561e9 100644 --- a/common/test/acceptance/tests/studio/test_studio_container.py +++ b/common/test/acceptance/tests/studio/test_studio_container.py @@ -4,23 +4,26 @@ The container page is used both for displaying units, and for displaying containers within units. """ import datetime -from unittest import skip - import ddt from nose.plugins.attrib import attr +from unittest import skip from base_studio_test import ContainerBase + from common.test.acceptance.fixtures.course import XBlockFixtureDesc -from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.lms.create_mode import ModeCreationPage -from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.pages.studio.component_editor import ComponentEditorView, ComponentVisibilityEditorView from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.html_component_editor import HtmlComponentEditorView from common.test.acceptance.pages.studio.move_xblock import MoveModalView from common.test.acceptance.pages.studio.utils import add_discussion, drag +from common.test.acceptance.pages.lms.courseware import CoursewarePage +from common.test.acceptance.pages.lms.staff_view import StaffCoursewarePage from common.test.acceptance.tests.helpers import create_user_partition_json -from openedx.core.lib.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID, Group + +from xmodule.partitions.partitions import ( + Group, ENROLLMENT_TRACK_PARTITION_ID, MINIMUM_STATIC_PARTITION_ID +) class NestedVerticalTest(ContainerBase): diff --git a/common/test/acceptance/tests/studio/test_studio_settings.py b/common/test/acceptance/tests/studio/test_studio_settings.py index 9324e2462f9..1ec99374752 100644 --- a/common/test/acceptance/tests/studio/test_studio_settings.py +++ b/common/test/acceptance/tests/studio/test_studio_settings.py @@ -3,9 +3,10 @@ Acceptance tests for Studio's Setting pages """ from __future__ import unicode_literals - import os -from textwrap import dedent + +from mock import patch +from nose.plugins.attrib import attr from bok_choy.promise import EmptyPromise from mock import patch @@ -13,15 +14,17 @@ from nose.plugins.attrib import attr from base_studio_test import StudioCourseTest from common.test.acceptance.fixtures.course import XBlockFixtureDesc -from common.test.acceptance.pages.common.utils import add_enrollment_course_modes -from common.test.acceptance.pages.lms.courseware import CoursewarePage +from common.test.acceptance.tests.helpers import create_user_partition_json, element_has_text from common.test.acceptance.pages.studio.overview import CourseOutlinePage from common.test.acceptance.pages.studio.settings import SettingsPage from common.test.acceptance.pages.studio.settings_advanced import AdvancedSettingsPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage +from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.studio.utils import get_input_value -from common.test.acceptance.tests.helpers import create_user_partition_json, element_has_text -from openedx.core.lib.partitions.partitions import Group +from common.test.acceptance.pages.common.utils import add_enrollment_course_modes + +from textwrap import dedent +from xmodule.partitions.partitions import Group @attr(shard=8) diff --git a/common/test/acceptance/tests/studio/test_studio_split_test.py b/common/test/acceptance/tests/studio/test_studio_split_test.py index 125d06d1681..9bc0c4d90bb 100644 --- a/common/test/acceptance/tests/studio/test_studio_split_test.py +++ b/common/test/acceptance/tests/studio/test_studio_split_test.py @@ -4,22 +4,24 @@ Acceptance tests for Studio related to the split_test module. import math from unittest import skip - -from bok_choy.promise import Promise from nose.plugins.attrib import attr from selenium.webdriver.support.ui import Select -from base_studio_test import StudioCourseTest +from xmodule.partitions.partitions import Group +from bok_choy.promise import Promise, EmptyPromise + from common.test.acceptance.fixtures.course import XBlockFixtureDesc -from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.pages.studio.component_editor import ComponentEditorView -from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.overview import CourseOutlinePage, CourseOutlineUnit +from common.test.acceptance.pages.studio.container import ContainerPage from common.test.acceptance.pages.studio.settings_group_configurations import GroupConfigurationsPage from common.test.acceptance.pages.studio.utils import add_advanced_component from common.test.acceptance.pages.xblock.utils import wait_for_xblock_initialization +from common.test.acceptance.pages.lms.courseware import CoursewarePage from common.test.acceptance.tests.helpers import create_user_partition_json -from openedx.core.lib.partitions.partitions import Group + +from base_studio_test import StudioCourseTest + from test_studio_container import ContainerBase diff --git a/lms/djangoapps/course_api/tests/test_serializers.py b/lms/djangoapps/course_api/tests/test_serializers.py index b6e850a954c..b1d1e76bb6a 100644 --- a/lms/djangoapps/course_api/tests/test_serializers.py +++ b/lms/djangoapps/course_api/tests/test_serializers.py @@ -9,11 +9,11 @@ import ddt from nose.plugins.attrib import attr from openedx.core.djangoapps.models.course_details import CourseDetails from openedx.core.djangoapps.content.course_overviews.models import CourseOverview -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE from rest_framework.test import APIRequestFactory from rest_framework.request import Request from xblock.core import XBlock +from xmodule.course_module import DEFAULT_START_DATE from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import check_mongo_calls diff --git a/lms/djangoapps/course_blocks/transformers/start_date.py b/lms/djangoapps/course_blocks/transformers/start_date.py index 40e7cdd125f..561d3c31532 100644 --- a/lms/djangoapps/course_blocks/transformers/start_date.py +++ b/lms/djangoapps/course_blocks/transformers/start_date.py @@ -6,7 +6,7 @@ from openedx.core.djangoapps.content.block_structure.transformer import ( FilteringTransformerMixin, ) from lms.djangoapps.courseware.access_utils import check_start_date -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE +from xmodule.course_metadata_utils import DEFAULT_START_DATE from .utils import collect_merged_date_field diff --git a/lms/djangoapps/course_blocks/transformers/tests/test_split_test.py b/lms/djangoapps/course_blocks/transformers/tests/test_split_test.py index 74c56ef1ebe..f5110868f5a 100644 --- a/lms/djangoapps/course_blocks/transformers/tests/test_split_test.py +++ b/lms/djangoapps/course_blocks/transformers/tests/test_split_test.py @@ -2,11 +2,12 @@ Tests for SplitTestTransformer. """ import ddt -import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api from nose.plugins.attrib import attr + +import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme -from openedx.core.lib.partitions.partitions import Group, UserPartition from student.tests.factories import CourseEnrollmentFactory +from xmodule.partitions.partitions import Group, UserPartition from xmodule.modulestore.tests.factories import check_mongo_calls from ...api import get_course_blocks diff --git a/lms/djangoapps/course_blocks/transformers/tests/test_user_partitions.py b/lms/djangoapps/course_blocks/transformers/tests/test_user_partitions.py index 3ec49242165..2d51078a3b2 100644 --- a/lms/djangoapps/course_blocks/transformers/tests/test_user_partitions.py +++ b/lms/djangoapps/course_blocks/transformers/tests/test_user_partitions.py @@ -2,17 +2,17 @@ """ Tests for UserPartitionTransformer. """ -import string from collections import namedtuple - import ddt from nose.plugins.attrib import attr -from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort +import string + from openedx.core.djangoapps.course_groups.partition_scheme import CohortPartitionScheme from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory, config_course_cohorts +from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort from openedx.core.djangoapps.course_groups.views import link_cohort_to_partition_group -from openedx.core.lib.partitions.partitions import Group, UserPartition from student.tests.factories import CourseEnrollmentFactory +from xmodule.partitions.partitions import Group, UserPartition from xmodule.modulestore.tests.factories import CourseFactory from ...api import get_course_blocks diff --git a/lms/djangoapps/course_blocks/transformers/user_partitions.py b/lms/djangoapps/course_blocks/transformers/user_partitions.py index 488ae1ac5c5..a01cdf3b54a 100644 --- a/lms/djangoapps/course_blocks/transformers/user_partitions.py +++ b/lms/djangoapps/course_blocks/transformers/user_partitions.py @@ -3,9 +3,9 @@ User Partitions Transformer """ from openedx.core.djangoapps.content.block_structure.transformer import ( BlockStructureTransformer, - FilteringTransformerMixin + FilteringTransformerMixin, ) -from openedx.core.lib.partitions.partitions_service import get_all_partitions_for_course +from xmodule.partitions.partitions_service import get_all_partitions_for_course from .split_test import SplitTestTransformer from .utils import get_field_on_block diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py index 1718bc8d902..c60368fe1da 100644 --- a/lms/djangoapps/courseware/access.py +++ b/lms/djangoapps/courseware/access.py @@ -10,12 +10,33 @@ Note: The access control logic in this file does NOT check for enrollment in If enrollment is to be checked, use get_course_with_access in courseware.courses. It is a wrapper around has_access that additionally checks for enrollment. """ -import logging from datetime import datetime - +import logging import pytz -from ccx_keys.locator import CCXLocator -from courseware.access_response import MilestoneError, MobileAvailabilityError, VisibilityError + +from django.conf import settings +from django.contrib.auth.models import AnonymousUser +from django.utils.timezone import UTC + +from opaque_keys.edx.keys import CourseKey, UsageKey + +from util import milestones_helpers as milestones_helpers +from xblock.core import XBlock + +from xmodule.course_module import ( + CourseDescriptor, + CATALOG_VISIBILITY_CATALOG_AND_ABOUT, + CATALOG_VISIBILITY_ABOUT, +) +from xmodule.error_module import ErrorDescriptor +from xmodule.x_module import XModule +from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPartitionGroupError + +from courseware.access_response import ( + MilestoneError, + MobileAvailabilityError, + VisibilityError, +) from courseware.access_utils import ( ACCESS_DENIED, ACCESS_GRANTED, @@ -25,16 +46,11 @@ from courseware.access_utils import ( in_preview_mode ) from courseware.masquerade import get_masquerade_role, is_masquerading_as_student -from django.conf import settings -from django.contrib.auth.models import AnonymousUser -from django.utils.timezone import UTC from lms.djangoapps.ccx.custom_exception import CCXLocatorValidationException from lms.djangoapps.ccx.models import CustomCourseForEdX from mobile_api.models import IgnoreMobileAvailableFlagConfig -from opaque_keys.edx.keys import CourseKey, UsageKey from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.external_auth.models import ExternalAuthMap -from openedx.core.lib.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPartitionGroupError from student import auth from student.models import CourseEnrollmentAllowed from student.roles import ( @@ -43,20 +59,16 @@ from student.roles import ( CourseInstructorRole, CourseStaffRole, GlobalStaff, + SupportStaffRole, OrgInstructorRole, OrgStaffRole, - SupportStaffRole ) -from util import milestones_helpers as milestones_helpers from util.milestones_helpers import ( - any_unfulfilled_milestones, get_pre_requisite_courses_not_completed, - is_prerequisite_courses_enabled + any_unfulfilled_milestones, + is_prerequisite_courses_enabled, ) -from xblock.core import XBlock -from xmodule.course_module import CATALOG_VISIBILITY_ABOUT, CATALOG_VISIBILITY_CATALOG_AND_ABOUT, CourseDescriptor -from xmodule.error_module import ErrorDescriptor -from xmodule.x_module import XModule +from ccx_keys.locator import CCXLocator log = logging.getLogger(__name__) diff --git a/lms/djangoapps/courseware/access_response.py b/lms/djangoapps/courseware/access_response.py index 75c86547d1a..976571cf241 100644 --- a/lms/djangoapps/courseware/access_response.py +++ b/lms/djangoapps/courseware/access_response.py @@ -3,7 +3,7 @@ This file contains all the classes used by has_access for error handling """ from django.utils.translation import ugettext as _ -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE +from xmodule.course_metadata_utils import DEFAULT_START_DATE class AccessResponse(object): diff --git a/lms/djangoapps/courseware/field_overrides.py b/lms/djangoapps/courseware/field_overrides.py index 2f9be430e11..02417d95157 100644 --- a/lms/djangoapps/courseware/field_overrides.py +++ b/lms/djangoapps/courseware/field_overrides.py @@ -14,15 +14,17 @@ package and is used to wrap the `authored_data` when constructing an `LmsFieldData`. This means overrides will be in effect for all scopes covered by `authored_data`, e.g. course content and settings stored in Mongo. """ -import threading from abc import ABCMeta, abstractmethod from contextlib import contextmanager +import threading from django.conf import settings -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin -from request_cache.middleware import RequestCache from xblock.field_data import FieldData +from request_cache.middleware import RequestCache +from xmodule.modulestore.inheritance import InheritanceMixin + + NOTSET = object() ENABLED_OVERRIDE_PROVIDERS_KEY = u'courseware.field_overrides.enabled_providers.{course_id}' ENABLED_MODULESTORE_OVERRIDE_PROVIDERS_KEY = u'courseware.modulestore_field_overrides.enabled_providers.{course_id}' diff --git a/lms/djangoapps/courseware/masquerade.py b/lms/djangoapps/courseware/masquerade.py index ce4eb590831..5cfeac5c109 100644 --- a/lms/djangoapps/courseware/masquerade.py +++ b/lms/djangoapps/courseware/masquerade.py @@ -11,12 +11,14 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.utils.translation import ugettext as _ from django.views.decorators.http import require_POST -from opaque_keys.edx.keys import CourseKey -from openedx.core.lib.partitions.partitions import NoSuchUserPartitionGroupError from student.models import CourseEnrollment -from util.json_request import JsonResponse, expect_json +from util.json_request import expect_json, JsonResponse + +from opaque_keys.edx.keys import CourseKey from xblock.fragment import Fragment from xblock.runtime import KeyValueStore +from xmodule.partitions.partitions import NoSuchUserPartitionGroupError + log = logging.getLogger(__name__) diff --git a/lms/djangoapps/courseware/tests/test_access.py b/lms/djangoapps/courseware/tests/test_access.py index ad32685be2f..f509c9f6feb 100644 --- a/lms/djangoapps/courseware/tests/test_access.py +++ b/lms/djangoapps/courseware/tests/test_access.py @@ -3,60 +3,66 @@ Test the access control framework """ import datetime +import ddt import itertools +import pytz +from django.contrib.auth.models import User +from ccx_keys.locator import CCXLocator +from django.test.client import RequestFactory +from django.core.urlresolvers import reverse +from django.test import TestCase +from mock import Mock, patch +from nose.plugins.attrib import attr +from opaque_keys.edx.locations import SlashSeparatedCourseKey + +from ccx.tests.factories import CcxFactory import courseware.access as access import courseware.access_response as access_response -import ddt -import pytz -from ccx.tests.factories import CcxFactory -from ccx_keys.locator import CCXLocator from courseware.masquerade import CourseMasquerade from courseware.tests.factories import ( BetaTesterFactory, GlobalStaffFactory, InstructorFactory, StaffFactory, - UserFactory + UserFactory, ) from courseware.tests.helpers import LoginEnrollmentTestCase, masquerade_as_group_member -from django.contrib.auth.models import User -from django.core.urlresolvers import reverse -from django.test import TestCase -from django.test.client import RequestFactory -from lms.djangoapps.ccx.models import CustomCourseForEdX -from milestones.tests.utils import MilestonesTestCaseMixin -from mock import Mock, patch -from nose.plugins.attrib import attr -from opaque_keys.edx.locations import SlashSeparatedCourseKey from openedx.core.djangoapps.content.course_overviews.models import CourseOverview -from openedx.core.lib.partitions.partitions import MINIMUM_STATIC_PARTITION_ID, Group, UserPartition from student.models import CourseEnrollment from student.roles import CourseCcxCoachRole, CourseStaffRole from student.tests.factories import ( AdminFactory, AnonymousUserFactory, CourseEnrollmentAllowedFactory, - CourseEnrollmentFactory + CourseEnrollmentFactory, ) -from util.milestones_helpers import fulfill_course_milestone, set_prerequisite_courses + from xmodule.course_module import ( - CATALOG_VISIBILITY_ABOUT, CATALOG_VISIBILITY_CATALOG_AND_ABOUT, - CATALOG_VISIBILITY_NONE + CATALOG_VISIBILITY_ABOUT, + CATALOG_VISIBILITY_NONE, ) from xmodule.error_module import ErrorDescriptor +from xmodule.partitions.partitions import Group, UserPartition, MINIMUM_STATIC_PARTITION_ID from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.django_utils import ( - TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, - SharedModuleStoreTestCase + SharedModuleStoreTestCase, + TEST_DATA_SPLIT_MODULESTORE ) -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.xml import CourseLocationManager from xmodule.tests import get_test_system +from util.milestones_helpers import ( + set_prerequisite_courses, + fulfill_course_milestone, +) +from milestones.tests.utils import MilestonesTestCaseMixin + +from lms.djangoapps.ccx.models import CustomCourseForEdX # pylint: disable=protected-access diff --git a/lms/djangoapps/courseware/tests/test_group_access.py b/lms/djangoapps/courseware/tests/test_group_access.py index dd2eb832492..a762e4d88bb 100644 --- a/lms/djangoapps/courseware/tests/test_group_access.py +++ b/lms/djangoapps/courseware/tests/test_group_access.py @@ -3,15 +3,17 @@ This module defines tests for courseware.access that are specific to group access control rules. """ -import courseware.access as access import ddt -from courseware.tests.factories import StaffFactory, UserFactory from nose.plugins.attrib import attr -from openedx.core.lib.partitions.partitions import USER_PARTITION_SCHEME_NAMESPACE, Group, UserPartition from stevedore.extension import Extension, ExtensionManager -from xmodule.modulestore.django import modulestore + from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.partitions.partitions import Group, UserPartition, USER_PARTITION_SCHEME_NAMESPACE +from xmodule.modulestore.django import modulestore + +import courseware.access as access +from courseware.tests.factories import StaffFactory, UserFactory class MemoryUserPartitionScheme(object): diff --git a/lms/djangoapps/courseware/tests/test_masquerade.py b/lms/djangoapps/courseware/tests/test_masquerade.py index 16809614bb7..64f175cf0d2 100644 --- a/lms/djangoapps/courseware/tests/test_masquerade.py +++ b/lms/djangoapps/courseware/tests/test_masquerade.py @@ -3,31 +3,32 @@ Unit tests for masquerade. """ import json import pickle +from mock import patch +from nose.plugins.attrib import attr from datetime import datetime +from django.core.urlresolvers import reverse +from django.test import TestCase +from django.utils.timezone import UTC + from capa.tests.response_xml_factory import OptionResponseXMLFactory from courseware.masquerade import ( CourseMasquerade, MasqueradingKeyValueStore, - get_masquerading_user_group, handle_ajax, - setup_masquerade + setup_masquerade, + get_masquerading_user_group ) from courseware.tests.factories import StaffFactory from courseware.tests.helpers import LoginEnrollmentTestCase, masquerade_as_group_member from courseware.tests.test_submitting_problems import ProblemSubmissionTestMixin -from django.core.urlresolvers import reverse -from django.test import TestCase -from django.utils.timezone import UTC -from mock import patch -from nose.plugins.attrib import attr -from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration -from openedx.core.lib.partitions.partitions import Group, UserPartition from student.tests.factories import UserFactory from xblock.runtime import DictKeyValueStore from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory +from xmodule.partitions.partitions import Group, UserPartition +from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration class MasqueradeTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase): diff --git a/lms/djangoapps/courseware/tests/test_split_module.py b/lms/djangoapps/courseware/tests/test_split_module.py index 4c6faea4057..c7aa323170d 100644 --- a/lms/djangoapps/courseware/tests/test_split_module.py +++ b/lms/djangoapps/courseware/tests/test_split_module.py @@ -1,16 +1,17 @@ """ Test for split test XModule """ -from courseware.model_data import FieldDataCache -from courseware.module_render import get_module_for_descriptor from django.core.urlresolvers import reverse from mock import MagicMock from nose.plugins.attrib import attr -from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory -from openedx.core.lib.partitions.partitions import Group, UserPartition -from student.tests.factories import CourseEnrollmentFactory, UserFactory + +from courseware.module_render import get_module_for_descriptor +from courseware.model_data import FieldDataCache +from student.tests.factories import UserFactory, CourseEnrollmentFactory +from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.partitions.partitions import Group, UserPartition +from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory @attr(shard=1) diff --git a/lms/djangoapps/courseware/tests/test_submitting_problems.py b/lms/djangoapps/courseware/tests/test_submitting_problems.py index 0d389fedc21..2532e67d551 100644 --- a/lms/djangoapps/courseware/tests/test_submitting_problems.py +++ b/lms/djangoapps/courseware/tests/test_submitting_problems.py @@ -10,33 +10,34 @@ import os from textwrap import dedent import ddt -from capa.tests.response_xml_factory import ( - CodeResponseXMLFactory, - CustomResponseXMLFactory, - OptionResponseXMLFactory, - SchematicResponseXMLFactory -) -from course_modes.models import CourseMode -from courseware.models import BaseStudentModuleHistory, StudentModule -from courseware.tests.helpers import LoginEnrollmentTestCase from django.conf import settings from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.test import TestCase from django.test.client import RequestFactory from django.utils.timezone import now -from lms.djangoapps.grades.new.course_grade_factory import CourseGradeFactory from mock import patch from nose.plugins.attrib import attr -from openedx.core.djangoapps.credit.api import get_credit_requirement_status, set_credit_requirements + +from capa.tests.response_xml_factory import ( + OptionResponseXMLFactory, CustomResponseXMLFactory, SchematicResponseXMLFactory, + CodeResponseXMLFactory, +) +from course_modes.models import CourseMode +from courseware.models import StudentModule, BaseStudentModuleHistory +from courseware.tests.helpers import LoginEnrollmentTestCase +from lms.djangoapps.grades.new.course_grade_factory import CourseGradeFactory +from openedx.core.djangoapps.credit.api import ( + set_credit_requirements, get_credit_requirement_status +) from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory -from openedx.core.lib.partitions.partitions import Group, UserPartition from openedx.core.lib.url_utils import quote_slashes -from student.models import CourseEnrollment, anonymous_id_for_user +from student.models import anonymous_id_for_user, CourseEnrollment from submissions import api as submissions_api from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.partitions.partitions import Group, UserPartition class ProblemSubmissionTestMixin(TestCase): diff --git a/lms/djangoapps/discussion_api/tests/test_api.py b/lms/djangoapps/discussion_api/tests/test_api.py index f32c90cc42e..32b818906d0 100644 --- a/lms/djangoapps/discussion_api/tests/test_api.py +++ b/lms/djangoapps/discussion_api/tests/test_api.py @@ -1,14 +1,24 @@ """ Tests for Discussion API internal interface """ -import itertools from datetime import datetime, timedelta -from urllib import urlencode +import itertools from urlparse import parse_qs, urlparse, urlunparse +from urllib import urlencode import ddt import httpretty import mock +from nose.plugins.attrib import attr +from pytz import UTC + +from django.core.exceptions import ValidationError +from django.test.client import RequestFactory + +from rest_framework.exceptions import PermissionDenied + +from opaque_keys.edx.locator import CourseLocator + from common.test.utils import MockSignalHandlerMixin, disable_signal from courseware.tests.factories import BetaTesterFactory, StaffFactory from discussion_api import api @@ -20,41 +30,35 @@ from discussion_api.api import ( get_comment_list, get_course, get_course_topics, - get_thread, get_thread_list, update_comment, - update_thread + update_thread, + get_thread, ) -from discussion_api.exceptions import CommentNotFoundError, DiscussionDisabledError, ThreadNotFoundError +from discussion_api.exceptions import DiscussionDisabledError, ThreadNotFoundError, CommentNotFoundError from discussion_api.tests.utils import ( CommentsServiceMockMixin, make_minimal_cs_comment, make_minimal_cs_thread, - make_paginated_api_response + make_paginated_api_response, ) -from django.core.exceptions import ValidationError -from django.test.client import RequestFactory -from django_comment_client.tests.utils import ForumsEnableMixin from django_comment_common.models import ( FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_MODERATOR, FORUM_ROLE_STUDENT, - Role + Role, ) -from nose.plugins.attrib import attr -from opaque_keys.edx.locator import CourseLocator +from django_comment_client.tests.utils import ForumsEnableMixin from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory from openedx.core.lib.exceptions import CourseNotFoundError, PageNotFoundError -from openedx.core.lib.partitions.partitions import Group, UserPartition -from pytz import UTC -from rest_framework.exceptions import PermissionDenied from student.tests.factories import CourseEnrollmentFactory, UserFactory from util.testing import UrlResetMixin from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.partitions.partitions import Group, UserPartition def _remove_discussion_tab(course, user_id): diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index 97a264052b6..b06a99bd7db 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -3,30 +3,15 @@ Unit tests for instructor.api methods. """ import datetime +import ddt import functools +import random +import pytz import io import json -import random import shutil import tempfile -import ddt -import lms.djangoapps.instructor.views.api -import lms.djangoapps.instructor_task.api -import pytz -from bulk_email.models import BulkEmailFlag, CourseEmail, CourseEmailTemplate -from certificates.models import CertificateStatuses -from certificates.tests.factories import GeneratedCertificateFactory -from course_modes.models import CourseMode -from courseware.models import StudentFieldOverride, StudentModule -from courseware.tests.factories import ( - BetaTesterFactory, - GlobalStaffFactory, - InstructorFactory, - StaffFactory, - UserProfileFactory -) -from courseware.tests.helpers import LoginEnrollmentTestCase from django.conf import settings from django.contrib.auth.models import User from django.core import mail @@ -37,56 +22,55 @@ from django.test import RequestFactory, TestCase from django.test.utils import override_settings from django.utils.timezone import utc from django.utils.translation import ugettext as _ -from django_comment_common.models import FORUM_ROLE_COMMUNITY_TA -from django_comment_common.utils import seed_permissions_roles -from lms.djangoapps.instructor.tests.utils import FakeContentTask, FakeEmail, FakeEmailInfo -from lms.djangoapps.instructor.views.api import ( - _split_input_list, - common_exceptions_400, - generate_unique_password, - require_finance_admin -) -from lms.djangoapps.instructor_task.api_helper import AlreadyRunningError + from mock import Mock, patch -from nose.plugins.attrib import attr from nose.tools import raises +from nose.plugins.attrib import attr from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locator import UsageKey -from openedx.core.djangoapps.course_groups.cohorts import set_course_cohort_settings -from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin -from openedx.core.lib.xblock_fields.fields import Date -from openedx.core.lib.xblock_utils import grade_histogram -from shoppingcart.models import ( - Coupon, - CouponRedemption, - CourseRegistrationCode, - CourseRegistrationCodeInvoiceItem, - Invoice, - InvoiceTransaction, - Order, - PaidCourseRegistration, - RegistrationCodeRedemption +from xmodule.modulestore import ModuleStoreEnum + +from bulk_email.models import BulkEmailFlag, CourseEmail, CourseEmailTemplate +from course_modes.models import CourseMode +from courseware.models import StudentModule +from courseware.tests.factories import ( + BetaTesterFactory, GlobalStaffFactory, InstructorFactory, StaffFactory, UserProfileFactory ) +from courseware.tests.helpers import LoginEnrollmentTestCase +from django_comment_common.models import FORUM_ROLE_COMMUNITY_TA +from django_comment_common.utils import seed_permissions_roles +from shoppingcart.models import ( + RegistrationCodeRedemption, Order, CouponRedemption, + PaidCourseRegistration, Coupon, Invoice, CourseRegistrationCode, CourseRegistrationCodeInvoiceItem, + InvoiceTransaction) from shoppingcart.pdf import PDFInvoice from student.models import ( - ALLOWEDTOENROLL_TO_ENROLLED, - ALLOWEDTOENROLL_TO_UNENROLLED, - ENROLLED_TO_ENROLLED, - ENROLLED_TO_UNENROLLED, - UNENROLLED_TO_ALLOWEDTOENROLL, - UNENROLLED_TO_ENROLLED, - UNENROLLED_TO_UNENROLLED, - CourseEnrollment, - CourseEnrollmentAllowed, - ManualEnrollmentAudit, - NonExistentCourseError + CourseEnrollment, CourseEnrollmentAllowed, NonExistentCourseError, + ManualEnrollmentAudit, UNENROLLED_TO_ENROLLED, ENROLLED_TO_UNENROLLED, + ALLOWEDTOENROLL_TO_UNENROLLED, ENROLLED_TO_ENROLLED, UNENROLLED_TO_ALLOWEDTOENROLL, + UNENROLLED_TO_UNENROLLED, ALLOWEDTOENROLL_TO_ENROLLED ) -from student.roles import CourseBetaTesterRole, CourseFinanceAdminRole, CourseInstructorRole, CourseSalesAdminRole -from student.tests.factories import AdminFactory, CourseModeFactory, UserFactory -from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase +from student.tests.factories import UserFactory, CourseModeFactory, AdminFactory +from student.roles import CourseBetaTesterRole, CourseSalesAdminRole, CourseFinanceAdminRole, CourseInstructorRole +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.fields import Date + +from courseware.models import StudentFieldOverride + +import lms.djangoapps.instructor_task.api +import lms.djangoapps.instructor.views.api +from lms.djangoapps.instructor.views.api import require_finance_admin +from lms.djangoapps.instructor.tests.utils import FakeContentTask, FakeEmail, FakeEmailInfo +from lms.djangoapps.instructor.views.api import _split_input_list, common_exceptions_400, generate_unique_password +from lms.djangoapps.instructor_task.api_helper import AlreadyRunningError +from certificates.tests.factories import GeneratedCertificateFactory +from certificates.models import CertificateStatuses + +from openedx.core.djangoapps.course_groups.cohorts import set_course_cohort_settings +from openedx.core.lib.xblock_utils import grade_histogram +from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin from .test_tools import msk_from_problem_urlname diff --git a/lms/djangoapps/instructor/tests/test_tools.py b/lms/djangoapps/instructor/tests/test_tools.py index 727312bb5a3..da8fe04d483 100644 --- a/lms/djangoapps/instructor/tests/test_tools.py +++ b/lms/djangoapps/instructor/tests/test_tools.py @@ -3,20 +3,21 @@ Tests for views/tools.py. """ import datetime +import mock import json import unittest -import mock -from courseware.field_overrides import OverrideFieldData -from django.test.utils import override_settings from django.utils.timezone import utc -from lms.djangoapps.ccx.tests.test_overrides import inject_field_overrides +from django.test.utils import override_settings from nose.plugins.attrib import attr -from opaque_keys.edx.keys import CourseKey -from openedx.core.lib.xblock_fields.fields import Date + +from courseware.field_overrides import OverrideFieldData +from lms.djangoapps.ccx.tests.test_overrides import inject_field_overrides from student.tests.factories import UserFactory +from xmodule.fields import Date from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from opaque_keys.edx.keys import CourseKey from ..views import tools diff --git a/lms/djangoapps/instructor/views/tools.py b/lms/djangoapps/instructor/views/tools.py index aac26841ce5..9d6daa511d6 100644 --- a/lms/djangoapps/instructor/views/tools.py +++ b/lms/djangoapps/instructor/views/tools.py @@ -1,18 +1,23 @@ """ Tools for the instructor dashboard """ +import dateutil import json -import dateutil -from courseware.field_overrides import disable_overrides -from courseware.models import StudentFieldOverride -from courseware.student_field_overrides import clear_override_for_user, get_override_for_user, override_field_for_user from django.contrib.auth.models import User from django.http import HttpResponseBadRequest from django.utils.timezone import utc from django.utils.translation import ugettext as _ + +from courseware.models import StudentFieldOverride +from courseware.field_overrides import disable_overrides +from courseware.student_field_overrides import ( + clear_override_for_user, + get_override_for_user, + override_field_for_user, +) +from xmodule.fields import Date from opaque_keys.edx.keys import UsageKey -from openedx.core.lib.xblock_fields.fields import Date DATE_FIELD = Date() diff --git a/lms/djangoapps/instructor_task/tasks_helper/grades.py b/lms/djangoapps/instructor_task/tasks_helper/grades.py index fe0d5084645..b2cdcc69611 100644 --- a/lms/djangoapps/instructor_task/tasks_helper/grades.py +++ b/lms/djangoapps/instructor_task/tasks_helper/grades.py @@ -1,36 +1,37 @@ """ Functionality for generating grade reports. """ -import logging -import re from collections import OrderedDict from datetime import datetime -from itertools import chain, izip, izip_longest +from itertools import chain, izip_longest, izip +from lazy import lazy +import logging +from pytz import UTC +import re from time import time -from certificates.models import CertificateWhitelist, GeneratedCertificate, certificate_info_for_user -from courseware.courses import get_course_by_id from instructor_analytics.basic import list_problem_responses from instructor_analytics.csvs import format_dictlist -from lazy import lazy -from lms.djangoapps.grades.context import grading_context, grading_context_for_course -from lms.djangoapps.grades.models import PersistentCourseGrade +from certificates.models import CertificateWhitelist, certificate_info_for_user, GeneratedCertificate +from courseware.courses import get_course_by_id +from lms.djangoapps.grades.context import grading_context_for_course, grading_context from lms.djangoapps.grades.new.course_grade_factory import CourseGradeFactory +from lms.djangoapps.grades.models import PersistentCourseGrade from lms.djangoapps.teams.models import CourseTeamMembership from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from openedx.core.djangoapps.content.block_structure.api import get_course_in_cache -from openedx.core.djangoapps.course_groups.cohorts import bulk_cache_cohorts, get_cohort, is_course_cohorted +from openedx.core.djangoapps.course_groups.cohorts import get_cohort, is_course_cohorted, bulk_cache_cohorts from openedx.core.djangoapps.user_api.course_tag.api import BulkCourseTags -from openedx.core.lib.partitions.partitions_service import PartitionService -from pytz import UTC from student.models import CourseEnrollment from student.roles import BulkRoleCache from xmodule.modulestore.django import modulestore +from xmodule.partitions.partitions_service import PartitionService from xmodule.split_test_module import get_split_user_partitions from .runner import TaskProgress from .utils import upload_csv_to_report_store + TASK_LOG = logging.getLogger('edx.celery.task') diff --git a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py index 52404b57840..2f4d5fde7c4 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks_helper.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks_helper.py @@ -10,73 +10,79 @@ Unit tests for LMS instructor-initiated background tasks helper functions. import os import shutil -import tempfile -import urllib from datetime import datetime +import urllib +from django.conf import settings +from django.core.urlresolvers import reverse +from django.test.utils import override_settings import ddt -import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api +from freezegun import freeze_time +from mock import Mock, patch, MagicMock +from nose.plugins.attrib import attr +from pytz import UTC +import tempfile import unicodecsv + from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory from certificates.models import CertificateStatuses, GeneratedCertificate -from certificates.tests.factories import CertificateWhitelistFactory, GeneratedCertificateFactory +from certificates.tests.factories import GeneratedCertificateFactory, CertificateWhitelistFactory from course_modes.models import CourseMode from courseware.tests.factories import InstructorFactory -from django.conf import settings -from django.core.urlresolvers import reverse -from django.test.utils import override_settings -from freezegun import freeze_time from instructor_analytics.basic import UNAVAILABLE from lms.djangoapps.grades.models import PersistentCourseGrade from lms.djangoapps.grades.transformer import GradesTransformer -from lms.djangoapps.instructor_task.tasks_helper.certs import generate_students_certificates -from lms.djangoapps.instructor_task.tasks_helper.enrollments import ( - upload_enrollment_report, - upload_exec_summary_report, - upload_may_enroll_csv, - upload_students_csv -) -from lms.djangoapps.instructor_task.tasks_helper.grades import CourseGradeReport, ProblemGradeReport, ProblemResponses -from lms.djangoapps.instructor_task.tasks_helper.misc import ( - cohort_students_and_upload, - upload_course_survey_report, - upload_ora2_data -) -from lms.djangoapps.instructor_task.tests.test_base import ( - InstructorTaskCourseTestCase, - InstructorTaskModuleTestCase, - TestReportMixin -) from lms.djangoapps.teams.tests.factories import CourseTeamFactory, CourseTeamMembershipFactory from lms.djangoapps.verify_student.tests.factories import SoftwareSecurePhotoVerificationFactory -from mock import MagicMock, Mock, patch -from nose.plugins.attrib import attr -from openedx.core.djangoapps.course_groups.models import CohortMembership, CourseUserGroupPartitionGroup +from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup, CohortMembership from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory from openedx.core.djangoapps.credit.tests.factories import CreditCourseFactory +import openedx.core.djangoapps.user_api.course_tag.api as course_tag_api from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme from openedx.core.djangoapps.util.testing import ContentGroupTestCase, TestConditionalContent -from openedx.core.lib.partitions.partitions import Group, UserPartition -from pytz import UTC from request_cache.middleware import RequestCache from shoppingcart.models import ( - Coupon, - CourseRegistrationCode, - CourseRegistrationCodeInvoiceItem, - Invoice, - InvoiceTransaction, - Order, - PaidCourseRegistration + Order, PaidCourseRegistration, CourseRegistrationCode, Invoice, + CourseRegistrationCodeInvoiceItem, InvoiceTransaction, Coupon ) -from student.models import ALLOWEDTOENROLL_TO_ENROLLED, CourseEnrollment, CourseEnrollmentAllowed, ManualEnrollmentAudit +from student.models import CourseEnrollment, CourseEnrollmentAllowed, ManualEnrollmentAudit, ALLOWEDTOENROLL_TO_ENROLLED from student.tests.factories import CourseEnrollmentFactory, CourseModeFactory, UserFactory -from survey.models import SurveyAnswer, SurveyForm +from survey.models import SurveyForm, SurveyAnswer from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls +from xmodule.partitions.partitions import Group, UserPartition from ..models import ReportStore -from ..tasks_helper.utils import UPDATE_STATUS_FAILED, UPDATE_STATUS_SUCCEEDED +from lms.djangoapps.instructor_task.tasks_helper.certs import ( + generate_students_certificates, +) +from lms.djangoapps.instructor_task.tasks_helper.enrollments import ( + upload_enrollment_report, + upload_may_enroll_csv, + upload_exec_summary_report, + upload_students_csv, +) +from lms.djangoapps.instructor_task.tasks_helper.grades import ( + CourseGradeReport, + ProblemGradeReport, + ProblemResponses, +) +from lms.djangoapps.instructor_task.tasks_helper.misc import ( + cohort_students_and_upload, + upload_course_survey_report, + upload_ora2_data, +) +from ..tasks_helper.utils import ( + UPDATE_STATUS_FAILED, + UPDATE_STATUS_SUCCEEDED, +) + +from lms.djangoapps.instructor_task.tests.test_base import ( + InstructorTaskCourseTestCase, + TestReportMixin, + InstructorTaskModuleTestCase +) class InstructorGradeReportTestCase(TestReportMixin, InstructorTaskCourseTestCase): diff --git a/lms/djangoapps/lms_xblock/mixin.py b/lms/djangoapps/lms_xblock/mixin.py index dae6543e43d..7bf2ed4f7a9 100644 --- a/lms/djangoapps/lms_xblock/mixin.py +++ b/lms/djangoapps/lms_xblock/mixin.py @@ -4,11 +4,12 @@ Namespace that defines fields common to all blocks used in the LMS #from django.utils.translation import ugettext_noop as _ from lazy import lazy -from openedx.core.lib.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPartitionGroupError -from openedx.core.lib.xblock_fields.inherited_fields import UserPartitionList + from xblock.core import XBlock -from xblock.fields import Boolean, Dict, Scope, String, XBlockMixin +from xblock.fields import Boolean, Scope, String, XBlockMixin, Dict from xblock.validation import ValidationMessage +from xmodule.modulestore.inheritance import UserPartitionList +from xmodule.partitions.partitions import NoSuchUserPartitionError, NoSuchUserPartitionGroupError # Please do not remove, this is a workaround for Django 1.8. # more information can be found here: https://openedx.atlassian.net/browse/PLAT-902 diff --git a/lms/djangoapps/lms_xblock/runtime.py b/lms/djangoapps/lms_xblock/runtime.py index 0a8434ea7be..58bf0f1f96c 100644 --- a/lms/djangoapps/lms_xblock/runtime.py +++ b/lms/djangoapps/lms_xblock/runtime.py @@ -1,22 +1,24 @@ """ Module implementing `xblock.runtime.Runtime` functionality for the LMS """ -import xblock.reference.plugins -from badges.service import BadgingService -from badges.utils import badges_enabled from django.conf import settings from django.core.urlresolvers import reverse -from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig + +from badges.service import BadgingService +from badges.utils import badges_enabled from openedx.core.djangoapps.user_api.course_tag import api as user_course_tag_api -from openedx.core.lib.partitions.partitions_service import PartitionService -from openedx.core.lib.url_utils import quote_slashes from openedx.core.lib.xblock_utils import xblock_local_resource_url +from openedx.core.lib.url_utils import quote_slashes from request_cache.middleware import RequestCache +import xblock.reference.plugins from xmodule.library_tools import LibraryToolsService -from xmodule.modulestore.django import ModuleI18nService, modulestore +from xmodule.modulestore.django import modulestore, ModuleI18nService +from xmodule.partitions.partitions_service import PartitionService from xmodule.services import SettingsService from xmodule.x_module import ModuleSystem +from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig + def handler_url(block, handler_name, suffix='', query='', thirdparty=False): """ diff --git a/lms/djangoapps/mobile_api/users/tests.py b/lms/djangoapps/mobile_api/users/tests.py index c57ea6ccd8d..2cb0e642634 100644 --- a/lms/djangoapps/mobile_api/users/tests.py +++ b/lms/djangoapps/mobile_api/users/tests.py @@ -13,6 +13,7 @@ from django.utils import timezone from django.template import defaultfilters from django.test import RequestFactory, override_settings from milestones.tests.utils import MilestonesTestCaseMixin +from xmodule.course_module import DEFAULT_START_DATE from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory from certificates.api import generate_user_certificates @@ -26,7 +27,6 @@ from courseware.access_response import ( from course_modes.models import CourseMode from lms.djangoapps.grades.tests.utils import mock_passing_grade from openedx.core.lib.courses import course_image_url -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE from student.models import CourseEnrollment from util.milestones_helpers import set_prerequisite_courses from util.testing import UrlResetMixin diff --git a/lms/djangoapps/mobile_api/video_outlines/tests.py b/lms/djangoapps/mobile_api/video_outlines/tests.py index 1f4ba044159..877bb87b7cc 100644 --- a/lms/djangoapps/mobile_api/video_outlines/tests.py +++ b/lms/djangoapps/mobile_api/video_outlines/tests.py @@ -4,22 +4,23 @@ Tests for video outline API """ import itertools -from collections import namedtuple from uuid import uuid4 +from collections import namedtuple import ddt +from nose.plugins.attrib import attr from edxval import api +from xmodule.modulestore.tests.factories import ItemFactory +from xmodule.video_module import transcripts_utils +from xmodule.modulestore.django import modulestore +from xmodule.partitions.partitions import Group, UserPartition from milestones.tests.utils import MilestonesTestCaseMixin + from mobile_api.models import MobileApiConfig -from mobile_api.testutils import MobileAPITestCase, MobileAuthTestMixin, MobileCourseAccessTestMixin -from nose.plugins.attrib import attr -from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort, remove_user_from_cohort -from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory -from openedx.core.lib.partitions.partitions import Group, UserPartition -from xmodule.modulestore.django import modulestore -from xmodule.modulestore.tests.factories import ItemFactory -from xmodule.video_module import transcripts_utils +from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup +from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort, remove_user_from_cohort +from mobile_api.testutils import MobileAPITestCase, MobileAuthTestMixin, MobileCourseAccessTestMixin class TestVideoAPITestCase(MobileAPITestCase): diff --git a/lms/envs/common.py b/lms/envs/common.py index 5b06aade2d2..7b4640aa177 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -731,7 +731,7 @@ VIRTUAL_UNIVERSITIES = [] ############# XBlock Configuration ########## # Import after sys.path fixup -from openedx.core.lib.xblock_fields.inherited_fields import InheritanceMixin +from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.modulestore import prefer_xmodules from xmodule.x_module import XModuleMixin diff --git a/lms/lib/xblock/test/test_mixin.py b/lms/lib/xblock/test/test_mixin.py index 60d0e8b5e16..f6cd9d68e99 100644 --- a/lms/lib/xblock/test/test_mixin.py +++ b/lms/lib/xblock/test/test_mixin.py @@ -2,13 +2,14 @@ Tests of the LMS XBlock Mixin """ import ddt -from lms_xblock.mixin import INVALID_USER_PARTITION_GROUP_VALIDATION, INVALID_USER_PARTITION_VALIDATION from nose.plugins.attrib import attr -from openedx.core.lib.partitions.partitions import Group, UserPartition + +from lms_xblock.mixin import INVALID_USER_PARTITION_VALIDATION, INVALID_USER_PARTITION_GROUP_VALIDATION from xblock.validation import ValidationMessage from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, ToyCourseFactory +from xmodule.modulestore.tests.factories import CourseFactory, ToyCourseFactory, ItemFactory +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_MODULESTORE +from xmodule.partitions.partitions import Group, UserPartition class LmsXBlockMixinTestCase(ModuleStoreTestCase): diff --git a/lms/templates/preview_menu.html b/lms/templates/preview_menu.html index 297de686308..d5de16c7b7a 100644 --- a/lms/templates/preview_menu.html +++ b/lms/templates/preview_menu.html @@ -7,7 +7,7 @@ from django.utils.translation import ugettext as _ from django.conf import settings from openedx.core.djangolib.js_utils import dump_js_escaped_json from openedx.core.djangolib.markup import HTML, Text -from openedx.core.lib.partitions.partitions_service import get_all_partitions_for_course +from xmodule.partitions.partitions_service import get_all_partitions_for_course %> <% diff --git a/openedx/core/djangoapps/content/course_overviews/models.py b/openedx/core/djangoapps/content/course_overviews/models.py index f61d994f3b2..20330043ac3 100644 --- a/openedx/core/djangoapps/content/course_overviews/models.py +++ b/openedx/core/djangoapps/content/course_overviews/models.py @@ -20,11 +20,10 @@ from lms.djangoapps import django_comment_client from openedx.core.djangoapps.models.course_details import CourseDetails from static_replace.models import AssetBaseUrlConfig from xmodule import course_metadata_utils, block_metadata_utils -from xmodule.course_module import CourseDescriptor +from xmodule.course_module import CourseDescriptor, DEFAULT_START_DATE from xmodule.error_module import ErrorDescriptor from xmodule.modulestore.django import modulestore from openedx.core.djangoapps.xmodule_django.models import CourseKeyField, UsageKeyField -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE log = logging.getLogger(__name__) diff --git a/openedx/core/djangoapps/content/course_overviews/tests.py b/openedx/core/djangoapps/content/course_overviews/tests.py index 741951ad6d2..103db6d1403 100644 --- a/openedx/core/djangoapps/content/course_overviews/tests.py +++ b/openedx/core/djangoapps/content/course_overviews/tests.py @@ -19,11 +19,11 @@ from PIL import Image from lms.djangoapps.certificates.api import get_active_web_certificate from openedx.core.djangoapps.models.course_details import CourseDetails from openedx.core.lib.courses import course_image_url -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE from static_replace.models import AssetBaseUrlConfig from xmodule.assetstore.assetmgr import AssetManager from xmodule.contentstore.django import contentstore from xmodule.contentstore.content import StaticContent +from xmodule.course_metadata_utils import DEFAULT_START_DATE from xmodule.course_module import ( CATALOG_VISIBILITY_CATALOG_AND_ABOUT, CATALOG_VISIBILITY_ABOUT, diff --git a/openedx/core/djangoapps/course_groups/partition_scheme.py b/openedx/core/djangoapps/course_groups/partition_scheme.py index 4a5b37bba12..e47981a5f06 100644 --- a/openedx/core/djangoapps/course_groups/partition_scheme.py +++ b/openedx/core/djangoapps/course_groups/partition_scheme.py @@ -8,10 +8,11 @@ from courseware.masquerade import ( # pylint: disable=import-error get_masquerading_user_group, is_masquerading_as_specific_student ) -from openedx.core.lib.partitions.partitions import NoSuchUserPartitionGroupError +from xmodule.partitions.partitions import NoSuchUserPartitionGroupError from .cohorts import get_cohort, get_group_info_for_cohort + log = logging.getLogger(__name__) diff --git a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py index eb0b99932bf..1e28ad2afda 100644 --- a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py +++ b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py @@ -3,21 +3,22 @@ Test the partitions and partitions service """ import django.test -from courseware.tests.test_masquerade import StaffMasqueradeTestCase from mock import patch from nose.plugins.attrib import attr -from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme -from openedx.core.djangolib.testing.utils import skip_unless_lms -from openedx.core.lib.partitions.partitions import Group, UserPartition, UserPartitionError + +from courseware.tests.test_masquerade import StaffMasqueradeTestCase from student.tests.factories import UserFactory +from xmodule.partitions.partitions import Group, UserPartition, UserPartitionError from xmodule.modulestore.django import modulestore -from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_MODULESTORE from xmodule.modulestore.tests.factories import ToyCourseFactory -from ..cohorts import add_user_to_cohort, get_course_cohorts, remove_user_from_cohort -from ..models import CourseUserGroupPartitionGroup +from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme +from openedx.core.djangolib.testing.utils import skip_unless_lms from ..partition_scheme import CohortPartitionScheme, get_cohorted_user_partition +from ..models import CourseUserGroupPartitionGroup from ..views import link_cohort_to_partition_group, unlink_cohort_partition_group +from ..cohorts import add_user_to_cohort, remove_user_from_cohort, get_course_cohorts from .helpers import CohortFactory, config_course_cohorts diff --git a/openedx/core/djangoapps/models/course_details.py b/openedx/core/djangoapps/models/course_details.py index 4fb3d7c9175..6f0a2de2508 100644 --- a/openedx/core/djangoapps/models/course_details.py +++ b/openedx/core/djangoapps/models/course_details.py @@ -1,15 +1,17 @@ """ CourseDetails """ -import logging import re +import logging from django.conf import settings + +from xmodule.fields import Date +from xmodule.modulestore.exceptions import ItemNotFoundError from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration from openedx.core.lib.courses import course_image_url -from openedx.core.lib.xblock_fields.fields import Date from xmodule.modulestore.django import modulestore -from xmodule.modulestore.exceptions import ItemNotFoundError + # This list represents the attribute keys for a course's 'about' info. # Note: The 'video' attribute is intentionally excluded as it must be diff --git a/openedx/core/djangoapps/user_api/partition_schemes.py b/openedx/core/djangoapps/user_api/partition_schemes.py index 85ba29fa1cc..070acbd0cc5 100644 --- a/openedx/core/djangoapps/user_api/partition_schemes.py +++ b/openedx/core/djangoapps/user_api/partition_schemes.py @@ -3,9 +3,9 @@ Provides partition support to the user service. """ import logging import random - import course_tag.api as course_tag_api -from openedx.core.lib.partitions.partitions import NoSuchUserPartitionGroupError, UserPartitionError + +from xmodule.partitions.partitions import UserPartitionError, NoSuchUserPartitionGroupError log = logging.getLogger(__name__) diff --git a/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py b/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py index 396fc7e6057..d12bc3f8c67 100644 --- a/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py +++ b/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py @@ -2,13 +2,13 @@ Test the user api's partition extensions. """ from collections import defaultdict +from mock import patch from unittest import TestCase -from mock import patch from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme, UserPartitionError -from openedx.core.lib.partitions.partitions import Group, UserPartition -from openedx.core.lib.partitions.tests.test_partitions import PartitionTestCase from student.tests.factories import UserFactory +from xmodule.partitions.partitions import Group, UserPartition +from xmodule.partitions.tests.test_partitions import PartitionTestCase class MemoryCourseTagAPI(object): diff --git a/openedx/core/djangoapps/util/testing.py b/openedx/core/djangoapps/util/testing.py index 4cde8eccae3..380c8cdfcfd 100644 --- a/openedx/core/djangoapps/util/testing.py +++ b/openedx/core/djangoapps/util/testing.py @@ -1,15 +1,15 @@ """ Mixins for setting up particular course structures (such as split tests or cohorted content) """ from datetime import datetime +from pytz import UTC from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory -from openedx.core.lib.partitions.partitions import Group, UserPartition -from pytz import UTC -from student.tests.factories import CourseEnrollmentFactory, UserFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.partitions.partitions import UserPartition, Group +from student.tests.factories import CourseEnrollmentFactory, UserFactory class ContentGroupTestCase(ModuleStoreTestCase): diff --git a/openedx/core/djangoapps/verified_track_content/partition_scheme.py b/openedx/core/djangoapps/verified_track_content/partition_scheme.py index b11b22d12ca..2260265b12b 100644 --- a/openedx/core/djangoapps/verified_track_content/partition_scheme.py +++ b/openedx/core/djangoapps/verified_track_content/partition_scheme.py @@ -1,17 +1,19 @@ """ UserPartitionScheme for enrollment tracks. """ -from course_modes.models import CourseMode +from django.conf import settings + from courseware.masquerade import ( get_course_masquerade, get_masquerading_user_group, is_masquerading_as_specific_student ) -from django.conf import settings +from course_modes.models import CourseMode +from student.models import CourseEnrollment from opaque_keys.edx.keys import CourseKey from openedx.core.djangoapps.verified_track_content.models import VerifiedTrackCohortedCourse -from openedx.core.lib.partitions.partitions import Group, NoSuchUserPartitionGroupError, UserPartition -from student.models import CourseEnrollment +from xmodule.partitions.partitions import NoSuchUserPartitionGroupError, Group, UserPartition + # These IDs must be less than 100 so that they do not overlap with Groups in # CohortUserPartition or RandomUserPartitionScheme diff --git a/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py b/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py index 66e47448c9a..0e007e2697b 100644 --- a/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py +++ b/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py @@ -2,17 +2,17 @@ Tests for verified_track_content/partition_scheme.py. """ from datetime import datetime, timedelta - import pytz + +from ..partition_scheme import EnrollmentTrackPartitionScheme, EnrollmentTrackUserPartition, ENROLLMENT_GROUP_IDS +from ..models import VerifiedTrackCohortedCourse from course_modes.models import CourseMode -from openedx.core.lib.partitions.partitions import MINIMUM_STATIC_PARTITION_ID, UserPartition + from student.models import CourseEnrollment from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory - -from ..models import VerifiedTrackCohortedCourse -from ..partition_scheme import ENROLLMENT_GROUP_IDS, EnrollmentTrackPartitionScheme, EnrollmentTrackUserPartition +from xmodule.partitions.partitions import UserPartition, MINIMUM_STATIC_PARTITION_ID class EnrollmentTrackUserPartitionTest(SharedModuleStoreTestCase): diff --git a/openedx/core/lib/xblock_fields/__init__.py b/openedx/core/lib/xblock_fields/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/openedx/core/lib/xblock_fields/inherited_fields.py b/openedx/core/lib/xblock_fields/inherited_fields.py deleted file mode 100644 index 4bde53364be..00000000000 --- a/openedx/core/lib/xblock_fields/inherited_fields.py +++ /dev/null @@ -1,239 +0,0 @@ -""" -Inherited fields for all XBlocks. -""" -from __future__ import absolute_import - -from datetime import datetime - -from django.conf import settings -from openedx.core.lib.partitions.partitions import UserPartition -from pytz import utc -from xblock.fields import Boolean, Dict, Float, Integer, List, Scope, String, XBlockMixin - -from .fields import Date, Timedelta - -DEFAULT_START_DATE = datetime(2030, 1, 1, tzinfo=utc) - -# Make '_' a no-op so we can scrape strings -# Using lambda instead of `django.utils.translation.ugettext_noop` because Django cannot be imported in this file -_ = lambda text: text - - -class UserPartitionList(List): - """Special List class for listing UserPartitions""" - def from_json(self, values): - return [UserPartition.from_json(v) for v in values] - - def to_json(self, values): - return [user_partition.to_json() - for user_partition in values] - - -class InheritanceMixin(XBlockMixin): - """Field definitions for inheritable fields.""" - - graded = Boolean( - help="Whether this module contributes to the final course grade", - scope=Scope.settings, - default=False, - ) - start = Date( - help="Start time when this module is visible", - default=DEFAULT_START_DATE, - scope=Scope.settings - ) - due = Date( - display_name=_("Due Date"), - help=_("Enter the default date by which problems are due."), - scope=Scope.settings, - ) - visible_to_staff_only = Boolean( - help=_("If true, can be seen only by course staff, regardless of start date."), - default=False, - scope=Scope.settings, - ) - course_edit_method = String( - display_name=_("Course Editor"), - help=_("Enter the method by which this course is edited (\"XML\" or \"Studio\")."), - default="Studio", - scope=Scope.settings, - deprecated=True # Deprecated because user would not change away from Studio within Studio. - ) - giturl = String( - display_name=_("GIT URL"), - help=_("Enter the URL for the course data GIT repository."), - scope=Scope.settings - ) - xqa_key = String( - display_name=_("XQA Key"), - help=_("This setting is not currently supported."), scope=Scope.settings, - deprecated=True - ) - annotation_storage_url = String( - help=_("Enter the location of the annotation storage server. The textannotation, videoannotation, and imageannotation advanced modules require this setting."), - scope=Scope.settings, - default="http://your_annotation_storage.com", - display_name=_("URL for Annotation Storage") - ) - annotation_token_secret = String( - help=_("Enter the secret string for annotation storage. The textannotation, videoannotation, and imageannotation advanced modules require this string."), - scope=Scope.settings, - default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - display_name=_("Secret Token String for Annotation") - ) - graceperiod = Timedelta( - help="Amount of time after the due date that submissions will be accepted", - scope=Scope.settings, - ) - group_access = Dict( - help=_("Enter the ids for the content groups this problem belongs to."), - scope=Scope.settings, - ) - - showanswer = String( - display_name=_("Show Answer"), - help=_( - # Translators: DO NOT translate the words in quotes here, they are - # specific words for the acceptable values. - 'Specify when the Show Answer button appears for each problem. ' - 'Valid values are "always", "answered", "attempted", "closed", ' - '"finished", "past_due", "correct_or_past_due", and "never".' - ), - scope=Scope.settings, - default="finished", - ) - - show_correctness = String( - display_name=_("Show Results"), - help=_( - # Translators: DO NOT translate the words in quotes here, they are - # specific words for the acceptable values. - 'Specify when to show answer correctness and score to learners. ' - 'Valid values are "always", "never", and "past_due".' - ), - scope=Scope.settings, - default="always", - ) - - rerandomize = String( - display_name=_("Randomization"), - help=_( - # Translators: DO NOT translate the words in quotes here, they are - # specific words for the acceptable values. - 'Specify the default for how often variable values in a problem are randomized. ' - 'This setting should be set to "never" unless you plan to provide a Python ' - 'script to identify and randomize values in most of the problems in your course. ' - 'Valid values are "always", "onreset", "never", and "per_student".' - ), - scope=Scope.settings, - default="never", - ) - days_early_for_beta = Float( - display_name=_("Days Early for Beta Users"), - help=_("Enter the number of days before the start date that beta users can access the course."), - scope=Scope.settings, - default=None, - ) - static_asset_path = String( - display_name=_("Static Asset Path"), - help=_("Enter the path to use for files on the Files & Uploads page. This value overrides the Studio default, c4x://."), - scope=Scope.settings, - default='', - ) - use_latex_compiler = Boolean( - display_name=_("Enable LaTeX Compiler"), - help=_("Enter true or false. If true, you can use the LaTeX templates for HTML components and advanced Problem components."), - default=False, - scope=Scope.settings - ) - max_attempts = Integer( - display_name=_("Maximum Attempts"), - help=_("Enter the maximum number of times a student can try to answer problems. By default, Maximum Attempts is set to null, meaning that students have an unlimited number of attempts for problems. You can override this course-wide setting for individual problems. However, if the course-wide setting is a specific number, you cannot set the Maximum Attempts for individual problems to unlimited."), - values={"min": 0}, scope=Scope.settings - ) - matlab_api_key = String( - display_name=_("Matlab API key"), - help=_("Enter the API key provided by MathWorks for accessing the MATLAB Hosted Service. " - "This key is granted for exclusive use in this course for the specified duration. " - "Do not share the API key with other courses. Notify MathWorks immediately " - "if you believe the key is exposed or compromised. To obtain a key for your course, " - "or to report an issue, please contact moocsupport@mathworks.com"), - scope=Scope.settings - ) - # This is should be scoped to content, but since it's defined in the policy - # file, it is currently scoped to settings. - user_partitions = UserPartitionList( - display_name=_("Group Configurations"), - help=_("Enter the configurations that govern how students are grouped together."), - default=[], - scope=Scope.settings - ) - video_speed_optimizations = Boolean( - display_name=_("Enable video caching system"), - help=_("Enter true or false. If true, video caching will be used for HTML5 videos."), - default=True, - scope=Scope.settings - ) - video_bumper = Dict( - display_name=_("Video Pre-Roll"), - help=_( - "Identify a video, 5-10 seconds in length, to play before course videos. Enter the video ID from " - "the Video Uploads page and one or more transcript files in the following format: {format}. " - "For example, an entry for a video with two transcripts looks like this: {example}" - ).format( - format='{"video_id": "ID", "transcripts": {"language": "/static/filename.srt"}}', - example=( - '{' - '"video_id": "77cef264-d6f5-4cf2-ad9d-0178ab8c77be", ' - '"transcripts": {"en": "/static/DemoX-D01_1.srt", "uk": "/static/DemoX-D01_1_uk.srt"}' - '}' - ), - ), - scope=Scope.settings - ) - - # TODO: Remove this Django dependency! It really doesn't belong here. - reset_key = "DEFAULT_SHOW_RESET_BUTTON" - default_reset_button = getattr(settings, reset_key) if hasattr(settings, reset_key) else False - show_reset_button = Boolean( - display_name=_("Show Reset Button for Problems"), - help=_( - "Enter true or false. If true, problems in the course default to always displaying a 'Reset' button. " - "You can override this in each problem's settings. All existing problems are affected when " - "this course-wide setting is changed." - ), - scope=Scope.settings, - default=default_reset_button - ) - edxnotes = Boolean( - display_name=_("Enable Student Notes"), - help=_("Enter true or false. If true, students can use the Student Notes feature."), - default=False, - scope=Scope.settings - ) - edxnotes_visibility = Boolean( - display_name="Student Notes Visibility", - help=_("Indicates whether Student Notes are visible in the course. " - "Students can also show or hide their notes in the courseware."), - default=True, - scope=Scope.user_info - ) - - in_entrance_exam = Boolean( - display_name=_("Tag this module as part of an Entrance Exam section"), - help=_("Enter true or false. If true, answer submissions for problem modules will be " - "considered in the Entrance Exam scoring/gating algorithm."), - scope=Scope.settings, - default=False - ) - - self_paced = Boolean( - display_name=_('Self Paced'), - help=_( - 'Set this to "true" to mark this course as self-paced. Self-paced courses do not have ' - 'due dates for assignments, and students can progress through the course at any rate before ' - 'the course ends.' - ), - default=False, - scope=Scope.settings - ) diff --git a/openedx/features/course_experience/tests/views/test_course_outline.py b/openedx/features/course_experience/tests/views/test_course_outline.py index bd9a2c95280..8e518bb621b 100644 --- a/openedx/features/course_experience/tests/views/test_course_outline.py +++ b/openedx/features/course_experience/tests/views/test_course_outline.py @@ -16,7 +16,7 @@ from student.tests.factories import UserFactory from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -from openedx.core.lib.xblock_fields.inherited_fields import DEFAULT_START_DATE +from xmodule.course_module import DEFAULT_START_DATE from .test_course_home import course_home_url -- GitLab