From 8e3844c246a2df37ff8cdadb8d5449c08b64ddef Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 16:00:47 +0200 Subject: [PATCH 01/11] Add tests for schema exclusions --- tests/test_schemas.py | 79 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index f8a63aa897..f67dfda4f8 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -8,12 +8,13 @@ from rest_framework import filters, pagination, permissions, serializers from rest_framework.compat import coreapi, coreschema -from rest_framework.decorators import detail_route, list_route +from rest_framework.decorators import detail_route, list_route, api_view, schema from rest_framework.request import Request from rest_framework.routers import DefaultRouter from rest_framework.schemas import ( AutoSchema, ManualSchema, SchemaGenerator, get_schema_view ) +from rest_framework.schemas.generators import EndpointEnumerator from rest_framework.test import APIClient, APIRequestFactory from rest_framework.utils import formatting from rest_framework.views import APIView @@ -613,3 +614,79 @@ def post(self, request, *args, **kwargs): descr = schema.get_description('example', 'get') # the first and last character are '\n' correctly removed by get_description assert descr == formatting.dedent(ExampleDocstringAPIView.__doc__[1:][:-1]) + + +# Views for SchemaGenerationExclusionTests +class ExcludedAPIView(APIView): + exclude_from_schema = True + + def get(self, request, *args, **kwargs): + pass + + +@api_view(['GET'], exclude_from_schema=True) +def excluded_fbv(request): + pass + + +@api_view(['GET']) +def included_fbv(request): + pass + + +@unittest.skipUnless(coreapi, 'coreapi is not installed') +class SchemaGenerationExclusionTests(TestCase): + def setUp(self): + self.patterns = [ + url('^excluded-cbv/?$', ExcludedAPIView.as_view()), + url('^excluded-fbv/?$', excluded_fbv), + url('^included-fbv/?$', included_fbv), + ] + + def test_schema_generator_excludes_correctly(self): + """Schema should not include excluded views""" + generator = SchemaGenerator(title='Exclusions', patterns=self.patterns) + schema = generator.get_schema() + expected = coreapi.Document( + url='', + title='Exclusions', + content={ + 'included-fbv': { + 'list': coreapi.Link(url='/included-fbv/', action='get') + } + } + ) + + assert len(schema.data) == 1 + assert 'included-fbv' in schema.data + assert schema == expected + + def test_endpoint_enumerator_excludes_correctly(self): + """It is responsibility of EndpointEnumerator to exclude views""" + inspector = EndpointEnumerator(self.patterns) + endpoints = inspector.get_api_endpoints() + + assert len(endpoints) == 1 + path, method, callback = endpoints[0] + assert path == '/included-fbv/' + + + def test_should_include_endpoint_excludes_correctly(self): + """This is the specific method that should handle the exclusion""" + inspector = EndpointEnumerator(self.patterns) + + pairs = [ + (inspector.get_path_from_regex(pattern.regex.pattern), pattern.callback) + for pattern in self.patterns + ] + + should_include = [ + inspector.should_include_endpoint(*pair) for pair in pairs + ] + + expected = [False, False, True] + + assert should_include == expected + + def test_deprecations(self): + pass \ No newline at end of file From 6b8bbe8e1f0b28492c2e92f13e58cc3459292616 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 16:01:32 +0200 Subject: [PATCH 02/11] Move exclusion check to should_include_endpoint --- rest_framework/schemas/generators.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 8344f64f0e..cc1ffb31b1 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -148,6 +148,9 @@ def should_include_endpoint(self, path, callback): if not is_api_view(callback): return False # Ignore anything except REST framework views. + if getattr(callback.cls, 'exclude_from_schema', False): + return False + if path.endswith('.{format}') or path.endswith('.{format}/'): return False # Ignore .json style URLs. @@ -239,8 +242,6 @@ def get_links(self, request=None): view_endpoints = [] for path, method, callback in self.endpoints: view = self.create_view(callback, method, request) - if getattr(view, 'exclude_from_schema', False): - continue path = self.coerce_path(path, method, view) paths.append(path) view_endpoints.append((path, method, view)) From f346118a8eafbecb8f9b5576b53283f3ef05d0b4 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 16:09:18 +0200 Subject: [PATCH 03/11] Update docs --- docs/api-guide/schemas.md | 6 ++++++ docs/api-guide/views.md | 17 +++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index f913f046f6..fc848199ca 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -225,6 +225,12 @@ To customise the `Link` generation you may: This allows manually specifying the schema for some views whilst maintaining automatic generation elsewhere. +You may disable schema generation for a view by setting `schema` to `None`: + + class CustomView(APIView): + ... + schema = None # Will not appear in schema + --- **Note**: For full details on `SchemaGenerator` plus the `AutoSchema` and diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index 24dd42578e..2f9f51cf92 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -130,7 +130,7 @@ REST framework also allows you to work with regular function based views. It pr ## @api_view() -**Signature:** `@api_view(http_method_names=['GET'], exclude_from_schema=False)` +**Signature:** `@api_view(http_method_names=['GET'])` 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: @@ -150,12 +150,6 @@ By default only `GET` methods will be accepted. Other methods will respond with return Response({"message": "Got some data!", "data": request.data}) return Response({"message": "Hello, world!"}) -You can also mark an API view as being omitted from any [auto-generated schema][schemas], -using the `exclude_from_schema` argument.: - - @api_view(['GET'], exclude_from_schema=True) - def api_docs(request): - ... ## API policy decorators @@ -204,7 +198,14 @@ decorator. For example: return Response({"message": "Hello for today! See you tomorrow!"}) This decorator takes a single `AutoSchema` instance, an `AutoSchema` subclass -instance or `ManualSchema` instance as described in the [Schemas documentation][schemas], +instance or `ManualSchema` instance as described in the [Schemas documentation][schemas]. +You may pass `None` in order to exclude the view from schema generation. + + @api_view(['GET']) + @schema(None) + def view(request): + return Response({"message": "Will not appear in schema!"}) + [cite]: http://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html [cite2]: http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html From 9d84e0c290e4a2fc8c2756029b8586491369a4e9 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 16:23:27 +0200 Subject: [PATCH 04/11] Switch to using `schema = None` --- rest_framework/decorators.py | 7 ++++++- rest_framework/routers.py | 2 +- rest_framework/schemas/generators.py | 7 ++++++- rest_framework/schemas/views.py | 2 +- rest_framework/views.py | 2 -- tests/test_schemas.py | 19 ++++++++++--------- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 1297f96b4c..f5a0c35794 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -75,7 +75,12 @@ def handler(self, *args, **kwargs): WrappedAPIView.schema = getattr(func, 'schema', APIView.schema) - WrappedAPIView.exclude_from_schema = exclude_from_schema + if exclude_from_schema: + # This won't catch an explicit `exclude_from_schema=False` + # but it should be good enough. + # TODO: DeprecationWarning + WrappedAPIView.exclude_from_schema = exclude_from_schema + return WrappedAPIView.as_view() return decorator diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 01daa7e7d4..3b5ef46d83 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -291,7 +291,7 @@ class APIRootView(views.APIView): The default basic root view for DefaultRouter """ _ignore_model_permissions = True - exclude_from_schema = True + schema = None # exclude from schema api_root_dict = None def get(self, request, *args, **kwargs): diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index cc1ffb31b1..21726ef263 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -148,7 +148,12 @@ def should_include_endpoint(self, path, callback): if not is_api_view(callback): return False # Ignore anything except REST framework views. - if getattr(callback.cls, 'exclude_from_schema', False): + if hasattr(callback.cls, 'exclude_from_schema'): + # TODO: deprecation warning + if getattr(callback.cls, 'exclude_from_schema', False): + return False + + if callback.cls.schema is None: return False if path.endswith('.{format}') or path.endswith('.{format}/'): diff --git a/rest_framework/schemas/views.py b/rest_framework/schemas/views.py index 932b5a4871..b13eadea9c 100644 --- a/rest_framework/schemas/views.py +++ b/rest_framework/schemas/views.py @@ -11,7 +11,7 @@ class SchemaView(APIView): _ignore_model_permissions = True - exclude_from_schema = True + schema = None # exclude from schema renderer_classes = None schema_generator = None public = False diff --git a/rest_framework/views.py b/rest_framework/views.py index ccc2047eec..dfed158887 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -112,8 +112,6 @@ class APIView(View): # Allow dependency injection of other settings to make testing easier. settings = api_settings - # Mark the view as being included or excluded from schema generation. - exclude_from_schema = False schema = AutoSchema() @classmethod diff --git a/tests/test_schemas.py b/tests/test_schemas.py index f67dfda4f8..1ecd31314c 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -8,7 +8,9 @@ from rest_framework import filters, pagination, permissions, serializers from rest_framework.compat import coreapi, coreschema -from rest_framework.decorators import detail_route, list_route, api_view, schema +from rest_framework.decorators import ( + api_view, detail_route, list_route, schema +) from rest_framework.request import Request from rest_framework.routers import DefaultRouter from rest_framework.schemas import ( @@ -618,13 +620,14 @@ def post(self, request, *args, **kwargs): # Views for SchemaGenerationExclusionTests class ExcludedAPIView(APIView): - exclude_from_schema = True + schema = None def get(self, request, *args, **kwargs): pass -@api_view(['GET'], exclude_from_schema=True) +@api_view(['GET']) +@schema(None) def excluded_fbv(request): pass @@ -670,15 +673,13 @@ def test_endpoint_enumerator_excludes_correctly(self): path, method, callback = endpoints[0] assert path == '/included-fbv/' - def test_should_include_endpoint_excludes_correctly(self): """This is the specific method that should handle the exclusion""" inspector = EndpointEnumerator(self.patterns) - pairs = [ - (inspector.get_path_from_regex(pattern.regex.pattern), pattern.callback) - for pattern in self.patterns - ] + # Not pretty. Mimics internals of EndpointEnumerator to put should_include_endpoint under test + pairs = [(inspector.get_path_from_regex(pattern.regex.pattern), pattern.callback) + for pattern in self.patterns] should_include = [ inspector.should_include_endpoint(*pair) for pair in pairs @@ -689,4 +690,4 @@ def test_should_include_endpoint_excludes_correctly(self): assert should_include == expected def test_deprecations(self): - pass \ No newline at end of file + pass From 1c2c4f43aec75b368fd8d1b736525d5d8bd929ab Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 16:50:15 +0200 Subject: [PATCH 05/11] Test PendingDeprecationWarnings --- rest_framework/decorators.py | 9 ++++++--- rest_framework/schemas/generators.py | 6 +++++- tests/test_schemas.py | 25 +++++++++++++++++++++---- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index f5a0c35794..7c9efc4d1b 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -9,6 +9,7 @@ from __future__ import unicode_literals import types +import warnings from django.utils import six @@ -76,9 +77,11 @@ def handler(self, *args, **kwargs): APIView.schema) if exclude_from_schema: - # This won't catch an explicit `exclude_from_schema=False` - # but it should be good enough. - # TODO: DeprecationWarning + warnings.warn( + "The `exclude_from_schema` argument to `api_view` is deprecated. " + "Use the `schema` decorator instead, passing `None`.", + PendingDeprecationWarning + ) WrappedAPIView.exclude_from_schema = exclude_from_schema return WrappedAPIView.as_view() diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 21726ef263..f24fdaafd3 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -3,6 +3,7 @@ See schemas.__init__.py for package overview. """ +import warnings from collections import OrderedDict from importlib import import_module @@ -149,7 +150,10 @@ def should_include_endpoint(self, path, callback): return False # Ignore anything except REST framework views. if hasattr(callback.cls, 'exclude_from_schema'): - # TODO: deprecation warning + fmt = ("{}. The `APIView.exclude_from_schema` is deprecated. " + "Set `schema = None` instead") + msg = fmt.format(callback.cls.__name__) + warnings.warn(msg, PendingDeprecationWarning) if getattr(callback.cls, 'exclude_from_schema', False): return False diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 1ecd31314c..90916fdf57 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -641,9 +641,9 @@ def included_fbv(request): class SchemaGenerationExclusionTests(TestCase): def setUp(self): self.patterns = [ - url('^excluded-cbv/?$', ExcludedAPIView.as_view()), - url('^excluded-fbv/?$', excluded_fbv), - url('^included-fbv/?$', included_fbv), + url('^excluded-cbv/$', ExcludedAPIView.as_view()), + url('^excluded-fbv/$', excluded_fbv), + url('^included-fbv/$', included_fbv), ] def test_schema_generator_excludes_correctly(self): @@ -690,4 +690,21 @@ def test_should_include_endpoint_excludes_correctly(self): assert should_include == expected def test_deprecations(self): - pass + with pytest.warns(PendingDeprecationWarning): + @api_view(["GET"], exclude_from_schema=True) + def view(request): + pass + + class OldFashjonedExcludedView(APIView): + exclude_from_schema = True + + def get(self, request, *args, **kwargs): + pass + + patterns = [ + url('^excluded-old-fashioned/$', OldFashjonedExcludedView.as_view()), + ] + + inspector = EndpointEnumerator(patterns) + with pytest.warns(PendingDeprecationWarning): + inspector.get_api_endpoints() From a966b8417e63f380dba8e466c74eee7273433d87 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 16:52:35 +0200 Subject: [PATCH 06/11] Add note to release notes. --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index f4617ac230..ef1e612aa6 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -43,6 +43,7 @@ You can determine your currently installed version using `pip freeze`: ### 3.6.5 * Fix `DjangoModelPermissions` to ensure user authentication before calling the view's `get_queryset()` method. As a side effect, this changes the order of the HTTP method permissions and authentication checks, and 405 responses will only be returned when authenticated. If you want to replicate the old behavior, see the PR for details. [#5376][gh5376] +* Deprecated `exclude_from_schema` on `APIView` and `api_view` decorator. Set `schema = None` or `@schema(None)` as appropriate. ### 3.6.4 From d4a49055dbe57edea46ac78232eb52f93663a5ef Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 16:59:59 +0200 Subject: [PATCH 07/11] s/deprecated/pending deprecation/ --- rest_framework/decorators.py | 2 +- rest_framework/schemas/generators.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 7c9efc4d1b..cdbd59e998 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -78,7 +78,7 @@ def handler(self, *args, **kwargs): if exclude_from_schema: warnings.warn( - "The `exclude_from_schema` argument to `api_view` is deprecated. " + "The `exclude_from_schema` argument to `api_view` is pending deprecation. " "Use the `schema` decorator instead, passing `None`.", PendingDeprecationWarning ) diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index f24fdaafd3..4d63ad5e98 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -150,7 +150,7 @@ def should_include_endpoint(self, path, callback): return False # Ignore anything except REST framework views. if hasattr(callback.cls, 'exclude_from_schema'): - fmt = ("{}. The `APIView.exclude_from_schema` is deprecated. " + fmt = ("{}. The `APIView.exclude_from_schema` is pending deprecation. " "Set `schema = None` instead") msg = fmt.format(callback.cls.__name__) warnings.warn(msg, PendingDeprecationWarning) From 6c377a3fe4cda8f77f22e39caec43fce36eecb36 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 17:01:40 +0200 Subject: [PATCH 08/11] Add PR link to release notes --- docs/topics/release-notes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index ef1e612aa6..b9fff2ce0c 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -43,7 +43,8 @@ You can determine your currently installed version using `pip freeze`: ### 3.6.5 * Fix `DjangoModelPermissions` to ensure user authentication before calling the view's `get_queryset()` method. As a side effect, this changes the order of the HTTP method permissions and authentication checks, and 405 responses will only be returned when authenticated. If you want to replicate the old behavior, see the PR for details. [#5376][gh5376] -* Deprecated `exclude_from_schema` on `APIView` and `api_view` decorator. Set `schema = None` or `@schema(None)` as appropriate. +* Deprecated `exclude_from_schema` on `APIView` and `api_view` decorator. Set `schema = None` or `@schema(None)` as appropriate. [#5422][gh5422] + ### 3.6.4 @@ -1424,3 +1425,4 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh5376]: https://github.com/encode/django-rest-framework/issues/5376 +[gh5422]: https://github.com/encode/django-rest-framework/issues/5422 From f349d35442cc2f841864cddf9f5b99ab6b19c54c Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Sep 2017 17:34:40 +0200 Subject: [PATCH 09/11] Correct typo in test class name --- tests/test_schemas.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 90916fdf57..0ee6131b64 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -695,14 +695,14 @@ def test_deprecations(self): def view(request): pass - class OldFashjonedExcludedView(APIView): + class OldFashionedExcludedView(APIView): exclude_from_schema = True def get(self, request, *args, **kwargs): pass patterns = [ - url('^excluded-old-fashioned/$', OldFashjonedExcludedView.as_view()), + url('^excluded-old-fashioned/$', OldFashionedExcludedView.as_view()), ] inspector = EndpointEnumerator(patterns) From 0cd24b455f5982e898735fda7e9e669c0610e8cd Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Fri, 15 Sep 2017 07:23:12 -0400 Subject: [PATCH 10/11] Test 'exclude_from_schema' deprecation warning message (#1) --- rest_framework/schemas/generators.py | 4 ++-- tests/test_schemas.py | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 4d63ad5e98..736d9d4192 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -150,8 +150,8 @@ def should_include_endpoint(self, path, callback): return False # Ignore anything except REST framework views. if hasattr(callback.cls, 'exclude_from_schema'): - fmt = ("{}. The `APIView.exclude_from_schema` is pending deprecation. " - "Set `schema = None` instead") + fmt = ("The `{}.exclude_from_schema` is pending deprecation. " + "Set `schema = None` instead.") msg = fmt.format(callback.cls.__name__) warnings.warn(msg, PendingDeprecationWarning) if getattr(callback.cls, 'exclude_from_schema', False): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 0ee6131b64..786db593bd 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -690,11 +690,17 @@ def test_should_include_endpoint_excludes_correctly(self): assert should_include == expected def test_deprecations(self): - with pytest.warns(PendingDeprecationWarning): + with pytest.warns(PendingDeprecationWarning) as record: @api_view(["GET"], exclude_from_schema=True) def view(request): pass + assert len(record) == 1 + assert str(record[0].message) == ( + "The `exclude_from_schema` argument to `api_view` is pending " + "deprecation. Use the `schema` decorator instead, passing `None`." + ) + class OldFashionedExcludedView(APIView): exclude_from_schema = True @@ -706,5 +712,11 @@ def get(self, request, *args, **kwargs): ] inspector = EndpointEnumerator(patterns) - with pytest.warns(PendingDeprecationWarning): + with pytest.warns(PendingDeprecationWarning) as record: inspector.get_api_endpoints() + + assert len(record) == 1 + assert str(record[0].message) == ( + "The `OldFashionedExcludedView.exclude_from_schema` is " + "pending deprecation. Set `schema = None` instead." + ) From 853dd233a2f2968d3316377f1fd5cb5b9b8edaea Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Fri, 15 Sep 2017 14:27:21 +0200 Subject: [PATCH 11/11] Correct deprecation warning message --- rest_framework/schemas/generators.py | 2 +- tests/test_schemas.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 736d9d4192..3e927527cb 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -150,7 +150,7 @@ def should_include_endpoint(self, path, callback): return False # Ignore anything except REST framework views. if hasattr(callback.cls, 'exclude_from_schema'): - fmt = ("The `{}.exclude_from_schema` is pending deprecation. " + fmt = ("The `{}.exclude_from_schema` attribute is pending deprecation. " "Set `schema = None` instead.") msg = fmt.format(callback.cls.__name__) warnings.warn(msg, PendingDeprecationWarning) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 786db593bd..184401a868 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -717,6 +717,6 @@ def get(self, request, *args, **kwargs): assert len(record) == 1 assert str(record[0].message) == ( - "The `OldFashionedExcludedView.exclude_from_schema` is " + "The `OldFashionedExcludedView.exclude_from_schema` attribute is " "pending deprecation. Set `schema = None` instead." )