Merge master

This commit is contained in:
Tom Christie 2014-12-15 12:18:55 +00:00
commit b6ee784240
10 changed files with 64 additions and 27 deletions

View File

@ -104,7 +104,7 @@ This permission is suitable if you want your API to only be accessible to regist
The `IsAdminUser` permission class will deny permission to any user, unless `user.is_staff` is `True` in which case permission will be allowed. The `IsAdminUser` permission class will deny permission to any user, unless `user.is_staff` is `True` in which case permission will be allowed.
This permission is suitable is you want your API to only be accessible to a subset of trusted administrators. This permission is suitable if you want your API to only be accessible to a subset of trusted administrators.
## IsAuthenticatedOrReadOnly ## IsAuthenticatedOrReadOnly

View File

@ -181,7 +181,7 @@ Similarly, we can control the format of the request that we send, using the `Con
"id": 4, "id": 4,
"title": "", "title": "",
"code": "print 456", "code": "print 456",
"linenos": true, "linenos": false,
"language": "python", "language": "python",
"style": "friendly" "style": "friendly"
} }

View File

@ -16,6 +16,23 @@ from django.utils import six
import django import django
def unicode_repr(instance):
# Get the repr of an instance, but ensure it is a unicode string
# on both python 3 (already the case) and 2 (not the case).
if six.PY2:
repr(instance).decode('utf-8')
return repr(instance)
def unicode_to_repr(value):
# Coerce a unicode string to the correct repr return type, depending on
# the Python version. We wrap all our `__repr__` implementations with
# this and then use unicode throughout internally.
if six.PY2:
return value.encode('utf-8')
return value
# OrderedDict only available in Python 2.7. # OrderedDict only available in Python 2.7.
# This will always be the case in Django 1.7 and above, as these versions # This will always be the case in Django 1.7 and above, as these versions
# no longer support Python 2.6. # no longer support Python 2.6.

View File

@ -1,3 +1,4 @@
from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError as DjangoValidationError from django.core.exceptions import ValidationError as DjangoValidationError
@ -10,7 +11,8 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework import ISO_8601 from rest_framework import ISO_8601
from rest_framework.compat import ( from rest_framework.compat import (
EmailValidator, MinValueValidator, MaxValueValidator, EmailValidator, MinValueValidator, MaxValueValidator,
MinLengthValidator, MaxLengthValidator, URLValidator, OrderedDict MinLengthValidator, MaxLengthValidator, URLValidator, OrderedDict,
unicode_repr, unicode_to_repr
) )
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
@ -113,7 +115,9 @@ class CreateOnlyDefault:
return self.default return self.default
def __repr__(self): def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, repr(self.default)) return unicode_to_repr(
'%s(%s)' % (self.__class__.__name__, unicode_repr(self.default))
)
class CurrentUserDefault: class CurrentUserDefault:
@ -124,7 +128,7 @@ class CurrentUserDefault:
return self.user return self.user
def __repr__(self): def __repr__(self):
return '%s()' % self.__class__.__name__ return unicode_to_repr('%s()' % self.__class__.__name__)
class SkipField(Exception): class SkipField(Exception):
@ -382,13 +386,23 @@ class Field(object):
""" """
Transform the *incoming* primitive data into a native value. Transform the *incoming* primitive data into a native value.
""" """
raise NotImplementedError('to_internal_value() must be implemented.') raise NotImplementedError(
'{cls}.to_internal_value() must be implemented.'.format(
cls=self.__class__.__name__
)
)
def to_representation(self, value): def to_representation(self, value):
""" """
Transform the *outgoing* native value into primitive data. Transform the *outgoing* native value into primitive data.
""" """
raise NotImplementedError('to_representation() must be implemented.') raise NotImplementedError(
'{cls}.to_representation() must be implemented.\n'
'If you are upgrading from REST framework version 2 '
'you might want `ReadOnlyField`.'.format(
cls=self.__class__.__name__
)
)
def fail(self, key, **kwargs): def fail(self, key, **kwargs):
""" """
@ -453,7 +467,7 @@ class Field(object):
This allows us to create descriptive representations for serializer This allows us to create descriptive representations for serializer
instances that show all the declared fields on the serializer. instances that show all the declared fields on the serializer.
""" """
return representation.field_repr(self) return unicode_to_repr(representation.field_repr(self))
# Boolean types... # Boolean types...

View File

@ -10,12 +10,11 @@ python primitives.
2. The process of marshalling between python primitives and request and 2. The process of marshalling between python primitives and request and
response content is handled by parsers and renderers. response content is handled by parsers and renderers.
""" """
import warnings from __future__ import unicode_literals
from django.db import models from django.db import models
from django.db.models.fields import FieldDoesNotExist from django.db.models.fields import FieldDoesNotExist
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework.compat import unicode_to_repr
from rest_framework.utils import model_meta from rest_framework.utils import model_meta
from rest_framework.utils.field_mapping import ( from rest_framework.utils.field_mapping import (
get_url_kwargs, get_field_kwargs, get_url_kwargs, get_field_kwargs,
@ -29,6 +28,7 @@ from rest_framework.validators import (
UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator, UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator,
UniqueTogetherValidator UniqueTogetherValidator
) )
import warnings
# Note: We do the following so that users of the framework can use this style: # Note: We do the following so that users of the framework can use this style:
@ -396,7 +396,7 @@ class Serializer(BaseSerializer):
return attrs return attrs
def __repr__(self): def __repr__(self):
return representation.serializer_repr(self, indent=1) return unicode_to_repr(representation.serializer_repr(self, indent=1))
# The following are used for accessing `BoundField` instances on the # The following are used for accessing `BoundField` instances on the
# serializer, for the purposes of presenting a form-like API onto the # serializer, for the purposes of presenting a form-like API onto the
@ -564,7 +564,7 @@ class ListSerializer(BaseSerializer):
return self.instance return self.instance
def __repr__(self): def __repr__(self):
return representation.list_repr(self, indent=1) return unicode_to_repr(representation.list_repr(self, indent=1))
# Include a backlink to the serializer class on return objects. # Include a backlink to the serializer class on return objects.
# Allows renderers such as HTMLFormRenderer to get the full field info. # Allows renderers such as HTMLFormRenderer to get the full field info.

View File

@ -6,6 +6,7 @@ from __future__ import unicode_literals
from django.db import models from django.db import models
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.functional import Promise from django.utils.functional import Promise
from rest_framework.compat import unicode_repr
import re import re
@ -25,7 +26,7 @@ def smart_repr(value):
if isinstance(value, Promise) and value._delegate_text: if isinstance(value, Promise) and value._delegate_text:
value = force_text(value) value = force_text(value)
value = repr(value).decode('utf-8') value = unicode_repr(value)
# Representations like u'help text' # Representations like u'help text'
# should simply be presented as 'help text' # should simply be presented as 'help text'

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals
import collections import collections
from rest_framework.compat import OrderedDict from rest_framework.compat import OrderedDict, unicode_to_repr
class ReturnDict(OrderedDict): class ReturnDict(OrderedDict):
@ -47,9 +48,9 @@ class BoundField(object):
return self._field.__class__ return self._field.__class__
def __repr__(self): def __repr__(self):
return '<%s value=%s errors=%s>' % ( return unicode_to_repr('<%s value=%s errors=%s>' % (
self.__class__.__name__, self.value, self.errors self.__class__.__name__, self.value, self.errors
) ))
class NestedBoundField(BoundField): class NestedBoundField(BoundField):

View File

@ -6,7 +6,9 @@ This gives us better separation of concerns, allows us to use single-step
object creation, and makes it possible to switch between using the implicit object creation, and makes it possible to switch between using the implicit
`ModelSerializer` class and an equivalent explicit `Serializer` class. `ModelSerializer` class and an equivalent explicit `Serializer` class.
""" """
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework.compat import unicode_to_repr
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from rest_framework.utils.representation import smart_repr from rest_framework.utils.representation import smart_repr
@ -59,10 +61,10 @@ class UniqueValidator:
raise ValidationError(self.message) raise ValidationError(self.message)
def __repr__(self): def __repr__(self):
return '<%s(queryset=%s)>' % ( return unicode_to_repr('<%s(queryset=%s)>' % (
self.__class__.__name__, self.__class__.__name__,
smart_repr(self.queryset) smart_repr(self.queryset)
) ))
class UniqueTogetherValidator: class UniqueTogetherValidator:
@ -141,11 +143,11 @@ class UniqueTogetherValidator:
raise ValidationError(self.message.format(field_names=field_names)) raise ValidationError(self.message.format(field_names=field_names))
def __repr__(self): def __repr__(self):
return '<%s(queryset=%s, fields=%s)>' % ( return unicode_to_repr('<%s(queryset=%s, fields=%s)>' % (
self.__class__.__name__, self.__class__.__name__,
smart_repr(self.queryset), smart_repr(self.queryset),
smart_repr(self.fields) smart_repr(self.fields)
) ))
class BaseUniqueForValidator: class BaseUniqueForValidator:
@ -205,12 +207,12 @@ class BaseUniqueForValidator:
raise ValidationError({self.field: message}) raise ValidationError({self.field: message})
def __repr__(self): def __repr__(self):
return '<%s(queryset=%s, field=%s, date_field=%s)>' % ( return unicode_to_repr('<%s(queryset=%s, field=%s, date_field=%s)>' % (
self.__class__.__name__, self.__class__.__name__,
smart_repr(self.queryset), smart_repr(self.queryset),
smart_repr(self.field), smart_repr(self.field),
smart_repr(self.date_field) smart_repr(self.date_field)
) ))
class UniqueForDateValidator(BaseUniqueForValidator): class UniqueForDateValidator(BaseUniqueForValidator):

View File

@ -62,7 +62,7 @@ class TestEmpty:
""" """
field = serializers.CharField(allow_blank=True) field = serializers.CharField(allow_blank=True)
output = field.run_validation('') output = field.run_validation('')
assert output is '' assert output == ''
def test_default(self): def test_default(self):
""" """
@ -817,7 +817,7 @@ class TestChoiceField(FieldValues):
] ]
) )
output = field.run_validation('') output = field.run_validation('')
assert output is '' assert output == ''
class TestChoiceFieldWithType(FieldValues): class TestChoiceFieldWithType(FieldValues):

View File

@ -1,6 +1,7 @@
# coding: utf-8 # coding: utf-8
from __future__ import unicode_literals from __future__ import unicode_literals
from rest_framework import serializers from rest_framework import serializers
from rest_framework.compat import unicode_repr
import pytest import pytest
@ -208,9 +209,10 @@ class TestUnicodeRepr:
class ExampleObject: class ExampleObject:
def __init__(self): def __init__(self):
self.example = '한국' self.example = '한국'
def __repr__(self): def __repr__(self):
return self.example.encode('utf8') return unicode_repr(self.example)
instance = ExampleObject() instance = ExampleObject()
serializer = ExampleSerializer(instance) serializer = ExampleSerializer(instance)
repr(serializer) repr(serializer) # Should not error.