Skip to content

Commit ef99f6d

Browse files
committed
Merge branch 'pr1491'
2 parents 9b83e5a + 2ec16a1 commit ef99f6d

4 files changed

Lines changed: 97 additions & 0 deletions

File tree

drf_spectacular/plumbing.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ def get_view_model(view, emit_warnings=True):
232232

233233
def get_doc(obj) -> str:
234234
""" get doc string with fallback on obj's base classes (ignoring DRF documentation). """
235+
if spectacular_settings.DISABLE_DOCSTRING_DESCRIPTIONS:
236+
return ''
237+
235238
def post_cleanup(doc: str) -> str:
236239
# also clean up trailing whitespace for each line
237240
return '\n'.join(line.rstrip() for line in doc.rstrip().split('\n'))

drf_spectacular/settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@
126126

127127
# function that returns a list of all classes that should be excluded from doc string extraction
128128
'GET_LIB_DOC_EXCLUDES': 'drf_spectacular.plumbing.get_lib_doc_excludes',
129+
# Stops docstrings of views, serializers and their methods, from being used as
130+
# description strings in the schema. Useful when docstrings are for internal use
131+
# only and should not be exposed in the API documentation.
132+
'DISABLE_DOCSTRING_DESCRIPTIONS': False,
129133

130134
# Function that returns a mocked request for view processing. For CLI usage
131135
# original_request will be None.

tests/test_plumbing.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import typing
66
from datetime import datetime
77
from enum import Enum
8+
from unittest import mock
89

910
if sys.version_info >= (3, 8):
1011
from typing import TypedDict
@@ -467,3 +468,52 @@ class MyClass(typing.Generic[T]):
467468

468469
doc = get_doc(MyClass)
469470
assert doc == ""
471+
472+
473+
@pytest.mark.parametrize('disable', [False, True])
474+
def test_get_doc_with_class_docstring(disable):
475+
class MyClass:
476+
"""a docstring"""
477+
478+
with mock.patch(
479+
"drf_spectacular.settings.spectacular_settings.DISABLE_DOCSTRING_DESCRIPTIONS",
480+
disable,
481+
):
482+
doc = get_doc(MyClass)
483+
if disable:
484+
assert doc == ""
485+
else:
486+
assert doc == "a docstring"
487+
488+
489+
@pytest.mark.parametrize('disable', [False, True])
490+
def test_get_doc_with_function_docstring(disable):
491+
def my_func():
492+
"""a docstring"""
493+
494+
with mock.patch(
495+
"drf_spectacular.settings.spectacular_settings.DISABLE_DOCSTRING_DESCRIPTIONS",
496+
disable,
497+
):
498+
doc = get_doc(my_func)
499+
if disable:
500+
assert doc == ""
501+
else:
502+
assert doc == "a docstring"
503+
504+
505+
@pytest.mark.parametrize('disable', [False, True])
506+
def test_get_doc_with_method_docstring(disable):
507+
class MyClass:
508+
def my_method(self):
509+
"""a docstring"""
510+
511+
with mock.patch(
512+
"drf_spectacular.settings.spectacular_settings.DISABLE_DOCSTRING_DESCRIPTIONS",
513+
disable,
514+
):
515+
doc = get_doc(MyClass().my_method)
516+
if disable:
517+
assert doc == ""
518+
else:
519+
assert doc == "a docstring"

tests/test_regressions.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,6 +2574,46 @@ def create(self, request):
25742574
)
25752575

25762576

2577+
@pytest.mark.parametrize('disable', [False, True])
2578+
def test_disable_docstring_descriptions(no_warnings, disable):
2579+
class XSerializer(serializers.Serializer):
2580+
"""serializer docstring"""
2581+
field = serializers.CharField()
2582+
field_method = serializers.SerializerMethodField()
2583+
2584+
def get_field_method(self) -> str:
2585+
"""method field docstring"""
2586+
return '' # pragma: no cover
2587+
2588+
class XViewset(viewsets.ModelViewSet):
2589+
"""view class docstring"""
2590+
serializer_class = XSerializer
2591+
queryset = SimpleModel.objects.none()
2592+
2593+
def retrieve(self, request):
2594+
"""action docstring"""
2595+
pass # pragma: no cover
2596+
2597+
with mock.patch(
2598+
'drf_spectacular.settings.spectacular_settings.DISABLE_DOCSTRING_DESCRIPTIONS', disable
2599+
):
2600+
schema = generate_schema('/x', XViewset)
2601+
2602+
if disable:
2603+
assert 'description' not in schema['paths']['/x/']['get']
2604+
assert 'description' not in schema['paths']['/x/{id}/']['get']
2605+
assert 'description' not in schema['components']['schemas']['X']
2606+
assert 'description' not in schema['components']['schemas']['X']['properties']['field_method']
2607+
else:
2608+
assert schema['paths']['/x/']['get']['description'] == 'view class docstring'
2609+
assert schema['paths']['/x/{id}/']['get']['description'] == 'action docstring'
2610+
assert schema['components']['schemas']['X']['description'] == 'serializer docstring'
2611+
assert (
2612+
schema['components']['schemas']['X']['properties']['field_method']['description']
2613+
== 'method field docstring'
2614+
)
2615+
2616+
25772617
@pytest.mark.parametrize('list_variation', [
25782618
serializers.ListField, serializers.ListSerializer
25792619
])

0 commit comments

Comments
 (0)