aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2014-08-19 13:28:07 +0100
committerTom Christie2014-08-19 13:28:07 +0100
commitbf09c32de8f9d528f83e9cb7a2773d1f4c9ab563 (patch)
tree334c85c136fe1dc010f8d7860b9431b3a9d87e56
parente385a7b8eb6e538698f28128e43fe8bfaefd4e97 (diff)
downloaddjango-rest-framework-bf09c32de8f9d528f83e9cb7a2773d1f4c9ab563.tar.bz2
Code linting and added runtests.py
-rw-r--r--.travis.yml2
-rw-r--r--pytest.ini2
-rw-r--r--requirements-test.txt (renamed from optionals.txt)6
-rw-r--r--requirements.txt2
-rw-r--r--rest_framework/__init__.py8
-rw-r--r--rest_framework/authentication.py2
-rw-r--r--rest_framework/authtoken/models.py1
-rw-r--r--rest_framework/authtoken/south_migrations/0001_initial.py9
-rw-r--r--rest_framework/decorators.py7
-rw-r--r--rest_framework/exceptions.py1
-rw-r--r--rest_framework/filters.py2
-rw-r--r--rest_framework/generics.py15
-rw-r--r--rest_framework/negotiation.py6
-rw-r--r--rest_framework/permissions.py22
-rw-r--r--rest_framework/renderers.py17
-rw-r--r--rest_framework/request.py25
-rw-r--r--rest_framework/response.py6
-rw-r--r--rest_framework/serializers.py40
-rw-r--r--rest_framework/settings.py12
-rw-r--r--rest_framework/status.py4
-rw-r--r--rest_framework/templatetags/rest_framework.py6
-rw-r--r--rest_framework/test.py7
-rw-r--r--rest_framework/urls.py10
-rw-r--r--rest_framework/utils/encoders.py31
-rw-r--r--rest_framework/utils/formatting.py4
-rw-r--r--rest_framework/utils/mediatypes.py2
-rw-r--r--rest_framework/views.py2
-rw-r--r--rest_framework/viewsets.py10
-rwxr-xr-xruntests.py86
-rw-r--r--tests/conftest.py (renamed from conftest.py)0
-rw-r--r--tests/serializers.py1
-rw-r--r--tests/settings.py11
-rw-r--r--tests/test_authentication.py73
-rw-r--r--tests/test_breadcrumbs.py61
-rw-r--r--tests/test_fields.py14
-rw-r--r--tests/test_files.py11
-rw-r--r--tests/test_filters.py9
-rw-r--r--tests/test_genericrelations.py24
-rw-r--r--tests/test_htmlrenderer.py3
-rw-r--r--tests/test_hyperlinkedserializers.py3
-rw-r--r--tests/test_pagination.py12
-rw-r--r--tests/test_permissions.py58
-rw-r--r--tests/test_relations.py11
-rw-r--r--tests/test_relations_hyperlink.py15
-rw-r--r--tests/test_relations_pk.py12
-rw-r--r--tests/test_renderers.py59
-rw-r--r--tests/test_request.py3
-rw-r--r--tests/test_response.py3
-rw-r--r--tests/test_reverse.py3
-rw-r--r--tests/test_routers.py9
-rw-r--r--tests/test_serializer.py30
-rw-r--r--tests/test_serializer_bulk_update.py6
-rw-r--r--tests/test_serializer_nested.py2
-rw-r--r--tests/test_serializers.py4
-rw-r--r--tests/test_status.py2
-rw-r--r--tests/test_templatetags.py2
-rw-r--r--tests/test_testing.py6
-rw-r--r--tests/test_throttling.py48
-rw-r--r--tests/test_urlizer.py1
-rw-r--r--tox.ini10
60 files changed, 548 insertions, 305 deletions
diff --git a/.travis.yml b/.travis.yml
index 5a6900a5..9894ee4e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,7 +28,7 @@ install:
- export PYTHONPATH=.
script:
- - py.test
+ - ./runtests.py
matrix:
exclude:
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index bbd083ac..00000000
--- a/pytest.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[pytest]
-addopts = --tb=short
diff --git a/optionals.txt b/requirements-test.txt
index 262e7644..a91dd0d4 100644
--- a/optionals.txt
+++ b/requirements-test.txt
@@ -1,3 +1,9 @@
+# Test requirements
+pytest-django==2.6
+pytest==2.5.2
+pytest-cov==1.6
+
+# Optional packages
markdown>=2.1.0
PyYAML>=3.10
defusedxml>=0.3
diff --git a/requirements.txt b/requirements.txt
index 360acb14..730c1d07 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1 @@
--e .
Django>=1.3
-pytest-django==2.6
diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py
index 01036cef..f30012b9 100644
--- a/rest_framework/__init__.py
+++ b/rest_framework/__init__.py
@@ -1,9 +1,9 @@
"""
-______ _____ _____ _____ __ _
-| ___ \ ___/ ___|_ _| / _| | |
-| |_/ / |__ \ `--. | | | |_ _ __ __ _ _ __ ___ _____ _____ _ __| | __
+______ _____ _____ _____ __
+| ___ \ ___/ ___|_ _| / _| | |
+| |_/ / |__ \ `--. | | | |_ _ __ __ _ _ __ ___ _____ _____ _ __| |__
| /| __| `--. \ | | | _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
-| |\ \| |___/\__/ / | | | | | | | (_| | | | | | | __/\ V V / (_) | | | <
+| |\ \| |___/\__/ / | | | | | | | (_| | | | | | | __/\ V V / (_) | | | <
\_| \_\____/\____/ \_/ |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_|
"""
diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py
index 82cea70f..5721a869 100644
--- a/rest_framework/authentication.py
+++ b/rest_framework/authentication.py
@@ -21,7 +21,7 @@ def get_authorization_header(request):
Hide some test client ickyness where the header can be unicode.
"""
auth = request.META.get('HTTP_AUTHORIZATION', b'')
- if type(auth) == type(''):
+ if isinstance(auth, type('')):
# Work around django test client oddness
auth = auth.encode(HTTP_HEADER_ENCODING)
return auth
diff --git a/rest_framework/authtoken/models.py b/rest_framework/authtoken/models.py
index 167fa531..db21d44c 100644
--- a/rest_framework/authtoken/models.py
+++ b/rest_framework/authtoken/models.py
@@ -1,6 +1,5 @@
import binascii
import os
-from hashlib import sha1
from django.conf import settings
from django.db import models
diff --git a/rest_framework/authtoken/south_migrations/0001_initial.py b/rest_framework/authtoken/south_migrations/0001_initial.py
index d5965e40..926de02b 100644
--- a/rest_framework/authtoken/south_migrations/0001_initial.py
+++ b/rest_framework/authtoken/south_migrations/0001_initial.py
@@ -1,15 +1,10 @@
# -*- coding: utf-8 -*-
-import datetime
from south.db import db
from south.v2 import SchemaMigration
-from django.db import models
-
-from rest_framework.settings import api_settings
-
try:
from django.contrib.auth import get_user_model
-except ImportError: # django < 1.5
+except ImportError: # django < 1.5
from django.contrib.auth.models import User
else:
User = get_user_model()
@@ -26,12 +21,10 @@ class Migration(SchemaMigration):
))
db.send_create_signal('authtoken', ['Token'])
-
def backwards(self, orm):
# Deleting model 'Token'
db.delete_table('authtoken_token')
-
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py
index 18e41a18..e06d6ff5 100644
--- a/rest_framework/decorators.py
+++ b/rest_framework/decorators.py
@@ -131,6 +131,7 @@ def list_route(methods=['get'], **kwargs):
return func
return decorator
+
# These are now pending deprecation, in favor of `detail_route` and `list_route`.
def link(**kwargs):
@@ -139,11 +140,13 @@ def link(**kwargs):
"""
msg = 'link is pending deprecation. Use detail_route instead.'
warnings.warn(msg, PendingDeprecationWarning, stacklevel=2)
+
def decorator(func):
func.bind_to_methods = ['get']
func.detail = True
func.kwargs = kwargs
return func
+
return decorator
@@ -153,9 +156,11 @@ def action(methods=['post'], **kwargs):
"""
msg = 'action is pending deprecation. Use detail_route instead.'
warnings.warn(msg, PendingDeprecationWarning, stacklevel=2)
+
def decorator(func):
func.bind_to_methods = methods
func.detail = True
func.kwargs = kwargs
return func
- return decorator \ No newline at end of file
+
+ return decorator
diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py
index 5f774a9f..97dab77e 100644
--- a/rest_framework/exceptions.py
+++ b/rest_framework/exceptions.py
@@ -23,6 +23,7 @@ class APIException(Exception):
def __str__(self):
return self.detail
+
class ParseError(APIException):
status_code = status.HTTP_400_BAD_REQUEST
default_detail = 'Malformed request.'
diff --git a/rest_framework/filters.py b/rest_framework/filters.py
index c3b846ae..538386ce 100644
--- a/rest_framework/filters.py
+++ b/rest_framework/filters.py
@@ -116,7 +116,7 @@ class OrderingFilter(BaseFilterBackend):
def get_ordering(self, request):
"""
Ordering is set by a comma delimited ?ordering=... query parameter.
-
+
The `ordering` query parameter can be overridden by setting
the `ordering_param` value on the OrderingFilter or by
specifying an `ORDERING_PARAM` value in the API settings.
diff --git a/rest_framework/generics.py b/rest_framework/generics.py
index cecb548f..02d24365 100644
--- a/rest_framework/generics.py
+++ b/rest_framework/generics.py
@@ -25,6 +25,7 @@ def strict_positive_int(integer_string, cutoff=None):
ret = min(ret, cutoff)
return ret
+
def get_object_or_404(queryset, *filter_args, **filter_kwargs):
"""
Same as Django's standard shortcut, but make sure to raise 404
@@ -162,10 +163,11 @@ class GenericAPIView(views.APIView):
raise Http404(_("Page is not 'last', nor can it be converted to an int."))
try:
page = paginator.page(page_number)
- except InvalidPage as e:
- raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
- 'page_number': page_number,
- 'message': str(e)
+ except InvalidPage as exc:
+ error_format = _('Invalid page (%(page_number)s): %(message)s')
+ raise Http404(error_format % {
+ 'page_number': page_number,
+ 'message': str(exc)
})
if deprecated_style:
@@ -208,7 +210,6 @@ class GenericAPIView(views.APIView):
return filter_backends
-
########################
### The following methods provide default implementations
### that you may want to override for more complex cases.
@@ -284,8 +285,8 @@ class GenericAPIView(views.APIView):
if self.model is not None:
return self.model._default_manager.all()
- raise ImproperlyConfigured("'%s' must define 'queryset' or 'model'"
- % self.__class__.__name__)
+ error_format = "'%s' must define 'queryset' or 'model'"
+ raise ImproperlyConfigured(error_format % self.__class__.__name__)
def get_object(self, queryset=None):
"""
diff --git a/rest_framework/negotiation.py b/rest_framework/negotiation.py
index 4d205c0e..ca7b5397 100644
--- a/rest_framework/negotiation.py
+++ b/rest_framework/negotiation.py
@@ -54,8 +54,10 @@ class DefaultContentNegotiation(BaseContentNegotiation):
for media_type in media_type_set:
if media_type_matches(renderer.media_type, media_type):
# Return the most specific media type as accepted.
- if (_MediaType(renderer.media_type).precedence >
- _MediaType(media_type).precedence):
+ if (
+ _MediaType(renderer.media_type).precedence >
+ _MediaType(media_type).precedence
+ ):
# Eg client requests '*/*'
# Accepted media type is 'application/json'
return renderer, renderer.media_type
diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py
index c9517138..6a1a0077 100644
--- a/rest_framework/permissions.py
+++ b/rest_framework/permissions.py
@@ -62,9 +62,11 @@ class IsAuthenticatedOrReadOnly(BasePermission):
"""
def has_permission(self, request, view):
- return (request.method in SAFE_METHODS or
- request.user and
- request.user.is_authenticated())
+ return (
+ request.method in SAFE_METHODS or
+ request.user and
+ request.user.is_authenticated()
+ )
class DjangoModelPermissions(BasePermission):
@@ -122,9 +124,11 @@ class DjangoModelPermissions(BasePermission):
perms = self.get_required_permissions(request.method, model_cls)
- return (request.user and
+ return (
+ request.user and
(request.user.is_authenticated() or not self.authenticated_users_only) and
- request.user.has_perms(perms))
+ request.user.has_perms(perms)
+ )
class DjangoModelPermissionsOrAnonReadOnly(DjangoModelPermissions):
@@ -212,6 +216,8 @@ class TokenHasReadWriteScope(BasePermission):
required = oauth2_constants.READ if read_only else oauth2_constants.WRITE
return oauth2_provider_scope.check(required, request.auth.scope)
- assert False, ('TokenHasReadWriteScope requires either the'
- '`OAuthAuthentication` or `OAuth2Authentication` authentication '
- 'class to be used.')
+ assert False, (
+ 'TokenHasReadWriteScope requires either the'
+ '`OAuthAuthentication` or `OAuth2Authentication` authentication '
+ 'class to be used.'
+ )
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py
index 7048d87d..3dabd277 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -8,7 +8,6 @@ REST framework also provides an HTML renderer the renders the browsable API.
"""
from __future__ import unicode_literals
-import copy
import json
import django
from django import forms
@@ -75,7 +74,6 @@ class JSONRenderer(BaseRenderer):
# E.g. If we're being called by the BrowsableAPIRenderer.
return renderer_context.get('indent', None)
-
def render(self, data, accepted_media_type=None, renderer_context=None):
"""
Render `data` into JSON, returning a bytestring.
@@ -86,8 +84,10 @@ class JSONRenderer(BaseRenderer):
renderer_context = renderer_context or {}
indent = self.get_indent(accepted_media_type, renderer_context)
- ret = json.dumps(data, cls=self.encoder_class,
- indent=indent, ensure_ascii=self.ensure_ascii)
+ ret = json.dumps(
+ data, cls=self.encoder_class,
+ indent=indent, ensure_ascii=self.ensure_ascii
+ )
# On python 2.x json.dumps() returns bytestrings if ensure_ascii=True,
# but if ensure_ascii=False, the return type is underspecified,
@@ -454,8 +454,10 @@ class BrowsableAPIRenderer(BaseRenderer):
if method in ('DELETE', 'OPTIONS'):
return True # Don't actually need to return a form
- if (not getattr(view, 'get_serializer', None)
- or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)):
+ if (
+ not getattr(view, 'get_serializer', None)
+ or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)
+ ):
return
serializer = view.get_serializer(instance=obj, data=data, files=files)
@@ -576,7 +578,7 @@ class BrowsableAPIRenderer(BaseRenderer):
'version': VERSION,
'breadcrumblist': self.get_breadcrumbs(request),
'allowed_methods': view.allowed_methods,
- 'available_formats': [renderer.format for renderer in view.renderer_classes],
+ 'available_formats': [renderer_cls.format for renderer_cls in view.renderer_classes],
'response_headers': response_headers,
'put_form': self.get_rendered_html_form(view, 'PUT', request),
@@ -625,4 +627,3 @@ class MultiPartRenderer(BaseRenderer):
def render(self, data, accepted_media_type=None, renderer_context=None):
return encode_multipart(self.BOUNDARY, data)
-
diff --git a/rest_framework/request.py b/rest_framework/request.py
index d508f9b4..620b00ad 100644
--- a/rest_framework/request.py
+++ b/rest_framework/request.py
@@ -295,8 +295,11 @@ class Request(object):
Return the content body of the request, as a stream.
"""
try:
- content_length = int(self.META.get('CONTENT_LENGTH',
- self.META.get('HTTP_CONTENT_LENGTH')))
+ content_length = int(
+ self.META.get(
+ 'CONTENT_LENGTH', self.META.get('HTTP_CONTENT_LENGTH')
+ )
+ )
except (ValueError, TypeError):
content_length = 0
@@ -320,9 +323,11 @@ class Request(object):
)
# We only need to use form overloading on form POST requests.
- if (not USE_FORM_OVERLOADING
+ if (
+ not USE_FORM_OVERLOADING
or self._request.method != 'POST'
- or not is_form_media_type(self._content_type)):
+ or not is_form_media_type(self._content_type)
+ ):
return
# At this point we're committed to parsing the request as form data.
@@ -330,15 +335,19 @@ class Request(object):
self._files = self._request.FILES
# Method overloading - change the method and remove the param from the content.
- if (self._METHOD_PARAM and
- self._METHOD_PARAM in self._data):
+ if (
+ self._METHOD_PARAM and
+ self._METHOD_PARAM in self._data
+ ):
self._method = self._data[self._METHOD_PARAM].upper()
# Content overloading - modify the content type, and force re-parse.
- if (self._CONTENT_PARAM and
+ if (
+ self._CONTENT_PARAM and
self._CONTENTTYPE_PARAM and
self._CONTENT_PARAM in self._data and
- self._CONTENTTYPE_PARAM in self._data):
+ self._CONTENTTYPE_PARAM in self._data
+ ):
self._content_type = self._data[self._CONTENTTYPE_PARAM]
self._stream = BytesIO(self._data[self._CONTENT_PARAM].encode(self.parser_context['encoding']))
self._data, self._files = (Empty, Empty)
diff --git a/rest_framework/response.py b/rest_framework/response.py
index 25b78524..80225cac 100644
--- a/rest_framework/response.py
+++ b/rest_framework/response.py
@@ -62,8 +62,10 @@ class Response(SimpleTemplateResponse):
ret = renderer.render(self.data, media_type, context)
if isinstance(ret, six.text_type):
- assert charset, 'renderer returned unicode, and did not specify ' \
- 'a charset value.'
+ assert charset, (
+ 'renderer returned unicode, and did not specify '
+ 'a charset value.'
+ )
return bytes(ret.encode(charset))
if not ret:
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 2fdc9b9d..95288671 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -449,9 +449,11 @@ class BaseSerializer(WritableField):
# If we have a model manager or similar object then we need
# to iterate through each instance.
- if (self.many and
+ if (
+ self.many and
not hasattr(obj, '__iter__') and
- is_simple_callable(getattr(obj, 'all', None))):
+ is_simple_callable(getattr(obj, 'all', None))
+ ):
obj = obj.all()
kwargs = {
@@ -601,8 +603,10 @@ class BaseSerializer(WritableField):
API schemas for auto-documentation.
"""
return SortedDict(
- [(field_name, field.metadata())
- for field_name, field in six.iteritems(self.fields)]
+ [
+ (field_name, field.metadata())
+ for field_name, field in six.iteritems(self.fields)
+ ]
)
@@ -656,8 +660,10 @@ class ModelSerializer(Serializer):
"""
cls = self.opts.model
- assert cls is not None, \
- "Serializer class '%s' is missing 'model' Meta option" % self.__class__.__name__
+ assert cls is not None, (
+ "Serializer class '%s' is missing 'model' Meta option" %
+ self.__class__.__name__
+ )
opts = cls._meta.concrete_model._meta
ret = SortedDict()
nested = bool(self.opts.depth)
@@ -668,9 +674,9 @@ class ModelSerializer(Serializer):
# If model is a child via multitable inheritance, use parent's pk
pk_field = pk_field.rel.to._meta.pk
- field = self.get_pk_field(pk_field)
- if field:
- ret[pk_field.name] = field
+ serializer_pk_field = self.get_pk_field(pk_field)
+ if serializer_pk_field:
+ ret[pk_field.name] = serializer_pk_field
# Deal with forward relationships
forward_rels = [field for field in opts.fields if field.serialize]
@@ -739,9 +745,11 @@ class ModelSerializer(Serializer):
is_m2m = isinstance(relation.field,
models.fields.related.ManyToManyField)
- if (is_m2m and
+ if (
+ is_m2m and
hasattr(relation.field.rel, 'through') and
- not relation.field.rel.through._meta.auto_created):
+ not relation.field.rel.through._meta.auto_created
+ ):
has_through_model = True
if nested:
@@ -911,10 +919,12 @@ class ModelSerializer(Serializer):
for field_name, field in self.fields.items():
field_name = field.source or field_name
- if field_name in exclusions \
- and not field.read_only \
- and (field.required or hasattr(instance, field_name)) \
- and not isinstance(field, Serializer):
+ if (
+ field_name in exclusions
+ and not field.read_only
+ and (field.required or hasattr(instance, field_name))
+ and not isinstance(field, Serializer)
+ ):
exclusions.remove(field_name)
return exclusions
diff --git a/rest_framework/settings.py b/rest_framework/settings.py
index 2727f596..6806a468 100644
--- a/rest_framework/settings.py
+++ b/rest_framework/settings.py
@@ -46,16 +46,12 @@ DEFAULTS = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
- 'DEFAULT_THROTTLE_CLASSES': (
- ),
- 'DEFAULT_CONTENT_NEGOTIATION_CLASS':
- 'rest_framework.negotiation.DefaultContentNegotiation',
+ 'DEFAULT_THROTTLE_CLASSES': (),
+ 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation',
# Genric view behavior
- 'DEFAULT_MODEL_SERIALIZER_CLASS':
- 'rest_framework.serializers.ModelSerializer',
- 'DEFAULT_PAGINATION_SERIALIZER_CLASS':
- 'rest_framework.pagination.PaginationSerializer',
+ 'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.serializers.ModelSerializer',
+ 'DEFAULT_PAGINATION_SERIALIZER_CLASS': 'rest_framework.pagination.PaginationSerializer',
'DEFAULT_FILTER_BACKENDS': (),
# Throttling
diff --git a/rest_framework/status.py b/rest_framework/status.py
index 76435371..90a75508 100644
--- a/rest_framework/status.py
+++ b/rest_framework/status.py
@@ -10,15 +10,19 @@ from __future__ import unicode_literals
def is_informational(code):
return code >= 100 and code <= 199
+
def is_success(code):
return code >= 200 and code <= 299
+
def is_redirect(code):
return code >= 300 and code <= 399
+
def is_client_error(code):
return code >= 400 and code <= 499
+
def is_server_error(code):
return code >= 500 and code <= 599
diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py
index 911b1b62..5b8fa385 100644
--- a/rest_framework/templatetags/rest_framework.py
+++ b/rest_framework/templatetags/rest_framework.py
@@ -152,8 +152,10 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru
middle = middle[len(opening):]
lead = lead + opening
# Keep parentheses at the end only if they're balanced.
- if (middle.endswith(closing)
- and middle.count(closing) == middle.count(opening) + 1):
+ if (
+ middle.endswith(closing)
+ and middle.count(closing) == middle.count(opening) + 1
+ ):
middle = middle[:-len(closing)]
trail = closing + trail
diff --git a/rest_framework/test.py b/rest_framework/test.py
index d4ec50a0..9242cf7c 100644
--- a/rest_framework/test.py
+++ b/rest_framework/test.py
@@ -49,9 +49,10 @@ class APIRequestFactory(DjangoRequestFactory):
else:
format = format or self.default_format
- assert format in self.renderer_classes, ("Invalid format '{0}'. "
- "Available formats are {1}. Set TEST_REQUEST_RENDERER_CLASSES "
- "to enable extra request formats.".format(
+ assert format in self.renderer_classes, (
+ "Invalid format '{0}'. Available formats are {1}. "
+ "Set TEST_REQUEST_RENDERER_CLASSES to enable "
+ "extra request formats.".format(
format,
', '.join(["'" + fmt + "'" for fmt in self.renderer_classes.keys()])
)
diff --git a/rest_framework/urls.py b/rest_framework/urls.py
index eed4bd14..8fa3073e 100644
--- a/rest_framework/urls.py
+++ b/rest_framework/urls.py
@@ -8,17 +8,19 @@ your API requires authentication:
...
url(r'^auth', include('rest_framework.urls', namespace='rest_framework'))
)
-
+
The urls must be namespaced as 'rest_framework', and you should make sure
your authentication settings include `SessionAuthentication`.
"""
from __future__ import unicode_literals
from django.conf.urls import patterns, url
+from django.contrib.auth import views
template_name = {'template_name': 'rest_framework/login.html'}
-urlpatterns = patterns('django.contrib.auth.views',
- url(r'^login/$', 'login', template_name, name='login'),
- url(r'^logout/$', 'logout', template_name, name='logout'),
+urlpatterns = patterns(
+ '',
+ url(r'^login/$', views.login, template_name, name='login'),
+ url(r'^logout/$', views.logout, template_name, name='logout')
)
diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py
index c125ac8a..00ffdfba 100644
--- a/rest_framework/utils/encoders.py
+++ b/rest_framework/utils/encoders.py
@@ -98,14 +98,23 @@ else:
node.flow_style = best_style
return node
- SafeDumper.add_representer(decimal.Decimal,
- SafeDumper.represent_decimal)
-
- SafeDumper.add_representer(SortedDict,
- yaml.representer.SafeRepresenter.represent_dict)
- SafeDumper.add_representer(DictWithMetadata,
- yaml.representer.SafeRepresenter.represent_dict)
- SafeDumper.add_representer(SortedDictWithMetadata,
- yaml.representer.SafeRepresenter.represent_dict)
- SafeDumper.add_representer(types.GeneratorType,
- yaml.representer.SafeRepresenter.represent_list)
+ SafeDumper.add_representer(
+ decimal.Decimal,
+ SafeDumper.represent_decimal
+ )
+ SafeDumper.add_representer(
+ SortedDict,
+ yaml.representer.SafeRepresenter.represent_dict
+ )
+ SafeDumper.add_representer(
+ DictWithMetadata,
+ yaml.representer.SafeRepresenter.represent_dict
+ )
+ SafeDumper.add_representer(
+ SortedDictWithMetadata,
+ yaml.representer.SafeRepresenter.represent_dict
+ )
+ SafeDumper.add_representer(
+ types.GeneratorType,
+ yaml.representer.SafeRepresenter.represent_list
+ )
diff --git a/rest_framework/utils/formatting.py b/rest_framework/utils/formatting.py
index 4b59ba84..6d53aed1 100644
--- a/rest_framework/utils/formatting.py
+++ b/rest_framework/utils/formatting.py
@@ -6,8 +6,6 @@ from __future__ import unicode_literals
from django.utils.html import escape
from django.utils.safestring import mark_safe
from rest_framework.compat import apply_markdown
-from rest_framework.settings import api_settings
-from textwrap import dedent
import re
@@ -40,6 +38,7 @@ def dedent(content):
return content.strip()
+
def camelcase_to_spaces(content):
"""
Translate 'CamelCaseNames' to 'Camel Case Names'.
@@ -49,6 +48,7 @@ def camelcase_to_spaces(content):
content = re.sub(camelcase_boundry, ' \\1', content).strip()
return ' '.join(content.split('_')).title()
+
def markup_description(description):
"""
Apply HTML markup to the given description.
diff --git a/rest_framework/utils/mediatypes.py b/rest_framework/utils/mediatypes.py
index 92f99efd..727f9c19 100644
--- a/rest_framework/utils/mediatypes.py
+++ b/rest_framework/utils/mediatypes.py
@@ -57,7 +57,7 @@ class _MediaType(object):
if key != 'q' and other.params.get(key, None) != self.params.get(key, None):
return False
- if self.sub_type != '*' and other.sub_type != '*' and other.sub_type != self.sub_type:
+ if self.sub_type != '*' and other.sub_type != '*' and other.sub_type != self.sub_type:
return False
if self.main_type != '*' and other.main_type != '*' and other.main_type != self.main_type:
diff --git a/rest_framework/views.py b/rest_framework/views.py
index a2668f2c..bca0aaef 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -31,6 +31,7 @@ def get_view_name(view_cls, suffix=None):
return name
+
def get_view_description(view_cls, html=False):
"""
Given a view class, return a textual description to represent the view.
@@ -119,7 +120,6 @@ class APIView(View):
headers['Vary'] = 'Accept'
return headers
-
def http_method_not_allowed(self, request, *args, **kwargs):
"""
If `request.method` does not correspond to a handler method,
diff --git a/rest_framework/viewsets.py b/rest_framework/viewsets.py
index 7eb29f99..bb5b304e 100644
--- a/rest_framework/viewsets.py
+++ b/rest_framework/viewsets.py
@@ -127,11 +127,11 @@ class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
class ModelViewSet(mixins.CreateModelMixin,
- mixins.RetrieveModelMixin,
- mixins.UpdateModelMixin,
- mixins.DestroyModelMixin,
- mixins.ListModelMixin,
- GenericViewSet):
+ mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.DestroyModelMixin,
+ mixins.ListModelMixin,
+ GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
diff --git a/runtests.py b/runtests.py
new file mode 100755
index 00000000..4da05ac3
--- /dev/null
+++ b/runtests.py
@@ -0,0 +1,86 @@
+#! /usr/bin/env python
+from __future__ import print_function
+
+import pytest
+import sys
+import os
+import subprocess
+
+
+PYTEST_ARGS = {
+ 'default': ['tests'],
+ 'fast': ['tests', '-q'],
+}
+
+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()
+
+
+if __name__ == "__main__":
+ try:
+ sys.argv.remove('--nolint')
+ except ValueError:
+ run_flake8 = True
+ else:
+ run_flake8 = False
+
+ try:
+ sys.argv.remove('--lintonly')
+ except ValueError:
+ run_tests = True
+ else:
+ run_tests = False
+
+ try:
+ sys.argv.remove('--fast')
+ except ValueError:
+ style = 'default'
+ else:
+ style = 'fast'
+ run_flake8 = False
+
+ if len(sys.argv) > 1:
+ pytest_args = sys.argv[1:]
+ first_arg = pytest_args[0]
+ if first_arg.startswith('-'):
+ # `runtests.py [flags]`
+ pytest_args = ['tests'] + pytest_args
+ elif is_class(first_arg) and is_function(first_arg):
+ # `runtests.py TestCase.test_function [flags]`
+ expression = split_class_and_function(first_arg)
+ pytest_args = ['tests', '-k', expression] + pytest_args[1:]
+ elif is_class(first_arg) or is_function(first_arg):
+ # `runtests.py TestCase [flags]`
+ # `runtests.py test_function [flags]`
+ pytest_args = ['tests', '-k', pytest_args[0]] + pytest_args[1:]
+ else:
+ pytest_args = PYTEST_ARGS[style]
+
+ if run_tests:
+ exit_on_failure(pytest.main(pytest_args))
+ if run_flake8:
+ exit_on_failure(flake8_main(FLAKE8_ARGS))
diff --git a/conftest.py b/tests/conftest.py
index fa5184dd..fa5184dd 100644
--- a/conftest.py
+++ b/tests/conftest.py
diff --git a/tests/serializers.py b/tests/serializers.py
index f2f85b6e..be7b3772 100644
--- a/tests/serializers.py
+++ b/tests/serializers.py
@@ -1,5 +1,4 @@
from rest_framework import serializers
-
from tests.models import NullableForeignKeySource
diff --git a/tests/settings.py b/tests/settings.py
index de41dc66..91c9ed09 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -68,7 +68,6 @@ SECRET_KEY = 'u@x-aj9(hoh#rb-^ymf#g2jx_hp0vj7u5#b@ag1n^seu9e!%cy'
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
-# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
@@ -104,8 +103,8 @@ INSTALLED_APPS = (
# OAuth is optional and won't work if there is no oauth_provider & oauth2
try:
- import oauth_provider
- import oauth2
+ import oauth_provider # NOQA
+ import oauth2 # NOQA
except ImportError:
pass
else:
@@ -114,7 +113,7 @@ else:
)
try:
- import provider
+ import provider # NOQA
except ImportError:
pass
else:
@@ -125,13 +124,13 @@ else:
# guardian is optional
try:
- import guardian
+ import guardian # NOQA
except ImportError:
pass
else:
ANONYMOUS_USER_ID = -1
AUTHENTICATION_BACKENDS = (
- 'django.contrib.auth.backends.ModelBackend', # default
+ 'django.contrib.auth.backends.ModelBackend', # default
'guardian.backends.ObjectPermissionBackend',
)
INSTALLED_APPS += (
diff --git a/tests/test_authentication.py b/tests/test_authentication.py
index f5bfc5e6..9db4f62d 100644
--- a/tests/test_authentication.py
+++ b/tests/test_authentication.py
@@ -45,26 +45,39 @@ class MockView(APIView):
return HttpResponse({'a': 1, 'b': 2, 'c': 3})
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
(r'^session/$', MockView.as_view(authentication_classes=[SessionAuthentication])),
(r'^basic/$', MockView.as_view(authentication_classes=[BasicAuthentication])),
(r'^token/$', MockView.as_view(authentication_classes=[TokenAuthentication])),
(r'^auth-token/$', 'rest_framework.authtoken.views.obtain_auth_token'),
(r'^oauth/$', MockView.as_view(authentication_classes=[OAuthAuthentication])),
- (r'^oauth-with-scope/$', MockView.as_view(authentication_classes=[OAuthAuthentication],
- permission_classes=[permissions.TokenHasReadWriteScope]))
+ (
+ r'^oauth-with-scope/$',
+ MockView.as_view(
+ authentication_classes=[OAuthAuthentication],
+ permission_classes=[permissions.TokenHasReadWriteScope]
+ )
+ )
)
+
class OAuth2AuthenticationDebug(OAuth2Authentication):
allow_query_params_token = True
if oauth2_provider is not None:
- urlpatterns += patterns('',
+ urlpatterns += patterns(
+ '',
url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')),
url(r'^oauth2-test/$', MockView.as_view(authentication_classes=[OAuth2Authentication])),
url(r'^oauth2-test-debug/$', MockView.as_view(authentication_classes=[OAuth2AuthenticationDebug])),
- url(r'^oauth2-with-scope-test/$', MockView.as_view(authentication_classes=[OAuth2Authentication],
- permission_classes=[permissions.TokenHasReadWriteScope])),
+ url(
+ r'^oauth2-with-scope-test/$',
+ MockView.as_view(
+ authentication_classes=[OAuth2Authentication],
+ permission_classes=[permissions.TokenHasReadWriteScope]
+ )
+ )
)
@@ -278,12 +291,16 @@ class OAuthTests(TestCase):
self.TOKEN_KEY = "token_key"
self.TOKEN_SECRET = "token_secret"
- self.consumer = Consumer.objects.create(key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET,
- name='example', user=self.user, status=self.consts.ACCEPTED)
+ self.consumer = Consumer.objects.create(
+ key=self.CONSUMER_KEY, secret=self.CONSUMER_SECRET,
+ name='example', user=self.user, status=self.consts.ACCEPTED
+ )
self.scope = Scope.objects.create(name="resource name", url="api/")
- self.token = OAuthToken.objects.create(user=self.user, consumer=self.consumer, scope=self.scope,
- token_type=OAuthToken.ACCESS, key=self.TOKEN_KEY, secret=self.TOKEN_SECRET, is_approved=True
+ self.token = OAuthToken.objects.create(
+ user=self.user, consumer=self.consumer, scope=self.scope,
+ token_type=OAuthToken.ACCESS, key=self.TOKEN_KEY, secret=self.TOKEN_SECRET,
+ is_approved=True
)
def _create_authorization_header(self):
@@ -501,24 +518,24 @@ class OAuth2Tests(TestCase):
self.REFRESH_TOKEN = "refresh_token"
self.oauth2_client = oauth2_provider.oauth2.models.Client.objects.create(
- client_id=self.CLIENT_ID,
- client_secret=self.CLIENT_SECRET,
- redirect_uri='',
- client_type=0,
- name='example',
- user=None,
- )
+ client_id=self.CLIENT_ID,
+ client_secret=self.CLIENT_SECRET,
+ redirect_uri='',
+ client_type=0,
+ name='example',
+ user=None,
+ )
self.access_token = oauth2_provider.oauth2.models.AccessToken.objects.create(
- token=self.ACCESS_TOKEN,
- client=self.oauth2_client,
- user=self.user,
- )
+ token=self.ACCESS_TOKEN,
+ client=self.oauth2_client,
+ user=self.user,
+ )
self.refresh_token = oauth2_provider.oauth2.models.RefreshToken.objects.create(
- user=self.user,
- access_token=self.access_token,
- client=self.oauth2_client
- )
+ user=self.user,
+ access_token=self.access_token,
+ client=self.oauth2_client
+ )
def _create_authorization_header(self, token=None):
return "Bearer {0}".format(token or self.access_token.token)
@@ -569,8 +586,10 @@ class OAuth2Tests(TestCase):
@unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
def test_post_form_passing_auth_url_transport(self):
"""Ensure GETing form over OAuth with correct client credentials in form data succeed"""
- response = self.csrf_client.post('/oauth2-test/',
- data={'access_token': self.access_token.token})
+ response = self.csrf_client.post(
+ '/oauth2-test/',
+ data={'access_token': self.access_token.token}
+ )
self.assertEqual(response.status_code, 200)
@unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
diff --git a/tests/test_breadcrumbs.py b/tests/test_breadcrumbs.py
index f26c3eaf..780fd5c4 100644
--- a/tests/test_breadcrumbs.py
+++ b/tests/test_breadcrumbs.py
@@ -24,7 +24,8 @@ class NestedResourceRoot(APIView):
class NestedResourceInstance(APIView):
pass
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^$', Root.as_view()),
url(r'^resource/$', ResourceRoot.as_view()),
url(r'^resource/(?P<key>[0-9]+)$', ResourceInstance.as_view()),
@@ -40,34 +41,60 @@ class BreadcrumbTests(TestCase):
def test_root_breadcrumbs(self):
url = '/'
- self.assertEqual(get_breadcrumbs(url), [('Root', '/')])
+ self.assertEqual(
+ get_breadcrumbs(url),
+ [('Root', '/')]
+ )
def test_resource_root_breadcrumbs(self):
url = '/resource/'
- self.assertEqual(get_breadcrumbs(url), [('Root', '/'),
- ('Resource Root', '/resource/')])
+ self.assertEqual(
+ get_breadcrumbs(url),
+ [
+ ('Root', '/'),
+ ('Resource Root', '/resource/')
+ ]
+ )
def test_resource_instance_breadcrumbs(self):
url = '/resource/123'
- self.assertEqual(get_breadcrumbs(url), [('Root', '/'),
- ('Resource Root', '/resource/'),
- ('Resource Instance', '/resource/123')])
+ self.assertEqual(
+ get_breadcrumbs(url),
+ [
+ ('Root', '/'),
+ ('Resource Root', '/resource/'),
+ ('Resource Instance', '/resource/123')
+ ]
+ )
def test_nested_resource_breadcrumbs(self):
url = '/resource/123/'
- self.assertEqual(get_breadcrumbs(url), [('Root', '/'),
- ('Resource Root', '/resource/'),
- ('Resource Instance', '/resource/123'),
- ('Nested Resource Root', '/resource/123/')])
+ self.assertEqual(
+ get_breadcrumbs(url),
+ [
+ ('Root', '/'),
+ ('Resource Root', '/resource/'),
+ ('Resource Instance', '/resource/123'),
+ ('Nested Resource Root', '/resource/123/')
+ ]
+ )
def test_nested_resource_instance_breadcrumbs(self):
url = '/resource/123/abc'
- self.assertEqual(get_breadcrumbs(url), [('Root', '/'),
- ('Resource Root', '/resource/'),
- ('Resource Instance', '/resource/123'),
- ('Nested Resource Root', '/resource/123/'),
- ('Nested Resource Instance', '/resource/123/abc')])
+ self.assertEqual(
+ get_breadcrumbs(url),
+ [
+ ('Root', '/'),
+ ('Resource Root', '/resource/'),
+ ('Resource Instance', '/resource/123'),
+ ('Nested Resource Root', '/resource/123/'),
+ ('Nested Resource Instance', '/resource/123/abc')
+ ]
+ )
def test_broken_url_breadcrumbs_handled_gracefully(self):
url = '/foobar'
- self.assertEqual(get_breadcrumbs(url), [('Root', '/')])
+ self.assertEqual(
+ get_breadcrumbs(url),
+ [('Root', '/')]
+ )
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 97ef016f..094ac1eb 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -648,7 +648,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '123'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is less than or equal to 100.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is less than or equal to 100.']})
def test_raise_min_value(self):
"""
@@ -660,7 +660,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '99'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is greater than or equal to 100.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is greater than or equal to 100.']})
def test_raise_max_digits(self):
"""
@@ -672,7 +672,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '123.456'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 5 digits in total.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 5 digits in total.']})
def test_raise_max_decimal_places(self):
"""
@@ -684,7 +684,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '123.4567'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 3 decimal places.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 3 decimal places.']})
def test_raise_max_whole_digits(self):
"""
@@ -696,7 +696,7 @@ class DecimalFieldTest(TestCase):
s = DecimalSerializer(data={'decimal_field': '12345.6'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']})
+ self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']})
class ChoiceFieldTests(TestCase):
@@ -729,7 +729,7 @@ class ChoiceFieldTests(TestCase):
def test_invalid_choice_model(self):
s = ChoiceFieldModelSerializer(data={'choice': 'wrong_value'})
self.assertFalse(s.is_valid())
- self.assertEqual(s.errors, {'choice': ['Select a valid choice. wrong_value is not one of the available choices.']})
+ self.assertEqual(s.errors, {'choice': ['Select a valid choice. wrong_value is not one of the available choices.']})
self.assertEqual(s.data['choice'], '')
def test_empty_choice_model(self):
@@ -875,7 +875,7 @@ class SlugFieldTests(TestCase):
s = SlugFieldSerializer(data={'slug_field': 'a b'})
self.assertEqual(s.is_valid(), False)
- self.assertEqual(s.errors, {'slug_field': ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]})
+ self.assertEqual(s.errors, {'slug_field': ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]})
class URLFieldTests(TestCase):
diff --git a/tests/test_files.py b/tests/test_files.py
index 78f4cf42..af110df9 100644
--- a/tests/test_files.py
+++ b/tests/test_files.py
@@ -85,11 +85,8 @@ class FileSerializerTests(TestCase):
"""
Validation should still function when no data dictionary is provided.
"""
- now = datetime.datetime.now()
- file = BytesIO(six.b('stuff'))
- file.name = 'stuff.txt'
- file.size = len(file.getvalue())
- uploaded_file = UploadedFile(file=file, created=now)
-
- serializer = UploadedFileSerializer(files={'file': file})
+ uploaded_file = BytesIO(six.b('stuff'))
+ uploaded_file.name = 'stuff.txt'
+ uploaded_file.size = len(uploaded_file.getvalue())
+ serializer = UploadedFileSerializer(files={'file': uploaded_file})
self.assertFalse(serializer.is_valid())
diff --git a/tests/test_filters.py b/tests/test_filters.py
index 85840e01..b29760fa 100644
--- a/tests/test_filters.py
+++ b/tests/test_filters.py
@@ -74,7 +74,8 @@ if django_filters:
def get_queryset(self):
return FilterableItem.objects.all()
- urlpatterns = patterns('',
+ urlpatterns = patterns(
+ '',
url(r'^(?P<pk>\d+)/$', FilterClassDetailView.as_view(), name='detail-view'),
url(r'^$', FilterClassRootView.as_view(), name='root-view'),
url(r'^get-queryset/$', GetQuerysetView.as_view(),
@@ -653,8 +654,8 @@ class SensitiveOrderingFilterTests(TestCase):
self.assertEqual(
response.data,
[
- {'id': 1, username_field: 'userA'}, # PassB
- {'id': 2, username_field: 'userB'}, # PassC
- {'id': 3, username_field: 'userC'}, # PassA
+ {'id': 1, username_field: 'userA'}, # PassB
+ {'id': 2, username_field: 'userB'}, # PassC
+ {'id': 3, username_field: 'userC'}, # PassA
]
)
diff --git a/tests/test_genericrelations.py b/tests/test_genericrelations.py
index 3a8f3c7f..95295eaa 100644
--- a/tests/test_genericrelations.py
+++ b/tests/test_genericrelations.py
@@ -117,18 +117,18 @@ class TestGenericRelations(TestCase):
serializer = TagSerializer(Tag.objects.all(), many=True)
expected = [
- {
- 'tag': 'django',
- 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
- },
- {
- 'tag': 'python',
- 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
- },
- {
- 'tag': 'reminder',
- 'tagged_item': 'Note: Remember the milk'
- }
+ {
+ 'tag': 'django',
+ 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
+ },
+ {
+ 'tag': 'python',
+ 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
+ },
+ {
+ 'tag': 'reminder',
+ 'tagged_item': 'Note: Remember the milk'
+ }
]
self.assertEqual(serializer.data, expected)
diff --git a/tests/test_htmlrenderer.py b/tests/test_htmlrenderer.py
index 88d11c46..5a680f99 100644
--- a/tests/test_htmlrenderer.py
+++ b/tests/test_htmlrenderer.py
@@ -34,7 +34,8 @@ def not_found(request):
raise Http404()
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^$', example),
url(r'^permission_denied$', permission_denied),
url(r'^not_found$', not_found),
diff --git a/tests/test_hyperlinkedserializers.py b/tests/test_hyperlinkedserializers.py
index d478ea73..d4548539 100644
--- a/tests/test_hyperlinkedserializers.py
+++ b/tests/test_hyperlinkedserializers.py
@@ -94,7 +94,8 @@ class OptionalRelationDetail(generics.RetrieveUpdateDestroyAPIView):
model_serializer_class = serializers.HyperlinkedModelSerializer
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^basic/$', BasicList.as_view(), name='basicmodel-list'),
url(r'^basic/(?P<pk>\d+)/$', BasicDetail.as_view(), name='basicmodel-detail'),
url(r'^anchor/(?P<pk>\d+)/$', AnchorDetail.as_view(), name='anchor-detail'),
diff --git a/tests/test_pagination.py b/tests/test_pagination.py
index 293146c0..d5b9244d 100644
--- a/tests/test_pagination.py
+++ b/tests/test_pagination.py
@@ -1,7 +1,6 @@
from __future__ import unicode_literals
import datetime
from decimal import Decimal
-from django.db import models
from django.core.paginator import Paginator
from django.test import TestCase
from django.utils import unittest
@@ -12,6 +11,7 @@ from .models import BasicModel, FilterableItem
factory = APIRequestFactory()
+
# Helper function to split arguments out of an url
def split_arguments_from_url(url):
if '?' not in url:
@@ -274,8 +274,8 @@ class TestUnpaginated(TestCase):
BasicModel(text=i).save()
self.objects = BasicModel.objects
self.data = [
- {'id': obj.id, 'text': obj.text}
- for obj in self.objects.all()
+ {'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()
]
self.view = DefaultPageSizeKwargView.as_view()
@@ -302,8 +302,8 @@ class TestCustomPaginateByParam(TestCase):
BasicModel(text=i).save()
self.objects = BasicModel.objects
self.data = [
- {'id': obj.id, 'text': obj.text}
- for obj in self.objects.all()
+ {'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()
]
self.view = PaginateByParamView.as_view()
@@ -483,8 +483,6 @@ class NonIntegerPaginator(object):
class TestNonIntegerPagination(TestCase):
-
-
def test_custom_pagination_serializer(self):
objects = ['john', 'paul', 'george', 'ringo']
paginator = NonIntegerPaginator(objects, 2)
diff --git a/tests/test_permissions.py b/tests/test_permissions.py
index a2cb0c36..93f8020f 100644
--- a/tests/test_permissions.py
+++ b/tests/test_permissions.py
@@ -12,6 +12,7 @@ import base64
factory = APIRequestFactory()
+
class RootView(generics.ListCreateAPIView):
model = BasicModel
authentication_classes = [authentication.BasicAuthentication]
@@ -101,42 +102,54 @@ class ModelPermissionsIntegrationTests(TestCase):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_options_permitted(self):
- request = factory.options('/',
- HTTP_AUTHORIZATION=self.permitted_credentials)
+ request = factory.options(
+ '/',
+ HTTP_AUTHORIZATION=self.permitted_credentials
+ )
response = root_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('actions', response.data)
self.assertEqual(list(response.data['actions'].keys()), ['POST'])
- request = factory.options('/1',
- HTTP_AUTHORIZATION=self.permitted_credentials)
+ request = factory.options(
+ '/1',
+ HTTP_AUTHORIZATION=self.permitted_credentials
+ )
response = instance_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('actions', response.data)
self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
def test_options_disallowed(self):
- request = factory.options('/',
- HTTP_AUTHORIZATION=self.disallowed_credentials)
+ request = factory.options(
+ '/',
+ HTTP_AUTHORIZATION=self.disallowed_credentials
+ )
response = root_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNotIn('actions', response.data)
- request = factory.options('/1',
- HTTP_AUTHORIZATION=self.disallowed_credentials)
+ request = factory.options(
+ '/1',
+ HTTP_AUTHORIZATION=self.disallowed_credentials
+ )
response = instance_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNotIn('actions', response.data)
def test_options_updateonly(self):
- request = factory.options('/',
- HTTP_AUTHORIZATION=self.updateonly_credentials)
+ request = factory.options(
+ '/',
+ HTTP_AUTHORIZATION=self.updateonly_credentials
+ )
response = root_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNotIn('actions', response.data)
- request = factory.options('/1',
- HTTP_AUTHORIZATION=self.updateonly_credentials)
+ request = factory.options(
+ '/1',
+ HTTP_AUTHORIZATION=self.updateonly_credentials
+ )
response = instance_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('actions', response.data)
@@ -153,6 +166,7 @@ class BasicPermModel(models.Model):
# add, change, delete built in to django
)
+
# Custom object-level permission, that includes 'view' permissions
class ViewObjectPermissions(permissions.DjangoObjectPermissions):
perms_map = {
@@ -205,7 +219,7 @@ class ObjectPermissionsIntegrationTests(TestCase):
app_label = BasicPermModel._meta.app_label
f = '{0}_{1}'.format
perms = {
- 'view': f('view', model_name),
+ 'view': f('view', model_name),
'change': f('change', model_name),
'delete': f('delete', model_name)
}
@@ -246,21 +260,27 @@ class ObjectPermissionsIntegrationTests(TestCase):
# Update
def test_can_update_permissions(self):
- request = factory.patch('/1', {'text': 'foobar'}, format='json',
- HTTP_AUTHORIZATION=self.credentials['writeonly'])
+ request = factory.patch(
+ '/1', {'text': 'foobar'}, format='json',
+ HTTP_AUTHORIZATION=self.credentials['writeonly']
+ )
response = object_permissions_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data.get('text'), 'foobar')
def test_cannot_update_permissions(self):
- request = factory.patch('/1', {'text': 'foobar'}, format='json',
- HTTP_AUTHORIZATION=self.credentials['deleteonly'])
+ request = factory.patch(
+ '/1', {'text': 'foobar'}, format='json',
+ HTTP_AUTHORIZATION=self.credentials['deleteonly']
+ )
response = object_permissions_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_cannot_update_permissions_non_existing(self):
- request = factory.patch('/999', {'text': 'foobar'}, format='json',
- HTTP_AUTHORIZATION=self.credentials['deleteonly'])
+ request = factory.patch(
+ '/999', {'text': 'foobar'}, format='json',
+ HTTP_AUTHORIZATION=self.credentials['deleteonly']
+ )
response = object_permissions_view(request, pk='999')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
diff --git a/tests/test_relations.py b/tests/test_relations.py
index cd276d30..bc1db69f 100644
--- a/tests/test_relations.py
+++ b/tests/test_relations.py
@@ -108,19 +108,25 @@ class RelatedFieldSourceTests(TestCase):
doesn't exist.
"""
from tests.models import ManyToManySource
+
class Meta:
model = ManyToManySource
+
attrs = {
'name': serializers.SlugRelatedField(
slug_field='name', source='banzai'),
'Meta': Meta,
}
- TestSerializer = type(str('TestSerializer'),
- (serializers.ModelSerializer,), attrs)
+ TestSerializer = type(
+ str('TestSerializer'),
+ (serializers.ModelSerializer,),
+ attrs
+ )
with self.assertRaises(AttributeError):
TestSerializer(data={'name': 'foo'})
+
@unittest.skipIf(get_version() < '1.6.0', 'Upstream behaviour changed in v1.6')
class RelatedFieldChoicesTests(TestCase):
"""
@@ -141,4 +147,3 @@ class RelatedFieldChoicesTests(TestCase):
widget_count = len(field.widget.choices)
self.assertEqual(widget_count, choice_count + 1, 'BLANK_CHOICE_DASH option should have been added')
-
diff --git a/tests/test_relations_hyperlink.py b/tests/test_relations_hyperlink.py
index ab1c6664..0c8eb254 100644
--- a/tests/test_relations_hyperlink.py
+++ b/tests/test_relations_hyperlink.py
@@ -16,7 +16,8 @@ request = factory.get('/') # Just to ensure we have a request in the serializer
def dummy_view(request, pk):
pass
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^dummyurl/(?P<pk>[0-9]+)/$', dummy_view, name='dummy-url'),
url(r'^manytomanysource/(?P<pk>[0-9]+)/$', dummy_view, name='manytomanysource-detail'),
url(r'^manytomanytarget/(?P<pk>[0-9]+)/$', dummy_view, name='manytomanytarget-detail'),
@@ -86,9 +87,9 @@ class HyperlinkedManyToManyTests(TestCase):
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
- {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
- {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
+ {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
+ {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
+ {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
]
self.assertEqual(serializer.data, expected)
@@ -114,9 +115,9 @@ class HyperlinkedManyToManyTests(TestCase):
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
- {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
- {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
+ {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
+ {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
+ {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
]
self.assertEqual(serializer.data, expected)
diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py
index ff59b250..c051b076 100644
--- a/tests/test_relations_pk.py
+++ b/tests/test_relations_pk.py
@@ -65,9 +65,9 @@ class PKManyToManyTests(TestCase):
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True)
expected = [
- {'id': 1, 'name': 'source-1', 'targets': [1]},
- {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
- {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
+ {'id': 1, 'name': 'source-1', 'targets': [1]},
+ {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
+ {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
]
self.assertEqual(serializer.data, expected)
@@ -93,9 +93,9 @@ class PKManyToManyTests(TestCase):
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True)
expected = [
- {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]},
- {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
- {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
+ {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]},
+ {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
+ {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
]
self.assertEqual(serializer.data, expected)
diff --git a/tests/test_renderers.py b/tests/test_renderers.py
index 1d8adfa7..0403cde2 100644
--- a/tests/test_renderers.py
+++ b/tests/test_renderers.py
@@ -76,7 +76,6 @@ class MockGETView(APIView):
return Response({'foo': ['bar', 'baz']})
-
class MockPOSTView(APIView):
def post(self, request, **kwargs):
return Response({'foo': request.DATA})
@@ -102,7 +101,8 @@ class HTMLView1(APIView):
def get(self, request, **kwargs):
return Response('text')
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
url(r'^cache$', MockGETView.as_view()),
@@ -312,16 +312,22 @@ class JSONRendererTests(TestCase):
class Dict(MutableMapping):
def __init__(self):
self._dict = dict()
+
def __getitem__(self, key):
return self._dict.__getitem__(key)
+
def __setitem__(self, key, value):
return self._dict.__setitem__(key, value)
+
def __delitem__(self, key):
return self._dict.__delitem__(key)
+
def __iter__(self):
return self._dict.__iter__()
+
def __len__(self):
return self._dict.__len__()
+
def keys(self):
return self._dict.keys()
@@ -330,22 +336,24 @@ class JSONRendererTests(TestCase):
x[2] = 3
ret = JSONRenderer().render(x)
data = json.loads(ret.decode('utf-8'))
- self.assertEquals(data, {'key': 'string value', '2': 3})
+ self.assertEquals(data, {'key': 'string value', '2': 3})
def test_render_obj_with_getitem(self):
class DictLike(object):
def __init__(self):
self._dict = {}
+
def set(self, value):
self._dict = dict(value)
+
def __getitem__(self, key):
return self._dict[key]
-
+
x = DictLike()
x.set({'a': 1, 'b': 'string'})
with self.assertRaises(TypeError):
JSONRenderer().render(x)
-
+
def test_without_content_type_args(self):
"""
Test basic JSON rendering.
@@ -394,35 +402,47 @@ class JSONPRendererTests(TestCase):
"""
Test JSONP rendering with View JSON Renderer.
"""
- resp = self.client.get('/jsonp/jsonrenderer',
- HTTP_ACCEPT='application/javascript')
+ resp = self.client.get(
+ '/jsonp/jsonrenderer',
+ HTTP_ACCEPT='application/javascript'
+ )
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp['Content-Type'], 'application/javascript; charset=utf-8')
- self.assertEqual(resp.content,
- ('callback(%s);' % _flat_repr).encode('ascii'))
+ self.assertEqual(
+ resp.content,
+ ('callback(%s);' % _flat_repr).encode('ascii')
+ )
def test_without_callback_without_json_renderer(self):
"""
Test JSONP rendering without View JSON Renderer.
"""
- resp = self.client.get('/jsonp/nojsonrenderer',
- HTTP_ACCEPT='application/javascript')
+ resp = self.client.get(
+ '/jsonp/nojsonrenderer',
+ HTTP_ACCEPT='application/javascript'
+ )
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp['Content-Type'], 'application/javascript; charset=utf-8')
- self.assertEqual(resp.content,
- ('callback(%s);' % _flat_repr).encode('ascii'))
+ self.assertEqual(
+ resp.content,
+ ('callback(%s);' % _flat_repr).encode('ascii')
+ )
def test_with_callback(self):
"""
Test JSONP rendering with callback function name.
"""
callback_func = 'myjsonpcallback'
- resp = self.client.get('/jsonp/nojsonrenderer?callback=' + callback_func,
- HTTP_ACCEPT='application/javascript')
+ resp = self.client.get(
+ '/jsonp/nojsonrenderer?callback=' + callback_func,
+ HTTP_ACCEPT='application/javascript'
+ )
self.assertEqual(resp.status_code, status.HTTP_200_OK)
self.assertEqual(resp['Content-Type'], 'application/javascript; charset=utf-8')
- self.assertEqual(resp.content,
- ('%s(%s);' % (callback_func, _flat_repr)).encode('ascii'))
+ self.assertEqual(
+ resp.content,
+ ('%s(%s);' % (callback_func, _flat_repr)).encode('ascii')
+ )
if yaml:
@@ -467,7 +487,6 @@ if yaml:
def assertYAMLContains(self, content, string):
self.assertTrue(string in content, '%r not in %r' % (string, content))
-
class UnicodeYAMLRendererTests(TestCase):
"""
Tests specific for the Unicode YAML Renderer
@@ -592,13 +611,13 @@ class CacheRenderTest(TestCase):
""" Return any errors that would be raised if `obj' is pickled
Courtesy of koffie @ http://stackoverflow.com/a/7218986/109897
"""
- if seen == None:
+ if seen is None:
seen = []
try:
state = obj.__getstate__()
except AttributeError:
return
- if state == None:
+ if state is None:
return
if isinstance(state, tuple):
if not isinstance(state[0], dict):
diff --git a/tests/test_request.py b/tests/test_request.py
index 0cde0fb4..8b048b5c 100644
--- a/tests/test_request.py
+++ b/tests/test_request.py
@@ -272,7 +272,8 @@ class MockView(APIView):
return Response(status=status.INTERNAL_SERVER_ERROR)
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
(r'^$', MockView.as_view()),
)
diff --git a/tests/test_response.py b/tests/test_response.py
index 0551f4a8..c28f186e 100644
--- a/tests/test_response.py
+++ b/tests/test_response.py
@@ -100,7 +100,8 @@ new_model_viewset_router = routers.DefaultRouter()
new_model_viewset_router.register(r'', HTMLNewModelViewSet)
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^setbyview$', MockViewSettingContentType.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
url(r'^.*\.(?P<format>.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
diff --git a/tests/test_reverse.py b/tests/test_reverse.py
index 0d3fddf0..675a9d5a 100644
--- a/tests/test_reverse.py
+++ b/tests/test_reverse.py
@@ -10,7 +10,8 @@ factory = APIRequestFactory()
def null_view(request):
pass
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^view$', null_view, name='view'),
)
diff --git a/tests/test_routers.py b/tests/test_routers.py
index 381569bd..b076f134 100644
--- a/tests/test_routers.py
+++ b/tests/test_routers.py
@@ -93,7 +93,8 @@ class TestCustomLookupFields(TestCase):
from tests import test_routers
urls = getattr(test_routers, 'urlpatterns')
- urls += patterns('',
+ urls += patterns(
+ '',
url(r'^', include(self.router.urls)),
)
@@ -104,7 +105,8 @@ class TestCustomLookupFields(TestCase):
def test_retrieve_lookup_field_list_view(self):
response = self.client.get('/notes/')
- self.assertEqual(response.data,
+ self.assertEqual(
+ response.data,
[{
"url": "http://testserver/notes/123/",
"uuid": "123", "text": "foo bar"
@@ -113,7 +115,8 @@ class TestCustomLookupFields(TestCase):
def test_retrieve_lookup_field_detail_view(self):
response = self.client.get('/notes/123/')
- self.assertEqual(response.data,
+ self.assertEqual(
+ response.data,
{
"url": "http://testserver/notes/123/",
"uuid": "123", "text": "foo bar"
diff --git a/tests/test_serializer.py b/tests/test_serializer.py
index 7d57fcf0..d27bdcf1 100644
--- a/tests/test_serializer.py
+++ b/tests/test_serializer.py
@@ -7,10 +7,12 @@ from django.utils import unittest
from django.utils.datastructures import MultiValueDict
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers, fields, relations
-from tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
- BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel,
- ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo, RESTFrameworkModel,
- ForeignKeySource, ManyToManySource)
+from tests.models import (
+ HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
+ BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel,
+ DefaultValueModel, ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo,
+ RESTFrameworkModel, ForeignKeySource
+)
from tests.models import BasicModelSerializer
import datetime
import pickle
@@ -99,6 +101,7 @@ class ActionItemSerializer(serializers.ModelSerializer):
class Meta:
model = ActionItem
+
class ActionItemSerializerOptionalFields(serializers.ModelSerializer):
"""
Intended to test that fields with `required=False` are excluded from validation.
@@ -109,6 +112,7 @@ class ActionItemSerializerOptionalFields(serializers.ModelSerializer):
model = ActionItem
fields = ('title',)
+
class ActionItemSerializerCustomRestore(serializers.ModelSerializer):
class Meta:
@@ -295,8 +299,10 @@ class BasicTests(TestCase):
in the Meta data
"""
serializer = PersonSerializer(self.person)
- self.assertEqual(set(serializer.data.keys()),
- set(['name', 'age', 'info']))
+ self.assertEqual(
+ set(serializer.data.keys()),
+ set(['name', 'age', 'info'])
+ )
def test_field_with_dictionary(self):
"""
@@ -331,9 +337,9 @@ class BasicTests(TestCase):
— id field is not populated if `data` is accessed prior to `save()`
"""
serializer = ActionItemSerializer(self.actionitem)
- self.assertIsNone(serializer.data.get('id',None), 'New instance. `id` should not be set.')
+ self.assertIsNone(serializer.data.get('id', None), 'New instance. `id` should not be set.')
serializer.save()
- self.assertIsNotNone(serializer.data.get('id',None), 'Model is saved. `id` should be set.')
+ self.assertIsNotNone(serializer.data.get('id', None), 'Model is saved. `id` should be set.')
def test_fields_marked_as_not_required_are_excluded_from_validation(self):
"""
@@ -660,10 +666,10 @@ class ModelValidationTests(TestCase):
serializer.save()
second_serializer = AlbumsSerializer(data={'title': 'a'})
self.assertFalse(second_serializer.is_valid())
- self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.'],})
+ self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.']})
third_serializer = AlbumsSerializer(data=[{'title': 'b', 'ref': '1'}, {'title': 'c'}], many=True)
self.assertFalse(third_serializer.is_valid())
- self.assertEqual(third_serializer.errors, [{'ref': ['Album with this Ref already exists.']}, {}])
+ self.assertEqual(third_serializer.errors, [{'ref': ['Album with this Ref already exists.']}, {}])
def test_foreign_key_is_null_with_partial(self):
"""
@@ -959,7 +965,7 @@ class WritableFieldDefaultValueTests(TestCase):
self.assertEqual(got, self.expected)
def test_get_default_value_with_callable(self):
- field = self.create_field(default=lambda : self.expected)
+ field = self.create_field(default=lambda: self.expected)
got = field.get_default_value()
self.assertEqual(got, self.expected)
@@ -974,7 +980,7 @@ class WritableFieldDefaultValueTests(TestCase):
self.assertIsNone(got)
def test_get_default_value_returns_non_True_values(self):
- values = [None, '', False, 0, [], (), {}] # values that assumed as 'False' in the 'if' clause
+ values = [None, '', False, 0, [], (), {}] # values that assumed as 'False' in the 'if' clause
for expected in values:
field = self.create_field(default=expected)
got = field.get_default_value()
diff --git a/tests/test_serializer_bulk_update.py b/tests/test_serializer_bulk_update.py
index 8b0ded1a..67a8ed0d 100644
--- a/tests/test_serializer_bulk_update.py
+++ b/tests/test_serializer_bulk_update.py
@@ -83,9 +83,9 @@ class BulkCreateSerializerTests(TestCase):
self.assertEqual(serializer.is_valid(), False)
expected_errors = [
- {'non_field_errors': ['Invalid data']},
- {'non_field_errors': ['Invalid data']},
- {'non_field_errors': ['Invalid data']}
+ {'non_field_errors': ['Invalid data']},
+ {'non_field_errors': ['Invalid data']},
+ {'non_field_errors': ['Invalid data']}
]
self.assertEqual(serializer.errors, expected_errors)
diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py
index 6d69ffbd..c09c24db 100644
--- a/tests/test_serializer_nested.py
+++ b/tests/test_serializer_nested.py
@@ -328,12 +328,14 @@ class NestedModelSerializerUpdateTests(TestCase):
class BlogPostSerializer(serializers.ModelSerializer):
comments = BlogPostCommentSerializer(many=True, source='blogpostcomment_set')
+
class Meta:
model = models.BlogPost
fields = ('id', 'title', 'comments')
class PersonSerializer(serializers.ModelSerializer):
posts = BlogPostSerializer(many=True, source='blogpost_set')
+
class Meta:
model = models.Person
fields = ('id', 'name', 'age', 'posts')
diff --git a/tests/test_serializers.py b/tests/test_serializers.py
index 2e276f15..09de9f4c 100644
--- a/tests/test_serializers.py
+++ b/tests/test_serializers.py
@@ -1,9 +1,7 @@
-from django.db import models
from django.test import TestCase
-
+from rest_framework.compat import six
from rest_framework.serializers import _resolve_model
from tests.models import BasicModel
-from rest_framework.compat import six
class ResolveModelTests(TestCase):
diff --git a/tests/test_status.py b/tests/test_status.py
index 7b1bdae3..721a6e30 100644
--- a/tests/test_status.py
+++ b/tests/test_status.py
@@ -30,4 +30,4 @@ class TestStatus(TestCase):
self.assertFalse(is_server_error(499))
self.assertTrue(is_server_error(500))
self.assertTrue(is_server_error(599))
- self.assertFalse(is_server_error(600)) \ No newline at end of file
+ self.assertFalse(is_server_error(600))
diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py
index d4da0c23..b96bc0ca 100644
--- a/tests/test_templatetags.py
+++ b/tests/test_templatetags.py
@@ -48,4 +48,4 @@ class Issue1386Tests(TestCase):
self.assertEqual(i, res)
# example from issue #1386, this shouldn't raise an exception
- _ = urlize_quoted_links("asdf:[/p]zxcv.com")
+ urlize_quoted_links("asdf:[/p]zxcv.com")
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 1b126e00..9c472026 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -28,7 +28,8 @@ def session_view(request):
})
-urlpatterns = patterns('',
+urlpatterns = patterns(
+ '',
url(r'^view/$', view),
url(r'^session-view/$', session_view),
)
@@ -142,7 +143,8 @@ class TestAPIRequestFactory(TestCase):
assertion error.
"""
factory = APIRequestFactory()
- self.assertRaises(AssertionError, factory.post,
+ self.assertRaises(
+ AssertionError, factory.post,
path='/view/', data={'example': 1}, format='xml'
)
diff --git a/tests/test_throttling.py b/tests/test_throttling.py
index 8c5eefe9..b0cb2fe7 100644
--- a/tests/test_throttling.py
+++ b/tests/test_throttling.py
@@ -27,7 +27,7 @@ class NonTimeThrottle(BaseThrottle):
if not hasattr(self.__class__, 'called'):
self.__class__.called = True
return True
- return False
+ return False
class MockView(APIView):
@@ -125,36 +125,42 @@ class ThrottlingTests(TestCase):
"""
Ensure for second based throttles.
"""
- self.ensure_response_header_contains_proper_throttle_field(MockView,
- ((0, None),
- (0, None),
- (0, None),
- (0, '1')
- ))
+ self.ensure_response_header_contains_proper_throttle_field(
+ MockView, (
+ (0, None),
+ (0, None),
+ (0, None),
+ (0, '1')
+ )
+ )
def test_minutes_fields(self):
"""
Ensure for minute based throttles.
"""
- self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling,
- ((0, None),
- (0, None),
- (0, None),
- (0, '60')
- ))
+ self.ensure_response_header_contains_proper_throttle_field(
+ MockView_MinuteThrottling, (
+ (0, None),
+ (0, None),
+ (0, None),
+ (0, '60')
+ )
+ )
def test_next_rate_remains_constant_if_followed(self):
"""
If a client follows the recommended next request rate,
the throttling rate should stay constant.
"""
- self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling,
- ((0, None),
- (20, None),
- (40, None),
- (60, None),
- (80, None)
- ))
+ self.ensure_response_header_contains_proper_throttle_field(
+ MockView_MinuteThrottling, (
+ (0, None),
+ (20, None),
+ (40, None),
+ (60, None),
+ (80, None)
+ )
+ )
def test_non_time_throttle(self):
"""
@@ -170,7 +176,7 @@ class ThrottlingTests(TestCase):
self.assertTrue(MockView_NonTimeThrottling.throttle_classes[0].called)
response = MockView_NonTimeThrottling.as_view()(request)
- self.assertFalse('X-Throttle-Wait-Seconds' in response)
+ self.assertFalse('X-Throttle-Wait-Seconds' in response)
class ScopedRateThrottleTests(TestCase):
diff --git a/tests/test_urlizer.py b/tests/test_urlizer.py
index 3dc8e8fe..a77aa22a 100644
--- a/tests/test_urlizer.py
+++ b/tests/test_urlizer.py
@@ -1,7 +1,6 @@
from __future__ import unicode_literals
from django.test import TestCase
from rest_framework.templatetags.rest_framework import urlize_quoted_links
-import sys
class URLizerTests(TestCase):
diff --git a/tox.ini b/tox.ini
index 484053a6..200dad38 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,13 +1,19 @@
[tox]
downloadcache = {toxworkdir}/cache/
envlist =
+ flake8,
py3.4-django1.7,py3.3-django1.7,py3.2-django1.7,py2.7-django1.7,
py3.4-django1.6,py3.3-django1.6,py3.2-django1.6,py2.7-django1.6,py2.6-django1.6,
py3.4-django1.5,py3.3-django1.5,py3.2-django1.5,py2.7-django1.5,py2.6-django1.5,
- py2.7-django1.4,py2.6-django1.4,
+ py2.7-django1.4,py2.6-django1.4
[testenv]
-commands = py.test -q
+commands = ./runtests.py --fast
+
+[testenv:flake8]
+basepython = python2.7
+deps = pytest==2.5.2
+commands = ./runtests.py --lintonly
[testenv:py3.4-django1.7]
basepython = python3.4