diff --git a/cms/envs/common.py b/cms/envs/common.py index 8748ee15595e..e79c0771ce9e 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -658,7 +658,7 @@ # A newer and safer request cache. 'edx_django_utils.cache.middleware.RequestCacheMiddleware', - 'edx_django_utils.monitoring.middleware.MonitoringMemoryMiddleware', + 'edx_django_utils.monitoring.MonitoringMemoryMiddleware', # Cookie monitoring 'openedx.core.lib.request_utils.CookieMonitoringMiddleware', diff --git a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py index a8104e867d15..49723673bd97 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/django_utils.py @@ -12,6 +12,7 @@ from django.conf import settings from django.contrib.auth.models import AnonymousUser, User +from django.db import connections from django.test import TestCase from django.test.utils import override_settings from mock import patch @@ -397,7 +398,7 @@ def setUp(self): for Django ORM models that will get cleaned up properly. """ # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} @classmethod @contextmanager @@ -486,7 +487,7 @@ class FooTest(ModuleStoreTestCase): CREATE_USER = True # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} @classmethod def setUpClass(cls): diff --git a/common/lib/xmodule/xmodule/video_module/transcripts_utils.py b/common/lib/xmodule/xmodule/video_module/transcripts_utils.py index 150379a2f870..781b2ce5f1a0 100644 --- a/common/lib/xmodule/xmodule/video_module/transcripts_utils.py +++ b/common/lib/xmodule/xmodule/video_module/transcripts_utils.py @@ -5,6 +5,7 @@ import copy +import html import logging import os from functools import wraps @@ -19,7 +20,6 @@ from pysrt.srtexc import Error from six import text_type from six.moves import range, zip -from six.moves.html_parser import HTMLParser from openedx.core.djangolib import blockstore_cache from openedx.core.lib import blockstore_api @@ -660,7 +660,7 @@ def convert(content, input_format, output_format): if output_format == 'txt': text = SubRipFile.from_string(content.decode('utf-8')).text - return HTMLParser().unescape(text) + return html.unescape(text) elif output_format == 'sjson': try: @@ -679,7 +679,7 @@ def convert(content, input_format, output_format): if output_format == 'txt': text = json.loads(content)['text'] text_without_none = [line if line else '' for line in text] - return HTMLParser().unescape("\n".join(text_without_none)) + return html.unescape("\n".join(text_without_none)) elif output_format == 'srt': return generate_srt_from_sjson(json.loads(content), speed=1.0) diff --git a/lms/djangoapps/ccx/tests/test_field_override_performance.py b/lms/djangoapps/ccx/tests/test_field_override_performance.py index ffd0238d5690..8aa947da68e4 100644 --- a/lms/djangoapps/ccx/tests/test_field_override_performance.py +++ b/lms/djangoapps/ccx/tests/test_field_override_performance.py @@ -16,6 +16,7 @@ from django.conf import settings from django.contrib.messages.storage.fallback import FallbackStorage from django.core.cache import caches +from django.db import connections from django.test.client import RequestFactory from django.test.utils import override_settings from edx_django_utils.cache import RequestCache @@ -57,7 +58,7 @@ class FieldOverridePerformanceTestCase(FieldOverrideTestMixin, ProceduralCourseT """ __test__ = False # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} # TEST_DATA must be overridden by subclasses TEST_DATA = None diff --git a/lms/djangoapps/courseware/tests/test_model_data.py b/lms/djangoapps/courseware/tests/test_model_data.py index 19f01d181dd9..b5f9c7387a01 100644 --- a/lms/djangoapps/courseware/tests/test_model_data.py +++ b/lms/djangoapps/courseware/tests/test_model_data.py @@ -6,7 +6,7 @@ import json from functools import partial -from django.db import DatabaseError +from django.db import connections, DatabaseError from django.test import TestCase from mock import Mock, patch from xblock.core import XBlock @@ -105,7 +105,7 @@ class TestStudentModuleStorage(OtherUserFailureTestMixin, TestCase): other_key_factory = partial(DjangoKeyValueStore.Key, Scope.user_state, 2, location('usage_id')) # user_id=2, not 1 existing_field_name = "a_field" # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} def setUp(self): super(TestStudentModuleStorage, self).setUp() @@ -230,7 +230,7 @@ def test_set_many_failure(self): class TestMissingStudentModule(TestCase): # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} def setUp(self): super(TestMissingStudentModule, self).setUp() diff --git a/lms/djangoapps/courseware/tests/test_submitting_problems.py b/lms/djangoapps/courseware/tests/test_submitting_problems.py index 86671db0d446..9e4b85758457 100644 --- a/lms/djangoapps/courseware/tests/test_submitting_problems.py +++ b/lms/djangoapps/courseware/tests/test_submitting_problems.py @@ -14,6 +14,7 @@ import six from django.conf import settings from django.contrib.auth.models import User +from django.db import connections from django.test import TestCase from django.test.client import RequestFactory from django.urls import reverse @@ -139,7 +140,7 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase, Probl """ # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} # arbitrary constant COURSE_SLUG = "100" COURSE_NAME = "test_course" @@ -342,7 +343,7 @@ class TestCourseGrader(TestSubmittingProblems): Suite of tests for the course grader. """ # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} def basic_setup(self, late=False, reset=False, showanswer=False): """ @@ -755,7 +756,7 @@ def test_min_grade_credit_requirements_status(self, mode): class ProblemWithUploadedFilesTest(TestSubmittingProblems): """Tests of problems with uploaded files.""" # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} def setUp(self): super(ProblemWithUploadedFilesTest, self).setUp() @@ -811,7 +812,7 @@ class TestPythonGradedResponse(TestSubmittingProblems): Check that we can submit a schematic and custom response, and it answers properly. """ # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} SCHEMATIC_SCRIPT = dedent(""" # for a schematic response, submission[i] is the json representation diff --git a/lms/djangoapps/courseware/tests/test_user_state_client.py b/lms/djangoapps/courseware/tests/test_user_state_client.py index d73b510c4d42..89c21c0f6956 100644 --- a/lms/djangoapps/courseware/tests/test_user_state_client.py +++ b/lms/djangoapps/courseware/tests/test_user_state_client.py @@ -6,6 +6,8 @@ from collections import defaultdict +from django.db import connections + from edx_user_state_client.tests import UserStateClientTestBase from lms.djangoapps.courseware.tests.factories import UserFactory @@ -20,7 +22,7 @@ class TestDjangoUserStateClient(UserStateClientTestBase, ModuleStoreTestCase): """ __test__ = True # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} def _user(self, user_idx): return self.users[user_idx].username diff --git a/lms/djangoapps/coursewarehistoryextended/tests.py b/lms/djangoapps/coursewarehistoryextended/tests.py index 71613824a51f..1dedabae9db2 100644 --- a/lms/djangoapps/coursewarehistoryextended/tests.py +++ b/lms/djangoapps/coursewarehistoryextended/tests.py @@ -10,6 +10,7 @@ from unittest import skipUnless from django.conf import settings +from django.db import connections from django.test import TestCase from mock import patch @@ -21,7 +22,7 @@ class TestStudentModuleHistoryBackends(TestCase): """ Tests of data in CSMH and CSMHE """ # Tell Django to clean out all databases, not just default - multi_db = True + databases = {alias for alias in connections} def setUp(self): super(TestStudentModuleHistoryBackends, self).setUp() diff --git a/lms/djangoapps/verify_student/management/commands/tests/test_populate_expiration_date.py b/lms/djangoapps/verify_student/management/commands/tests/test_populate_expiration_date.py index 39ce50b4d850..e1f18a4e64ad 100644 --- a/lms/djangoapps/verify_student/management/commands/tests/test_populate_expiration_date.py +++ b/lms/djangoapps/verify_student/management/commands/tests/test_populate_expiration_date.py @@ -15,7 +15,7 @@ from common.test.utils import MockS3BotoMixin from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from lms.djangoapps.verify_student.tests.test_models import FAKE_SETTINGS, mock_software_secure_post -from student.tests.factories import UserFactory +from common.djangoapps.student.tests.factories import UserFactory LOGGER_NAME = 'lms.djangoapps.verify_student.management.commands.populate_expiration_date' diff --git a/lms/envs/common.py b/lms/envs/common.py index 5572bd1ddffa..00c1694c0757 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1686,10 +1686,10 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring # A newer and safer request cache. 'edx_django_utils.cache.middleware.RequestCacheMiddleware', - 'edx_django_utils.monitoring.middleware.CachedCustomMonitoringMiddleware', + 'edx_django_utils.monitoring.CachedCustomMonitoringMiddleware', # Generate code ownership attributes. Keep this immediately after RequestCacheMiddleware. - 'edx_django_utils.monitoring.code_owner.middleware.CodeOwnerMonitoringMiddleware', + 'edx_django_utils.monitoring.CodeOwnerMonitoringMiddleware', # Cookie monitoring 'openedx.core.lib.request_utils.CookieMonitoringMiddleware', diff --git a/openedx/core/djangoapps/content_libraries/tests/test_runtime.py b/openedx/core/djangoapps/content_libraries/tests/test_runtime.py index 498db6901974..534c28738059 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_runtime.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_runtime.py @@ -5,6 +5,7 @@ import json from completion.test_utils import CompletionWaffleTestMixin +from django.db import connections from django.test import TestCase, override_settings from organizations.models import Organization from rest_framework.test import APIClient @@ -183,7 +184,7 @@ class ContentLibraryXBlockUserStateTest(ContentLibraryContentTestMixin, TestCase if the library allows direct learning. """ - multi_db = True + databases = {alias for alias in connections} @XBlock.register_temp_plugin(UserStateTestBlock, UserStateTestBlock.BLOCK_TYPE) def test_default_values(self): diff --git a/openedx/features/course_duration_limits/tests/test_models.py b/openedx/features/course_duration_limits/tests/test_models.py index 98c042b6369d..529412927835 100644 --- a/openedx/features/course_duration_limits/tests/test_models.py +++ b/openedx/features/course_duration_limits/tests/test_models.py @@ -182,13 +182,13 @@ def test_config_overrides(self, global_setting, site_setting, org_setting, cours def test_all_current_course_configs(self): # Set up test objects for global_setting in (True, False, None): - CourseDurationLimitConfig.objects.create(enabled=global_setting, enabled_as_of=datetime(2018, 1, 1)) + CourseDurationLimitConfig.objects.create(enabled=global_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) for site_setting in (True, False, None): test_site_cfg = SiteConfigurationFactory.create( site_values={'course_org_filter': []} ) CourseDurationLimitConfig.objects.create( - site=test_site_cfg.site, enabled=site_setting, enabled_as_of=datetime(2018, 1, 1) + site=test_site_cfg.site, enabled=site_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC) ) for org_setting in (True, False, None): @@ -197,7 +197,7 @@ def test_all_current_course_configs(self): test_site_cfg.save() CourseDurationLimitConfig.objects.create( - org=test_org, enabled=org_setting, enabled_as_of=datetime(2018, 1, 1) + org=test_org, enabled=org_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC) ) for course_setting in (True, False, None): @@ -206,7 +206,7 @@ def test_all_current_course_configs(self): id=CourseLocator(test_org, 'test_course', 'run-{}'.format(course_setting)) ) CourseDurationLimitConfig.objects.create( - course=test_course, enabled=course_setting, enabled_as_of=datetime(2018, 1, 1) + course=test_course, enabled=course_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC) ) with self.assertNumQueries(4): @@ -241,7 +241,7 @@ def test_all_current_course_configs(self): ) def test_caching_global(self): - global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) + global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) global_config.save() RequestCache.clear_all_namespaces() @@ -267,7 +267,7 @@ def test_caching_global(self): def test_caching_site(self): site_cfg = SiteConfigurationFactory() - site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1)) + site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) site_config.save() RequestCache.clear_all_namespaces() @@ -291,7 +291,7 @@ def test_caching_site(self): with self.assertNumQueries(1): self.assertFalse(CourseDurationLimitConfig.current(site=site_cfg.site).enabled) - global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) + global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) global_config.save() RequestCache.clear_all_namespaces() @@ -305,7 +305,7 @@ def test_caching_org(self): site_cfg = SiteConfigurationFactory.create( site_values={'course_org_filter': course.org} ) - org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1)) + org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) org_config.save() RequestCache.clear_all_namespaces() @@ -329,7 +329,7 @@ def test_caching_org(self): with self.assertNumQueries(2): self.assertFalse(CourseDurationLimitConfig.current(org=course.org).enabled) - global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) + global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) global_config.save() RequestCache.clear_all_namespaces() @@ -338,7 +338,7 @@ def test_caching_org(self): with self.assertNumQueries(0): self.assertFalse(CourseDurationLimitConfig.current(org=course.org).enabled) - site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1)) + site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) site_config.save() RequestCache.clear_all_namespaces() @@ -352,7 +352,7 @@ def test_caching_course(self): site_cfg = SiteConfigurationFactory.create( site_values={'course_org_filter': course.org} ) - course_config = CourseDurationLimitConfig(course=course, enabled=True, enabled_as_of=datetime(2018, 1, 1)) + course_config = CourseDurationLimitConfig(course=course, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) course_config.save() RequestCache.clear_all_namespaces() @@ -376,7 +376,7 @@ def test_caching_course(self): with self.assertNumQueries(2): self.assertFalse(CourseDurationLimitConfig.current(course_key=course.id).enabled) - global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1)) + global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) global_config.save() RequestCache.clear_all_namespaces() @@ -385,7 +385,7 @@ def test_caching_course(self): with self.assertNumQueries(0): self.assertFalse(CourseDurationLimitConfig.current(course_key=course.id).enabled) - site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1)) + site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) site_config.save() RequestCache.clear_all_namespaces() @@ -394,7 +394,7 @@ def test_caching_course(self): with self.assertNumQueries(0): self.assertFalse(CourseDurationLimitConfig.current(course_key=course.id).enabled) - org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1)) + org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) org_config.save() RequestCache.clear_all_namespaces() diff --git a/openedx/features/course_experience/tests/views/test_course_home.py b/openedx/features/course_experience/tests/views/test_course_home.py index 5c727ac54ae4..82ce8d4977eb 100644 --- a/openedx/features/course_experience/tests/views/test_course_home.py +++ b/openedx/features/course_experience/tests/views/test_course_home.py @@ -213,7 +213,7 @@ def test_queries(self): """ Verify that the view's query count doesn't regress. """ - CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1)) + CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC)) # Pre-fetch the view to populate any caches course_home_url(self.course) @@ -578,7 +578,7 @@ def test_expired_course(self): Ensure that a user accessing an expired course sees a redirect to the student dashboard, not a 404. """ - CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2010, 1, 1)) + CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2010, 1, 1, tzinfo=UTC)) course = CourseFactory.create(start=THREE_YEARS_AGO) url = course_home_url(course) @@ -614,7 +614,7 @@ def test_expiration_banner_with_expired_upgrade_deadline(self): Ensure that a user accessing a course with an expired upgrade deadline will still see the course expiration banner without the upgrade related text. """ - past = datetime(2010, 1, 1) + past = datetime(2010, 1, 1, tzinfo=UTC) CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=past) course = CourseFactory.create(start=now() - timedelta(days=10)) CourseModeFactory.create(course_id=course.id, mode_slug=CourseMode.AUDIT) @@ -634,7 +634,7 @@ def test_audit_only_not_expired(self): Verify that enrolled users are NOT shown the course expiration banner and can access the course home page if course audit only """ - CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2010, 1, 1)) + CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2010, 1, 1, tzinfo=UTC)) audit_only_course = CourseFactory.create() self.create_user_for_course(audit_only_course, CourseUserType.ENROLLED) response = self.client.get(course_home_url(audit_only_course)) @@ -648,7 +648,7 @@ def test_expired_course_in_holdback(self): Ensure that a user accessing an expired course that is in the holdback does not get redirected to the student dashboard, not a 404. """ - CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2010, 1, 1)) + CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2010, 1, 1, tzinfo=UTC)) course = CourseFactory.create(start=THREE_YEARS_AGO) url = course_home_url(course) @@ -775,7 +775,7 @@ def test_course_messaging(self): config = CourseDurationLimitConfig( course=CourseOverview.get_from_id(self.course.id), enabled=True, - enabled_as_of=datetime(2018, 1, 1) + enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC) ) config.save() @@ -808,7 +808,7 @@ def test_course_messaging_for_staff(self): config = CourseDurationLimitConfig( course=CourseOverview.get_from_id(self.course.id), enabled=True, - enabled_as_of=datetime(2018, 1, 1) + enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC) ) config.save() url = course_home_url(self.course) @@ -833,7 +833,7 @@ def test_course_expiration_banner_with_unicode(self, mock_strftime_localized, mo config = CourseDurationLimitConfig( course=CourseOverview.get_from_id(self.course.id), enabled=True, - enabled_as_of=datetime(2018, 1, 1) + enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC) ) config.save() url = course_home_url(self.course) 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 ab5e6b13ee80..d77b6258d058 100644 --- a/openedx/features/course_experience/tests/views/test_course_outline.py +++ b/openedx/features/course_experience/tests/views/test_course_outline.py @@ -20,6 +20,7 @@ from mock import Mock, patch from opaque_keys.edx.keys import CourseKey, UsageKey from pyquery import PyQuery as pq +from pytz import UTC from six import text_type from waffle.models import Switch from waffle.testutils import override_switch @@ -214,7 +215,7 @@ def test_reset_course_deadlines_banner_shows_for_self_paced_course( ): ContentTypeGatingConfig.objects.create( enabled=True, - enabled_as_of=datetime.datetime(2017, 1, 1), + enabled_as_of=datetime.datetime(2017, 1, 1, tzinfo=UTC), ) course = self.courses[0] for mode in course_modes: diff --git a/openedx/features/course_experience/tests/views/test_course_updates.py b/openedx/features/course_experience/tests/views/test_course_updates.py index b9113290c1a7..cf2556e8de18 100644 --- a/openedx/features/course_experience/tests/views/test_course_updates.py +++ b/openedx/features/course_experience/tests/views/test_course_updates.py @@ -7,6 +7,7 @@ import six from django.urls import reverse +from pytz import UTC from lms.djangoapps.courseware.courses import get_course_info_usage_key from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES @@ -126,7 +127,7 @@ def test_view(self): self.assertContains(response, 'Second Message') def test_queries(self): - ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1)) + ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC)) create_course_update(self.course, self.user, 'First Message') # Pre-fetch the view to populate any caches