Fix problems that drf-yasg uncovered.

These were originally fixed individually, but had to be reverted, and
are now combined in one commit.  The originals were:

7b9040f6b0 This enum was backwards
8774ff1f9b Use ref_name to disambiguate serializers that drf-yasg would otherwise assume are the same.
8a44397139 Is this field missing because it is None?
4a1154a7ca Give a safer buffer for clearing the rate limiting
64c47856dd DRF 3.7.4 changed how you delegate to another view, so don't
7359ca4fb2 Is this right? It fixes two tests
fdd66e5390 Adjust the expected error message for DRF 3.7.7
9257f68fd8 The default TIME_ZONE should be UTC
This commit is contained in:
Ned Batchelder
2019-06-07 15:42:06 -04:00
parent 6da0d5bf92
commit b3a731550c
17 changed files with 42 additions and 23 deletions

View File

@@ -125,7 +125,7 @@ class CourseRunImageSerializer(serializers.Serializer):
class CourseRunSerializerCommonFieldsMixin(serializers.Serializer):
schedule = CourseRunScheduleSerializer(source='*', required=False)
pacing_type = CourseRunPacingTypeField(source='self_paced', required=False,
choices=(('instructor_paced', False), ('self_paced', True),))
choices=((False, 'instructor_paced'), (True, 'self_paced'),))
class CourseRunSerializer(CourseRunSerializerCommonFieldsMixin, CourseRunTeamSerializerMixin, serializers.Serializer):

View File

@@ -680,7 +680,7 @@ STATICFILES_DIRS = [
# Locale/Internationalization
CELERY_TIMEZONE = 'UTC'
TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
TIME_ZONE = 'UTC'
LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGES_BIDI = lms.envs.common.LANGUAGES_BIDI

View File

@@ -28,6 +28,10 @@ class CourseModeSerializer(serializers.Serializer):
sku = serializers.CharField(required=False)
bulk_sku = serializers.CharField(required=False)
class Meta(object):
# For disambiguating within the drf-yasg swagger schema
ref_name = 'course_modes.CourseMode'
def create(self, validated_data):
"""
This method must be implemented for use in our

View File

@@ -30,7 +30,6 @@ class EntitlementsSerializerTests(ModuleStoreTestCase):
'course_uuid': str(entitlement.course_uuid),
'mode': entitlement.mode,
'refund_locked': False,
'enrollment_course_run': None,
'order_number': entitlement.order_number,
'created': entitlement.created.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
'modified': entitlement.modified.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),

View File

@@ -36,6 +36,8 @@ class CourseModeSerializer(serializers.ModelSerializer):
class Meta(object):
model = CourseMode
fields = ('name', 'currency', 'price', 'sku', 'bulk_sku', 'expires')
# For disambiguating within the drf-yasg swagger schema
ref_name = 'commerce.CourseMode'
def validate_course_id(course_id):
@@ -77,6 +79,10 @@ class CourseSerializer(serializers.Serializer):
verification_deadline = PossiblyUndefinedDateTimeField(format=None, allow_null=True, required=False)
modes = CourseModeSerializer(many=True)
class Meta(object):
# For disambiguating within the drf-yasg swagger schema
ref_name = 'commerce.Course'
def validate(self, attrs):
""" Ensure the verification deadline occurs AFTER the course mode enrollment deadlines. """
verification_deadline = attrs.get('verification_deadline', None)

View File

@@ -61,6 +61,7 @@ from openedx.core.djangoapps.django_comment_common.signals import (
thread_voted
)
from openedx.core.djangoapps.django_comment_common.utils import get_course_discussion_settings
from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
from openedx.core.djangoapps.user_api.accounts.views import AccountViewSet
from openedx.core.lib.exceptions import CourseNotFoundError, DiscussionNotFoundError, PageNotFoundError
@@ -365,10 +366,11 @@ def _get_user_profile_dict(request, usernames):
A dict with username as key and user profile details as value.
"""
request.GET = request.GET.copy() # Make a mutable copy of the GET parameters.
request.GET['username'] = usernames
user_profile_details = AccountViewSet.as_view({'get': 'list'})(request).data
if usernames:
username_list = usernames.split(",")
else:
username_list = []
user_profile_details = get_account_settings(request, username_list)
return {user['username']: user for user in user_profile_details}

View File

@@ -122,7 +122,7 @@ class GradingPolicyTestMixin(object):
"""
The view should return HTTP status 401 if user is unauthenticated.
"""
self.assert_get_for_course(expected_status_code=401, HTTP_AUTHORIZATION=None)
self.assert_get_for_course(expected_status_code=401, HTTP_AUTHORIZATION="")
def test_staff_authorized(self):
"""

View File

@@ -147,3 +147,5 @@ class UserSerializer(serializers.ModelSerializer):
model = User
fields = ('id', 'username', 'email', 'name', 'course_enrollments')
lookup_field = 'username'
# For disambiguating within the drf-yasg swagger schema
ref_name = 'mobile_api.User'

View File

@@ -1738,8 +1738,8 @@ class ProgramCourseEnrollmentOverviewViewTests(ProgramCacheTestCaseMixin, Shared
course_run_overview = response.data['course_runs'][0]
self.assertEqual(course_run_overview['start_date'], '2018-12-31T05:00:00Z')
self.assertEqual(course_run_overview['end_date'], '2019-01-02T05:00:00Z')
self.assertEqual(course_run_overview['start_date'], '2018-12-31T00:00:00Z')
self.assertEqual(course_run_overview['end_date'], '2019-01-02T00:00:00Z')
# course run end date may not exist
self.course_overview.end = None

View File

@@ -1749,8 +1749,8 @@ class RegistrationCodeRedemptionCourseEnrollment(SharedModuleStoreTestCase):
response = self.client.post(url)
self.assertEquals(response.status_code, 403)
# now reset the time to 5 mins from now in future in order to unblock
reset_time = datetime.now(UTC) + timedelta(seconds=300)
# now reset the time to 6 mins from now in future in order to unblock
reset_time = datetime.now(UTC) + timedelta(seconds=361)
with freeze_time(reset_time):
response = self.client.post(url)
self.assertEquals(response.status_code, 404)
@@ -1773,8 +1773,8 @@ class RegistrationCodeRedemptionCourseEnrollment(SharedModuleStoreTestCase):
response = self.client.get(url)
self.assertEquals(response.status_code, 403)
# now reset the time to 5 mins from now in future in order to unblock
reset_time = datetime.now(UTC) + timedelta(seconds=300)
# now reset the time to 6 mins from now in future in order to unblock
reset_time = datetime.now(UTC) + timedelta(seconds=361)
with freeze_time(reset_time):
response = self.client.get(url)
self.assertEquals(response.status_code, 404)

View File

@@ -997,7 +997,7 @@ MEDIA_URL = '/media/'
# Locale/Internationalization
CELERY_TIMEZONE = 'UTC'
TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
TIME_ZONE = 'UTC'
LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html
# these languages display right to left
LANGUAGES_BIDI = ("he", "ar", "fa", "ur", "fa-ir", "rtl")

View File

@@ -45,6 +45,10 @@ class CourseSerializer(serializers.Serializer): # pylint: disable=abstract-meth
invite_only = serializers.BooleanField(source="invitation_only")
course_modes = serializers.SerializerMethodField()
class Meta(object):
# For disambiguating within the drf-yasg swagger schema
ref_name = 'enrollment.Course'
def __init__(self, *args, **kwargs):
self.include_expired = kwargs.pop("include_expired", False)
super(CourseSerializer, self).__init__(*args, **kwargs)

View File

@@ -551,7 +551,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
("level_of_education", "none", u"ȻħȺɍłɇs", u'"ȻħȺɍłɇs" is not a valid choice.'),
("country", "GB", "XY", u'"XY" is not a valid choice.'),
("year_of_birth", 2009, "not_an_int", u"A valid integer is required."),
("name", "bob", "z" * 256, u"Ensure this value has at most 255 characters (it has 256)."),
("name", "bob", "z" * 256, u"Ensure this field has no more than 255 characters."),
("name", u"ȻħȺɍłɇs", " ", u"The name field must be at least 1 character long."),
("goals", "Smell the roses"),
("mailing_address", "Sesame Street"),

View File

@@ -470,7 +470,7 @@ def get_expected_validation_developer_message(preference_key, preference_value):
preference_key=preference_key,
preference_value=preference_value,
error={
"key": [u"Ensure this value has at most 255 characters (it has 256)."]
"key": [u"Ensure this field has no more than 255 characters."]
}
)

View File

@@ -34,6 +34,8 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
# This list is the minimal set required by the notification service
fields = ("id", "url", "email", "name", "username", "preferences")
read_only_fields = ("id", "email", "username")
# For disambiguating within the drf-yasg swagger schema
ref_name = 'user_api.User'
class UserPreferenceSerializer(serializers.HyperlinkedModelSerializer):

View File

@@ -207,7 +207,7 @@ class TestContentTypeGatingConfig(CacheIsolationTestCase):
all_configs[CourseLocator('7-True', 'test_course', 'run-None')],
{
'enabled': (True, Provenance.org),
'enabled_as_of': (datetime(2018, 1, 1, 5, tzinfo=pytz.UTC), Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
'studio_override_enabled': (None, Provenance.default),
}
)
@@ -215,7 +215,7 @@ class TestContentTypeGatingConfig(CacheIsolationTestCase):
all_configs[CourseLocator('7-True', 'test_course', 'run-False')],
{
'enabled': (False, Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 5, tzinfo=pytz.UTC), Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
'studio_override_enabled': (None, Provenance.default),
}
)
@@ -223,7 +223,7 @@ class TestContentTypeGatingConfig(CacheIsolationTestCase):
all_configs[CourseLocator('7-None', 'test_course', 'run-None')],
{
'enabled': (True, Provenance.site),
'enabled_as_of': (datetime(2018, 1, 1, 5, tzinfo=pytz.UTC), Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
'studio_override_enabled': (None, Provenance.default),
}
)

View File

@@ -236,21 +236,21 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
all_configs[CourseLocator('7-True', 'test_course', 'run-None')],
{
'enabled': (True, Provenance.org),
'enabled_as_of': (datetime(2018, 1, 1, 5, tzinfo=pytz.UTC), Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
}
)
self.assertEqual(
all_configs[CourseLocator('7-True', 'test_course', 'run-False')],
{
'enabled': (False, Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 5, tzinfo=pytz.UTC), Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
}
)
self.assertEqual(
all_configs[CourseLocator('7-None', 'test_course', 'run-None')],
{
'enabled': (True, Provenance.site),
'enabled_as_of': (datetime(2018, 1, 1, 5, tzinfo=pytz.UTC), Provenance.run),
'enabled_as_of': (datetime(2018, 1, 1, 0, tzinfo=pytz.UTC), Provenance.run),
}
)