Merge pull request #2200 from maryokhin/master

Clean up compat code
This commit is contained in:
Tom Christie 2014-12-05 13:14:14 +00:00
commit 65d6cba75f
30 changed files with 90 additions and 156 deletions

View File

@ -33,7 +33,7 @@ Some tips on good issue reporting:
* When describing issues try to phrase your ticket in terms of the *behavior* you think needs changing rather than the *code* you think need changing.
* Search the issue list first for related items, and make sure you're running the latest version of REST framework before reporting an issue.
* If reporting a bug, then try to include a pull request with a failing test case. This will help us quickly identify if there is a valid issue, and make sure that it gets fixed more quickly if there is one.
* Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintainence overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation.
* Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation.
* Closing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened.
## Triaging issues
@ -82,7 +82,7 @@ GitHub's documentation for working on pull requests is [available here][pull-req
Always run the tests before submitting pull requests, and ideally run `tox` in order to check that your modifications are compatible with both Python 2 and Python 3, and that they run properly on all supported versions of Django.
Once you've made a pull request take a look at the travis build status in the GitHub interface and make sure the tests are runnning as you'd expect.
Once you've made a pull request take a look at the travis build status in the GitHub interface and make sure the tests are running as you'd expect.
![Travis status][travis-status]

View File

@ -267,7 +267,7 @@ class OAuthAuthentication(BaseAuthentication):
def authenticate_header(self, request):
"""
If permission is denied, return a '401 Unauthorized' response,
with an appropraite 'WWW-Authenticate' header.
with an appropriate 'WWW-Authenticate' header.
"""
return 'OAuth realm="%s"' % self.www_authenticate_realm

View File

@ -1,7 +1,9 @@
import binascii
import os
from django.conf import settings
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
# Prior to Django 1.5, the AUTH_USER_MODEL setting does not exist.
@ -11,6 +13,7 @@ from django.db import models
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
@python_2_unicode_compatible
class Token(models.Model):
"""
The default authorization token model.
@ -35,5 +38,5 @@ class Token(models.Model):
def generate_key(self):
return binascii.hexlify(os.urandom(20)).decode()
def __unicode__(self):
def __str__(self):
return self.key

View File

@ -6,24 +6,14 @@ versions of django/python, and compatibility wrappers around optional packages.
# flake8: noqa
from __future__ import unicode_literals
import inspect
from django.core.exceptions import ImproperlyConfigured
from django.utils.encoding import force_text
from django.utils.six.moves.urllib import parse as urlparse
from django.conf import settings
from django.utils import six
import django
import inspect
# Handle django.utils.encoding rename in 1.5 onwards.
# smart_unicode -> smart_text
# force_unicode -> force_text
try:
from django.utils.encoding import smart_text
except ImportError:
from django.utils.encoding import smart_unicode as smart_text
try:
from django.utils.encoding import force_text
except ImportError:
from django.utils.encoding import force_unicode as force_text
# OrderedDict only available in Python 2.7.
@ -32,7 +22,7 @@ except ImportError:
# For Django <= 1.6 and Python 2.6 fall back to OrderedDict.
try:
from collections import OrderedDict
except:
except ImportError:
from django.utils.datastructures import SortedDict as OrderedDict
@ -49,7 +39,6 @@ try:
except ImportError:
django_filters = None
if django.VERSION >= (1, 6):
def clean_manytomany_helptext(text):
return text
@ -72,30 +61,6 @@ if 'guardian' in settings.INSTALLED_APPS:
pass
# cStringIO only if it's available, otherwise StringIO
try:
import cStringIO.StringIO as StringIO
except ImportError:
StringIO = six.StringIO
BytesIO = six.BytesIO
# urlparse compat import (Required because it changed in python 3.x)
try:
from urllib import parse as urlparse
except ImportError:
import urlparse
# UserDict moves in Python 3
try:
from UserDict import UserDict
from UserDict import DictMixin
except ImportError:
from collections import UserDict
from collections import MutableMapping as DictMixin
def get_model_name(model_cls):
try:
return model_cls._meta.model_name
@ -104,14 +69,6 @@ def get_model_name(model_cls):
return model_cls._meta.module_name
def get_concrete_model(model_cls):
try:
return model_cls._meta.concrete_model
except AttributeError:
# 1.3 does not include concrete model
return model_cls
# View._allowed_methods only present from 1.5 onwards
if django.VERSION >= (1, 5):
from django.views.generic import View
@ -123,7 +80,6 @@ else:
return [m.upper() for m in self.http_method_names if hasattr(self, m)]
# MinValueValidator, MaxValueValidator et al. only accept `message` in 1.8+
if django.VERSION >= (1, 8):
from django.core.validators import MinValueValidator, MaxValueValidator
@ -187,6 +143,7 @@ if 'patch' not in View.http_method_names:
# RequestFactory only provides `generic` from 1.5 onwards
from django.test.client import RequestFactory as DjangoRequestFactory
from django.test.client import FakePayload
try:
# In 1.5 the test client uses force_bytes
from django.utils.encoding import force_bytes as force_bytes_or_smart_bytes
@ -194,26 +151,22 @@ except ImportError:
# In 1.4 the test client just uses smart_str
from django.utils.encoding import smart_str as force_bytes_or_smart_bytes
class RequestFactory(DjangoRequestFactory):
def generic(self, method, path,
data='', content_type='application/octet-stream', **extra):
parsed = urlparse.urlparse(path)
data = force_bytes_or_smart_bytes(data, settings.DEFAULT_CHARSET)
r = {
'PATH_INFO': self._get_path(parsed),
'QUERY_STRING': force_text(parsed[4]),
'PATH_INFO': self._get_path(parsed),
'QUERY_STRING': force_text(parsed[4]),
'REQUEST_METHOD': six.text_type(method),
}
if data:
r.update({
'CONTENT_LENGTH': len(data),
'CONTENT_TYPE': six.text_type(content_type),
'wsgi.input': FakePayload(data),
})
elif django.VERSION <= (1, 4):
# For 1.3 we need an empty WSGI payload
r.update({
'wsgi.input': FakePayload('')
'CONTENT_TYPE': six.text_type(content_type),
'wsgi.input': FakePayload(data),
})
r.update(extra)
return self.request(**r)
@ -287,10 +240,12 @@ try:
import provider as oauth2_provider
from provider import scope as oauth2_provider_scope
from provider import constants as oauth2_constants
if oauth2_provider.__version__ in ('0.2.3', '0.2.4'):
# 0.2.3 and 0.2.4 are supported version that do not support
# timezone aware datetimes
import datetime
provider_now = datetime.datetime.now
else:
# Any other supported version does use timezone aware datetimes
@ -301,7 +256,7 @@ except ImportError:
oauth2_constants = None
provider_now = None
# `seperators` argument to `json.dumps()` differs between 2.x and 3.x
# `separators` argument to `json.dumps()` differs between 2.x and 3.x
# See: http://bugs.python.org/issue22767
if six.PY3:
SHORT_SEPARATORS = (',', ':')
@ -309,37 +264,3 @@ if six.PY3:
else:
SHORT_SEPARATORS = (b',', b':')
LONG_SEPARATORS = (b', ', b': ')
# Handle lazy strings across Py2/Py3
from django.utils.functional import Promise
if six.PY3:
def is_non_str_iterable(obj):
if (isinstance(obj, str) or
(isinstance(obj, Promise) and obj._delegate_text)):
return False
return hasattr(obj, '__iter__')
else:
def is_non_str_iterable(obj):
return hasattr(obj, '__iter__')
try:
from django.utils.encoding import python_2_unicode_compatible
except ImportError:
def python_2_unicode_compatible(klass):
"""
A decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.
To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
"""
if '__str__' not in klass.__dict__:
raise ValueError("@python_2_unicode_compatible cannot be applied "
"to %s because it doesn't define __str__()." %
klass.__name__)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass

View File

@ -5,11 +5,11 @@ In addition Django's built in 403 and 404 exceptions are handled.
(`django.http.Http404` and `django.core.exceptions.PermissionDenied`)
"""
from __future__ import unicode_literals
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from rest_framework import status
from rest_framework.compat import force_text
import math

View File

@ -5,11 +5,11 @@ from django.core.validators import RegexValidator
from django.forms import ImageField as DjangoImageField
from django.utils import six, timezone
from django.utils.dateparse import parse_date, parse_datetime, parse_time
from django.utils.encoding import is_protected_type
from django.utils.encoding import is_protected_type, smart_text
from django.utils.translation import ugettext_lazy as _
from rest_framework import ISO_8601
from rest_framework.compat import (
smart_text, EmailValidator, MinValueValidator, MaxValueValidator,
EmailValidator, MinValueValidator, MaxValueValidator,
MinLengthValidator, MaxLengthValidator, URLValidator, OrderedDict
)
from rest_framework.exceptions import ValidationError

View File

@ -1,17 +1,18 @@
"""
The metadata API is used to allow cusomization of how `OPTIONS` requests
The metadata API is used to allow customization of how `OPTIONS` requests
are handled. We currently provide a single default implementation that returns
some fairly ad-hoc information about the view.
Future implementations might use JSON schema or other definations in order
Future implementations might use JSON schema or other definitions in order
to return this information in a more standardized way.
"""
from __future__ import unicode_literals
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.utils.encoding import force_text
from rest_framework import exceptions, serializers
from rest_framework.compat import force_text, OrderedDict
from rest_framework.compat import OrderedDict
from rest_framework.request import clone_request
from rest_framework.utils.field_mapping import ClassLookupDict

View File

@ -12,7 +12,9 @@ from django.http import QueryDict
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter
from django.utils import six
from rest_framework.compat import etree, yaml, force_text, urlparse
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.encoding import force_text
from rest_framework.compat import etree, yaml
from rest_framework.exceptions import ParseError
from rest_framework import renderers
import json

View File

@ -184,7 +184,7 @@ class DjangoObjectPermissions(DjangoModelPermissions):
if not user.has_perms(perms, obj):
# If the user does not have permissions we need to determine if
# they have read permissions to see 403, or not, and simply see
# a 404 reponse.
# a 404 response.
if request.method in ('GET', 'OPTIONS', 'HEAD'):
# Read permissions already checked and failed, no need

View File

@ -1,4 +1,4 @@
from rest_framework.compat import smart_text, urlparse
from django.utils.encoding import smart_text
from rest_framework.fields import get_attribute, empty, Field
from rest_framework.reverse import reverse
from rest_framework.utils import html
@ -6,6 +6,7 @@ from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
from django.core.urlresolvers import resolve, get_script_prefix, NoReverseMatch, Resolver404
from django.db.models.query import QuerySet
from django.utils import six
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.translation import ugettext_lazy as _
@ -141,7 +142,7 @@ class PrimaryKeyRelatedField(RelatedField):
def get_iterable(self, instance, source_attrs):
# For consistency with `get_attribute` we're using `serializable_value()`
# here. Typically there won't be any difference, but some custom field
# types might return a non-primative value for the pk otherwise.
# types might return a non-primitive value for the pk otherwise.
#
# We could try to get smart with `values_list('pk', flat=True)`, which
# would be better in some case, but would actually end up with *more*

View File

@ -16,11 +16,11 @@ from django.http.multipartparser import parse_header
from django.template import Context, RequestContext, loader, Template
from django.test.client import encode_multipart
from django.utils import six
from django.utils.encoding import smart_text
from django.utils.xmlutils import SimplerXMLGenerator
from django.utils.six.moves import StringIO
from rest_framework import exceptions, serializers, status, VERSION
from rest_framework.compat import (
SHORT_SEPARATORS, LONG_SEPARATORS, StringIO, smart_text, yaml
)
from rest_framework.compat import SHORT_SEPARATORS, LONG_SEPARATORS, yaml
from rest_framework.exceptions import ParseError
from rest_framework.settings import api_settings
from rest_framework.request import is_form_media_type, override_method
@ -287,7 +287,9 @@ class TemplateHTMLRenderer(BaseRenderer):
return view.get_template_names()
elif hasattr(view, 'template_name'):
return [view.template_name]
raise ImproperlyConfigured('Returned a template response with no `template_name` attribute set on either the view or response')
raise ImproperlyConfigured(
'Returned a template response with no `template_name` attribute set on either the view or response'
)
def get_exception_template(self, response):
template_names = [name % {'status_code': response.status_code}

View File

@ -14,9 +14,9 @@ from django.http import QueryDict
from django.http.multipartparser import parse_header
from django.utils.datastructures import MultiValueDict
from django.utils.datastructures import MergeDict as DjangoMergeDict
from django.utils.six import BytesIO
from rest_framework import HTTP_HEADER_ENCODING
from rest_framework import exceptions
from rest_framework.compat import BytesIO
from rest_framework.settings import api_settings
import warnings

View File

@ -10,17 +10,13 @@ python primitives.
2. The process of marshalling between python primitives and request and
response content is handled by parsers and renderers.
"""
from django.core.exceptions import ImproperlyConfigured
from django.core.exceptions import ValidationError as DjangoValidationError
import warnings
from django.db import models
from django.db.models.fields import FieldDoesNotExist
from django.utils import six
from django.utils.translation import ugettext_lazy as _
from rest_framework.compat import OrderedDict
from rest_framework.exceptions import ValidationError
from rest_framework.fields import empty, set_value, Field, SkipField
from rest_framework.settings import api_settings
from rest_framework.utils import html, model_meta, representation
from rest_framework.utils import model_meta
from rest_framework.utils.field_mapping import (
get_url_kwargs, get_field_kwargs,
get_relation_kwargs, get_nested_relation_kwargs,
@ -33,9 +29,7 @@ from rest_framework.validators import (
UniqueForDateValidator, UniqueForMonthValidator, UniqueForYearValidator,
UniqueTogetherValidator
)
import copy
import inspect
import warnings
# Note: We do the following so that users of the framework can use this style:
#
@ -65,6 +59,7 @@ class BaseSerializer(Field):
The BaseSerializer class provides a minimal class which may be used
for writing custom serializer implementations.
"""
def __init__(self, instance=None, data=None, **kwargs):
self.instance = instance
self._initial_data = data
@ -245,7 +240,7 @@ class Serializer(BaseSerializer):
"""
A dictionary of {field_name: field_instance}.
"""
# `fields` is evalutated lazily. We do this to ensure that we don't
# `fields` is evaluated lazily. We do this to ensure that we don't
# have issues importing modules that use ModelSerializers as fields,
# even if Django's app-loading stage has not yet run.
if not hasattr(self, '_fields'):
@ -343,7 +338,7 @@ class Serializer(BaseSerializer):
# Normally you should raise `serializers.ValidationError`
# inside your codebase, but we handle Django's validation
# exception class as well for simpler compat.
# Eg. Calling Model.clean() explictily inside Serializer.validate()
# Eg. Calling Model.clean() explicitly inside Serializer.validate()
raise ValidationError({
api_settings.NON_FIELD_ERRORS_KEY: list(exc.messages)
})
@ -576,7 +571,7 @@ class ModelSerializer(Serializer):
The process of automatically determining a set of serializer fields
based on the model fields is reasonably complex, but you almost certainly
don't need to dig into the implemention.
don't need to dig into the implementation.
If the `ModelSerializer` class *doesn't* generate the set of fields that
you need you should either declare the extra/differing fields explicitly on
@ -636,7 +631,7 @@ class ModelSerializer(Serializer):
isinstance(field, BaseSerializer) and (key in validated_attrs)
for key, field in self.fields.items()
), (
'The `.create()` method does not suport nested writable fields '
'The `.create()` method does not support nested writable fields '
'by default. Write an explicit `.create()` method for serializer '
'`%s.%s`, or set `read_only=True` on nested serializer fields.' %
(self.__class__.__module__, self.__class__.__name__)
@ -684,7 +679,7 @@ class ModelSerializer(Serializer):
isinstance(field, BaseSerializer) and (key in validated_attrs)
for key, field in self.fields.items()
), (
'The `.update()` method does not suport nested writable fields '
'The `.update()` method does not support nested writable fields '
'by default. Write an explicit `.update()` method for serializer '
'`%s.%s`, or set `read_only=True` on nested serializer fields.' %
(self.__class__.__module__, self.__class__.__name__)
@ -824,7 +819,7 @@ class ModelSerializer(Serializer):
# applied, we can add the extra 'required=...' or 'default=...'
# arguments that are appropriate to these fields, or add a `HiddenField` for it.
for unique_constraint_name in unique_constraint_names:
# Get the model field that is refered too.
# Get the model field that is referred too.
unique_constraint_field = model._meta.get_field(unique_constraint_name)
if getattr(unique_constraint_field, 'auto_now_add', None):
@ -907,7 +902,7 @@ class ModelSerializer(Serializer):
)
# Check that any fields declared on the class are
# also explicity included in `Meta.fields`.
# also explicitly included in `Meta.fields`.
missing_fields = set(declared_fields.keys()) - set(fields)
if missing_fields:
missing_field = list(missing_fields)[0]
@ -1001,6 +996,7 @@ class ModelSerializer(Serializer):
class Meta:
model = relation_info.related
depth = nested_depth
return NestedSerializer
@ -1027,4 +1023,5 @@ class HyperlinkedModelSerializer(ModelSerializer):
class Meta:
model = relation_info.related
depth = nested_depth
return NestedSerializer

View File

@ -47,7 +47,7 @@ DEFAULTS = {
'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation',
'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata',
# Genric view behavior
# Generic view behavior
'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.serializers.ModelSerializer',
'DEFAULT_PAGINATION_SERIALIZER_CLASS': 'rest_framework.pagination.PaginationSerializer',
'DEFAULT_FILTER_BACKENDS': (),

View File

@ -3,11 +3,11 @@ from django import template
from django.core.urlresolvers import reverse, NoReverseMatch
from django.http import QueryDict
from django.utils import six
from django.utils.encoding import iri_to_uri
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.encoding import iri_to_uri, force_text
from django.utils.html import escape
from django.utils.safestring import SafeData, mark_safe
from django.utils.html import smart_urlquote
from rest_framework.compat import urlparse, force_text
from rest_framework.renderers import HTMLFormRenderer
import re

View File

@ -4,8 +4,9 @@ Helper classes for parsers.
from __future__ import unicode_literals
from django.db.models.query import QuerySet
from django.utils import six, timezone
from django.utils.encoding import force_text
from django.utils.functional import Promise
from rest_framework.compat import force_text, OrderedDict
from rest_framework.compat import OrderedDict
import datetime
import decimal
import types

View File

@ -5,6 +5,7 @@ See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
"""
from __future__ import unicode_literals
from django.http.multipartparser import parse_header
from django.utils.encoding import python_2_unicode_compatible
from rest_framework import HTTP_HEADER_ENCODING
@ -43,6 +44,7 @@ def order_by_precedence(media_type_lst):
return [media_types for media_types in ret if media_types]
@python_2_unicode_compatible
class _MediaType(object):
def __init__(self, media_type_str):
if media_type_str is None:
@ -79,9 +81,6 @@ class _MediaType(object):
return 3
def __str__(self):
return self.__unicode__().encode('utf-8')
def __unicode__(self):
ret = "%s/%s" % (self.main_type, self.sub_type)
for key, val in self.params.items():
ret += "; %s=%s" % (key, val)

View File

@ -3,8 +3,8 @@ Helper functions for creating user-friendly representations
of serializer classes and serializer fields.
"""
from django.db import models
from django.utils.encoding import force_text
from django.utils.functional import Promise
from rest_framework.compat import force_text
import re

View File

@ -4,7 +4,7 @@ the using Django's `.full_clean()`.
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
`ModelSerializer` class and an equivelent explicit `Serializer` class.
`ModelSerializer` class and an equivalent explicit `Serializer` class.
"""
from django.utils.translation import ugettext_lazy as _
from rest_framework.exceptions import ValidationError

View File

@ -5,9 +5,10 @@ from __future__ import unicode_literals
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.utils.encoding import smart_text
from django.views.decorators.csrf import csrf_exempt
from rest_framework import status, exceptions
from rest_framework.compat import smart_text, HttpResponseBase, View
from rest_framework.compat import HttpResponseBase, View
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.settings import api_settings

View File

@ -44,7 +44,7 @@ class ViewSetMixin(object):
instantiated view, we need to totally reimplement `.as_view`,
and slightly modify the view function that is created and returned.
"""
# The suffix initkwarg is reserved for identifing the viewset type
# The suffix initkwarg is reserved for identifying the viewset type
# eg. 'List' or 'Instance'.
cls.suffix = None
@ -98,12 +98,12 @@ class ViewSetMixin(object):
view.suffix = initkwargs.get('suffix', None)
return csrf_exempt(view)
def initialize_request(self, request, *args, **kargs):
def initialize_request(self, request, *args, **kwargs):
"""
Set the `.action` attribute on the view,
depending on the request method.
"""
request = super(ViewSetMixin, self).initialize_request(request, *args, **kargs)
request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs)
self.action = self.action_map.get(request.method.lower())
return request

View File

@ -17,24 +17,29 @@ FLAKE8_ARGS = ['rest_framework', 'tests', '--ignore=E501']
sys.path.append(os.path.dirname(__file__))
def exit_on_failure(ret, message=None):
if ret:
sys.exit(ret)
def flake8_main(args):
print('Running flake8 code linting')
ret = subprocess.call(['flake8'] + args)
print('flake8 failed' if ret else 'flake8 passed')
return ret
def split_class_and_function(string):
class_string, function_string = string.split('.', 1)
return "%s and %s" % (class_string, function_string)
def is_function(string):
# `True` if it looks like a test function is included in the string.
return string.startswith('test_') or '.test_' in string
def is_class(string):
# `True` if first character is uppercase - assume it's a class name.
return string[0] == string[0].upper()

View File

@ -2,7 +2,8 @@
from __future__ import unicode_literals
from django.test import TestCase
from rest_framework.compat import apply_markdown, smart_text
from django.utils.encoding import python_2_unicode_compatible, smart_text
from rest_framework.compat import apply_markdown
from rest_framework.views import APIView
from .description import ViewWithNonASCIICharactersInDocstring
from .description import UTF8_TEST_DOCSTRING
@ -107,6 +108,7 @@ class TestViewNamesAndDescriptions(TestCase):
"""
# use a mock object instead of gettext_lazy to ensure that we can't end
# up with a test case string in our l10n catalog
@python_2_unicode_compatible
class MockLazyStr(object):
def __init__(self, string):
self.s = string
@ -114,9 +116,6 @@ class TestViewNamesAndDescriptions(TestCase):
def __str__(self):
return self.s
def __unicode__(self):
return self.s
class MockView(APIView):
__doc__ = MockLazyStr("a gettext string")

View File

@ -31,7 +31,7 @@ class AssociatedModelSerializer(serializers.ModelSerializer):
# Tests
class IneritedModelSerializationTests(TestCase):
class InheritedModelSerializationTests(TestCase):
def test_multitable_inherited_model_fields_as_expected(self):
"""

View File

@ -5,8 +5,8 @@ from django import forms
from django.core.files.uploadhandler import MemoryFileUploadHandler
from django.test import TestCase
from django.utils import unittest
from django.utils.six.moves import StringIO
from rest_framework.compat import etree
from rest_framework.compat import StringIO
from rest_framework.exceptions import ParseError
from rest_framework.parsers import FormParser, FileUploadParser
from rest_framework.parsers import XMLParser

View File

@ -3,8 +3,8 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.generic import GenericRelation, GenericForeignKey
from django.db import models
from django.test import TestCase
from django.utils.encoding import python_2_unicode_compatible
from rest_framework import serializers
from rest_framework.compat import python_2_unicode_compatible
@python_2_unicode_compatible

View File

@ -7,9 +7,11 @@ from django.core.cache import cache
from django.db import models
from django.test import TestCase
from django.utils import six, unittest
from django.utils.six import BytesIO
from django.utils.six.moves import StringIO
from django.utils.translation import ugettext_lazy as _
from rest_framework import status, permissions
from rest_framework.compat import yaml, etree, StringIO, BytesIO
from rest_framework.compat import yaml, etree
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \

View File

@ -187,7 +187,7 @@ class MockView(APIView):
if request.POST.get('example') is not None:
return Response(status=status.HTTP_200_OK)
return Response(status=status.INTERNAL_SERVER_ERROR)
return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
urlpatterns = patterns(
'',

View File

@ -148,7 +148,7 @@ class TestUniquenessTogetherValidation(TestCase):
def test_ignore_excluded_fields(self):
"""
When model fields are not included in a serializer, then uniqueness
validtors should not be added for that field.
validators should not be added for that field.
"""
class ExcludedFieldSerializer(serializers.ModelSerializer):
class Meta:

View File

@ -1,6 +1,6 @@
[tox]
envlist =
py27-flake8,
py27-{flake8,docs},
{py26,py27}-django14,
{py26,py27,py32,py33,py34}-django{15,16},
{py27,py32,py33,py34}-django{17,master}
@ -10,8 +10,8 @@ commands = ./runtests.py --fast
setenv =
PYTHONDONTWRITEBYTECODE=1
deps =
django14: Django==1.4.16
django15: Django==1.5.11
django14: Django==1.4.11
django15: Django==1.5.5
django16: Django==1.6.8
django17: Django==1.7.1
djangomaster: https://github.com/django/django/zipball/master