From bc075212cb05a52a2b2b2b4c909cfbd03c7ebd8e Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Mon, 24 May 2021 09:47:44 +0200 Subject: [PATCH 001/228] Fix running runtests.py without arguments. (#7954) Regression in aa12a5f967705f70b1dbe457bb2396d106e3570b. --- runtests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtests.py b/runtests.py index c340b55d8..98f34c067 100755 --- a/runtests.py +++ b/runtests.py @@ -45,5 +45,7 @@ if __name__ == "__main__": # `runtests.py TestCase [flags]` # `runtests.py test_function [flags]` pytest_args = ['tests', '-k', pytest_args[0]] + pytest_args[1:] + else: + pytest_args = [] sys.exit(pytest.main(pytest_args)) From 9d149f23177055b3b1ea12cf62de0d669739b544 Mon Sep 17 00:00:00 2001 From: Abduaziz <68025869+AbduazizZiyodov@users.noreply.github.com> Date: Wed, 2 Jun 2021 14:02:11 +0500 Subject: [PATCH 002/228] Fixed some punctuation marks & small typos (#8015) --- docs/api-guide/authentication.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 4497f73bd..60544079f 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -11,7 +11,7 @@ source: Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The [permission] and [throttling] policies can then use those credentials to determine if the request should be permitted. -REST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes. +REST framework provides several authentication schemes out of the box, and also allows you to implement custom schemes. Authentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed. @@ -23,7 +23,7 @@ The `request.auth` property is used for any additional authentication informatio **Note:** Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with. -For information on how to setup the permission polices for your API please see the [permissions documentation][permission]. +For information on how to set up the permission policies for your API please see the [permissions documentation][permission]. --- @@ -195,7 +195,7 @@ If you've already created some users, you can generate tokens for all existing u ##### By exposing an api endpoint -When using `TokenAuthentication`, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the `obtain_auth_token` view to your URLconf: +When using `TokenAuthentication`, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behaviour. To use it, add the `obtain_auth_token` view to your URLconf: from rest_framework.authtoken import views urlpatterns += [ @@ -210,7 +210,7 @@ The `obtain_auth_token` view will return a JSON response when valid `username` a Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. -By default there are no permissions or throttling applied to the `obtain_auth_token` view. If you do wish to apply throttling you'll need to override the view class, +By default, there are no permissions or throttling applied to the `obtain_auth_token` view. If you do wish to apply to throttle you'll need to override the view class, and include them using the `throttle_classes` attribute. If you need a customized version of the `obtain_auth_token` view, you can do so by subclassing the `ObtainAuthToken` view class, and using that in your url conf instead. @@ -244,7 +244,7 @@ And in your `urls.py`: ##### With Django admin -It is also possible to create Tokens manually through admin interface. In case you are using a large user base, we recommend that you monkey patch the `TokenAdmin` class to customize it to your needs, more specifically by declaring the `user` field as `raw_field`. +It is also possible to create Tokens manually through the admin interface. In case you are using a large user base, we recommend that you monkey patch the `TokenAdmin` class customize it to your needs, more specifically by declaring the `user` field as `raw_field`. `your_app/admin.py`: @@ -279,11 +279,11 @@ If successfully authenticated, `SessionAuthentication` provides the following cr Unauthenticated responses that are denied permission will result in an `HTTP 403 Forbidden` response. -If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `PATCH`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details. +If you're using an AJAX-style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `PATCH`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details. **Warning**: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected. -CSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied. +CSRF validation in REST framework works slightly differently from standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied. ## RemoteUserAuthentication @@ -316,7 +316,7 @@ In some circumstances instead of returning `None`, you may want to raise an `Aut Typically the approach you should take is: * If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked. -* If authentication is attempted but fails, raise a `AuthenticationFailed` exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes. +* If authentication is attempted but fails, raise an `AuthenticationFailed` exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes. You *may* also override the `.authenticate_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response. @@ -353,7 +353,7 @@ The following example will authenticate any incoming request as the user given b # Third party packages -The following third party packages are also available. +The following third-party packages are also available. ## Django OAuth Toolkit @@ -384,7 +384,7 @@ For more details see the [Django REST framework - Getting started][django-oauth- The [Django REST framework OAuth][django-rest-framework-oauth] package provides both OAuth1 and OAuth2 support for REST framework. -This package was previously included directly in REST framework but is now supported and maintained as a third party package. +This package was previously included directly in the REST framework but is now supported and maintained as a third-party package. #### Installation & configuration @@ -408,7 +408,7 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a ## Djoser -[Djoser][djoser] library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system. +[Djoser][djoser] library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and uses token-based authentication. This is ready to use REST implementation of the Django authentication system. ## django-rest-auth / dj-rest-auth @@ -426,15 +426,15 @@ There are currently two forks of this project. ## django-rest-knox -[Django-rest-knox][django-rest-knox] library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into). +[Django-rest-knox][django-rest-knox] library provides models and views to handle token-based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into). ## drfpasswordless -[drfpasswordless][drfpasswordless] adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's own TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number. +[drfpasswordless][drfpasswordless] adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number. ## django-rest-authemail -[django-rest-authemail][django-rest-authemail] provides a RESTful API interface for user signup and authentication. Email addresses are used for authentication, rather than usernames. API endpoints are available for signup, signup email verification, login, logout, password reset, password reset verification, email change, email change verification, password change, and user detail. A fully-functional example project and detailed instructions are included. +[django-rest-authemail][django-rest-authemail] provides a RESTful API interface for user signup and authentication. Email addresses are used for authentication, rather than usernames. API endpoints are available for signup, signup email verification, login, logout, password reset, password reset verification, email change, email change verification, password change, and user detail. A fully functional example project and detailed instructions are included. ## Django-Rest-Durin From 61e7a993bd0702d30e3049179000bc7c5f284781 Mon Sep 17 00:00:00 2001 From: Ian De Bie Date: Mon, 7 Jun 2021 04:30:23 -0500 Subject: [PATCH 003/228] fix comments by using correct css comment syntax (#8019) these intended comments were causing errors in sonarqube scans due to using wrong css comment syntax --- rest_framework/static/rest_framework/docs/css/base.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rest_framework/static/rest_framework/docs/css/base.css b/rest_framework/static/rest_framework/docs/css/base.css index 0be2bafa9..06b240c52 100644 --- a/rest_framework/static/rest_framework/docs/css/base.css +++ b/rest_framework/static/rest_framework/docs/css/base.css @@ -7,15 +7,15 @@ h1 { } pre.highlight code * { - white-space: nowrap; // this sets all children inside to nowrap + white-space: nowrap; /* this sets all children inside to nowrap */ } pre.highlight { - overflow-x: auto; // this sets the scrolling in x + overflow-x: auto; /* this sets the scrolling in x */ } pre.highlight code { - white-space: pre; // forces to respect
 formatting
+  white-space: pre;       /* forces  to respect 
 formatting */
 }
 
 .main-container {

From 24a938abaadd98b5482bec33defd285625842342 Mon Sep 17 00:00:00 2001
From: Finn Gundlach 
Date: Wed, 16 Jun 2021 15:53:29 +0200
Subject: [PATCH 004/228] Update documentation to include Django 3.2 as
 supported version (#8037)

---
 README.md     | 2 +-
 docs/index.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index ff76a5525..fce275256 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ There is a live example API for testing purposes, [available here][sandbox].
 # Requirements
 
 * Python (3.5, 3.6, 3.7, 3.8, 3.9)
-* Django (2.2, 3.0, 3.1)
+* Django (2.2, 3.0, 3.1, 3.2)
 
 We **highly recommend** and only officially support the latest patch release of
 each Python and Django series.
diff --git a/docs/index.md b/docs/index.md
index 530813684..28e330250 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -84,7 +84,7 @@ continued development by **[signing up for a paid plan][funding]**.
 REST framework requires the following:
 
 * Python (3.5, 3.6, 3.7, 3.8, 3.9)
-* Django (2.2, 3.0, 3.1)
+* Django (2.2, 3.0, 3.1, 3.2)
 
 We **highly recommend** and only officially support the latest patch release of
 each Python and Django series.

From e92016ac2e926483e05e296558fc3d1ea3279625 Mon Sep 17 00:00:00 2001
From: Adam Johnson 
Date: Mon, 21 Jun 2021 11:33:43 +0100
Subject: [PATCH 005/228] Stop ignoring test outcome for Django 3.2 (#7927)

---
 requirements/requirements-optionals.txt |  2 +-
 setup.py                                |  1 +
 tox.ini                                 | 12 ------------
 3 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/requirements/requirements-optionals.txt b/requirements/requirements-optionals.txt
index 4cb0e54f4..75b9ab4d6 100644
--- a/requirements/requirements-optionals.txt
+++ b/requirements/requirements-optionals.txt
@@ -2,7 +2,7 @@
 coreapi==2.3.1
 coreschema==0.0.4
 django-filter>=2.4.0,<3.0
-django-guardian>=2.3.0,<2.4
+django-guardian>=2.4.0,<2.5
 markdown==3.3;python_version>="3.6"
 markdown==3.2.2;python_version=="3.5"
 psycopg2-binary>=2.8.5,<2.9
diff --git a/setup.py b/setup.py
index e2a1c0222..5fd4df20d 100755
--- a/setup.py
+++ b/setup.py
@@ -92,6 +92,7 @@ setup(
         'Framework :: Django :: 2.2',
         'Framework :: Django :: 3.0',
         'Framework :: Django :: 3.1',
+        'Framework :: Django :: 3.2',
         'Intended Audience :: Developers',
         'License :: OSI Approved :: BSD License',
         'Operating System :: OS Independent',
diff --git a/tox.ini b/tox.ini
index bf4de90d0..f23486a68 100644
--- a/tox.ini
+++ b/tox.ini
@@ -50,18 +50,6 @@ deps =
        -rrequirements/requirements-testing.txt
        -rrequirements/requirements-documentation.txt
 
-[testenv:py36-django32]
-ignore_outcome = true
-
-[testenv:py37-django32]
-ignore_outcome = true
-
-[testenv:py38-django32]
-ignore_outcome = true
-
-[testenv:py39-django32]
-ignore_outcome = true
-
 [testenv:py38-djangomain]
 ignore_outcome = true
 

From c8a9c856c25a1a360a91d2c7bc11e0dacfb9c3a4 Mon Sep 17 00:00:00 2001
From: Burak Kadir Er 
Date: Mon, 28 Jun 2021 14:51:21 +0300
Subject: [PATCH 006/228] fix a small typo (#8060)

---
 docs/api-guide/renderers.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md
index 954fb3bb9..7dbc5eee8 100644
--- a/docs/api-guide/renderers.md
+++ b/docs/api-guide/renderers.md
@@ -105,7 +105,7 @@ The TemplateHTMLRenderer will create a `RequestContext`, using the `response.dat
 
 ---
 
-**Note:** When used with a view that makes use of a serializer the `Response` sent for rendering may not be a dictionay and will need to be wrapped in a dict before returning to allow the TemplateHTMLRenderer to render it. For example:
+**Note:** When used with a view that makes use of a serializer the `Response` sent for rendering may not be a dictionary and will need to be wrapped in a dict before returning to allow the TemplateHTMLRenderer to render it. For example:
 
 ```
 response.data = {'results': response.data}

From d2977cff989f9b14f402ecf1e9235ee3d110977b Mon Sep 17 00:00:00 2001
From: Nikita Sobolev 
Date: Mon, 28 Jun 2021 15:07:41 +0300
Subject: [PATCH 007/228] Fixes inconsistent headers in `serializer` docs
 (#8056)

Some headers were using `.`, some - were not.
Now, all of them are the same with `.`, because it was easier to fix.
---
 docs/api-guide/serializers.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md
index f05fe7e7e..13c0c8710 100644
--- a/docs/api-guide/serializers.md
+++ b/docs/api-guide/serializers.md
@@ -605,13 +605,13 @@ For `ModelSerializer` this defaults to `PrimaryKeyRelatedField`.
 
 For `HyperlinkedModelSerializer` this defaults to `serializers.HyperlinkedRelatedField`.
 
-### `serializer_url_field`
+### `.serializer_url_field`
 
 The serializer field class that should be used for any `url` field on the serializer.
 
 Defaults to `serializers.HyperlinkedIdentityField`
 
-### `serializer_choice_field`
+### `.serializer_choice_field`
 
 The serializer field class that should be used for any choice fields on the serializer.
 

From 98e56e0327596db352b35fa3b3dc8355dc9bd030 Mon Sep 17 00:00:00 2001
From: Evgeny Panfilov 
Date: Thu, 1 Jul 2021 17:04:44 +0300
Subject: [PATCH 008/228] fix empty string as a value for a validated
 DecimalField (#8064) (#8067)

---
 rest_framework/fields.py |  8 +++++---
 tests/test_fields.py     | 24 ++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index e4be54751..bedc02b94 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -1046,6 +1046,11 @@ class DecimalField(Field):
                 'Invalid rounding option %s. Valid values for rounding are: %s' % (rounding, valid_roundings))
         self.rounding = rounding
 
+    def validate_empty_values(self, data):
+        if smart_str(data).strip() == '' and self.allow_null:
+            return (True, None)
+        return super().validate_empty_values(data)
+
     def to_internal_value(self, data):
         """
         Validate that the input is a decimal number and return a Decimal
@@ -1063,9 +1068,6 @@ class DecimalField(Field):
         try:
             value = decimal.Decimal(data)
         except decimal.DecimalException:
-            if data == '' and self.allow_null:
-                return None
-
             self.fail('invalid')
 
         if value.is_nan():
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 78a9effb8..d99ca9c40 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -1163,6 +1163,30 @@ class TestMinMaxDecimalField(FieldValues):
     )
 
 
+class TestAllowEmptyStrDecimalFieldWithValidators(FieldValues):
+    """
+    Check that empty string ('', ' ') is acceptable value for the DecimalField
+    if allow_null=True and there are max/min validators
+    """
+    valid_inputs = {
+        None: None,
+        '': None,
+        ' ': None,
+        '  ': None,
+        5: Decimal('5'),
+        '0': Decimal('0'),
+        '10': Decimal('10'),
+    }
+    invalid_inputs = {
+        -1: ['Ensure this value is greater than or equal to 0.'],
+        11: ['Ensure this value is less than or equal to 10.'],
+    }
+    outputs = {
+        None: '',
+    }
+    field = serializers.DecimalField(max_digits=3, decimal_places=1, allow_null=True, min_value=0, max_value=10)
+
+
 class TestNoMaxDigitsDecimalField(FieldValues):
     field = serializers.DecimalField(
         max_value=100, min_value=0,

From b215375125980114482779b36dd825775ef7e482 Mon Sep 17 00:00:00 2001
From: Nikhil Benesch 
Date: Fri, 6 Aug 2021 05:10:58 -0400
Subject: [PATCH 009/228] Propagate nullability in ModelSerializer (#8116)

Propagate the nullability of underlying model fields in ModelSerializer
when those fields are marked as read only. This ensures the correct
generation of OpenAPI schemas.

Fix #8041.
---
 rest_framework/serializers.py |  5 ++---
 tests/schemas/test_openapi.py | 19 +++++++++++++++++++
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 49eec8259..9ea57f1af 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -1326,9 +1326,8 @@ class ModelSerializer(Serializer):
         """
         if extra_kwargs.get('read_only', False):
             for attr in [
-                'required', 'default', 'allow_blank', 'allow_null',
-                'min_length', 'max_length', 'min_value', 'max_value',
-                'validators', 'queryset'
+                'required', 'default', 'allow_blank', 'min_length',
+                'max_length', 'min_value', 'max_value', 'validators', 'queryset'
             ]:
                 kwargs.pop(attr, None)
 
diff --git a/tests/schemas/test_openapi.py b/tests/schemas/test_openapi.py
index aef20670e..daa035a3f 100644
--- a/tests/schemas/test_openapi.py
+++ b/tests/schemas/test_openapi.py
@@ -2,6 +2,7 @@ import uuid
 import warnings
 
 import pytest
+from django.db import models
 from django.test import RequestFactory, TestCase, override_settings
 from django.urls import path
 from django.utils.translation import gettext_lazy as _
@@ -110,6 +111,24 @@ class TestFieldMapping(TestCase):
         assert data['properties']['default_false']['default'] is False, "default must be false"
         assert 'default' not in data['properties']['without_default'], "default must not be defined"
 
+    def test_nullable_fields(self):
+        class Model(models.Model):
+            rw_field = models.CharField(null=True)
+            ro_field = models.CharField(null=True)
+
+        class Serializer(serializers.ModelSerializer):
+            class Meta:
+                model = Model
+                fields = ["rw_field", "ro_field"]
+                read_only_fields = ["ro_field"]
+
+        inspector = AutoSchema()
+
+        data = inspector.map_serializer(Serializer())
+        assert data['properties']['rw_field']['nullable'], "rw_field nullable must be true"
+        assert data['properties']['ro_field']['nullable'], "ro_field nullable must be true"
+        assert data['properties']['ro_field']['readOnly'], "ro_field read_only must be true"
+
 
 @pytest.mark.skipif(uritemplate is None, reason='uritemplate not installed.')
 class TestOperationIntrospection(TestCase):

From fdb49314754ff13d91c6eec7ccdb8ece52bea9eb Mon Sep 17 00:00:00 2001
From: Aarni Koskela 
Date: Fri, 6 Aug 2021 12:14:52 +0300
Subject: [PATCH 010/228] Make Field constructors keyword-only (#7632)

---
 rest_framework/fields.py | 46 ++++++++++++++++++++--------------------
 tests/test_fields.py     |  5 +++++
 2 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index bedc02b94..5cafed555 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -320,7 +320,7 @@ class Field:
     default_empty_html = empty
     initial = None
 
-    def __init__(self, read_only=False, write_only=False,
+    def __init__(self, *, read_only=False, write_only=False,
                  required=None, default=empty, initial=empty, source=None,
                  label=None, help_text=None, style=None,
                  error_messages=None, validators=None, allow_null=False):
@@ -1163,14 +1163,14 @@ class DateTimeField(Field):
     }
     datetime_parser = datetime.datetime.strptime
 
-    def __init__(self, format=empty, input_formats=None, default_timezone=None, *args, **kwargs):
+    def __init__(self, format=empty, input_formats=None, default_timezone=None, **kwargs):
         if format is not empty:
             self.format = format
         if input_formats is not None:
             self.input_formats = input_formats
         if default_timezone is not None:
             self.timezone = default_timezone
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
 
     def enforce_timezone(self, value):
         """
@@ -1249,12 +1249,12 @@ class DateField(Field):
     }
     datetime_parser = datetime.datetime.strptime
 
-    def __init__(self, format=empty, input_formats=None, *args, **kwargs):
+    def __init__(self, format=empty, input_formats=None, **kwargs):
         if format is not empty:
             self.format = format
         if input_formats is not None:
             self.input_formats = input_formats
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, value):
         input_formats = getattr(self, 'input_formats', api_settings.DATE_INPUT_FORMATS)
@@ -1315,12 +1315,12 @@ class TimeField(Field):
     }
     datetime_parser = datetime.datetime.strptime
 
-    def __init__(self, format=empty, input_formats=None, *args, **kwargs):
+    def __init__(self, format=empty, input_formats=None, **kwargs):
         if format is not empty:
             self.format = format
         if input_formats is not None:
             self.input_formats = input_formats
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, value):
         input_formats = getattr(self, 'input_formats', api_settings.TIME_INPUT_FORMATS)
@@ -1470,9 +1470,9 @@ class MultipleChoiceField(ChoiceField):
     }
     default_empty_html = []
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, **kwargs):
         self.allow_empty = kwargs.pop('allow_empty', True)
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
 
     def get_value(self, dictionary):
         if self.field_name not in dictionary:
@@ -1529,12 +1529,12 @@ class FileField(Field):
         'max_length': _('Ensure this filename has at most {max_length} characters (it has {length}).'),
     }
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, **kwargs):
         self.max_length = kwargs.pop('max_length', None)
         self.allow_empty_file = kwargs.pop('allow_empty_file', False)
         if 'use_url' in kwargs:
             self.use_url = kwargs.pop('use_url')
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, data):
         try:
@@ -1578,9 +1578,9 @@ class ImageField(FileField):
         ),
     }
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, **kwargs):
         self._DjangoImageField = kwargs.pop('_DjangoImageField', DjangoImageField)
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
 
     def to_internal_value(self, data):
         # Image validation is a bit grungy, so we'll just outright
@@ -1595,8 +1595,8 @@ class ImageField(FileField):
 # Composite field types...
 
 class _UnvalidatedField(Field):
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
         self.allow_blank = True
         self.allow_null = True
 
@@ -1617,7 +1617,7 @@ class ListField(Field):
         'max_length': _('Ensure this field has no more than {max_length} elements.')
     }
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, **kwargs):
         self.child = kwargs.pop('child', copy.deepcopy(self.child))
         self.allow_empty = kwargs.pop('allow_empty', True)
         self.max_length = kwargs.pop('max_length', None)
@@ -1629,7 +1629,7 @@ class ListField(Field):
             "Remove `source=` from the field declaration."
         )
 
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
         self.child.bind(field_name='', parent=self)
         if self.max_length is not None:
             message = lazy_format(self.error_messages['max_length'], max_length=self.max_length)
@@ -1694,7 +1694,7 @@ class DictField(Field):
         'empty': _('This dictionary may not be empty.'),
     }
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, **kwargs):
         self.child = kwargs.pop('child', copy.deepcopy(self.child))
         self.allow_empty = kwargs.pop('allow_empty', True)
 
@@ -1704,7 +1704,7 @@ class DictField(Field):
             "Remove `source=` from the field declaration."
         )
 
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
         self.child.bind(field_name='', parent=self)
 
     def get_value(self, dictionary):
@@ -1753,8 +1753,8 @@ class DictField(Field):
 class HStoreField(DictField):
     child = CharField(allow_blank=True, allow_null=True)
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
         assert isinstance(self.child, CharField), (
             "The `child` argument must be an instance of `CharField`, "
             "as the hstore extension stores values as strings."
@@ -1769,11 +1769,11 @@ class JSONField(Field):
     # Workaround for isinstance calls when importing the field isn't possible
     _is_jsonfield = True
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, **kwargs):
         self.binary = kwargs.pop('binary', False)
         self.encoder = kwargs.pop('encoder', None)
         self.decoder = kwargs.pop('decoder', None)
-        super().__init__(*args, **kwargs)
+        super().__init__(**kwargs)
 
     def get_value(self, dictionary):
         if html.is_html_input(dictionary) and self.field_name in dictionary:
diff --git a/tests/test_fields.py b/tests/test_fields.py
index d99ca9c40..2d4cc44ae 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -2010,6 +2010,11 @@ class TestListField(FieldValues):
             field.to_internal_value(input_value)
         assert exc_info.value.detail == ['Expected a list of items but got type "dict".']
 
+    def test_constructor_misuse_raises(self):
+        # Test that `ListField` can only be instantiated with keyword arguments
+        with pytest.raises(TypeError):
+            serializers.ListField(serializers.CharField())
+
 
 class TestNestedListField(FieldValues):
     """

From 2942590ee3d3596683405dcdb1017e1833f5cb02 Mon Sep 17 00:00:00 2001
From: Ma77heus <58952630+MattheusHenrique@users.noreply.github.com>
Date: Fri, 6 Aug 2021 12:39:58 -0300
Subject: [PATCH 011/228] fix: broken cite (#8086)

Co-authored-by: MattheusHenrique 
---
 docs/api-guide/renderers.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md
index 7dbc5eee8..f13b7ba94 100644
--- a/docs/api-guide/renderers.md
+++ b/docs/api-guide/renderers.md
@@ -528,7 +528,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily
 [Rest Framework Latex] provides a renderer that outputs PDFs using Laulatex. It is maintained by [Pebble (S/F Software)][mypebble].
 
 
-[cite]: https://docs.djangoproject.com/en/stable/stable/template-response/#the-rendering-process
+[cite]: https://docs.djangoproject.com/en/stable/ref/template-response/#the-rendering-process
 [conneg]: content-negotiation.md
 [html-and-forms]: ../topics/html-and-forms.md
 [browser-accept-headers]: http://www.gethifi.com/blog/browser-rest-http-accept-headers

From cba24464e8f63377627f3016df88ee74d11a817d Mon Sep 17 00:00:00 2001
From: Paul Wayper 
Date: Sat, 7 Aug 2021 01:45:15 +1000
Subject: [PATCH 012/228] Botbot has been acquired, all paths now point to
 startupresources (#8050)

Signed-off-by: Paul Wayper 
---
 docs/index.md | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/docs/index.md b/docs/index.md
index 28e330250..ccbaf7373 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -186,7 +186,7 @@ Framework.
 
 ## Support
 
-For support please see the [REST framework discussion group][group], try the  `#restframework` channel on `irc.freenode.net`, search [the IRC archives][botbot], or raise a  question on [Stack Overflow][stack-overflow], making sure to include the ['django-rest-framework'][django-rest-framework-tag] tag.
+For support please see the [REST framework discussion group][group], try the  `#restframework` channel on `irc.freenode.net`, or raise a  question on [Stack Overflow][stack-overflow], making sure to include the ['django-rest-framework'][django-rest-framework-tag] tag.
 
 For priority support please sign up for a [professional or premium sponsorship plan](https://fund.django-rest-framework.org/topics/funding/).
 
@@ -257,7 +257,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 [funding]: community/funding.md
 
 [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
-[botbot]: https://botbot.me/freenode/restframework/
 [stack-overflow]: https://stackoverflow.com/
 [django-rest-framework-tag]: https://stackoverflow.com/questions/tagged/django-rest-framework
 [security-mail]: mailto:rest-framework-security@googlegroups.com

From c4404f3d5d2df2a5c7450517b48c4e6dfeb3c89e Mon Sep 17 00:00:00 2001
From: Paul Wayper 
Date: Sat, 7 Aug 2021 01:46:26 +1000
Subject: [PATCH 013/228] We now use Libera.chat rather than Freenode for IRC
 (#8049)

Signed-off-by: Paul Wayper 

Co-authored-by: Tom Christie 
---
 README.md     | 2 +-
 docs/index.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index fce275256..b8d8ca61b 100644
--- a/README.md
+++ b/README.md
@@ -168,7 +168,7 @@ Or to create a new user:
 
 Full documentation for the project is available at [https://www.django-rest-framework.org/][docs].
 
-For questions and support, use the [REST framework discussion group][group], or `#restframework` on freenode IRC.
+For questions and support, use the [REST framework discussion group][group], or `#restframework` on libera.chat IRC.
 
 You may also want to [follow the author on Twitter][twitter].
 
diff --git a/docs/index.md b/docs/index.md
index ccbaf7373..641800b93 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -186,7 +186,7 @@ Framework.
 
 ## Support
 
-For support please see the [REST framework discussion group][group], try the  `#restframework` channel on `irc.freenode.net`, or raise a  question on [Stack Overflow][stack-overflow], making sure to include the ['django-rest-framework'][django-rest-framework-tag] tag.
+For support please see the [REST framework discussion group][group], try the  `#restframework` channel on `irc.libera.chat`, or raise a  question on [Stack Overflow][stack-overflow], making sure to include the ['django-rest-framework'][django-rest-framework-tag] tag.
 
 For priority support please sign up for a [professional or premium sponsorship plan](https://fund.django-rest-framework.org/topics/funding/).
 

From b824b33dc3a3facad3ef2b41fbe02ab2a7578bc3 Mon Sep 17 00:00:00 2001
From: Thomas Grainger 
Date: Fri, 6 Aug 2021 16:46:57 +0100
Subject: [PATCH 014/228] add changelog project_url (#8085)

---
 setup.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/setup.py b/setup.py
index 5fd4df20d..d755a00fe 100755
--- a/setup.py
+++ b/setup.py
@@ -109,6 +109,7 @@ setup(
     project_urls={
         'Funding': 'https://fund.django-rest-framework.org/topics/funding/',
         'Source': 'https://github.com/encode/django-rest-framework',
+        'Changelog': 'https://www.django-rest-framework.org/community/release-notes/',
     },
 )
 

From e95e91ccf2065cbf474892b73ebd5790e5a4ae14 Mon Sep 17 00:00:00 2001
From: Ben Hampson <77866043+Ben-Hampson@users.noreply.github.com>
Date: Fri, 6 Aug 2021 17:49:41 +0200
Subject: [PATCH 015/228] Use correct link for httpie (#8005)

Before it was linking to a fork of a fork of httpie. I've changed it to the right URL.
---
 docs/tutorial/1-serialization.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md
index 85d8676b1..908b7474a 100644
--- a/docs/tutorial/1-serialization.md
+++ b/docs/tutorial/1-serialization.md
@@ -374,5 +374,5 @@ We'll see how we can start to improve things in [part 2 of the tutorial][tut-2].
 [sandbox]: https://restframework.herokuapp.com/
 [venv]: https://docs.python.org/3/library/venv.html
 [tut-2]: 2-requests-and-responses.md
-[httpie]: https://github.com/jakubroztocil/httpie#installation
+[httpie]: https://github.com/httpie/httpie#installation
 [curl]: https://curl.haxx.se/

From cdd53c7de912d5868c96f4e3883df248a3e6341d Mon Sep 17 00:00:00 2001
From: juliangeissler <81534590+juliangeissler@users.noreply.github.com>
Date: Sun, 8 Aug 2021 15:45:00 +0200
Subject: [PATCH 016/228] Update Tutorial - Relationships & Hyperlinked APIs
 (#7950)

unnecessary import, because it is already added in the previous section
---
 docs/tutorial/5-relationships-and-hyperlinked-apis.md | 1 -
 1 file changed, 1 deletion(-)

diff --git a/docs/tutorial/5-relationships-and-hyperlinked-apis.md b/docs/tutorial/5-relationships-and-hyperlinked-apis.md
index b0f338085..f999fdf50 100644
--- a/docs/tutorial/5-relationships-and-hyperlinked-apis.md
+++ b/docs/tutorial/5-relationships-and-hyperlinked-apis.md
@@ -31,7 +31,6 @@ The other thing we need to consider when creating the code highlight view is tha
 Instead of using a concrete generic view, we'll use the base class for representing instances, and create our own `.get()` method.  In your `snippets/views.py` add:
 
     from rest_framework import renderers
-    from rest_framework.response import Response
 
     class SnippetHighlight(generics.GenericAPIView):
         queryset = Snippet.objects.all()

From c5d9144aef1144825942ddffe0a6af23102ef44a Mon Sep 17 00:00:00 2001
From: Mark <33526445+mark-gold@users.noreply.github.com>
Date: Wed, 11 Aug 2021 13:30:09 +0300
Subject: [PATCH 017/228] fix typo (#8122)

Co-authored-by: mgold 
---
 docs/api-guide/validators.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api-guide/validators.md b/docs/api-guide/validators.md
index 4451489d4..76dcb0d54 100644
--- a/docs/api-guide/validators.md
+++ b/docs/api-guide/validators.md
@@ -238,7 +238,7 @@ In the case of update operations on *nested* serializers there's no way of
 applying this exclusion, because the instance is not available.
 
 Again, you'll probably want to explicitly remove the validator from the
-serializer class, and write the code the for the validation constraint
+serializer class, and write the code for the validation constraint
 explicitly, in a `.validate()` method, or in the view.
 
 ## Debugging complex cases

From c927053d4b99ada6b3fd5d70c6536554ff5fe8c0 Mon Sep 17 00:00:00 2001
From: jefcolbi 
Date: Tue, 31 Aug 2021 12:51:47 +0100
Subject: [PATCH 018/228] Replacing django-rest-auth with dj-rest-auth (#8146)

---
 docs/community/third-party-packages.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/community/third-party-packages.md b/docs/community/third-party-packages.md
index e53fc3d50..933244a6a 100644
--- a/docs/community/third-party-packages.md
+++ b/docs/community/third-party-packages.md
@@ -54,7 +54,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
 * [hawkrest][hawkrest] - Provides Hawk HTTP Authorization.
 * [djangorestframework-httpsignature][djangorestframework-httpsignature] - Provides an easy to use HTTP Signature Authentication mechanism.
 * [djoser][djoser] - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.
-* [django-rest-auth][django-rest-auth] - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc.
+* [dj-rest-auth][dj-rest-auth] - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc.
 * [drf-oidc-auth][drf-oidc-auth] - Implements OpenID Connect token authentication for DRF.
 * [drfpasswordless][drfpasswordless] - Adds (Medium, Square Cash inspired) passwordless logins and signups via email and mobile numbers.
 * [django-rest-authemail][django-rest-authemail] - Provides a RESTful API for user signup and authentication using email addresses.
@@ -193,7 +193,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
 [gaiarestframework]: https://github.com/AppsFuel/gaiarestframework
 [drf-extensions]: https://github.com/chibisov/drf-extensions
 [ember-django-adapter]: https://github.com/dustinfarris/ember-django-adapter
-[django-rest-auth]: https://github.com/Tivix/django-rest-auth/
+[dj-rest-auth]: https://github.com/iMerica/dj-rest-auth
 [django-versatileimagefield]: https://github.com/WGBH/django-versatileimagefield
 [django-versatileimagefield-drf-docs]:https://django-versatileimagefield.readthedocs.io/en/latest/drf_integration.html
 [drf-tracking]: https://github.com/aschn/drf-tracking

From 88666629a70f5c3fbe31e11aecd9817338de9c92 Mon Sep 17 00:00:00 2001
From: Asif Saif Uddin 
Date: Tue, 31 Aug 2021 18:56:08 +0600
Subject: [PATCH 019/228] stop testing django 3.0 as its EOL (#8136)

---
 tox.ini | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tox.ini b/tox.ini
index f23486a68..25f841821 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,6 @@
 [tox]
 envlist =
        {py35,py36,py37}-django22,
-       {py36,py37,py38}-django30,
        {py36,py37,py38,py39}-django31,
        {py36,py37,py38,py39}-django32,
        {py38,py39}-djangomain,
@@ -10,7 +9,6 @@ envlist =
 [travis:env]
 DJANGO =
     2.2: django22
-    3.0: django30
     3.1: django31
     3.2: django32
     main: djangomain
@@ -23,9 +21,8 @@ setenv =
        PYTHONWARNINGS=once
 deps =
         django22: Django>=2.2,<3.0
-        django30: Django>=3.0,<3.1
         django31: Django>=3.1,<3.2
-        django32: Django>=3.2a1,<4.0
+        django32: Django>=3.2,<4.0
         djangomain: https://github.com/django/django/archive/main.tar.gz
         -rrequirements/requirements-testing.txt
         -rrequirements/requirements-optionals.txt

From 6b392a46ea025148a24ce665e9c18e4386dde8fa Mon Sep 17 00:00:00 2001
From: Aditya Mitra <55396651+aditya-mitra@users.noreply.github.com>
Date: Tue, 31 Aug 2021 18:27:02 +0530
Subject: [PATCH 020/228] [FIX] Typo in api-guide/authentication (#8144)

---
 docs/api-guide/authentication.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md
index 60544079f..57bbaeb67 100644
--- a/docs/api-guide/authentication.md
+++ b/docs/api-guide/authentication.md
@@ -13,7 +13,7 @@ Authentication is the mechanism of associating an incoming request with a set of
 
 REST framework provides several authentication schemes out of the box, and also allows you to implement custom schemes.
 
-Authentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.
+Authentication always runs at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.
 
 The `request.user` property will typically be set to an instance of the `contrib.auth` package's `User` class.
 

From 4632b5daaed5a71a1be3e7d412a7f9a2e5520b90 Mon Sep 17 00:00:00 2001
From: Ryan Nowakowski 
Date: Tue, 31 Aug 2021 08:18:49 -0500
Subject: [PATCH 021/228] Fix subtitle of schemas for filtering (#8145)

Fix a likely copy/paste error
---
 docs/api-guide/filtering.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md
index 478e3bcf9..3541388ca 100644
--- a/docs/api-guide/filtering.md
+++ b/docs/api-guide/filtering.md
@@ -335,7 +335,7 @@ Generic filters may also present an interface in the browsable API. To do so you
 
 The method should return a rendered HTML string.
 
-## Pagination & schemas
+## Filtering & schemas
 
 You can also make the filter controls available to the schema autogeneration
 that REST framework provides, by implementing a `get_schema_fields()` method. This method should have the following signature:

From cb206e4701dd67f859c015bea111d0e77e364c4a Mon Sep 17 00:00:00 2001
From: Juan Benitez 
Date: Fri, 3 Sep 2021 07:00:23 -0500
Subject: [PATCH 022/228] fix: change View class to Throttle class on
 SimpleRateThrottle Docstring (#8147)

---
 rest_framework/throttling.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rest_framework/throttling.py b/rest_framework/throttling.py
index 0ba2ba66b..e262b886b 100644
--- a/rest_framework/throttling.py
+++ b/rest_framework/throttling.py
@@ -52,7 +52,7 @@ class SimpleRateThrottle(BaseThrottle):
     A simple cache implementation, that only requires `.get_cache_key()`
     to be overridden.
 
-    The rate (requests / seconds) is set by a `rate` attribute on the View
+    The rate (requests / seconds) is set by a `rate` attribute on the Throttle
     class.  The attribute is a string of the form 'number_of_requests/period'.
 
     Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day')

From 96001c5de61b5fe7c083bdd8e5810105e3575014 Mon Sep 17 00:00:00 2001
From: Anthony Randall 
Date: Fri, 3 Sep 2021 06:23:19 -0600
Subject: [PATCH 023/228] Added an article - implementing rest apis with
 embedded privacy from doordash engineering blog (#7956)

* Update tutorials-and-resources.md

* Update tutorials-and-resources.md
---
 docs/community/tutorials-and-resources.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/docs/community/tutorials-and-resources.md b/docs/community/tutorials-and-resources.md
index dae292f50..23faf7912 100644
--- a/docs/community/tutorials-and-resources.md
+++ b/docs/community/tutorials-and-resources.md
@@ -76,6 +76,7 @@ There are a wide range of resources available for learning and using Django REST
 * [Chatbot Using Django REST Framework + api.ai + Slack — Part 1/3][chatbot-using-drf-part1]
 * [New Django Admin with DRF and EmberJS... What are the News?][new-django-admin-with-drf-and-emberjs]
 * [Blog posts about Django REST Framework][medium-django-rest-framework]
+* [Implementing Rest APIs With Embedded Privacy][doordash-implementing-rest-apis]
 
 ### Documentations
 * [Classy Django REST Framework][cdrf.co]
@@ -128,3 +129,4 @@ Want your Django REST Framework talk/tutorial/article to be added to our website
 [anna-email]: mailto:anna@django-rest-framework.org
 [pycon-us-2017]: https://www.youtube.com/watch?v=Rk6MHZdust4
 [django-rest-react-valentinog]: https://www.valentinog.com/blog/tutorial-api-django-rest-react/
+[doordash-implementing-rest-apis]: https://doordash.engineering/2013/10/07/implementing-rest-apis-with-embedded-privacy/

From 655e803adfb19b8cb5b94a4895f1baffed55a958 Mon Sep 17 00:00:00 2001
From: Peter Uittenbroek 
Date: Fri, 3 Sep 2021 15:37:03 +0200
Subject: [PATCH 024/228] #7157: Fix RemoteUserAuthentication calling django
 authenticate with request argument (#7158)

---
 rest_framework/authentication.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py
index 9111007c0..382abf158 100644
--- a/rest_framework/authentication.py
+++ b/rest_framework/authentication.py
@@ -227,6 +227,6 @@ class RemoteUserAuthentication(BaseAuthentication):
     header = "REMOTE_USER"
 
     def authenticate(self, request):
-        user = authenticate(remote_user=request.META.get(self.header))
+        user = authenticate(request=request, remote_user=request.META.get(self.header))
         if user and user.is_active:
             return (user, None)

From 9716b1b6b7779543c134856e59f1c1393963e46f Mon Sep 17 00:00:00 2001
From: Ivan Trushin <33528037+WannaFight@users.noreply.github.com>
Date: Mon, 6 Sep 2021 14:18:13 +0300
Subject: [PATCH 025/228] Fix arguments (#7995)

`path()` has no argument `namespace`, it has `name` argument
---
 docs/tutorial/quickstart.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md
index ee839790f..e19577f61 100644
--- a/docs/tutorial/quickstart.md
+++ b/docs/tutorial/quickstart.md
@@ -126,7 +126,7 @@ Okay, now let's wire up the API URLs.  On to `tutorial/urls.py`...
     # Additionally, we include login URLs for the browsable API.
     urlpatterns = [
         path('', include(router.urls)),
-        path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
+        path('api-auth/', include('rest_framework.urls', name='rest_framework'))
     ]
 
 Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.

From 9ce541e90990307e06da1b7f5a2576406366a5e5 Mon Sep 17 00:00:00 2001
From: Tom Christie 
Date: Mon, 6 Sep 2021 12:19:20 +0100
Subject: [PATCH 026/228] Revert "Fix arguments (#7995)" (#8156)

This reverts commit 9716b1b6b7779543c134856e59f1c1393963e46f.
---
 docs/tutorial/quickstart.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md
index e19577f61..ee839790f 100644
--- a/docs/tutorial/quickstart.md
+++ b/docs/tutorial/quickstart.md
@@ -126,7 +126,7 @@ Okay, now let's wire up the API URLs.  On to `tutorial/urls.py`...
     # Additionally, we include login URLs for the browsable API.
     urlpatterns = [
         path('', include(router.urls)),
-        path('api-auth/', include('rest_framework.urls', name='rest_framework'))
+        path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
     ]
 
 Because we're using viewsets instead of views, we can automatically generate the URL conf for our API, by simply registering the viewsets with a router class.

From 73f3325f80a381d1d62ab1b84956295963f445ed Mon Sep 17 00:00:00 2001
From: Tom Christie 
Date: Fri, 10 Sep 2021 11:32:27 +0100
Subject: [PATCH 027/228] Update stream.io link (#8161)

---
 README.md     | 2 +-
 docs/index.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index b8d8ca61b..e3bcc2a1c 100644
--- a/README.md
+++ b/README.md
@@ -197,7 +197,7 @@ Please see the [security policy][security-policy].
 [bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png
 
 [sentry-url]: https://getsentry.com/welcome/
-[stream-url]: https://getstream.io/try-the-api/?utm_source=drf&utm_medium=banner&utm_campaign=drf
+[stream-url]: https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer
 [rollbar-url]: https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial
 [esg-url]: https://software.esg-usa.com/
 [retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship
diff --git a/docs/index.md b/docs/index.md
index 641800b93..9b667c669 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -75,7 +75,7 @@ continued development by **[signing up for a paid plan][funding]**.
 
 
-*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), and [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship).* +*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), and [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship).* --- From 761f56ef4025543e9cf39346d25641305e7d957d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 10 Sep 2021 14:45:06 +0100 Subject: [PATCH 028/228] Update stream.io link --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 9b667c669..f000d2e09 100644 --- a/docs/index.md +++ b/docs/index.md @@ -67,7 +67,7 @@ continued development by **[signing up for a paid plan][funding]**.
  • Sentry
  • -
  • Stream
  • +
  • Stream
  • ESG
  • Rollbar
  • Retool
  • From f0a5b958a134e8cd94e3ef3263e8fa623ac9b82f Mon Sep 17 00:00:00 2001 From: Dan Lousqui Date: Tue, 14 Sep 2021 14:45:55 +0200 Subject: [PATCH 029/228] Add max_length and min_length options to ListSerializer (#8165) --- docs/api-guide/serializers.md | 8 ++++ rest_framework/serializers.py | 27 +++++++++++++- tests/test_serializer_lists.py | 67 ++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 13c0c8710..cf8525748 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -755,6 +755,14 @@ The following argument can also be passed to a `ListSerializer` field or a seria This is `True` by default, but can be set to `False` if you want to disallow empty lists as valid input. +### `max_length` + +This is `None` by default, but can be set to a positive integer if you want to validates that the list contains no more than this number of elements. + +### `min_length` + +This is `None` by default, but can be set to a positive integer if you want to validates that the list contains no fewer than this number of elements. + ### Customizing `ListSerializer` behavior There *are* a few use cases when you might want to customize the `ListSerializer` behavior. For example: diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 9ea57f1af..389680517 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -71,7 +71,8 @@ from rest_framework.relations import Hyperlink, PKOnlyObject # NOQA # isort:ski LIST_SERIALIZER_KWARGS = ( 'read_only', 'write_only', 'required', 'default', 'initial', 'source', 'label', 'help_text', 'style', 'error_messages', 'allow_empty', - 'instance', 'data', 'partial', 'context', 'allow_null' + 'instance', 'data', 'partial', 'context', 'allow_null', + 'max_length', 'min_length' ) ALL_FIELDS = '__all__' @@ -143,12 +144,18 @@ class BaseSerializer(Field): return CustomListSerializer(*args, **kwargs) """ allow_empty = kwargs.pop('allow_empty', None) + max_length = kwargs.pop('max_length', None) + min_length = kwargs.pop('min_length', None) child_serializer = cls(*args, **kwargs) list_kwargs = { 'child': child_serializer, } if allow_empty is not None: list_kwargs['allow_empty'] = allow_empty + if max_length is not None: + list_kwargs['max_length'] = max_length + if min_length is not None: + list_kwargs['min_length'] = min_length list_kwargs.update({ key: value for key, value in kwargs.items() if key in LIST_SERIALIZER_KWARGS @@ -568,12 +575,16 @@ class ListSerializer(BaseSerializer): default_error_messages = { 'not_a_list': _('Expected a list of items but got type "{input_type}".'), - 'empty': _('This list may not be empty.') + 'empty': _('This list may not be empty.'), + 'max_length': _('Ensure this field has no more than {max_length} elements.'), + 'min_length': _('Ensure this field has at least {min_length} elements.') } def __init__(self, *args, **kwargs): self.child = kwargs.pop('child', copy.deepcopy(self.child)) self.allow_empty = kwargs.pop('allow_empty', True) + self.max_length = kwargs.pop('max_length', None) + self.min_length = kwargs.pop('min_length', None) assert self.child is not None, '`child` is a required argument.' assert not inspect.isclass(self.child), '`child` has not been instantiated.' super().__init__(*args, **kwargs) @@ -635,6 +646,18 @@ class ListSerializer(BaseSerializer): api_settings.NON_FIELD_ERRORS_KEY: [message] }, code='empty') + if self.max_length is not None and len(data) > self.max_length: + message = self.error_messages['max_length'].format(max_length=self.max_length) + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [message] + }, code='max_length') + + if self.min_length is not None and len(data) < self.min_length: + message = self.error_messages['min_length'].format(min_length=self.min_length) + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [message] + }, code='min_length') + ret = [] errors = [] diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index f35c4fcc9..551f62666 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -616,3 +616,70 @@ class TestEmptyListSerializer: assert serializer.is_valid() assert serializer.validated_data == [] + + +class TestMaxMinLengthListSerializer: + """ + Tests the behaviour of ListSerializers when max_length and min_length are used + """ + + def setup(self): + class IntegerSerializer(serializers.Serializer): + some_int = serializers.IntegerField() + + class MaxLengthSerializer(serializers.Serializer): + many_int = IntegerSerializer(many=True, max_length=5) + + class MinLengthSerializer(serializers.Serializer): + many_int = IntegerSerializer(many=True, min_length=3) + + class MaxMinLengthSerializer(serializers.Serializer): + many_int = IntegerSerializer(many=True, min_length=3, max_length=5) + + self.MaxLengthSerializer = MaxLengthSerializer + self.MinLengthSerializer = MinLengthSerializer + self.MaxMinLengthSerializer = MaxMinLengthSerializer + + def test_min_max_length_two_items(self): + input_data = {'many_int': [{'some_int': i} for i in range(2)]} + + max_serializer = self.MaxLengthSerializer(data=input_data) + min_serializer = self.MinLengthSerializer(data=input_data) + max_min_serializer = self.MaxMinLengthSerializer(data=input_data) + + assert max_serializer.is_valid() + assert max_serializer.validated_data == input_data + + assert not min_serializer.is_valid() + + assert not max_min_serializer.is_valid() + + def test_min_max_length_four_items(self): + input_data = {'many_int': [{'some_int': i} for i in range(4)]} + + max_serializer = self.MaxLengthSerializer(data=input_data) + min_serializer = self.MinLengthSerializer(data=input_data) + max_min_serializer = self.MaxMinLengthSerializer(data=input_data) + + assert max_serializer.is_valid() + assert max_serializer.validated_data == input_data + + assert min_serializer.is_valid() + assert min_serializer.validated_data == input_data + + assert max_min_serializer.is_valid() + assert min_serializer.validated_data == input_data + + def test_min_max_length_six_items(self): + input_data = {'many_int': [{'some_int': i} for i in range(6)]} + + max_serializer = self.MaxLengthSerializer(data=input_data) + min_serializer = self.MinLengthSerializer(data=input_data) + max_min_serializer = self.MaxMinLengthSerializer(data=input_data) + + assert not max_serializer.is_valid() + + assert min_serializer.is_valid() + assert min_serializer.validated_data == input_data + + assert not max_min_serializer.is_valid() From 250479dc3799a281429c2c10d9605a1a85d3e517 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 22 Sep 2021 09:57:17 +0200 Subject: [PATCH 030/228] Added pytz to install_requires. pytz will not automatically be installed with Django from v4.0. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d755a00fe..b8e220cb4 100755 --- a/setup.py +++ b/setup.py @@ -82,7 +82,7 @@ setup( author_email='tom@tomchristie.com', # SEE NOTE BELOW (*) packages=find_packages(exclude=['tests*']), include_package_data=True, - install_requires=["django>=2.2"], + install_requires=["django>=2.2", "pytz"], python_requires=">=3.5", zip_safe=False, classifiers=[ From f651878df33bf12d3b637f2377e234a2f0a0523c Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 22 Sep 2021 09:58:34 +0200 Subject: [PATCH 031/228] Adjusted DateTimeField docs for zoneinfo. --- docs/api-guide/fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 04f993942..b986009f9 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -325,7 +325,7 @@ Corresponds to `django.db.models.fields.DateTimeField`. * `format` - A string representing the output format. If not specified, this defaults to the same value as the `DATETIME_FORMAT` settings key, which will be `'iso-8601'` unless set. Setting to a format string indicates that `to_representation` return values should be coerced to string output. Format strings are described below. Setting this value to `None` indicates that Python `datetime` objects should be returned by `to_representation`. In this case the datetime encoding will be determined by the renderer. * `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATETIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`. -* `default_timezone` - A `pytz.timezone` representing the timezone. If not specified and the `USE_TZ` setting is enabled, this defaults to the [current timezone][django-current-timezone]. If `USE_TZ` is disabled, then datetime objects will be naive. +* `default_timezone` - A `tzinfo` subclass (`zoneinfo` or `pytz`) prepresenting the timezone. If not specified and the `USE_TZ` setting is enabled, this defaults to the [current timezone][django-current-timezone]. If `USE_TZ` is disabled, then datetime objects will be naive. #### `DateTimeField` format strings. From 2d9eee5d022bf77d6bb25e1d8b57da9e9c94f96f Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 22 Sep 2021 10:00:49 +0200 Subject: [PATCH 032/228] Adjusted URLPatternsTestCase to use addClassCleanup() from Django 4.0. Refs https://github.com/django/django/commit/faba5b702a9c5bb9452a543100928bcb5f66ebcf. addClassCleanup() is available from Python 3.8, which is the minimum supported Python from Django 4.0. --- rest_framework/test.py | 30 ++++++++++++++++++++++-------- tests/test_testing.py | 22 +++++++++++++++++----- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/rest_framework/test.py b/rest_framework/test.py index e934eff55..0212348ee 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -3,6 +3,7 @@ import io from importlib import import_module +import django from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.handlers.wsgi import WSGIHandler @@ -357,6 +358,13 @@ class APILiveServerTestCase(testcases.LiveServerTestCase): client_class = APIClient +def cleanup_url_patterns(cls): + if hasattr(cls, '_module_urlpatterns'): + cls._module.urlpatterns = cls._module_urlpatterns + else: + del cls._module.urlpatterns + + class URLPatternsTestCase(testcases.SimpleTestCase): """ Isolate URL patterns on a per-TestCase basis. For example, @@ -385,14 +393,20 @@ class URLPatternsTestCase(testcases.SimpleTestCase): cls._module.urlpatterns = cls.urlpatterns cls._override.enable() + + if django.VERSION > (4, 0): + cls.addClassCleanup(cls._override.disable) + cls.addClassCleanup(cleanup_url_patterns, cls) + super().setUpClass() - @classmethod - def tearDownClass(cls): - super().tearDownClass() - cls._override.disable() + if django.VERSION < (4, 0): + @classmethod + def tearDownClass(cls): + super().tearDownClass() + cls._override.disable() - if hasattr(cls, '_module_urlpatterns'): - cls._module.urlpatterns = cls._module_urlpatterns - else: - del cls._module.urlpatterns + if hasattr(cls, '_module_urlpatterns'): + cls._module.urlpatterns = cls._module_urlpatterns + else: + del cls._module.urlpatterns diff --git a/tests/test_testing.py b/tests/test_testing.py index cc60e4f00..5066ee142 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -1,5 +1,6 @@ from io import BytesIO +import django from django.contrib.auth.models import User from django.shortcuts import redirect from django.test import TestCase, override_settings @@ -282,6 +283,10 @@ class TestAPIRequestFactory(TestCase): assert request.META['CONTENT_TYPE'] == 'application/json' +def check_urlpatterns(cls): + assert urlpatterns is not cls.urlpatterns + + class TestUrlPatternTestCase(URLPatternsTestCase): urlpatterns = [ path('', view), @@ -293,11 +298,18 @@ class TestUrlPatternTestCase(URLPatternsTestCase): super().setUpClass() assert urlpatterns is cls.urlpatterns - @classmethod - def tearDownClass(cls): - assert urlpatterns is cls.urlpatterns - super().tearDownClass() - assert urlpatterns is not cls.urlpatterns + if django.VERSION > (4, 0): + cls.addClassCleanup( + check_urlpatterns, + cls + ) + + if django.VERSION < (4, 0): + @classmethod + def tearDownClass(cls): + assert urlpatterns is cls.urlpatterns + super().tearDownClass() + assert urlpatterns is not cls.urlpatterns def test_urlpatterns(self): assert self.client.get('/').status_code == 200 From 4916854492e6c999977b8577b5a15e6ffc784550 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 22 Sep 2021 10:02:28 +0200 Subject: [PATCH 033/228] Removed USE_L10N setting from Django 4.0. USE_L10N defaults to True from Django 4.0, and will be removed in Django 5.0. --- tests/conftest.py | 4 +++- tests/test_fields.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index cc32cc637..79cabd5e1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,6 +18,8 @@ def pytest_addoption(parser): def pytest_configure(config): from django.conf import settings + # USE_L10N is deprecated, and will be removed in Django 5.0. + use_l10n = {"USE_L10N": True} if django.VERSION < (4, 0) else {} settings.configure( DEBUG_PROPAGATE_EXCEPTIONS=True, DATABASES={ @@ -33,7 +35,6 @@ def pytest_configure(config): SITE_ID=1, SECRET_KEY='not very secret in tests', USE_I18N=True, - USE_L10N=True, STATIC_URL='/static/', ROOT_URLCONF='tests.urls', TEMPLATES=[ @@ -68,6 +69,7 @@ def pytest_configure(config): PASSWORD_HASHERS=( 'django.contrib.auth.hashers.MD5PasswordHasher', ), + **use_l10n, ) # guardian is optional diff --git a/tests/test_fields.py b/tests/test_fields.py index 2d4cc44ae..a3b37584b 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1220,12 +1220,12 @@ class TestNoStringCoercionDecimalField(FieldValues): class TestLocalizedDecimalField(TestCase): - @override_settings(USE_L10N=True, LANGUAGE_CODE='pl') + @override_settings(LANGUAGE_CODE='pl') def test_to_internal_value(self): field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True) assert field.to_internal_value('1,1') == Decimal('1.1') - @override_settings(USE_L10N=True, LANGUAGE_CODE='pl') + @override_settings(LANGUAGE_CODE='pl') def test_to_representation(self): field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True) assert field.to_representation(Decimal('1.1')) == '1,1' From 19b609155479f967a41ffc20a58bb09229f1e64b Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 22 Sep 2021 10:06:10 +0200 Subject: [PATCH 034/228] Adjusted authentication test for internal CSRF changes. Private _get_new_csrf_token() was removed in https://github.com/django/django/commit/231de683d86374c2b74da2185efc6ddfb5eb3341. --- tests/authentication/test_authentication.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/authentication/test_authentication.py b/tests/authentication/test_authentication.py index a73e0d79c..d771aaf8b 100644 --- a/tests/authentication/test_authentication.py +++ b/tests/authentication/test_authentication.py @@ -1,5 +1,6 @@ import base64 +import django import pytest from django.conf import settings from django.contrib.auth.models import User @@ -218,7 +219,16 @@ class SessionAuthTests(TestCase): Ensure POSTing form over session authentication with CSRF token succeeds. Regression test for #6088 """ - from django.middleware.csrf import _get_new_csrf_token + # Remove this shim when dropping support for Django 2.2. + if django.VERSION < (3, 0): + from django.middleware.csrf import _get_new_csrf_token + else: + from django.middleware.csrf import ( + _get_new_csrf_string, _mask_cipher_secret + ) + + def _get_new_csrf_token(): + return _mask_cipher_secret(_get_new_csrf_string()) self.csrf_client.login(username=self.username, password=self.password) From f46c33e4e2c545e3fd90de692242c53a6fe6e7e9 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 22 Sep 2021 10:07:00 +0200 Subject: [PATCH 035/228] Fixed TestDefaultTZDateTimeField to allow multiple tzinfo implementations. zoneinfo was made the default time zone implementation in https://github.com/django/django/commit/306607d5b99b6eca6ae2c1e726d8eb32b9b2ca1b. --- tests/test_fields.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index a3b37584b..7a5304a82 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1464,15 +1464,24 @@ class TestDefaultTZDateTimeField(TestCase): cls.field = serializers.DateTimeField() cls.kolkata = pytz.timezone('Asia/Kolkata') + def assertUTC(self, tzinfo): + """ + Check UTC for datetime.timezone, ZoneInfo, and pytz tzinfo instances. + """ + assert ( + tzinfo is utc or + (getattr(tzinfo, "key", None) or getattr(tzinfo, "zone", None)) == "UTC" + ) + def test_default_timezone(self): - assert self.field.default_timezone() == utc + self.assertUTC(self.field.default_timezone()) def test_current_timezone(self): - assert self.field.default_timezone() == utc + self.assertUTC(self.field.default_timezone()) activate(self.kolkata) assert self.field.default_timezone() == self.kolkata deactivate() - assert self.field.default_timezone() == utc + self.assertUTC(self.field.default_timezone()) @pytest.mark.skipif(pytz is None, reason='pytz not installed') From c62e3ca764d90e7b8402cc4022cffad2a07fa5be Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 22 Sep 2021 10:08:14 +0200 Subject: [PATCH 036/228] Added Django 4.0 to test matrix. --- tox.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 25f841821..6f49d373f 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist = {py35,py36,py37}-django22, {py36,py37,py38,py39}-django31, {py36,py37,py38,py39}-django32, - {py38,py39}-djangomain, + {py38,py39}-{django40,djangomain}, base,dist,docs, [travis:env] @@ -11,6 +11,7 @@ DJANGO = 2.2: django22 3.1: django31 3.2: django32 + 4.0: django40 main: djangomain [testenv] @@ -23,6 +24,7 @@ deps = django22: Django>=2.2,<3.0 django31: Django>=3.1,<3.2 django32: Django>=3.2,<4.0 + django40: Django>=4.0a1,<5.0 djangomain: https://github.com/django/django/archive/main.tar.gz -rrequirements/requirements-testing.txt -rrequirements/requirements-optionals.txt From 1fa5bc31c0c047eb2109929b17f8e53e84b7d40b Mon Sep 17 00:00:00 2001 From: Akhil Kokani Date: Mon, 27 Sep 2021 14:31:47 +0530 Subject: [PATCH 037/228] Update serializers.md (#8189) * Update serializers.md Removed unwanted word, "neither". * Update docs/api-guide/serializers.md Co-authored-by: Tom Christie --- docs/api-guide/serializers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index cf8525748..377f732ac 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -116,7 +116,7 @@ Calling `.save()` will either create a new instance, or update an existing insta # .save() will update the existing `comment` instance. serializer = CommentSerializer(comment, data=data) -Both the `.create()` and `.update()` methods are optional. You can implement either neither, one, or both of them, depending on the use-case for your serializer class. +Both the `.create()` and `.update()` methods are optional. You can implement either none, one, or both of them, depending on the use-case for your serializer class. #### Passing additional attributes to `.save()` From 605a624da6958bd5e633a391eb65e72d0526f37c Mon Sep 17 00:00:00 2001 From: Phil Leggetter Date: Tue, 5 Oct 2021 14:02:34 +0100 Subject: [PATCH 038/228] Add PostHog as premium sponsors (#8193) * Add PostHog as premium sponsors * Adding 275x250 PostHog image --- README.md | 5 ++++- docs/img/premium/posthog-readme.png | Bin 0 -> 2402 bytes docs/index.md | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 docs/img/premium/posthog-readme.png diff --git a/README.md b/README.md index e3bcc2a1c..8ba0a5e1d 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,9 @@ The initial aim is to provide a single full-time position on REST framework. [![][esg-img]][esg-url] [![][retool-img]][retool-url] [![][bitio-img]][bitio-url] +[![][posthog-img]][posthog-url] -Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [ESG][esg-url], [Retool][retool-url], and [bit.io][bitio-url]. +Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [ESG][esg-url], [Retool][retool-url], [bit.io][bitio-url], and [PostHog][posthog-url]. --- @@ -195,6 +196,7 @@ Please see the [security policy][security-policy]. [esg-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/esg-readme.png [retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png [bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png +[posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png [sentry-url]: https://getsentry.com/welcome/ [stream-url]: https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer @@ -202,6 +204,7 @@ Please see the [security policy][security-policy]. [esg-url]: https://software.esg-usa.com/ [retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship [bitio-url]: https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship +[posthog-url]: https://posthog.com?utm_source=drf&utm_medium=sponsorship&utm_campaign=open-source-sponsorship [oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth [oauth2-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit diff --git a/docs/img/premium/posthog-readme.png b/docs/img/premium/posthog-readme.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca8b0ecf04599491790c65f6ac2382a1f45cb34 GIT binary patch literal 2402 zcmai$dpy(oAIIm?kqEUVMI1|COS+h2jFQXTx1B9IU5@L*+;d$jLMd%T+LDdA=Y9!U zO`&8o_mayIDdv_-A-UVxJbwN6dpyqL@p*i{ulM)+e7#=Z@At0{8Hcslxnuth5D2u> z$`W-31QG!Y^y+po!Cqx!8!Whp6OA#(AW(UN)Vj+y!7LJV#=-^wfTCV04r1+CN^`RT6k>eVYF zBcruOb2^VqMINXu5{N;Nm zqHJ#!fI!<5tx(2xq5U(1Q-n$wWLu}W2EJU6rPH6guvvy==MQlDuww4toQBkVvx=gB zS56+3F_shmk9B{jb$qEsJ>}{Re&V>w8v9)6amureTuaCH72!MtnmxS`rtIbfQ8e9$UWfTA8?9)t?!XzL_}Y0;vq!}N8n+<^&H^8AcCFY4@fNOCpmAEU**@Zl%mYXyJ-UgseWGAX^U|40*v+ zfXPrB@bc8vNIp9*MDikKcSEHwu|0PLVtGV@`6R2u#yu$wc8g+LOl>S2ad zNlq75jnbj!Li+}4Hk8eTq?md-io$%ik8Vif4I@P%8K6VEX@g_9_%%>-ohogqEmNrl zWWBQA=;}w`oukPTxMpbNgHp2WFZqNl@k?fK$Cs8z-!G%x@j@t#e39C>$l zgZtJ{NLKmfDJJjzpM)p-zow=T7c!IAXmXAAa3Y5p5EM;Z>c zOqrTzK1V;PP3h$!@uGlamb4CXM%Fvf9sS;PpLbw?dN;3?t`-CD<~==K$ffI8?KJBV z$O0~1mn?g`EfXfhy#hsnfXpWyk2r#9m7z44^L5I$0d_@TD)J6|dUee^N(9NF1QIdW z7c8JDBqEOj8U4gaCAneZ3DCwRAn``nY$?~Xx0?q80yo_Ds5fs2k_s70qc`RT8gvp` zTmuBwT)-mjhWgODYlM1lVq4QO!B6S!<=I0&irx##s3-*T9Gs{@SVZkJf7v0pGL<_l zXb8u|uZMka*Uc{xCpT@S)B;2g$(-4-#?`YOSJi-6!ACCYAY)CZ^w9FXyr)y%fk_sq zKox&aL8E}ZYC|6VH1U2bs(rYDQ1M*QV@F-69=a(k=n+(2Uo7kG{ah1=LObq9E{v5P z@wfuEW_yVEt^(zEYC-g_v**Icv2Uw@^!n2qc0lw;GgSyEajkc()wgzg zMwx4?mmd*ZSzv-sS*PrXmPwoHCu{J#mEU6f3zKHcfstl%v;N|g@enS*%Ae54Yj}uj z%lRoIKV@-jL<`+`t5!Mnl8aSt*vsldhPXT0zMwmyK)w{wBavcnpw(X>_Rr*HGi{_F z`~2dwy1Ho@*a$7Y4t*SX^aNdgA^0qU)M;vy`e}AuIy{*?sC@UQs*0i<6PuK90L3BJ z#nu2OGmkAxPU;{s;ymw-l>?7T5Yauir!94LW*z^DztyXG!f=i;5#G|L`JzA-TT^-W zHSb#W!vG3FzjIEZh*9}Hxs6!gW;WIx?N=MJ7)t$m?ZjAUQpgDMNjqCLrYR@e8Ul8~ z+Psy>pX(WZ4Gf-eKGYK;%Zx|s>8`Sae1=jgch4VabK)gvvD*?Qv2i2$B^`H8g(+00 z8erfHDDIDivGiM~LzTQwW+tc7($y{!-|=5XBhem8GYv~9_Zy_fot1a<^}{Qx3@~0n zS>`OXmrvV6GeX5woY=vOc{V)GTp#|EC$#lWGRBhLZsws0(C2FIb2}u9JexkenOO|F z=vsfrkhza|EXMqeXfR2?fdF^x_TMO+4y!qL_>}X}ju(jP#?Fv{$BUg`IpaUv(gW(Z zokCrLI|RF?YB?TgRZY3pmX*-GG86H1Km1GAOX<@~Si73-#j?8`_8RP`)TGykPIkqn zX{gu7UC#Qv&Yk?s{{C}%Q7(!+Rdy)#y!uRZldTj(uRUy_tCLN2kOmNxK6b8dBUqK0 z3rQnZ0wp{|!dKhD!%!+SW46E;%T$M|%&@3Z6X%=% E0-^VOCIA2c literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md index f000d2e09..54b788107 100644 --- a/docs/index.md +++ b/docs/index.md @@ -72,10 +72,11 @@ continued development by **[signing up for a paid plan][funding]**.
  • Rollbar
  • Retool
  • bit.io
  • +
  • PostHog
-*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), and [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship).* +*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), and [bit.io](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship).* --- From 6ea95b6ad1bc0d4a4234a267b1ba32701878c6bb Mon Sep 17 00:00:00 2001 From: thetarby <45286577+thetarby@users.noreply.github.com> Date: Tue, 5 Oct 2021 17:33:55 +0300 Subject: [PATCH 039/228] Highlight `select_related` and `prefetch_related` usage in documentation (#7610) * docs updated to highlight use of select_related and prefetch related to avoid n+1 problems * Apply suggestions from code review cosmetic changes Co-authored-by: Xavier Ordoquy * cosmetic changes Co-authored-by: Xavier Ordoquy --- docs/api-guide/fields.md | 10 +++++++++- docs/api-guide/generic-views.md | 7 +++++++ docs/api-guide/relations.md | 31 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index b986009f9..5b9688dca 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -78,7 +78,14 @@ Defaults to `False` ### `source` -The name of the attribute that will be used to populate the field. May be a method that only takes a `self` argument, such as `URLField(source='get_absolute_url')`, or may use dotted notation to traverse attributes, such as `EmailField(source='user.email')`. When serializing fields with dotted notation, it may be necessary to provide a `default` value if any object is not present or is empty during attribute traversal. +The name of the attribute that will be used to populate the field. May be a method that only takes a `self` argument, such as `URLField(source='get_absolute_url')`, or may use dotted notation to traverse attributes, such as `EmailField(source='user.email')`. + +When serializing fields with dotted notation, it may be necessary to provide a `default` value if any object is not present or is empty during attribute traversal. Beware of possible n+1 problems when using source attribute if you are accessing a relational orm model. For example: + + class CommentSerializer(serializers.Serializer): + email = serializers.EmailField(source="user.email") + +would require user object to be fetched from database when it is not prefetched. If that is not wanted, be sure to be using `prefetch_related` and `select_related` methods appropriately. For more information about the methods refer to [django documentation][django-docs-select-related]. The value `source='*'` has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations, or for fields which require access to the complete object in order to determine the output representation. @@ -855,3 +862,4 @@ The [django-rest-framework-hstore][django-rest-framework-hstore] package provide [django-hstore]: https://github.com/djangonauts/django-hstore [python-decimal-rounding-modes]: https://docs.python.org/3/library/decimal.html#rounding-modes [django-current-timezone]: https://docs.djangoproject.com/en/stable/topics/i18n/timezones/#default-time-zone-and-current-time-zone +[django-docs-select-related]: https://docs.djangoproject.com/en/3.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index afc2cab56..fbafec93a 100644 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -96,6 +96,12 @@ For example: user = self.request.user return user.accounts.all() +--- + +**Note:** If the serializer_class used in the generic view spans orm relations, leading to an n+1 problem, you could optimize your queryset in this method using `select_related` and `prefetch_related`. To get more information about n+1 problem and use cases of the mentioned methods refer to related section in [django documentation][django-docs-select-related]. + +--- + #### `get_object(self)` Returns an object instance that should be used for detail views. Defaults to using the `lookup_field` parameter to filter the base queryset. @@ -389,3 +395,4 @@ The following third party packages provide additional generic view implementatio [UpdateModelMixin]: #updatemodelmixin [DestroyModelMixin]: #destroymodelmixin [django-rest-multiple-models]: https://github.com/MattBroach/DjangoRestMultipleModels +[django-docs-select-related]: https://docs.djangoproject.com/en/3.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related \ No newline at end of file diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index f444125cf..4547253b0 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -17,6 +17,37 @@ Relational fields are used to represent model relationships. They can be applie --- +--- + +**Note:** REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of `select_related` and `prefetch_related` since it would be too much magic. A serializer with a field spanning an orm relation through its source attribute could require an additional database hit to fetch related object from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer. + +For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched: + + class AlbumSerializer(serializers.ModelSerializer): + tracks = serializers.SlugRelatedField( + many=True, + read_only=True, + slug_field='title' + ) + + class Meta: + model = Album + fields = ['album_name', 'artist', 'tracks'] + + # For each album object, tracks should be fetched from database + qs = Album.objects.all() + print(AlbumSerializer(qs, many=True).data) + +If `AlbumSerializer` is used to serialize a fairly large queryset with `many=True` then it could be a serious performance problem. Optimizing the queryset passed to `AlbumSerializer` with: + + qs = Album.objects.prefetch_related('tracks') + # No additional database hits required + print(AlbumSerializer(qs, many=True).data) + +would solve the issue. + +--- + #### Inspecting relationships. When using the `ModelSerializer` class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style. From 53a0585dacea328ce74083f0da0dea10c4df03e5 Mon Sep 17 00:00:00 2001 From: Edmund <2623895+edmundlam@users.noreply.github.com> Date: Thu, 7 Oct 2021 04:09:00 -0400 Subject: [PATCH 040/228] Update permissions.md to fix garden path sentences (#8206) --- docs/api-guide/permissions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 6912c375c..19bc0e66a 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -24,9 +24,9 @@ A slightly less strict style of permission would be to allow full access to auth Permissions in REST framework are always defined as a list of permission classes. Before running the main body of the view each permission in the list is checked. -If any permission check fails an `exceptions.PermissionDenied` or `exceptions.NotAuthenticated` exception will be raised, and the main body of the view will not run. +If any permission check fails, an `exceptions.PermissionDenied` or `exceptions.NotAuthenticated` exception will be raised, and the main body of the view will not run. -When the permissions checks fail either a "403 Forbidden" or a "401 Unauthorized" response will be returned, according to the following rules: +When the permission checks fail, either a "403 Forbidden" or a "401 Unauthorized" response will be returned, according to the following rules: * The request was successfully authenticated, but permission was denied. *— An HTTP 403 Forbidden response will be returned.* * The request was not successfully authenticated, and the highest priority authentication class *does not* use `WWW-Authenticate` headers. *— An HTTP 403 Forbidden response will be returned.* From ddc5cd7e4b5f4bf250afd412b314af6728ea1726 Mon Sep 17 00:00:00 2001 From: Uzair Ali <72073401+uzair-ali10@users.noreply.github.com> Date: Thu, 7 Oct 2021 20:22:44 +0530 Subject: [PATCH 041/228] Imported Response (#8207) --- docs/api-guide/views.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index 2224c1f3a..878a291b2 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -145,6 +145,7 @@ REST framework also allows you to work with regular function based views. It pr The core of this functionality is the `api_view` decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data: from rest_framework.decorators import api_view + from rest_framework.response import Response @api_view() def hello_world(request): From 00cd4ef864a8bf6d6c90819a983017070f9f08a5 Mon Sep 17 00:00:00 2001 From: rgermain Date: Fri, 15 Oct 2021 16:13:20 +0200 Subject: [PATCH 042/228] add third packages nested-multipart-parser (#8208) --- docs/community/third-party-packages.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/community/third-party-packages.md b/docs/community/third-party-packages.md index 933244a6a..e25421f50 100644 --- a/docs/community/third-party-packages.md +++ b/docs/community/third-party-packages.md @@ -106,6 +106,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque * [djangorestframework-msgpack][djangorestframework-msgpack] - Provides MessagePack renderer and parser support. * [djangorestframework-jsonapi][djangorestframework-jsonapi] - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec. * [djangorestframework-camel-case][djangorestframework-camel-case] - Provides camel case JSON renderers and parsers. +* [nested-multipart-parser][nested-multipart-parser] - Provides nested parser for http multipart request ### Renderers @@ -183,6 +184,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque [wq.db.rest]: https://wq.io/docs/about-rest [djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack [djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case +[nested-multipart-parser]: https://github.com/remigermain/nested-multipart-parser [djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv [drf_ujson2]: https://github.com/Amertz08/drf_ujson2 [rest-pandas]: https://github.com/wq/django-rest-pandas From 781890b7df88086d9cba07904e53db346ec4a715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lavoie?= Date: Mon, 8 Nov 2021 03:59:32 -0600 Subject: [PATCH 043/228] docs(api-guide-testing): Fix typo 'CRSF' and plural of word (#8238) --- docs/api-guide/testing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index 73de68a76..62eb8dd1a 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -234,7 +234,7 @@ If you're using `SessionAuthentication` then you'll need to include a CSRF token for any `POST`, `PUT`, `PATCH` or `DELETE` requests. You can do so by following the same flow that a JavaScript based client would use. -First make a `GET` request in order to obtain a CRSF token, then present that +First, make a `GET` request in order to obtain a CSRF token, then present that token in the following request. For example... @@ -259,7 +259,7 @@ With careful usage both the `RequestsClient` and the `CoreAPIClient` provide the ability to write test cases that can run either in development, or be run directly against your staging server or production environment. -Using this style to create basic tests of a few core piece of functionality is +Using this style to create basic tests of a few core pieces of functionality is a powerful way to validate your live service. Doing so may require some careful attention to setup and teardown to ensure that the tests run in a way that they do not directly affect customer data. From 060a3b632f6f6ff2f84235d1be5da55020c40ff3 Mon Sep 17 00:00:00 2001 From: Anton Burnashev Date: Wed, 10 Nov 2021 17:31:15 +0100 Subject: [PATCH 044/228] Docs: fix broken link (#8245) --- docs/api-guide/pagination.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index 632af6a82..379c1975a 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -312,7 +312,7 @@ The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagi ## link-header-pagination -The [`django-rest-framework-link-header-pagination` package][drf-link-header-pagination] includes a `LinkHeaderPagination` class which provides pagination via an HTTP `Link` header as described in [Github's developer documentation](github-link-pagination). +The [`django-rest-framework-link-header-pagination` package][drf-link-header-pagination] includes a `LinkHeaderPagination` class which provides pagination via an HTTP `Link` header as described in [GitHub REST API documentation][github-traversing-with-pagination]. [cite]: https://docs.djangoproject.com/en/stable/topics/pagination/ [link-header]: ../img/link-header-pagination.png @@ -322,3 +322,4 @@ The [`django-rest-framework-link-header-pagination` package][drf-link-header-pag [drf-link-header-pagination]: https://github.com/tbeadle/django-rest-framework-link-header-pagination [disqus-cursor-api]: https://cra.mr/2011/03/08/building-cursors-for-the-disqus-api [float_cursor_pagination_example]: https://gist.github.com/keturn/8bc88525a183fd41c73ffb729b8865be#file-fpcursorpagination-py +[github-traversing-with-pagination]: https://docs.github.com/en/rest/guides/traversing-with-pagination From 0d5250cffada2ac250e24407953d4862d04d3dae Mon Sep 17 00:00:00 2001 From: Dmytro Litvinov Date: Mon, 15 Nov 2021 10:54:19 +0200 Subject: [PATCH 045/228] Fix link to installation of httpie (#8257) Right now httpie moved to "httpie" organization (https://github.com/httpie/httpie) and they don't have "installation" at their GitHub. Instead of that, they have "Getting started" section with link to "Installation instructions". --- docs/tutorial/quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index ee839790f..f4dcc5606 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -225,4 +225,4 @@ If you want to get a more in depth understanding of how REST framework fits toge [image]: ../img/quickstart.png [tutorial]: 1-serialization.md [guide]: ../api-guide/requests.md -[httpie]: https://github.com/jakubroztocil/httpie#installation +[httpie]: https://httpie.io/docs#installation From 580bf45ccfd5c423a938729907d813f4862dca38 Mon Sep 17 00:00:00 2001 From: Asif Saif Uddin Date: Mon, 22 Nov 2021 16:48:58 +0600 Subject: [PATCH 046/228] test v4 beta 1 (#8222) * test v4 beta 1 * django 4 rc1 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 6f49d373f..1ab505195 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ deps = django22: Django>=2.2,<3.0 django31: Django>=3.1,<3.2 django32: Django>=3.2,<4.0 - django40: Django>=4.0a1,<5.0 + django40: Django>=4.0rc1,<5.0 djangomain: https://github.com/django/django/archive/main.tar.gz -rrequirements/requirements-testing.txt -rrequirements/requirements-optionals.txt From 380ac8e79dd85e6798eb00a730b7d4c4c4a86ebd Mon Sep 17 00:00:00 2001 From: Yecine Megdiche Date: Mon, 6 Dec 2021 16:32:33 +0100 Subject: [PATCH 047/228] Remove old-style `super` calls (#8226) --- docs/api-guide/filtering.md | 2 +- docs/api-guide/serializers.md | 2 +- docs/tutorial/4-authentication-and-permissions.md | 2 +- rest_framework/fields.py | 2 ++ rest_framework/schemas/coreapi.py | 8 ++++---- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 3541388ca..512acafbd 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -241,7 +241,7 @@ To dynamically change search fields based on request content, it's possible to s def get_search_fields(self, view, request): if request.query_params.get('title_only'): return ['title'] - return super(CustomSearchFilter, self).get_search_fields(view, request) + return super().get_search_fields(view, request) For more details, see the [Django documentation][search-django-admin]. diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 377f732ac..4d032bd9e 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -1095,7 +1095,7 @@ For example, if you wanted to be able to set which fields should be used by a se fields = kwargs.pop('fields', None) # Instantiate the superclass normally - super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if fields is not None: # Drop any fields that are not specified in the `fields` argument. diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 79ce355c9..cb0321ea2 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -38,7 +38,7 @@ And now we can add a `.save()` method to our model class: formatter = HtmlFormatter(style=self.style, linenos=linenos, full=True, **options) self.highlighted = highlight(self.code, lexer, formatter) - super(Snippet, self).save(*args, **kwargs) + super().save(*args, **kwargs) When that's all done we'll need to update our database tables. Normally we'd create a database migration in order to do that, but for the purposes of this tutorial, let's just delete the database and start again. diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 5cafed555..d7e7816ce 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1491,6 +1491,8 @@ class MultipleChoiceField(ChoiceField): self.fail('empty') return { + # Arguments for super() are needed because of scoping inside + # comprehensions. super(MultipleChoiceField, self).to_internal_value(item) for item in data } diff --git a/rest_framework/schemas/coreapi.py b/rest_framework/schemas/coreapi.py index 75ed5671a..179f0fa3c 100644 --- a/rest_framework/schemas/coreapi.py +++ b/rest_framework/schemas/coreapi.py @@ -58,7 +58,7 @@ class LinkNode(OrderedDict): def __init__(self): self.links = [] self.methods_counter = Counter() - super(LinkNode, self).__init__() + super().__init__() def get_available_key(self, preferred_key): if preferred_key not in self: @@ -120,7 +120,7 @@ class SchemaGenerator(BaseSchemaGenerator): assert coreapi, '`coreapi` must be installed for schema support.' assert coreschema, '`coreschema` must be installed for schema support.' - super(SchemaGenerator, self).__init__(title, url, description, patterns, urlconf) + super().__init__(title, url, description, patterns, urlconf) self.coerce_method_names = api_settings.SCHEMA_COERCE_METHOD_NAMES def get_links(self, request=None): @@ -346,7 +346,7 @@ class AutoSchema(ViewInspector): * `manual_fields`: list of `coreapi.Field` instances that will be added to auto-generated fields, overwriting on `Field.name` """ - super(AutoSchema, self).__init__() + super().__init__() if manual_fields is None: manual_fields = [] self._manual_fields = manual_fields @@ -587,7 +587,7 @@ class ManualSchema(ViewInspector): * `fields`: list of `coreapi.Field` instances. * `description`: String description for view. Optional. """ - super(ManualSchema, self).__init__() + super().__init__() assert all(isinstance(f, coreapi.Field) for f in fields), "`fields` must be a list of coreapi.Field instances" self._fields = fields self._description = description From dabf2216c33a365f80354d962177d72914e8936f Mon Sep 17 00:00:00 2001 From: Jaap Roes Date: Wed, 8 Dec 2021 15:30:34 +0100 Subject: [PATCH 048/228] Update django-cors-headers links (#8176) --- docs/topics/ajax-csrf-cors.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/topics/ajax-csrf-cors.md b/docs/topics/ajax-csrf-cors.md index 646f3f563..a65e3fdf8 100644 --- a/docs/topics/ajax-csrf-cors.md +++ b/docs/topics/ajax-csrf-cors.md @@ -31,11 +31,11 @@ In order to make AJAX requests, you need to include CSRF token in the HTTP heade The best way to deal with CORS in REST framework is to add the required response headers in middleware. This ensures that CORS is supported transparently, without having to change any behavior in your views. -[Otto Yiu][ottoyiu] maintains the [django-cors-headers] package, which is known to work correctly with REST framework APIs. +[Adam Johnson][adamchainz] maintains the [django-cors-headers] package, which is known to work correctly with REST framework APIs. [cite]: https://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/ [csrf]: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) [csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax [cors]: https://www.w3.org/TR/cors/ -[ottoyiu]: https://github.com/ottoyiu/ -[django-cors-headers]: https://github.com/ottoyiu/django-cors-headers/ +[adamchainz]: https://github.com/adamchainz +[django-cors-headers]: https://github.com/adamchainz/django-cors-headers From 37b73ef46e8cf4cc746709542d7d26f6b152a26d Mon Sep 17 00:00:00 2001 From: Jeremy Langley Date: Wed, 8 Dec 2021 06:33:41 -0800 Subject: [PATCH 049/228] IsAdmin permissions changed to IsAdminUser (#8227) Documentation change to keep up with the code permission changes. Co-authored-by: Jeremy Langley --- docs/api-guide/viewsets.md | 2 +- docs/community/3.9-announcement.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md index d4ab5a731..417972507 100644 --- a/docs/api-guide/viewsets.md +++ b/docs/api-guide/viewsets.md @@ -125,7 +125,7 @@ You may inspect these attributes to adjust behaviour based on the current action if self.action == 'list': permission_classes = [IsAuthenticated] else: - permission_classes = [IsAdmin] + permission_classes = [IsAdminUser] return [permission() for permission in permission_classes] ## Marking extra actions for routing diff --git a/docs/community/3.9-announcement.md b/docs/community/3.9-announcement.md index fee6e6909..d673fdd18 100644 --- a/docs/community/3.9-announcement.md +++ b/docs/community/3.9-announcement.md @@ -110,7 +110,7 @@ You can now compose permission classes using the and/or operators, `&` and `|`. For example... ```python -permission_classes = [IsAuthenticated & (ReadOnly | IsAdmin)] +permission_classes = [IsAuthenticated & (ReadOnly | IsAdminUser)] ``` If you're using custom permission classes then make sure that you are subclassing From 3a762d9aac526f26ea2e9798140cb99a1d3ebc18 Mon Sep 17 00:00:00 2001 From: Matthew Pull Date: Wed, 8 Dec 2021 14:35:06 +0000 Subject: [PATCH 050/228] Update permissions.md (#8260) I might just be misunderstanding something (always a strong possibility!), but it seems to me that the table on the Permissions page is slightly inaccurate. For `permission_classes`, wouldn't it have global-level permissions for list actions (rather than no permission control, as is currently listed)? --- docs/api-guide/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 19bc0e66a..5d6462b45 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -286,7 +286,7 @@ The following table lists the access restriction methods and the level of contro | | `queryset` | `permission_classes` | `serializer_class` | |------------------------------------|------------|----------------------|--------------------| -| Action: list | global | no | object-level* | +| Action: list | global | global | object-level* | | Action: create | no | global | object-level | | Action: retrieve | global | object-level | object-level | | Action: update | global | object-level | object-level | From b0d407fd6344e6be9a0f1374cf53cf7e5286b67f Mon Sep 17 00:00:00 2001 From: Alexander Klimenko Date: Wed, 8 Dec 2021 17:37:32 +0300 Subject: [PATCH 051/228] Made api_setting.UNICODE_JSON/ensure_ascii affecting json schema (#7991) --- rest_framework/renderers.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 5b7ba8a8c..b0ddca2b5 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -1035,13 +1035,16 @@ class CoreAPIJSONOpenAPIRenderer(_BaseOpenAPIRenderer): media_type = 'application/vnd.oai.openapi+json' charset = None format = 'openapi-json' + ensure_ascii = not api_settings.UNICODE_JSON def __init__(self): assert coreapi, 'Using CoreAPIJSONOpenAPIRenderer, but `coreapi` is not installed.' 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, + ensure_ascii=self.ensure_ascii).encode('utf-8') class OpenAPIRenderer(BaseRenderer): @@ -1065,6 +1068,9 @@ class JSONOpenAPIRenderer(BaseRenderer): charset = None encoder_class = encoders.JSONEncoder format = 'openapi-json' + ensure_ascii = not api_settings.UNICODE_JSON def render(self, data, media_type=None, renderer_context=None): - return json.dumps(data, cls=self.encoder_class, indent=2).encode('utf-8') + return json.dumps( + data, cls=self.encoder_class, indent=2, + ensure_ascii=self.ensure_ascii).encode('utf-8') From 47ee3fc9a999440e721424aa5100f9eb216f0096 Mon Sep 17 00:00:00 2001 From: Chen Wen Kang <23054115+cwkang1998@users.noreply.github.com> Date: Wed, 8 Dec 2021 22:38:42 +0800 Subject: [PATCH 052/228] Update docs related to coreapi to include deprecation notice (#8186) * Update docs related to coreapi to include deprecation notice * Update docs to use reference to version 3.10 release notes instead of 3.9 --- docs/coreapi/7-schemas-and-client-libraries.md | 11 +++++++++++ docs/coreapi/from-documenting-your-api.md | 11 +++++++++++ docs/coreapi/index.md | 4 ++-- docs/coreapi/schemas.md | 8 ++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/coreapi/7-schemas-and-client-libraries.md b/docs/coreapi/7-schemas-and-client-libraries.md index 203d81ea5..d95019dab 100644 --- a/docs/coreapi/7-schemas-and-client-libraries.md +++ b/docs/coreapi/7-schemas-and-client-libraries.md @@ -1,5 +1,16 @@ # Tutorial 7: Schemas & client libraries +---- + +**DEPRECATION NOTICE:** Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation as of Django REST Framework v3.10. See the [Version 3.10 Release Announcement](../community/3.10-announcement.md) for more details. + +If you are looking for information regarding schemas, you might want to look at these updated resources: + +1. [Schema](../api-guide/schemas.md) +2. [Documenting your API](../topics/documenting-your-api.md) + +---- + A schema is a machine-readable document that describes the available API endpoints, their URLS, and what operations they support. diff --git a/docs/coreapi/from-documenting-your-api.md b/docs/coreapi/from-documenting-your-api.md index 604dfa668..65ad71c7a 100644 --- a/docs/coreapi/from-documenting-your-api.md +++ b/docs/coreapi/from-documenting-your-api.md @@ -1,6 +1,17 @@ ## Built-in API documentation +---- + +**DEPRECATION NOTICE:** Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation as of Django REST Framework v3.10. See the [Version 3.10 Release Announcement](../community/3.10-announcement.md) for more details. + +If you are looking for information regarding schemas, you might want to look at these updated resources: + +1. [Schema](../api-guide/schemas.md) +2. [Documenting your API](../topics/documenting-your-api.md) + +---- + The built-in API documentation includes: * Documentation of API endpoints. diff --git a/docs/coreapi/index.md b/docs/coreapi/index.md index 9195eb33e..dbcb11584 100644 --- a/docs/coreapi/index.md +++ b/docs/coreapi/index.md @@ -1,8 +1,8 @@ # Legacy CoreAPI Schemas Docs -Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation in Django REST Framework v3.10. +Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation as of Django REST Framework v3.10. -See the [Version 3.10 Release Announcement](/community/3.10-announcement.md) for more details. +See the [Version 3.10 Release Announcement](../community/3.10-announcement.md) for more details. ---- diff --git a/docs/coreapi/schemas.md b/docs/coreapi/schemas.md index 653105a7a..9f1482d2d 100644 --- a/docs/coreapi/schemas.md +++ b/docs/coreapi/schemas.md @@ -2,6 +2,14 @@ source: schemas.py # Schemas +---- + +**DEPRECATION NOTICE:** Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation as of Django REST Framework v3.10. See the [Version 3.10 Release Announcement](../community/3.10-announcement.md) for more details. + +You are probably looking for [this page](../api-guide/schemas.md) if you want latest information regarding schemas. + +---- + > A machine-readable [schema] describes what resources are available via the API, what their URLs are, how they are represented and what operations they support. > > — Heroku, [JSON Schema for the Heroku Platform API][cite] From 6e0cb8a7aa2db1694b46fa3eff5a5271fd7d828e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 8 Dec 2021 14:53:06 +0000 Subject: [PATCH 053/228] Add CryptAPI sponsorship (#8283) --- README.md | 5 ++++- docs/img/premium/cryptapi-readme.png | Bin 0 -> 17864 bytes 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/img/premium/cryptapi-readme.png diff --git a/README.md b/README.md index 8ba0a5e1d..4b089469f 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,9 @@ The initial aim is to provide a single full-time position on REST framework. [![][retool-img]][retool-url] [![][bitio-img]][bitio-url] [![][posthog-img]][posthog-url] +[![][cryptapi-img]][cryptapi-url] -Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [ESG][esg-url], [Retool][retool-url], [bit.io][bitio-url], and [PostHog][posthog-url]. +Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [ESG][esg-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], and [CryptAPI][cryptapi-url]. --- @@ -197,6 +198,7 @@ Please see the [security policy][security-policy]. [retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png [bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png [posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png +[posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png [sentry-url]: https://getsentry.com/welcome/ [stream-url]: https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer @@ -205,6 +207,7 @@ Please see the [security policy][security-policy]. [retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship [bitio-url]: https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship [posthog-url]: https://posthog.com?utm_source=drf&utm_medium=sponsorship&utm_campaign=open-source-sponsorship +[cryptapi-url]: https://cryptapi.io [oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth [oauth2-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit diff --git a/docs/img/premium/cryptapi-readme.png b/docs/img/premium/cryptapi-readme.png new file mode 100644 index 0000000000000000000000000000000000000000..163f6a9ea20f17909e6e38537a627f19e5766a66 GIT binary patch literal 17864 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 G_5WXyfz+@7 literal 0 HcmV?d00001 From d1bab643ab249f2c18cc0e6047033ca726c51605 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 8 Dec 2021 14:53:45 +0000 Subject: [PATCH 054/228] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b089469f..8875d650e 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ Please see the [security policy][security-policy]. [retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png [bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png [posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png -[posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png +[cryptapi-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png [sentry-url]: https://getsentry.com/welcome/ [stream-url]: https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer From c05998f5ddedec7c8c012a9be08aa41130a46b75 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 8 Dec 2021 15:11:55 +0000 Subject: [PATCH 055/228] Add CryptAPI to docs homepage --- docs/index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 54b788107..a86349df1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -72,11 +72,12 @@ continued development by **[signing up for a paid plan][funding]**.

  • Rollbar
  • Retool
  • bit.io
  • -
  • PostHog
  • +
  • PostHog
  • +
  • CryptAPI
  • -*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), and [bit.io](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship).* +*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), and [CryptAPI](https://cryptapi.io).* --- From 1cb3fa2e81ae33d52f4dcfc8b873f7b8093acd50 Mon Sep 17 00:00:00 2001 From: Jet Li Date: Fri, 10 Dec 2021 17:31:05 +0800 Subject: [PATCH 056/228] Test Django 4.0 (#8280) * Test Django 4.0 Django 4.0 released today. * Test Django 4.0 * Test Django 4.0 * Test Django 4.0 --- README.md | 2 +- docs/index.md | 2 +- setup.py | 1 + tox.ini | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8875d650e..7a899cdb4 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements * Python (3.5, 3.6, 3.7, 3.8, 3.9) -* Django (2.2, 3.0, 3.1, 3.2) +* Django (2.2, 3.0, 3.1, 3.2, 4.0) We **highly recommend** and only officially support the latest patch release of each Python and Django series. diff --git a/docs/index.md b/docs/index.md index a86349df1..294e1e6d3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -86,7 +86,7 @@ continued development by **[signing up for a paid plan][funding]**. REST framework requires the following: * Python (3.5, 3.6, 3.7, 3.8, 3.9) -* Django (2.2, 3.0, 3.1, 3.2) +* Django (2.2, 3.0, 3.1, 3.2, 4.0) We **highly recommend** and only officially support the latest patch release of each Python and Django series. diff --git a/setup.py b/setup.py index b8e220cb4..394845e14 100755 --- a/setup.py +++ b/setup.py @@ -93,6 +93,7 @@ setup( 'Framework :: Django :: 3.0', 'Framework :: Django :: 3.1', 'Framework :: Django :: 3.2', + 'Framework :: Django :: 4.0', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', diff --git a/tox.ini b/tox.ini index 1ab505195..f2ae6cd6b 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ deps = django22: Django>=2.2,<3.0 django31: Django>=3.1,<3.2 django32: Django>=3.2,<4.0 - django40: Django>=4.0rc1,<5.0 + django40: Django>=4.0,<5.0 djangomain: https://github.com/django/django/archive/main.tar.gz -rrequirements/requirements-testing.txt -rrequirements/requirements-optionals.txt From 16ca0c24d3d6fdf5663f761cadc2d4b1baf8acc8 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 10 Dec 2021 11:53:48 +0000 Subject: [PATCH 057/228] Add 3.10 to tox.ini and setup.py --- setup.py | 2 +- tox.ini | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 394845e14..c18975ef2 100755 --- a/setup.py +++ b/setup.py @@ -99,11 +99,11 @@ setup( 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3 :: Only', 'Topic :: Internet :: WWW/HTTP', ], diff --git a/tox.ini b/tox.ini index f2ae6cd6b..b7d62e081 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,8 @@ envlist = {py35,py36,py37}-django22, {py36,py37,py38,py39}-django31, - {py36,py37,py38,py39}-django32, - {py38,py39}-{django40,djangomain}, + {py36,py37,py38,py39,py310}-django32, + {py38,py39,py310}-{django40,djangomain}, base,dist,docs, [travis:env] @@ -54,3 +54,6 @@ ignore_outcome = true [testenv:py39-djangomain] ignore_outcome = true + +[testenv:py310-djangomain] +ignore_outcome = true From 217b0bf3af0b9332023113aab40283ea6929842d Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 10 Dec 2021 12:04:27 +0000 Subject: [PATCH 058/228] Add Python 3.10 to test matrix (#8287) * Add Python 3.10 to test matrix * Update README, docs homepage to properly reflect Python versions that we test against --- .github/workflows/main.yml | 1 + README.md | 2 +- docs/index.md | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fc166c434..42fee2a12 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,6 +18,7 @@ jobs: - '3.7' - '3.8' - '3.9' + - '3.10' steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 7a899cdb4..18d1364c6 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements -* Python (3.5, 3.6, 3.7, 3.8, 3.9) +* Python (3.6, 3.7, 3.8, 3.9, 3.10) * Django (2.2, 3.0, 3.1, 3.2, 4.0) We **highly recommend** and only officially support the latest patch release of diff --git a/docs/index.md b/docs/index.md index 294e1e6d3..2954f793a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -85,7 +85,7 @@ continued development by **[signing up for a paid plan][funding]**. REST framework requires the following: -* Python (3.5, 3.6, 3.7, 3.8, 3.9) +* Python (3.6, 3.7, 3.8, 3.9, 3.10) * Django (2.2, 3.0, 3.1, 3.2, 4.0) We **highly recommend** and only officially support the latest patch release of From 773f479719755193af8b0b7cb9915893738df152 Mon Sep 17 00:00:00 2001 From: Paolo Melchiorre Date: Fri, 10 Dec 2021 16:31:01 +0100 Subject: [PATCH 059/228] Python/Django compatibility updates (#8288) * Update python and django versions in tox.ini * Update python requires in setup.py * Update tox.ini Co-authored-by: Tom Christie --- setup.py | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index c18975ef2..210cc9ed0 100755 --- a/setup.py +++ b/setup.py @@ -83,7 +83,7 @@ setup( packages=find_packages(exclude=['tests*']), include_package_data=True, install_requires=["django>=2.2", "pytz"], - python_requires=">=3.5", + python_requires=">=3.6", zip_safe=False, classifiers=[ 'Development Status :: 5 - Production/Stable', diff --git a/tox.ini b/tox.ini index b7d62e081..a41176d72 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] envlist = - {py35,py36,py37}-django22, + {py36,py37,py38,py39}-django22, {py36,py37,py38,py39}-django31, {py36,py37,py38,py39,py310}-django32, {py38,py39,py310}-{django40,djangomain}, From ba25869045f203c62a0a9ddf5c54b7f882d8308c Mon Sep 17 00:00:00 2001 From: Alexander Clausen Date: Mon, 13 Dec 2021 09:57:55 +0100 Subject: [PATCH 060/228] Fix `REQUIRED_PYTHON` in setup.py (#8292) Just a left-over from #8288 to sync the "Unsupported Python version" message with `python_requires`. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 210cc9ed0..3c3761c86 100755 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ from io import open from setuptools import find_packages, setup CURRENT_PYTHON = sys.version_info[:2] -REQUIRED_PYTHON = (3, 5) +REQUIRED_PYTHON = (3, 6) # This check and everything above must remain compatible with Python 2.7. if CURRENT_PYTHON < REQUIRED_PYTHON: From d0bb4d877f95ea85446b8fc66d247f01337897d2 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 13 Dec 2021 09:33:03 +0000 Subject: [PATCH 061/228] Tweak test_description (#8293) --- tests/test_description.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_description.py b/tests/test_description.py index 3b7d95e0a..363ad6513 100644 --- a/tests/test_description.py +++ b/tests/test_description.py @@ -23,7 +23,7 @@ indented # hash style header # -``` json +```json [{ "alpha": 1, "beta": "this is a string" @@ -107,7 +107,7 @@ class TestViewNamesAndDescriptions(TestCase): # hash style header # - ``` json + ```json [{ "alpha": 1, "beta": "this is a string" From 9c97946531b85858fcee5df56240de6d29571da2 Mon Sep 17 00:00:00 2001 From: tim-mccurrach <34194722+tim-mccurrach@users.noreply.github.com> Date: Mon, 13 Dec 2021 13:08:40 +0000 Subject: [PATCH 062/228] Make api_view respect standard wrapper assignments (#8291) --- rest_framework/decorators.py | 20 ++++---------------- tests/test_decorators.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 30b9d84d4..7ba43d37c 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -7,6 +7,7 @@ based views, as well as the `@action` decorator, which is used to annotate methods on viewsets that should be included by routers. """ import types +from functools import update_wrapper from django.forms.utils import pretty_name @@ -22,18 +23,8 @@ def api_view(http_method_names=None): def decorator(func): - WrappedAPIView = type( - 'WrappedAPIView', - (APIView,), - {'__doc__': func.__doc__} - ) - - # Note, the above allows us to set the docstring. - # It is the equivalent of: - # - # class WrappedAPIView(APIView): - # pass - # WrappedAPIView.__doc__ = func.doc <--- Not possible to do this + class WrappedAPIView(APIView): + pass # api_view applied without (method_names) assert not(isinstance(http_method_names, types.FunctionType)), \ @@ -52,9 +43,6 @@ def api_view(http_method_names=None): for method in http_method_names: setattr(WrappedAPIView, method.lower(), handler) - WrappedAPIView.__name__ = func.__name__ - WrappedAPIView.__module__ = func.__module__ - WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes', APIView.renderer_classes) @@ -73,7 +61,7 @@ def api_view(http_method_names=None): WrappedAPIView.schema = getattr(func, 'schema', APIView.schema) - return WrappedAPIView.as_view() + return update_wrapper(WrappedAPIView.as_view(), func) return decorator diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 99ba13e60..116d6f1be 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -162,6 +162,16 @@ class DecoratorTestCase(TestCase): assert isinstance(view.cls.schema, CustomSchema) + def test_wrapper_assignments(self): + @api_view(["GET"]) + def test_view(request): + """example docstring""" + pass + + assert test_view.__name__ == "test_view" + assert test_view.__doc__ == "example docstring" + assert test_view.__qualname__ == "DecoratorTestCase.test_wrapper_assignments..test_view" + class ActionDecoratorTestCase(TestCase): From 7a84dc749cbc0db106c1ad40d7776ec307d08559 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 13 Dec 2021 13:10:17 +0000 Subject: [PATCH 063/228] Version 3.13 (#8285) * Version 3.12.5 * Version 3.13 * Version 3.13 --- docs/community/3.13-announcement.md | 55 +++++++++++++++++++++++++++++ docs/community/release-notes.md | 16 +++++++++ mkdocs.yml | 1 + rest_framework/__init__.py | 2 +- 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 docs/community/3.13-announcement.md diff --git a/docs/community/3.13-announcement.md b/docs/community/3.13-announcement.md new file mode 100644 index 000000000..e2c1fefa6 --- /dev/null +++ b/docs/community/3.13-announcement.md @@ -0,0 +1,55 @@ + + +# Django REST framework 3.13 + +## Django 4.0 support + +The latest release now fully supports Django 4.0. + +Our requirements are now: + +* Python 3.6+ +* Django 4.0, 3.2, 3.1, 2.2 (LTS) + +## Fields arguments are now keyword-only + +When instantiating fields on serializers, you should always use keyword arguments, +such as `serializers.CharField(max_length=200)`. This has always been the case, +and all the examples that we have in the documentation use keyword arguments, +rather than positional arguments. + +From REST framework 3.13 onwards, this is now *explicitly enforced*. + +The most feasible cases where users might be accidentally omitting the keyword arguments +are likely in the composite fields, `ListField` and `DictField`. For instance... + +```python +aliases = serializers.ListField(serializers.CharField()) +``` + +They must now use the more explicit keyword argument style... + +```python +aliases = serializers.ListField(child=serializers.CharField()) +``` + +This change has been made because using positional arguments here *does not* result in the expected behaviour. + +See Pull Request [#7632](https://github.com/encode/django-rest-framework/pull/7632) for more details. diff --git a/docs/community/release-notes.md b/docs/community/release-notes.md index baeeaf874..d3e9dd7cc 100644 --- a/docs/community/release-notes.md +++ b/docs/community/release-notes.md @@ -34,6 +34,22 @@ You can determine your currently installed version using `pip show`: --- +## 3.13.x series + +### 3.13.0 + +Date: 13th December 2021 + +* Django 4.0 compatability. [#8178] +* Add `max_length` and `min_length` options to `ListSerializer`. [#8165] +* Add `get_request_serializer` and `get_response_serializer` hooks to `AutoSchema`. [#7424] +* Fix OpenAPI representation of null-able read only fields. [#8116] +* Respect `UNICODE_JSON` setting in API schema outputs. [#7991] +* Fix for `RemoteUserAuthentication`. [#7158] +* Make Field constructors keyword-only. [#7632] + +--- + ## 3.12.x series ### 3.12.4 diff --git a/mkdocs.yml b/mkdocs.yml index 573898bca..439245a8d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,6 +66,7 @@ nav: - 'Contributing to REST framework': 'community/contributing.md' - 'Project management': 'community/project-management.md' - 'Release Notes': 'community/release-notes.md' + - '3.13 Announcement': 'community/3.13-announcement.md' - '3.12 Announcement': 'community/3.12-announcement.md' - '3.11 Announcement': 'community/3.11-announcement.md' - '3.10 Announcement': 'community/3.10-announcement.md' diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 0c75d3617..88d86c03e 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -10,7 +10,7 @@ ______ _____ _____ _____ __ import django __title__ = 'Django REST framework' -__version__ = '3.12.4' +__version__ = '3.13.0' __author__ = 'Tom Christie' __license__ = 'BSD 3-Clause' __copyright__ = 'Copyright 2011-2019 Encode OSS Ltd' From b3beb15b00ce8b251205aa5a344d6e6ddfac74a8 Mon Sep 17 00:00:00 2001 From: Jameel Al-Aziz <247849+jalaziz@users.noreply.github.com> Date: Mon, 13 Dec 2021 06:03:09 -0800 Subject: [PATCH 064/228] Fix CursorPagination parameter schema type (#7708) The CursorPagination's cursor query parameter expects a string and not an integer. Fixes #7691 --- rest_framework/pagination.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py index dc120d8e8..e815d8d5c 100644 --- a/rest_framework/pagination.py +++ b/rest_framework/pagination.py @@ -961,7 +961,7 @@ class CursorPagination(BasePagination): 'in': 'query', 'description': force_str(self.cursor_query_description), 'schema': { - 'type': 'integer', + 'type': 'string', }, } ] From f3bb5b9cdc7cb53c27535e4817112e6d2eba08a0 Mon Sep 17 00:00:00 2001 From: Abhineet Date: Mon, 13 Dec 2021 19:34:04 +0530 Subject: [PATCH 065/228] Add missing commas in pagination response samples (#8185) --- docs/api-guide/pagination.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index 379c1975a..aadc1bbc7 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -78,7 +78,7 @@ This pagination style accepts a single number page number in the request query p HTTP 200 OK { - "count": 1023 + "count": 1023, "next": "https://api.example.org/accounts/?page=5", "previous": "https://api.example.org/accounts/?page=3", "results": [ @@ -126,7 +126,7 @@ This pagination style mirrors the syntax used when looking up multiple database HTTP 200 OK { - "count": 1023 + "count": 1023, "next": "https://api.example.org/accounts/?limit=100&offset=500", "previous": "https://api.example.org/accounts/?limit=100&offset=300", "results": [ From 2d52c9e8bca06d5427596ea7f73b8294aa984036 Mon Sep 17 00:00:00 2001 From: juliangeissler <81534590+juliangeissler@users.noreply.github.com> Date: Mon, 13 Dec 2021 15:08:55 +0100 Subject: [PATCH 066/228] Update Tutorial - quickstart (#7943) * Tutorial - Adjust quickstart Add asgi.py file Also add paragraph for the second user, which is later displayed * Tutorial - Adjust quickstart It seems that there is no CLI command to easily create a user Remove the second user from the Markdown Image next * Tutorial - quickstart - Update browsable API image Only show the admin user New Image has similar width and is compressed --- docs/img/quickstart.png | Bin 39050 -> 27279 bytes docs/tutorial/quickstart.md | 13 +------------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/docs/img/quickstart.png b/docs/img/quickstart.png index 5006d60fe0c3f89723524ae5e8d45a115cd8e6d8..e3581f308b75b53443bab679e6ceb5a38b3776fa 100644 GIT binary patch literal 27279 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≥1YOF3HI=x zb^Ja7rk)7s^Wwa^)K2CWA>6rsm#pc~DoDiRZ&O<}4NkjQJg6MX{v1T5)G#W<9C=T* zD`k}ckcC1ly$TzVUH=Eh-VZiI+S$Af7-EqcvhArqzQZk*iC)51BCs;o3pZbWPPh;p z7h@_Nv0z#8Z{B8%+TXjEE2mh``9zTKE{EG2V|5*MO$*$Jc{@t}yPD@uz z1HD9(RrrTSNUrP7$TTo>k3R2D!gcv6E_aPKi7(tnXCqjezLe?77=)_{ucjYzFhyj5 zf$A{le8MCV)udJv->mJiErVj7-7fkl$8)Z%<=vSP zeoQBhOVxnBobGa))2SYwe&|D8vJ;K%gn{OS6d74-UDFC?r}hfTd|Xc4oj zOFD&u(*`-WX&^7C$9w7nl60k;5e)-5r~a&BAz{7c-7v$$*yMGI*YA5?+j2D9$Ok2@ zKug=f=fzm9Lem$g(xq{{!QfuOpkt!OgjbWn&r6A+?4fVJ!GUC3?Jz)!M`mG+9UoKT znF$i9)X)t;gl+FzVb7T5)XLy+s<41$6Cq<_AR^W;eW zADTlxxZ&=LH%#$=V>h8MJdU#Ds5@L_ri7NkBDaW0>mDS*nyXc)`2G6LtX~l+6O6qA zq;>hGj)a9{cmckI2NC%X$}=grrj7X@bluLi5j9VNAm-n(Vlw%tRL1AllAV6PRp z(xaoX-)Z81si182z-i@HU%d@3stB?{lizYcGLNss>`8y0#@&rJ_CI>jJ;h7{4~$oW zkSag4`==y%_{8=X9^7ek4Wc0GSZ}g9!njL0R=d{Et;RBUNQ?g1e^m*~st|1{OA2BV zVs6n6Ey7aawmWKqma2rr3ZJs|bPzk%I7px^ud|eteNd~cc$Rv#9DR2|yCfziEg`xu z_^a}L<}L`u8on7oN_|!&A=hjE$fF~dT6z~W4u_ zN{2mX#dPAL8X0_CU{L=jM;8LK6o5hxVGY8q`N^vy1O?BNXG`Gn}2Q3^Stl* z-uT8h#?Lq&_Px1dt-0o!^P1N+?=U3=DRdMf6gW6I^taODDsXTJ_;7IW4M_0do3Oyd zbvQVbIBPL6rMF^YWJ)fM7S?v=aB$LL@d=1ZsyleSZN8Jl%$PeLe#R)k(Pw|6kVaHS ze!Ja;i8LI=RMsAzLjk`V&Z2^=hf2oX_0C>dE!_PL-Xn8;rl9bF=61^O7n{)U-jz=4SN$tp+amdoP~H#j9UsB@WP!Q{M^;Pb?DLfNS)tgj*j(JG{0hSB9?Jc` zFiTggbJ00EYI7(PrT1&rO~c);JKbRdXL)V`g`tz`A;O=`V!T#J}-ItbEXk2?~hCsbo3t@+uz#ycU|2k zZQTF5wl0f7O~WC5QP-}Qk$MAWWar+A`IN7c@{H(SfB0+mPZ|c~{S%lL^#JMvq#VvpH(MYuWqZ zGTkiX)1X%q>0A|vBkd$!2!WVr6zw+ckA9OqL3%@@g;5ver-bD3t|jZm3wWv5=)8{< zf-RgL={@3UCvhTmd!L_0iWbac^g`~PHPSmL%qKabC|`*FLMIg6#6)oUut;u5hZ!D} zlg%575tel}rcr>&5Im6Gsl|A} z11A)9AC+ws_bP-y01Xug@1rkSCw~4iuehK;vDsixUS6L^X zF@_OwrTrYsKA8vnr%w76H0Ni$fiH*?qXv7Sy(GQ*Jwom1tHP^qy|}*f{X`%Q+gfw| zop;H9OMQ!Q%NCGACNV}chjojrC(50jtrP0U4 zxeYv%VcuZac(M`uSiM919rcg+IVxrHajM_1f0a_bQPKTM->AbbRi$=Zvo6&CivC?( zR9rExu1&7m$0@!-gFu3!Bv{*$J6&7xmBSUy^O+zPjnKaNDSTH-M=vN_y(tNp#y188Zx80JI zf+nf6ue$|A>ch&+Z|tKN%xh=e`1oTp7^*%n$~S(nZh&HCiXk6Bpt+8$0GjAcxWPa{vxf151f$YCrWoERQ2 zo%R1FHSRhgJ6$~C`&aa|gO=~$a19I+N*7qJ?_BF6{xQgj?N3<3{Aau9MjR_j%3R9|d9 z-F$I^aw3I?i;58;kH?I6$b`=9oq))EQ&ON2paCgaC~eh-XrY!8mq^*y*yY$W*!vJx zeTI|7TKmS_Gt=!63w;6^^_cP4@yOr5ui~jwtSYZ2)&AD}xqg4U>J1_~VqK^4rvRxY z)0(x>s5^yS1-pEP{KS!z5xp&&E#q&(95LQ$S2NvH65B2_<^$6s?(c0=i3f%!OWR8) zftPo+EZ%+m6e5)-)zaILAHT&v%FX&YF?yDz+#mrZqO-_6(ih_8c+|Qnc8+{Zf8o7j zyTW*CfA;?F`<=&)kZxH^THE(|(#z^w&l?epF?4Bk-ZuDV3L}Z`aLr(g;5`I^cLi^3 z-|fDmd9VL2;(cbw_Qz1s1u<%|Tv1!G{Eo#AnU3qu#1KcMHk@pN7|e0(un4rslBhJT zomQ8_fo!_sg4==&^`_z~jU}DZ27d3eZmzGkbG8anra7HCdpT`Yck}A|VFVg-=0m)_ z@zv2MA$vnhog^E4M>1ZWmCq`vD=D3yIXACKuBHEyUF*fx!x_N&N$o@ZQYKC2Sdl-0 zGxkNoV$wUsFa^He#8ukg<)!NSskL>oMs$7nr}+zc2l6EN*GR>aSvBg`%sW+~MvaUU zICo@3eNICKeV1{BDc=0D{1KV%JPhyyxgAtnE7J)h$d;wb6v3H9;Es}{(9J;^oJ zooPpOI)u6IaQVI^NY|-(tfr#o$QCPq`&`jNB>s-Gn$kncveNzckMz0p+jODkG>_>x z>BRLow1acVQq8BsWPq>kz8TPGE_!{`oN9#@L(5t zXJ;>R7kapM9x130aC`8!Cw3=4HPblbxnQD?!L{g>#Ps2H8_&7!h2aY);)Wac?TyJd zBP*#Q6Ze<=aTnpoMQ&R54IW*7>m3EX+jp~!h8Qha-;-YsKB!)g4%GWNj^1wE&My5v z`kn3B;mL6rAx!7Tdp>?_dL!Q6711Bpzf<^55hc?`m_yjp5BY{&F#YQJMeTm-ef`X# z@N(wxUqeGkbE4;IxUb2d_4dFY-4npYA&E0CO09=?eIH5Zurf#;#kv&8nC)=2Kz}`L z0oQ?f;ee2Z%~u8hu^e!_2&(>JjFkS)hmZ02ZU&f;b71kQ$o6ZGN-AMMTEjLE$0?HpYB zy@V+KoWT!1!@g#vAp3KQo2?Lqmb?;~n4^n187B)T3mb(n3KG@O^AX5_Mrdx`FosZrvLFACwCXSKTk0;Wi_`mw>Niib7g(S z@{098ZVs*$G&ALQbvLmwH+B0n?*F*mp9zQ>TeAM+YeClkezqVhY()PU;osB$^DUUa zFp41Sf7ntOWkUr04ICU9+*|QCYF=skOP+qXXH6nUmb$wRKD61?kAmTl$+&_->F5}w zPjI7y=C*wr7;*}bLVI0syFAp6yrL!`Z;Dhz=}_L%fwM*5dZ_aBJ8;k2CExU}R5&E3 z?^}qz%e)wzy`!!k^=r!{Y!Jy1;1Dnj(<%Md6Dv)nQLIi8<5j^5R`_*9H{0j-XHp8{ z%_ah&X^7yfl_+)HKnAad=nu!TNW@kTr`0&?Xf9*r+6~AZIJ(@FAXHfU^ zyR9_sML|K?7dF{(19xl!7d(FQM8C=HEkpdX7raWv(=Ua5IN901mcEsjA08g&N*xwg zQ&%^KNT3t2wfFYYva*&x@lZB4HU`(sw*@{xpMgs7sCPP)B|LO@cekpls=+Y!>(>wr z()+b&k%WYV@Fh_`bWCh)c8j5;ckkePqqXevYXk0l&S$@W{|-hYDK735pU&?-Ffy{q zQZyeP5dmp(XM`95L%&ANR-)4=)4Lkt80Ecl8%lbG9cFg2IXwL3FK7L@^mp&x9V|6} z3JJkhR#BPwz1Dl!v{wd(Pk{FHqp0)c(dxv+#L>~wITSLuaXdDrl&9i-zCVAmHHxDw zCnvYu>Q5N*Dp^jm+@Myc6ra@q4IQ0?(+U%-->eGQ^En>gF=9bck;&n9BSrjz$ff(y z%8!tcr}dva9_}taef$_n#8s4)^*UQ=YI@ooy5K%rrcc7}<|NpDd3hNW6tuEpWN5gI zfcT7xnp#3aqJQH!mR8ZAEg(HKCnsm_J#|j!Ck#z>b#zi;K@N^s^uWWG3p_kLgI2%f zP=3z?JN9H2!`6K-hK|loNR4$TO+TvE%lx_qJ!6UG|yKelAdiO`27{q8H6B8<$sC*7u-1AaAuYb18X5`Z<%jPvguU*r-GOn9J45Utb){ux3WaJ>L|itVA?V@+kM?Lm)xFAg>wvqKB~Z_dH` zeEj$k3aLLF%kIpRO>BUIJ^AFxld!Nbu%rzx8z>JRV7qUEq5K{ZIAlYkjP3uXm|3Po zhsSF0f`Fhvqd07PT#6JrUv25-)c^*0b+Xm$zGuNnWI3GT4*W$nPX!D(E-nsiW3U!TH39RjU6}sy5qS@Q+j%OkI5&9h|xF0%lGH?p`oE^X)n$x8})vU zNJ8rD=b<7Gx30iTM6;z86$5{T(O#eKbQ&09DP$|9@j7>yR5tLpfBpJ(ch`o3ft9sh zrxe&j+>DcG!=+J2Tr&Uq~BjmZ6Fu0eVI;9{kz)Hw)7kI%jGROpH2%4csbFP-AS)yBjP zjGAS0b=hTg2yk$m(d+B$j;&Xl$(9-P3=A?dGS`!t_io!`+4-3PK45!^<6>ee85js# zj--J-1iVG$WQc=3nTeB=lZ>o=d07Pf--vA}L&$e;ru01`Mjc6=>(&SdIGxLO=4iFE zMQ$5fO9!IBS`YfUW$yS~qwCiF-A(GSMT^1c5(hg0nqJGiU4l%WOx{;}D((H}iC_~$ zBEd@i`0>MIQe9Kiaj_xhrdBai`2AD#fxbSn91uZsrJ@%|GxSE-gtLB4-aM+CqwOvGYPXNrn0E$JJIZ;vomxgB&Y9E*4(N7{{E4YxzW)Wkn>8#Xb`W! zlr1bQT;f#<0!@|QScHH(Q*fpf3 zrNLEEq#_6B=cI6O?e-UouA}x#OB!9NGPS`XQRLdw;h$} zmqK$a`5;8n(9rPmY86j^tx#3g)s+>uslDEvF21`ytG=np&i(;%E+=PPv)}U+fzZAT14V@+T`v?3I)-eKBGJ1wf`e;q^V=KN%Hivl`C;lzWb-{54t-WM}IK7N0H4}xf3ULJ^x zEgsO6HC}gj_nUJlF}GdPw9WM1+15xpB}I!tW_tSFc5ZY+T-=9`AFVlw$Q3y`&^m>a zx-F{jw%7Y(HOurs&U(q?pa=5FxYg&+pG!(g1pO|Za-$aBBh;vaA0;I=fC<9GQQ~FX z4;K0A4w;ylBg4Y@oL1m`arb4#=k?Pv!jqB+^4Ca30{r&pDq$gm)b|$wT1Ze3+`%mH zdUmwQw!lD&CJ(5Nyu3U}>4EoGTVT_pzu>K?s$yqi+V6{@WQZTw@faNes6VK82AB}c z?E2cLczSnjZE|dk&3#ubFfg!L(=71l2jV^kz!#LC4!5B{TXesFz^>I9)+hO`1)T9_ zM!rz3NTqOhZ|~}m@X6!Hbn!9=H=ZC7z77Zw_VtVnRbx=Mw=Z2{W?+T=6&D3W6`>R; zVKCyhG}!h}pYjVo9Z~$Ox{7;KuX+jFo+1q`z85|>ZhTl*H#Z=rS9^Xd(I|$#=PgSb z-UQi=M9{0^+cz2z-@!zHPb}t}EQ+|?gvP&y#~8!vWQ(-VmQGV$jVsnbW(I&Xh*5r0 z!n$?=6`uuZIWIeVwU;z-f2K55Ca}QpEL}Fqnz>RPz+Bj~?9fs!CvgNZ6$Ahdt zN1uUjope`(Uc>&J@nxa)9TM!*nzk_~=F^zaYBv9!k78h4ak;9XV^F%~zt}_hc2lTu4kF=bcTiuz%jS1=xU*R9;oX`|v5j+hRDtlv8X^W|~PxKhC`Dt+XpTiXLinP!n z3l2@QTAeFIlZdOvQfGl@#32vue~*O}{$z@*!g7s_P2}-r;TxmT9_x^H7YdV1L6AHh z%5Alo@a`>_!azK2^gsUz<+XF{dl(Y@zfCB(rS!M(=P&;p#Gf&Fd^p_xQ*rz+CC2|! zfb4CPvl*hp`|AB;{xEX@>upf&Ki?^#@e6()h<-wRPjs)H!tg&l7-kHT{;)oiN+*Qh zo@QvB72UUsGYur4u*T-dD|r4f^*2TVNJFac+cP4;-7BMB!Z&{a>-4@|5OePN<8zBN z5ox2|k#>{HBaDujW?)B!T=?qb^b8va$6C=i7JY>{MP=&Xjv;dMkzin4{XI64U9Xq0 zeFxEb-$%4}?HSYmTE2g;rWa;|$}-#iTH553X$MP3WFM+0j!Ch2-%cwbBP8zCFQekg z3vYV=;;mctzE4`LnEY%y>TMwDJlO_ z{9&YFdq~tKa2_r3(0dpK~Pb_*8A@I`Z_0v z0)!h8k+#rKhV^>^k7N%5*Jhk=;-L;xcK;6`dYwR7X+x< zPi`k!$W@*WxYuU5(ZOG!s|?6nd@K98G>CL5QqR4d#}$I*bM648AR|85_CBbcH4t$A z^+BA1FW~kPIs#1NDNL@Z+H)SAG$A5b{?~mO!9%?VE@_(RRo3eAiVH^v!#LbjU?8J^M>;yE;IHXN=v{5XsXBdyv`oA1CJFZ0HW+( z78k`+^Npo4pbc-PwdIOG(CDQG$J-}0TyGc}TW3san;s0P48JBgG4DoA(0=K~OG3^WSExg&huB&oEttQ4|7p3|Yj9ywjrb0_pGnKIJ0kr)B zK_7`xHqMJr#qlg1Y#JAq<;ttt@@-KWn8S7Fk(eO%doKIeCwf;jefbl{{=E-wvEVr@ zcphq^q0i6f@7Yb$<3kx3dUb<;Iy-zmIETzfma52^U@{agJC1xk4b{N6dO-kv| zE@gaf^QRI49p!8;EHMq#Nv@t{O_ov~o!(M9wrys?m^6ct)u_<6Qe>2`qirG{>o@qj zdnEz)6aM9H^R9Zbcne=uYu(n+Ap`GGn}sWLf*zK1dCDcYc6W}KJ5Fxj-Z_v6)t95x z`u~obOjP1yHX@(_nT?WCtW<+IvZt@FucoF3i&7G#$L1w~cB`waM>9o8adD?WHQ4HZ zvml%kuscHZ)V3o}pP^ccha+LBpPDJ*Kil%uQcq{pE78m3_pu9JS-%{^02EnSs?oxHX}lvv`~@P6@&reX!!BI=tGgiTgo90iS)=hx8YIAUnt zF4xbdg=}5res4TSy*tNtJGZPS2yxcwm+yQIXr9*N0miob>tg%)1ZG{~huf2QM$J0w z$&e)z_GH+uKiiviwtZWC$V0Hu^kCJrf^QTyr6WJE*+EW-23n>5Ef zWJSFc8W7h1S*9;=9`Q+m!*QwUY*JCgoCDzK>tEdwi&BTJH!N84nZhjqU5@n3RlMK;v;= zYnaHL_FPC5TY8d(+;j6DFGe;&rD`_vHZv9Xa@0^Vq(3K{u_v#+8ZcuI6F1?C?Q&Pu zD&&xQJV3~yPghc0!Y$%ysOA^Ss%>@0x*#EfJ5PcHd3J1UnsOd% zhW93*hXxZ_+rVG!X8i?yPPZ$JI}HM^HbDBUFMjUR{^|r27x{9@9p(X`#+j=DObvF} zdTIU7DgeC{6;#t#0kAs`L;xV=pCHf+a}K&ThmW#bcU!b{Y;#O4FXobVNNgKkTx)S& zNlPoh-sa0Pu+gev!t_@urz5`x*Hy;RXkB6eM{{RE#t#cdoU%BP>Z&h?jdYfz&QimH z)}XLmi2hcyRhrf zav^xrIUakROM9kpad(xNk{Q_8cvu8AFRn|(8aH*^Kt$}P7FXwTm^c#YmiS)&vcavp zVRtKhxSVF|IWgn|eUx5-Ig>ax(IoA9*<9)a=IGUI?bqX{;$9RsAuKk4 zJOo4;TIW!@01r9&Dj=g3fIrL217eO@vr~AHgpkmCy${O+)fZvHinFRML%?&SE+U23 zIY*ABTC2-PGtqPt#OTw#Sq#V7$8bRq=@sH=Ch_MRFI#c-R$A5L-}QK&w9-Y0cigaE z_4vmVU#N$K^wp}@Ki&1dEz#G0;M;m4ZvE&m;ui~p%UvYNx&F_(ctGEB5k&%m6A&eL zAPSZnwzXPM(oo2}eVfeZY5{l#z#p9Y2w`mi#%X<>mqa7~W+^-f5P*(q`#mm0Lk?T) z5&WR64pIf!g6O0t7ZUZb5Dn@5t`%=CUnz$+xm``W-l4wMMCb5^--Am?3Y5$q@qnBL z0U+>h&oJ<6BN3Fli;IgOS+S$VrltzGZVru#JP6X$hn4OxHl6?ucRmw(@Yr*IZrlSe zU-puVygpe~RaF8VK(Li<1zo9fLVQh!Ti2y`oMjO*a&l&Yy#CiU<5q5Z%@AU(|I*M;2)({>`=I;2b6 zaU{ma`(N+mKin)o%niY+sH|k59=Ke5dym)KalsTgXc##Mo#i9GcvAo6%NJ09Qxuh# zKkOEl?+XigAFpSNeVWSz`IvWV(XF$X9AvH-3F-X{3u^@)&Um39Tn10tzC#%WV%J4()R{4SctUa6^W~yUJRn z#1WspFq-|MT&Q>N4mRXb2tdHiWe=2&&>?2JHc)50eH%V^eJ!0a$oGSRH2p`1bjn66 zj@akql8*c;ZrC(i@TRxjPeB~Z0P01xw3JnhK?e2yafISv1d`*W%O-&78J#>(@ZD?>XmCaaGODpMzkr6RFDQTwp zU;^Jyeq4g2P#YT?ZimI~)7A372%FqJ><@i&0x{j|TxU3$RHvt6{6%jkS@{3V3es zXTn@HhDMPUaKlMTXU0Rl@#g`R(#>I8AXu^0)m6I<;Au;M!@2nBd-%7K zu;1!`eVY8rR8mGJd*r0o9|xQ<~apz7^?RckvtW#bOGM^RBxJ-swN7SHP`J}hg_ z6tHRw3kv}Ke)#YK*gszt0M+NXxG-)P{z5`T)0l{Oj$Sj^oG z21ESQCr^;~$GTCO{9c?NK86?g*e(boI6wi8@pzN)aj?)!sr`0ybMr`Dspx>VI5{`B z8q-`#=gKA}fczS2KY3q+q~dgL5)GleAgd^L)|+-pz9Rk!hJuH!bqRPGk!SGDDM;Wx z{{$GEVk^30sNaSA4ad~DUMKcG)UsrLc(7GY}N5qM3|A0?iNc+G4HR&So z;NCyP&GGNw68x$B1TMJEWo6YIZ-@5Z+N{Tj4BQTFE5OUJiC$fAP4>c-K ziW%|Ee~+u4H=y0E3%OJ4W0XoI|KItZP<;|fX@Q>SCtswg9Bdb(I?tnjmUr%ZP>34M z{vSNt-~0|M!h-`zOTwfP3fliLT3B&4jM*^0Je~^3df&sA-g`fw=74xSnnv{5mf_#M z0DLE5v>9F-@tQch2h0;8lNkW|6UHk95RY%Rw6zz5rqCUA>SE0?rPnGmW!W? z!dL4s!JHv}etw>U>ifut)i&k$#zq;hd_fpK4LraIbj975_@DJgTmefw5ccJLA3 zpl@){RVN`e^=95O6R1f*R3A-x)wvU#2ny)L#6S>{7x#e{3beZQ^Is#n-rkM&IwB$> zkZPZm_D3H@v7SFSZ!TZM0w9Q4rzTV&7zhumg{t}7jz0xG_OfbqYANDaa?$h`FI z?8m^q(V?Mi$#Osj*+-&@Eo^A;y1o2uQ@e1!d<-mwkB<+GwYEQBjq=e1JOVEwuc4tK zJDZ$~>kOE4cwitrGLl5tk5^YxoF?{dwvw5-`NrmEnO>vIQj>dK@~}mWgCJ<$nJTd=fO$= zDj$`?Q&6DRS?7Y@g4|}W-xOGck&?yJKF8~CA^wdBmW-tudkeL;;O>n$yg(2Iyx>S0 zUo2o}V0j;iw_thgY?D$`Z3R}qy@8&>53*`eQ4t_w-v4MPX|N|GPI_P^^bNU!MTMUU z9=eq4sKrS83~1yPsDJq1m(d_5=tvl~7%Ybh_yGBbo{la_!1LgEV-Vw|pcNZIC>=k4 z6X>>pc`*2gNkn8*KiD0C50qU2+nEv|h1k^UQ0y)?a$o@@3CbM9RzE&2uJ}-&v)%5Q z{JcCYWizwC#;rg;-=56JXs*o43L=grA!lMLX>H9AsjxQ(RMGk2avKo5fCSRu^Q0SW zc*fZN7aWjpF6!LY6Mq2}sy~)?@60E}SdXMZe;)`Ww*ZMR8Z3H{TkAsy`$tDTec<&g ziI2ci09>2NVfoAxX+O9*9lZ3gf{}yedFla_s=)hO5X5lCfp5S7TUJ&Uko7@SflRXi ziOL&rvey@fnTd%&=LGE%_K+5C`vtuww?eT`&wyQw>-At=9zaJT3<-;fXa-uKiODa( z-Pk$eHr?^(Ob(Q{UfY~*kAr{_fyeBkKKhfldN2*#E_Fa%+ri=B_UZ%y0RfNJbF(4pd-vF#*$K(QZ@9@x3b7l9j%eo661O@;3^Q)_?dGt8|l$CQO&w!1x zvf9nqLHSdG=%6_R0&GM##rjPF2%DY++4{JhY=F+V1&DvnP%7%h6{zBy{nflXJ|H`O z|J?(kFTj#`%sO$vT`qRsJwavX;2?AbZGfr* z!lCO65nf(i5s^T!y*gC&w^{cNSV16%G? zXq45&UvE+Im{t_B){uaA1)NQ50_nbVa>wW5z@BI212PUCi(Z58g+sbRJ&;X7(?tG> zg{5U6c&?$}?~iMjFmrH&_Av|61H9v3^yHc(K;qpmivZ145Ft`~fv6uwNJvOzIm4+u zjJV+-IM2?`YBI#Lqfy4o*xK5HMM_tgnrjDQI9MC@1$DI4kDuxCzh}4fKpOt?dyY(7n@k{q)!8=!6=@({|jh}@0XjA_dQ?>MOmlKj1JwROJN&09S&-mG142_oXWccA7v!3&NWm?zX8;hH(TF)$4KQ0E=Hty|)L+j;Swk(6bA-=)LHnEk74q@) z^838}+-X$#^5?%GB=LW-LcaQAheduLQ627j>&H=@oZSmNNc-H;5ct2*EUT+-Q2R?o zaik&GZxB{JDqynOpGo}>a~)i3*OJ2c|EVB~9<;9WXfUc87)*{CVJj7%@Q&HPYc~-y zswA(N!_=}vV&Z=6@R*cTLQSneZFkdO4KyDP4AjWvwds|evH)ov^i*1K>w>Sw$Bl2z z>kqaY{rBR=t-cPL%g4gx<*YpLQF3iK)lqP1ywv>^2;J?8RWMO`@pr@1e)S)R8bOse zgy47uBf>tMV3x6cQ72OCICXOf*6cXOKF=+!faBdNy@s`v?Vin$KH=06LNiJNtF5kQ?;in<;z{>4{#sY2aLa3CTRJV4$12dL<8n5+g$E>P~%3_q?ZpW2FI{(|$ zjc2B=Bd|ii6Ro@nAeNG6pucQyCNh+QGBvKpTAa6jF5dy$&so9e@2LS7r0_U=?U$?JCD~3lqiircpX$LgYS!`k@ z%QZQz?kQYUrNT_`nio8Baj|-QTv@y(;O=ShG{5zP_(3jc7>o%L@KhiX@oyS+)K~EL zPyb;=Mo~OnG;I^sXT|xF&*hZ#!Hb8NH?*|TIoE2r^=>eMnVGJk1~d`UtJ2^o8?R0S zpvbeV*I+l#p6|=|XNF{Hn)+%0*P)=6V=DvX3&a^ah{XKTI8IrCcrFSWno3as#OXwm z*i&<2cGh!uiar9bWeF%iFvG8|8iRyoQN07IeM7FSz}Nt0)68F$AnvXp?g+ zMW6<`SmL=o418$o>yvJdo)hp{^gMmcpPHGu*xDi*u!o`z()h)4VBq;atZC0ne|B@p^MO2Zu(Pw1Rxx10*{rwa1QR= z+pgEO5R9CPBsN!8&W?hV>wy-K@7RQd{Q*}B<>kyw-#Y?u2@3YdvV}BZO|77cV2lqg z`&Lj?h>VO<1+ijJF4c%AFE5Aoq@;k(P4m<`&?d=}$cT%g`5pq@aASeZkb;4Ex~EqP zJ7(I(y(tRxF%^P-j^3`WFG04-vt{wTP{0ks!5y&W<$?CA+`47co83&H;uVdmtZ{)@g^n)J1Eof0O{@;_wfxoh- zPv_=~{COHtqe?KN|N0Murb$R&ts0Oq{~4KK(~!5q-#Bmopl5u-{-qs0*!&Mq!4Bgr zj0j=;MFko#2&PsD%s5P9FheCEx8%;MA#Q5KE^}+05`_LmAWAE)$wx!oZZZK~wwwg?8+S%&y~mqwMYDd0?S^{MlA^sMFKQO`^R zYwf?xWzIj$gVIDY_brQOH76N3{!-=Cf_bpmJeGrW9c57MZ;A;H zR-TQWI`V@LaF>+-g~PFu*PrT-OmCyqP9{!CQ7uY3O(8b2JABa*#)7?MQKwBeR!+Wl~+Jd_q3=4~w%5=Dc ziRFDmg6!VMxSGUa1%P-+PL}$n;BV9awOerZ12#@9Xw9wlIcv+8_iX~z(^7-;+S3qY zZo4_JQK5?xo!W5ATvfe|G(Ofj_06rVz~lb#s}p?CW$En-$Qoda8H$7Ly!`w@GxnCB z=J@exX(cL!fG)S#%&w{7^e_ed`N|J57ndra>H}^0`1n}Q-YvY8Dkp|g3cLy66z|h= zu;jT+$mcQzs;<;yGGMK&=PoBR@{$DkHOTgJ7-NmR{-?My9^=KE7sd> zw^k4lwwh7a$&*K*j(vfTe*xqz&SNFmoufL=L_DCF7oGO4xwDNY`k)as74Ql& zdB5l(jjmD}8Z$siupcxrH7zbK-Wtu!jEyzrPW3(8h1%q*R#sN>@$rer#l#r1CpXCC zshoj_gUaKNPW22M++T+|L%`>Fb7-~l>sRdBCaoVbASXI;WY`{Ag>44H|1eF8E#DLza$R>cV!qiP#<*&@XWg5U48#6G<5Hs zX8-(h?yElS#3_+<2D@WpaF-Q@U+VZ=R!Y~aoyp>WrqWbXi^~YGUFAzx=xwEMR|p7b zorFf2JJ`CEClG$#M4)g}mUwl`0QZ#Zs3i+P-;3c~m5*Fy55;~iT%g;#Z zX-isa<@gwTc-Tt5M$w6RbLlr?KD$8y_p1mHX2%~FxLZzcROfUwb3XFpHbh2qBIHcvCwmOrJlf$yeAtNA!w34 zJw1&i=2_p`YP&l(@i4Wp*c8JMT6fd`4&HkJ{SODbQ{bf%;k(mVa8{b2x67}tu)260 z8acPcr39T~o|GZ}_mxtgLj5gKn(LzleM|M8ui(5`k##$nh+9jT{76j`v2k|zOoveN z`O4t4vqazKo{#kY>s1p)IutfIWip{?Dt&oE0^;6&7GO{-QCm>Y)2HY%qXYagK$RpW z?zNw?;uNp(KA~wg>7Ci_r==~|Z>C|~>*|ZiwW~i|s8!9M{5|A*G&Ftbv{7exLXEu> ztU4P?M^3SQx`FNQkD$5MKuyoh#I1I9jw6A-Av?cV^gHY0Qz~6>dkL2kx#bT(&FRu)Sfmi`Gc+9cIR<6mVGhDtp)nX zBk=z~lM2dz4eP0rHOoo?q_}rN3q~`DQa=x{!#DxN6jh^Mv>|1mVk@F!$DSNx!n(O z9v(c{CWrTEFcAyn_UHpeCw8 zd48^gi^X>?+27wEMaq{Tba$%CPJU3H2S(aXssXx|U#7k?wE!<~$;s{853w~VPS~fxo}yC@nU~-*NQc2_ zD`rqFgWo~4DOnNVZ2-`Nf6Gb}M5CrxSZ>RvxxHJKILqm=oP)A7j>@B;Pyd_}RIlx% z;r04cBk2M!{hZc82`^>#BaE%FczDfM09y5HE0=FBNSShU+5`2 zFS2E0y=4(2kF|JiRrg}hc3)4&-#=KV`KbAQ8A zZLaz1+DLuqS$A0)t(05hVA{iv#&pI!{dJtqCLV6sD~i0wpbd{w>KUw@VlKtUayG10 zEsg-h8{h*qm6R%se%J!gAuSF-$O3pP$G)_+smW*JuU_z$lDs&h2GeL?-`JjewZ-uM zR3T1tOz0+{?7+)1Ee1T6BYGGf_t<|YbxwIo2tp$NT`PRJ$1Pi z^am=b9C0hh-b7@0isegb*IJ6>v*Q#|`RPTe1B<}YQpco|ji1CDP5qQjB7UA#YX+zf zvE$@4W}Y+gh(4Zk&bJfSSEj`7;js1l1agLpi;IaVbXoNXl-M-X)MW;Dhd^9mHoSjT z-_pTB?4L25i}cD$ z)#;Uf^aBwmT3DymZHL`~LNn$=Ny>ghUFBMM-yMH#7}B}#S{tFr3&D%^7NN9*?rW!$ za@Hv5;9b+n<%YNEO_^6fSI>}OzHj_2L5ErZ)|>lBt;cmSKNc2zGGGkq7@dKBgp7iM z$M?KEjpE6PiBPM)FXVtZ_3`k~0Nn?FfEm~d^Yhwu&AmN6K;5YeQrFcjo}3=ad_cjX zrupfU9NWG$ZF2@%&4%w`O;9nE`mLV_rgi#qr9{#I?3!Hiae}B*VOQ8xtu6E@Xo_c? z9W99&UOTKBPRw5f^6O*qoh+VRN~=Tqj2s5%-lXGDyhoQ*^?yGn1ltybJ{p5Zr+0&4ZRw7{0Yq;(w6g zdUM};)g8ZBz8Kyo-gP@O{k{62FJkT5zxGCLdBoW{o1wR52ybt;SuybV_O6a{@UQdY z$vLQm_&y3Z3ZH>Bhy!C?->-YQm`i83$1woK>^f7Dj6)k`$rDA)BTTur5=XDtdcAuK zSe)OU1b`eF8sIl>z5#(;%}x6AQ5?G*y=!B0A{6$oCuxE&MAwHE`Vw#7gk z?QF@_YP_bwMs!zM%69;c@3mC~BuU!}yziRd%g&f%W7Sg}qdr{kEJaF%Sxv^E$^>>B z9=_FPvtC(#s4f3t=e)Qlax)r5m}J-N5&5N2Pg!%SB!xmY1Q*Nd68oQh%;a@l$DgeBzu2gbZt^b`!u?I3HH{~g5(t8@S%`< zxlVE5(xZM;M7NBKv(|UN2KLOk#4H}9C310yEa8w4 zX)PNCxKFg7mLXe2xNllEcf5xmF)a7G3Cjkz#T=I{KG!a#BKN6qoTxak7fQ9AR?MfS zO7=6nXnJ~L8o{%#ciOO~jEU7bHkR1tdr~eo_y0Bb)^Sm9ZTl$dR#21)7CASy!uZRZ6#BhVZfe#d3vxTHodK1F@&YG4@ zYZCc<5!IUoqX{9kp(yUyUrWTzt?S#6m;m`>grbK)N6TDH!3+KQigiSv8e3Qdrm7>UK<9g3#G?7`+TEYfi@R-rR2h?Q()UC2$zx%`R z6_+u6((;#-?dz$J-BYh1iy~9LTNJh&8P|Dnr3W|#zYB=%3Ig802g$MJc8kI!OGHG3 z9@Mr}y;#VbmjhI=+1aDuti~JjH*4#B$$u$}Z>7!I1qs~O=> z7jYyzu_iEI2p{fe!GqT?j}N|n$9Zy~_D#-I7S^48aC*L0eF{4(hwa($udb+Sr9|o` z9(SaB=%c>cI0%M>aZJ+XyM;f{SiNdNP(2Ba!+rR9pPnpoY{^05WcQ=Ku18*Oa;Zhz zbr3y-=RPiOVr*<)s~smZRcW-i(C#f8!3#Xel-dcX`GS4KgJqm# zy;^lU&Lo#RMv+*!hyjA>9o9H0vV`wWJsZm3$v<^1N##XrMb5$;z2cXl&_bT^b6~H{ z?*h*fLB>ahkB;47EnDjoJwatV)~b$z*NuxmQ{!V0d;dYcMxMxq&>qC;Wb}W?4}hjn(3h{hsx1 zzPR%)Y*42Lmw$`htws3lSG6bWpa(w(SB~hnBVJ=@m>FrF*5#?)sXm@adr5U|voh6w z7KQSAJYV}%kbbco6UU@pQc_&p`|Vo=(iylJV8Ci-I$U!`T|#qmaz4(4u zHbON1Djeg$&!p|`n#S&x>7KOhl1c5!2kfiUujnYmX$wc0E2mBg{`^!8_fqN*HJ!}P zL!Z1{&k15LQ@_g7@>AER**V0vmn$%vJzK$x$Om2dbMrZO*Bk{ykOk!}oW4IWBTsxl zOdr#sqWg(18>ST)+1lg+&vGhPAfdNs?aIN)&eRk*JQTXU*&{AOriDCwbmd?wGM(bn zBJ<})Ev-lej)afQ4N3P*Kf(eZ$1~V*XOGtlK;7T@FuRv&ywx0 zyZI~c`EwMq^PH8B`EC=H4!B>wQ`4V(zGnGMht;Zx@%VW0_BB?co(q1V)_Y~dNMDwS z3RIf`+&*I{$1>MRHoXBC>C&|GsdSg5wX1_jmZmB;9vk4#(9FY=e{3AkQiVQ<>H4iV z`<03Eg1kUgLt&rpYYA$E2Zu&i;t-oz_>=6Wn3-)6HQp+XuKWkrHM>#;*^TViejYC< z$SDM^Qom|^v1O-dRjNKQv(k#=d`@$Kd}Lg!&Z2ME$NKR-z5iO+skC*@yziKH4)(<% zhLcB}>o7E`ckSVc8Bb~t&#GRn-e_Tdq*}xyYhL$}inaP$ZT+WljM4Zv_gZH*bj4~c zCL??;VAEni){8atOOXe6+6m{sD0h zyT1>f5nCmb&3SXA2>IVdmz@|>$7UR+_4R{Yqfn~ z#)=zto-8rU@_R5%(Tn1&^kB=DX0Zq)EY~z=|Q-!88Q#^+rO`Z0v0!a6>mkP^xZQdYEe}8)NixVAQ zl-=Oh#{Q(_{qo+nckb^Gnwp%DQPn1X`dXDgFw?6_MRpprb+krhS{e#z zOp8-q9*|Op%k{B)Ham!ntIL6RlF2J2 z;09jwj;oZ3pTprv-UPGvzHB$PEtHGkHf+XCKR^#Iq(U`b1!WjbG(QqtVu$;k;DC){ zyH&xN2MNNXrPGftK}Gg!nGmxb@z$hB2UL}`fV%o@l7jo8+`JwC{^?o}i~jQ~Kd(WY zsH}n9Nm8)e%%q3$$T0PnNrY(k)Y413Zr$TqURL%0w7tjFZ5ek5y^4#94VhOsx?Hg` zSUs7PY`?RxpQDPu*mmFL!8n(Tv(roCCl~OZE^zNZB_|x4=$l*uSJI|?mZ+&k62I6Q ziWKPrvYrvT;sm=R(%2_<_~Ja16s*nyuBBf-qpBQ}?-qIh% z>8Rpot8krktb>ydwbjN7c-o%l(RRm7$0~RffGN*7r!6kl$R#2j=lexfGN|QHZi<6a z$^S#L`Hq1kLzu7H5cuAjgEO=~EzRgoE+W`@f}axsf$B>rz60#4i#E#gD^{+I9}f$`huV{hNYT}on1O_$V5D|m zvz#>)3f%nl!+O=)Dyv^j#4Nx4xf#DEmQ|*CJov-6j}ASEmlZ|q;32+SGC*RbtnT3B zYL&dFjPw+_ug(Q7gQf#!8=gh~n{6P86;G?~m?-H%Z!deN+qcz;s1IC?fJL-f%s_YPG z3;R4h-7DDUIs1(bAu{}`UpEh+KG_B$6R7DkRhIDpjLk ztyZZ;YC5wme00IF*417cG2>?YI5}D^&5!!pDq}o{Nj)UC*^N17{o;hfC_Nm`orR)P z-^Wk#Cq9pj;eio}$78|OdT{KL5-Gv##eLC=IYrdNPK8-a0_^Ce!L@~s+DuYD;Et+F zRFZYL-6T##f+Og|EKM^!50l{D!ry9vce4_ceVl8L_G>TsRCsQvGc-EDb~v^(ctSds z7VPciY<>1LGT0X8dk9@Q&%NQBwI|1vbS5#Cx?<{bTk+djq9*0-`C{HFwQzs6E6wri zS%NhR=CZ^IY6tG&{Q4M)+8<2wq3t!E*D^+eoS}+<5NXMhryeS6)2eO#sdQQ!)1`w= zJF4i1I*SZp=@aoH7j&M9cP23^>Njw2{zgL+V?vuGXPVK_Dso5k+bm5?N`N%&VAsBT zbjl#od+yY9V8LY<)?inP(^l&Y+mAM&4@B=J&(>V&{!? z!$#YekWrE@tYbeHDGXde^)kw7Suv7_O)yc6wRr`hA@ciAIl zW>}z!LD@|tO+vm|b;S<7RyWYzR)5;cr$3EWTMBqAB9Q*ccb#kNh%^wVa{(ztX-nU_U|=I*Y255K zh&vP8RYc)F1@MV@=_PIY=(0{Uv?EPO4XFcMr?{QVCmM~LXnW*5m zhy5+9!kC+z0>4V2c7q|i!_~_fERV-j9V6lO#h2lF_|e^upXwNPOC%dthnx=vD~V$G z3-hCM=_XtL-Z8s6{=l;oXS!~eaKqAj;kUf9&0Rs?T8D*3KafA^GF0L}z`Zv_GS=X~Fk=kA3^q)S#(3~TQh0K=H$97kY6 zBBY5iTt8Xvr}1GU+rVRQpbmae&pYl_|D(E~Ss-+4PB-a%y)-KQ%ehthu&Fk6lh`R? zgz0)lIpu4DqC&240mXzQW`$!4Tfs;}q3qhZc93{UZZI-1PIu3>i*jxVF}E3nb4hc8 zI}$0^zX(flIZqn)3C!6DaXj`pdhI6B$=6OP<)b(B7u!Z0Utsws9K1^?G5@F~--HIl5|QI&hKaHW)Q+Ha|gR z94NyCc9ar`J`6f7_c5%r8`V2p$sySzW&Bi>$WM11L7CK<&J^%0oI)2dD-d_uH<{?1 z6gf{Jr05i1rpI^nZrBGCQ{Y(Y2HFegka!a=4_)J_{b>3Z8J|GHZ;nHzlPkHQs(#Xw zRIs2{e)|^%C6Y*II%_Zeq5e-e6|S+OnxhR})BG zK7PY{CZ4A=N>*FDUk1)aQy(CsT*W+NWyx4vtQr%u1Od}a%KmO#wrJLn#{4$1Xl{P) z*CrxxMRyj^JM@G3@%3sdd>Nv$3Rfm` z96PVu#cmSZN$o-IK_2L%N6yS{xp_dz%~9Gm-jIXqd!Blzr01uqY0#W|`ou7Gc? z_OPp{;XmEuQ1x?h=^wRYD4Uy2LPvWnkz1H}=0-+v^;K> z<y{7#D7q#Ph*;Bf)iD1S<>=|h3Y|!xO;wo zi_>=AqasZ|St93kP*BAzd8a_cK8BSJf^g_Y4;>gKT&2$l zFB~^1RmWJ+Zk%)Pe%7HKJJ^i#rOFaw>uD?snb$?d+qJpa%7;8XP+j_-)xvff+@0`S zWZYIzdgI-Py_J{?_WYwNDuyD5Xm2S(t(4i>!yjgnDrvI2D0J*7YKSx{ImnHCWlxXf zj)e$}KFd}7W@`7H;;*>FrafLsS`E00ITnPrro+Z&oTOrEFsyBTynh}x1hv(es^!QV zqtU8~y_?Ns-FJZ?B^!jPHW{0&gxz+0MiVZaXd^Gg(7tLvFbC%k&$WR`RH z?~zaJ`|$8VMJKbC%Mp>W^6w<)+9}Dg+=w+gTDkIiw}qXiQ!vnv{G3p+SS_6caXCjR7$!o(9&`@Rx&)EJ*Gh84K- zLh1RV>DKs}CH53Ko2DmtFi&2xlM5~)Rm9facy%e$7;ft0quCu{QWv{YtjV#wtAn6Y zuxTHr4&0VWfjBE$8VLc`c>O@((2knJHUgW_iZl7;+L6^(1ln6M73GC>xBxWp255qr z9k#k9U)2zYs~w)Z^A_W2Kt-aC&X(NMRV#jDc=ezI^q>|tFfm!p?3pvU=G3T5oGx;? zJ$Val-Bn8Yt|&WxW~rRSQsP1n8^C8W@1|d8)=K^a!1`z2aXX6ja3k14tlkNgJ$`jj zbH)35QWLJHqoWKVJokLDC%mE-#|qWKFc>1eI9Bmp;Q@z+TPgP}&J?J_H}kl4!bg*= zD`|9?qa}=&H#rvT!C!Sz4I!^X2BNOq@2?L+iub%H2qAj8g8sjOuKGAC1COWUh@Wc8$+9 z)s_-r^j>qE9al}`ku4O0dQWHPV&~=RbiG>^H=n$}`U)JG^%HRhj&KU*0P}TK(v9sD z#8n1Ob>(Ga5H%^XNk)$NL9drv-A;U$cn(&53p~gw-Ir-?#cRbAx?Msn8mz=??1Vw} z1nG7t>>+6EHr{vM1Z=GVbnJMw#hS}ezG*WCUuTHe7 zq#Hsh@np#D6YTiG#^qM zp&X%5hixU4Mo<9G19JPk*xZU4rU3h^otXCq@`$}VucTu-iAp@?cwK{+x}UO)DebxT zhL0p#Vii=s0#-dUXemNZt`97o^EPx70kdSkX9^>Xl7qRu67?F^pX!$$P3?p_f9As4 z(?@(YoX>}?_DXWycVg38fmB0Atg4A;=>mT4@~I%UXQtnkC|Q^s#C~8It8hN<*(VO$ z)zSQ(e(Qtt3^|A4^2e)N(;Ofod@SBk^rqj*pnSe{uh8!_D@LcqeIX3j6LP}g#=ZNt znCTm%=3y$?Jz3M7W9Xy=H!bq$pcCmPPkkqmNQB_elwhtsraaZ0yLLo}2e3N6dr1|b zSAZEPx=?7PKq5^dV3;e>&LxG0HXTYph`-kS|8|&IZ0IqsvCT<|7jgZd2V8#&MnjvvNra z6i7Tg*pd5ytGO;U^=N>#P&Q^Io{bnJP+yh)zUHPZFrR=;5WInZEEEuhxJf#EQ(l{C z6xlxbS}*&vz8~hB;5PHS>i|AXqoRn`y+rT?J`PsC#9Z%CTm0zd4Zr>UkMOAzHO2su zp)2-E47JJkWG*a&WWDjKGbtjZd z`U|vP9#C({>0qsVr#p1JSidE2g{2a+38v;YIQj4>L}ydua_uZrM>oUg(Rmc=Gqg@$ zP#NkjevVCH@6#-eu`qQuzMrK^jUtzCRXDjIoWOW*ErN(ynsQT+YaE0kDjdlx!#)&A zMj7p@XOtpsQ>zJrVbEf( zIXo9A?nS&>jtX^HJdf_ifd#lpR??0pBiH7&%2IxK@5HR%V2}7vCiy$F*A+})EpTH( zaMVMa_b}x6E7XY_?Z`Nn-bDW5Mw9T=_GK3%l~_el{=uo=hpV0DHg6QJ7<~+h}_7 zIptXSY*Bqjt+i16G|o&r|(lyV5FeztlxA-XDZXLoxz3CH0}m3x=8gYB;H@WF0SYIX!BFd8Rz$Afu;t zI3s=?CRS`FY#C<0%5evc7gI{PM=l2))4wH)(%xC$fGPlFjoZ#^Fae$CoQUaC+C#CL zX$@Xawm~nzR*@c!?7Tl2JuZsz3gwN=d;-bv9<4tN^S?(372~Hg>ucdUJhyPcRNyI- zMvazsM%^N1GxPIySnbQGZGNiV-|XfBtBPsiX*7`CX;TbuA7IDY$l;x9U8^v7!-gmc z+^Ej)VTCS2S~WX43%VWhE-x$*ltck=;X}9gj00fCuUF$DrGt-R29mwJcB4hKS%vj6 z7DUcUw@SG@>;|jmJRtBCCPj+rr0d7bp0remVGqe*NBgYxA|&L4Ay^9VV55TUa{G~3 zCTE`mE{jhFk%|~uOg-bL{gZ^I$*d1^w{$Y=#l>8NBd*_%jipLEbk{||8RkghsyvHV z>bg*1P#}PuL)m=CV=i`OgB!z;lKne|>lyl}4O$zCDvM<_s@@Pcq~W8{)XpwK=Hjv> zSmB$ln>NaI$V&0++4uCqTFehG8zGJOTWmRJ4=?L35U<2^VKx(vX9r%vAK0vpmNxlD z+%5%qeFK|OI>+4DTzeazUY%rDVIolsT;^h;g`c17Lzvd+GyNk(GdGjYANGf(oT$%nw0f?-Tdk{4 zC}Bi(GtW1sZE)msZfp8(P;P2ihkHW~rwh78V7f8hjZnFx_%{~fAllo-=HXof<%|@w zK%5px&@J@d9@;_X6v67v-xCzE1oZNHtvpkz_Oq`g(bua?V1- zM$xR4gx_^kjz9ORaS&f z_gj0DjE8@)C>@c3C^Qab_*%*vtP(-#GalqAiaLvIRP<7BxUh)q!`;g@2fVji(~vqO)OW2#V^^eSW!vc_YvyN<{5D!K^wqQ zdCik~#`biGEM}P3^ep%qqWBQGmJQ&qv43Un6UPG0u2LCG@d521Q)RiF1^IiLG8Gyc z{5FG(*5uyLX)2!x9h{Sk9c)(fldh}^#AyFNzxVKoFiMe%IbJ3=vtU6(Yoxi7P}Fkf zS*#e1^Bj%)Qbf|VEk1Raf0wF=(nrX>S*9Mw(3(VM5xA<`+=kpRW$1|ZMWIOUoZyLm zw@tT6=bS(e-^m(ZMLNZM?YN@K{9A-1+q-&HeZ6cBmSqEQj%9gx=g)MXZ*pl_@UbbB zH|~{RT-`qI<$em`m_sgHToMj44$SIiELBoV60UM1ZdRq(}g>?D^lCx3;n86he$Cqj?7{U=`bPz7R#PIGIHeBsevU>~z zC55Fv5jh%e~AcAp&%{SX^XAgo7~?Kwm%PqGCZTUU&1 zRR+rE6}C2&LJ&(}L`T8JJ;~$_86uaLtaJ2jE2SE=#Q>#f@EOiF_w> z&xebx`Xu;pa720awHQCV&*9CXFfpS5`|a;Wg2Zj3kfLTdnl@tJyC!RUI_W)?k0^K3 zV&Zo*TdRzv|4hg_+Xx4MRk%cN3HJe@7~WlAk|!L5%v0|Dkqc>45cc+2UXV$aQ(y(b ze8W4&-b;f=Vs@t9Rg!@Rld{Tl4bebLM=Nkd&AFoM;xGu8`fPTbN}3xbUIp9)9U{MY zkpId|0E&wCA{>BZ0Jim)l(kG9mD5_w09&%C3HFpo2?F4*ZK0xfhe(vumtKZi+DI~N%o1<&8n~Q&Iz|pt(eaSB*zoYb z!*fL{R6e-o+`ua6=T3$RiXtEA0FqaJ`A+Zrwmf%oSSNeCZ!BtXT9BgXr?GR7jMuak5qMHg2upD5ZMj&{ znO29$Lsn`$j*G9h5}WFGOUG@dp``?outVqXb~tEnO+RMGS{!mXd#KykHgeNd``}wt zr8nm+2>cNM?|!V!KD`&Oeh15UCVx|xvQ!b-9~oWNJS6B~{X^-~#})3KIogn}IS>AA z9$*|e@P67I@r(8J?YGS^>mXv7+SY1dIj$@A(I;n5pD*u@ z^5pha1F6G+>}h?x&3y_c#ip(I>(t@tQy?0yXr690(XYrA+=*s+ywZ(BIZ`W*_?S^gCC-W5p*!^+Y9~t<4&(Zp(LZH0Z%P9}% ziLsM;bxC6?rvbYKf-r#0r3EROb|~^qiQVZH>MAP93JU}a0P8Epaxzsh`>~S zdpBKD^EnECSkkh^JdvBJcJnG>lgQT=wj(JTeEo1*WvBIe7c@pErAdQ|#X1$Q_i?f( zRhAPEO*`8~1|ggrh>iJ9cisLpHBkD&VPK@aB1aDtQSunPY!uJHln$|$YqV^BMjAt> z|D;BnkKmwW#-hcunVTi=)ov)^$_nX`O?`0oKV#I#0Y6LNwvFbAIBo8}BB=OVAzZy* zKE@h;x_~=XF;BK!Mr~vRfhNwKs}y+XWd5wP_;O>!Vib3h7Dklg3=PDfj+;%$Ia|BZ zw4*lp=Z+xMA`ME+U*{df+Tvl1P0YcP1GJu zD7)?s;k7fM6rQswDQ9xEBm z{|BNdX^C30nxOO56WH?^6<^!9=M)=x)Rz>9Q>6}^5evkw**MYgOOKga@EfgKRvw|} zS!H%*e!V;k{7~8sJcI*R*Mf6?UT)1s$xXB&vNG|Gub_Nn`>T9J2o-@K*F`(nrSSnz z`LvSjj$HdkVX73EfmeN-7Q0IX>hs20%d4kqgsN*GA+|E;$Sc;M5OT=25s#qQhSxw3 z($B{^h%x>H+*5WS-rBRX7d%ziiH?ioAo}*@<6_hV45l4pT?Jsd4JX^;<{hmCY)-da z`G3T<^b}rBX0`tPHSb^Hhz8s9zFy+bX?qyK zG=24|gCyK^hz~gpilvzap9<}dcGG6s-X0t{?ylGVPCGT*gHb9m;`$;0PgJw7wA3XZ z?~seU%C^gKw$vM5R(*WT96Gmte4ffW8MuZmf;a|_1&@L8CH?9hPSfWkUH3J77l5;2 z{HY5Nk+&p&R9x$G3i_IIH0ODEG=h+)#PKfz=lP zu~_Pcst|#u=S_9C+9}}DjYFSK8AfrE#0(Rhdrr0prD-stp$QRzu&o1{P`WwJF)|Wz za6qkZmY3np(lG&V;;$D5PASAv!I^Ca81hZMbIs=)Ph+Uoj?n{g>Qc;7=)zt6YF?Vx zdZ1DX;ZG-zyI21$Ze=)GFZDe-{;|)vaFTy%TD7uxNT@-~esm4Xnc)MN$KvP>mDnq` znIDx0(+#qY^QahO?s)xEd*hscRAtS_o=!p$_Mq&r((GNXyBD8!3{ty$LDpDQV!4ub zb99kG+hxgoeo$S0@Mb-QXH#2OAAxAEVVqifM-jAz4A7>BhJ5fs+K!$|@L=(aV%Rix zT+CPn(yXxhO3}M?3n5qcCFB>AkJiUEP2zauy`<;reVN%BKq*`2k;gv2X6N+IaUC^t{TZ}L>hO&)3o#buy z+rba@NjXVoqa1(M2Q!Xy>vxqd@7J@>z-en*liI1av%;(r&5P?+rL9wH9~o!r(tp-y zXJFukMKcoR))yT0>H^z*P!LQe0>a{VT!VoyUsOxZ6+B46_IxprLt@=!YH)U{Ubd|4 zaWMcJ9qE~q!YAhSNT(8yMtez5*SW$UzR|u^`nEfkUl2^>g{|1)m_0QngMus36JXp4 z#PLjHCAb%uQ^sdOW3e3^Me<WuDr8#WgWFRoJ9d@NpfaBl@)sos(Xqs#EYRQVzjpr z)PPoLWu@b&>#!?g%F%H|ped78K3=Cq7i=lTdnF#2KL}L* zTtOxvJEM|Jv)j6==*3@R{j$V;dI6cUL7(PRJktA8lniFycQ*|>P3=b>Y_BkN6b{iZ zJGx%En$2i@0=JIn`ugNGgw%1YR?vxAN5RJK%G$YR)QZb5o%H|5fa3ew?7?b7q5YlI z2WUc%z)}nG{R~=8N}+o2D-Xk2Ch)MlXEwb$h8hBUurYx$Tz;D)B2?DMh1-=$qpNp& zKy!7=D*aFYHAWo9c=Ryp&R_pS7 zIiIE*zGX;;4~e{~b#m$DHh?)=3QDME{eFaI5hk*jYXyg#C4@fdgj*l%)~wOiyFnNlu4gj!8?CTqm2&GMgqB^-t8Z(AoeA1w-y z`Y{DyP%xcR@*A9ID2M3WM`AkZrDXM6AF;kyRh()PL5v(AE5i$leAn$ZBIVQs>Gw|T z!gA2jnaI)!Q4hRxQcnyYuyvveQtwrXOC{7rQQaZDnNPyU(OF<^EQ@O z;Iy?Ci@7!)&ZV(DO7_`NkMVe-y~6~$eb!(Pt`llsqxV+bmQ(>*el5OAQDurP7PB6m zF9Sn#o}@)`{8hj$Af3!bZKyAO`#n6NTBL>7X?0M04zJX7uBlOPN_w6YUXcd?x=w?& zhe1cmWP9^Y-=9?^_)N4NX{nkd=5-TpW_?43SE*(1GSD=xS6lrZH>fVdCb z1jc{>agS$1f=qzWCotw;m0mAzQ4EN3S&Lmu*|SmSFOMPfH#=CK6dgJQtoTV-sK$`A zxRlRiZN-gNgf7OL*J6r15P)x-UfH$BgLublgLZ32#L|}d73%Urk;j4~TAmsmLrcAR zi?}y&l~cIvjh0LQw)kxUBJQ5HFUN z7iI~86y^+iA9+NqKyRV(3P>rlD{nK+=8`&Wj~x+CaQi%w{MC>HZO*e;GolK(F5}{2 zWn9oMd++<#Z1AMd(Rs?ozUjU@*pUwa)+7VvDvr4}0?WJ{=cjI2Gfxa`)S{2AHt5GiK zxhN(e`#k(_K^rHu17@stu4sBbu_Kqko@dZ?Ad6CJHMCmZN}d#!zuH(yULJ*+WJ71WH< z6=OGDFj#$cz&LJ{z4d`2#`(PP^IUWhx?Wjw<>!kO%0KZ_08)c;m|@C+=J+i(FJZ*U zbBk1*>;9&H2B`Y_*Rx4HV{M&1uU1aD7XQ2o{w-ie~TnF}v|b zhabc5tBHT$4gejH@)o?NmdL#G3wC$_+Ih<67iwQ!kY%il-$0Y10rmmX+HMte#7AW5 z_0SCoHdehbqZVh_x**pRC>pG6r09g8E&*IJRRf5m?Z7T$=2uo$TQSkoCv+F^1a6Lg z(3CPMpfS&*h_P^CTz%S#2yeeYFSaZ)W0p$hRKQS1u5Y=>s*j_b!fAOR^8y+e3jkVV zU+cdhM6uuB0Nok)sH}MgvAmiirb2c1Py**&2@R9Bpr37Ty46ShbP=Hv((w~@fkCyI zU|Z;G{}L&=1>bU|MZVDmS@r`m)>_p5u{{K4v|0=(wg9-8+jgBu$0tWePhYatbnAhd z&jcGBhhCVXX6h9e>noHfNTe@88+0q{aS1$&a!fWQsz@_(aT9<{VHcj|?o+0bU?wd1)N3K^;&kFJ6+rI!*Ze+K+e=I|TNtE3{p98nfB7hh^=!%6_XFMl<#boxZZl##IY zbuM=&V3dLsgTPFEY(lteSSU=$3Yx-7LL2ZbeSWZY<*lJmC4fp^+*~S6VUGflVHcCw zYwYP#2%c1$8WOwQY6I4FvA0sB9_=5 z!l4zfPdSywdj%YW4vkmtRVQKX#v3H9hd@>bTLmE_JJv=We;_OHom7i(HF6-`iV%MKB6lwUr1lZ%RlXwOMH0FTT4Eu?X+1Evdbv(DDh=c_3^m{z( z50IY6A#MQnMJwIHo6MGzP_62SwyxX;0x8#BkZ50XWpzV)WE3O4D_u^@&eTD=h?B$W zaNS#&IYaelZz1^bpYSg0K947mA!hFV)f1WdpiwO3;zG$GuAM4?zOOg(8kR(3-@s$o zY<}s#1ObP?nE6KzI{mkSCs%s_zIPigBQP1-s)?@gT)KEeKc;*eOhaeP9U0~B_*`EY zA~7ug&9m=+eoFpRH}==q?__|-&LrJ`%%AFnz!4c<9V~&O;6B`4IkloOm zD+w?+!Dlkcumeob6=LVt4A*DD@Hqm1{i~MqzeY=fR3%ou`0kxoX&T^UFEnuOzrTOS zr?`FkCy(d(xmH{pmvBZax!U!Ux=7?u(b2)i4Q!;8Ny1}OW-h|OIfZWgYL*7=o&W2k z|Cqslr1VnPdmk+Sc=>--l>SEtydp*n+4JhEsjZwM1jr%Zp$ z2JFXurcS^&Ant)#zdj=0S;(2;D(0Af#{;9ZOi`Op@;v= z_c=Wzi4Bnl*9StD&BZU=q5)%8Mh4{`BiiGazy($U@o!Al`p0u>nF3RFHl)Dw@!xa% zZ(hb<;}-i4C=y)DL`9YRfBC@zoyD66bo4KX#r_!MQ}GUCz?lo^hKsN1_vETW@3ZT9Q1kLCBk$#ugTX@yg)z#Dh!I@-qF3@zAi_W#@1rout z;8MF&)m;nrXWlI@{qI~0+uZRt*qv>VHw6Q`FAO@nhWG)NW(;(iCv~0rfm&%sR1{Uf z8KCiCZCuYT08GD^hlBc+hJiCXbAVVG@OEsvHuakx0)pcf6kx#wJi&m9rg0-bzv&^3gT%Cy+4*%u_Z74YbuRa}K~FVu^*Qys6X#+r6Iwh7F)%y6?UV#L<9i z6i|;Utf&AI?m$RfAzknsuQ{2edrCf>3S!&bF(Uva&MfEg)Oc zKs3%Q9Zm8i7Du#Tlq*6>G+0wqQAI^%IW(U7byzicx-$RPYgXQ0CYT~|7MN|!18K3B zum8=P2}0(=wMr+zWjdPfIn${ZbIm-E}`mX+-t9E=1NrH_xLl;N6ybpJN7F3uj~P@45jT{!5(A`krET-7gU@(W-D zKLU!x$GdQWgB=ud9%W)`TGu#fmI1c>RMALRG3&dGtEK5u1H*%sTNvTCk(Y3_>(**D z$_n@v@I<|V%x#(~F8J0xw{YMX5OnYTmrD;&@<$4tB+^JP*t>(32z1`Dg4*|4LCby( za2iXcfQ|wP&WK_FGFZ#8LO_p>02FuE`rCkQ6nQeU*R&@b)b0R88&Yf=ExeqMIL8!qwJM0C7&cRFvTP0HZ*HWD#aDcRUK>NZ!*3Az_5RJfb z{c?yY0k`=Dc%KPc**Ya<&)>R)<&%1-G@Pwzl?B;unAP*8NUWK$?dY zWCY}%0fV0zR01qBJr!Uu_4M?ZUqw=iq(?;!Pu)Hy1Ihw`X}@^3Kn(r^8D{!EI z3kp8PZR`X72O5b<4$kB^UyfraEu2k78| ziMyWIc)u|ekrsdY)bQgSCfFj;c>QEi*=U(L_Se$5FCP2_-~ms`C8fOcq}LHxaA5zg zORqnymo^-a0S^%pDA^zF&7*)~g2>f=WO?&JkGlql3kN7vVr9U*0k6js%sL>V1Yrfc zeUMwdtW7|>y{m~8L|^eAvtMgNZQ*Jf5WoV-93Z8j0GM^reT3(Me3_nx2Gq1a87TOO zoG-_KOOu4Jwjg!^al4MC<)%0>q{d=2AJEdm^jg6`8XNf|yPVe2-0t{)(a`r%D;`e= z>eW!VD=^;xg8mvnkf#FpgMobxzyb4juF@z7=ZTOIe8&~g*rUe5A>i2e4@g~sa)=!u zC${rL%m6b7>=jPi)^Q`;HfI>H;Zk@kM*)W}N#S7(X7jcC0W?47Kv1LOybugopL?Tj z9w3Jc0#V&M(6h=*(9?!M0I?ozK;kolcfdOW9eN-o9f;E&ge?NpCXaT(KZr$vn8Ueu z%T{@-FPN2XvksCzJ}~B9vr}FWPRQia#{nz-bH9rc{pRmL3k+y25fKwh)}_eNQil-$035(-@8RLWpEj_x51M+VWifEiKTU4MnRx8Y0bk*@7s}RB52V|_0lnyT}AUfs=^99lXKwG1DT*4Q4Y#?JcQ*!~htK=z# zYPta%B%m$91B)Y*v|?rlEM1oS^lWTv+OM0WqQ`VWxrbAXo+?10V01$vedp-N8K!4f zsY!yWDa8eW_+zD@kX!)+%y6gpa_*%RP+ToX`c zm@RWo^{lML8Ix=){WC$vG^C4FfIZehGGw#NSgXZzL9eMZmGkq%gqsl<4##aUQeU2T zOe$cL+6RL1@F~VE7lu`Lq928kOPjwQy{IYLL<{RKAHgJvsA#-N8OTvQX@S9^MGqtk za{?oAqzN8V4(o%xx9V%%@_-v?IQrKgz-#HHgO_Olb@(H%eA=y>FQ=AlbeI>l3D7d> zsKKo|N`3p?)X#JO*;a<#`muZpYd6^Zx!6lij9U*(?0uxh`lz0WGiB_f!{a zwEXeR+^m0TkDOSv57sbP=*#dlZf;)g+tnA<`LkOKVVuY=zlTR6kvmO`%{33ub=iE? zY429<4`&^!9JMC;Nnz~oNe-kPh&t4FOnNwiJZ&f@3cPGS`sFu=ew4&`PrMypNavM* zE}|TtIT&eW^r6tg_|(XFwlOdr8l>6&@_bgXTDf@tVtMOIWxEVBEmf7sQOWW=Zygxq z7m5-go1M!_p?tJ7ohPyvNbEx=RhK1nTFBw@7m+#58ecn;c27H?`Edn za%oCGlCEvhy%r_X1o3Kd2=W)j`hd+NVA~`p868N5XPR?z!MDJEN_p=q|~(!pES>l$Yh5m{Y#dSB^OeN3$9U(_`#(d7|5s958`|FIf5M<3wECm+{gyk1=EI+x0)P?yudJTAu~vjjp#=WD zK>pfa$uHR3aK}Gu+<;#?+Ax)!jjg<>sAumKTK){2l(qlOGvMlK`Q?ZaVI<)|(Yb*9 zDKI}YSpV3m^Y6ED9ew<}h0Vej1;s|UG3P4guB+$HL^h+2qQTXEiNKbTMfuGdq3Etq aw|wZ70#vl|AAy6>q{S7)%0%D1`#%6AGMOC! diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index f4dcc5606..4fa2fbbe5 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -42,6 +42,7 @@ The project layout should look like: ./tutorial/quickstart/models.py ./tutorial/quickstart/tests.py ./tutorial/quickstart/views.py + ./tutorial/asgi.py ./tutorial/settings.py ./tutorial/urls.py ./tutorial/wsgi.py @@ -176,12 +177,6 @@ We can now access our API, both from the command-line, using tools like `curl`.. "url": "http://127.0.0.1:8000/users/1/", "username": "admin" }, - { - "email": "tom@example.com", - "groups": [], - "url": "http://127.0.0.1:8000/users/2/", - "username": "tom" - } ] } @@ -202,12 +197,6 @@ Or using the [httpie][httpie], command line tool... "url": "http://localhost:8000/users/1/", "username": "paul" }, - { - "email": "tom@example.com", - "groups": [], - "url": "http://127.0.0.1:8000/users/2/", - "username": "tom" - } ] } From a780e80debac0d12bb62fbb0ed98635e601e76de Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 15 Dec 2021 15:16:38 +0000 Subject: [PATCH 067/228] Revert "Make api_view respect standard wrapper assignments (#8291)" (#8297) This reverts commit 9c97946531b85858fcee5df56240de6d29571da2. --- rest_framework/decorators.py | 20 ++++++++++++++++---- tests/test_decorators.py | 10 ---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 7ba43d37c..30b9d84d4 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -7,7 +7,6 @@ based views, as well as the `@action` decorator, which is used to annotate methods on viewsets that should be included by routers. """ import types -from functools import update_wrapper from django.forms.utils import pretty_name @@ -23,8 +22,18 @@ def api_view(http_method_names=None): def decorator(func): - class WrappedAPIView(APIView): - pass + WrappedAPIView = type( + 'WrappedAPIView', + (APIView,), + {'__doc__': func.__doc__} + ) + + # Note, the above allows us to set the docstring. + # It is the equivalent of: + # + # class WrappedAPIView(APIView): + # pass + # WrappedAPIView.__doc__ = func.doc <--- Not possible to do this # api_view applied without (method_names) assert not(isinstance(http_method_names, types.FunctionType)), \ @@ -43,6 +52,9 @@ def api_view(http_method_names=None): for method in http_method_names: setattr(WrappedAPIView, method.lower(), handler) + WrappedAPIView.__name__ = func.__name__ + WrappedAPIView.__module__ = func.__module__ + WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes', APIView.renderer_classes) @@ -61,7 +73,7 @@ def api_view(http_method_names=None): WrappedAPIView.schema = getattr(func, 'schema', APIView.schema) - return update_wrapper(WrappedAPIView.as_view(), func) + return WrappedAPIView.as_view() return decorator diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 116d6f1be..99ba13e60 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -162,16 +162,6 @@ class DecoratorTestCase(TestCase): assert isinstance(view.cls.schema, CustomSchema) - def test_wrapper_assignments(self): - @api_view(["GET"]) - def test_view(request): - """example docstring""" - pass - - assert test_view.__name__ == "test_view" - assert test_view.__doc__ == "example docstring" - assert test_view.__qualname__ == "DecoratorTestCase.test_wrapper_assignments..test_view" - class ActionDecoratorTestCase(TestCase): From f4cf0260bf3c9323e798325702be690ca25949ca Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 15 Dec 2021 15:18:24 +0000 Subject: [PATCH 068/228] Version 3.13.1 --- docs/community/release-notes.md | 6 ++++++ rest_framework/__init__.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/community/release-notes.md b/docs/community/release-notes.md index d3e9dd7cc..8629e4fee 100644 --- a/docs/community/release-notes.md +++ b/docs/community/release-notes.md @@ -36,6 +36,12 @@ You can determine your currently installed version using `pip show`: ## 3.13.x series +### 3.13.1 + +Date: 15th December 2021 + +* Revert schema naming changes with function based `@api_view`. [#8297] + ### 3.13.0 Date: 13th December 2021 diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 88d86c03e..8b0679ef9 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -10,7 +10,7 @@ ______ _____ _____ _____ __ import django __title__ = 'Django REST framework' -__version__ = '3.13.0' +__version__ = '3.13.1' __author__ = 'Tom Christie' __license__ = 'BSD 3-Clause' __copyright__ = 'Copyright 2011-2019 Encode OSS Ltd' From 45082b39368729caa70534dde11b0788ef186a37 Mon Sep 17 00:00:00 2001 From: Guilouf Date: Fri, 17 Dec 2021 16:20:14 +0100 Subject: [PATCH 069/228] Fixed missing "fields" meta argument in docs (#8243) * Fixed missing "fields" meta argument in docs, leading to an assertion error * Update docs/api-guide/serializers.md Co-authored-by: Tom Christie Co-authored-by: Tom Christie --- docs/api-guide/serializers.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 4d032bd9e..da57ac0a4 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -524,6 +524,7 @@ You can add extra fields to a `ModelSerializer` or override the default fields b class Meta: model = Account + fields = ['url', 'groups'] Extra fields can correspond to any property or callable on the model. From bce9df9b5e0f54a6076519835393fea59accb40c Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Wed, 22 Dec 2021 15:08:58 +0000 Subject: [PATCH 070/228] Make ReturnDict support dict union operators on Python 3.9 and later (#8302) Fixes issue #8301 --- rest_framework/utils/serializer_helpers.py | 17 +++++++++++++++++ tests/test_serializer.py | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index 4cd2ada31..54068f5fb 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -1,3 +1,4 @@ +import sys from collections import OrderedDict from collections.abc import Mapping, MutableMapping @@ -28,6 +29,22 @@ class ReturnDict(OrderedDict): # but preserve the raw data. return (dict, (dict(self),)) + if sys.version_info >= (3, 9): + # These are basically copied from OrderedDict, with `serializer` added. + def __or__(self, other): + if not isinstance(other, dict): + return NotImplemented + new = self.__class__(self, serializer=self.serializer) + new.update(other) + return new + + def __ror__(self, other): + if not isinstance(other, dict): + return NotImplemented + new = self.__class__(other, serializer=self.serializer) + new.update(self) + return new + class ReturnList(list): """ diff --git a/tests/test_serializer.py b/tests/test_serializer.py index afefd70e1..c4c29ba4a 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -740,3 +740,25 @@ class TestDeclaredFieldInheritance: 'f4': serializers.CharField, 'f5': serializers.CharField, } + + +class Test8301Regression: + @pytest.mark.skipif( + sys.version_info < (3, 9), + reason="dictionary union operator requires Python 3.9 or higher", + ) + def test_ReturnDict_merging(self): + # Serializer.data returns ReturnDict, this is essentially a test for that. + + class TestSerializer(serializers.Serializer): + char = serializers.CharField() + + s = TestSerializer(data={'char': 'x'}) + assert s.is_valid() + assert s.data | {} == {'char': 'x'} + assert s.data | {'other': 'y'} == {'char': 'x', 'other': 'y'} + assert {} | s.data == {'char': 'x'} + assert {'other': 'y'} | s.data == {'char': 'x', 'other': 'y'} + + assert (s.data | {}).__class__ == s.data.__class__ + assert ({} | s.data).__class__ == s.data.__class__ From 5b2abbed25ef41c4cc1b3806037c6bd7631db327 Mon Sep 17 00:00:00 2001 From: kaushik kothiya <46051127+kaushikk25@users.noreply.github.com> Date: Wed, 22 Dec 2021 20:47:57 +0530 Subject: [PATCH 071/228] Correct variable name (#8306) urlpatterns name variable name in space remove. --- docs/api-guide/format-suffixes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/format-suffixes.md b/docs/api-guide/format-suffixes.md index dfdf24953..da4a1af78 100644 --- a/docs/api-guide/format-suffixes.md +++ b/docs/api-guide/format-suffixes.md @@ -62,7 +62,7 @@ Also note that `format_suffix_patterns` does not support descending into `includ If using the `i18n_patterns` function provided by Django, as well as `format_suffix_patterns` you should make sure that the `i18n_patterns` function is applied as the final, or outermost function. For example: - url patterns = [ + urlpatterns = [ … ] From f9ccbad4d910d19e4298300ee90467051fc08f47 Mon Sep 17 00:00:00 2001 From: Suntae Kim Date: Thu, 6 Jan 2022 22:55:44 +0900 Subject: [PATCH 072/228] minor update on tutorial serialization (#8323) --- docs/tutorial/1-serialization.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index 908b7474a..67746c517 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -45,7 +45,7 @@ We'll need to add our new `snippets` app and the `rest_framework` app to `INSTAL INSTALLED_APPS = [ ... 'rest_framework', - 'snippets.apps.SnippetsConfig', + 'snippets', ] Okay, we're ready to roll. @@ -77,7 +77,7 @@ For the purposes of this tutorial we're going to start by creating a simple `Sni We'll also need to create an initial migration for our snippet model, and sync the database for the first time. python manage.py makemigrations snippets - python manage.py migrate + python manage.py migrate snippets ## Creating a Serializer class @@ -307,8 +307,8 @@ Quit out of the shell... Validating models... 0 errors found - Django version 1.11, using settings 'tutorial.settings' - Development server is running at http://127.0.0.1:8000/ + Django version 4.0,1 using settings 'tutorial.settings' + Starting Development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. In another terminal window, we can test the server. From c5be86a6dbf3d21b00a296af5994fa075826bf0b Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 11 Jan 2022 13:01:25 +0000 Subject: [PATCH 073/228] Update sponsor URL (#8328) * Update sponsor URL * Update index.md --- README.md | 2 +- docs/index.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 18d1364c6..d8fd83d67 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,7 @@ Please see the [security policy][security-policy]. [cryptapi-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png [sentry-url]: https://getsentry.com/welcome/ -[stream-url]: https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer +[stream-url]: https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage [rollbar-url]: https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial [esg-url]: https://software.esg-usa.com/ [retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship diff --git a/docs/index.md b/docs/index.md index 2954f793a..4871ba458 100644 --- a/docs/index.md +++ b/docs/index.md @@ -67,7 +67,7 @@ continued development by **[signing up for a paid plan][funding]**.

    -*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=sponsorship&utm_content=developer), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), and [CryptAPI](https://cryptapi.io).* +*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), and [CryptAPI](https://cryptapi.io).* --- From 94eb804abe5d414d59b3a84332e93fbb58811e9c Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Kushwaha <33164379+kushshiv@users.noreply.github.com> Date: Mon, 17 Jan 2022 15:11:23 +0530 Subject: [PATCH 074/228] Update filtering.md (#8331) --- docs/api-guide/filtering.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 512acafbd..9a4ae2745 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -224,7 +224,7 @@ The search behavior may be restricted by prepending various characters to the `s * '^' Starts-with search. * '=' Exact matches. -* '@' Full-text search. (Currently only supported Django's [PostgreSQL backend](https://docs.djangoproject.com/en/dev/ref/contrib/postgres/search/).) +* '@' Full-text search. (Currently only supported Django's [PostgreSQL backend][postgres-search].) * '$' Regex search. For example: @@ -374,3 +374,4 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter] [drf-url-filter]: https://github.com/manjitkumar/drf-url-filters [HStoreField]: https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/#hstorefield [JSONField]: https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/#jsonfield +[postgres-search]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/search/ From 02eeb6fa003b5cbe3851ac18392f129d31a1a6bd Mon Sep 17 00:00:00 2001 From: denniskloyn <97915409+denniskloyn@users.noreply.github.com> Date: Tue, 18 Jan 2022 08:52:11 +0000 Subject: [PATCH 075/228] Change `MIDDLEWARE_CLASSES` to `MIDDLEWARE` (#8333) The `MIDDLEWARE_CLASSES` setting got changed to `MIDDLEWARE` in [Django 1.10](https://docs.djangoproject.com/en/1.10/topics/http/middleware/). --- docs/topics/internationalization.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/topics/internationalization.md b/docs/topics/internationalization.md index c20cf9e33..267ccdb37 100644 --- a/docs/topics/internationalization.md +++ b/docs/topics/internationalization.md @@ -17,9 +17,9 @@ You can change the default language by using the standard Django `LANGUAGE_CODE` LANGUAGE_CODE = "es-es" -You can turn on per-request language requests by adding `LocalMiddleware` to your `MIDDLEWARE_CLASSES` setting: +You can turn on per-request language requests by adding `LocalMiddleware` to your `MIDDLEWARE` setting: - MIDDLEWARE_CLASSES = [ + MIDDLEWARE = [ ... 'django.middleware.locale.LocaleMiddleware' ] @@ -90,7 +90,7 @@ If you're only translating custom error messages that exist inside your project ## How the language is determined -If you want to allow per-request language preferences you'll need to include `django.middleware.locale.LocaleMiddleware` in your `MIDDLEWARE_CLASSES` setting. +If you want to allow per-request language preferences you'll need to include `django.middleware.locale.LocaleMiddleware` in your `MIDDLEWARE` setting. You can find more information on how the language preference is determined in the [Django documentation][django-language-preference]. For reference, the method is: From f378f98a401f28df4ef9bdaf3ee56a1017c195ab Mon Sep 17 00:00:00 2001 From: Sevdimali Date: Thu, 27 Jan 2022 19:02:20 +0400 Subject: [PATCH 076/228] if else optimization (#8340) Removed redundant parentheses --- rest_framework/decorators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 30b9d84d4..3b572c09e 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -142,7 +142,7 @@ def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs): how the `@renderer_classes` etc. decorators work for function- based API views. """ - methods = ['get'] if (methods is None) else methods + methods = ['get'] if methods is None else methods methods = [method.lower() for method in methods] assert detail is not None, ( From a5d741aba473d5099d59ff622dbf9702df842441 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 1 Feb 2022 09:42:43 +0000 Subject: [PATCH 077/228] Update renderers.py --- rest_framework/renderers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index b0ddca2b5..8824fa660 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -105,7 +105,7 @@ class JSONRenderer(BaseRenderer): # We always fully escape \u2028 and \u2029 to ensure we output JSON # that is a strict javascript subset. - # See: http://timelessrepo.com/json-isnt-a-javascript-subset + # See: https://gist.github.com/damncabbage/623b879af56f850a6ddc ret = ret.replace('\u2028', '\\u2028').replace('\u2029', '\\u2029') return ret.encode() From c26ec5a3b8080d528112557f86423aee317ed8a4 Mon Sep 17 00:00:00 2001 From: Bhuwan Panta <67514385+Bhuwan-web@users.noreply.github.com> Date: Tue, 1 Feb 2022 19:33:22 +0545 Subject: [PATCH 078/228] Update 6-viewsets-and-routers.md (#8349) # Basename key missing in the tutorial ```diff +router.register(r'snippets', views.SnippetViewSet,basename="snippets") +router.register(r'users', views.UserViewSet,basename="users") -router.register(r'snippets', views.SnippetViewSet) -router.register(r'users', views.UserViewSet) ``` --- docs/tutorial/6-viewsets-and-routers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/6-viewsets-and-routers.md b/docs/tutorial/6-viewsets-and-routers.md index f012677d3..18066f056 100644 --- a/docs/tutorial/6-viewsets-and-routers.md +++ b/docs/tutorial/6-viewsets-and-routers.md @@ -112,8 +112,8 @@ Here's our re-wired `snippets/urls.py` file. # Create a router and register our viewsets with it. router = DefaultRouter() - router.register(r'snippets', views.SnippetViewSet) - router.register(r'users', views.UserViewSet) + router.register(r'snippets', views.SnippetViewSet,basename="snippets") + router.register(r'users', views.UserViewSet,basename="users") # The API URLs are now determined automatically by the router. urlpatterns = [ From 5bea22f32179276596b4c8152616d54a735a5341 Mon Sep 17 00:00:00 2001 From: Partho Kumar Rajvor Date: Thu, 3 Feb 2022 17:57:47 +0600 Subject: [PATCH 079/228] Added http 102, 103, 421, and 425 status codes (#8350) --- rest_framework/status.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rest_framework/status.py b/rest_framework/status.py index 2561d7689..7df26b388 100644 --- a/rest_framework/status.py +++ b/rest_framework/status.py @@ -29,6 +29,8 @@ def is_server_error(code): HTTP_100_CONTINUE = 100 HTTP_101_SWITCHING_PROTOCOLS = 101 +HTTP_102_PROCESSING = 102 +HTTP_103_EARLY_HINTS = 103 HTTP_200_OK = 200 HTTP_201_CREATED = 201 HTTP_202_ACCEPTED = 202 @@ -67,9 +69,11 @@ HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415 HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416 HTTP_417_EXPECTATION_FAILED = 417 HTTP_418_IM_A_TEAPOT = 418 +HTTP_421_MISDIRECTED_REQUEST = 421 HTTP_422_UNPROCESSABLE_ENTITY = 422 HTTP_423_LOCKED = 423 HTTP_424_FAILED_DEPENDENCY = 424 +HTTP_425_TOO_EARLY = 425 HTTP_426_UPGRADE_REQUIRED = 426 HTTP_428_PRECONDITION_REQUIRED = 428 HTTP_429_TOO_MANY_REQUESTS = 429 From efc7c1d664e5909f5f1f4d07a7bb70daef1c396e Mon Sep 17 00:00:00 2001 From: Josh Date: Sat, 12 Feb 2022 10:21:59 -0600 Subject: [PATCH 080/228] Update `accepted_media_type` argument in Renderer docs (#8364) --- docs/api-guide/renderers.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index f13b7ba94..67dff441c 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -257,7 +257,7 @@ This renderer is used for rendering HTML multipart form data. **It is not suita # Custom renderers -To implement a custom renderer, you should override `BaseRenderer`, set the `.media_type` and `.format` properties, and implement the `.render(self, data, media_type=None, renderer_context=None)` method. +To implement a custom renderer, you should override `BaseRenderer`, set the `.media_type` and `.format` properties, and implement the `.render(self, data, accepted_media_type=None, renderer_context=None)` method. The method should return a bytestring, which will be used as the body of the HTTP response. @@ -267,7 +267,7 @@ The arguments passed to the `.render()` method are: The request data, as set by the `Response()` instantiation. -### `media_type=None` +### `accepted_media_type=None` Optional. If provided, this is the accepted media type, as determined by the content negotiation stage. @@ -291,7 +291,7 @@ The following is an example plaintext renderer that will return a response with media_type = 'text/plain' format = 'txt' - def render(self, data, media_type=None, renderer_context=None): + def render(self, data, accepted_media_type=None, renderer_context=None): return smart_text(data, encoding=self.charset) ## Setting the character set @@ -303,7 +303,7 @@ By default renderer classes are assumed to be using the `UTF-8` encoding. To us format = 'txt' charset = 'iso-8859-1' - def render(self, data, media_type=None, renderer_context=None): + def render(self, data, accepted_media_type=None, renderer_context=None): return data.encode(self.charset) Note that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring by the `Response` class, with the `charset` attribute set on the renderer used to determine the encoding. @@ -318,7 +318,7 @@ In some cases you may also want to set the `render_style` attribute to `'binary' charset = None render_style = 'binary' - def render(self, data, media_type=None, renderer_context=None): + def render(self, data, accepted_media_type=None, renderer_context=None): return data --- From a53e523f939332189b4ba8db7f99758b7d63e59b Mon Sep 17 00:00:00 2001 From: Timothy Allen Date: Tue, 8 Mar 2022 05:39:16 -0500 Subject: [PATCH 081/228] We've renamed the drf-renderer-xlsx package to drf-excel. (#8396) --- docs/api-guide/renderers.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index 67dff441c..685a98f5e 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -470,15 +470,15 @@ Modify your REST framework settings. [MessagePack][messagepack] is a fast, efficient binary serialization format. [Juan Riaza][juanriaza] maintains the [djangorestframework-msgpack][djangorestframework-msgpack] package which provides MessagePack renderer and parser support for REST framework. -## XLSX (Binary Spreadsheet Endpoints) +## Microsoft Excel: XLSX (Binary Spreadsheet Endpoints) -XLSX is the world's most popular binary spreadsheet format. [Tim Allen][flipperpa] of [The Wharton School][wharton] maintains [drf-renderer-xlsx][drf-renderer-xlsx], which renders an endpoint as an XLSX spreadsheet using OpenPyXL, and allows the client to download it. Spreadsheets can be styled on a per-view basis. +XLSX is the world's most popular binary spreadsheet format. [Tim Allen][flipperpa] of [The Wharton School][wharton] maintains [drf-excel][drf-excel], which renders an endpoint as an XLSX spreadsheet using OpenPyXL, and allows the client to download it. Spreadsheets can be styled on a per-view basis. #### Installation & configuration Install using pip. - $ pip install drf-renderer-xlsx + $ pip install drf-excel Modify your REST framework settings. @@ -488,15 +488,15 @@ Modify your REST framework settings. 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', - 'drf_renderer_xlsx.renderers.XLSXRenderer', + 'drf_excel.renderers.XLSXRenderer', ], } To avoid having a file streamed without a filename (which the browser will often default to the filename "download", with no extension), we need to use a mixin to override the `Content-Disposition` header. If no filename is provided, it will default to `export.xlsx`. For example: from rest_framework.viewsets import ReadOnlyModelViewSet - from drf_renderer_xlsx.mixins import XLSXFileMixin - from drf_renderer_xlsx.renderers import XLSXRenderer + from drf_excel.mixins import XLSXFileMixin + from drf_excel.renderers import XLSXRenderer from .models import MyExampleModel from .serializers import MyExampleSerializer @@ -549,7 +549,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily [mjumbewu]: https://github.com/mjumbewu [flipperpa]: https://github.com/flipperpa [wharton]: https://github.com/wharton -[drf-renderer-xlsx]: https://github.com/wharton/drf-renderer-xlsx +[drf-excel]: https://github.com/wharton/drf-excel [vbabiy]: https://github.com/vbabiy [rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/ [rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/ From 0e3bc2b1e0189ecc143868ca31dd3393a8aa76f4 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 11 Mar 2022 10:58:59 +0000 Subject: [PATCH 082/228] Throttling disclaimer (#8403) * Throttling disclaimer * Expand throttling disclaimer. --- docs/api-guide/throttling.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index a3e42cacf..6fab79a2b 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -19,6 +19,8 @@ Multiple throttles can also be used if you want to impose both burst throttling Throttles do not necessarily only refer to rate-limiting requests. For example a storage service might also need to throttle against bandwidth, and a paid data service might want to throttle against a certain number of a records being accessed. +**The application-level throttling that REST framework provides should not be considered a security measure or protection against brute forcing or denial-of-service attacks. Deliberately malicious actors will always be able to spoof IP origins, and application-level throttling is intended for implementing policies such as different business tiers and basic protections against service over-use.** + ## How throttling is determined As with permissions and authentication, throttling in REST framework is always defined as a list of classes. @@ -79,7 +81,7 @@ Throttle classes set in this way will override any viewset level class settings. } return Response(content) -## How clients are identified +## How clients are identified The `X-Forwarded-For` HTTP header and `REMOTE_ADDR` WSGI variable are used to uniquely identify client IP addresses for throttling. If the `X-Forwarded-For` header is present then it will be used, otherwise the value of the `REMOTE_ADDR` variable from the WSGI environment will be used. From b3083d83ae197e92591116d1cd4231ae9565dbfa Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 16 Mar 2022 11:35:04 +0000 Subject: [PATCH 083/228] Update index.md (#8411) Update security email. --- docs/index.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 4871ba458..e58f24df8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -194,9 +194,11 @@ For priority support please sign up for a [professional or premium sponsorship p ## Security -If you believe you’ve found something in Django REST framework which has security implications, please **do not raise the issue in a public forum**. +Security issues are handled under the supervision of the [Django security team](https://www.djangoproject.com/foundation/teams/#security-team). -Send a description of the issue via email to [rest-framework-security@googlegroups.com][security-mail]. The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure. +**Please report security issues by emailing security@djangoproject.com**. + +The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure. ## License From b521160c92783b9d2a76d6bc3fa30df10d7251ac Mon Sep 17 00:00:00 2001 From: baseplate-admin <61817579+baseplate-admin@users.noreply.github.com> Date: Wed, 16 Mar 2022 17:35:24 +0600 Subject: [PATCH 084/228] Fix code block in `README.md` (#8408) Hi there, The code block below show imply `Python` as it lives in `settings.py` ``` INSTALLED_APPS = [ ... 'rest_framework', ] ``` This pull request essentially fixes that. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d8fd83d67..bf4016751 100644 --- a/README.md +++ b/README.md @@ -67,11 +67,12 @@ Install using `pip`... pip install djangorestframework Add `'rest_framework'` to your `INSTALLED_APPS` setting. - - INSTALLED_APPS = [ - ... - 'rest_framework', - ] +```python +INSTALLED_APPS = [ + ... + 'rest_framework', +] +``` # Example From 070c32f4a62ef0544f58de404c87d86db36fd825 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 16 Mar 2022 12:12:25 +0000 Subject: [PATCH 085/228] Update SECURITY.md (#8412) --- SECURITY.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index d3faefa3c..a92a1b0cf 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,8 +2,8 @@ ## Reporting a Vulnerability -If you believe you've found something in Django REST framework which has security implications, please **do not raise the issue in a public forum**. +Security issues are handled under the supervision of the [Django security team](https://www.djangoproject.com/foundation/teams/#security-team). -Send a description of the issue via email to [rest-framework-security@googlegroups.com][security-mail]. The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure. + **Please report security issues by emailing security@djangoproject.com**. -[security-mail]: mailto:rest-framework-security@googlegroups.com + The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure. From 0b88583a101d6eb95bf9bfb5dd9df47014a45a71 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 23 Mar 2022 12:28:46 +0100 Subject: [PATCH 086/228] Bumped versions in Github actions configuration to v3. (#8414) --- .github/workflows/main.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 42fee2a12..c88dc55cd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,18 +21,13 @@ jobs: - '3.10' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - - - uses: actions/cache@v2 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('requirements/*.txt') }} - restore-keys: | - ${{ runner.os }}-pip- + cache: 'pip' + cache-dependency-path: 'requirements/*.txt' - name: Upgrade packaging tools run: python -m pip install --upgrade pip setuptools virtualenv wheel From 75f19981233c112326b13e4b2abb4b71effd9fbe Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 23 Mar 2022 11:52:26 +0000 Subject: [PATCH 087/228] Update throttling docs (#8424) --- docs/api-guide/throttling.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 6fab79a2b..719378247 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -19,7 +19,9 @@ Multiple throttles can also be used if you want to impose both burst throttling Throttles do not necessarily only refer to rate-limiting requests. For example a storage service might also need to throttle against bandwidth, and a paid data service might want to throttle against a certain number of a records being accessed. -**The application-level throttling that REST framework provides should not be considered a security measure or protection against brute forcing or denial-of-service attacks. Deliberately malicious actors will always be able to spoof IP origins, and application-level throttling is intended for implementing policies such as different business tiers and basic protections against service over-use.** +**The application-level throttling that REST framework provides should not be considered a security measure or protection against brute forcing or denial-of-service attacks. Deliberately malicious actors will always be able to spoof IP origins. In addition to this, the built-in throttling implementations are implemented using Django's cache framework, and use non-atomic operations to determine the request rate, which may sometimes result in some fuzziness. + +The application-level throttling provided by REST framework is intended for implementing policies such as different business tiers and basic protections against service over-use.** ## How throttling is determined From a4334a81260b15df07550f7a9e96c1753beaa269 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 23 Mar 2022 11:52:45 +0000 Subject: [PATCH 088/228] Update contribution guidelines (#8422) --- CONTRIBUTING.md | 6 +++++- docs/community/contributing.md | 15 ++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a7f17b1a3..d567d45a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,7 @@ # Contributing to REST framework -See the [Contributing guide in the documentation](https://www.django-rest-framework.org/community/contributing/). +At this point in it's lifespan we consider Django REST framework to be essentially feature-complete. We may accept pull requests that track the continued development of Django versions, but would prefer not to accept new features or code formatting changes. + +Apart from minor documentation changes, the [GitHub discussions page](https://github.com/encode/django-rest-framework/discussions) should generally be your starting point. Please only raise an issue or pull request if you've been recommended to do so after discussion. + +The [Contributing guide in the documentation](https://www.django-rest-framework.org/community/contributing/) gives some more information on our process and code of conduct. diff --git a/docs/community/contributing.md b/docs/community/contributing.md index de1f8db0f..2232bd10b 100644 --- a/docs/community/contributing.md +++ b/docs/community/contributing.md @@ -6,6 +6,12 @@ There are many ways you can contribute to Django REST framework. We'd like it to be a community-led project, so please get involved and help shape the future of the project. +--- + +**Note**: At this point in it's lifespan we consider Django REST framework to be essentially feature-complete. We may accept pull requests that track the continued development of Django versions, but would prefer not to accept new features or code formatting changes. + +--- + ## Community The most important thing you can do to help push the REST framework project forward is to be actively involved wherever possible. Code contributions are often overvalued as being the primary way to get involved in a project, we don't believe that needs to be the case. @@ -26,14 +32,13 @@ The [Django code of conduct][code-of-conduct] gives a fuller set of guidelines f # Issues -It's really helpful if you can make sure to address issues on the correct channel. Usage questions should be directed to the [discussion group][google-group]. Feature requests, bug reports and other issues should be raised on the GitHub [issue tracker][issues]. +Our contribution process is that the [GitHub discussions page](https://github.com/encode/django-rest-framework/discussions) should generally be your starting point. Please only raise an issue or pull request if you've been recommended to do so after discussion. -Some tips on good issue reporting: +Some tips on good potential issue reporting: * When describing issues try to phrase your ticket in terms of the *behavior* you think needs changing rather than the *code* you think need changing. -* Search the issue list first for related items, and make sure you're running the latest version of REST framework before reporting an issue. -* If reporting a bug, then try to include a pull request with a failing test case. This will help us quickly identify if there is a valid issue, and make sure that it gets fixed more quickly if there is one. -* Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation. +* Search the GitHub project page for related items, and make sure you're running the latest version of REST framework before reporting an issue. +* Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation. At this point in it's lifespan we consider Django REST framework to be essentially feature-complete. * Closing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened. ## Triaging issues From 4464ce7270e6242fec212a4257aa1277d023ff1b Mon Sep 17 00:00:00 2001 From: Shivendra Pratap Kushwaha <33164379+kushshiv@users.noreply.github.com> Date: Wed, 23 Mar 2022 17:37:44 +0530 Subject: [PATCH 089/228] Link added for Test Case Classes and corrected stable link for Refresh from DB (#8381) Link added for Test Case Classes and corrected stable link for Refresh from DB. --- docs/api-guide/testing.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index 62eb8dd1a..261df80f2 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -299,7 +299,7 @@ similar way as with `RequestsClient`. # API Test cases -REST framework includes the following test case classes, that mirror the existing Django test case classes, but use `APIClient` instead of Django's default `Client`. +REST framework includes the following test case classes, that mirror the existing [Django's test case classes][provided_test_case_classes], but use `APIClient` instead of Django's default `Client`. * `APISimpleTestCase` * `APITransactionTestCase` @@ -413,5 +413,6 @@ For example, to add support for using `format='html'` in test requests, you migh [client]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client [requestfactory]: https://docs.djangoproject.com/en/stable/topics/testing/advanced/#django.test.client.RequestFactory [configuration]: #configuration -[refresh_from_db_docs]: https://docs.djangoproject.com/en/1.11/ref/models/instances/#django.db.models.Model.refresh_from_db +[refresh_from_db_docs]: https://docs.djangoproject.com/en/stable/ref/models/instances/#django.db.models.Model.refresh_from_db [session_objects]: https://requests.readthedocs.io/en/master/user/advanced/#session-objects +[provided_test_case_classes]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#provided-test-case-classes From 7e4e6d207070d50736827a281b5cb70eb161b782 Mon Sep 17 00:00:00 2001 From: Wagner de Lima Date: Wed, 23 Mar 2022 13:09:05 +0100 Subject: [PATCH 090/228] docs: include drf-social-oauth2 to docs. (#8310) django-rest-framework-social-oauth2 is not a maintained library anymore. --- docs/api-guide/authentication.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 57bbaeb67..2f23e1718 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -420,9 +420,9 @@ There are currently two forks of this project. * [Django-rest-auth][django-rest-auth] is the original project, [but is not currently receiving updates](https://github.com/Tivix/django-rest-auth/issues/568). * [Dj-rest-auth][dj-rest-auth] is a newer fork of the project. -## django-rest-framework-social-oauth2 +## drf-social-oauth2 -[Django-rest-framework-social-oauth2][django-rest-framework-social-oauth2] library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to "in-house" oauth2 tokens and use and generate oauth2 tokens to authenticate your users. +[Drf-social-oauth2][drf-social-oauth2] is a framework that helps you authenticate with major social oauth2 vendors, such as Facebook, Google, Twitter, Orcid, etc. It generates tokens in a JWTed way with an easy setup. ## django-rest-knox @@ -473,7 +473,7 @@ More information can be found in the [Documentation](https://django-rest-durin.r [djoser]: https://github.com/sunscrapers/djoser [django-rest-auth]: https://github.com/Tivix/django-rest-auth [dj-rest-auth]: https://github.com/jazzband/dj-rest-auth -[django-rest-framework-social-oauth2]: https://github.com/PhilipGarnero/django-rest-framework-social-oauth2 +[drf-social-oauth2]: https://github.com/wagnerdelima/drf-social-oauth2 [django-rest-knox]: https://github.com/James1345/django-rest-knox [drfpasswordless]: https://github.com/aaronn/django-rest-framework-passwordless [django-rest-authemail]: https://github.com/celiao/django-rest-authemail From df4d16d2f17bd53626266eb829fed40cf8a73e48 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 24 Mar 2022 09:23:16 +0000 Subject: [PATCH 091/228] Add StaleBot (#8423) --- .github/stale.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 000000000..f9ebbced4 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,22 @@ +# Documentation: https://github.com/probot/stale + +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 + +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. + +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false + +# Limit the number of actions per hour, from 1-30. Default is 30 +limitPerRun: 1 + +# Label to use when marking as stale +staleLabel: stale From df92e57ad6c8394ca54654dfc7a2722f822ed8c8 Mon Sep 17 00:00:00 2001 From: hashlash Date: Thu, 24 Mar 2022 16:57:42 +0700 Subject: [PATCH 092/228] Added test client support for HTTP 307 and 308 redirects (#8419) * Add retain test data on follow=True * Simplify TestAPITestClient.test_follow_redirect Inspired from Django's ClientTest.test_follow_307_and_308_redirect * Add 307 308 follow redirect test --- rest_framework/test.py | 12 ++++---- tests/test_testing.py | 70 +++++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/rest_framework/test.py b/rest_framework/test.py index 0212348ee..07df743c8 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -288,7 +288,7 @@ class APIClient(APIRequestFactory, DjangoClient): def get(self, path, data=None, follow=False, **extra): response = super().get(path, data=data, **extra) if follow: - response = self._handle_redirects(response, **extra) + response = self._handle_redirects(response, data=data, **extra) return response def post(self, path, data=None, format=None, content_type=None, @@ -296,7 +296,7 @@ class APIClient(APIRequestFactory, DjangoClient): response = super().post( path, data=data, format=format, content_type=content_type, **extra) if follow: - response = self._handle_redirects(response, **extra) + response = self._handle_redirects(response, data=data, format=format, content_type=content_type, **extra) return response def put(self, path, data=None, format=None, content_type=None, @@ -304,7 +304,7 @@ class APIClient(APIRequestFactory, DjangoClient): response = super().put( path, data=data, format=format, content_type=content_type, **extra) if follow: - response = self._handle_redirects(response, **extra) + response = self._handle_redirects(response, data=data, format=format, content_type=content_type, **extra) return response def patch(self, path, data=None, format=None, content_type=None, @@ -312,7 +312,7 @@ class APIClient(APIRequestFactory, DjangoClient): response = super().patch( path, data=data, format=format, content_type=content_type, **extra) if follow: - response = self._handle_redirects(response, **extra) + response = self._handle_redirects(response, data=data, format=format, content_type=content_type, **extra) return response def delete(self, path, data=None, format=None, content_type=None, @@ -320,7 +320,7 @@ class APIClient(APIRequestFactory, DjangoClient): response = super().delete( path, data=data, format=format, content_type=content_type, **extra) if follow: - response = self._handle_redirects(response, **extra) + response = self._handle_redirects(response, data=data, format=format, content_type=content_type, **extra) return response def options(self, path, data=None, format=None, content_type=None, @@ -328,7 +328,7 @@ class APIClient(APIRequestFactory, DjangoClient): response = super().options( path, data=data, format=format, content_type=content_type, **extra) if follow: - response = self._handle_redirects(response, **extra) + response = self._handle_redirects(response, data=data, format=format, content_type=content_type, **extra) return response def logout(self): diff --git a/tests/test_testing.py b/tests/test_testing.py index 5066ee142..b6579e369 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -1,7 +1,10 @@ +import itertools from io import BytesIO +from unittest.mock import patch import django from django.contrib.auth.models import User +from django.http import HttpResponseRedirect from django.shortcuts import redirect from django.test import TestCase, override_settings from django.urls import path @@ -14,7 +17,7 @@ from rest_framework.test import ( ) -@api_view(['GET', 'POST']) +@api_view(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']) def view(request): return Response({ 'auth': request.META.get('HTTP_AUTHORIZATION', b''), @@ -36,6 +39,11 @@ def redirect_view(request): return redirect('/view/') +@api_view(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']) +def redirect_307_308_view(request, code): + return HttpResponseRedirect('/view/', status=code) + + class BasicSerializer(serializers.Serializer): flag = fields.BooleanField(default=lambda: True) @@ -51,6 +59,7 @@ urlpatterns = [ path('view/', view), path('session-view/', session_view), path('redirect-view/', redirect_view), + path('redirect-view//', redirect_307_308_view), path('post-view/', post_view) ] @@ -146,41 +155,32 @@ class TestAPITestClient(TestCase): """ Follow redirect by setting follow argument. """ - response = self.client.get('/redirect-view/') - assert response.status_code == 302 - response = self.client.get('/redirect-view/', follow=True) - assert response.redirect_chain is not None - assert response.status_code == 200 + for method in ('get', 'post', 'put', 'patch', 'delete', 'options'): + with self.subTest(method=method): + req_method = getattr(self.client, method) + response = req_method('/redirect-view/') + assert response.status_code == 302 + response = req_method('/redirect-view/', follow=True) + assert response.redirect_chain is not None + assert response.status_code == 200 - response = self.client.post('/redirect-view/') - assert response.status_code == 302 - response = self.client.post('/redirect-view/', follow=True) - assert response.redirect_chain is not None - assert response.status_code == 200 - - response = self.client.put('/redirect-view/') - assert response.status_code == 302 - response = self.client.put('/redirect-view/', follow=True) - assert response.redirect_chain is not None - assert response.status_code == 200 - - response = self.client.patch('/redirect-view/') - assert response.status_code == 302 - response = self.client.patch('/redirect-view/', follow=True) - assert response.redirect_chain is not None - assert response.status_code == 200 - - response = self.client.delete('/redirect-view/') - assert response.status_code == 302 - response = self.client.delete('/redirect-view/', follow=True) - assert response.redirect_chain is not None - assert response.status_code == 200 - - response = self.client.options('/redirect-view/') - assert response.status_code == 302 - response = self.client.options('/redirect-view/', follow=True) - assert response.redirect_chain is not None - assert response.status_code == 200 + def test_follow_307_308_preserve_kwargs(self, *mocked_methods): + """ + Follow redirect by setting follow argument, and make sure the following + method called with appropriate kwargs. + """ + methods = ('get', 'post', 'put', 'patch', 'delete', 'options') + codes = (307, 308) + for method, code in itertools.product(methods, codes): + subtest_ctx = self.subTest(method=method, code=code) + patch_ctx = patch.object(self.client, method, side_effect=getattr(self.client, method)) + with subtest_ctx, patch_ctx as req_method: + kwargs = {'data': {'example': 'test'}, 'format': 'json'} + response = req_method('/redirect-view/%s/' % code, follow=True, **kwargs) + assert response.redirect_chain is not None + assert response.status_code == 200 + for _, call_args, call_kwargs in req_method.mock_calls: + assert all(call_kwargs[k] == kwargs[k] for k in kwargs if k in call_kwargs) def test_invalid_multipart_data(self): """ From 86673a337a4fe8861c090b4532379b97e3921fef Mon Sep 17 00:00:00 2001 From: Kojo Idrissa Date: Thu, 14 Apr 2022 15:00:38 -0500 Subject: [PATCH 093/228] corrected grammar to improve clarity (#8466) --- docs/api-guide/relations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 4547253b0..9c8295b85 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -19,7 +19,7 @@ Relational fields are used to represent model relationships. They can be applie --- -**Note:** REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of `select_related` and `prefetch_related` since it would be too much magic. A serializer with a field spanning an orm relation through its source attribute could require an additional database hit to fetch related object from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer. +**Note:** REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of `select_related` and `prefetch_related` since it would be too much magic. A serializer with a field spanning an orm relation through its source attribute could require an additional database hit to fetch related objects from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer. For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched: From b1004a47334a0dd1929e6d50b8f7ff6badc959f4 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Mon, 25 Apr 2022 01:16:18 +0300 Subject: [PATCH 094/228] docs: Add a note on concurrency and races (#6950) Refs #5181 Co-authored-by: Adam Johnson --- docs/api-guide/throttling.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 719378247..b87522197 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -106,6 +106,12 @@ If you need to use a cache other than `'default'`, you can do so by creating a c You'll need to remember to also set your custom throttle class in the `'DEFAULT_THROTTLE_CLASSES'` settings key, or using the `throttle_classes` view attribute. +## A note on concurrency + +The built-in throttle implementations are open to [race conditions][race], so under high concurrency they may allow a few extra requests through. + +If your project relies on guaranteeing the number of requests during concurrent requests, you will need to implement your own throttle class. See [issue #5181][gh5181] for more details. + --- # API Reference @@ -214,3 +220,5 @@ The following is an example of a rate throttle, that will randomly throttle 1 in [identifying-clients]: http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster [cache-setting]: https://docs.djangoproject.com/en/stable/ref/settings/#caches [cache-docs]: https://docs.djangoproject.com/en/stable/topics/cache/#setting-up-the-cache +[gh5181]: https://github.com/encode/django-rest-framework/issues/5181 +[race]: https://en.wikipedia.org/wiki/Race_condition#Data_race From cdc956a96caafddcf4ecaf6218e340ebb3ce6d72 Mon Sep 17 00:00:00 2001 From: Q_back Date: Tue, 3 May 2022 12:10:37 +0200 Subject: [PATCH 095/228] Update description of docs/api-guide/fields.md -> required (#8476) fix: Documentation did not point out that default value of `required` `Field` parameter is `False` depending on the Django's `Model.field`. --- docs/api-guide/fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 5b9688dca..e9ef5c6b6 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -42,7 +42,7 @@ Set to false if this field is not required to be present during deserialization. Setting this to `False` also allows the object attribute or dictionary key to be omitted from output when serializing the instance. If the key is not present it will simply not be included in the output representation. -Defaults to `True`. +Defaults to `True`. If you're using [Model Serializer](https://www.django-rest-framework.org/api-guide/serializers/#modelserializer) default value will be `False` if you have specified `blank=True` or `default` or `null=True` at your field in your `Model`. ### `default` From 33b86a8e5383ae7c6bba03cf09b12b8f7cadd20f Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 18 May 2022 13:10:38 +0100 Subject: [PATCH 096/228] Recommend Django REST Knox (#8490) * Recommend Django REST Knox * Pin jinja2 to fix docs builds --- docs/api-guide/authentication.md | 26 +++++++++++++-------- requirements/requirements-documentation.txt | 1 + 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 2f23e1718..fca9374d0 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -120,6 +120,14 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401 ## TokenAuthentication +--- + +**Note:** The token authentication provided by Django REST framework is a fairly simple implementation. + +For an implementation which allows more than one token per user, has some tighter security implementation details, and supports token expiry, please see the [Django REST Knox][django-rest-knox] third party package. + +--- + This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. To use the `TokenAuthentication` scheme you'll need to [configure the authentication classes](#setting-the-authentication-scheme) to include `TokenAuthentication`, and additionally include `rest_framework.authtoken` in your `INSTALLED_APPS` setting: @@ -129,11 +137,9 @@ To use the `TokenAuthentication` scheme you'll need to [configure the authentica 'rest_framework.authtoken' ] ---- +Make sure to run `manage.py migrate` after changing your settings. -**Note:** Make sure to run `manage.py migrate` after changing your settings. The `rest_framework.authtoken` app provides Django database migrations. - ---- +The `rest_framework.authtoken` app provides Django database migrations. You'll also need to create tokens for your users. @@ -146,7 +152,7 @@ For clients to authenticate, the token key should be included in the `Authorizat Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b -**Note:** If you want to use a different keyword in the header, such as `Bearer`, simply subclass `TokenAuthentication` and set the `keyword` class variable. +*If you want to use a different keyword in the header, such as `Bearer`, simply subclass `TokenAuthentication` and set the `keyword` class variable.* If successfully authenticated, `TokenAuthentication` provides the following credentials. @@ -355,6 +361,10 @@ The following example will authenticate any incoming request as the user given b The following third-party packages are also available. +## django-rest-knox + +[Django-rest-knox][django-rest-knox] library provides models and views to handle token-based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into). + ## Django OAuth Toolkit The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support and works with Python 3.4+. The package is maintained by [jazzband][jazzband] 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**. @@ -422,11 +432,7 @@ There are currently two forks of this project. ## drf-social-oauth2 -[Drf-social-oauth2][drf-social-oauth2] is a framework that helps you authenticate with major social oauth2 vendors, such as Facebook, Google, Twitter, Orcid, etc. It generates tokens in a JWTed way with an easy setup. - -## django-rest-knox - -[Django-rest-knox][django-rest-knox] library provides models and views to handle token-based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into). +[Drf-social-oauth2][drf-social-oauth2] is a framework that helps you authenticate with major social oauth2 vendors, such as Facebook, Google, Twitter, Orcid, etc. It generates tokens in a JWTed way with an easy setup. ## drfpasswordless diff --git a/requirements/requirements-documentation.txt b/requirements/requirements-documentation.txt index ad4928730..cf2dc26e8 100644 --- a/requirements/requirements-documentation.txt +++ b/requirements/requirements-documentation.txt @@ -1,2 +1,3 @@ # MkDocs to build our documentation. mkdocs>=1.1.2,<1.2 +jinja2>=2.10,<3.1.0 # contextfilter has been renamed From ed00e11cc5f338062ff2e90b552643804fc67dba Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 26 May 2022 10:40:46 +0100 Subject: [PATCH 097/228] Add FEZTO --- README.md | 11 ++++------- docs/img/premium/fezto-readme.png | Bin 0 -> 22592 bytes 2 files changed, 4 insertions(+), 7 deletions(-) create mode 100644 docs/img/premium/fezto-readme.png diff --git a/README.md b/README.md index bf4016751..9476e92d2 100644 --- a/README.md +++ b/README.md @@ -21,14 +21,13 @@ The initial aim is to provide a single full-time position on REST framework. [![][sentry-img]][sentry-url] [![][stream-img]][stream-url] -[![][rollbar-img]][rollbar-url] -[![][esg-img]][esg-url] [![][retool-img]][retool-url] [![][bitio-img]][bitio-url] [![][posthog-img]][posthog-url] [![][cryptapi-img]][cryptapi-url] +[![][fezto-img]][fezto-url] -Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [ESG][esg-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], and [CryptAPI][cryptapi-url]. +Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], [CryptAPI][cryptapi-url], and [FEZTO][fezto-url]. --- @@ -194,21 +193,19 @@ Please see the [security policy][security-policy]. [sentry-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/sentry-readme.png [stream-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/stream-readme.png -[rollbar-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/rollbar-readme.png -[esg-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/esg-readme.png [retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png [bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png [posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png [cryptapi-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png +[fezto-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/fezto-readme.png [sentry-url]: https://getsentry.com/welcome/ [stream-url]: https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage -[rollbar-url]: https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial -[esg-url]: https://software.esg-usa.com/ [retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship [bitio-url]: https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship [posthog-url]: https://posthog.com?utm_source=drf&utm_medium=sponsorship&utm_campaign=open-source-sponsorship [cryptapi-url]: https://cryptapi.io +[fezto-url]: https://www.fezto.xyz/?utm_source=DjangoRESTFramework [oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth [oauth2-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit diff --git a/docs/img/premium/fezto-readme.png b/docs/img/premium/fezto-readme.png new file mode 100644 index 0000000000000000000000000000000000000000..7cc3be6e6c18de05af1c8c2601f4edc627bac0b6 GIT binary patch literal 22592 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 Date: Thu, 26 May 2022 10:48:08 +0100 Subject: [PATCH 098/228] Resize sponsor images --- docs/img/premium/bitio-readme.png | Bin 18526 -> 18479 bytes docs/img/premium/cryptapi-readme.png | Bin 17864 -> 17824 bytes docs/img/premium/posthog-readme.png | Bin 2402 -> 4881 bytes docs/img/premium/retool-readme.png | Bin 8962 -> 8921 bytes docs/img/premium/sentry-readme.png | Bin 24504 -> 24506 bytes docs/img/premium/stream-readme.png | Bin 19213 -> 19170 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/img/premium/bitio-readme.png b/docs/img/premium/bitio-readme.png index c47118cc6956b8a27a1be8edf3b84f8fa119e54c..d5d6259e61946a911024aaf9835d885539323c31 100644 GIT binary patch delta 17556 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 a@`qhkO^(>-(f~YWgu&C*&t;ucLK6TrZLfp? delta 17605 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 QcrFQpr>mdKI;Vst0HO}u@&Et; diff --git a/docs/img/premium/cryptapi-readme.png b/docs/img/premium/cryptapi-readme.png index 163f6a9ea20f17909e6e38537a627f19e5766a66..10839b13b4835ea1abf18dbb89b0b8e9c5b6e0fa 100644 GIT binary patch delta 16101 zcmZWwRZtyGu*Tip?cnZCaCf)h2@)Vca9s!v2X}XOC%8j!hY;MI;0~AnKHaMOvO85f z)jKWI{q=OuNF-!#BqT?;nu;tc5)l#v1O%$QoRkIx1SHzW_z3~-|lW>j}Q=Ak$$4b|^3es3)Nnb~Rxd78`JZgR1A^+!Jo+g(`YhKG7-7)Yxi!EwVwu zswT=0BB3c_Opv(KXnXnwBHF-L7%fuxy{ABwG$!h4t-T~ud@>(RD7)mDB2e`^tds6O zr9L;uB1A!HiBWt%u*mV=t%$@7VFrCX567=FIJP*^m`f9?i)_iC?-l)-DaB`rY6UnL zO=2UM^#P7b(BJqV|w6&!uNsn9o> zVnJGx{E`xyx?&{u7O(NQy=`Vu&j%8ZztVG%ka~#HELh)o$5TD!-QySV;mh~iF?R05 zo1&(3P*0JhBQ(0h>%(-&F{Dr@q6crim0u;uZdkM7h902(N3~z@Kp=`xa|<0;>%P%m z+nhj!Tn^T^DBhx%;7&S}1c7!2Ig5M_QJuL+J(iwFEudkTBtB45!CdbejfVYNr=Grv94KRZ>q?KgAntx8JT=?kQrIlLkCr3cAjb`C@b!Ufl{dQ4kpbAs`JcZ zKX#9epSPgkh(`d5wWJ_4@ed-tB9r^3k}dC%{io02js=o??|&8>$)xA<#oSZkRw7yk zZ*OhT7EKyvL5ufW(KT!nss2miA`Yu3!~b~FCnM*+r=|o9L+3xL&GaALA~9xT^fyEEScN6p1f ziO0-&mD-eH7#YEsA^6Th&K7>pj3AlBBt~5qksB~$o!;kduWBRs-djApD zY|HXYf8$PH2TI3j|CVtH`azod5GHFoEh;S{Y}Bw~Zc*7^*2<`gpkG_IlxH%OR24#| z)TSIfVSwk$Y;a8NBs9kUEXU3W%?isd&vEuU2?FWB6vfYXf3L`T$-_!L$=udBQI{w; z5qTAo1x~_VZQttr zvSk}PjMb=FIWQ3szf{yN`q7L}EQFmsdd}fBjRSGLpk(0cfsv}8l@DRs0KZ*D%v5QR z3Ybb@>%ueIoJx&9ts)GGJQ|tY?t7s+8KhzTnRA7URPrTP?M*@?DvsL~^k$YyGn-V@ z4^PVOaJHf3jEQ%(s4dFMK$x7ZUmF+^aX#za^AiDWR7!KYl`r#2Zp)8 zoO?|k{`Y6DXoPrb-v{I%O<^?xRGx>ke|Ew_?W#3h&#(3;A;EeZUsLS=BS5@G@C3Se z^nd|37;`IabVcYO307PWCNiA;on#gQ7XVYosWh-j8hKnqjIc{0} zX0r(FJ90$j(bB80y)o{X(YH`Hgx+NsI`D38OKD)xPf{Jd%x%BEo>63Za<%+(Uegrc zeV>MNO-?L}6ls|BjDxQn4Gv64ofi)dailjBiCsPJZ7_2qDfsep!gF*#`|t1o6>;}} zr~(v)yNNyw#=5NVT+t*QYjEAq#Pkv|UyI{lYi*8*m{@u#Env`~CE(6?uU?DIWZBy7 zsCvMljKiOI)%UEzMtY0d2AJu49bHYkX6ff{7a)n(F~`qg%=pdTD=m1DB-)vTvUmYx zPd!$hMeGhkKPcU-&I&8&^atpGfCw8ZS;09gB@6@yHSQ-$aVkxmIDb!H0 zf~#b{$VAYC&$MYjfr6s24{mWFZP}i}2+8lD#|SFiidnACw7-=g53{a7G;iUfn}&lF zFFpcoNC3~*`%cGGluvpCZp4Hkyq-TA1CxuHM4rHvJ==Cyhys@N2<)Z5sgmr3WzSh& zVRd%3s=g#Rb&ON_V{Zf-E*CiVwmPj2aUoX~59L}CXwmZmUBe19D1qs40`UTgM{LIW zZe2+-KU8MXpvL)EAnA)X{~!(HjHo~9y(eP**ad@fOPKNt*Ezf`GkLLhA5Ccg_8gKb zwwXm}B+92NF&V+gjZwB`%<|D2A!Sy(!su;VlV&7JlIZLDC%nE^Zpaa~+0oEDCdzLN zeN8d@Z+8F~Y7IIM?4y@u-v|e|?KRko0~n&hL4rtg#l47z(jQQuV%kwmR}6x@+)}cG zxkJv9L?0qao)gN5^utjby`nn55(F?)d>A8gE~mUqZUv|ZTu{+%R!t6yh5hdbkXp3A z5nNn9hAy{!t4b<@P3W(oQrccIudYjlVSpw8-rWcl)x~i z-`M8aAEL&r3v{mNtivpIc-FHce5;rs-Cg#@X!n`jl!8JHBeo~Pg zU4LdMKIu10chovYEq4^C!}xTtu>;^`6=$=dx`Yl!bE07|BPJgyj}pomu64t_w4df@ zuMyMB-iWF;P)Wa_L^Rf`_roBY3IUA@p%D9yRdbH#v>M0PRY#|jj=}Aw_eyL?IfYX< zG8jF9HtdcHIQFQW9`17i&oAvtAdM`@!yDLCq#*d$Fn0}IVsjXds8Cu!7RYQ<-A|J# z#Aru9W+3Z&5aT%7q|E2Q!8M}l^_j5vP}}b1SYH00*k{@M6WZ@WU7ua9Y2Mow?a`6U z`OBhr2CSJ66~7C(^3{nJOa5_#oIkp2=mwz?=u^p+o3}Vq#QG?%3LMYvDaf}4Frl&H z(yXmyYsVW0Bo-H@l&&n&17uI73hq({X7YnGBfx2@-!}itkG%*-dY?f;?}&3BexGWJ z3&&6PEkkGtR#2qk6hRFAet}+L*zQc>Aj$Eq1vb9Or4&27j9dhJ6oGs+(k@6{qzZeN z0X`madKsI~a(?v^JHAsAik}6(>wWgSQTvsr({aB*TSv&m8#glq4?M+p8R9#&E_lY9 zfLnCYq@XN7(&r-qYlGsTXDN-N6G+fgSijo^n{h}Vw?6}3`-{xSo*?TckEcRoVOnIO zi8GI%y;^ecV+TPFt_!4x z`Dtz7t87#l-ev5J?_h5Hck{DkujMGI&PQ5wOl$LdPrX(L=Q!(?X=u>($R}m1v-td* z8K7!`)NttT90fw!C(tDd++k9a^g!VaVxrh7Wcj`F$->BgYBZlUs(0nbq zVGfdJsue$g`gn}*@jn;r;!NfrPO=8snLXy1#dUj(M<^f1hNndJ-oM&=KEdJYzcj=1(LgvnClyXVQ0B8T z#;B?Yy3JK&kn4>C7Q8%Er-hD#oIpD&mN-0E6)`*6Ki z53k&&MbwLpc?jSE?pdzmZ{6t%ihRKw`y0)HH0#XiI@3ssd5am`NzsKQZjUh^>lgNw z{Swegrda-E0N3fugaFL`KH3@9SZx7r(v_cdKJoYhs2Ve~fYn;EBpwzKK3;Q5qMN`7 zSSi$`H2VfmooTm=UxsbM75G7Fd^6RFao)4JpUmQM|B2py)?P`(6u+~L&}bqoq!^I2 z5LOOQS#B`N{A96qCsT*(My0<=?3MmwGYpHPuu%R{Q8T4{!c{+ws3-=l#10YCINBaD zN%#_!5ry8p&Wc8`+DI(~Ib?cpCZq-k-~ASJ@Jtvjza>-Fy}&#bQ+%zx%(dlLN!$wR zH#NwkNlmyXqo4)&-k!&=yI*8ZtsV1;r^8^XJk&I1rD9bIX=EEvi{1y=hL1bqOfWQX zSlZVeXTPsdFiTj#g2$7qYG!CJw)$j$KBQayhXES!u~^WasE?#KjOvs>`vGb;^9bO? zqHclj{NTp6@ED!%f%=}Q9BL9bcJ*=pJYa5(V~CDW(+NTjj{F(aKiA_5m|EARMyxf~ z;bqMKGBN2;PYHN{PRqx~f0D9s%H!qvTiXfwcgJa8_UAr#kV|KTPd;5*OlTSkZcr*p zc#Bqv5&Rv7E~$_Pm=LQQe;+uC(FtFHGmQP2Xyo@1yFf7;==$1z^~EwBNOM=@r!!yj zm9s7~>!5Gg*0vMG#7KrH%voC9osx(1k4a5YLMZxcL2f4?Kd0?#^OS7}f>4aVGrboc zO&a5m9`-JKp{W!6nQNDSx$b(7!Q^#)naJ*#ov>e*uuG#ol*7ugwUIOzSjGj_Rskv7P+Ma8 z6!O8v{EbMGie>Oohp<_}d}ow!nh_plZJy*cn5rEOP?|K^`GpZiR)bbUGx{SXv23Ix z*F<-vpE>TC>bz_%kQg*06|9op?AEa^37U5`vv=jTa~F~f0OqkF6t|QB%*ir5g@b6cM%SwEhR%SyN!NH`vfF~a@`%% zMGuCXy1ZGNTiM=$!A*X7@@u(sYO-{)>xL)xmuSu7qEEfw>c03^@m+-;AP+F>^pE=v zwO0&i%O*+_0!Z?-s#I^@ihMRjj5DCGM;}2TEGL_v=pd~56YUHKL?lP2=fm0FHjQ0D zN#zIuvkZ-dv_;A=g4BvC8NSm2!^)vIelk-3Qw#UFMzChbt$E>j?L$FLDe`T6tx2nc zm!H-|7<}~>{qE5qdZ@rO2MmYuVK}PeU@D`3&OlKlKu=lF7@OT(FPkl|kefng#@={U zhuTa;oR>)rbSg-soxF5(bV7$E5ooSRCf+hkYm5+`n!a8fpLvbu-_mS-Xnuy@p&*P| zqTqHqV4VzSH9l_XSh-2>xT!!%_5iNL|leE(ds^}&^3;zux{UE3KEBB85iCJvY6 zC3A^}XBm{~!#WXH3MppJ(LIA`ST2^2&%9s96|3 zbF;nfzFwkXLbZtJM&pJ{Em;fn@o^kIxE+Y+-i9AeYQnQJfO-&i2|gUY09% z2lci-!(BmkD1ratbTs6_DM3K>e~7dCAKouCuvj$a2gs{th&%cJv^gK}d|^NNsQKS%*Nq{=)S3;sNU^hx&JH5=ffW@(E-bs^Dg`Fyyv>w7w+bg!(|-7QXhnVsq|%BnLpFL}lzPxmjq}){%n2zpt!u?jF<6X`qor^AAa3M#{jQ4&cAU>FweD_<)B2?U$ZInL$-Gq3OpU=!d>VTIdPQ~%DBJ4gDD}w zHW4q5{U%fTIUM;)^#2{xIXQmW@4fncu&TBrlU@AIt8pB?2yrErkD2o#UftcnY+^Z*Y|&bOs7Cf?+Dq4j_ZS}^2S94-Abd2qM0FA zk@VB46lkn;CepMv6mae)A^!8E5ax>1$x0h17DsK)DCE9PSw^fFu_3DTbT>J%HRo}k zckk^d0|^0Hyp663iEgLBsFTaDEzJ9Ug*;H~5Baab)Ap-x69t;??2Lc@OM~z(t2(~D zf7K9Z*=mR#k-o?pG5@~teRlRna;5g&!02x8)PWD{SDDC1ZnM)dwqJE$X4)@&g#JaK z#DUGzzzf++5+?zUD#s=XU%vYeNb7mj0vFvCqXHa-axe^6wAS>o>FQVA z7$A$y{uzZJv}(&n5x!@D5tnx&wASIR?N~qI{1AdhC7t#|ma{OdYhO%^+ozyF)U>V5 zujEH;J?6+Y&4oX|>KXhkEzIn&+$VG|icj9L{7=tm{hT%mCdMuI?{;QnbU#s5rvtcV z3-=7%?5V^wv5}cHtFJNdy2!L&M~+m17Q!6ph6o6Bcm3cN-|hDGrhj&+Mejt<1~P4w zna-!%xh|PB0dp0OsPB0d?p;zh<>c5eR8GPU)ZZvYbST2CpUsTn1dSWG6W4DKxseq| z=DfkX;kGxtUXt^he_N;mz0XUyYT zHyp3QzDoz#X4>~=P+aUVMUQzpi)%F?pVauCvBsI^!Ifc1Jf0ve_HPtw>C$z*`kKM* z17Xfy@5we5#0SHk^C&VKms4BOjgujNZnSDcw=gD(Y6B&H)hQK5a-w;mM-(dbA^|V{?!;XTRgx!kE6dR?ZEZiyUs z8x!8JEJ}rSS%pGYs4~a$Z^lY|myGn06g(fR-sx)DkDIFqV{Cts^aluK-#Qaov7&wf z>i24r69|9RL3IfF<%z4XSaO73Ul0ZLAw*)m@=|D5(>fJfC1nMj`4w8N3U)NHUMSxk zQ;|xR2Dp{kGA)&rSwGdV=N%3f1oPvd-fSm?YukUD zMniu^td@6))K=L~FGeh!}~;g%Ft-o9aGosJS};vP=rggWw! zgdTDtAfOOa?oH8DK0%4q{0}S_auEG-5sCUCQMGuP-B?{ztWm@M<@F<%|L@+BI)VTd zaSAJN!R{)Zw_6JoeCwCTX~#*cbXxWFNKVHq zliAaq%=%W$adV=iCSN2T^31<2dj=(xEQJ+%3(~HVc1(_LnGuPl=59T|=b66-`N@?V z)wmZXjLIi^dqExb!I61|l*)T=7QflhJ4N&j!Y?bOVw6NvjQ`Dl4`H8za^_#d{ibU3 z0Qh5m+uRQCvaGDY8Tw2l{qXYGlbOiqjbi+A>y~6lEI{QS=>$cc$s%mKd>06 zeGd)qk!4e10|r6B<+<(Q)^%4o|BDDUI^Z6UhtRZ5V`K&BtGPs+JM;v+C2*l=wxZt7 zWQuIezq!#n8S0}7-v90mWXp8U$Qwrw-g~AY=*#}7c&(y~vg`4OBgxItQ5#pj5#k+( zQK<_rEsA>JP`t`(JiVDO-y$opWxfVBU+vX8kVAp|ZoB}7J)7^fD)jAjf2M3I0qKnR zlIXU}s;lt=5V3ZtXEsYxfwZUs@ngWFTKjOALY4)(&11EsZYnz5)#pE|>u=x7zv@cB z6*Pi8gK9H4gz{4kd(F#FqWU1}rgib@VQP}{cPlNb4lhQnXP?3lyu zap^R{^w6b!8~?$MzN;+rwEYJo;Bs=pCtVmAVH~Sqa;K@6%Sb7!~MlUA(`|7f3MJ^#YY_U|X-Q0J=+6qB2B7`lh_kl7ew$ zsk2g`*7_mDXjV~&JLxg{p z8I{@xxdBa&R4#wj&j^PGxIy? zhsmgTehqHZ&>CrG%B&M?RHAnVTYL`IZu7YbG{wSa#J^U;$AWUnF6CV>yN<^isX_<@<~GC37M7HhHcrH0jB9y#W`)pNoB(^cW z*WO8*jT&m?4LY?GK+S!+`&I3XsQd$))OBPZjam8EQgoM}am>D1+U?9E(|yY(Ja+Af zv(GMk@8Lsh4z{55pWB0S)BdR*j}6GVWjQZVYxWF$gx82fpxgR=DXQG#;9(#0$3X&S zxW)99IzIATW_23erAm402{Y7A>gU(xKRK59f)&|nf& zl~n@T>pl;*00Tz%*PE#g!gGGgN{I;K>6nO&g{a~$qgPu$Y#;3%{Ayo@qFMeFt2MWl zs;lkzXnGL1^q$t~A^sv&n5ZojR{}N4G2ZVU4|DZ%n@2W0&2U|`oTg)^+6?5+{<^Q7 zK&%Py+Uu#$FYj=da4TVo{gLESgIkQt_uvWYG=M!D1z_nXc*j#Ldc=u?J${y5^O&y$ z7M4xbJHM7$*6!~2>uRkFpX=bb2p8{}9E$S?AW&lmBn@?f;oi3p#Ra^<&>{<;hodqa ze2W&}3O(`RE*wq|WqZ*PB-wJXq-CNg|2*r@*O zeo+`T0nF-*w~Q{@lcJEi5iWMQ%Su0mKuw~M;-k7)FOWT(9`B{VImzZAaF4YWc-Ahe+YE*z%+C5!Tg7qA%Fkfwhc`UWXiKJP=0+} zU_)~6UBzwikig1ZYK9%u?2*VpsAwGD0EXDZcjEl~ zpjl}(-+XP~rt;{-ILImpMdOIB38@xPL3$5Qht??QU16j(ThbNvyz3)L>YlJu8g@^t zpEoIs$xA^r2~7P7(?AveWO6g_?>}Q-Ub^B_3BskOYoI%oRzn{^NT1rSvE;0_F|yTz zJ!sQ|9!`%g<+0aLDzbOQ|1Ek)R3FF(Aei*3&Jflf7Up(wu*!Il>=1O=tB4W7vQac9 zj&2E-|8R-v=~4^|V^vHs;=;Fl33!(bd=A(deWhSa@z*yEqJr7%i>Gu+{W}Wh_N-<6 zdbJT)o!PX%zEfd7Hn-A=ivaGoyCHOd^B3ToXbNpa`@$vVDN#5B2%@?o&`-|*0 z{)lUlwH5hW4C}2LM)rDL`Fh1-gn=CMfq9?AcTx6)Su>}D=}A@ukV>+$6*7t~G)u+| zhs33;UM5;&dW7F9&jhGK?Ay>Dpfk6IlC{UlTkFkV+QQtctB+K**|Ct#j8SN!zhh17 zX?|T_Z?fA=_{Hes{U|q5Z=GiiaLwn>m>vq8!kKV;f9pZ;p;o?b@!$vzsJJg|J#?IZ zz(HB+XvM{?F7t6W|57o7itVDdb3Ixz!5Te%e2DADKr;dsY+tMgebmm?dNY%cG${LT zXOe6qcuuc84;cU6Qx4pE*KvDs3o0SH52gh(^@sgW@>VPQnD+O<16~^HjSEc}uP@OgvxL%$8BU2h=e&3<`vl)k z+a!Of6j-$Kv6T{R&BD<8Z^NXOV2l4X8tlBj%nsg# z$UW7N3tno13oi~IxfYfh?+^&PG(lUWokRgWN2VQ;H}pTzLeK9;u0rEAy%zBJRxB7T zpU0|wE@Nivv!w{#m&UeC@!I;;ke#z!_4WO0$7 z-?>Aw$!i~^{lai;MDj##sat1GWW^7&Nm8rCpe=Ti_1Oj2mY?Az-L5@OY(c%cj#hMLUJ5@b+okB<{;Ayz)AL8A`=@oL{?E~IcBFrX2Lx&zOv%KI zIC=dCXB-YF^SIA|foR0!Vj(ir2C;4!gC~vil9Q0LD{-a7j`rYu5dW9s%&}f-zle~t zs04bU)D5dz%h!Zj;_5iJfA61%1zOZ`t8B_4EUy&C#bg6bH>2`vO+_3?TtLcBv+cw_ zXQvX}4@_mko5rm{yyFQetCCI2#V z+#i|HzTf_S68}?6&ijRQKjddZF!l=uZkuE&$%1{zoGv z&HXF$`HyuiG%=r&SAc-~rFC(v2%|HChYvsO(ctPYs+b~F?jJWwP2{|)*)?f!0|wyn zoC2~I{k*fO<`PGvrUgG&YloAZSYEV6P#ZUzNwe7rfC;e~g=1=qw_x`#O0!r%#1F=GiUpt-u+_^&Z>o94?yoJ5&qmZlFLZx{yzDT)^`+}vXXcs;yx}bj^!hP!qbrlD z@^AR?pJp!mtu0Y;QzX`+$!Lw2)612&$`fPUQ2d4s*E^f}>sYmv4jv8{CcH&0u1L(Y zF!5p(0NL-3l-i@l(&b&bF@_746r8L)j(AXxt@tkFGWL)7?d_wlMz+x72}xY(0m?Ve zP!M@aZ*WBQz@;Hqu6d4Zvq8I}5lQRQS+6;`y*;imuY@7iJrCtX4SrMyR-}!d&fZKX z0vudRiL@A{a`>1_8B^)?(AeEL%*~Bz@GJHQketk4xrzv6$~jmU1Fer<5P(B({w)^xX)r;)vp}uecEL`!m|E+KS^9 zP}XB91SauEzF{tQh-Cu9kFlo4aA~f%7gKJ-QHZg~e)n2f@*ABu2mkW%b4Rd@ox~ym zlKy^QMIim>j7a&U9?|xv8hdr#ZXT{-XxSYS2i$3(kb>?fu0Dr9VIP}JYk>??EFYL> z+jgY-Xns`Wk%PBmZGEU8?GthWr?}m;Q;k>MBskdNOiF5=HIwjEdJ?kl?p%4jIK^)- z$rxP9=PeT4s92itO4LhiKdK3E11>&9y z32*69h+Id$Nzu-0nxm*H^a<&YXjk>YVw^+HgX*itB%|4?88OKBqx~LojSueD|#ThoThOK(fd8u zd&J?M^RH4P&k&S_TtL{IH9{N;7~g4JXdQlGI`{ihyGNi4<$aS%Py%0ViV-ncV&Q}B zkYt;7Z^l@B%kC855kt^AwSm5W;`HWu1@Y%$HF&uxyuRfPf5%uk;q;63ew%+FCH3d;#<+k%s%prpCk`l}0cYl`7 z=1iQ+v6PeQZjWb@j==DFKqg(lOIBj?;*h~?;*jSp)}mBYnzE%|O7EtBt5o%uDD6GrsFQ2Y5YF=0&+*XDHYAX3IveM0)XIWY zaxWJaEojK=|2rEolfGs>4Cs)u&YbR6lA^sV@VTPq!ohx2yp{l#Gu483tY?prbQsCS z=_1g>B7@=S&y8pJ@I)l!o6)2qooL3owL3QjU)-I=%C zVS91NsN}4nD{lcv-)^`UdgLC8R1F+xGrAba7)Ew8%iC!e_#R#VO>*uRe7`kV%0pL+ z4@K{~yH&}mM(Mgs5(&6U3kTIK+P9u#X)bhTDOH^WKjS58M)LGW$>$ys4b8AKKl_2* zLmg%W<5!3KzqLo)$G`VPaKhc?rUP{_uy3m)~3QB{|PDK>*Qb3S+jX)~`xke6$kJR^^5 z$8yWqii84cgZyze5VI~3Ska^32!{j?nb#0b_~D15_T4w)h2n(}zrS9@RIzlwMbY(C zIYbsfQ|Te0hvjmizFiCl7d?tqP{iV~l3pgX#0(J-bBzvR4D8b(C_uvC=TZ3{pJZ;a zgNacGx$)X4e42Z>8w*dCGwKYFo}~Gr!x@ISZ2HCNd3x#aIk8s)a!0*}l<^ zDCx>QqaCk%FL^#Orm6t_>#9YFh3e1U;Cq$OrIE4Ro{VdGAtZ$-W*Dh`raE0Ixc0?1m0{F$AK95ry%dU?T!#+t!6L>ok z_b|WrVZIR?aH7h78xn7nUDhRE3}itcpvaJhfn>>&Sj4#F8DkoHtr_%j-c7^XaU9Rz z<7~7LkSXeHY-OpU{A5x}@^#W=Nc>be3|s|xqQ?@iKgryD6x>onZPj&&;J+vOqDzt4 z8%&k=#e-&2@0Q?9zSMpdQe{(g(obcSU_pk~nf{SQbRl2?9Hr_VI!$jv622MoD~X=K zZ#3$7jX6yvclG#7*+{DLola{mz>^v&)81DVsot10<~ojrL1*dCAhJae&y*Dy!ukSQ zBb_)leyORfSqF#pb!3eOc^F?YW-{$5NRQ+XaN2<}Rt8y{46NRi?o3JC(A!>b;&fPTG>ECE{8W?P^jD^*(WaQh3 z`c3=uI0hPpPS9Cq8BCJ*EqDz^z%j63xsMJL(mWb%I~0B2Tj@5Iu!R6(a-8o$qi3<% zqwmFRkO742Uv^sXxJ%blFKAj@k+_4C$gLB?Pax>=Glcuy^|0vDv7H{S&c^%zI|bfP z6JcLR0&n``F)J|TmSMuO0kGB0v^?+~u_NRd33mB8*QKj1JP9Cb`u z^|^V@aMTyGgokDDkWWF8RDy)-AwES$M}*!0#}!^R$2%7ya3LyN2IG{j%*%AU{$^CZ z15qdh#l+0($WS$y)Nfe~Z_k%C8Kj|c)ubZOgy9|P$v9M)JcV6!m9}^u>t#qw^p#|W zm{e6XuQUGAoJ)4}TMiJ01w>*)57XF=Iy)H9lHYXc|N8bJ!a9vyse6KE zT7G&x=ZZ~w5TlaQF`HG(J4@3eNLySKtf>BRHIGfAt*juQc2?D>)qf)^u9cs+pZOij zL8wW5Y8~|1JoM+Xe`J)gy*wRDeE6jntXpld30OAN!Dfd{aB1BD4BS6`Mj(eB{bla5 zZAa2cJr7&=6fiKV-VUP8yke7SnaQM;=lg+FEV_o>ui;yKgj40;_#Q}vI3Zy^MbB@5 zFguOqqp?fqLtsh-R~*O$xGu9@hudJF*(j3O=J20HiYMfxha%<3UaKk@)?V~=B5Dj9 zZm^btxbY3i{NUhL0Q4M47_{Te`Z1F(i#=$%%1C?b{_0E-lE78{mCdkIw#;dG6NhSt zIco-9-v)0Yr#h}#?p=Z)-&tm1J@l4tPq>R_MZanCw>bRsuLlpTyXJJb2D=6QW+7~(jB-V zdgca+=zNB&EywxdGZ_!1W)3VY*x1p6Z6%sGs}+|v(N>1fcdFc8OnfWUtFGjg9eZJk zI=%*!Demj)9}U&N7bgWzd}%VfrN%vu2m~CbOp=TrfE)Fr>A(7O^!@iRcj7(PNChZ7 z5;Sa4BFeVZpIW1?De1g3{>ZI3zS(ly`Q{beE>N{4(xG&22a5jJwzVbq%l$oqbpLqHBb>U5yqT z+J};d1QfexS6a-ZoQ6^QJ`0A{+qR*}lZffcpM)E-n~1`h+>uIMn}aoimxV5ubCKWN zp3?QLUO{uUGnOT;-)H=JVqQ$Ni)~629d5zcqU5|E4d8wClYIeV{)5Z?af@-eB`u!t z?f6-+m+m-so&AazKb5~T0p74wGWJgqV)zvTz;^y!ehdC5pQiv>GnPB<&Tao|OiI#) zzGToXW&=-P$sG~~T1vGyEE++Cs49+GA(LYuYD~>be_aZVeEFL79$&{Tf(}dZ5X(K* zb&FCafxR(udk$<`{i{t2yO4U&2RB+%<)W(9L3#qDk}OWBRrG_Ot8i)_AA1ib(qiQS zW*L=My4rQtUt?;p7pNIe@Q^D7f(D52Jp8P9ENGm8e$KQF*A9G1oCj3 zo9r!RuOkcZWn`~^n$4L=ksS#geuevKvx=%xScK{uQi(NH-EluabEdAHOe&>&y{HtP z#xP@%p_#B~Ep+vy3n#fO@JreT`k?D4a0k8{O;F&+(<8%1i%wQ`%tj62@Y8xVV;3+@ z2@?w?gvb2+{P4%Qm+$+$q6Nltqa5p{h`Oe*rdRJA?jE*~U+qP#jk7FwV)7?=;xHx( zi4-$ZtMgoBEAmXeyh*R~y1_U6VutrZSN9q&;!yio+b*t~dQaJH3+)Y%=!9A!;Ndp$ zdf+gsBtU5{$?4ypDY44u@^oD|t@tPEVaEA2j}}0xfM`dopB})0)eLa3+gnE|hR>dE zwv9cvOw7j&gnjCWHrCKv_OFp&Kz#Ku?p-@=pPgz9_xpW5WO=E?oSSS5OMVd2#i=6ik zEEe|lJM9qFe|a|HcIeqe&iRGexFKF5oGnQ4ic;Z7fcEk(Uhh&*8k15lu|%!6!gQ~2rUZ<&SaF6d{jxlG@*^BQ5?;SCYH~OaQ1$;_UPIVkUL1F&45P} zAUg1=4r&P}LRe?@-xJH% ziDiApbay(3ErW;WSE8}Bhv89znrZU%9^Urgiz98SwgY$A4wJGaSQ zDH7zsPt4zt%iN-{7sojNn(`ezFRQH&zV48BcO4AKuCPc_Ly=Z^oQ(mJMlqCZs%@Or ztlj$yQNg`Gz45mo3gxugqFc{zDIatuVlEfTmXbFFwvy!ZrcpD|LxeO^Xtu*ElIKaD zf%;HUCY=NsqeB{?Mb0O><9;4Xm)b#&lwI;-FNkO=U}*x=q06l&x`5|jxnu!(O-9V1WOno(0v%^F#Rg;EFT9i>tGOH*DU=7rTjZF0M~cjXEV?UXOx+TCwvKB-}4QG_K4DuiHnS+mo>kG~E^yBPn6*VLH7& zE@P>(jo9slu;2Ar!Tin+VwaBN82tGFRSC4z-w%r_(!MYA%T&D!v=|;T>KR7|Ut$?E zG+(AIvNQz%AzUFQ&&MUHm!@7J&~ZgXC}pRnKI^6!S8JL|nXhgG)y}-I&1WQFIhQ8lagOBy`<=8LNvm%-il`R*2Z3aiUlNu`2tw)%37z#;JdD#gSvo=FOC|71ENW`IZ%SB#SKK=&J^UagvLCm z3+cNdpUA7`htuSgb)p+nqFMcAuBZBqkWzxLM~CU$n?*~fvJC}lhwgO-^n3Q?_|jnW zBCYIdNFd?chbg)86^33&-gKfUHe+xt@V@o}Ai-38R0*MP192w&wnS!)^$LHbgFX!- z+`*6Aq1QZJAK`l|fqrrRtd!5^bN%d#%dgBZrb6ytIgn6z5Y8{S1eKIY!jZ=S)Q?ZC+4p`Gw%-2w>d z4lC!pI5CViB>qiDyi@}Kr%2PUOrsbn-K@xHfkS^^IDCz{I2`0O-j=V1)-|6M!8v1A zH-wq!xG`2Y`oIbI>#UT4&J)gx{IBmo@!JR&OWp*5*PEsViP=RAy3j?W&2RQbn#`c! zIZXC>icBwE4CnK+2N^}4kb=S1_ZHIA+n8Hb62reLye#lc?X##0Q&N$xl+|+#EyxDZ zsrn|3DOT*#?L@Bh{$0=@??VgshU*`e&NeEjRD3$T0|gIQ&)AZ_MWOP9f;dWmEy}S7 z#9JdK)H`*R-zK!^55!5>$I{wq{n}l3x^rt47Lgp>?wo&wr(`OOH3HU9IO?(%g27YP zVe5yl9upqj658@hFC|)cV`CSBW(<3rNaXr`t#9PGm9JDBx(0j0vRPzGH&a6m1-mE( zb8E_5_#=KG!KL^`tEXf*{smad*p9y6I@;uC@`R|^%TTNgLq4{4^>U?$&~s)YO- zp^*p2bf@@lRY|J|s*+QCdo;q30>cq=W$pV9jP8cCzG}`i zZnyrZl~(zfYOJdKxwCfU2gP3e*A2Z%JUbhbC>qq5XLXZWZs(quw8$t87dco+5CHzK z8<|k||2yj)`L*m*zZshoVlqElFK2cr-D0_EnkUddN=R2Tetqn8Nf6NZ zaa(5w&hCcB>yXJ0oRuF|KkM;V(u0jAgcSeR8Da%>wB#C-o zvtlQ@2xo(44&(L>#-n_8=*0PKQ!rJr#~&r<4{d`J$pCZ#H#s$U%}l|UqT0d?VjddK zxOO&(NQx+$_#4pC(7obe-!S2AzuPYk?wJgMP$aSMsQZA7`E#9YfxDMT)KNC6{@_pn z;ZIAl!zY2N6w_QR?vkdA4w8b8bI0(i87*z7>7=L<*|k9N5*)D--)_GjHY1#n3`Gfo zV}T;%dGB2I#u)o*;I!57rd}8p!SAIlW^hq-;)U)6Kj_wkAy$Fyc;L_ebl2L@PUg~g zQ@znzuv%@eZ_20GBr49F*tpkM$qd(zXA)TAq*xt3)WakMRI_M^lBgz7BSN Pe1VXcR*|ZfF#Y*I_$DB3 delta 16128 zcmZX5V{|4>v~_GuY}>}fn%Ks~b}}(Lwr$(V#F%7a+nm_8Z{BZx_t*XNbg$L@oUXI$ z?A^7itMVd2ha*85!xiNv5aDp)KtMncr6k3aK|ny!zRq7@puTFWc|VXp z#OnIR6j8h)4HT4Qqw@YK1?^hQ)}CK@*?)A~Z(eL(=&g0Fb%Aa5YBWEck1H{C{OgxAkqkX5+P>VW`l6Q*5qsv3Cl+UhlZaopKtwSCr}LgNq>BjT4X zB|)+ke#1cMW?1WIec#NW1mq>1m{PMKWP1V>3)EL&37jwfWP637hf;l2Ol=1!23Q$d zMU%`Yu#L{p>5y+yG^yn2u|eA(6>oDxn>I8Up>7CZ~yYaR6K=VKT-N<3qk`?0)KCvDSokT#6G-w%cOIAY(5By7-x2&sfoREZ!aoi+tSns>(RNc*#_ZT)5pGt_I24(E;UCs>_x#W}Io-L1ie@Fz~VvEzG-k+3F^&aJav|Tg9 zQE3xKzp(R=yrcA9AGs?d=G+%z31-B=?Ra=Ob~T*L>wPc7P>v%2Qz@SjG(I#lw9#UU zTFovByHAtO0{R1vu~B*&huVHU7Yq^RL%R}0g0LmV40O+|KLST+TZ`EjBPHxpKcEF< zwLd=ERgCvl4at`tQOxp~5U~T7Ecxx%Pltv%QYItkjM7s5hp>#E73;~4@2wbf68aKu z?g$G#c5pkQH~h@Joq|jt4~$f8F%Aw~o~kie5z2$p0Li3scMS>do!*Ach2$#=+Bbwc$H@rH$omE+C7TlOjEk0C@<;dgPe@usLy@>r zsY!okCW-R1za5zVGbMt3#1iegQaT;Z@}mZ$dS`v9v}m_RbL)n*uv-h#1&4i2lK z^>6b#2UJN8V8<}|M|seNmX%`uBS>!2<*?VM(>G^a!N8{v@Dt%tq(X4x^MIWnpVJ(R z`AwydX?s}FyB=hEWXEXOP(SjxQFvetSEt|=t{%gT;0nUY%H8CK>0)Y-q6e;zjw=RU zJqYV>JcVak`!&hQlWlvoADft4R7sl;59K_7`Ck$tF+Z=5(JI3cIvyna7T1sdSj3unP13%m)7b9h|AO-iwFy#LV<-fIg!jW69O7IOZ!xz!P zha&Pge6+jddP)~oVMVZoNqiBW5BJ<#@StV@GJpMFUkH-}KaaE@dYtZL6Bb)ISm6MG zQMJE!k7+k0pg3)Z#j05;N|Jx3Te@D`QuTRuYvKH-ndpn(tH`H8Sr47Bzm0}er|>>{ z#ORNW=FbZPExp(hsUygXpPYgc1r@Pf)Sk}oY!rh!>}&tLe%h`L{?N2GTgri9X0udi zB=bn#d>wJXPU~;8IxYrm@HU*07pGxjO9RY_RwUMLLQIjSPNEBTy4@DS zlodnl%Kv3?qG?Kgpoi?!5b98cl~1%H5nN9@v!E-%nn>-cx#D>93JXprKwd1Q)N$y? z|B(H9{xUUO7p==nGCkc{m(99K@EgbL5V$>yvroB${PSCeIbre!)iT231rW11(%jy2 zhGvQf@0FH6ryp3;9sN6AM6l(Yz4eZmR6WE(HUf6k7!`w&GabhQ22D=_?j}9*F;_pA zuIok8GhUP(N9ed!z!qexTb*2eo^)uJia36;ap5D@3b4fJ#8dRTDr}uIAN9bou~|Z2 zMH0SswxAy{XtwtwH8HkZ0dq*)rsVL!@BQx)!5f84cXbamIQb)D%KwSAG;TuZI6iFB43YLN~fCs8g^Q7gMUWCL>2A zzWIfB&vgm4LI%R&lTfiTo(F#Mnts;?b}L!2{XwNMI_C=>5a1eu@?jecAIJ0=$-Y$9 z?bRkN-J~8iu8mLLDtCM?lRjV_-SVg;t5Yvd@#Tz55B-oGBl?{!^efi5;fh}ZfdeJ3 zdR|y@0@Sq0R-iN0H-)Sm@K76UucOv8^WpEzY$NJ;J%;!eQ-^Wi&6*nw+8KyJj{DDN zxTvs)w`#xmkDmn!@%2cM{y|BE+-D`hx_HM5Is&R`%^&TJM6OuS4kp4MAStq|+x)C- zBdEhAXMd1mZvIMCEZ30Bd~1Z*z>A#pFnN3jH6f)OaFLN8^F@E zB;PHo7W%@UPRN>N1V6ZtU{CTrJOq=>DX5Axuau`CZ;{2zjDv`B@^;v!(O-!-)wS=A zk_oRd-K-rZZc)sctJq$#o#wl*Crq750-+wwfUAid(x2IX<~~x=4own8_!8-N45qGH zVt(m>6lM=cWiWCfNv=^Uq|F>9tT9pAOB(kMIoEk(7BRyYHbszF5*HOP|BMf9_|o=M zhsMdrK-fIQ4cvtN(nl_CO4@Rwgi=ucs{y}sKC-$F;+}C6H;=iW3gX0LU(_36?UBtv zS=Rlkl7@~>%Ni=OIMe?S$1$Lsf;j^iziwI4-DF=%L>XrNqIv@YbD}wfD;9*i&I99B z$%qktrtv*dJMAh>Bpm^^Wy8iH<5ft9I7V8!bM)hUUJ{ZI9u$6`x#XoeZf|U?0_2@q z1innf#DZbHp}Axz7x6S)Y~J~-IahEn->wJxHOsFV>t1k=ozlLrk>jwOP#{wDs5ge} zE#>dp5{HHED>7RmX*c$_Lk!zcMb|eBMS8V&17;9xdu!_ zkuZsB)=PNZte2&hl?njl?x%rpvVrnlD6_Y!_uoj2s47FqXe|@^q}a48F)}Y)FhDgWYardGEh|YDyjJGyE_$zhG#;&Hp%u^bo(b z{9|gyPDi<@4bhuscP3aC%56Cn0D;=itoLda>27?CS&uWiXt0dJVF2dRs;ucUjk2X4 zoabH4LUtdHGy=)*#NfE_ln?tnBl$zkzD1j;?}R77K@aL zn9=XPk9I%XN^bA-d<#HQC;{&ImkZRgUWP1g%xXC;V(Bhu2G3^5NH%r!?N9|Xerr~3 zXqUb>)dd3gx}*xt467c@qJ2!Dq!&C`N7E&NSO>GZjtFi*jb@mD$Vf|kqE&| z&$J0rKb;A_=;Qq07W^SG))|UU;d;iEVvF)yP`5O>vK~j)J5;=@Q=%5UR7Fm?GbWfE zU67+ILrgx(#dN8sB#Fk?&b`I!S!AIb%h)066B->tJR z&RG8pnS+p@T$qS8BdcrfY$Se`eXDGlUsy}+hi<;fLHPGp$KbKkrDh~y%Pk)4Oxb5J zRsfvq82#~{TlvzD*^#YpH~`|&1y-9Q9XDQO?+%_U$M6fsF4B6CGX~jAdSOi3lAvK_ zL8+|L6oRfCbJA!v$4+GvuQ9qMM!CYHUvqT0$BkU+fA4E5;0HO)H!_mS#j;8`;lCA! z%=f-CbSI>UrrMpwrUFnea&Df0aCA^lp7k6>6<9r3C1}4dHJ$(VzQ;$>CAQ#14)le9|OreZ0|_P zUZK5f7&!D26S6`O=-TruB7hzXv2qpkJz=IHrOL?FCzh;>mM@IG5DYWgUr1Z1F^m`q(zHA@kuKSqE$(23*O3|1Q zU*P!Jt&>jyv!F)iknOq>)t_QEm4wFMhDE2zhiLpG>;k>+WyJmNlK7N9H(~z#{R>0M z5iFvpj~{%u*H%ipfH}N!Z^Qrgc|?_{pso&uUf{|bviMSFu1YAM+d9a*wJnFF196S< zw|en)FK&2K$9;Kbc+ohPwRo=wlx}Xzpk*>aA#eFJq0;W#re7?Ni7xdRR7OI(jt?XD zQ~1$pB!Wgi+VHbK4)#S??jcm9T{H8EJl_SAahl8lsmZ|H-~UO<*}n{o3S@6pnm=5P zrALt{f-3U2ag-%AYQj3}*Mq;ZLPEOO!&Kr9v0Ab@r4jr=vnx~GijLxqBi1IDW$4SR zQ1z=eKtqfyEcXsn9_J(0oyRLvSADZHVOt=Zp z^UZ!#Ot$pf^{mUSpcY+@w;M%?7GIYXR>$PG+;k~(cX*le>0>R zRooTMtker;cB}Hm?7~wk{31`Eu8`+Q3EM3N#K`C42+amcw5!F6rN-qY+3#eACZ30^ z9N!aj{VjzbcPD~or6wJDLBaSYjv<&xvPq}?XD*ZMG4zcFcE^2Q!gn2RaI>K^*Fo|4 z$k3{5%QWC(L_Ju=Xuhuqs+rUk>5)}96{ZG>M-=qu@;d`Ib)1n%EpBFdm^;;HwJ z2V#T1PiqA+4;+Qd`8}tZ`3;d5Mbh#B#*J|~&F>PqQW<%vM5a8AI}HTQn~Ejl*pj0DF3FVUB9 zDijr3!mF=(1_8cOBNgu&m{QI`7A_+s)1xo4RbWYirduGn$wRUq%H0oskLtiq9|N`J z`rmNUx%zP-udy9X!mHt;J`6x@8+N<2eQ!S8q1pVw zNfd`7#0#ve@Z&REoxRsMP%Jz});Lc4ip?Of{gM9jDbS!(E39B0xL?CZ*CwvfdqW5w zn6GIu0ti0yF_<%}FGXEh*rZ+xML8n=uL0k#vKYwfD!)LHFYv!PAK@OS z=BS>UkS{Xoo=5-k`M=Q{uEc%53wYxPJfzg0qQe*j#vO+#mQs%~{)923)N*fAPma!Z zOTe?otdq+mZ-)B2&^Ee~;;JnlhxygC*#NqxVKc5$+zy9Rqt{mznZf#o0Ko5nQmtgX zd>qb$5?Ayq7lerM4R6n5P(z9ZD-xW|@%&Y7>4X@zm3-Hymc|sYQW->0yYuqxBwu<< zZ)!P#F?OGSteF9mvVTdSF_K?%Ra3P_Wf^e3vL6XEIa_&NZ|d80G{Y$z37QoLDczUZ z_9Yo5r|X}CV(NnUYEmCSx4*2u{1RK&w{@dRWjfq|Hp3ft9C-H4yyE%`w{Quvz{kiI zyP)1FO-h8E6O(U?cap-ij@eh9Ybo%vGQ;&c|7q7^UW#-^1MJgcptpJhDknx`1F8fr zW(oIAVKl(+CaTVAPyqWCP0Ek#H*$)Cz-35arh7%A)=!l};2@iyuGo{Y=?TBG`s)@; zx`2ryeedJ6g{Q%d%#h@^DG$y>0_XuUzhw3$#P_K(j>7@3Tc3yjJSV>mhpA{f;C$wQ zC_|+M#S_ja$5fo~oAyAyMhJIK4siv5`N&!=aUooR{H!aW z_fLkzZy*aJG4?;)@v&Fhzvd6P?5JBo^`FMnF=e?TK%(X?Vkw*{+`M0x8?(ROV`fBO zz^)8wCh7b1{3_2{yB<;8D|w7)6s_qn$DF+rrLF(e)_PmW+CcMRFIxn2b(<-Q)y3;O4qD^-l?1c;~>DZ^r}3BD`! zPe&Um4v20U+FWkHW$>8oFXn$^BvP^T$hx;tpGC>FE}@kND9f8)j)QUc2;d~)W!6iR z8E^7~N38jc|G|U#(>AvA?&V#;G06)lWM*PqaW#gDq0O2h>2y=|yESU_&Vp-meZFL8_rqdOvxo|NI^7(FwD_ zFBSSEnV1r@!Vw7~XH5@Og|$r%Eu(om?-!c$&DnS(*>FL)bK7v0WlmZ2Z$wW1efwNm z9#T08al~wj1ix^^gqDZx11e49v%`Fc#l zdF|CZ;cSAJVztqcs9%;?ipmDA@Z#-|Swj1;huj-ibC5agUU``$f8BksA(9o%lPIFZ zo048jcYb9Pfd(*(A&DMZ0-(=ef#R~bSZwIW&iP!(Yw;R z9cm`jH4UOOJ9Hq29jQumnHXvpr92unsIo*+ns_Nibg-o$lWib-kgiPzxVS{jO`hPj z#`G28y?!mi3#K)T*w$|}|9e_YGkga*k{09i1G(c?ptd#U^rg$D- z!;|gC!6Q3DPb)&!VrT~fEb^6qAxqK@92G+zxr5$GpQP)(NkTs|#>*3)|BI)N-$XJK zlDZ0gBQvB;&_kPJ?{dg+TjcipAVfWS^Fi#r04oMYvg0yn@pxhhrbSm*%01 zGg?_?g_hs?nTxgM0{NdZ2e-`s#2Fh!VDWT5xpcG(S}q#qcv=5RxB`dwTkM)J!^VHi z87HxxC^+$ohz-d50ipbf`ZKaf8!P{*SL?gT-o0|nunXc6F>UkyviNe1_G>@nTlnze z-_dexe^-gTjdZEM9t!toc92NU#a`F~V!U8P<&1yrsV`n(Xyh(;8!M1}Pp=U-etGA4 zB`XddDpv$on#<|UUcfkp=)(DLb1_h>jsDSXz2k89p3?-76;vVH<6}_ZQj@oQ-gaa) zD(R|=a9iPth>$Z0zMfz_h;hB z4NJ8yIOr161hbP@R{mL?M!w{burXT5K32?f8#w43>({V%9-=STDXmUaF0tfcGi>e; z%LQq0QS88}?=}n@Rb9~?)@4_Wp5W(c1KFm;jU*Ld8Kj7&H|v5F_uZrPuubgiMcoZ{uirqY7D(2fjT!1l!#(T>$ z;8+Ec_-yy&>{Cq$NpMuRLp(UuW5nO7ZSSB%#Lfu|>0M%GW^Z(3YwAE`_n&uiJ8w6f z$7+HQ1}r3Q!+yp~v8^+8Wi`;IBmDW7&X$za4P8pDo>ps7gLq-%=NQ+Yzdnt*&tuIT zU7j?%k@pjP2R|dw!AtlK4~F=$$2h(b?70^RMlVZ8&SR+tN8A?>bYIO9+%NA@NEL7$ zoxH1K`;$pVsSlS`|jL6;j?;cuJ_HAyxZFWT5cZ6M+hAHHZMU#VqAWx!z;l4S0 z8dCCgZ0|1ndd2#d{m4k(=vlr=)~Pp4ztd}MsaxO;`3UbwHG9Z3G(9O9Cs6&u1^xgq z;Swrh?Mj8ep1467Lfm=GcUWLc>t!6Seen71ez7OsW_%pw1^(CeU82?QyndE>5(=CL zL^n591#jVQmc)bg?ygWTQu6Lh77En6!iF?DIRHAmLivA=DY+h0eOQ`(t5_a)F|_yJGdO%ccCd7xlh7TPI=*~ z(9H1kw!E;I0;zz0>pRsgFf(^z8vK3oE-CO*7aBv7_wT8xtMG0~@WQs;Dy`!uvc&NS zjH|bdeORqw&ZO*zeMv#+Ra*r>v&s^Z?l0;6Dk-8LI8rN1+m*P+FK3wPe+%#c`yZHm zMx>aj@?jsuLfLUwPQ9hH9S?jM6|XpH*Bu7rnUb+E43>Rh`TFqzIOm_hOT6i2&NQ>g z(36QOD^8=)9z`#^xrMk0UrLWd_J9GU3N4Y~;cr=0$NRZMTgYr8owU79yzYPodh40VQZBrJ4?WfxfHAd+B}dq82<;_*;vosYsdl zXPqQr+Ee}g7W`{Z+c%z;?_`|3^xN!o-EOByFBl7J5<+f5)fp{EoRQ)85*z9{hQ;qE5D00H& zn6A)sMHBu-I_MN`wPzo+-@FU{>{Ufx+04~J{xgX%^HvttjAE8RvvCapG}0<{KelW~ zEyf&C!Ga$>?^3QEl#Km%BhzPwU3*bsDg)`yV#2htixa#3)~IUYGC1N65jrcKhY{CSY2e6*#r9Svkh??yBEZVA zL?c1kymJ-pITn*Mr5{`X{d;5i&R-Q~juyJ(LW*kMkXRmEbHy|i_n5tPE=ea zM@bY*o$UQC6NaM>Ly{8rp$kY*d`@I(pGL$Q}8GG1Wh@KVK!D`J05K=kGT@`e7SH+ z$u6(9)=BOB<@9Y(t-S1yqLrDjcP3v?p`Ig7IaQnQlksq=3*u^D8Rkv6EkzYG2Vp#K`B2Jj5GLKwo1n_NA#fm-f$ zhE0pmhMtz)DDi{6GGLH4i|Kiv^VulDyb%J_IvXT)X6<#2+ef1at@$I0ey5xgX&Z$8~V9k zZ8)0;p#4EM)EMfW>vSw`AFT8CxQ+^7h5B6vndp-+j5F#X!o3}-$ld6MF3-!4$R#&a z60>ZX4vW$B#y5g)S$Z7B)5}xly9%~%RL&H#{DgX$PlICCY8K27@-RUFW2hGC(4EUnK+>Gp_owHB=ZsbYkIWrY?s`2-F%a{@9vP2Jd^t zh|=+-@c3Pr)Sx*dJf;MjqTyoL7UH-8M`~+y@GN^f=Jx&&H!%HChMp#5;^1t6HpPvv z@39fDL}S$!pZBaew&T{qtz$*4Wi%4rpSgl<+b&%H9vp)~(L0Mk`7p+(qli!yl`6GE z=yMiRr?&x(t~&`!Ert9juj675=5HI}WeaVSp7h^q90>420_>WaIZGBewIj#@JSdWf zxRB3OJG;jg=^Bsgo`Vx($sc1biXk1FQv+&k%xVhEMZI-6u=Zys?Q1>DI^7Jtj!XgZ z+C&q?#=#WDm1fC6xF-W+Ccbh^R(YyUVUBb0qwPzFp|F>9r<-}FMo1f2;hJZ|mXw3R zaSxwgyNQjWOkVDwsPf3HBu+R$E9VA=YaQdu(uh#HKDCIvvD=KNtj0 z*e)ZtDz!uhHOzp(EZU{rf$`2$kgi1(3xYN7aW%88u;(GsxAU>Zb>IfCUKZ6}5?PF=x-?|m z-KF(7$QOZ<8ADpDyTnl2i`wwLc<&^Yva0oQuNEy4uKv!=6TUC?`eQ(YgbqF;rz{Y3 zZ8T>Hh)1NG@B_AaF{1J%BR@7B{_Vq=krJ4@nriKcPcO6(HM=ZF0|3N*2b(sZPjC;V zxBs7Mwd`o~svKweL+9UlRn2RBPv*Z}ZE1gw+=bq-2wX}jhv)1FsfYAd%VpDMCKtzJ znL;utnfwcqGpw6+?qv!>@K7BfEB!2{5HA=Lr=wJ!Tm%we)z*Sa{<<>Rsk9k#L|yOW zCPDLq{%90!svDjg?MpdIKo1BXV2-L;ipN$UVEgmK6Zgox5hlg%w$9PpwAh%>cOH*Unm?2HQhgeNguRV0nj4Q<04R&TQxVR>O3qe%}eQmp{1bL$d5Pb!!OE$ZIDnaou!#~ zuH{8Vu(xRtna%7iD|Pr7I&t?deEhP99*Aid@YB_6mKC zo-~d7q)C-7UI@tVx0Wk z`EW1(-A0gMdgMG=-MsCa$<;NDNvZDKMmzgK^$B!la8-oG^05aK+8TA(m5WOep-ghj zgfiJk@_TKE{f9|#TbSn#*!Oi4;+v|@!1GwwTz+D8>uX|sy75oQvzf@9EW&XS5^9y) z@LRb*YBi>tv6fkjr{oYj{6>D=20+>Y)stHS^zif{hnY5!(r`^`e!Cih?mQ<8T3CkX zh>`|a79>J(I|E`{SI;zRurrbV`*0gg%m<>38N7K4TqvjHln`=&|7+lOYS&CRU^sr@ z6EdF0g&#gOgNmfC-jgMujYfFqcw3GeqFg#uGMedVfqounl^9s?;ERHkGUptsp5mtw zeph~NOPZ12uj7U8gOzzr)sG|?F@68w7tW>e{-N20zpm<9`L@h`(oXav-IP5iXHn|| zyyaol^VfXs@1GKHJK0XxNR&!=faSj<0@${^>e70SyfwJkuPl~JD6HaKBJFlA9z@BNoZCin7Favoi$%atLbN{*=`x z1`Bse&Q<+>L7MJ8JARdWT?T|w*Tfq$!^C^@d*lSqKRs_d4r%59!AbC5e9rRWJKrn^ z?9Es=6P!Yimhg1$QNLNL8Xrrvu^2mtnFBxL zGW)mh2Ue2gg^j?bSebX$FAfk(9@!aloWZsup$(W*2xzmI1GmpvUKL(P`@YNAO2)SB z397$;?G^ICNi|cD!{XQoK8VPJnr{5n^@-Jfa=uYr;s-i%+3iJ>g-z&vD+7a>6#els zzsTKZFwO-xYENG$ENL4QZxOy+-(ujlh!|;4mf9?u&+TyX*S0SdcsO}c;&9p`- zHE&UlmCRJ$62j*FaBJh>hcutFhk)xILLACLfJLEkU z)f=^l1v~c&NUr;Zw{)4ZlI*@PZK{YnF%Z67T1UGy?Hq??Z){uDU9bC{>mmu zfJ=#c-##+Gbu}~tFQuIR%%2<9Maqk#fd4c$MoAF8iN!cUD1y=FLCLw3EDT*tr5mpD z)Ne?_T|`~(J4bQ~m!-Eb^vcEP6}a4h%?yz1*`EF^nwkIJfR@p`>qA~WaAU$PVu=%D zx(qu&U9Cy+-RR#@p+vIx%|kEG0-ns4eJ5{2&7q;`5w~Pt(X%k((oVS z=gU}`F{pCTdIXO+JxLwTwS0;Y2VV&B1Qb)RkciTe#_)7^NF^c=kE!J$uN5jxc>p+S zNk-PssGku`#F&I)kZEJuR;@C{rjW2Y77H_m)_?hBIUrh~#Nu%k6K<2lm&Z55Vb_HtkU0 z+5U#qE6}bY{UO)sKMxwfcZ0+OF5l3*o_vs_C=y|CS*TJveQ%u5L_%km2Z0H5 zmi@m1Xpd%+RQ8v8vr_Ja&F;V(f@~9!017PreA|FV=dZ&GXoa6dTTdZ+9Ol?ieZQOH z(N{vbw~@P7l-H{A)x2Mz9@$xqhsrF6Szulph281+)$QOPLS#YGNQUKMmnyHbn%s)na8K8&_@=qM}$KF8nLi_T+=$4eD zx=>J`Qry~G9Z4-~#U&13l{b6Gl_%NLUew!(e=3>ju*m})`-R-~aG_h$XWWRQtiK=J zPH#p!JB`Kq5x|mYX;!x*O?R|r%{TIrgHnLJ(-4CriX-xR&%>w5J{(-1v}goYV{Um$-SJ)|X&pbT=WV^}tMBJ`x{|0cb)R>RnrClj zQw>WlWP{_vAN)P1m5Y+5=14@-^K)^NcZj;bBO#o-GbHy@&5ZX|`xo5lo`LBdt!^)V zQg@;0g?U~G5dgbR{$l>77MAB4TzuWO;x>%gpzWs}QIeEGKc!AbbXYzGG4(?U#cpk) z%-WXeZl3bsKV1h`SIj@j<`ic`YVYkf{hDGw^na9Cwxn!kq*M8@IKRN(2AgI_i>81? zvaH50D&>{7^oO<|W+TpckWa$+rEU^rt=2;`V1%W$90OzEx>cm%kvb8Z%1?DT&;-#g z+jIBQ(32%W=xT^MiFXoe+HG<+V{vs~$*PkE{>E@7@V-_ZV z33#C5i)XEzdFq!+4Uda%Avv0SYT=y5a`i2VXHh=`jMrNWWAgE2dMo zNaqU{6p$e$a~1z6NMm*JLCbc6DPt4w#{_)nq&uuf1173$HW#ax{{*djAD(SS4scPLh)d9!Mcb8mg!ZL7nTlpp!w zN*Fep_#z?FEwt+dNgRurNP3mmPL{_%3a(>Qp0FtGtkkEEDw-UI&a3o>1SwlVZ;#k!3mQhce`_NESpK$72+Jx0KYzOv2}g+T}WlzlJk(yqvsFB5y9w%P<}|Q3?t94 zFNrP9zwANDAaX4>7o^gn0?H z7}f2#s7(Q!QI$*NjF)l9YtJAk3aj42&w*QLgg-|snL@9+&huzxDzj5{ze0C*5d|$s zwK}{K3y?}jH-kgUy+CmVL);JHoU0?1D866;Xh^5eJw= zUvhAHj6aZ%f3B$B_6X1KZaDm7U`D;fV;74=?Kq*rh{j)A#@-lRXwr#4QqhK6h|qBs z@s^`Hx5V;kMl01=lo#XsucVqQ&lH@OT(Unqaawd-+A+z`F zAg2i<+Wpp}Gga4@FEIV|>3S7BWdlHPwZWGHE~Tl$g6yne5mv6$N8T(?0p^>3^LcNB zakQIVI{@8448#}W#ftkU;uIEK#5?wFsMvsEe%UqjIDvqq00+CW2STO&51zgz3$(Vp z_)qnk-vr_|2RVA8{deMqrb4+>aJQ(u>`V(tt46|-)JhGQ+5g}qgOLMgb^uXLB>9Bf z&rJlJ#1Osv8?t8hO^Y)x?z_KC*lqY>;7}zyy4i4gsaP~jn;7Skh#%LPUJ9O#1FT|X z)A1=wT{m3w_nJ31Ma;Vy3D){+NqD1e_AE%r5#q(CSEpOp0rn{G*!s9$J_EXF`q3f5 z>phSLy~XYHN(w)l#15A~69N7=t@;mkt6ruKj~)2Eu9lSX0uNCh|8O5BDttaHy%w>q z=Zr9+gLJ7N-+{B=gfyN1(kVpRy91A&_?1Uz8$=7A{FI zFSX^}ZLb%YnEdM+VMnY%S)?Sph}V*_dzYbe)5yKBdeMIj-XRzv)qQMKZ05dI#h+!| zvsS!Mb!_x%^aVKMBLFp5()GzRjds;Y^V#3e+Lr|SY+zM*@wFKi3?%JC|EXXE#$9e2 z&1SW*p2AAHb<0fZuwl_K;yui@ z5FL+)7$c5u#1Lv3Q>uoJ4o$t(Z54eVg1ix#%Zu$0sWr(fKLI%2%kJ~pp>aZ3B$rlB z9qUiLu1OJKqJO%}7D171&OOQY5@`s^Qx$upyw!_k@0G}NJAuVGsW`htMg+^tE01JW zzUGGb@TR-el|0tA9`601&=3$r!Mzd$IZd>v5S|4sY8BQrA_zhobuM8^vupxG&|@Qv zWJb=5bI|w`u^odpsQvA5OFw zuhsI5eh~~is%3Cm^BN4`AAf-${ zys+0v;`qEfh6gB|Gky2<5-6PdH(o8qXFT=7+X|%9$TcRLhG?^?E>6u7!IkcJrvJd= z;~zwM0DaWG%g;sjz%A?~SGyN&60 zWblZly8TEM0NBL+^euHEibyrJ_3F(IECDO)0gL281jrQOB5c_x&@LNZfh{)7IUsAn zws_(g$A6J@+AcvV5;EvWA9UX!^159T;@uJkBd4O2vxwWdw^ELbuQn1rH*y4~C|c+} zNZ`CEEAKmmfjoeD$0jP(Fdv#DYT0t~cLbI&`ULRTB!=vQ+NmhY)?r`=d)3 zLbU(4H&)qOjocOi<^2$${pp!3Q%2c&rITi~(QY2fb2_<)b4SN7Dsg_91+0S;EL#F} zZNyRC^~!UZFpKv5pOPqJ_9JSM}2A%AmrmFZgmy$FgQ$Qo72 ze|zr+)z}oY7Dg(E28;87AQLRJ-&r>L1^v$*O4~_pw^`n zFVBX2Ecj-}`~@kQCg^)1r-Yha1HOF0^xSY{)B7m@Eal;9r<+7i4JSbhxx6c~Wp^A~ zQ4o&3P1$TB2F`SX(;O&R6Y}_cWT0ELaKhaL z*>ZIWEGM)Z5p~;%j z6w*XxCPS7fyKH4J7&AV%&-2swANYR1_v>}v=RW7$*E!d@uJ`r6&V7>M_Ld?-hlM~O zkchRFIRXUQbpUwZ6x#c#56vjlkV&A;<69ui&Y50 z1!VTO)t)HE9j+}#lRQ?Y;lb(DWlbvs(c&nkju^}&) z6Tfjbmw8<`INRGBpRxyASk(s#W;kJDfaF6B)|u_WQzw5ju0t0M*Pf?iV_SKJUGW-I z(D?KNtAziSB`{%)YNsYH_8`=XHA*Z zd&v7oq9LCs$fEhJ;aSVdJ+6WXFVk;hdR5YJ;rmCWrYyCz%Tjic%{{CTURumCQ=lF8 z1fwR^kJJ*eloAL^eh#moA}cYvI~{r$EvYFoc&yUfOiN6X>Xbu3&iq%}&cM;DhuO#2 z>3A&u-N_Y4)-&Fbh`eto)o-h%aB*j-qznS}136aK`R~eOLeyfRvTtK?PC8HVU$Ewo zR5(myXQ=z`P6)5Gpun)5j)Pb@04IPAx!B_M=jQ{ClEnfNadOc_wd8_CV zmn_H-KdXcAN+q(}dQ#kBpKAjsjq4{8wWvgV+fSD*>v3oc)8R;A?fM?!7&x1brq&1R>R7MLa= znXBLcX*Vi?3dh!aXuF_)B5GX=3JT1%MgdGcK*~KQxu3|qpjCuX0cs!M*fT$^0flrK zW9KRnUX_@?$$A>W#FLEk50H7{R43`6qZhOyf7<@{lk<|_|80=;vd37E@S`P$Ay_jl z5zJXB@EY>bRyUNRAn%>JsvvK)Oo-7e7Nkou#UmEr1&+m4mILmT3Hq4=2TYVv0yfq`1ae%&Jd1o;+g*-)&GshziSo8drV|^*1@viV-BHnzfu5 z^+zOn`B*gH25kul4wKbWGHoiHob6P^SK=+Iz+Q-^wR?$djmt(+|AeYvf9&T*e?=yf zuQO{Z=(AZ_SqP%JsHzbepdZd{sY@S%9{a^bMMd4d-J0mF33hjLyCjJ*z$G!1E7;up{00)?`ubYCw*QIa)!mh65 zOE6c8g6%rs&p*F@{AlOx&9bQ&j00mWEG_|fVrKoi;$;Om-2sx7!WDc;CQshzt*Uyk zL|ZwZ3D~h{f*nUtoD6UBuAPbN?eGqZjg9s9SJfNx*+CP2YLXqd*oi2CyLx!6`0-Op zZEbBQ!VSOf%LNz<4r4nxzd$cAqfBt!D&qS^jUo1WcKOA{iV6xvIXSMbuIiFPN(WB= zOW|K!|4YF`wTH0*ZJ$PYSH6YEP8T|_{hE6eW5{xkZE-0%Q5tad2a%Z=yfIJjg5H{L zfU!cGU@R2W4rRXdwWO^+#O=_fTl7i0;|cc;aeHqwx28XRN~Nh@4(P7iTBe;K&}Z#Q zg3bc~5q9DiT{OYY&OMXig;&I?LZ1OqbOevb8@&;7DzO9XA@(XfL+k1e{Ga1T%PtgA zQUnhR#X&SZ$gZk+C=1`M0O($jsSp~HTI+y*%jX633tVesE>FA@)s*0oI-=)k>ky@J zXk_2z$5t4fHC(!Z1nQCG(7 zIrRXu>P4|*&n|urA9_Zd+cJiwI=Nm)9sbi-TuZ|}g05EJl@C!y*ssRfec8y(2dKbk zi8*S8n;YKU<0jWClfjVvU<6C8UwyEgxcXf*&mbTqmjB#cP1Te6@D+Nw4w<@|I9Z)= z!sBLa{rBzX(2XVZYTX^e-uU#w27o$Zc7HQ1(hjYmYJQEnOI zx@Vei=H}R{Uf2pH!(MQo*c=n3Bx%yBs_-@y_N2D$%f9Y6}~`m`(8o3tD3)GbDLv@_7Q{tU72``)LQq3n@6R7!=&}w`)2hx88cH;{y*k+mmKS> z9P_?)3rW|by&oCzTuh^JzZIsBex7D?7DuXCu{giD;NaB6TQzWXSAQkzzL}Ysm6a6+ z!$}idKRh6}*(l;3U31aWlH}QP(Jd`n9Y{5l`0=S8K%@LDn~t2B<)PCB-wKUm^z2Rr z_?>0UMjC;!K(yzd2|+HBU%#HBlg5heiwAy&8ts`4KNPQ)s^f-VX!zt`pQ+LWRjtzu zsCVO>o_OT5n%V8k+kh_~ZiY*Cw1#95j=(AqN{_EK-omqbt>0N1XW4|EDLPI;wl{|r zo-NPp@n2|YC_f*U=*~}x7d_Batwz)JJ5Z;2J?Y^_1)~v&rDIvjvp{>&pH0V= zW#|RME=aB|a*gM)SCR0r^d8^?q=NtIy>@gb=gD5y zmm9=T)RBT{UK80W(|5F;e^6)o-a&h^fr+F%BW;f14Z%-q#~h+g#&z??bJ2kW=!;VI zs;Z#8DMS*n8d0Jc5QDbral!d3hAuA1nm%|d{BCgbR!ZsfnwoyausWzzYL6em(4$fB zx}xjiNXzuHqtEfGDoBd%x}~M6s%m(XN6U#Dcol2aYX*v3;{a(NAp2>@zQ$Mb|%dABeShk@Y&h2qru+ZRNhSg+S==c(m3<`SgvD)=~`hF$7fPmSy>ypprBMi z9a#t1#xUyF6T0F!pT}KG77^7>OG|5#E6B~y9~v4eE4X`dG%FB#itgOFk9@X3Fx*g5 zX5wq>+UzK_r10Sx{UW2NkMHgtE|P>1=q@!LB?W#OU@UAqlzh)6BF=G?bgS1L??)3( zJEWT(zP}&um%@wE0b{jJoXEDR2-dGwPoW7k*pQKA<2&=WSK4Tv zjXq?WnJ-kvIXxCZ89!fS1B5*^d1O1hxn`)Lt+C}yb4{0bZBtVdu<3Xxsu+}qw^eP5 z?`vSa`8tuZFCaAZi|N+{&I9g*zNjy-D7VCkaFItfb5log+J}~%qsL;`_N*uZ)tkH8lkzdfVuh)rMz1+~%pXRa%R2k%Ypi@mF`A1>$iaqEm{l z1Z}^;BBHTg_Z9b}_u`GlfIyCdT=>JDO^yCF1v#S|k5qBic66JH%x8gv!Tpo2`jalg zu4ig+6e6R5l%>ZH2iOFV_}fEJf(i8c#6p z%#)7yvrjLdj3N*Zy(kWDIq6;h`Q}i(NCQ#m|VzEsDi18udSA}Cik_5frzn* z;X^0>Ii*;6*`5I3Av1KtXofw(gyD^5^{ubRI)-#+_~phU{NmyUdAX9mo00(74hx7c z`ntXLxafOWQIRz;aLwStxGwe?_`6Qw&8#x{vXr+8E_FrR7BA0H2mjn;n%~{UQ(=_l zV)C@ey9z{dVxYg$MYs;RsshC>ulgbY=@+Uj3M{*Cgx~!4U2-_?tkHKf1PTAo(`YP_gifpVY+J2Ncsi_ z1M_NYvS_<(%hjj;kHdE!sHdEl{ z)#e&eQBil*e#*X<_@u}tl_cu2D#oT_nM`^#APSOJEc2mou_xLF`oFRFmI?8w$?;on@yLD2Z` zKS2IWZOB%Tlaqrc7U%%U2b|tzu@U6AvriH^`Ty*|<$s<4b#L$TZ+9`WyXp}SoN0lq ME$q!}&R@OzA3!)iFaQ7m literal 2402 zcmai$dpy(oAIIm?kqEUVMI1|COS+h2jFQXTx1B9IU5@L*+;d$jLMd%T+LDdA=Y9!U zO`&8o_mayIDdv_-A-UVxJbwN6dpyqL@p*i{ulM)+e7#=Z@At0{8Hcslxnuth5D2u> z$`W-31QG!Y^y+po!Cqx!8!Whp6OA#(AW(UN)Vj+y!7LJV#=-^wfTCV04r1+CN^`RT6k>eVYF zBcruOb2^VqMINXu5{N;Nm zqHJ#!fI!<5tx(2xq5U(1Q-n$wWLu}W2EJU6rPH6guvvy==MQlDuww4toQBkVvx=gB zS56+3F_shmk9B{jb$qEsJ>}{Re&V>w8v9)6amureTuaCH72!MtnmxS`rtIbfQ8e9$UWfTA8?9)t?!XzL_}Y0;vq!}N8n+<^&H^8AcCFY4@fNOCpmAEU**@Zl%mYXyJ-UgseWGAX^U|40*v+ zfXPrB@bc8vNIp9*MDikKcSEHwu|0PLVtGV@`6R2u#yu$wc8g+LOl>S2ad zNlq75jnbj!Li+}4Hk8eTq?md-io$%ik8Vif4I@P%8K6VEX@g_9_%%>-ohogqEmNrl zWWBQA=;}w`oukPTxMpbNgHp2WFZqNl@k?fK$Cs8z-!G%x@j@t#e39C>$l zgZtJ{NLKmfDJJjzpM)p-zow=T7c!IAXmXAAa3Y5p5EM;Z>c zOqrTzK1V;PP3h$!@uGlamb4CXM%Fvf9sS;PpLbw?dN;3?t`-CD<~==K$ffI8?KJBV z$O0~1mn?g`EfXfhy#hsnfXpWyk2r#9m7z44^L5I$0d_@TD)J6|dUee^N(9NF1QIdW z7c8JDBqEOj8U4gaCAneZ3DCwRAn``nY$?~Xx0?q80yo_Ds5fs2k_s70qc`RT8gvp` zTmuBwT)-mjhWgODYlM1lVq4QO!B6S!<=I0&irx##s3-*T9Gs{@SVZkJf7v0pGL<_l zXb8u|uZMka*Uc{xCpT@S)B;2g$(-4-#?`YOSJi-6!ACCYAY)CZ^w9FXyr)y%fk_sq zKox&aL8E}ZYC|6VH1U2bs(rYDQ1M*QV@F-69=a(k=n+(2Uo7kG{ah1=LObq9E{v5P z@wfuEW_yVEt^(zEYC-g_v**Icv2Uw@^!n2qc0lw;GgSyEajkc()wgzg zMwx4?mmd*ZSzv-sS*PrXmPwoHCu{J#mEU6f3zKHcfstl%v;N|g@enS*%Ae54Yj}uj z%lRoIKV@-jL<`+`t5!Mnl8aSt*vsldhPXT0zMwmyK)w{wBavcnpw(X>_Rr*HGi{_F z`~2dwy1Ho@*a$7Y4t*SX^aNdgA^0qU)M;vy`e}AuIy{*?sC@UQs*0i<6PuK90L3BJ z#nu2OGmkAxPU;{s;ymw-l>?7T5Yauir!94LW*z^DztyXG!f=i;5#G|L`JzA-TT^-W zHSb#W!vG3FzjIEZh*9}Hxs6!gW;WIx?N=MJ7)t$m?ZjAUQpgDMNjqCLrYR@e8Ul8~ z+Psy>pX(WZ4Gf-eKGYK;%Zx|s>8`Sae1=jgch4VabK)gvvD*?Qv2i2$B^`H8g(+00 z8erfHDDIDivGiM~LzTQwW+tc7($y{!-|=5XBhem8GYv~9_Zy_fot1a<^}{Qx3@~0n zS>`OXmrvV6GeX5woY=vOc{V)GTp#|EC$#lWGRBhLZsws0(C2FIb2}u9JexkenOO|F z=vsfrkhza|EXMqeXfR2?fdF^x_TMO+4y!qL_>}X}ju(jP#?Fv{$BUg`IpaUv(gW(Z zokCrLI|RF?YB?TgRZY3pmX*-GG86H1Km1GAOX<@~Si73-#j?8`_8RP`)TGykPIkqn zX{gu7UC#Qv&Yk?s{{C}%Q7(!+Rdy)#y!uRZldTj(uRUy_tCLN2kOmNxK6b8dBUqK0 z3rQnZ0wp{|!dKhD!%!+SW46E;%T$M|%&@3Z6X%=% E0-^VOCIA2c diff --git a/docs/img/premium/retool-readme.png b/docs/img/premium/retool-readme.png index 56adba04d3acc812f5499e19ecd9c72d3632eb32..9715634274d3a17d50099384201259e6e2d4c172 100644 GIT binary patch literal 8921 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 diff --git a/docs/img/premium/sentry-readme.png b/docs/img/premium/sentry-readme.png index 420e8ee8770b07df2af147c9b95293331158db18..3c8858aca7093410b568e373f0a6ad78469f6c62 100644 GIT binary patch delta 23629 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

    #CGJW@%-Vi_DV!G=cC3Dxq)931F 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 Prr~5I6(!2W4gCKH;KJcb diff --git a/docs/img/premium/stream-readme.png b/docs/img/premium/stream-readme.png index 15da6ba71d07b65483d340b7dd519c6171126eba..a6a7317b7c2ef88c011e7cb8a98b649287ac0657 100644 GIT binary patch literal 19170 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 X{nT9-*dJL4I-tta)z4*}Q$iB}z?3lk From e5fb9af0eaffde683fa0af3987085f86cf0d2640 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 26 May 2022 11:19:09 +0100 Subject: [PATCH 099/228] Add FEZTO as a premium sponsor --- docs/index.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index e58f24df8..a96f06a30 100644 --- a/docs/index.md +++ b/docs/index.md @@ -68,16 +68,15 @@ continued development by **[signing up for a paid plan][funding]**.

    -*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), and [CryptAPI](https://cryptapi.io).* +*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [CryptAPI](https://cryptapi.io), and [FEZTO](https://www.fezto.xyz/?utm_source=DjangoRESTFramework).* --- From ce21454a431e0feb057ff9069a8295e2b071d79e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 6 Jun 2022 11:00:01 +0100 Subject: [PATCH 100/228] Update homepage sponsors --- docs/index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index a96f06a30..aa502a621 100644 --- a/docs/index.md +++ b/docs/index.md @@ -68,6 +68,7 @@ continued development by **[signing up for a paid plan][funding]**.
    -*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [CryptAPI](https://cryptapi.io), and [FEZTO](https://www.fezto.xyz/?utm_source=DjangoRESTFramework).* +*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage), [Spacinov](https://www.spacinov.com/), [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship), [bit.io](https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [PostHog](https://posthog.com?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship), [CryptAPI](https://cryptapi.io), and [FEZTO](https://www.fezto.xyz/?utm_source=DjangoRESTFramework).* --- From 7069083b0f3c67f030dad1b9f5c6c079f30a84d2 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 6 Jun 2022 11:07:25 +0100 Subject: [PATCH 101/228] Promote Spacinov to premium sponsorship --- README.md | 5 ++++- docs/img/premium/spacinov-readme.png | Bin 0 -> 56997 bytes 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/img/premium/spacinov-readme.png diff --git a/README.md b/README.md index 9476e92d2..3fbd2f83a 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ The initial aim is to provide a single full-time position on REST framework. [![][sentry-img]][sentry-url] [![][stream-img]][stream-url] +[![][spacinov-img]][spacinov-url] [![][retool-img]][retool-url] [![][bitio-img]][bitio-url] [![][posthog-img]][posthog-url] [![][cryptapi-img]][cryptapi-url] [![][fezto-img]][fezto-url] -Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], [CryptAPI][cryptapi-url], and [FEZTO][fezto-url]. +Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Spacinov][spacinov-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], [CryptAPI][cryptapi-url], and [FEZTO][fezto-url]. --- @@ -193,6 +194,7 @@ Please see the [security policy][security-policy]. [sentry-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/sentry-readme.png [stream-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/stream-readme.png +[spacinov-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/spacinov-readme.png [retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png [bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png [posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png @@ -201,6 +203,7 @@ Please see the [security policy][security-policy]. [sentry-url]: https://getsentry.com/welcome/ [stream-url]: https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage +[spacinov-url]: https://www.spacinov.com/ [retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship [bitio-url]: https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship [posthog-url]: https://posthog.com?utm_source=drf&utm_medium=sponsorship&utm_campaign=open-source-sponsorship diff --git a/docs/img/premium/spacinov-readme.png b/docs/img/premium/spacinov-readme.png new file mode 100644 index 0000000000000000000000000000000000000000..20e925211aecab7d5be832d9c4cd96478fb2e909 GIT binary patch literal 56997 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 z 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 literal 0 HcmV?d00001 From 333f1ffb943370816f2e0b0137f0e7cb786a1d51 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Mon, 6 Jun 2022 13:39:06 +0200 Subject: [PATCH 102/228] Confirmed support for Django 4.1. (#8498) --- README.md | 2 +- docs/index.md | 2 +- rest_framework/fields.py | 3 +-- setup.py | 1 + tests/test_encoders.py | 5 +++-- tests/test_fields.py | 4 +++- tests/test_model_serializer.py | 10 +++++++--- tox.ini | 6 ++++-- 8 files changed, 21 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3fbd2f83a..e6e43047e 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements * Python (3.6, 3.7, 3.8, 3.9, 3.10) -* Django (2.2, 3.0, 3.1, 3.2, 4.0) +* Django (2.2, 3.0, 3.1, 3.2, 4.0, 4.1) We **highly recommend** and only officially support the latest patch release of each Python and Django series. diff --git a/docs/index.md b/docs/index.md index aa502a621..2f44fae9a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -86,7 +86,7 @@ continued development by **[signing up for a paid plan][funding]**. REST framework requires the following: * Python (3.6, 3.7, 3.8, 3.9, 3.10) -* Django (2.2, 3.0, 3.1, 3.2, 4.0) +* Django (2.2, 3.0, 3.1, 3.2, 4.0, 4.1) We **highly recommend** and only officially support the latest patch release of each Python and Django series. diff --git a/rest_framework/fields.py b/rest_framework/fields.py index d7e7816ce..8d02b3206 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -27,7 +27,6 @@ from django.utils.duration import duration_string from django.utils.encoding import is_protected_type, smart_str from django.utils.formats import localize_input, sanitize_separators from django.utils.ipv6 import clean_ipv6_address -from django.utils.timezone import utc from django.utils.translation import gettext_lazy as _ from pytz.exceptions import InvalidTimeError @@ -1190,7 +1189,7 @@ class DateTimeField(Field): except InvalidTimeError: self.fail('make_aware', timezone=field_timezone) elif (field_timezone is None) and timezone.is_aware(value): - return timezone.make_naive(value, utc) + return timezone.make_naive(value, datetime.timezone.utc) return value def default_timezone(self): diff --git a/setup.py b/setup.py index 3c3761c86..cb6708c6e 100755 --- a/setup.py +++ b/setup.py @@ -94,6 +94,7 @@ setup( 'Framework :: Django :: 3.1', 'Framework :: Django :: 3.2', 'Framework :: Django :: 4.0', + 'Framework :: Django :: 4.1', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', diff --git a/tests/test_encoders.py b/tests/test_encoders.py index c104dd5a5..953e5564b 100644 --- a/tests/test_encoders.py +++ b/tests/test_encoders.py @@ -1,15 +1,16 @@ -from datetime import date, datetime, timedelta +from datetime import date, datetime, timedelta, timezone from decimal import Decimal from uuid import uuid4 import pytest from django.test import TestCase -from django.utils.timezone import utc from rest_framework.compat import coreapi from rest_framework.utils.encoders import JSONEncoder from rest_framework.utils.serializer_helpers import ReturnList +utc = timezone.utc + class MockList: def tolist(self): diff --git a/tests/test_fields.py b/tests/test_fields.py index 7a5304a82..ec121c822 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -9,7 +9,7 @@ import pytz from django.core.exceptions import ValidationError as DjangoValidationError from django.http import QueryDict from django.test import TestCase, override_settings -from django.utils.timezone import activate, deactivate, override, utc +from django.utils.timezone import activate, deactivate, override import rest_framework from rest_framework import exceptions, serializers @@ -17,6 +17,8 @@ from rest_framework.fields import ( BuiltinSignatureError, DjangoImageField, is_simple_callable ) +utc = datetime.timezone.utc + # Tests for helper functions. # --------------------------- diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index 7da1b41ae..abb4830d1 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -12,6 +12,7 @@ import sys import tempfile from collections import OrderedDict +import django import pytest from django.core.exceptions import ImproperlyConfigured from django.core.serializers.json import DjangoJSONEncoder @@ -452,11 +453,14 @@ class TestPosgresFieldsMapping(TestCase): model = ArrayFieldModel fields = ['array_field', 'array_field_with_blank'] + validators = "" + if django.VERSION < (4, 1): + validators = ", validators=[]" expected = dedent(""" TestSerializer(): - array_field = ListField(allow_empty=False, child=CharField(label='Array field', validators=[])) - array_field_with_blank = ListField(child=CharField(label='Array field with blank', validators=[]), required=False) - """) + array_field = ListField(allow_empty=False, child=CharField(label='Array field'%s)) + array_field_with_blank = ListField(child=CharField(label='Array field with blank'%s), required=False) + """ % (validators, validators)) self.assertEqual(repr(TestSerializer()), expected) @pytest.mark.skipif(hasattr(models, 'JSONField'), reason='has models.JSONField') diff --git a/tox.ini b/tox.ini index a41176d72..c275a0abe 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist = {py36,py37,py38,py39}-django22, {py36,py37,py38,py39}-django31, {py36,py37,py38,py39,py310}-django32, - {py38,py39,py310}-{django40,djangomain}, + {py38,py39,py310}-{django40,django41,djangomain}, base,dist,docs, [travis:env] @@ -12,6 +12,7 @@ DJANGO = 3.1: django31 3.2: django32 4.0: django40 + 4.1: django41 main: djangomain [testenv] @@ -24,7 +25,8 @@ deps = django22: Django>=2.2,<3.0 django31: Django>=3.1,<3.2 django32: Django>=3.2,<4.0 - django40: Django>=4.0,<5.0 + django40: Django>=4.0,<4.1 + django41: Django>=4.1a1,<4.2 djangomain: https://github.com/django/django/archive/main.tar.gz -rrequirements/requirements-testing.txt -rrequirements/requirements-optionals.txt From 5471f8a1d9f54e298b3826a4d910d56ad3c6206c Mon Sep 17 00:00:00 2001 From: Leonardo Gregianin Date: Mon, 6 Jun 2022 07:39:36 -0400 Subject: [PATCH 103/228] Added django-requestlogs in third party packages (#8497) --- docs/community/third-party-packages.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/community/third-party-packages.md b/docs/community/third-party-packages.md index e25421f50..d4e590952 100644 --- a/docs/community/third-party-packages.md +++ b/docs/community/third-party-packages.md @@ -148,6 +148,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque * [django-elasticsearch-dsl-drf][django-elasticsearch-dsl-drf] - Integrate Elasticsearch DSL with Django REST framework. Package provides views, serializers, filter backends, pagination and other handy add-ons. * [django-api-client][django-api-client] - DRF client that groups the Endpoint response, for use in CBVs and FBV as if you were working with Django's Native Models.. * [fast-drf] - A model based library for making API development faster and easier. +* [django-requestlogs] - Providing middleware and other helpers for audit logging for REST framework. [cite]: http://www.software-ecosystems.com/Software_Ecosystems/Ecosystems.html [cookiecutter]: https://github.com/jpadilla/cookiecutter-django-rest-framework @@ -237,3 +238,4 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque [graphwrap]: https://github.com/PaulGilmartin/graph_wrap [rest-framework-actions]: https://github.com/AlexisMunera98/rest-framework-actions [fast-drf]: https://github.com/iashraful/fast-drf +[django-requestlogs]: https://github.com/Raekkeri/django-requestlogs From 292ead1fe0f779254590a47a352d545d57132266 Mon Sep 17 00:00:00 2001 From: ghazi-git Date: Mon, 6 Jun 2022 12:46:11 +0100 Subject: [PATCH 104/228] add drf-standardized-errors to third party packages (#8487) Co-authored-by: Tom Christie --- docs/api-guide/exceptions.md | 9 +++++++++ docs/community/third-party-packages.md | 2 ++ 2 files changed, 11 insertions(+) diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index e62a7e4f9..347541d56 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -260,6 +260,15 @@ Set as `handler400`: handler400 = 'rest_framework.exceptions.bad_request' +# Third party packages + +The following third-party packages are also available. + +## DRF Standardized Errors + +The [drf-standardized-errors][drf-standardized-errors] package provides an exception handler that generates the same format for all 4xx and 5xx responses. It is a drop-in replacement for the default exception handler and allows customizing the error response format without rewriting the whole exception handler. The standardized error response format is easier to document and easier to handle by API consumers. + [cite]: https://doughellmann.com/blog/2009/06/19/python-exception-handling-techniques/ [authentication]: authentication.md [django-custom-error-views]: https://docs.djangoproject.com/en/dev/topics/http/views/#customizing-error-views +[drf-standardized-errors]: https://github.com/ghazi-git/drf-standardized-errors diff --git a/docs/community/third-party-packages.md b/docs/community/third-party-packages.md index d4e590952..9513b13d1 100644 --- a/docs/community/third-party-packages.md +++ b/docs/community/third-party-packages.md @@ -149,6 +149,7 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque * [django-api-client][django-api-client] - DRF client that groups the Endpoint response, for use in CBVs and FBV as if you were working with Django's Native Models.. * [fast-drf] - A model based library for making API development faster and easier. * [django-requestlogs] - Providing middleware and other helpers for audit logging for REST framework. +* [drf-standardized-errors][drf-standardized-errors] - DRF exception handler to standardize error responses for all API endpoints. [cite]: http://www.software-ecosystems.com/Software_Ecosystems/Ecosystems.html [cookiecutter]: https://github.com/jpadilla/cookiecutter-django-rest-framework @@ -239,3 +240,4 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque [rest-framework-actions]: https://github.com/AlexisMunera98/rest-framework-actions [fast-drf]: https://github.com/iashraful/fast-drf [django-requestlogs]: https://github.com/Raekkeri/django-requestlogs +[drf-standardized-errors]: https://github.com/ghazi-git/drf-standardized-errors From 281fc074ba255ed9c5724cc971fa86c78d4dca38 Mon Sep 17 00:00:00 2001 From: Krukov D Date: Mon, 6 Jun 2022 14:54:57 +0300 Subject: [PATCH 105/228] improve performance for noncallble attributes (#8502) Co-authored-by: Dima Kryukov --- rest_framework/fields.py | 3 +++ tests/test_fields.py | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 8d02b3206..31e5b994c 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -62,6 +62,9 @@ def is_simple_callable(obj): """ True if the object is a callable that takes no arguments. """ + if not callable(obj): + return False + # Bail early since we cannot inspect built-in function signatures. if inspect.isbuiltin(obj): raise BuiltinSignatureError( diff --git a/tests/test_fields.py b/tests/test_fields.py index ec121c822..19f734513 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -75,6 +75,10 @@ class TestIsSimpleCallable: assert is_simple_callable(valid_vargs_kwargs) assert not is_simple_callable(invalid) + @pytest.mark.parametrize('obj', (True, None, "str", b'bytes', 123, 1.23)) + def test_not_callable(self, obj): + assert not is_simple_callable(obj) + def test_4602_regression(self): from django.db import models From bb7dcef19bceae1dd43c19d5a9d9dddc75868c83 Mon Sep 17 00:00:00 2001 From: Daniel Gilge <33256939+dgilge@users.noreply.github.com> Date: Mon, 6 Jun 2022 14:31:00 +0200 Subject: [PATCH 106/228] Update get_schema in docs (#7402) --- docs/api-guide/schemas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index b9de6745f..5bdf5ee54 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -165,7 +165,7 @@ In order to customize the top-level schema, subclass as an argument to the `generateschema` command or `get_schema_view()` helper function. -### get_schema(self, request) +### get_schema(self, request=None, public=False) Returns a dictionary that represents the OpenAPI schema: From 563a20a04098937db1e2c353b2ee6a3059e92ebf Mon Sep 17 00:00:00 2001 From: Alan Crosswell Date: Mon, 6 Jun 2022 08:44:02 -0400 Subject: [PATCH 107/228] make get_reference public (#7515) --- docs/api-guide/schemas.md | 5 +++++ rest_framework/schemas/openapi.py | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index 5bdf5ee54..004e2d3ce 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -313,6 +313,11 @@ Computes the component's name from the serializer. You may see warnings if your API has duplicate component names. If so you can override `get_component_name()` or pass the `component_name` `__init__()` kwarg (see below) to provide different names. +#### `get_reference()` + +Returns a reference to the serializer component. This may be useful if you override `get_schema()`. + + #### `map_serializer()` Maps serializers to their OpenAPI representations. diff --git a/rest_framework/schemas/openapi.py b/rest_framework/schemas/openapi.py index 5e9d59f8b..122846376 100644 --- a/rest_framework/schemas/openapi.py +++ b/rest_framework/schemas/openapi.py @@ -636,7 +636,7 @@ class AutoSchema(ViewInspector): """ return self.get_serializer(path, method) - def _get_reference(self, serializer): + def get_reference(self, serializer): return {'$ref': '#/components/schemas/{}'.format(self.get_component_name(serializer))} def get_request_body(self, path, method): @@ -650,7 +650,7 @@ class AutoSchema(ViewInspector): if not isinstance(serializer, serializers.Serializer): item_schema = {} else: - item_schema = self._get_reference(serializer) + item_schema = self.get_reference(serializer) return { 'content': { @@ -674,7 +674,7 @@ class AutoSchema(ViewInspector): if not isinstance(serializer, serializers.Serializer): item_schema = {} else: - item_schema = self._get_reference(serializer) + item_schema = self.get_reference(serializer) if is_list_view(path, method, self.view): response_schema = { @@ -808,3 +808,11 @@ class AutoSchema(ViewInspector): RemovedInDRF314Warning, stacklevel=2 ) return self.allows_filters(path, method) + + def _get_reference(self, serializer): + warnings.warn( + "Method `_get_reference()` has been renamed to `get_reference()`. " + "The old name will be removed in DRF v3.14.", + RemovedInDRF314Warning, stacklevel=2 + ) + return self.get_reference(serializer) From 1396f6886a39acb7fe52729c7b99fe2d7d245dac Mon Sep 17 00:00:00 2001 From: Grigory Date: Mon, 6 Jun 2022 15:53:42 +0300 Subject: [PATCH 108/228] Respect model error_messages for relation (#7599) --- rest_framework/utils/field_mapping.py | 22 ++++++++++++++-------- tests/test_validators.py | 13 +++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py index 4f8a4f192..673821b5e 100644 --- a/rest_framework/utils/field_mapping.py +++ b/rest_framework/utils/field_mapping.py @@ -217,15 +217,9 @@ def get_field_kwargs(field_name, model_field): ] if getattr(model_field, 'unique', False): - unique_error_message = model_field.error_messages.get('unique', None) - if unique_error_message: - unique_error_message = unique_error_message % { - 'model_name': model_field.model._meta.verbose_name, - 'field_label': model_field.verbose_name - } validator = UniqueValidator( queryset=model_field.model._default_manager, - message=unique_error_message) + message=get_unique_error_message(model_field)) validator_kwarg.append(validator) if validator_kwarg: @@ -281,7 +275,9 @@ def get_relation_kwargs(field_name, relation_info): if model_field.validators: kwargs['validators'] = model_field.validators if getattr(model_field, 'unique', False): - validator = UniqueValidator(queryset=model_field.model._default_manager) + validator = UniqueValidator( + queryset=model_field.model._default_manager, + message=get_unique_error_message(model_field)) kwargs['validators'] = kwargs.get('validators', []) + [validator] if to_many and not model_field.blank: kwargs['allow_empty'] = False @@ -300,3 +296,13 @@ def get_url_kwargs(model_field): return { 'view_name': get_detail_view_name(model_field) } + + +def get_unique_error_message(model_field): + unique_error_message = model_field.error_messages.get('unique', None) + if unique_error_message: + unique_error_message = unique_error_message % { + 'model_name': model_field.model._meta.verbose_name, + 'field_label': model_field.verbose_name + } + return unique_error_message diff --git a/tests/test_validators.py b/tests/test_validators.py index bccbe1514..39490ac86 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -42,6 +42,12 @@ class RelatedModelSerializer(serializers.ModelSerializer): fields = ('username', 'email') +class RelatedModelUserSerializer(serializers.ModelSerializer): + class Meta: + model = RelatedModel + fields = ('user',) + + class AnotherUniquenessModel(models.Model): code = models.IntegerField(unique=True) @@ -83,6 +89,13 @@ class TestUniquenessValidation(TestCase): assert not serializer.is_valid() assert serializer.errors == {'username': ['uniqueness model with this username already exists.']} + def test_relation_is_not_unique(self): + RelatedModel.objects.create(user=self.instance) + data = {'user': self.instance.pk} + serializer = RelatedModelUserSerializer(data=data) + assert not serializer.is_valid() + assert serializer.errors == {'user': ['related model with this user already exists.']} + def test_is_unique(self): data = {'username': 'other'} serializer = UniquenessSerializer(data=data) From f8a03b096be27b4caac25dc119ccda81ad678d4f Mon Sep 17 00:00:00 2001 From: Patrick Daley Date: Tue, 7 Jun 2022 23:35:01 +1200 Subject: [PATCH 109/228] Remove pluralisation from basenames (#8517) HyperlinkIdentityFields in serializers reference 'snippet-highlight' and 'snippet-detail', router basenames updated to match. --- docs/tutorial/6-viewsets-and-routers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/6-viewsets-and-routers.md b/docs/tutorial/6-viewsets-and-routers.md index 18066f056..e12becbd0 100644 --- a/docs/tutorial/6-viewsets-and-routers.md +++ b/docs/tutorial/6-viewsets-and-routers.md @@ -112,8 +112,8 @@ Here's our re-wired `snippets/urls.py` file. # Create a router and register our viewsets with it. router = DefaultRouter() - router.register(r'snippets', views.SnippetViewSet,basename="snippets") - router.register(r'users', views.UserViewSet,basename="users") + router.register(r'snippets', views.SnippetViewSet,basename="snippet") + router.register(r'users', views.UserViewSet,basename="user") # The API URLs are now determined automatically by the router. urlpatterns = [ From e7af8d662bf837e4fee844b28606cda63c0d30a9 Mon Sep 17 00:00:00 2001 From: itsdkey Date: Wed, 8 Jun 2022 14:41:26 +0200 Subject: [PATCH 110/228] tests for #5127 (#7715) * tests for #5127 * Resolves #5127 --- tests/browsable_api/no_auth_urls.py | 3 ++- tests/browsable_api/serializers.py | 8 +++++++ tests/browsable_api/test_browsable_api.py | 27 +++++++++++++++++++++++ tests/browsable_api/views.py | 22 ++++++++++++++++++ tests/models.py | 5 +++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/browsable_api/serializers.py diff --git a/tests/browsable_api/no_auth_urls.py b/tests/browsable_api/no_auth_urls.py index 65701c065..33491ad92 100644 --- a/tests/browsable_api/no_auth_urls.py +++ b/tests/browsable_api/no_auth_urls.py @@ -1,7 +1,8 @@ from django.urls import path -from .views import MockView +from .views import BasicModelWithUsersViewSet, MockView urlpatterns = [ path('', MockView.as_view()), + path('basicviewset', BasicModelWithUsersViewSet.as_view({'get': 'list'})), ] diff --git a/tests/browsable_api/serializers.py b/tests/browsable_api/serializers.py new file mode 100644 index 000000000..e8a1cdef8 --- /dev/null +++ b/tests/browsable_api/serializers.py @@ -0,0 +1,8 @@ +from rest_framework.serializers import ModelSerializer +from tests.models import BasicModelWithUsers + + +class BasicSerializer(ModelSerializer): + class Meta: + model = BasicModelWithUsers + fields = '__all__' diff --git a/tests/browsable_api/test_browsable_api.py b/tests/browsable_api/test_browsable_api.py index 17644c2ac..a76d11fe3 100644 --- a/tests/browsable_api/test_browsable_api.py +++ b/tests/browsable_api/test_browsable_api.py @@ -1,8 +1,35 @@ from django.contrib.auth.models import User from django.test import TestCase, override_settings +from rest_framework.permissions import IsAuthenticated from rest_framework.test import APIClient +from .views import BasicModelWithUsersViewSet, OrganizationPermissions + + +@override_settings(ROOT_URLCONF='tests.browsable_api.no_auth_urls') +class AnonymousUserTests(TestCase): + """Tests correct handling of anonymous user request on endpoints with IsAuthenticated permission class.""" + + def setUp(self): + self.client = APIClient(enforce_csrf_checks=True) + + def tearDown(self): + self.client.logout() + + def test_get_raises_typeerror_when_anonymous_user_in_queryset_filter(self): + with self.assertRaises(TypeError): + self.client.get('/basicviewset') + + def test_get_returns_http_forbidden_when_anonymous_user(self): + old_permissions = BasicModelWithUsersViewSet.permission_classes + BasicModelWithUsersViewSet.permission_classes = [IsAuthenticated, OrganizationPermissions] + + response = self.client.get('/basicviewset') + + BasicModelWithUsersViewSet.permission_classes = old_permissions + self.assertEqual(response.status_code, 403) + @override_settings(ROOT_URLCONF='tests.browsable_api.auth_urls') class DropdownWithAuthTests(TestCase): diff --git a/tests/browsable_api/views.py b/tests/browsable_api/views.py index e1cf13a1e..e73967bf8 100644 --- a/tests/browsable_api/views.py +++ b/tests/browsable_api/views.py @@ -1,6 +1,16 @@ from rest_framework import authentication, renderers +from rest_framework.permissions import BasePermission from rest_framework.response import Response from rest_framework.views import APIView +from rest_framework.viewsets import ModelViewSet + +from ..models import BasicModelWithUsers +from .serializers import BasicSerializer + + +class OrganizationPermissions(BasePermission): + def has_object_permission(self, request, view, obj): + return request.user.is_staff or (request.user == obj.owner.organization_user.user) class MockView(APIView): @@ -9,3 +19,15 @@ class MockView(APIView): def get(self, request): return Response({'a': 1, 'b': 2, 'c': 3}) + + +class BasicModelWithUsersViewSet(ModelViewSet): + queryset = BasicModelWithUsers.objects.all() + serializer_class = BasicSerializer + permission_classes = [OrganizationPermissions] + # permission_classes = [IsAuthenticated, OrganizationPermissions] + renderer_classes = (renderers.BrowsableAPIRenderer, renderers.JSONRenderer) + + def get_queryset(self): + qs = super().get_queryset().filter(users=self.request.user) + return qs diff --git a/tests/models.py b/tests/models.py index afe649760..666e9f003 100644 --- a/tests/models.py +++ b/tests/models.py @@ -1,5 +1,6 @@ import uuid +from django.contrib.auth.models import User from django.db import models from django.utils.translation import gettext_lazy as _ @@ -33,6 +34,10 @@ class ManyToManySource(RESTFrameworkModel): targets = models.ManyToManyField(ManyToManyTarget, related_name='sources') +class BasicModelWithUsers(RESTFrameworkModel): + users = models.ManyToManyField(User) + + # ForeignKey class ForeignKeyTarget(RESTFrameworkModel): name = models.CharField(max_length=100) From 26830c3d2d45a60385d1166c37a031e2e75cf858 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Wed, 8 Jun 2022 16:37:46 +0300 Subject: [PATCH 111/228] Fix QueryDict type error in test (#8475) QueryDict takes a `str` argument. Discovered while working on djangorestframework-stubs. --- tests/test_fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_fields.py b/tests/test_fields.py index 19f734513..cbec79119 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1865,9 +1865,9 @@ class TestMultipleChoiceField(FieldValues): def test_against_partial_and_full_updates(self): field = serializers.MultipleChoiceField(choices=(('a', 'a'), ('b', 'b'))) field.partial = False - assert field.get_value(QueryDict({})) == [] + assert field.get_value(QueryDict('')) == [] field.partial = True - assert field.get_value(QueryDict({})) == rest_framework.fields.empty + assert field.get_value(QueryDict('')) == rest_framework.fields.empty class TestEmptyMultipleChoiceField(FieldValues): From 5185cc934862a5ab13316c85402c12a6d744f94c Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 8 Jun 2022 15:46:19 +0200 Subject: [PATCH 112/228] Handle unset fields with 'many=True' (#7574) * Handle unset fields with 'many=True' The docs note: When serializing fields with dotted notation, it may be necessary to provide a `default` value if any object is not present or is empty during attribute traversal. However, this doesn't work for fields with 'many=True'. When using these, the default is simply ignored. The solution is simple: do in 'ManyRelatedField' what we were already doing for 'Field', namely, catch possible 'AttributeError' and 'KeyError' exceptions and return the default if there is one set. Signed-off-by: Stephen Finucane Closes: #7550 * Add test cases for #7550 Signed-off-by: Stephen Finucane --- rest_framework/relations.py | 27 +++++++++++++- tests/test_model_serializer.py | 67 ++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index c98700784..bdedd43b8 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -10,7 +10,7 @@ from django.utils.encoding import smart_str, uri_to_iri from django.utils.translation import gettext_lazy as _ from rest_framework.fields import ( - Field, empty, get_attribute, is_simple_callable, iter_options + Field, SkipField, empty, get_attribute, is_simple_callable, iter_options ) from rest_framework.reverse import reverse from rest_framework.settings import api_settings @@ -535,7 +535,30 @@ class ManyRelatedField(Field): if hasattr(instance, 'pk') and instance.pk is None: return [] - relationship = get_attribute(instance, self.source_attrs) + try: + relationship = get_attribute(instance, self.source_attrs) + except (KeyError, AttributeError) as exc: + if self.default is not empty: + return self.get_default() + if self.allow_null: + return None + if not self.required: + raise SkipField() + msg = ( + 'Got {exc_type} when attempting to get a value for field ' + '`{field}` on serializer `{serializer}`.\nThe serializer ' + 'field might be named incorrectly and not match ' + 'any attribute or key on the `{instance}` instance.\n' + 'Original exception text was: {exc}.'.format( + exc_type=type(exc).__name__, + field=self.field_name, + serializer=self.parent.__class__.__name__, + instance=instance.__class__.__name__, + exc=exc + ) + ) + raise type(exc)(msg) + return relationship.all() if hasattr(relationship, 'all') else relationship def to_representation(self, iterable): diff --git a/tests/test_model_serializer.py b/tests/test_model_serializer.py index abb4830d1..419eae632 100644 --- a/tests/test_model_serializer.py +++ b/tests/test_model_serializer.py @@ -1025,6 +1025,73 @@ class Issue2704TestCase(TestCase): assert serializer.data == expected +class Issue7550FooModel(models.Model): + text = models.CharField(max_length=100) + bar = models.ForeignKey( + 'Issue7550BarModel', null=True, blank=True, on_delete=models.SET_NULL, + related_name='foos', related_query_name='foo') + + +class Issue7550BarModel(models.Model): + pass + + +class Issue7550TestCase(TestCase): + + def test_dotted_source(self): + + class _FooSerializer(serializers.ModelSerializer): + class Meta: + model = Issue7550FooModel + fields = ('id', 'text') + + class FooSerializer(serializers.ModelSerializer): + other_foos = _FooSerializer(source='bar.foos', many=True) + + class Meta: + model = Issue7550BarModel + fields = ('id', 'other_foos') + + bar = Issue7550BarModel.objects.create() + foo_a = Issue7550FooModel.objects.create(bar=bar, text='abc') + foo_b = Issue7550FooModel.objects.create(bar=bar, text='123') + + assert FooSerializer(foo_a).data == { + 'id': foo_a.id, + 'other_foos': [ + { + 'id': foo_a.id, + 'text': foo_a.text, + }, + { + 'id': foo_b.id, + 'text': foo_b.text, + }, + ], + } + + def test_dotted_source_with_default(self): + + class _FooSerializer(serializers.ModelSerializer): + class Meta: + model = Issue7550FooModel + fields = ('id', 'text') + + class FooSerializer(serializers.ModelSerializer): + other_foos = _FooSerializer(source='bar.foos', default=[], many=True) + + class Meta: + model = Issue7550FooModel + fields = ('id', 'other_foos') + + foo = Issue7550FooModel.objects.create(bar=None, text='abc') + + assert FooSerializer(foo).data == { + 'id': foo.id, + 'other_foos': [], + } + + class DecimalFieldModel(models.Model): decimal_field = models.DecimalField( max_digits=3, From 82475c232b531e075fe7666d808f9e68d052d35b Mon Sep 17 00:00:00 2001 From: Alessandro <9991341+alessandrosp@users.noreply.github.com> Date: Wed, 8 Jun 2022 23:03:00 +0900 Subject: [PATCH 113/228] Made relative URLs clickable as well. (#8464) --- rest_framework/templatetags/rest_framework.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py index db0e9c95c..ccd9430b4 100644 --- a/rest_framework/templatetags/rest_framework.py +++ b/rest_framework/templatetags/rest_framework.py @@ -218,7 +218,7 @@ def format_value(value): return template.render(context) elif isinstance(value, str): if ( - (value.startswith('http:') or value.startswith('https:')) and not + (value.startswith('http:') or value.startswith('https:') or value.startswith('/')) and not re.search(r'\s', value) ): return mark_safe('{value}'.format(value=escape(value))) From 2506d0b4f2ac8bdbf35d33b3dd8a56f3e8d0da75 Mon Sep 17 00:00:00 2001 From: Burak Kadir Er Date: Thu, 9 Jun 2022 17:30:47 +0300 Subject: [PATCH 114/228] Update include and namespace URLs (#8520) --- docs/api-guide/routers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index 8d8594eee..70c05fdde 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -338,5 +338,5 @@ The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions [drf-extensions-nested-viewsets]: https://chibisov.github.io/drf-extensions/docs/#nested-routes [drf-extensions-collection-level-controllers]: https://chibisov.github.io/drf-extensions/docs/#collection-level-controllers [drf-extensions-customizable-endpoint-names]: https://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name -[url-namespace-docs]: https://docs.djangoproject.com/en/1.11/topics/http/urls/#url-namespaces -[include-api-reference]: https://docs.djangoproject.com/en/2.0/ref/urls/#include +[url-namespace-docs]: https://docs.djangoproject.com/en/4.0/topics/http/urls/#url-namespaces +[include-api-reference]: https://docs.djangoproject.com/en/4.0/ref/urls/#include From fa9d516ee24b2447a351af92e139d386b4f0d2b4 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 20 Jun 2022 10:44:27 +0100 Subject: [PATCH 115/228] Update docstring test for more recent pygments version (#8530) * Update docstring test for more recent pygments version * Drop unused import --- requirements/requirements-optionals.txt | 5 ++-- tests/test_description.py | 31 ++++--------------------- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/requirements/requirements-optionals.txt b/requirements/requirements-optionals.txt index 75b9ab4d6..f3bb9b709 100644 --- a/requirements/requirements-optionals.txt +++ b/requirements/requirements-optionals.txt @@ -3,8 +3,7 @@ coreapi==2.3.1 coreschema==0.0.4 django-filter>=2.4.0,<3.0 django-guardian>=2.4.0,<2.5 -markdown==3.3;python_version>="3.6" -markdown==3.2.2;python_version=="3.5" +markdown==3.3 psycopg2-binary>=2.8.5,<2.9 -pygments>=2.7.1,<2.8 +pygments==2.12 pyyaml>=5.3.1,<5.4 diff --git a/tests/test_description.py b/tests/test_description.py index 363ad6513..ecc6b9776 100644 --- a/tests/test_description.py +++ b/tests/test_description.py @@ -1,5 +1,3 @@ -import sys - import pytest from django.test import TestCase @@ -33,7 +31,7 @@ indented # If markdown is installed we also test it's working # (and that our wrapped forces '=' to h2 and '-' to h3) -MARKDOWN_BASE = """

    an example docstring

    +MARKDOWN_DOCSTRING = """

    an example docstring