mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-29 17:39:48 +03:00
Merge branch 'master' of https://github.com/encode/django-rest-framework into 34
This commit is contained in:
commit
b37eb5f2fa
|
@ -59,7 +59,7 @@ Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recom
|
|||
To run the tests, clone the repository, and then:
|
||||
|
||||
# Setup the virtual environment
|
||||
virtualenv env
|
||||
python3 -m venv env
|
||||
source env/bin/activate
|
||||
pip install django
|
||||
pip install -r requirements.txt
|
||||
|
@ -115,7 +115,7 @@ It's also useful to remember that if you have an outstanding pull request then p
|
|||
|
||||
GitHub's documentation for working on pull requests is [available here][pull-requests].
|
||||
|
||||
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.
|
||||
Always run the tests before submitting pull requests, and ideally run `tox` in order to check that your modifications are compatible on all supported versions of Python and 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 running as you'd expect.
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ The following third party packages are also available.
|
|||
|
||||
## Django OAuth Toolkit
|
||||
|
||||
The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by [Evonove][evonove] and uses the excellent [OAuthLib][oauthlib]. The package is well documented, and well supported and is currently our **recommended package for OAuth 2.0 support**.
|
||||
The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support and works with Python 3.4+. The package is maintained by [Evonove][evonove] and uses the excellent [OAuthLib][oauthlib]. The package is well documented, and well supported and is currently our **recommended package for OAuth 2.0 support**.
|
||||
|
||||
#### Installation & configuration
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ If you want the date field to be entirely hidden from the user, then use `Hidden
|
|||
|
||||
---
|
||||
|
||||
**Note**: The `UniqueFor<Range>Validation` classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
|
||||
**Note**: The `UniqueFor<Range>Validator` classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recom
|
|||
To run the tests, clone the repository, and then:
|
||||
|
||||
# Setup the virtual environment
|
||||
virtualenv env
|
||||
python3 -m venv env
|
||||
source env/bin/activate
|
||||
pip install django
|
||||
pip install -r requirements.txt
|
||||
|
@ -121,7 +121,7 @@ It's also useful to remember that if you have an outstanding pull request then p
|
|||
|
||||
GitHub's documentation for working on pull requests is [available here][pull-requests].
|
||||
|
||||
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.
|
||||
Always run the tests before submitting pull requests, and ideally run `tox` in order to check that your modifications are compatible on all supported versions of Python and 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 running as you'd expect.
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ continued development by **[signing up for a paid plan][funding]**.
|
|||
|
||||
REST framework requires the following:
|
||||
|
||||
* Python (2.7, 3.4, 3.5, 3.6, 3.7)
|
||||
* Python (3.4, 3.5, 3.6, 3.7)
|
||||
* Django (1.11, 2.0, 2.1, 2.2)
|
||||
|
||||
We **highly recommend** and only officially support the latest patch release of
|
||||
|
|
|
@ -14,18 +14,18 @@ The tutorial is fairly in-depth, so you should probably get a cookie and a cup o
|
|||
|
||||
## Setting up a new environment
|
||||
|
||||
Before we do anything else we'll create a new virtual environment, using [virtualenv]. This will make sure our package configuration is kept nicely isolated from any other projects we're working on.
|
||||
Before we do anything else we'll create a new virtual environment, using [venv]. This will make sure our package configuration is kept nicely isolated from any other projects we're working on.
|
||||
|
||||
virtualenv env
|
||||
python3 -m venv env
|
||||
source env/bin/activate
|
||||
|
||||
Now that we're inside a virtualenv environment, we can install our package requirements.
|
||||
Now that we're inside a virtual environment, we can install our package requirements.
|
||||
|
||||
pip install django
|
||||
pip install djangorestframework
|
||||
pip install pygments # We'll be using this for the code highlighting
|
||||
|
||||
**Note:** To exit the virtualenv environment at any time, just type `deactivate`. For more information see the [virtualenv documentation][virtualenv].
|
||||
**Note:** To exit the virtual environment at any time, just type `deactivate`. For more information see the [venv documentation][venv].
|
||||
|
||||
## Getting started
|
||||
|
||||
|
@ -372,7 +372,7 @@ We'll see how we can start to improve things in [part 2 of the tutorial][tut-2].
|
|||
[quickstart]: quickstart.md
|
||||
[repo]: https://github.com/encode/rest-framework-tutorial
|
||||
[sandbox]: https://restframework.herokuapp.com/
|
||||
[virtualenv]: http://www.virtualenv.org/en/latest/index.html
|
||||
[venv]: https://docs.python.org/3/library/venv.html
|
||||
[tut-2]: 2-requests-and-responses.md
|
||||
[httpie]: https://github.com/jakubroztocil/httpie#installation
|
||||
[curl]: https://curl.haxx.se/
|
||||
|
|
|
@ -10,11 +10,11 @@ Create a new Django project named `tutorial`, then start a new app called `quick
|
|||
mkdir tutorial
|
||||
cd tutorial
|
||||
|
||||
# Create a virtualenv to isolate our package dependencies locally
|
||||
virtualenv env
|
||||
# Create a virtual environment to isolate our package dependencies locally
|
||||
python3 -m venv env
|
||||
source env/bin/activate # On Windows use `env\Scripts\activate`
|
||||
|
||||
# Install Django and Django REST framework into the virtualenv
|
||||
# Install Django and Django REST framework into the virtual environment
|
||||
pip install django
|
||||
pip install djangorestframework
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import binascii
|
|||
|
||||
from django.contrib.auth import authenticate, get_user_model
|
||||
from django.middleware.csrf import CsrfViewMiddleware
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import HTTP_HEADER_ENCODING, exceptions
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class AuthTokenConfig(AppConfig):
|
||||
|
|
|
@ -3,7 +3,7 @@ import os
|
|||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class Token(models.Model):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.contrib.auth import authenticate
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ The `compat` module provides support for backwards compatibility with older
|
|||
versions of Django/Python, and compatibility wrappers around optional packages.
|
||||
"""
|
||||
import sys
|
||||
from collections.abc import Mapping, MutableMapping # noqa
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import validators
|
||||
|
|
|
@ -8,8 +8,8 @@ import math
|
|||
|
||||
from django.http import JsonResponse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ungettext
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList
|
||||
|
@ -230,7 +230,7 @@ class Throttled(APIException):
|
|||
wait = math.ceil(wait)
|
||||
detail = ' '.join((
|
||||
detail,
|
||||
force_text(ungettext(self.extra_detail_singular.format(wait=wait),
|
||||
force_text(ngettext(self.extra_detail_singular.format(wait=wait),
|
||||
self.extra_detail_plural.format(wait=wait),
|
||||
wait))))
|
||||
self.wait = wait
|
||||
|
|
|
@ -6,6 +6,7 @@ import inspect
|
|||
import re
|
||||
import uuid
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Mapping
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
@ -25,12 +26,12 @@ from django.utils.formats import localize_input, sanitize_separators
|
|||
from django.utils.functional import lazy
|
||||
from django.utils.ipv6 import clean_ipv6_address
|
||||
from django.utils.timezone import utc
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from pytz.exceptions import InvalidTimeError
|
||||
|
||||
from rest_framework import ISO_8601
|
||||
from rest_framework.compat import (
|
||||
Mapping, MaxLengthValidator, MaxValueValidator, MinLengthValidator,
|
||||
MaxLengthValidator, MaxValueValidator, MinLengthValidator,
|
||||
MinValueValidator, ProhibitNullCharactersValidator
|
||||
)
|
||||
from rest_framework.exceptions import ErrorDetail, ValidationError
|
||||
|
@ -1753,7 +1754,7 @@ class JSONField(Field):
|
|||
try:
|
||||
if self.binary or getattr(data, 'is_json_string', False):
|
||||
if isinstance(data, bytes):
|
||||
data = data.decode('utf-8')
|
||||
data = data.decode()
|
||||
return json.loads(data)
|
||||
else:
|
||||
json.dumps(data)
|
||||
|
@ -1764,10 +1765,7 @@ class JSONField(Field):
|
|||
def to_representation(self, value):
|
||||
if self.binary:
|
||||
value = json.dumps(value)
|
||||
# On python 2.x the return type for json.dumps() is underspecified.
|
||||
# On python 3.x json.dumps() returns unicode strings.
|
||||
if isinstance(value, str):
|
||||
value = bytes(value.encode('utf-8'))
|
||||
value = value.encode()
|
||||
return value
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.db.models.constants import LOOKUP_SEP
|
|||
from django.db.models.sql.constants import ORDER_PATTERN
|
||||
from django.template import loader
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import RemovedInDRF310Warning
|
||||
from rest_framework.compat import (
|
||||
|
|
|
@ -29,7 +29,7 @@ class Command(BaseCommand):
|
|||
|
||||
renderer = self.get_renderer(options['format'])
|
||||
output = renderer.render(schema, renderer_context={})
|
||||
self.stdout.write(output.decode('utf-8'))
|
||||
self.stdout.write(output.decode())
|
||||
|
||||
def get_renderer(self, format):
|
||||
renderer_cls = {
|
||||
|
|
|
@ -10,7 +10,7 @@ from django.core.paginator import InvalidPage
|
|||
from django.core.paginator import Paginator as DjangoPaginator
|
||||
from django.template import loader
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
from rest_framework.exceptions import NotFound
|
||||
|
|
|
@ -80,8 +80,7 @@ class FormParser(BaseParser):
|
|||
"""
|
||||
parser_context = parser_context or {}
|
||||
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
|
||||
data = QueryDict(stream.read(), encoding=encoding)
|
||||
return data
|
||||
return QueryDict(stream.read(), encoding=encoding)
|
||||
|
||||
|
||||
class MultiPartParser(BaseParser):
|
||||
|
@ -202,7 +201,7 @@ class FileUploadParser(BaseParser):
|
|||
|
||||
try:
|
||||
meta = parser_context['request'].META
|
||||
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8'))
|
||||
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode())
|
||||
filename_parm = disposition[1]
|
||||
if 'filename*' in filename_parm:
|
||||
return self.get_encoded_filename(filename_parm)
|
||||
|
|
|
@ -7,7 +7,7 @@ from django.db.models import Manager
|
|||
from django.db.models.query import QuerySet
|
||||
from django.urls import NoReverseMatch, Resolver404, get_script_prefix, resolve
|
||||
from django.utils.encoding import smart_text, uri_to_iri
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.fields import (
|
||||
Field, empty, get_attribute, is_simple_callable, iter_options
|
||||
|
|
|
@ -104,18 +104,11 @@ class JSONRenderer(BaseRenderer):
|
|||
allow_nan=not self.strict, separators=separators
|
||||
)
|
||||
|
||||
# On python 2.x json.dumps() returns bytestrings if ensure_ascii=True,
|
||||
# but if ensure_ascii=False, the return type is underspecified,
|
||||
# and may (or may not) be unicode.
|
||||
# On python 3.x json.dumps() returns unicode strings.
|
||||
if isinstance(ret, str):
|
||||
# We always fully escape \u2028 and \u2029 to ensure we output JSON
|
||||
# that is a strict javascript subset. If bytes were returned
|
||||
# by json.dumps() then we don't have these characters in any case.
|
||||
# that is a strict javascript subset.
|
||||
# See: http://timelessrepo.com/json-isnt-a-javascript-subset
|
||||
ret = ret.replace('\u2028', '\\u2028').replace('\u2029', '\\u2029')
|
||||
return bytes(ret.encode('utf-8'))
|
||||
return ret
|
||||
return ret.encode()
|
||||
|
||||
|
||||
class TemplateHTMLRenderer(BaseRenderer):
|
||||
|
@ -574,7 +567,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
|||
data.pop(name, None)
|
||||
content = renderer.render(data, accepted, context)
|
||||
# Renders returns bytes, but CharField expects a str.
|
||||
content = content.decode('utf-8')
|
||||
content = content.decode()
|
||||
else:
|
||||
content = None
|
||||
|
||||
|
@ -681,7 +674,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
|||
csrf_header_name = csrf_header_name[5:]
|
||||
csrf_header_name = csrf_header_name.replace('_', '-')
|
||||
|
||||
context = {
|
||||
return {
|
||||
'content': self.get_content(renderer, data, accepted_media_type, renderer_context),
|
||||
'code_style': pygments_css(self.code_style),
|
||||
'view': view,
|
||||
|
@ -717,7 +710,6 @@ class BrowsableAPIRenderer(BaseRenderer):
|
|||
'csrf_cookie_name': csrf_cookie_name,
|
||||
'csrf_header_name': csrf_header_name
|
||||
}
|
||||
return context
|
||||
|
||||
def render(self, data, accepted_media_type=None, renderer_context=None):
|
||||
"""
|
||||
|
@ -1032,7 +1024,7 @@ class OpenAPIRenderer(_BaseOpenAPIRenderer):
|
|||
|
||||
def render(self, data, media_type=None, renderer_context=None):
|
||||
structure = self.get_structure(data)
|
||||
return yaml.dump(structure, default_flow_style=False).encode('utf-8')
|
||||
return yaml.dump(structure, default_flow_style=False).encode()
|
||||
|
||||
|
||||
class JSONOpenAPIRenderer(_BaseOpenAPIRenderer):
|
||||
|
@ -1045,4 +1037,4 @@ class JSONOpenAPIRenderer(_BaseOpenAPIRenderer):
|
|||
|
||||
def render(self, data, media_type=None, renderer_context=None):
|
||||
structure = self.get_structure(data)
|
||||
return json.dumps(structure, indent=4).encode('utf-8')
|
||||
return json.dumps(structure, indent=4).encode()
|
||||
|
|
|
@ -184,9 +184,7 @@ class EndpointEnumerator:
|
|||
)
|
||||
api_endpoints.extend(nested_endpoints)
|
||||
|
||||
api_endpoints = sorted(api_endpoints, key=endpoint_ordering)
|
||||
|
||||
return api_endpoints
|
||||
return sorted(api_endpoints, key=endpoint_ordering)
|
||||
|
||||
def get_path_from_regex(self, path_regex):
|
||||
"""
|
||||
|
@ -195,8 +193,7 @@ class EndpointEnumerator:
|
|||
path = simplify_regex(path_regex)
|
||||
|
||||
# Strip Django 2.0 convertors as they are incompatible with uritemplate format
|
||||
path = re.sub(_PATH_PARAMETER_COMPONENT_RE, r'{\g<parameter>}', path)
|
||||
return path
|
||||
return re.sub(_PATH_PARAMETER_COMPONENT_RE, r'{\g<parameter>}', path)
|
||||
|
||||
def should_include_endpoint(self, path, callback):
|
||||
"""
|
||||
|
|
|
@ -11,7 +11,7 @@ from weakref import WeakKeyDictionary
|
|||
|
||||
from django.db import models
|
||||
from django.utils.encoding import force_text, smart_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import exceptions, serializers
|
||||
from rest_framework.compat import coreapi, coreschema, uritemplate
|
||||
|
@ -435,8 +435,7 @@ class AutoSchema(ViewInspector):
|
|||
by_name = OrderedDict((f.name, f) for f in fields)
|
||||
for f in update_with:
|
||||
by_name[f.name] = f
|
||||
fields = list(by_name.values())
|
||||
return fields
|
||||
return list(by_name.values())
|
||||
|
||||
def get_encoding(self, path, method):
|
||||
"""
|
||||
|
|
|
@ -14,6 +14,7 @@ import copy
|
|||
import inspect
|
||||
import traceback
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Mapping
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
|
@ -23,9 +24,9 @@ from django.db.models.fields import Field as DjangoModelField
|
|||
from django.db.models.fields import FieldDoesNotExist
|
||||
from django.utils import timezone
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.compat import Mapping, postgres_fields
|
||||
from rest_framework.compat import postgres_fields
|
||||
from rest_framework.exceptions import ErrorDetail, ValidationError
|
||||
from rest_framework.fields import get_error_detail, set_value
|
||||
from rest_framework.settings import api_settings
|
||||
|
|
|
@ -18,10 +18,9 @@ This module provides the `api_setting` object, that is used to access
|
|||
REST framework settings, checking for user settings first, then falling
|
||||
back to the defaults.
|
||||
"""
|
||||
from importlib import import_module
|
||||
|
||||
from django.conf import settings
|
||||
from django.test.signals import setting_changed
|
||||
from django.utils.module_loading import import_string
|
||||
|
||||
from rest_framework import ISO_8601
|
||||
|
||||
|
@ -175,11 +174,8 @@ def import_from_string(val, setting_name):
|
|||
Attempt to import a class from a string representation.
|
||||
"""
|
||||
try:
|
||||
# Nod to tastypie's use of importlib.
|
||||
module_path, class_name = val.rsplit('.', 1)
|
||||
module = import_module(module_path)
|
||||
return getattr(module, class_name)
|
||||
except (ImportError, AttributeError) as e:
|
||||
return import_string(val)
|
||||
except ImportError as e:
|
||||
msg = "Could not import '%s' for API setting '%s'. %s: %s." % (val, setting_name, e.__class__.__name__, e)
|
||||
raise ImportError(msg)
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<div class="modal-body">
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
<h4 class="text-center">You are logged in as {{ user.username }}.</h4>
|
||||
<h4 class="text-center">You are logged in as {{ user.get_username }}.</h4>
|
||||
{% else %}
|
||||
|
||||
<div class="text-center">
|
||||
|
|
|
@ -47,7 +47,7 @@ class JSONEncoder(json.JSONEncoder):
|
|||
return tuple(obj)
|
||||
elif isinstance(obj, bytes):
|
||||
# Best-effort for binary blobs. See #4187.
|
||||
return obj.decode('utf-8')
|
||||
return obj.decode()
|
||||
elif hasattr(obj, 'tolist'):
|
||||
# Numpy arrays and array scalars.
|
||||
return obj.tolist()
|
||||
|
|
|
@ -41,9 +41,7 @@ def smart_repr(value):
|
|||
# <django.core.validators.RegexValidator object at 0x1047af050>
|
||||
# Should be presented as
|
||||
# <django.core.validators.RegexValidator object>
|
||||
value = re.sub(' at 0x[0-9A-Fa-f]{4,32}>', '>', value)
|
||||
|
||||
return value
|
||||
return re.sub(' at 0x[0-9A-Fa-f]{4,32}>', '>', value)
|
||||
|
||||
|
||||
def field_repr(field, force_many=False):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from collections import OrderedDict
|
||||
from collections.abc import MutableMapping
|
||||
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
from rest_framework.compat import MutableMapping
|
||||
from rest_framework.utils import json
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ object creation, and makes it possible to switch between using the implicit
|
|||
`ModelSerializer` class and an equivalent explicit `Serializer` class.
|
||||
"""
|
||||
from django.db import DataError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.utils.representation import smart_repr
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import re
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import exceptions
|
||||
from rest_framework.compat import unicode_http_header
|
||||
|
|
|
@ -11,7 +11,7 @@ PYTEST_ARGS = {
|
|||
|
||||
FLAKE8_ARGS = ['rest_framework', 'tests']
|
||||
|
||||
ISORT_ARGS = ['--recursive', '--check-only', '--diff', '-o' 'uritemplate', '-p', 'tests', 'rest_framework', 'tests']
|
||||
ISORT_ARGS = ['--recursive', '--check-only', '--diff', 'rest_framework', 'tests']
|
||||
|
||||
|
||||
def exit_on_failure(ret, message=None):
|
||||
|
|
|
@ -14,8 +14,8 @@ skip=.tox
|
|||
atomic=true
|
||||
multi_line_output=5
|
||||
known_standard_library=types
|
||||
known_third_party=pytest,_pytest,django,pytz
|
||||
known_first_party=rest_framework
|
||||
known_third_party=pytest,_pytest,django,pytz,uritemplate
|
||||
known_first_party=rest_framework,tests
|
||||
|
||||
[coverage:run]
|
||||
# NOTE: source is ignored with pytest-cov (but uses the same).
|
||||
|
|
|
@ -183,7 +183,7 @@ class SessionAuthTests(TestCase):
|
|||
cf. [#1810](https://github.com/encode/django-rest-framework/pull/1810)
|
||||
"""
|
||||
response = self.csrf_client.get('/auth/login/')
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert '<label for="id_username">Username:</label>' in content
|
||||
|
||||
def test_post_form_session_auth_failing_csrf(self):
|
||||
|
|
|
@ -24,18 +24,18 @@ class DropdownWithAuthTests(TestCase):
|
|||
def test_name_shown_when_logged_in(self):
|
||||
self.client.login(username=self.username, password=self.password)
|
||||
response = self.client.get('/')
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert 'john' in content
|
||||
|
||||
def test_logout_shown_when_logged_in(self):
|
||||
self.client.login(username=self.username, password=self.password)
|
||||
response = self.client.get('/')
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert '>Log out<' in content
|
||||
|
||||
def test_login_shown_when_logged_out(self):
|
||||
response = self.client.get('/')
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert '>Log in<' in content
|
||||
|
||||
|
||||
|
@ -59,16 +59,16 @@ class NoDropdownWithoutAuthTests(TestCase):
|
|||
def test_name_shown_when_logged_in(self):
|
||||
self.client.login(username=self.username, password=self.password)
|
||||
response = self.client.get('/')
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert 'john' in content
|
||||
|
||||
def test_dropdown_not_shown_when_logged_in(self):
|
||||
self.client.login(username=self.username, password=self.password)
|
||||
response = self.client.get('/')
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert '<li class="dropdown">' not in content
|
||||
|
||||
def test_dropdown_not_shown_when_logged_out(self):
|
||||
response = self.client.get('/')
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert '<li class="dropdown">' not in content
|
||||
|
|
|
@ -34,7 +34,7 @@ class DropdownWithAuthTests(TestCase):
|
|||
def test_login(self):
|
||||
response = self.client.get('/api/')
|
||||
assert 200 == response.status_code
|
||||
content = response.content.decode('utf-8')
|
||||
content = response.content.decode()
|
||||
assert 'form action="/api/"' in content
|
||||
assert 'input name="nested.one"' in content
|
||||
assert 'input name="nested.two"' in content
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class RESTFrameworkModel(models.Model):
|
||||
|
|
|
@ -202,8 +202,7 @@ class ActionDecoratorTestCase(TestCase):
|
|||
def method():
|
||||
raise NotImplementedError
|
||||
|
||||
# Python 2.x compatibility - cast __name__ to str
|
||||
method.__name__ = str(name)
|
||||
method.__name__ = name
|
||||
getattr(test_action.mapping, name)(method)
|
||||
|
||||
# ensure the mapping returns the correct method name
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.test import RequestFactory, TestCase
|
||||
from django.utils import translation
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.exceptions import (
|
||||
APIException, ErrorDetail, Throttled, _get_error_details, bad_request,
|
||||
|
|
|
@ -164,7 +164,7 @@ class TestRootView(TestCase):
|
|||
request = factory.post('/', data, HTTP_ACCEPT='text/html')
|
||||
response = self.view(request).render()
|
||||
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
|
||||
assert expected_error in response.rendered_content.decode('utf-8')
|
||||
assert expected_error in response.rendered_content.decode()
|
||||
|
||||
|
||||
EXPECTED_QUERIES_FOR_PUT = 2
|
||||
|
@ -311,7 +311,7 @@ class TestInstanceView(TestCase):
|
|||
request = factory.put('/', data, HTTP_ACCEPT='text/html')
|
||||
response = self.view(request, pk=1).render()
|
||||
expected_error = '<span class="help-block">Ensure this field has no more than 100 characters.</span>'
|
||||
assert expected_error in response.rendered_content.decode('utf-8')
|
||||
assert expected_error in response.rendered_content.decode()
|
||||
|
||||
|
||||
class TestFKInstanceView(TestCase):
|
||||
|
@ -538,7 +538,7 @@ class TestFilterBackendAppliedToViews(TestCase):
|
|||
view = DynamicSerializerView.as_view()
|
||||
request = factory.get('/')
|
||||
response = view(request).render()
|
||||
content = response.content.decode('utf8')
|
||||
content = response.content.decode()
|
||||
assert 'field_b' in content
|
||||
assert 'field_a' not in content
|
||||
|
||||
|
|
|
@ -40,9 +40,7 @@ class TestFileUploadParser(TestCase):
|
|||
def setUp(self):
|
||||
class MockRequest:
|
||||
pass
|
||||
self.stream = io.BytesIO(
|
||||
"Test text file".encode('utf-8')
|
||||
)
|
||||
self.stream = io.BytesIO(b"Test text file")
|
||||
request = MockRequest()
|
||||
request.upload_handlers = (MemoryFileUploadHandler(),)
|
||||
request.META = {
|
||||
|
@ -128,7 +126,7 @@ class TestFileUploadParser(TestCase):
|
|||
|
||||
class TestJSONParser(TestCase):
|
||||
def bytes(self, value):
|
||||
return io.BytesIO(value.encode('utf-8'))
|
||||
return io.BytesIO(value.encode())
|
||||
|
||||
def test_float_strictness(self):
|
||||
parser = JSONParser()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import re
|
||||
from collections import OrderedDict
|
||||
from collections.abc import MutableMapping
|
||||
|
||||
import pytest
|
||||
from django.conf.urls import include, url
|
||||
|
@ -9,10 +10,10 @@ from django.http.request import HttpRequest
|
|||
from django.template import loader
|
||||
from django.test import TestCase, override_settings
|
||||
from django.utils.safestring import SafeText
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import permissions, serializers, status
|
||||
from rest_framework.compat import MutableMapping, coreapi
|
||||
from rest_framework.compat import coreapi
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.renderers import (
|
||||
AdminRenderer, BaseRenderer, BrowsableAPIRenderer, DocumentationRenderer,
|
||||
|
@ -75,8 +76,7 @@ class MockView(APIView):
|
|||
renderer_classes = (RendererA, RendererB)
|
||||
|
||||
def get(self, request, **kwargs):
|
||||
response = Response(DUMMYCONTENT, status=DUMMYSTATUS)
|
||||
return response
|
||||
return Response(DUMMYCONTENT, status=DUMMYSTATUS)
|
||||
|
||||
|
||||
class MockGETView(APIView):
|
||||
|
@ -303,14 +303,14 @@ class JSONRendererTests(TestCase):
|
|||
o = DummyTestModel.objects.create(name='dummy')
|
||||
qs = DummyTestModel.objects.values('id', 'name')
|
||||
ret = JSONRenderer().render(qs)
|
||||
data = json.loads(ret.decode('utf-8'))
|
||||
data = json.loads(ret.decode())
|
||||
self.assertEqual(data, [{'id': o.id, 'name': o.name}])
|
||||
|
||||
def test_render_queryset_values_list(self):
|
||||
o = DummyTestModel.objects.create(name='dummy')
|
||||
qs = DummyTestModel.objects.values_list('id', 'name')
|
||||
ret = JSONRenderer().render(qs)
|
||||
data = json.loads(ret.decode('utf-8'))
|
||||
data = json.loads(ret.decode())
|
||||
self.assertEqual(data, [[o.id, o.name]])
|
||||
|
||||
def test_render_dict_abc_obj(self):
|
||||
|
@ -340,7 +340,7 @@ class JSONRendererTests(TestCase):
|
|||
x['key'] = 'string value'
|
||||
x[2] = 3
|
||||
ret = JSONRenderer().render(x)
|
||||
data = json.loads(ret.decode('utf-8'))
|
||||
data = json.loads(ret.decode())
|
||||
self.assertEqual(data, {'key': 'string value', '2': 3})
|
||||
|
||||
def test_render_obj_with_getitem(self):
|
||||
|
@ -380,7 +380,7 @@ class JSONRendererTests(TestCase):
|
|||
renderer = JSONRenderer()
|
||||
content = renderer.render(obj, 'application/json')
|
||||
# Fix failing test case which depends on version of JSON library.
|
||||
self.assertEqual(content.decode('utf-8'), _flat_repr)
|
||||
self.assertEqual(content.decode(), _flat_repr)
|
||||
|
||||
def test_with_content_type_args(self):
|
||||
"""
|
||||
|
@ -389,7 +389,7 @@ class JSONRendererTests(TestCase):
|
|||
obj = {'foo': ['bar', 'baz']}
|
||||
renderer = JSONRenderer()
|
||||
content = renderer.render(obj, 'application/json; indent=2')
|
||||
self.assertEqual(strip_trailing_whitespace(content.decode('utf-8')), _indented_repr)
|
||||
self.assertEqual(strip_trailing_whitespace(content.decode()), _indented_repr)
|
||||
|
||||
|
||||
class UnicodeJSONRendererTests(TestCase):
|
||||
|
@ -400,7 +400,7 @@ class UnicodeJSONRendererTests(TestCase):
|
|||
obj = {'countries': ['United Kingdom', 'France', 'España']}
|
||||
renderer = JSONRenderer()
|
||||
content = renderer.render(obj, 'application/json')
|
||||
self.assertEqual(content, '{"countries":["United Kingdom","France","España"]}'.encode('utf-8'))
|
||||
self.assertEqual(content, '{"countries":["United Kingdom","France","España"]}'.encode())
|
||||
|
||||
def test_u2028_u2029(self):
|
||||
# The \u2028 and \u2029 characters should be escaped,
|
||||
|
@ -409,7 +409,7 @@ class UnicodeJSONRendererTests(TestCase):
|
|||
obj = {'should_escape': '\u2028\u2029'}
|
||||
renderer = JSONRenderer()
|
||||
content = renderer.render(obj, 'application/json')
|
||||
self.assertEqual(content, '{"should_escape":"\\u2028\\u2029"}'.encode('utf-8'))
|
||||
self.assertEqual(content, '{"should_escape":"\\u2028\\u2029"}'.encode())
|
||||
|
||||
|
||||
class AsciiJSONRendererTests(TestCase):
|
||||
|
@ -422,7 +422,7 @@ class AsciiJSONRendererTests(TestCase):
|
|||
obj = {'countries': ['United Kingdom', 'France', 'España']}
|
||||
renderer = AsciiJSONRenderer()
|
||||
content = renderer.render(obj, 'application/json')
|
||||
self.assertEqual(content, '{"countries":["United Kingdom","France","Espa\\u00f1a"]}'.encode('utf-8'))
|
||||
self.assertEqual(content, '{"countries":["United Kingdom","France","Espa\\u00f1a"]}'.encode())
|
||||
|
||||
|
||||
# Tests for caching issue, #346
|
||||
|
@ -653,9 +653,9 @@ class BrowsableAPIRendererTests(URLPatternsTestCase):
|
|||
|
||||
def test_extra_actions_dropdown(self):
|
||||
resp = self.client.get('/api/examples/', HTTP_ACCEPT='text/html')
|
||||
assert 'id="extra-actions-menu"' in resp.content.decode('utf-8')
|
||||
assert '/api/examples/list_action/' in resp.content.decode('utf-8')
|
||||
assert '>Extra list action<' in resp.content.decode('utf-8')
|
||||
assert 'id="extra-actions-menu"' in resp.content.decode()
|
||||
assert '/api/examples/list_action/' in resp.content.decode()
|
||||
assert '>Extra list action<' in resp.content.decode()
|
||||
|
||||
|
||||
class AdminRendererTests(TestCase):
|
||||
|
|
|
@ -438,13 +438,13 @@ class TestEmptyPrefix(URLPatternsTestCase, TestCase):
|
|||
def test_empty_prefix_list(self):
|
||||
response = self.client.get('/empty-prefix/')
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content.decode('utf-8')) == [{'uuid': '111', 'text': 'First'},
|
||||
assert json.loads(response.content.decode()) == [{'uuid': '111', 'text': 'First'},
|
||||
{'uuid': '222', 'text': 'Second'}]
|
||||
|
||||
def test_empty_prefix_detail(self):
|
||||
response = self.client.get('/empty-prefix/1/')
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content.decode('utf-8')) == {'uuid': '111', 'text': 'First'}
|
||||
assert json.loads(response.content.decode()) == {'uuid': '111', 'text': 'First'}
|
||||
|
||||
|
||||
class TestRegexUrlPath(URLPatternsTestCase, TestCase):
|
||||
|
@ -456,14 +456,14 @@ class TestRegexUrlPath(URLPatternsTestCase, TestCase):
|
|||
kwarg = '1234'
|
||||
response = self.client.get('/regex/list/{}/'.format(kwarg))
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content.decode('utf-8')) == {'kwarg': kwarg}
|
||||
assert json.loads(response.content.decode()) == {'kwarg': kwarg}
|
||||
|
||||
def test_regex_url_path_detail(self):
|
||||
pk = '1'
|
||||
kwarg = '1234'
|
||||
response = self.client.get('/regex/{}/detail/{}/'.format(pk, kwarg))
|
||||
assert response.status_code == 200
|
||||
assert json.loads(response.content.decode('utf-8')) == {'pk': pk, 'kwarg': kwarg}
|
||||
assert json.loads(response.content.decode()) == {'pk': pk, 'kwarg': kwarg}
|
||||
|
||||
|
||||
class TestViewInitkwargs(URLPatternsTestCase, TestCase):
|
||||
|
|
|
@ -1358,4 +1358,4 @@ def test_schema_handles_exception():
|
|||
response = schema_view(request)
|
||||
response.render()
|
||||
assert response.status_code == 403
|
||||
assert "You do not have permission to perform this action." in str(response.content)
|
||||
assert b"You do not have permission to perform this action." in response.content
|
||||
|
|
|
@ -2,12 +2,12 @@ import inspect
|
|||
import pickle
|
||||
import re
|
||||
from collections import ChainMap
|
||||
from collections.abc import Mapping
|
||||
|
||||
import pytest
|
||||
from django.db import models
|
||||
|
||||
from rest_framework import exceptions, fields, relations, serializers
|
||||
from rest_framework.compat import Mapping
|
||||
from rest_framework.fields import Field
|
||||
|
||||
from .models import (
|
||||
|
@ -386,23 +386,6 @@ class TestIncorrectlyConfigured:
|
|||
)
|
||||
|
||||
|
||||
class TestUnicodeRepr:
|
||||
def test_repr(self):
|
||||
class ExampleSerializer(serializers.Serializer):
|
||||
example = serializers.CharField()
|
||||
|
||||
class ExampleObject:
|
||||
def __init__(self):
|
||||
self.example = '한국'
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.example)
|
||||
|
||||
instance = ExampleObject()
|
||||
serializer = ExampleSerializer(instance)
|
||||
repr(serializer) # Should not error.
|
||||
|
||||
|
||||
class TestNotRequiredOutput:
|
||||
def test_not_required_output_for_dict(self):
|
||||
"""
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.shortcuts import render
|
|||
def test_base_template_with_context():
|
||||
context = {'request': True, 'csrf_token': 'TOKEN'}
|
||||
result = render({}, 'rest_framework/base.html', context=context)
|
||||
assert re.search(r'\bcsrfToken: "TOKEN"', result.content.decode('utf-8'))
|
||||
assert re.search(r'\bcsrfToken: "TOKEN"', result.content.decode())
|
||||
|
||||
|
||||
def test_base_template_with_no_context():
|
||||
|
@ -14,4 +14,4 @@ def test_base_template_with_no_context():
|
|||
# so it can be easily extended.
|
||||
result = render({}, 'rest_framework/base.html')
|
||||
# note that this response will not include a valid CSRF token
|
||||
assert re.search(r'\bcsrfToken: ""', result.content.decode('utf-8'))
|
||||
assert re.search(r'\bcsrfToken: ""', result.content.decode())
|
||||
|
|
Loading…
Reference in New Issue
Block a user