chore: Replace pytz with zoneinfo for UTC handling - Part 1 (#37523)
First PR to replace pytz with zoneinfo for UTC handling across codebase. This PR migrates all UTC timezone handling from pytz to Python’s standard library zoneinfo. The pytz library is now deprecated, and its documentation recommends using zoneinfo for all new code. This update modernizes our codebase, removes legacy pytz usage, and ensures compatibility with current best practices for timezone management in Python 3.9+. No functional changes to timezone logic - just a direct replacement for UTC handling. https://github.com/openedx/edx-platform/issues/33980
This commit is contained in:
@@ -6,9 +6,9 @@ Tests for Bookmarks models.
|
||||
import datetime
|
||||
from contextlib import contextmanager
|
||||
from unittest import mock
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from freezegun import freeze_time
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
|
||||
@@ -352,7 +352,7 @@ class BookmarkModelTests(BookmarksTestsBase):
|
||||
bookmark, __ = Bookmark.create(bookmark_data)
|
||||
assert bookmark.xblock_cache is not None
|
||||
|
||||
modification_datetime = datetime.datetime.now(pytz.utc) + datetime.timedelta(seconds=seconds_delta)
|
||||
modification_datetime = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(seconds=seconds_delta)
|
||||
with freeze_time(modification_datetime):
|
||||
bookmark.xblock_cache.paths = paths
|
||||
bookmark.xblock_cache.save()
|
||||
|
||||
@@ -5,6 +5,7 @@ import datetime
|
||||
import logging
|
||||
import uuid
|
||||
from typing import TYPE_CHECKING, Any, List, Union
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pycountry
|
||||
import requests
|
||||
@@ -13,7 +14,6 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||
from edx_rest_api_client.auth import SuppliedJwtAuth
|
||||
from edx_rest_api_client.client import USER_AGENT
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
|
||||
from common.djangoapps.entitlements.utils import is_course_run_entitlement_fulfillable
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
@@ -593,7 +593,7 @@ def get_fulfillable_course_runs_for_entitlement(entitlement, course_runs):
|
||||
enrollable_sessions = []
|
||||
|
||||
# Only retrieve list of published course runs that can still be enrolled and upgraded
|
||||
search_time = datetime.datetime.now(UTC)
|
||||
search_time = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
for course_run in course_runs:
|
||||
course_id = CourseKey.from_string(course_run.get("key"))
|
||||
(user_enrollment_mode, is_active) = CourseEnrollment.enrollment_mode_for_user(
|
||||
|
||||
@@ -4,9 +4,9 @@ Unit tests for the API module
|
||||
import datetime
|
||||
from unittest import mock
|
||||
from urllib import parse
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
import pytz
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
@@ -44,10 +44,10 @@ class APIsTestCase(SharedModuleStoreTestCase):
|
||||
|
||||
# Create a course outline
|
||||
start = datetime.datetime(
|
||||
2010, 5, 12, 2, 42, tzinfo=pytz.UTC
|
||||
2010, 5, 12, 2, 42, tzinfo=ZoneInfo("UTC")
|
||||
)
|
||||
due = datetime.datetime(
|
||||
2010, 7, 7, 0, 0, tzinfo=pytz.UTC
|
||||
2010, 7, 7, 0, 0, tzinfo=ZoneInfo("UTC")
|
||||
)
|
||||
|
||||
cls.chapters = [
|
||||
|
||||
@@ -7,8 +7,8 @@ import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytz
|
||||
from ccx_keys.locator import CCXLocator
|
||||
from config_models.models import ConfigurationModel
|
||||
from django.conf import settings
|
||||
@@ -705,7 +705,7 @@ class CourseOverview(TimeStampedModel):
|
||||
course_overviews = course_overviews.filter(**filter_)
|
||||
if active_only:
|
||||
course_overviews = course_overviews.filter(
|
||||
Q(end__isnull=True) | Q(end__gte=datetime.now().replace(tzinfo=pytz.UTC))
|
||||
Q(end__isnull=True) | Q(end__gte=datetime.now().replace(tzinfo=ZoneInfo("UTC")))
|
||||
)
|
||||
|
||||
return course_overviews
|
||||
@@ -737,11 +737,11 @@ class CourseOverview(TimeStampedModel):
|
||||
"""
|
||||
if active_only:
|
||||
return course_overviews.filter(
|
||||
Q(end__isnull=True) | Q(end__gte=datetime.now().replace(tzinfo=pytz.UTC))
|
||||
Q(end__isnull=True) | Q(end__gte=datetime.now().replace(tzinfo=ZoneInfo("UTC")))
|
||||
)
|
||||
if archived_only:
|
||||
return course_overviews.filter(
|
||||
end__lt=datetime.now().replace(tzinfo=pytz.UTC)
|
||||
end__lt=datetime.now().replace(tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
return course_overviews
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@ import pytest
|
||||
import datetime # lint-amnesty, pylint: disable=wrong-import-order
|
||||
import itertools # lint-amnesty, pylint: disable=wrong-import-order
|
||||
import math # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.db.utils import IntegrityError
|
||||
from django.test.utils import override_settings
|
||||
@@ -93,7 +94,7 @@ class CourseOverviewTestCase(CatalogIntegrationMixin, ModuleStoreTestCase, Cache
|
||||
"""
|
||||
if date_time is None:
|
||||
return None
|
||||
epoch = datetime.datetime.utcfromtimestamp(0).replace(tzinfo=pytz.utc)
|
||||
epoch = datetime.datetime.utcfromtimestamp(0).replace(tzinfo=ZoneInfo("UTC"))
|
||||
return math.floor((date_time - epoch).total_seconds())
|
||||
|
||||
# Load the CourseOverview from the cache twice. The first load will be a cache miss (because the cache
|
||||
|
||||
@@ -6,10 +6,10 @@ Tests for the course_overviews app's signal functionality.
|
||||
import datetime
|
||||
from unittest.mock import patch
|
||||
from collections import namedtuple
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytest
|
||||
import ddt
|
||||
from pytz import UTC
|
||||
|
||||
from xmodule.data import CertificatesDisplayBehaviors
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
@@ -33,7 +33,7 @@ class CourseOverviewSignalsTestCase(ImmediateOnCommitMixin, ModuleStoreTestCase)
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_ONLY_SPLIT_MODULESTORE_DRAFT_PREFERRED
|
||||
ENABLED_SIGNALS = ['course_deleted', 'course_published']
|
||||
TODAY = datetime.datetime.utcnow().replace(tzinfo=UTC)
|
||||
TODAY = datetime.datetime.utcnow().replace(tzinfo=ZoneInfo("UTC"))
|
||||
NEXT_WEEK = TODAY + datetime.timedelta(days=7)
|
||||
|
||||
def assert_changed_signal_sent(self, changes, mock_signal):
|
||||
|
||||
@@ -12,12 +12,13 @@ import logging
|
||||
import shlex
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import dateutil.parser
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
|
||||
from openedx.core.djangoapps.credentials.models import NotifyCredentialsConfig
|
||||
from openedx.core.djangoapps.credentials.tasks.v1.tasks import handle_notify_credentials
|
||||
@@ -32,7 +33,7 @@ log = logging.getLogger(__name__)
|
||||
def parsetime(timestr):
|
||||
dt = dateutil.parser.parse(timestr)
|
||||
if dt.tzinfo is None:
|
||||
dt = dt.replace(tzinfo=UTC)
|
||||
dt = dt.replace(tzinfo=ZoneInfo("UTC"))
|
||||
return dt
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import datetime
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.db import transaction
|
||||
from edx_proctoring.api import get_last_exam_completion_date
|
||||
|
||||
@@ -296,7 +296,7 @@ def create_credit_request(course_key, provider_id, username):
|
||||
|
||||
parameters = {
|
||||
"request_uuid": credit_request.uuid,
|
||||
"timestamp": to_timestamp(datetime.datetime.now(pytz.UTC)),
|
||||
"timestamp": to_timestamp(datetime.datetime.now(ZoneInfo("UTC"))),
|
||||
"course_org": course_key.org,
|
||||
"course_num": course_key.course,
|
||||
"course_run": course_key.run,
|
||||
|
||||
@@ -10,7 +10,7 @@ import datetime
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from config_models.models import ConfigurationModel
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
@@ -536,7 +536,7 @@ def default_deadline_for_credit_eligibility():
|
||||
"""
|
||||
The default deadline to use when creating a new CreditEligibility model.
|
||||
"""
|
||||
return datetime.datetime.now(pytz.UTC) + datetime.timedelta(
|
||||
return datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(
|
||||
days=getattr(settings, "CREDIT_ELIGIBILITY_EXPIRATION_DAYS", 365)
|
||||
)
|
||||
|
||||
@@ -617,7 +617,7 @@ class CreditEligibility(TimeStampedModel):
|
||||
return cls.objects.filter(
|
||||
username=username,
|
||||
course__enabled=True,
|
||||
deadline__gt=datetime.datetime.now(pytz.UTC)
|
||||
deadline__gt=datetime.datetime.now(ZoneInfo("UTC"))
|
||||
).select_related('course')
|
||||
|
||||
@classmethod
|
||||
@@ -636,7 +636,7 @@ class CreditEligibility(TimeStampedModel):
|
||||
course__course_key=course_key,
|
||||
course__enabled=True,
|
||||
username=username,
|
||||
deadline__gt=datetime.datetime.now(pytz.UTC),
|
||||
deadline__gt=datetime.datetime.now(ZoneInfo("UTC")),
|
||||
).exists()
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
@@ -78,7 +78,7 @@ class CreditProviderCallbackSerializer(serializers.Serializer): # pylint:disabl
|
||||
log.warning(msg)
|
||||
raise serializers.ValidationError(msg)
|
||||
|
||||
elapsed = (datetime.datetime.now(pytz.UTC) - date_time).total_seconds()
|
||||
elapsed = (datetime.datetime.now(ZoneInfo("UTC")) - date_time).total_seconds()
|
||||
if elapsed > settings.CREDIT_PROVIDER_TIMESTAMP_EXPIRATION:
|
||||
msg = f'[{value}] is too far in the past (over [{elapsed}] seconds).'
|
||||
log.warning(msg)
|
||||
|
||||
@@ -7,7 +7,7 @@ import uuid
|
||||
|
||||
import factory
|
||||
from factory.fuzzy import FuzzyText
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
|
||||
from openedx.core.djangoapps.credit.models import (
|
||||
@@ -80,7 +80,7 @@ class CreditRequestFactory(factory.django.DjangoModelFactory):
|
||||
|
||||
obj.parameters = json.dumps({
|
||||
"request_uuid": obj.uuid,
|
||||
"timestamp": to_timestamp(datetime.datetime.now(pytz.UTC)),
|
||||
"timestamp": to_timestamp(datetime.datetime.now(ZoneInfo("UTC"))),
|
||||
"course_org": course_key.org,
|
||||
"course_num": course_key.course,
|
||||
"course_run": course_key.run,
|
||||
|
||||
@@ -9,7 +9,7 @@ from unittest import mock
|
||||
import pytest
|
||||
import ddt
|
||||
import httpretty
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.core import mail
|
||||
from django.db import connection
|
||||
@@ -400,7 +400,7 @@ class CreditRequirementApiTests(CreditApiTestBase):
|
||||
CreditEligibility.objects.create(
|
||||
course=credit_course,
|
||||
username="staff",
|
||||
deadline=datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=1)
|
||||
deadline=datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=1)
|
||||
)
|
||||
|
||||
# The user should NOT be eligible for credit
|
||||
@@ -960,7 +960,7 @@ class CreditProviderIntegrationApiTests(CreditApiTestBase):
|
||||
# Validate the timestamp
|
||||
assert 'timestamp' in parameters
|
||||
parsed_date = from_timestamp(parameters['timestamp'])
|
||||
assert parsed_date < datetime.datetime.now(pytz.UTC)
|
||||
assert parsed_date < datetime.datetime.now(ZoneInfo("UTC"))
|
||||
|
||||
# Validate course information
|
||||
assert parameters['course_org'] == self.course_key.org
|
||||
|
||||
@@ -7,7 +7,7 @@ from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.test.client import RequestFactory
|
||||
from opaque_keys.edx.keys import UsageKey
|
||||
from openedx_events.data import EventsMetadata
|
||||
@@ -47,8 +47,8 @@ class TestMinGradedRequirementStatus(ModuleStoreTestCase):
|
||||
satisfied. But if student grade is less than and deadline is passed then
|
||||
user will be marked as failed.
|
||||
"""
|
||||
VALID_DUE_DATE = datetime.now(pytz.UTC) + timedelta(days=20)
|
||||
EXPIRED_DUE_DATE = datetime.now(pytz.UTC) - timedelta(days=20)
|
||||
VALID_DUE_DATE = datetime.now(ZoneInfo("UTC")) + timedelta(days=20)
|
||||
EXPIRED_DUE_DATE = datetime.now(ZoneInfo("UTC")) - timedelta(days=20)
|
||||
|
||||
DATES = {
|
||||
'valid': VALID_DUE_DATE,
|
||||
|
||||
@@ -7,7 +7,7 @@ import datetime
|
||||
import json
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.test import Client, TestCase
|
||||
from django.test.utils import override_settings
|
||||
@@ -523,7 +523,7 @@ class CreditProviderCallbackViewTests(UserMixin, TestCase):
|
||||
"""
|
||||
provider_id = kwargs.get('provider_id', self.provider.provider_id)
|
||||
secret_key = kwargs.get('secret_key', '931433d583c84ca7ba41784bad3232e6')
|
||||
timestamp = kwargs.get('timestamp', to_timestamp(datetime.datetime.now(pytz.UTC)))
|
||||
timestamp = kwargs.get('timestamp', to_timestamp(datetime.datetime.now(ZoneInfo("UTC"))))
|
||||
keys = kwargs.get('keys', {self.provider.provider_id: secret_key})
|
||||
|
||||
url = reverse('credit:provider_callback', args=[provider_id])
|
||||
@@ -577,7 +577,7 @@ class CreditProviderCallbackViewTests(UserMixin, TestCase):
|
||||
if timedelta == 'invalid':
|
||||
timestamp = timedelta
|
||||
else:
|
||||
timestamp = to_timestamp(datetime.datetime.now(pytz.UTC) + timedelta)
|
||||
timestamp = to_timestamp(datetime.datetime.now(ZoneInfo("UTC")) + timedelta)
|
||||
request_uuid = self._create_credit_request_and_get_uuid()
|
||||
response = self._credit_provider_callback(request_uuid, 'approved', timestamp=timestamp)
|
||||
assert response.status_code == 400
|
||||
@@ -585,7 +585,7 @@ class CreditProviderCallbackViewTests(UserMixin, TestCase):
|
||||
def test_post_with_string_timestamp(self):
|
||||
""" Verify the endpoint supports timestamps transmitted as strings instead of integers. """
|
||||
request_uuid = self._create_credit_request_and_get_uuid()
|
||||
timestamp = str(to_timestamp(datetime.datetime.now(pytz.UTC)))
|
||||
timestamp = str(to_timestamp(datetime.datetime.now(ZoneInfo("UTC"))))
|
||||
response = self._credit_provider_callback(request_uuid, 'approved', timestamp=timestamp)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Views for the credit Django app.
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
@@ -166,7 +166,7 @@ class CreditEligibilityView(generics.ListAPIView):
|
||||
return queryset.filter(
|
||||
username=username,
|
||||
course__course_key=course_key,
|
||||
deadline__gt=datetime.datetime.now(pytz.UTC)
|
||||
deadline__gt=datetime.datetime.now(ZoneInfo("UTC"))
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
@@ -369,7 +369,7 @@ class EnrollmentDataTest(ModuleStoreTestCase):
|
||||
def _update_verified_mode_as_expired(self, course_id):
|
||||
"""Dry method to change verified mode expiration."""
|
||||
mode = CourseMode.objects.get(course_id=course_id, mode_slug=CourseMode.VERIFIED)
|
||||
mode.expiration_datetime = datetime.datetime(year=1970, month=1, day=1, tzinfo=UTC)
|
||||
mode.expiration_datetime = datetime.datetime(year=1970, month=1, day=1, tzinfo=ZoneInfo("UTC"))
|
||||
mode.save()
|
||||
|
||||
def assert_enrollment_modes(self, expected_modes, include_expired):
|
||||
|
||||
@@ -12,7 +12,7 @@ from urllib.parse import quote
|
||||
import ddt
|
||||
import httpretty
|
||||
import pytest
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
@@ -356,8 +356,8 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase, Ente
|
||||
@ddt.unpack
|
||||
def test_force_enrollment(self, course_modes, enrollment_mode, force_enrollment):
|
||||
# Create the course modes (if any) required for this test case
|
||||
start_date = datetime.datetime(2021, 12, 1, 5, 0, 0, tzinfo=pytz.UTC)
|
||||
end_date = datetime.datetime(2022, 12, 1, 5, 0, 0, tzinfo=pytz.UTC)
|
||||
start_date = datetime.datetime(2021, 12, 1, 5, 0, 0, tzinfo=ZoneInfo("UTC"))
|
||||
end_date = datetime.datetime(2022, 12, 1, 5, 0, 0, tzinfo=ZoneInfo("UTC"))
|
||||
self.course = CourseFactory.create(
|
||||
emit_signals=True,
|
||||
start=start_date,
|
||||
@@ -658,11 +658,11 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase, Ente
|
||||
# enforced at the data layer, so we need to handle the case
|
||||
# in which no dates are specified.
|
||||
(None, None, None, None),
|
||||
(datetime.datetime(2015, 1, 2, 3, 4, 5, tzinfo=pytz.UTC), None, "2015-01-02T03:04:05Z", None),
|
||||
(None, datetime.datetime(2015, 1, 2, 3, 4, 5, tzinfo=pytz.UTC), None, "2015-01-02T03:04:05Z"),
|
||||
(datetime.datetime(2015, 1, 2, 3, 4, 5, tzinfo=ZoneInfo("UTC")), None, "2015-01-02T03:04:05Z", None),
|
||||
(None, datetime.datetime(2015, 1, 2, 3, 4, 5, tzinfo=ZoneInfo("UTC")), None, "2015-01-02T03:04:05Z"),
|
||||
(
|
||||
datetime.datetime(2014, 6, 7, 8, 9, 10, tzinfo=pytz.UTC),
|
||||
datetime.datetime(2015, 1, 2, 3, 4, 5, tzinfo=pytz.UTC),
|
||||
datetime.datetime(2014, 6, 7, 8, 9, 10, tzinfo=ZoneInfo("UTC")),
|
||||
datetime.datetime(2015, 1, 2, 3, 4, 5, tzinfo=ZoneInfo("UTC")),
|
||||
"2014-06-07T08:09:10Z",
|
||||
"2015-01-02T03:04:05Z",
|
||||
),
|
||||
@@ -1078,7 +1078,7 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase, Ente
|
||||
|
||||
# Change verified mode expiration.
|
||||
mode = CourseMode.objects.get(course_id=self.course.id, mode_slug=CourseMode.VERIFIED)
|
||||
mode.expiration_datetime = datetime.datetime(year=1970, month=1, day=1, tzinfo=pytz.utc)
|
||||
mode.expiration_datetime = datetime.datetime(year=1970, month=1, day=1, tzinfo=ZoneInfo("UTC"))
|
||||
mode.save()
|
||||
|
||||
# Deactivate enrollment.
|
||||
@@ -1198,7 +1198,7 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase, Ente
|
||||
|
||||
# Change verified mode expiration.
|
||||
mode = CourseMode.objects.get(course_id=self.course.id, mode_slug=CourseMode.VERIFIED)
|
||||
mode.expiration_datetime = datetime.datetime(year=1970, month=1, day=1, tzinfo=pytz.utc)
|
||||
mode.expiration_datetime = datetime.datetime(year=1970, month=1, day=1, tzinfo=ZoneInfo("UTC"))
|
||||
mode.save()
|
||||
self.assert_enrollment_status(
|
||||
as_server=using_api_key,
|
||||
@@ -1784,7 +1784,7 @@ class CourseEnrollmentsApiListTest(APITestCase, ModuleStoreTestCase):
|
||||
"""
|
||||
Test the course enrollments list API.
|
||||
"""
|
||||
CREATED_DATA = datetime.datetime(2018, 1, 1, 0, 0, 1, tzinfo=pytz.UTC)
|
||||
CREATED_DATA = datetime.datetime(2018, 1, 1, 0, 0, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@@ -7,7 +7,7 @@ import datetime
|
||||
from django.test import override_settings
|
||||
import pytest
|
||||
import ddt
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from django.conf import settings
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
@@ -86,13 +86,13 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
jsondetails.self_paced = True
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).self_paced ==\
|
||||
jsondetails.self_paced
|
||||
jsondetails.start_date = datetime.datetime(2010, 10, 1, 0, tzinfo=UTC)
|
||||
jsondetails.start_date = datetime.datetime(2010, 10, 1, 0, tzinfo=ZoneInfo("UTC"))
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).start_date ==\
|
||||
jsondetails.start_date
|
||||
jsondetails.end_date = datetime.datetime(2011, 10, 1, 0, tzinfo=UTC)
|
||||
jsondetails.end_date = datetime.datetime(2011, 10, 1, 0, tzinfo=ZoneInfo("UTC"))
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user).end_date ==\
|
||||
jsondetails.end_date
|
||||
jsondetails.certificate_available_date = datetime.datetime(2010, 10, 1, 0, tzinfo=UTC)
|
||||
jsondetails.certificate_available_date = datetime.datetime(2010, 10, 1, 0, tzinfo=ZoneInfo("UTC"))
|
||||
assert CourseDetails.update_from_json(self.course.id, jsondetails.__dict__, self.user)\
|
||||
.certificate_available_date == jsondetails.certificate_available_date
|
||||
jsondetails.course_image_name = "an_image.jpg"
|
||||
@@ -126,7 +126,7 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
jsondetails.instructor_info
|
||||
|
||||
def test_toggle_pacing_during_course_run(self):
|
||||
self.course.start = datetime.datetime.now(UTC)
|
||||
self.course.start = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
|
||||
details = CourseDetails.fetch(self.course.id)
|
||||
|
||||
@@ -10,7 +10,7 @@ from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from edx_django_utils.monitoring import set_code_owner_attribute
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from openedx.core.djangoapps.notifications.audience_filters import NotificationFilter
|
||||
from openedx.core.djangoapps.notifications.base_notification import (
|
||||
@@ -75,7 +75,7 @@ def delete_expired_notifications():
|
||||
This task deletes all expired notifications
|
||||
"""
|
||||
batch_size = settings.EXPIRED_NOTIFICATIONS_DELETE_BATCH_SIZE
|
||||
expiry_date = datetime.now(UTC) - timedelta(days=settings.NOTIFICATIONS_EXPIRY)
|
||||
expiry_date = datetime.now(ZoneInfo("UTC")) - timedelta(days=settings.NOTIFICATIONS_EXPIRY)
|
||||
start_time = datetime.now()
|
||||
total_deleted = 0
|
||||
delete_count = None
|
||||
|
||||
@@ -6,7 +6,7 @@ import ddt
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
from datetime import datetime
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from openedx.core.djangoapps.notifications.grouping_notifications import (
|
||||
@@ -128,7 +128,7 @@ class TestGroupUserNotifications(ModuleStoreTestCase):
|
||||
|
||||
self.assertFalse(old_notification.save.called)
|
||||
|
||||
@ddt.data(datetime(2023, 1, 1, tzinfo=utc), None)
|
||||
@ddt.data(datetime(2023, 1, 1, tzinfo=ZoneInfo("UTC")), None)
|
||||
def test_not_grouped_when_notification_is_seen(self, last_seen):
|
||||
"""
|
||||
Notification is not grouped if the notification is marked as seen
|
||||
@@ -172,11 +172,11 @@ class TestGetUserExistingNotifications(unittest.TestCase):
|
||||
# Mock the notification objects returned by the filter
|
||||
mock_notification1 = MagicMock(spec=Notification)
|
||||
mock_notification1.user_id = 1
|
||||
mock_notification1.created = datetime(2023, 9, 1, tzinfo=utc)
|
||||
mock_notification1.created = datetime(2023, 9, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
mock_notification2 = MagicMock(spec=Notification)
|
||||
mock_notification2.user_id = 1
|
||||
mock_notification2.created = datetime(2023, 9, 2, tzinfo=utc)
|
||||
mock_notification2.created = datetime(2023, 9, 2, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
mock_filter.return_value = [mock_notification1, mock_notification2]
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.core.cache import cache
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient, APITestCase
|
||||
|
||||
@@ -192,7 +192,7 @@ class NotificationListAPIViewTest(APITestCase):
|
||||
"""
|
||||
Test that the view can filter notifications by expiry date.
|
||||
"""
|
||||
today = datetime.now(UTC)
|
||||
today = datetime.now(ZoneInfo("UTC"))
|
||||
|
||||
# Create two notifications for the user, one with current date and other with expiry date.
|
||||
Notification.objects.create(
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.db.models import Count
|
||||
from django_ratelimit.core import is_ratelimited
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext as _
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from rest_framework import generics, status
|
||||
from rest_framework.decorators import api_view
|
||||
from rest_framework.generics import UpdateAPIView
|
||||
@@ -80,7 +80,7 @@ class NotificationListAPIView(generics.ListAPIView):
|
||||
"""
|
||||
Override the get_queryset method to filter the queryset by app name, request.user and created
|
||||
"""
|
||||
expiry_date = datetime.now(UTC) - timedelta(days=settings.NOTIFICATIONS_EXPIRY)
|
||||
expiry_date = datetime.now(ZoneInfo("UTC")) - timedelta(days=settings.NOTIFICATIONS_EXPIRY)
|
||||
app_name = self.request.query_params.get('app_name')
|
||||
|
||||
if self.request.query_params.get('tray_opened'):
|
||||
@@ -212,7 +212,7 @@ class NotificationReadAPIView(APIView):
|
||||
- 404: Not Found status code if the notification was not found.
|
||||
"""
|
||||
notification_id = request.data.get('notification_id', None)
|
||||
read_at = datetime.now(UTC)
|
||||
read_at = datetime.now(ZoneInfo("UTC"))
|
||||
|
||||
if notification_id:
|
||||
notification = get_object_or_404(Notification, pk=notification_id, user=request.user)
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.dispatch import receiver
|
||||
from oauth2_provider.models import AccessToken
|
||||
from oauth2_provider.oauth2_validators import OAuth2Validator
|
||||
from oauth2_provider.scopes import get_scopes_backend
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from ..models import RestrictedApplication
|
||||
# pylint: disable=W0223
|
||||
@@ -23,7 +23,7 @@ def on_access_token_presave(sender, instance, *args, **kwargs): # pylint: disab
|
||||
Mark AccessTokens as expired for 'restricted applications' if required.
|
||||
"""
|
||||
if RestrictedApplication.should_expire_access_token(instance.application):
|
||||
instance.expires = datetime(1970, 1, 1, tzinfo=utc)
|
||||
instance.expires = datetime(1970, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
class EdxOAuth2Validator(OAuth2Validator):
|
||||
@@ -152,4 +152,4 @@ def _get_utc_now():
|
||||
"""
|
||||
Return current time in UTC.
|
||||
"""
|
||||
return datetime.utcnow().replace(tzinfo=utc)
|
||||
return datetime.utcnow().replace(tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from django_mysql.models import ListCharField
|
||||
from oauth2_provider.settings import oauth2_settings
|
||||
from organizations.models import Organization
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
from openedx.core.lib.request_utils import get_request_or_stub
|
||||
@@ -53,7 +53,7 @@ class RestrictedApplication(models.Model):
|
||||
For access_tokens for RestrictedApplications, make sure that the expiry date
|
||||
is set at the beginning of the epoch which is Jan. 1, 1970
|
||||
"""
|
||||
return access_token.expires == datetime(1970, 1, 1, tzinfo=utc)
|
||||
return access_token.expires == datetime(1970, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
class ApplicationAccess(models.Model):
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import factory
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from factory.django import DjangoModelFactory
|
||||
from factory.fuzzy import FuzzyText
|
||||
from oauth2_provider.models import AccessToken, Application, RefreshToken
|
||||
@@ -39,7 +39,7 @@ class AccessTokenFactory(DjangoModelFactory):
|
||||
django_get_or_create = ('user', 'application')
|
||||
|
||||
token = FuzzyText(length=32)
|
||||
expires = datetime.now(pytz.UTC) + timedelta(days=1)
|
||||
expires = datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
|
||||
|
||||
|
||||
class RefreshTokenFactory(DjangoModelFactory):
|
||||
|
||||
@@ -4,7 +4,7 @@ Utilities for enforcing and tracking compliance with password policy rules.
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
@@ -69,7 +69,7 @@ def enforce_compliance_on_login(user, password):
|
||||
if deadline is None:
|
||||
return
|
||||
|
||||
now = datetime.now(pytz.UTC)
|
||||
now = datetime.now(ZoneInfo("UTC"))
|
||||
if now >= deadline: # lint-amnesty, pylint: disable=no-else-raise
|
||||
raise NonCompliantPasswordException(
|
||||
HTML(_(
|
||||
|
||||
@@ -6,7 +6,7 @@ from datetime import datetime, timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from dateutil.parser import parse as parse_date
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
@@ -75,7 +75,7 @@ class TestCompliance(TestCase):
|
||||
mock_check_user_compliance.return_value = False
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._get_compliance_deadline_for_user') as \
|
||||
mock_get_compliance_deadline_for_user:
|
||||
mock_get_compliance_deadline_for_user.return_value = datetime.now(pytz.UTC) - timedelta(1)
|
||||
mock_get_compliance_deadline_for_user.return_value = datetime.now(ZoneInfo("UTC")) - timedelta(1)
|
||||
pytest.raises(NonCompliantPasswordException, enforce_compliance_on_login, user, password)
|
||||
|
||||
# Test deadline is in the future
|
||||
@@ -84,7 +84,7 @@ class TestCompliance(TestCase):
|
||||
mock_check_user_compliance.return_value = False
|
||||
with patch('openedx.core.djangoapps.password_policy.compliance._get_compliance_deadline_for_user') as \
|
||||
mock_get_compliance_deadline_for_user:
|
||||
mock_get_compliance_deadline_for_user.return_value = datetime.now(pytz.UTC) + timedelta(1)
|
||||
mock_get_compliance_deadline_for_user.return_value = datetime.now(ZoneInfo("UTC")) + timedelta(1)
|
||||
assert pytest.raises(NonCompliantPasswordWarning, enforce_compliance_on_login, user, password)
|
||||
|
||||
def test_check_user_compliance(self):
|
||||
|
||||
@@ -7,7 +7,7 @@ from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
import datetime # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from django.urls import reverse
|
||||
from django.http import HttpResponse
|
||||
@@ -30,8 +30,8 @@ from ..views import LOG_MESSAGE_CREATE, LOG_MESSAGE_DELETE
|
||||
from .helpers import make_image_file
|
||||
|
||||
TEST_PASSWORD = "test"
|
||||
TEST_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 1, tzinfo=UTC)
|
||||
TEST_UPLOAD_DT2 = datetime.datetime(2003, 1, 9, 15, 43, 1, tzinfo=UTC)
|
||||
TEST_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 1, tzinfo=ZoneInfo("UTC"))
|
||||
TEST_UPLOAD_DT2 = datetime.datetime(2003, 1, 9, 15, 43, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
|
||||
|
||||
@@ -11,7 +11,7 @@ from contextlib import closing
|
||||
from django.utils.translation import gettext as _
|
||||
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
|
||||
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from rest_framework import permissions, status
|
||||
from rest_framework.parsers import FormParser, MultiPartParser
|
||||
from rest_framework.response import Response
|
||||
@@ -38,7 +38,7 @@ def _make_upload_dt():
|
||||
Generate a server-side timestamp for the upload. This is in a separate
|
||||
function so its behavior can be overridden in tests.
|
||||
"""
|
||||
return datetime.datetime.utcnow().replace(tzinfo=UTC)
|
||||
return datetime.datetime.utcnow().replace(tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
class ProfileImageView(DeveloperErrorViewMixin, APIView):
|
||||
|
||||
@@ -10,7 +10,7 @@ from unittest import mock
|
||||
import ddt
|
||||
import httpretty
|
||||
import pytest
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
import requests
|
||||
from celery.exceptions import MaxRetriesExceededError
|
||||
from django.conf import settings
|
||||
@@ -520,7 +520,7 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
self.available_date = datetime.now(pytz.UTC) + timedelta(days=1)
|
||||
self.available_date = datetime.now(ZoneInfo("UTC")) + timedelta(days=1)
|
||||
self.course = CourseOverviewFactory.create(
|
||||
self_paced=True, # Any option to allow the certificate to be viewable for the course
|
||||
certificate_available_date=self.available_date,
|
||||
@@ -1023,7 +1023,7 @@ class UpdateCertificateAvailableDateOnCourseUpdateTestCase(CredentialsApiConfigM
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.end_date = datetime.now(pytz.UTC) + timedelta(days=90)
|
||||
self.end_date = datetime.now(ZoneInfo("UTC")) + timedelta(days=90)
|
||||
self.credentials_api_config = self.create_credentials_config(enabled=False)
|
||||
|
||||
def tearDown(self):
|
||||
@@ -1135,7 +1135,7 @@ class UpdateCertificateAvailableDateOnCourseUpdateTestCase(CredentialsApiConfigM
|
||||
explicitly set as part of the course overview.
|
||||
"""
|
||||
self._update_credentials_api_config(True)
|
||||
certificate_available_date = datetime.now(pytz.UTC) + timedelta(days=120)
|
||||
certificate_available_date = datetime.now(ZoneInfo("UTC")) + timedelta(days=120)
|
||||
|
||||
course_overview = self._create_course_overview(
|
||||
False,
|
||||
@@ -1168,7 +1168,7 @@ class UpdateCertificateAvailableDateOnCourseUpdateTestCase(CredentialsApiConfigM
|
||||
invalid data is set in a course overview, we don't pass it to Credentials.
|
||||
"""
|
||||
self._update_credentials_api_config(True)
|
||||
certificate_available_date = datetime.now(pytz.UTC) + timedelta(days=120)
|
||||
certificate_available_date = datetime.now(ZoneInfo("UTC")) + timedelta(days=120)
|
||||
|
||||
course_overview = self._create_course_overview(
|
||||
True,
|
||||
|
||||
@@ -15,7 +15,7 @@ from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from edx_toggles.toggles.testutils import override_waffle_switch
|
||||
from opaque_keys.edx.keys import CourseKey # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
from testfixtures import LogCapture
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
@@ -209,7 +209,7 @@ class TestProgramProgressMeter(ModuleStoreTestCase):
|
||||
CourseEntitlementFactory.create(
|
||||
user=self.user,
|
||||
course_uuid=course_uuid,
|
||||
expired_at=datetime.datetime.now(utc),
|
||||
expired_at=datetime.datetime.now(ZoneInfo("UTC")),
|
||||
mode=CourseMode.VERIFIED,
|
||||
enrollment_course_run=enrollment
|
||||
|
||||
@@ -308,7 +308,7 @@ class TestProgramProgressMeter(ModuleStoreTestCase):
|
||||
the right type for which the upgrade deadline has not passed.
|
||||
"""
|
||||
course_run_key = generate_course_run_key()
|
||||
now = datetime.datetime.now(utc)
|
||||
now = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
upgrade_deadline = None if not offset else str(now + datetime.timedelta(days=offset))
|
||||
required_seat = SeatFactory(type=CourseMode.VERIFIED, upgrade_deadline=upgrade_deadline)
|
||||
enrolled_seat = SeatFactory(type=CourseMode.AUDIT)
|
||||
@@ -488,7 +488,7 @@ class TestProgramProgressMeter(ModuleStoreTestCase):
|
||||
|
||||
def test_simulate_progress(self, mock_get_programs): # lint-amnesty, pylint: disable=too-many-statements
|
||||
"""Simulate the entirety of a user's progress through a program."""
|
||||
today = datetime.datetime.now(utc)
|
||||
today = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
two_days_ago = today - datetime.timedelta(days=2)
|
||||
three_days_ago = today - datetime.timedelta(days=3)
|
||||
yesterday = today - datetime.timedelta(days=1)
|
||||
@@ -862,8 +862,8 @@ def _create_course(self, course_price, course_run_count=1, make_entitlement=Fals
|
||||
course_runs = []
|
||||
for x in range(course_run_count):
|
||||
course = ModuleStoreCourseFactory.create(run='Run_' + str(x))
|
||||
course.start = datetime.datetime.now(utc) - datetime.timedelta(days=1)
|
||||
course.end = datetime.datetime.now(utc) + datetime.timedelta(days=1)
|
||||
course.start = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=1)
|
||||
course.end = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=1)
|
||||
course.instructor_info = self.instructors
|
||||
course = self.update_course(course, self.user.id)
|
||||
|
||||
@@ -899,8 +899,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
super().setUp()
|
||||
|
||||
self.course = ModuleStoreCourseFactory()
|
||||
self.course.start = datetime.datetime.now(utc) - datetime.timedelta(days=1)
|
||||
self.course.end = datetime.datetime.now(utc) + datetime.timedelta(days=1)
|
||||
self.course.start = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=1)
|
||||
self.course.end = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=1)
|
||||
self.course = self.update_course(self.course, self.user.id)
|
||||
|
||||
self.course_run = CourseRunFactory(key=str(self.course.id))
|
||||
@@ -941,7 +941,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
Verify that changes to the course run end date do not affect our
|
||||
assessment of the course run being open for enrollment.
|
||||
"""
|
||||
self.course.end = datetime.datetime.now(utc) + datetime.timedelta(days=days_offset)
|
||||
self.course.end = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=days_offset)
|
||||
self.course = self.update_course(self.course, self.user.id)
|
||||
|
||||
data = ProgramDataExtender(self.program, self.user).extend()
|
||||
@@ -1022,8 +1022,8 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
"""
|
||||
Verify that course run enrollment status is reflected correctly.
|
||||
"""
|
||||
self.course.enrollment_start = datetime.datetime.now(utc) - datetime.timedelta(days=start_offset)
|
||||
self.course.enrollment_end = datetime.datetime.now(utc) - datetime.timedelta(days=end_offset)
|
||||
self.course.enrollment_start = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=start_offset)
|
||||
self.course.enrollment_end = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=end_offset)
|
||||
|
||||
self.course = self.update_course(self.course, self.user.id)
|
||||
|
||||
@@ -1040,7 +1040,7 @@ class TestProgramDataExtender(ModuleStoreTestCase):
|
||||
Verify that a closed course run with no explicit enrollment start date
|
||||
doesn't cause an error. Regression test for ECOM-4973.
|
||||
"""
|
||||
self.course.enrollment_end = datetime.datetime.now(utc) - datetime.timedelta(days=1)
|
||||
self.course.enrollment_end = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=1)
|
||||
self.course = self.update_course(self.course, self.user.id)
|
||||
|
||||
data = ProgramDataExtender(self.program, self.user).extend()
|
||||
|
||||
@@ -14,7 +14,7 @@ from django.core.cache import cache
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
from common.djangoapps.course_modes.api import get_paid_modes_for_course
|
||||
@@ -43,7 +43,7 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
# The datetime module's strftime() methods require a year >= 1900.
|
||||
DEFAULT_ENROLLMENT_START_DATE = datetime.datetime(1900, 1, 1, tzinfo=utc)
|
||||
DEFAULT_ENROLLMENT_START_DATE = datetime.datetime(1900, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -286,7 +286,7 @@ class ProgramProgressMeter:
|
||||
list of dict, each containing information about a user's progress
|
||||
towards completing a program.
|
||||
"""
|
||||
now = datetime.datetime.now(utc)
|
||||
now = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
|
||||
progress = []
|
||||
programs = programs or self.engaged_programs
|
||||
@@ -598,15 +598,17 @@ class ProgramDataExtender:
|
||||
run_mode["enrollment_open_date"] = strftime_localized(self.enrollment_start, "SHORT_DATE")
|
||||
|
||||
def _attach_course_run_is_course_ended(self, run_mode):
|
||||
end_date = self.course_overview.end or datetime.datetime.max.replace(tzinfo=utc)
|
||||
run_mode["is_course_ended"] = end_date < datetime.datetime.now(utc)
|
||||
end_date = self.course_overview.end or datetime.datetime.max.replace(tzinfo=ZoneInfo("UTC"))
|
||||
run_mode["is_course_ended"] = end_date < datetime.datetime.now(ZoneInfo("UTC"))
|
||||
|
||||
def _attach_course_run_is_enrolled(self, run_mode):
|
||||
run_mode["is_enrolled"] = CourseEnrollment.is_enrolled(self.user, self.course_run_key)
|
||||
|
||||
def _attach_course_run_is_enrollment_open(self, run_mode):
|
||||
enrollment_end = self.course_overview.enrollment_end or datetime.datetime.max.replace(tzinfo=utc)
|
||||
run_mode["is_enrollment_open"] = self.enrollment_start <= datetime.datetime.now(utc) < enrollment_end
|
||||
enrollment_end = self.course_overview.enrollment_end or datetime.datetime.max.replace(tzinfo=ZoneInfo("UTC"))
|
||||
run_mode["is_enrollment_open"] = (
|
||||
self.enrollment_start <= datetime.datetime.now(ZoneInfo("UTC")) < enrollment_end
|
||||
)
|
||||
|
||||
def _attach_course_run_advertised_start(self, run_mode):
|
||||
"""
|
||||
|
||||
@@ -5,7 +5,7 @@ Base management command for sending emails
|
||||
|
||||
import datetime
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
@@ -62,7 +62,7 @@ class SendEmailBaseCommand(PrefixedDebugLoggerMixin, BaseCommand): # lint-amnes
|
||||
|
||||
current_date = datetime.datetime(
|
||||
*[int(x) for x in options['date'].split('-')],
|
||||
tzinfo=pytz.UTC
|
||||
tzinfo=ZoneInfo("UTC")
|
||||
)
|
||||
self.log_debug('Current date = %s', current_date.isoformat())
|
||||
override_recipient_email = options.get('override_recipient_email')
|
||||
|
||||
@@ -3,7 +3,7 @@ Management command to send Schedule course updates
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from textwrap import dedent # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
@@ -23,7 +23,7 @@ class Command(SendEmailBaseCommand):
|
||||
def handle(self, *args, ** options):
|
||||
current_date = datetime.datetime(
|
||||
*[int(x) for x in options['date'].split('-')],
|
||||
tzinfo=pytz.UTC
|
||||
tzinfo=ZoneInfo("UTC")
|
||||
)
|
||||
|
||||
site = Site.objects.get(domain__iexact=options['site_domain_name'])
|
||||
|
||||
@@ -7,7 +7,7 @@ import datetime
|
||||
from textwrap import dedent
|
||||
|
||||
import factory
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
@@ -26,29 +26,29 @@ class ThreeDayNudgeSchedule(ScheduleFactory):
|
||||
"""
|
||||
A ScheduleFactory that creates a Schedule set up for a 3-day nudge email.
|
||||
"""
|
||||
start_date = factory.Faker('date_time_between', start_date='-3d', end_date='-3d', tzinfo=pytz.UTC)
|
||||
start_date = factory.Faker('date_time_between', start_date='-3d', end_date='-3d', tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
class TenDayNudgeSchedule(ScheduleFactory):
|
||||
"""
|
||||
A ScheduleFactory that creates a Schedule set up for a 10-day nudge email.
|
||||
"""
|
||||
start_date = factory.Faker('date_time_between', start_date='-10d', end_date='-10d', tzinfo=pytz.UTC)
|
||||
start_date = factory.Faker('date_time_between', start_date='-10d', end_date='-10d', tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
class UpgradeReminderSchedule(ScheduleFactory):
|
||||
"""
|
||||
A ScheduleFactory that creates a Schedule set up for a 2-days-remaining upgrade reminder.
|
||||
"""
|
||||
start_date = factory.Faker('past_datetime', tzinfo=pytz.UTC)
|
||||
upgrade_deadline = factory.Faker('date_time_between', start_date='+2d', end_date='+2d', tzinfo=pytz.UTC)
|
||||
start_date = factory.Faker('past_datetime', tzinfo=ZoneInfo("UTC"))
|
||||
upgrade_deadline = factory.Faker('date_time_between', start_date='+2d', end_date='+2d', tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
class ContentHighlightSchedule(ScheduleFactory):
|
||||
"""
|
||||
A ScheduleFactory that creates a Schedule set up for a course highlights email.
|
||||
"""
|
||||
start_date = factory.Faker('date_time_between', start_date='-7d', end_date='-7d', tzinfo=pytz.UTC)
|
||||
start_date = factory.Faker('date_time_between', start_date='-7d', end_date='-7d', tzinfo=ZoneInfo("UTC"))
|
||||
experience = factory.RelatedFactory(ScheduleExperienceFactory, 'schedule', experience_type=ScheduleExperience.EXPERIENCES.course_updates) # lint-amnesty, pylint: disable=line-too-long
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from unittest.mock import Mock, patch
|
||||
|
||||
import attr
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.db.models import Max
|
||||
@@ -119,7 +119,7 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin): # lint-amnesty, pyli
|
||||
return max_user_id + num_bins - (max_user_id % num_bins)
|
||||
|
||||
def _get_dates(self, offset=None): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
current_day = _get_datetime_beginning_of_day(datetime.datetime.now(pytz.UTC))
|
||||
current_day = _get_datetime_beginning_of_day(datetime.datetime.now(ZoneInfo("UTC")))
|
||||
offset = offset or self.expected_offsets[0]
|
||||
target_day = current_day + datetime.timedelta(days=offset)
|
||||
if self.resolver.schedule_date_field == 'upgrade_deadline':
|
||||
@@ -148,7 +148,7 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin): # lint-amnesty, pyli
|
||||
CourseModeFactory(
|
||||
course_id=course_id,
|
||||
mode_slug=CourseMode.VERIFIED,
|
||||
expiration_datetime=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=30),
|
||||
expiration_datetime=datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=30),
|
||||
)
|
||||
self._courses_with_verified_modes.add(course_id)
|
||||
return schedule
|
||||
@@ -158,7 +158,7 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin): # lint-amnesty, pyli
|
||||
Updates the schedule config model by making sure the new entry
|
||||
has a later timestamp.
|
||||
"""
|
||||
later_time = datetime.datetime.now(pytz.UTC) + datetime.timedelta(minutes=1)
|
||||
later_time = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(minutes=1)
|
||||
with freeze_time(later_time):
|
||||
ScheduleConfigFactory.create(**schedule_config_kwargs)
|
||||
|
||||
@@ -167,7 +167,7 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin): # lint-amnesty, pyli
|
||||
|
||||
def test_handle(self):
|
||||
with patch.object(self.command, 'async_send_task') as mock_send:
|
||||
test_day = datetime.datetime(2017, 8, 1, tzinfo=pytz.UTC)
|
||||
test_day = datetime.datetime(2017, 8, 1, tzinfo=ZoneInfo("UTC"))
|
||||
self.command().handle(date='2017-08-01', site_domain_name=self.site_config.site.domain)
|
||||
|
||||
for offset in self.expected_offsets:
|
||||
@@ -287,7 +287,7 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin): # lint-amnesty, pyli
|
||||
}
|
||||
self._update_schedule_config(schedule_config_kwargs)
|
||||
|
||||
current_datetime = datetime.datetime(2017, 8, 1, tzinfo=pytz.UTC)
|
||||
current_datetime = datetime.datetime(2017, 8, 1, tzinfo=ZoneInfo("UTC"))
|
||||
with patch.object(self.task, 'apply_async') as mock_apply_async:
|
||||
self.task.enqueue(self.site_config.site, current_datetime, 3)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from unittest import skipUnless
|
||||
from unittest.mock import DEFAULT, Mock, patch
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
@@ -33,7 +33,7 @@ class TestSendEmailBaseCommand(CacheIsolationTestCase): # lint-amnesty, pylint:
|
||||
self.command.handle(site_domain_name=self.site.domain, date='2017-09-29')
|
||||
send_emails.assert_called_once_with(
|
||||
self.site,
|
||||
datetime.datetime(2017, 9, 29, tzinfo=pytz.UTC),
|
||||
datetime.datetime(2017, 9, 29, tzinfo=ZoneInfo("UTC")),
|
||||
None,
|
||||
None
|
||||
)
|
||||
@@ -45,7 +45,7 @@ class TestSendEmailBaseCommand(CacheIsolationTestCase): # lint-amnesty, pylint:
|
||||
for expected_site in expected_sites:
|
||||
send_emails.assert_any_call(
|
||||
expected_site,
|
||||
datetime.datetime(2017, 9, 29, tzinfo=pytz.UTC),
|
||||
datetime.datetime(2017, 9, 29, tzinfo=ZoneInfo("UTC")),
|
||||
None,
|
||||
None
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ Factories for schedules tests
|
||||
|
||||
|
||||
import factory
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from openedx.core.djangoapps.schedules import models
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
@@ -22,8 +22,8 @@ class ScheduleFactory(factory.django.DjangoModelFactory): # lint-amnesty, pylin
|
||||
class Meta:
|
||||
model = models.Schedule
|
||||
|
||||
start_date = factory.Faker('future_datetime', tzinfo=pytz.UTC)
|
||||
upgrade_deadline = factory.Faker('future_datetime', tzinfo=pytz.UTC)
|
||||
start_date = factory.Faker('future_datetime', tzinfo=ZoneInfo("UTC"))
|
||||
upgrade_deadline = factory.Faker('future_datetime', tzinfo=ZoneInfo("UTC"))
|
||||
enrollment = factory.SubFactory(CourseEnrollmentFactory)
|
||||
experience = factory.RelatedFactory(ScheduleExperienceFactory, 'schedule')
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from unittest.mock import Mock
|
||||
|
||||
import crum
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
@@ -123,7 +123,7 @@ class TestBinnedSchedulesBaseResolver(SchedulesResolverTestMixin, TestCase):
|
||||
# experiment. Note that the experiment waffle is currently inactive, but they should still be excluded because
|
||||
# they were bucketed at enrollment time.
|
||||
bin_num = BinnedSchedulesBaseResolver.bin_num_for_user_id(user.id)
|
||||
resolver = BinnedSchedulesBaseResolver(None, self.site, datetime.datetime.now(pytz.UTC), 0, bin_num)
|
||||
resolver = BinnedSchedulesBaseResolver(None, self.site, datetime.datetime.now(ZoneInfo("UTC")), 0, bin_num)
|
||||
resolver.schedule_date_field = 'created'
|
||||
schedules = resolver.get_schedules_with_target_date_by_bin_and_orgs()
|
||||
|
||||
@@ -235,7 +235,7 @@ class TestCourseNextSectionUpdateResolver(SchedulesResolverTestMixin, ModuleStor
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.today = datetime.datetime.utcnow()
|
||||
self.today = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
self.yesterday = self.today - datetime.timedelta(days=1)
|
||||
self.course = CourseFactory.create(
|
||||
highlights_enabled_for_messaging=True, self_paced=True,
|
||||
|
||||
@@ -8,7 +8,7 @@ from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
@@ -188,7 +188,7 @@ def _create_course_run(self_paced=True, start_day_offset=-1):
|
||||
|
||||
Both audit and verified `CourseMode` objects will be created for the course run.
|
||||
"""
|
||||
now = datetime.datetime.now(utc)
|
||||
now = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
start = now + datetime.timedelta(days=start_day_offset)
|
||||
course = CourseFactory.create(start=start, self_paced=self_paced)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Tests for schedules utils
|
||||
import datetime
|
||||
|
||||
import ddt
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
@@ -26,7 +26,7 @@ class ResetSelfPacedScheduleTests(SharedModuleStoreTestCase):
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
self.config = ScheduleConfigFactory()
|
||||
|
||||
start = datetime.datetime.now(utc) + datetime.timedelta(days=course_start_offset)
|
||||
start = datetime.datetime.now(ZoneInfo("UTC")) + datetime.timedelta(days=course_start_offset)
|
||||
self.course = CourseFactory.create(start=start, self_paced=True)
|
||||
|
||||
self.enrollment = CourseEnrollmentFactory(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.db import transaction
|
||||
|
||||
from openedx.core.djangoapps.schedules.models import Schedule
|
||||
@@ -59,7 +59,7 @@ def reset_self_paced_schedule(user, course_key, use_enrollment_date=False):
|
||||
if use_enrollment_date:
|
||||
new_start_date = schedule.enrollment.created
|
||||
else:
|
||||
new_start_date = datetime.datetime.now(pytz.utc)
|
||||
new_start_date = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
|
||||
# Make sure we don't start the clock on the learner's schedule before the course even starts
|
||||
new_start_date = max(new_start_date, schedule.enrollment.course.start)
|
||||
|
||||
@@ -12,7 +12,7 @@ from django.core.validators import ValidationError, validate_email
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.translation import override as override_language
|
||||
from eventtracking import tracker
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from common.djangoapps.student import views as student_views
|
||||
from common.djangoapps.student.models import (
|
||||
@@ -375,7 +375,7 @@ def _store_old_name_if_needed(old_name, user_profile, requesting_user):
|
||||
meta['old_names'].append([
|
||||
old_name,
|
||||
f"Name change requested through account API by {requesting_user.username}",
|
||||
datetime.datetime.now(UTC).isoformat()
|
||||
datetime.datetime.now(ZoneInfo("UTC")).isoformat()
|
||||
])
|
||||
user_profile.set_meta(meta)
|
||||
user_profile.save()
|
||||
|
||||
@@ -6,7 +6,7 @@ Helpers for testing retirement functionality
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.test import TestCase
|
||||
from social_django.models import UserSocialAuth
|
||||
|
||||
@@ -67,7 +67,7 @@ def create_retirement_status(user, state=None, create_datetime=None):
|
||||
Assumes that retirement states have been setup before calling.
|
||||
"""
|
||||
if create_datetime is None:
|
||||
create_datetime = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=8)
|
||||
create_datetime = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=8)
|
||||
|
||||
retirement = UserRetirementStatus.create_retirement(user)
|
||||
if state:
|
||||
|
||||
@@ -17,7 +17,7 @@ from django.http import HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.urls import reverse
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from social_django.models import UserSocialAuth
|
||||
|
||||
from common.djangoapps.student.models import (
|
||||
@@ -381,7 +381,7 @@ class TestAccountApi(UserSettingsEventTestMixin, EmailTemplateTagMixin, CreateAc
|
||||
meta['old_names'] = []
|
||||
for num in range(3):
|
||||
meta['old_names'].append(
|
||||
[f'old_name_{num}', 'test', datetime.datetime.now(UTC).isoformat()]
|
||||
[f'old_name_{num}', 'test', datetime.datetime.now(ZoneInfo("UTC")).isoformat()]
|
||||
)
|
||||
user_profile.set_meta(meta)
|
||||
user_profile.save()
|
||||
|
||||
@@ -8,7 +8,7 @@ import hashlib
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.test import TestCase
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
@@ -16,7 +16,7 @@ from common.djangoapps.student.tests.factories import UserFactory
|
||||
from ..image_helpers import get_profile_image_urls_for_user
|
||||
|
||||
TEST_SIZES = {'full': 50, 'small': 10}
|
||||
TEST_PROFILE_IMAGE_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 1, tzinfo=UTC)
|
||||
TEST_PROFILE_IMAGE_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
|
||||
@patch.dict('django.conf.settings.PROFILE_IMAGE_SIZES_MAP', TEST_SIZES, clear=True)
|
||||
|
||||
@@ -7,7 +7,7 @@ import json
|
||||
from unittest import mock
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from consent.models import DataSharingConsent
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.contrib.sites.models import Site
|
||||
@@ -516,7 +516,7 @@ class TestPartnerReportingList(ModuleStoreTestCase):
|
||||
self.headers = build_jwt_headers(self.test_superuser)
|
||||
self.url = reverse('accounts_retirement_partner_report')
|
||||
self.maxDiff = None
|
||||
self.test_created_datetime = datetime.datetime(2018, 1, 1, tzinfo=pytz.UTC)
|
||||
self.test_created_datetime = datetime.datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
ExternalIdType.objects.get_or_create(name=ExternalIdType.CALIPER)
|
||||
|
||||
def get_user_dict(self, user, enrollments):
|
||||
@@ -769,7 +769,7 @@ class TestAccountRetirementList(RetirementTestCase):
|
||||
# retirements = [2018-04-10..., 2018-04-09..., 2018-04-08...]
|
||||
pending_state = RetirementState.objects.get(state_name='PENDING')
|
||||
for days_back in range(1, days_back_to_test, -1):
|
||||
create_datetime = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=days_back)
|
||||
create_datetime = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=days_back)
|
||||
retirements.append(create_retirement_status(
|
||||
UserFactory(),
|
||||
state=pending_state,
|
||||
@@ -927,12 +927,12 @@ class TestAccountRetirementsByStatusAndDate(RetirementTestCase):
|
||||
|
||||
# Create retirements for the last 10 days
|
||||
for days_back in range(0, 10): # lint-amnesty, pylint: disable=simplifiable-range
|
||||
create_datetime = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=days_back)
|
||||
create_datetime = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=days_back)
|
||||
ret = create_retirement_status(UserFactory(), state=complete_state, create_datetime=create_datetime)
|
||||
retirements.append(self._retirement_to_dict(ret))
|
||||
|
||||
# Go back in time adding days to the query, assert the correct retirements are present
|
||||
end_date = datetime.datetime.now(pytz.UTC)
|
||||
end_date = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
for days_back in range(1, 11):
|
||||
retirement_dicts = retirements[:days_back]
|
||||
start_date = end_date - datetime.timedelta(days=days_back - 1)
|
||||
|
||||
@@ -10,7 +10,7 @@ from unittest import mock
|
||||
from urllib.parse import quote
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
from django.test.testcases import TransactionTestCase
|
||||
@@ -44,7 +44,7 @@ from openedx.features.name_affirmation_api.utils import get_name_affirmation_ser
|
||||
|
||||
from .. import ALL_USERS_VISIBILITY, CUSTOM_VISIBILITY, PRIVATE_VISIBILITY
|
||||
|
||||
TEST_PROFILE_IMAGE_UPLOADED_AT = datetime.datetime(2002, 1, 9, 15, 43, 1, tzinfo=pytz.UTC)
|
||||
TEST_PROFILE_IMAGE_UPLOADED_AT = datetime.datetime(2002, 1, 9, 15, 43, 1, tzinfo=ZoneInfo("UTC"))
|
||||
|
||||
# this is used in one test to check the behavior of profile image url
|
||||
# generation with a relative url in the config.
|
||||
@@ -304,7 +304,7 @@ class TestCancelAccountRetirementStatusView(UserAPITestCase):
|
||||
current_state=retirement_state,
|
||||
last_state=retirement_state,
|
||||
original_email=self.user.email,
|
||||
created=datetime.datetime.now(pytz.UTC)
|
||||
created=datetime.datetime.now(ZoneInfo("UTC"))
|
||||
)
|
||||
url = reverse("cancel_account_retirement")
|
||||
response = client.post(url, data={'retirement_id': user_retirement_status.id})
|
||||
@@ -329,7 +329,7 @@ class TestCancelAccountRetirementStatusView(UserAPITestCase):
|
||||
current_state=retirement_state,
|
||||
last_state=retirement_state,
|
||||
original_email=self.user.email,
|
||||
created=datetime.datetime.now(pytz.UTC)
|
||||
created=datetime.datetime.now(ZoneInfo("UTC"))
|
||||
)
|
||||
user_retirement_status.user.set_unusable_password()
|
||||
assert UserRetirementStatus.objects.count() == 1
|
||||
@@ -585,8 +585,8 @@ class TestAccountsAPI(FilteredQueryCountMixin, CacheIsolationTestCase, UserAPITe
|
||||
|
||||
@mock.patch('openedx.core.djangoapps.user_api.accounts.views.is_email_retired')
|
||||
@ddt.data(
|
||||
(datetime.datetime.now(pytz.UTC), True),
|
||||
(datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=15), False)
|
||||
(datetime.datetime.now(ZoneInfo("UTC")), True),
|
||||
(datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=15), False)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_search_emails_retired_before_cooloff_period(self, created_date, can_cancel, mock_is_email_retired):
|
||||
|
||||
@@ -9,7 +9,7 @@ import datetime
|
||||
import logging
|
||||
from functools import wraps
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from consent.models import DataSharingConsent
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
@@ -198,11 +198,11 @@ class AccountViewSet(ViewSet):
|
||||
if is_email_retired(user_email):
|
||||
can_cancel_retirement = True
|
||||
retirement_id = None
|
||||
earliest_datetime = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=settings.COOL_OFF_DAYS)
|
||||
earliest_datetime = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=settings.COOL_OFF_DAYS)
|
||||
try:
|
||||
retirement_status = UserRetirementStatus.objects.get(
|
||||
created__gt=earliest_datetime,
|
||||
created__lt=datetime.datetime.now(pytz.UTC),
|
||||
created__lt=datetime.datetime.now(ZoneInfo("UTC")),
|
||||
original_email=user_email,
|
||||
)
|
||||
retirement_id = retirement_status.id
|
||||
@@ -891,7 +891,7 @@ class AccountRetirementStatusView(ViewSet):
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
earliest_datetime = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=cool_off_days)
|
||||
earliest_datetime = datetime.datetime.now(ZoneInfo("UTC")) - datetime.timedelta(days=cool_off_days)
|
||||
|
||||
retirements = (
|
||||
UserRetirementStatus.objects.select_related("user", "current_state", "last_state")
|
||||
@@ -921,9 +921,12 @@ class AccountRetirementStatusView(ViewSet):
|
||||
so to get one day you would set both dates to that day.
|
||||
"""
|
||||
try:
|
||||
start_date = datetime.datetime.strptime(request.GET["start_date"], "%Y-%m-%d").replace(tzinfo=pytz.UTC)
|
||||
end_date = datetime.datetime.strptime(request.GET["end_date"], "%Y-%m-%d").replace(tzinfo=pytz.UTC)
|
||||
now = datetime.datetime.now(pytz.UTC)
|
||||
start_date = (
|
||||
datetime.datetime.strptime(request.GET["start_date"], "%Y-%m-%d")
|
||||
.replace(tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
end_date = datetime.datetime.strptime(request.GET["end_date"], "%Y-%m-%d").replace(tzinfo=ZoneInfo("UTC"))
|
||||
now = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
if start_date > now or end_date > now or start_date > end_date:
|
||||
raise RetirementStateError("Dates must be today or earlier, and start must be earlier than end.")
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ from enterprise.models import (
|
||||
)
|
||||
from integrated_channels.sap_success_factors.models import SapSuccessFactorsLearnerDataTransmissionAudit
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from common.djangoapps.entitlements.models import CourseEntitlement, CourseEntitlementSupportDetail
|
||||
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
|
||||
@@ -82,7 +82,7 @@ class Command(BaseCommand):
|
||||
user.save()
|
||||
|
||||
# UserProfile
|
||||
profile_image_uploaded_date = datetime(2018, 5, 3, tzinfo=UTC)
|
||||
profile_image_uploaded_date = datetime(2018, 5, 3, tzinfo=ZoneInfo("UTC"))
|
||||
user_profile, __ = UserProfile.objects.get_or_create(
|
||||
user=user
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ from enum import Enum
|
||||
from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from oauth2_provider import models as dot_models
|
||||
from rest_framework import status
|
||||
@@ -42,7 +42,7 @@ def utcnow():
|
||||
"""
|
||||
Helper function to return the current UTC time localized to the UTC timezone.
|
||||
"""
|
||||
return datetime.now(pytz.UTC)
|
||||
return datetime.now(ZoneInfo("UTC"))
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
|
||||
@@ -26,7 +26,7 @@ from edx_django_utils.monitoring import set_custom_attribute
|
||||
from openedx_events.learning.data import UserData, UserPersonalData
|
||||
from openedx_events.learning.signals import STUDENT_REGISTRATION_COMPLETED
|
||||
from openedx_filters.learning.filters import StudentRegistrationRequested
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from django_ratelimit.decorators import ratelimit
|
||||
from requests import HTTPError
|
||||
from rest_framework.response import Response
|
||||
@@ -371,7 +371,7 @@ def _track_user_registration(user, profile, params, third_party_provider, regist
|
||||
'name': profile.name,
|
||||
# Mailchimp requires the age & yearOfBirth to be integers, we send a sane integer default if falsey.
|
||||
'age': profile.age or -1,
|
||||
'yearOfBirth': profile.year_of_birth or datetime.datetime.now(UTC).year,
|
||||
'yearOfBirth': profile.year_of_birth or datetime.datetime.now(ZoneInfo("UTC")).year,
|
||||
'education': profile.level_of_education_display,
|
||||
'address': profile.mailing_address,
|
||||
'gender': profile.gender_display,
|
||||
@@ -530,7 +530,9 @@ def _record_utm_registration_attribution(request, user):
|
||||
# We divide by 1000 here because the javascript timestamp generated is in milliseconds not seconds.
|
||||
# PYTHON: time.time() => 1475590280.823698
|
||||
# JS: new Date().getTime() => 1475590280823
|
||||
created_at_datetime = datetime.datetime.fromtimestamp(int(created_at_unixtime) / float(1000), tz=UTC)
|
||||
created_at_datetime = datetime.datetime.fromtimestamp(
|
||||
int(created_at_unixtime) / float(1000), tz=ZoneInfo("UTC")
|
||||
)
|
||||
UserAttribute.set_user_attribute(
|
||||
user,
|
||||
REGISTRATION_UTM_CREATED_AT,
|
||||
|
||||
@@ -19,7 +19,7 @@ from django.urls import reverse
|
||||
from freezegun import freeze_time
|
||||
from oauth2_provider.models import AccessToken as dot_access_token
|
||||
from oauth2_provider.models import RefreshToken as dot_refresh_token
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from testfixtures import LogCapture
|
||||
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories
|
||||
@@ -319,7 +319,7 @@ class TestPasswordChange(CreateAccountMixin, CacheIsolationTestCase):
|
||||
|
||||
# now reset the time to 1 min from now in future and change the email and
|
||||
# verify that it will allow another request from same IP
|
||||
reset_time = datetime.now(UTC) + timedelta(seconds=61)
|
||||
reset_time = datetime.now(ZoneInfo("UTC")) + timedelta(seconds=61)
|
||||
with freeze_time(reset_time):
|
||||
response = self._change_password(email=self.OLD_EMAIL)
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -16,7 +16,7 @@ from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from openedx_events.tests.utils import OpenEdxEventsTestMixin
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from social_django.models import Partial, UserSocialAuth
|
||||
from testfixtures import LogCapture
|
||||
|
||||
@@ -949,7 +949,7 @@ class RegistrationViewTestV1(
|
||||
)
|
||||
|
||||
def test_register_form_year_of_birth(self):
|
||||
this_year = datetime.now(UTC).year
|
||||
this_year = datetime.now(ZoneInfo("UTC")).year
|
||||
year_options = (
|
||||
[
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ from django.urls import reverse
|
||||
from django.utils.http import int_to_base36
|
||||
from freezegun import freeze_time
|
||||
from oauth2_provider import models as dot_models
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests import factories as dot_factories
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
@@ -267,7 +267,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
|
||||
self.request_password_reset(200)
|
||||
# now reset the time to 1 min from now in future and change the email and
|
||||
# verify that it will allow another request from same IP
|
||||
reset_time = datetime.now(UTC) + timedelta(seconds=61)
|
||||
reset_time = datetime.now(ZoneInfo("UTC")) + timedelta(seconds=61)
|
||||
with freeze_time(reset_time):
|
||||
for status in [200, 403]:
|
||||
self.request_password_reset(status)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from openedx.core.djangoapps.course_groups.models import CourseUserGroupPartitionGroup
|
||||
from openedx.core.djangoapps.course_groups.tests.helpers import CohortFactory
|
||||
@@ -32,7 +32,7 @@ class ContentGroupTestCase(ModuleStoreTestCase):
|
||||
# This test needs to use a course that has already started --
|
||||
# discussion topics only show up if the course has already started,
|
||||
# and the default start date for courses is Jan 1, 2030.
|
||||
start=datetime(2012, 2, 3, tzinfo=UTC),
|
||||
start=datetime(2012, 2, 3, tzinfo=ZoneInfo("UTC")),
|
||||
user_partitions=[
|
||||
UserPartition(
|
||||
0,
|
||||
|
||||
@@ -5,7 +5,7 @@ Tests for verified_track_content/partition_scheme.py.
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
import pytest
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
@@ -38,7 +38,7 @@ class EnrollmentTrackUserPartitionTest(SharedModuleStoreTestCase):
|
||||
# Note that the verified mode is expired-- this is intentional.
|
||||
create_mode(
|
||||
self.course, CourseMode.VERIFIED, "Verified Enrollment Track", min_price=1,
|
||||
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||
expiration_datetime=datetime.now(ZoneInfo("UTC")) + timedelta(days=-1)
|
||||
)
|
||||
# Note that the credit mode is not selectable-- this is intentional so we
|
||||
# can test that it is filtered out.
|
||||
@@ -128,7 +128,7 @@ class EnrollmentTrackPartitionSchemeTest(SharedModuleStoreTestCase):
|
||||
def test_enrolled_in_expired(self):
|
||||
create_mode(
|
||||
self.course, CourseMode.VERIFIED, "Verified Enrollment Track",
|
||||
min_price=1, expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||
min_price=1, expiration_datetime=datetime.now(ZoneInfo("UTC")) + timedelta(days=-1)
|
||||
)
|
||||
CourseEnrollment.enroll(self.student, self.course.id, mode=CourseMode.VERIFIED)
|
||||
assert 'Verified Enrollment Track' == self._get_user_group().name
|
||||
@@ -153,7 +153,7 @@ class EnrollmentTrackPartitionSchemeTest(SharedModuleStoreTestCase):
|
||||
# the upgrade deadline has passed (see EDUCATOR-1511 for why this matters).
|
||||
create_mode(
|
||||
self.course, CourseMode.VERIFIED, "Verified Enrollment Track", min_price=1,
|
||||
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||
expiration_datetime=datetime.now(ZoneInfo("UTC")) + timedelta(days=-1)
|
||||
)
|
||||
assert 'Verified Enrollment Track' == self._get_user_group().name
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from django.utils.html import escape
|
||||
from edx_django_utils.plugins import pluggable_override
|
||||
from lxml import etree, html
|
||||
from opaque_keys.edx.asides import AsideUsageKeyV1, AsideUsageKeyV2
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from web_fragments.fragment import Fragment
|
||||
from xblock.core import XBlock
|
||||
from xblock.exceptions import InvalidScopeError
|
||||
@@ -310,7 +310,7 @@ def add_staff_markup(user, disable_staff_debug_info, block, view, frag, context)
|
||||
# Useful to indicate to staff if problem has been released or not.
|
||||
# TODO (ichuang): use _has_access_block.can_load in lms.courseware.access,
|
||||
# instead of now>mstart comparison here.
|
||||
now = datetime.datetime.now(UTC)
|
||||
now = datetime.datetime.now(ZoneInfo("UTC"))
|
||||
is_released = "unknown"
|
||||
mstart = block.start
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
from icalendar import Calendar, Event, vCalAddress, vText
|
||||
@@ -59,7 +59,7 @@ def generate_ics_files_for_user_course(course, user, user_calendar_sync_config_i
|
||||
assignments = get_course_assignments(course.id, user)
|
||||
platform_name = get_value('platform_name', settings.PLATFORM_NAME)
|
||||
platform_email = get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
|
||||
now = datetime.now(pytz.utc)
|
||||
now = datetime.now(ZoneInfo("UTC"))
|
||||
site_config = SiteConfiguration.get_configuration_for_org(course.org)
|
||||
|
||||
ics_files = {}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.test import RequestFactory, TestCase
|
||||
from freezegun import freeze_time
|
||||
|
||||
@@ -21,7 +21,7 @@ class TestIcsGeneration(TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
freezer = freeze_time(datetime(2013, 10, 3, 8, 24, 55, tzinfo=pytz.utc))
|
||||
freezer = freeze_time(datetime(2013, 10, 3, 8, 24, 55, tzinfo=ZoneInfo("UTC")))
|
||||
self.addCleanup(freezer.stop)
|
||||
freezer.start()
|
||||
|
||||
@@ -103,7 +103,7 @@ END:VCALENDAR
|
||||
|
||||
def test_generate_ics_for_user_course(self):
|
||||
""" Tests that a simple sample set of course assignments is generated correctly """
|
||||
now = datetime.now(pytz.utc)
|
||||
now = datetime.now(ZoneInfo("UTC"))
|
||||
day1 = now + timedelta(1)
|
||||
day2 = now + timedelta(1)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import datetime
|
||||
import logging
|
||||
|
||||
import crum
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from web_fragments.fragment import Fragment
|
||||
@@ -88,7 +88,7 @@ class ContentTypeGatingPartition(UserPartition):
|
||||
return None
|
||||
|
||||
expiration_datetime = verified_mode.expiration_datetime
|
||||
if expiration_datetime and expiration_datetime < datetime.datetime.now(pytz.UTC):
|
||||
if expiration_datetime and expiration_datetime < datetime.datetime.now(ZoneInfo("UTC")):
|
||||
ecommerce_checkout_link = None
|
||||
else:
|
||||
ecommerce_checkout_link = self._get_checkout_link(user, verified_mode.sku, str(course_key))
|
||||
|
||||
@@ -6,7 +6,7 @@ import itertools # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from datetime import datetime, timedelta # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
import ddt
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.utils import timezone
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from unittest.mock import Mock # lint-amnesty, pylint: disable=wrong-import-order
|
||||
@@ -217,17 +217,17 @@ class TestContentTypeGatingConfig(CacheIsolationTestCase): # pylint: disable=mi
|
||||
# Point-test some of the final configurations
|
||||
assert all_configs[CourseLocator('7-True', 'test_course', 'run-None')] == {
|
||||
'enabled': (True, Provenance.org),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=ZoneInfo("UTC")), Provenance.run),
|
||||
'studio_override_enabled': (None, Provenance.default)
|
||||
}
|
||||
assert all_configs[CourseLocator('7-True', 'test_course', 'run-False')] == {
|
||||
'enabled': (False, Provenance.run),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=ZoneInfo("UTC")), Provenance.run),
|
||||
'studio_override_enabled': (None, Provenance.default)
|
||||
}
|
||||
assert all_configs[CourseLocator('7-None', 'test_course', 'run-None')] == {
|
||||
'enabled': (True, Provenance.site),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=ZoneInfo("UTC")), Provenance.run),
|
||||
'studio_override_enabled': (None, Provenance.default)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import ddt
|
||||
from crum import set_current_request
|
||||
from django.test import RequestFactory
|
||||
from django.utils import timezone
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
@@ -34,9 +34,12 @@ class TestAccess(ModuleStoreTestCase):
|
||||
def setUp(self):
|
||||
super().setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
|
||||
CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC))
|
||||
CourseDurationLimitConfig.objects.create(
|
||||
enabled=True,
|
||||
enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True)
|
||||
self.course = CourseOverviewFactory.create(start=datetime(2018, 1, 1, tzinfo=UTC), self_paced=True)
|
||||
self.course = CourseOverviewFactory.create(start=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC")), self_paced=True)
|
||||
|
||||
def assertDateInMessage(self, date, message): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
# First, check that the formatted version is in there
|
||||
@@ -148,7 +151,7 @@ class TestAccess(ModuleStoreTestCase):
|
||||
course_id=enrollment.course.id,
|
||||
mode_slug=CourseMode.AUDIT,
|
||||
)
|
||||
Schedule.objects.update(start_date=datetime(2017, 1, 1, tzinfo=UTC))
|
||||
Schedule.objects.update(start_date=datetime(2017, 1, 1, tzinfo=ZoneInfo("UTC")))
|
||||
|
||||
content_availability_date = max(enrollment.created, enrollment.course.start)
|
||||
access_duration = get_user_course_duration(enrollment.user, enrollment.course)
|
||||
|
||||
@@ -8,7 +8,7 @@ from unittest.mock import Mock
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.utils import timezone
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
@@ -178,13 +178,18 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
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, tzinfo=pytz.UTC)) # lint-amnesty, pylint: disable=line-too-long
|
||||
CourseDurationLimitConfig.objects.create(
|
||||
enabled=global_setting,
|
||||
enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("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, tzinfo=pytz.UTC)
|
||||
site=test_site_cfg.site,
|
||||
enabled=site_setting,
|
||||
enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
|
||||
for org_setting in (True, False, None):
|
||||
@@ -193,7 +198,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
test_site_cfg.save()
|
||||
|
||||
CourseDurationLimitConfig.objects.create(
|
||||
org=test_org, enabled=org_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)
|
||||
org=test_org, enabled=org_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
|
||||
for course_setting in (True, False, None):
|
||||
@@ -202,7 +207,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
id=CourseLocator(test_org, 'test_course', f'run-{course_setting}')
|
||||
)
|
||||
CourseDurationLimitConfig.objects.create(
|
||||
course=test_course, enabled=course_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC) # lint-amnesty, pylint: disable=line-too-long
|
||||
course=test_course, enabled=course_setting, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC")) # lint-amnesty, pylint: disable=line-too-long
|
||||
)
|
||||
|
||||
with self.assertNumQueries(4):
|
||||
@@ -216,22 +221,25 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
# Point-test some of the final configurations
|
||||
assert all_configs[CourseLocator('7-True', 'test_course', 'run-None')] == {
|
||||
'enabled': (True, Provenance.org),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=ZoneInfo("UTC")),
|
||||
Provenance.run)
|
||||
}
|
||||
assert all_configs[CourseLocator('7-True', 'test_course', 'run-False')] == {
|
||||
'enabled': (False, Provenance.run),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=ZoneInfo("UTC")),
|
||||
Provenance.run)
|
||||
}
|
||||
assert all_configs[CourseLocator('7-None', 'test_course', 'run-None')] == {
|
||||
'enabled': (True, Provenance.site),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC),
|
||||
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=ZoneInfo("UTC")),
|
||||
Provenance.run)
|
||||
}
|
||||
|
||||
def test_caching_global(self):
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC))
|
||||
global_config = CourseDurationLimitConfig(
|
||||
enabled=True,
|
||||
enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
global_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -257,7 +265,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
|
||||
def test_caching_site(self):
|
||||
site_cfg = SiteConfigurationFactory()
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) # lint-amnesty, pylint: disable=line-too-long
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))) # lint-amnesty, pylint: disable=line-too-long
|
||||
site_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -281,7 +289,10 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(1):
|
||||
assert not CourseDurationLimitConfig.current(site=site_cfg.site).enabled
|
||||
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC))
|
||||
global_config = CourseDurationLimitConfig(
|
||||
enabled=True,
|
||||
enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
global_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -295,7 +306,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
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, tzinfo=pytz.UTC)) # lint-amnesty, pylint: disable=line-too-long
|
||||
org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))) # lint-amnesty, pylint: disable=line-too-long
|
||||
org_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -319,7 +330,10 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(2):
|
||||
assert not CourseDurationLimitConfig.current(org=course.org).enabled
|
||||
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC))
|
||||
global_config = CourseDurationLimitConfig(
|
||||
enabled=True,
|
||||
enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
global_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -328,7 +342,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(0):
|
||||
assert not CourseDurationLimitConfig.current(org=course.org).enabled
|
||||
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) # lint-amnesty, pylint: disable=line-too-long
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))) # lint-amnesty, pylint: disable=line-too-long
|
||||
site_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -342,7 +356,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
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, tzinfo=pytz.UTC)) # lint-amnesty, pylint: disable=line-too-long
|
||||
course_config = CourseDurationLimitConfig(course=course, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))) # lint-amnesty, pylint: disable=line-too-long
|
||||
course_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -366,7 +380,10 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(2):
|
||||
assert not CourseDurationLimitConfig.current(course_key=course.id).enabled
|
||||
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC))
|
||||
global_config = CourseDurationLimitConfig(
|
||||
enabled=True,
|
||||
enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))
|
||||
)
|
||||
global_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -375,7 +392,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(0):
|
||||
assert not CourseDurationLimitConfig.current(course_key=course.id).enabled
|
||||
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) # lint-amnesty, pylint: disable=line-too-long
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))) # lint-amnesty, pylint: disable=line-too-long
|
||||
site_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
@@ -384,7 +401,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(0):
|
||||
assert not CourseDurationLimitConfig.current(course_key=course.id).enabled
|
||||
|
||||
org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=pytz.UTC)) # lint-amnesty, pylint: disable=line-too-long
|
||||
org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC"))) # lint-amnesty, pylint: disable=line-too-long
|
||||
org_config.save()
|
||||
|
||||
RequestCache.clear_all_namespaces()
|
||||
|
||||
@@ -5,7 +5,7 @@ Tests for the course updates page.
|
||||
from datetime import datetime
|
||||
|
||||
from django.urls import reverse
|
||||
from pytz import UTC
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES
|
||||
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
|
||||
@@ -41,7 +41,7 @@ class TestCourseUpdatesPage(BaseCourseUpdatesTestCase):
|
||||
self.assertContains(response, 'Second Message')
|
||||
|
||||
def test_queries(self):
|
||||
ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=UTC))
|
||||
ContentTypeGatingConfig.objects.create(enabled=True, enabled_as_of=datetime(2018, 1, 1, tzinfo=ZoneInfo("UTC")))
|
||||
self.create_course_update('First Message')
|
||||
|
||||
# Pre-fetch the view to populate any caches
|
||||
|
||||
@@ -11,7 +11,7 @@ not other discounts like coupons or enterprise/program offers configured in ecom
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from crum import get_current_request, impersonate
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
@@ -197,7 +197,7 @@ def _is_in_holdback_and_bucket(user):
|
||||
Return whether the specified user is in the first-purchase-discount holdback group.
|
||||
This will also stable bucket the user.
|
||||
"""
|
||||
if datetime(2020, 8, 1, tzinfo=pytz.UTC) <= datetime.now(tz=pytz.UTC):
|
||||
if datetime(2020, 8, 1, tzinfo=ZoneInfo("UTC")) <= datetime.now(tz=ZoneInfo("UTC")):
|
||||
return False
|
||||
|
||||
# Holdback is 10%
|
||||
|
||||
@@ -6,7 +6,7 @@ from unittest.mock import Mock, patch
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.contrib.sites.models import Site
|
||||
from django.utils.timezone import now
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
@@ -39,7 +39,7 @@ class TestApplicability(ModuleStoreTestCase):
|
||||
self.user = UserFactory.create()
|
||||
self.course = CourseFactory.create(run='test', display_name='test')
|
||||
CourseModeFactory.create(course_id=self.course.id, mode_slug='verified')
|
||||
now_time = datetime.now(tz=pytz.UTC).strftime("%Y-%m-%d %H:%M:%S%z")
|
||||
now_time = datetime.now(tz=ZoneInfo("UTC")).strftime("%Y-%m-%d %H:%M:%S%z")
|
||||
ExperimentData.objects.create(
|
||||
user=self.user, experiment_id=REV1008_EXPERIMENT_ID, key=str(self.course.id), value=now_time
|
||||
)
|
||||
@@ -175,6 +175,6 @@ class TestApplicability(ModuleStoreTestCase):
|
||||
with patch('openedx.features.discounts.applicability.stable_bucketing_hash_group', return_value=0):
|
||||
with patch(
|
||||
'openedx.features.discounts.applicability.datetime',
|
||||
Mock(now=Mock(return_value=datetime(2020, 8, 1, 0, 1, tzinfo=pytz.UTC)), wraps=datetime),
|
||||
Mock(now=Mock(return_value=datetime(2020, 8, 1, 0, 1, tzinfo=ZoneInfo("UTC"))), wraps=datetime),
|
||||
):
|
||||
assert not _is_in_holdback_and_bucket(self.user)
|
||||
|
||||
@@ -4,7 +4,7 @@ Utility functions for working with discounts and discounted pricing.
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from django.conf import settings
|
||||
from django.utils.translation import get_language
|
||||
from django.utils.translation import gettext as _
|
||||
@@ -89,7 +89,7 @@ def generate_offer_data(user, course):
|
||||
ExperimentData.objects.get_or_create(
|
||||
user=user, experiment_id=REV1008_EXPERIMENT_ID, key=str(course),
|
||||
defaults={
|
||||
'value': datetime.now(tz=pytz.UTC).strftime('%Y-%m-%d %H:%M:%S%z'),
|
||||
'value': datetime.now(tz=ZoneInfo("UTC")).strftime('%Y-%m-%d %H:%M:%S%z'),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from completion import handlers
|
||||
from completion.models import BlockCompletion
|
||||
from completion.test_utils import CompletionSetUpMixin
|
||||
from django.test import TestCase
|
||||
from pytz import utc
|
||||
from zoneinfo import ZoneInfo
|
||||
from xblock.completable import XBlockCompletionMode
|
||||
from xblock.core import XBlock
|
||||
|
||||
@@ -66,7 +66,7 @@ class ScorableCompletionHandlerTestCase(CompletionSetUpMixin, TestCase):
|
||||
usage_id=str(block_key),
|
||||
weighted_earned=0.0,
|
||||
weighted_possible=3.0,
|
||||
modified=datetime.utcnow().replace(tzinfo=utc),
|
||||
modified=datetime.utcnow().replace(tzinfo=ZoneInfo("UTC")),
|
||||
score_db_table='submissions',
|
||||
**params
|
||||
)
|
||||
@@ -127,7 +127,7 @@ class ScorableCompletionHandlerTestCase(CompletionSetUpMixin, TestCase):
|
||||
usage_id=str(self.block_key),
|
||||
weighted_earned=0.0,
|
||||
weighted_possible=3.0,
|
||||
modified=datetime.utcnow().replace(tzinfo=utc),
|
||||
modified=datetime.utcnow().replace(tzinfo=ZoneInfo("UTC")),
|
||||
score_db_table='submissions',
|
||||
)
|
||||
mock_handler.assert_called()
|
||||
@@ -153,7 +153,7 @@ class DisabledCompletionHandlerTestCase(CompletionSetUpMixin, TestCase):
|
||||
usage_id=str(self.block_key),
|
||||
weighted_earned=0.0,
|
||||
weighted_possible=3.0,
|
||||
modified=datetime.utcnow().replace(tzinfo=utc),
|
||||
modified=datetime.utcnow().replace(tzinfo=ZoneInfo("UTC")),
|
||||
score_db_table='submissions',
|
||||
)
|
||||
with pytest.raises(BlockCompletion.DoesNotExist):
|
||||
|
||||
@@ -44,7 +44,7 @@ from datetime import datetime, timedelta
|
||||
import html
|
||||
|
||||
from unittest import mock
|
||||
import pytz
|
||||
from zoneinfo import ZoneInfo
|
||||
from bs4 import BeautifulSoup
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
@@ -199,7 +199,7 @@ class GradePublishTestMixin:
|
||||
'score': score,
|
||||
'max_score': max_score})
|
||||
# Shim a return time, defaults to 1 hour before now
|
||||
return datetime.now().replace(tzinfo=pytz.UTC) - timedelta(hours=1)
|
||||
return datetime.now().replace(tzinfo=ZoneInfo("UTC")) - timedelta(hours=1)
|
||||
|
||||
self.scores = []
|
||||
patcher = mock.patch("lms.djangoapps.grades.signals.handlers.set_score", capture_score)
|
||||
|
||||
Reference in New Issue
Block a user