3.2, 3.3 compat

This commit is contained in:
Tom Christie 2013-02-01 14:03:28 +00:00
parent d9c7b1c585
commit f4f237e3ee
15 changed files with 131 additions and 109 deletions

View File

@ -1,3 +1,6 @@
__version__ = '2.1.17' __version__ = '2.1.17'
VERSION = __version__ # synonym VERSION = __version__ # synonym
# Header encoding (see RFC5987)
HTTP_HEADER_ENCODING = 'iso-8859-1'

View File

@ -1,10 +1,11 @@
""" """
Provides a set of pluggable authentication policies. Provides a set of pluggable authentication policies.
""" """
from __future__ import unicode_literals
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.utils.encoding import DjangoUnicodeDecodeError from django.utils.encoding import DjangoUnicodeDecodeError
from rest_framework import exceptions from rest_framework import exceptions, HTTP_HEADER_ENCODING
from rest_framework.compat import CsrfViewMiddleware from rest_framework.compat import CsrfViewMiddleware
from rest_framework.compat import smart_text from rest_framework.compat import smart_text
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
@ -43,23 +44,25 @@ class BasicAuthentication(BaseAuthentication):
Returns a `User` if a correct username and password have been supplied Returns a `User` if a correct username and password have been supplied
using HTTP Basic authentication. Otherwise returns `None`. using HTTP Basic authentication. Otherwise returns `None`.
""" """
auth = request.META.get('HTTP_AUTHORIZATION', '').split() auth = request.META.get('HTTP_AUTHORIZATION', b'')
if type(auth) == type(''):
# Work around django test client oddness
auth = auth.encode(HTTP_HEADER_ENCODING)
auth = auth.split()
if not auth or auth[0].lower() != "basic": if not auth or auth[0].lower() != b'basic':
return None return None
if len(auth) != 2: if len(auth) != 2:
raise exceptions.AuthenticationFailed('Invalid basic header') raise exceptions.AuthenticationFailed('Invalid basic header')
encoding = api_settings.HTTP_HEADER_ENCODING
try: try:
auth_parts = base64.b64decode(auth[1].encode(encoding)).partition(':') auth_parts = base64.b64decode(auth[1]).decode(HTTP_HEADER_ENCODING).partition(':')
except TypeError: except (TypeError, UnicodeDecodeError):
raise exceptions.AuthenticationFailed('Invalid basic header') raise exceptions.AuthenticationFailed('Invalid basic header')
try: try:
userid = smart_text(auth_parts[0]) userid, password = auth_parts[0], auth_parts[2]
password = smart_text(auth_parts[2])
except DjangoUnicodeDecodeError: except DjangoUnicodeDecodeError:
raise exceptions.AuthenticationFailed('Invalid basic header') raise exceptions.AuthenticationFailed('Invalid basic header')

View File

@ -311,7 +311,7 @@ class SlugRelatedField(RelatedField):
return self.queryset.get(**{self.slug_field: data}) return self.queryset.get(**{self.slug_field: data})
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise ValidationError(self.error_messages['does_not_exist'] % raise ValidationError(self.error_messages['does_not_exist'] %
(self.slug_field, unicode(data))) (self.slug_field, smart_text(data)))
except (TypeError, ValueError): except (TypeError, ValueError):
msg = self.error_messages['invalid'] msg = self.error_messages['invalid']
raise ValidationError(msg) raise ValidationError(msg)

View File

@ -212,7 +212,7 @@ class BaseSerializer(Field):
reverted_data = {} reverted_data = {}
if data is not None and not isinstance(data, dict): if data is not None and not isinstance(data, dict):
self._errors['non_field_errors'] = [u'Invalid data'] self._errors['non_field_errors'] = ['Invalid data']
return None return None
for field_name, field in self.fields.items(): for field_name, field in self.fields.items():
@ -287,7 +287,7 @@ class BaseSerializer(Field):
""" """
Deserialize primitives -> objects. Deserialize primitives -> objects.
""" """
if hasattr(data, '__iter__') and not isinstance(data, dict): if hasattr(data, '__iter__') and not isinstance(data, (dict, six.text_type)):
# TODO: error data when deserializing lists # TODO: error data when deserializing lists
return [self.from_native(item, None) for item in data] return [self.from_native(item, None) for item in data]
@ -525,7 +525,7 @@ class ModelSerializer(Serializer):
""" """
try: try:
instance.full_clean(exclude=self.get_validation_exclusions()) instance.full_clean(exclude=self.get_validation_exclusions())
except ValidationError, err: except ValidationError as err:
self._errors = err.message_dict self._errors = err.message_dict
return None return None
return instance return instance

View File

@ -75,9 +75,6 @@ DEFAULTS = {
'URL_FORMAT_OVERRIDE': 'format', 'URL_FORMAT_OVERRIDE': 'format',
'FORMAT_SUFFIX_KWARG': 'format', 'FORMAT_SUFFIX_KWARG': 'format',
# Header encoding (see RFC5987)
'HTTP_HEADER_ENCODING': 'iso-8859-1',
} }

View File

@ -1,6 +1,9 @@
from __future__ import unicode_literals
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.http import HttpResponse from django.http import HttpResponse
from django.test import Client, TestCase from django.test import Client, TestCase
from rest_framework import HTTP_HEADER_ENCODING
from rest_framework import permissions from rest_framework import permissions
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
from rest_framework.authentication import TokenAuthentication, BasicAuthentication, SessionAuthentication from rest_framework.authentication import TokenAuthentication, BasicAuthentication, SessionAuthentication
@ -41,13 +44,17 @@ class BasicAuthTests(TestCase):
def test_post_form_passing_basic_auth(self): def test_post_form_passing_basic_auth(self):
"""Ensure POSTing json over basic auth with correct credentials passes and does not require CSRF""" """Ensure POSTing json over basic auth with correct credentials passes and does not require CSRF"""
auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).encode('iso-8859-1').strip().decode('iso-8859-1') credentials = ('%s:%s' % (self.username, self.password))
base64_credentials = base64.b64encode(credentials.encode(HTTP_HEADER_ENCODING)).decode(HTTP_HEADER_ENCODING)
auth = 'Basic %s' % base64_credentials
response = self.csrf_client.post('/basic/', {'example': 'example'}, HTTP_AUTHORIZATION=auth) response = self.csrf_client.post('/basic/', {'example': 'example'}, HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_post_json_passing_basic_auth(self): def test_post_json_passing_basic_auth(self):
"""Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF""" """Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF"""
auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).encode('iso-8859-1').strip().decode('iso-8859-1') credentials = ('%s:%s' % (self.username, self.password))
base64_credentials = base64.b64encode(credentials.encode(HTTP_HEADER_ENCODING)).decode(HTTP_HEADER_ENCODING)
auth = 'Basic %s' % base64_credentials
response = self.csrf_client.post('/basic/', json.dumps({'example': 'example'}), 'application/json', HTTP_AUTHORIZATION=auth) response = self.csrf_client.post('/basic/', json.dumps({'example': 'example'}), 'application/json', HTTP_AUTHORIZATION=auth)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View File

@ -86,16 +86,16 @@ class TestGenericRelations(TestCase):
serializer = TagSerializer(Tag.objects.all()) serializer = TagSerializer(Tag.objects.all())
expected = [ expected = [
{ {
'tag': u'django', 'tag': 'django',
'tagged_item': u'Bookmark: https://www.djangoproject.com/' 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
}, },
{ {
'tag': u'python', 'tag': 'python',
'tagged_item': u'Bookmark: https://www.djangoproject.com/' 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
}, },
{ {
'tag': u'reminder', 'tag': 'reminder',
'tagged_item': u'Note: Remember the milk' 'tagged_item': 'Note: Remember the milk'
} }
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)

View File

@ -218,11 +218,11 @@ class HyperlinkedForeignKeyTests(TestCase):
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_update_incorrect_type(self): def test_foreign_key_update_incorrect_type(self):
data = {'url': '/foreignkeysource/1/', 'name': u'source-1', 'target': 2} data = {'url': '/foreignkeysource/1/', 'name': 'source-1', 'target': 2}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid()) self.assertFalse(serializer.is_valid())
self.assertEquals(serializer.errors, {'target': [u'Incorrect type. Expected url string, received int.']}) self.assertEquals(serializer.errors, {'target': ['Incorrect type. Expected url string, received int.']})
def test_reverse_foreign_key_update(self): def test_reverse_foreign_key_update(self):
data = {'url': '/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']} data = {'url': '/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}
@ -439,7 +439,7 @@ class HyperlinkedNullableOneToOneTests(TestCase):
queryset = OneToOneTarget.objects.all() queryset = OneToOneTarget.objects.all()
serializer = NullableOneToOneTargetSerializer(queryset) serializer = NullableOneToOneTargetSerializer(queryset)
expected = [ expected = [
{'url': '/onetoonetarget/1/', 'name': u'target-1', 'nullable_source': '/nullableonetoonesource/1/'}, {'url': '/onetoonetarget/1/', 'name': 'target-1', 'nullable_source': '/nullableonetoonesource/1/'},
{'url': '/onetoonetarget/2/', 'name': u'target-2', 'nullable_source': None}, {'url': '/onetoonetarget/2/', 'name': 'target-2', 'nullable_source': None},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)

View File

@ -109,7 +109,7 @@ class NestedNullableOneToOneTests(TestCase):
queryset = OneToOneTarget.objects.all() queryset = OneToOneTarget.objects.all()
serializer = NullableOneToOneTargetSerializer(queryset) serializer = NullableOneToOneTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'nullable_source': {'id': 1, 'name': u'source-1', 'target': 1}}, {'id': 1, 'name': 'target-1', 'nullable_source': {'id': 1, 'name': 'source-1', 'target': 1}},
{'id': 2, 'name': u'target-2', 'nullable_source': None}, {'id': 2, 'name': 'target-2', 'nullable_source': None},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)

View File

@ -198,11 +198,11 @@ class PKForeignKeyTests(TestCase):
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_update_incorrect_type(self): def test_foreign_key_update_incorrect_type(self):
data = {'id': 1, 'name': u'source-1', 'target': 'foo'} data = {'id': 1, 'name': 'source-1', 'target': 'foo'}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid()) self.assertFalse(serializer.is_valid())
self.assertEquals(serializer.errors, {'target': [u'Incorrect type. Expected pk value, received str.']}) self.assertEquals(serializer.errors, {'target': ['Incorrect type. Expected pk value, received str.']})
def test_reverse_foreign_key_update(self): def test_reverse_foreign_key_update(self):
data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]} data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]}
@ -415,7 +415,7 @@ class PKNullableOneToOneTests(TestCase):
queryset = OneToOneTarget.objects.all() queryset = OneToOneTarget.objects.all()
serializer = NullableOneToOneTargetSerializer(queryset) serializer = NullableOneToOneTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'nullable_source': 1}, {'id': 1, 'name': 'target-1', 'nullable_source': 1},
{'id': 2, 'name': u'target-2', 'nullable_source': None}, {'id': 2, 'name': 'target-2', 'nullable_source': None},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)

View File

@ -39,9 +39,9 @@ class PKForeignKeyTests(TestCase):
queryset = ForeignKeySource.objects.all() queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset) serializer = ForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 'target-1'}, {'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': 'target-1'} {'id': 3, 'name': 'source-3', 'target': 'target-1'}
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
@ -49,13 +49,13 @@ class PKForeignKeyTests(TestCase):
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset) serializer = ForeignKeyTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'sources': ['source-1', 'source-2', 'source-3']}, {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
{'id': 2, 'name': u'target-2', 'sources': []}, {'id': 2, 'name': 'target-2', 'sources': []},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_update(self): def test_foreign_key_update(self):
data = {'id': 1, 'name': u'source-1', 'target': 'target-2'} data = {'id': 1, 'name': 'source-1', 'target': 'target-2'}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
@ -66,21 +66,21 @@ class PKForeignKeyTests(TestCase):
queryset = ForeignKeySource.objects.all() queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset) serializer = ForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 'target-2'}, {'id': 1, 'name': 'source-1', 'target': 'target-2'},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': 'target-1'} {'id': 3, 'name': 'source-3', 'target': 'target-1'}
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_update_incorrect_type(self): def test_foreign_key_update_incorrect_type(self):
data = {'id': 1, 'name': u'source-1', 'target': 123} data = {'id': 1, 'name': 'source-1', 'target': 123}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid()) self.assertFalse(serializer.is_valid())
self.assertEquals(serializer.errors, {'target': [u'Object with name=123 does not exist.']}) self.assertEquals(serializer.errors, {'target': ['Object with name=123 does not exist.']})
def test_reverse_foreign_key_update(self): def test_reverse_foreign_key_update(self):
data = {'id': 2, 'name': u'target-2', 'sources': ['source-1', 'source-3']} data = {'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']}
instance = ForeignKeyTarget.objects.get(pk=2) instance = ForeignKeyTarget.objects.get(pk=2)
serializer = ForeignKeyTargetSerializer(instance, data=data) serializer = ForeignKeyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
@ -89,8 +89,8 @@ class PKForeignKeyTests(TestCase):
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
new_serializer = ForeignKeyTargetSerializer(queryset) new_serializer = ForeignKeyTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'sources': ['source-1', 'source-2', 'source-3']}, {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
{'id': 2, 'name': u'target-2', 'sources': []}, {'id': 2, 'name': 'target-2', 'sources': []},
] ]
self.assertEquals(new_serializer.data, expected) self.assertEquals(new_serializer.data, expected)
@ -101,55 +101,55 @@ class PKForeignKeyTests(TestCase):
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset) serializer = ForeignKeyTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'sources': ['source-2']}, {'id': 1, 'name': 'target-1', 'sources': ['source-2']},
{'id': 2, 'name': u'target-2', 'sources': ['source-1', 'source-3']}, {'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_create(self): def test_foreign_key_create(self):
data = {'id': 4, 'name': u'source-4', 'target': 'target-2'} data = {'id': 4, 'name': 'source-4', 'target': 'target-2'}
serializer = ForeignKeySourceSerializer(data=data) serializer = ForeignKeySourceSerializer(data=data)
serializer.is_valid() serializer.is_valid()
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
obj = serializer.save() obj = serializer.save()
self.assertEquals(serializer.data, data) self.assertEquals(serializer.data, data)
self.assertEqual(obj.name, u'source-4') self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is added, and everything else is as expected # Ensure source 4 is added, and everything else is as expected
queryset = ForeignKeySource.objects.all() queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset) serializer = ForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 'target-1'}, {'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': 'target-1'}, {'id': 3, 'name': 'source-3', 'target': 'target-1'},
{'id': 4, 'name': u'source-4', 'target': 'target-2'}, {'id': 4, 'name': 'source-4', 'target': 'target-2'},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_reverse_foreign_key_create(self): def test_reverse_foreign_key_create(self):
data = {'id': 3, 'name': u'target-3', 'sources': ['source-1', 'source-3']} data = {'id': 3, 'name': 'target-3', 'sources': ['source-1', 'source-3']}
serializer = ForeignKeyTargetSerializer(data=data) serializer = ForeignKeyTargetSerializer(data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
obj = serializer.save() obj = serializer.save()
self.assertEquals(serializer.data, data) self.assertEquals(serializer.data, data)
self.assertEqual(obj.name, u'target-3') self.assertEqual(obj.name, 'target-3')
# Ensure target 3 is added, and everything else is as expected # Ensure target 3 is added, and everything else is as expected
queryset = ForeignKeyTarget.objects.all() queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset) serializer = ForeignKeyTargetSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'target-1', 'sources': ['source-2']}, {'id': 1, 'name': 'target-1', 'sources': ['source-2']},
{'id': 2, 'name': u'target-2', 'sources': []}, {'id': 2, 'name': 'target-2', 'sources': []},
{'id': 3, 'name': u'target-3', 'sources': ['source-1', 'source-3']}, {'id': 3, 'name': 'target-3', 'sources': ['source-1', 'source-3']},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_update_with_invalid_null(self): def test_foreign_key_update_with_invalid_null(self):
data = {'id': 1, 'name': u'source-1', 'target': None} data = {'id': 1, 'name': 'source-1', 'target': None}
instance = ForeignKeySource.objects.get(pk=1) instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data) serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid()) self.assertFalse(serializer.is_valid())
self.assertEquals(serializer.errors, {'target': [u'Value may not be null']}) self.assertEquals(serializer.errors, {'target': ['Value may not be null']})
class SlugNullableForeignKeyTests(TestCase): class SlugNullableForeignKeyTests(TestCase):
@ -166,28 +166,28 @@ class SlugNullableForeignKeyTests(TestCase):
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset) serializer = NullableForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 'target-1'}, {'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': None}, {'id': 3, 'name': 'source-3', 'target': None},
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_create_with_valid_null(self): def test_foreign_key_create_with_valid_null(self):
data = {'id': 4, 'name': u'source-4', 'target': None} data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data) serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
obj = serializer.save() obj = serializer.save()
self.assertEquals(serializer.data, data) self.assertEquals(serializer.data, data)
self.assertEqual(obj.name, u'source-4') self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected # Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset) serializer = NullableForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 'target-1'}, {'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': None}, {'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': u'source-4', 'target': None} {'id': 4, 'name': 'source-4', 'target': None}
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
@ -196,27 +196,27 @@ class SlugNullableForeignKeyTests(TestCase):
The emptystring should be interpreted as null in the context The emptystring should be interpreted as null in the context
of relationships. of relationships.
""" """
data = {'id': 4, 'name': u'source-4', 'target': ''} data = {'id': 4, 'name': 'source-4', 'target': ''}
expected_data = {'id': 4, 'name': u'source-4', 'target': None} expected_data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data) serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
obj = serializer.save() obj = serializer.save()
self.assertEquals(serializer.data, expected_data) self.assertEquals(serializer.data, expected_data)
self.assertEqual(obj.name, u'source-4') self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected # Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset) serializer = NullableForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': 'target-1'}, {'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': None}, {'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': u'source-4', 'target': None} {'id': 4, 'name': 'source-4', 'target': None}
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
def test_foreign_key_update_with_valid_null(self): def test_foreign_key_update_with_valid_null(self):
data = {'id': 1, 'name': u'source-1', 'target': None} data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1) instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data) serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
@ -227,9 +227,9 @@ class SlugNullableForeignKeyTests(TestCase):
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset) serializer = NullableForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': None}, {'id': 1, 'name': 'source-1', 'target': None},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': None} {'id': 3, 'name': 'source-3', 'target': None}
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)
@ -238,8 +238,8 @@ class SlugNullableForeignKeyTests(TestCase):
The emptystring should be interpreted as null in the context The emptystring should be interpreted as null in the context
of relationships. of relationships.
""" """
data = {'id': 1, 'name': u'source-1', 'target': ''} data = {'id': 1, 'name': 'source-1', 'target': ''}
expected_data = {'id': 1, 'name': u'source-1', 'target': None} expected_data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1) instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data) serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid()) self.assertTrue(serializer.is_valid())
@ -250,8 +250,8 @@ class SlugNullableForeignKeyTests(TestCase):
queryset = NullableForeignKeySource.objects.all() queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset) serializer = NullableForeignKeySourceSerializer(queryset)
expected = [ expected = [
{'id': 1, 'name': u'source-1', 'target': None}, {'id': 1, 'name': 'source-1', 'target': None},
{'id': 2, 'name': u'source-2', 'target': 'target-1'}, {'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': u'source-3', 'target': None} {'id': 3, 'name': 'source-3', 'target': None}
] ]
self.assertEquals(serializer.data, expected) self.assertEquals(serializer.data, expected)

View File

@ -236,17 +236,17 @@ class ValidationTests(TestCase):
data = ['i am', 'a', 'list'] data = ['i am', 'a', 'list']
serializer = CommentSerializer(self.comment, data=data) serializer = CommentSerializer(self.comment, data=data)
self.assertEquals(serializer.is_valid(), False) self.assertEquals(serializer.is_valid(), False)
self.assertEquals(serializer.errors, {'non_field_errors': [u'Invalid data']}) self.assertEquals(serializer.errors, {'non_field_errors': ['Invalid data']})
data = 'and i am a string' data = 'and i am a string'
serializer = CommentSerializer(self.comment, data=data) serializer = CommentSerializer(self.comment, data=data)
self.assertEquals(serializer.is_valid(), False) self.assertEquals(serializer.is_valid(), False)
self.assertEquals(serializer.errors, {'non_field_errors': [u'Invalid data']}) self.assertEquals(serializer.errors, {'non_field_errors': ['Invalid data']})
data = 42 data = 42
serializer = CommentSerializer(self.comment, data=data) serializer = CommentSerializer(self.comment, data=data)
self.assertEquals(serializer.is_valid(), False) self.assertEquals(serializer.is_valid(), False)
self.assertEquals(serializer.errors, {'non_field_errors': [u'Invalid data']}) self.assertEquals(serializer.errors, {'non_field_errors': ['Invalid data']})
def test_cross_field_validation(self): def test_cross_field_validation(self):
@ -300,7 +300,7 @@ class ValidationTests(TestCase):
} }
serializer = ActionItemSerializerCustomRestore(data=data) serializer = ActionItemSerializerCustomRestore(data=data)
self.assertEquals(serializer.is_valid(), False) self.assertEquals(serializer.is_valid(), False)
self.assertEquals(serializer.errors, {'title': [u'Ensure this value has at most 200 characters (it has 201).']}) self.assertEquals(serializer.errors, {'title': ['Ensure this value has at most 200 characters (it has 201).']})
def test_default_modelfield_max_length_exceeded(self): def test_default_modelfield_max_length_exceeded(self):
data = { data = {
@ -340,7 +340,7 @@ class CustomValidationTests(TestCase):
serializer = self.CommentSerializerWithFieldValidator(data=data) serializer = self.CommentSerializerWithFieldValidator(data=data)
self.assertFalse(serializer.is_valid()) self.assertFalse(serializer.is_valid())
self.assertEquals(serializer.errors, {'content': [u'Test not in value']}) self.assertEquals(serializer.errors, {'content': ['Test not in value']})
def test_missing_data(self): def test_missing_data(self):
""" """
@ -352,7 +352,7 @@ class CustomValidationTests(TestCase):
} }
serializer = self.CommentSerializerWithFieldValidator(data=incomplete_data) serializer = self.CommentSerializerWithFieldValidator(data=incomplete_data)
self.assertFalse(serializer.is_valid()) self.assertFalse(serializer.is_valid())
self.assertEquals(serializer.errors, {'content': [u'This field is required.']}) self.assertEquals(serializer.errors, {'content': ['This field is required.']})
def test_wrong_data(self): def test_wrong_data(self):
""" """
@ -365,7 +365,7 @@ class CustomValidationTests(TestCase):
} }
serializer = self.CommentSerializerWithFieldValidator(data=wrong_data) serializer = self.CommentSerializerWithFieldValidator(data=wrong_data)
self.assertFalse(serializer.is_valid()) self.assertFalse(serializer.is_valid())
self.assertEquals(serializer.errors, {'email': [u'Enter a valid e-mail address.']}) self.assertEquals(serializer.errors, {'email': ['Enter a valid e-mail address.']})
class PositiveIntegerAsChoiceTests(TestCase): class PositiveIntegerAsChoiceTests(TestCase):

View File

@ -1,6 +1,6 @@
from django.test.client import RequestFactory, FakePayload from django.test.client import RequestFactory, FakePayload
from django.test.client import MULTIPART_CONTENT from django.test.client import MULTIPART_CONTENT
from urlparse import urlparse from rest_framework.compat import urlparse
class RequestFactory(RequestFactory): class RequestFactory(RequestFactory):
@ -14,7 +14,7 @@ class RequestFactory(RequestFactory):
patch_data = self._encode_data(data, content_type) patch_data = self._encode_data(data, content_type)
parsed = urlparse(path) parsed = urlparse.urlparse(path)
r = { r = {
'CONTENT_LENGTH': len(patch_data), 'CONTENT_LENGTH': len(patch_data),
'CONTENT_TYPE': content_type, 'CONTENT_TYPE': content_type,

View File

@ -139,7 +139,7 @@
# raise errors on unexpected request data""" # raise errors on unexpected request data"""
# content = {'qwerty': 'uiop', 'extra': 'extra'} # content = {'qwerty': 'uiop', 'extra': 'extra'}
# validator.allow_unknown_form_fields = True # validator.allow_unknown_form_fields = True
# self.assertEqual({'qwerty': u'uiop'}, # self.assertEqual({'qwerty': 'uiop'},
# validator.validate_request(content, None), # validator.validate_request(content, None),
# "Resource didn't accept unknown fields.") # "Resource didn't accept unknown fields.")
# validator.allow_unknown_form_fields = False # validator.allow_unknown_form_fields = False

36
tox.ini
View File

@ -1,13 +1,28 @@
[tox] [tox]
downloadcache = {toxworkdir}/cache/ downloadcache = {toxworkdir}/cache/
envlist = py2.7-django1.5,py2.7-django1.4,py2.7-django1.3,py2.6-django1.5,py2.6-django1.4,py2.6-django1.3 envlist = py3.3-django1.5,py3.2-django1.5,py2.7-django1.5,py2.7-django1.4,py2.7-django1.3,py2.6-django1.5,py2.6-django1.4,py2.6-django1.3
[testenv] [testenv]
commands = {envpython} rest_framework/runtests/runtests.py commands = {envpython} rest_framework/runtests/runtests.py
[testenv:py3.3-django1.5]
basepython = python3.3
deps = https://www.djangoproject.com/download/1.5c1/tarball/
django-filter==0.5.4
[testenv:py3.2-django1.5]
basepython = python3.2
deps = https://www.djangoproject.com/download/1.5c1/tarball/
django-filter==0.5.4
[testenv:py2.7-django1.5] [testenv:py2.7-django1.5]
basepython = python2.7 basepython = python2.7
deps = https://github.com/django/django/zipball/master deps = https://www.djangoproject.com/download/1.5c1/tarball/
django-filter==0.5.4
[testenv:py2.6-django1.5]
basepython = python2.6
deps = https://www.djangoproject.com/download/1.5c1/tarball/
django-filter==0.5.4 django-filter==0.5.4
[testenv:py2.7-django1.4] [testenv:py2.7-django1.4]
@ -15,22 +30,19 @@ basepython = python2.7
deps = django==1.4.3 deps = django==1.4.3
django-filter==0.5.4 django-filter==0.5.4
[testenv:py2.7-django1.3]
basepython = python2.7
deps = django==1.3.5
django-filter==0.5.4
[testenv:py2.6-django1.5]
basepython = python2.6
deps = https://github.com/django/django/zipball/master
django-filter==0.5.4
[testenv:py2.6-django1.4] [testenv:py2.6-django1.4]
basepython = python2.6 basepython = python2.6
deps = django==1.4.3 deps = django==1.4.3
django-filter==0.5.4 django-filter==0.5.4
[testenv:py2.7-django1.3]
basepython = python2.7
deps = django==1.3.5
django-filter==0.5.4
six
[testenv:py2.6-django1.3] [testenv:py2.6-django1.3]
basepython = python2.6 basepython = python2.6
deps = django==1.3.5 deps = django==1.3.5
django-filter==0.5.4 django-filter==0.5.4
six