Merge pull request #16176 from edx/pwnage101/remove-1.4-shims_PLAT-1424

[WIP] cleanup django 1.4 shims and mentions
This commit is contained in:
Troy Sankey
2017-10-06 14:27:31 -04:00
committed by GitHub
8 changed files with 18 additions and 83 deletions

View File

@@ -1,13 +1,8 @@
"""
Utilities for django models.
"""
import re
import unicodedata
from django.conf import settings
from django.dispatch import Signal
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
from django_countries.fields import Country
from eventtracking import tracker
@@ -171,20 +166,3 @@ def _get_truncated_setting_value(value, max_length=None):
return value[0:max_length], True
else:
return value, False
# Taken from Django 1.8 source code because it's not supported in 1.4
def slugify(value):
"""Converts value into a string suitable for readable URLs.
Converts to ASCII. Converts spaces to hyphens. Removes characters that
aren't alphanumerics, underscores, or hyphens. Converts to lowercase.
Also strips leading and trailing whitespace.
Args:
value (string): String to slugify.
"""
value = force_unicode(value)
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
value = re.sub(r'[^\w\s-]', '', value).strip().lower()
return mark_safe(re.sub(r'[-\s]+', '-', value))

View File

@@ -5,7 +5,7 @@ import hashlib
import logging
from django.core.urlresolvers import reverse
from django.template.defaultfilters import slugify
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
from badges.models import BadgeAssertion, BadgeClass, CourseCompleteImageConfiguration

View File

@@ -64,7 +64,7 @@ from student.roles import CourseBetaTesterRole
from track import contexts
from util import milestones_helpers
from util.json_request import JsonResponse
from util.model_utils import slugify
from django.utils.text import slugify
from util.sandboxing import can_execute_unsafe_code, get_python_lib_zip
from xblock_django.user_service import DjangoXBlockUserService
from xmodule.contentstore.django import contentstore

View File

@@ -27,7 +27,7 @@ from lms.djangoapps.teams import TEAM_DISCUSSION_CONTEXT
from lms.djangoapps.teams.utils import emit_team_event
from openedx.core.djangoapps.xmodule_django.models import CourseKeyField
from student.models import CourseEnrollment, LanguageField
from util.model_utils import slugify
from django.utils.text import slugify
from .errors import AlreadyOnTeamInCourse, ImmutableMembershipFieldException, NotEnrolledInCourseForTeam

View File

@@ -12,16 +12,6 @@ from .models import CourseOverview, CourseOverviewImageConfig, CourseOverviewIma
class CourseOverviewAdmin(admin.ModelAdmin):
"""
Simple, read-only list/search view of Course Overviews.
The detail view is broken because our primary key for this model are
course keys, which can have a number of chars that break admin URLs.
There's probably a way to make this work properly, but I don't have the
time to investigate. I would normally disable the links by setting
`list_display_links = None`, but that's not a valid value for that
field in Django 1.4. So I'm left with creating a page where the detail
view links are all broken for Split courses. Because I only created
this page to manually test a hotfix, the list view works for this
purpose, and that's all the yak I have time to shave today.
"""
list_display = [
'id',

View File

@@ -355,11 +355,10 @@ class CourseOverviewTestCase(ModuleStoreTestCase):
'openedx.core.djangoapps.content.course_overviews.models.CourseOverview._get_pk_val'
) as mock_get_pk_val:
mock_get_pk_val.return_value = None
# This method was not present in django 1.4. Django 1.8 calls this method if
# _get_pk_val returns None. This method will return empty str if there is no
# default value present. So mock it to avoid returning the empty str as primary key
# value. Due to empty str, model.save will do an update instead of insert which is
# incorrect and get exception in
# Django 1.8+ calls this method if _get_pk_val returns None. This method will
# return empty str if there is no default value present. So mock it to avoid
# returning the empty str as primary key value. Due to empty str, model.save will do
# an update instead of insert which is incorrect and get exception in
# openedx.core.djangoapps.xmodule_django.models.OpaqueKeyField.get_prep_value
with mock.patch('django.db.models.Field.get_pk_value_on_save') as mock_get_pk_value_on_save:

View File

@@ -33,40 +33,6 @@ TEST_UPLOAD_DT = datetime.datetime(2002, 1, 9, 15, 43, 01, tzinfo=UTC)
TEST_UPLOAD_DT2 = datetime.datetime(2003, 1, 9, 15, 43, 01, tzinfo=UTC)
class PatchedClient(APIClient):
"""
Patch DRF's APIClient to avoid a unicode error on file upload.
Famous last words: This is a *temporary* fix that we should be
able to remove once we upgrade Django past 1.4.
"""
def request(self, *args, **kwargs):
"""Construct an API request. """
# DRF's default test client implementation uses `six.text_type()`
# to convert the CONTENT_TYPE to `unicode`. In Django 1.4,
# this causes a `UnicodeDecodeError` when Django parses a multipart
# upload.
#
# This is the DRF code we're working around:
# https://github.com/tomchristie/django-rest-framework/blob/3.1.3/rest_framework/compat.py#L227
#
# ... and this is the Django code that raises the exception:
#
# https://github.com/django/django/blob/1.4.22/django/http/multipartparser.py#L435
#
# Django unhelpfully swallows the exception, so to the application code
# it appears as though the user didn't send any file data.
#
# This appears to be an issue only with requests constructed in the test
# suite, not with the upload code used in production.
#
if isinstance(kwargs.get("CONTENT_TYPE"), basestring):
kwargs["CONTENT_TYPE"] = str(kwargs["CONTENT_TYPE"])
return super(PatchedClient, self).request(*args, **kwargs)
class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
"""
Base class / shared infrastructure for tests of profile_image "upload" and
@@ -75,7 +41,6 @@ class ProfileImageEndpointMixin(UserSettingsEventTestMixin):
# subclasses should override this with the name of the view under test, as
# per the urls.py configuration.
_view_name = None
client_class = PatchedClient
def setUp(self):
super(ProfileImageEndpointMixin, self).setUp()

View File

@@ -2,7 +2,7 @@
import datetime
import json
from unittest import skipUnless, SkipTest
from unittest import skipUnless
import ddt
import httpretty
@@ -158,7 +158,7 @@ class RoleTestCase(UserApiTestCase):
self.assertHttpMethodNotAllowed(self.request_with_auth("put", self.LIST_URI))
def test_patch_list_not_allowed(self):
raise SkipTest("Django 1.4's test client does not support patch")
self.assertHttpMethodNotAllowed(self.request_with_auth("patch", self.LIST_URI))
def test_delete_list_not_allowed(self):
self.assertHttpMethodNotAllowed(self.request_with_auth("delete", self.LIST_URI))
@@ -243,7 +243,7 @@ class UserViewSetTest(UserApiTestCase):
self.assertHttpMethodNotAllowed(self.request_with_auth("put", self.LIST_URI))
def test_patch_list_not_allowed(self):
raise SkipTest("Django 1.4's test client does not support patch")
self.assertHttpMethodNotAllowed(self.request_with_auth("patch", self.LIST_URI))
def test_delete_list_not_allowed(self):
self.assertHttpMethodNotAllowed(self.request_with_auth("delete", self.LIST_URI))
@@ -310,7 +310,7 @@ class UserViewSetTest(UserApiTestCase):
self.assertHttpMethodNotAllowed(self.request_with_auth("put", self.detail_uri))
def test_patch_detail_not_allowed(self):
raise SkipTest("Django 1.4's test client does not support patch")
self.assertHttpMethodNotAllowed(self.request_with_auth("patch", self.detail_uri))
def test_delete_detail_not_allowed(self):
self.assertHttpMethodNotAllowed(self.request_with_auth("delete", self.detail_uri))
@@ -496,7 +496,7 @@ class PreferenceUsersListViewTest(UserApiTestCase):
self.assertHttpMethodNotAllowed(self.request_with_auth("put", self.LIST_URI))
def test_patch_not_allowed(self):
raise SkipTest("Django 1.4's test client does not support patch")
self.assertHttpMethodNotAllowed(self.request_with_auth("patch", self.LIST_URI))
def test_delete_not_allowed(self):
self.assertHttpMethodNotAllowed(self.request_with_auth("delete", self.LIST_URI))
@@ -571,7 +571,8 @@ class LoginSessionViewTest(UserAPITestCase):
self.assertHttpMethodNotAllowed(response)
def test_patch_not_allowed(self):
raise SkipTest("Django 1.4's test client does not support patch")
response = self.client.patch(self.url)
self.assertHttpMethodNotAllowed(response)
def test_login_form(self):
# Retrieve the login form
@@ -738,7 +739,8 @@ class PasswordResetViewTest(UserAPITestCase):
self.assertHttpMethodNotAllowed(response)
def test_patch_not_allowed(self):
raise SkipTest("Django 1.4's test client does not support patch")
response = self.client.patch(self.url)
self.assertHttpMethodNotAllowed(response)
def test_password_reset_form(self):
# Retrieve the password reset form
@@ -991,7 +993,8 @@ class RegistrationViewTest(ThirdPartyAuthTestMixin, UserAPITestCase):
self.assertHttpMethodNotAllowed(response)
def test_patch_not_allowed(self):
raise SkipTest("Django 1.4's test client does not support patch")
response = self.client.patch(self.url)
self.assertHttpMethodNotAllowed(response)
def test_register_form_default_fields(self):
no_extra_fields_setting = {}