Compare commits
No commits in common. "master" and "1.17.0" have entirely different histories.
|
|
@ -1,8 +1,10 @@
|
||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
|
- '2.7'
|
||||||
|
- '3.5'
|
||||||
- '3.6'
|
- '3.6'
|
||||||
- '3.7'
|
- '3.7'
|
||||||
- '3.8'
|
- '3.8-dev'
|
||||||
|
|
||||||
dist: xenial
|
dist: xenial
|
||||||
|
|
||||||
|
|
@ -37,6 +39,7 @@ matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- env: TOXENV=lint
|
- env: TOXENV=lint
|
||||||
- env: TOXENV=djmaster
|
- env: TOXENV=djmaster
|
||||||
|
- python: '3.8-dev'
|
||||||
|
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ You want to contribute some code? Great! Here are a few steps to get you started
|
||||||
|
|
||||||
.. code:: console
|
.. code:: console
|
||||||
|
|
||||||
(venv) $ python testproj/manage.py generate_swagger tests/reference.yaml --overwrite --user admin --url http://test.local:8002/
|
(venv) $ python testproj/manage.py generate_swagger ../tests/reference.yaml --overwrite --user admin --url http://test.local:8002/
|
||||||
|
|
||||||
After checking the git diff to verify that no unexpected changes appeared, you should commit the new
|
After checking the git diff to verify that no unexpected changes appeared, you should commit the new
|
||||||
``reference.yaml`` together with your changes.
|
``reference.yaml`` together with your changes.
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ Generate **real** Swagger/OpenAPI 2.0 specifications from a Django Rest Framewor
|
||||||
|
|
||||||
Compatible with
|
Compatible with
|
||||||
|
|
||||||
- **Django Rest Framework**: 3.8, 3.9, 3.10, 3.11
|
- **Django Rest Framework**: 3.8, 3.9, 3.10
|
||||||
- **Django**: 1.11, 2.2, 3.0
|
- **Django**: 1.11, 2.1, 2.2
|
||||||
- **Python**: 2.7, 3.6, 3.7, 3.8
|
- **Python**: 2.7, 3.5, 3.6, 3.7
|
||||||
|
|
||||||
Only the latest patch version of each ``major.minor`` series of Python, Django and Django REST Framework is supported.
|
Only the latest patch version of each ``major.minor`` series of Python, Django and Django REST Framework is supported.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,6 @@
|
||||||
Changelog
|
Changelog
|
||||||
#########
|
#########
|
||||||
|
|
||||||
|
|
||||||
**********
|
|
||||||
**1.17.1**
|
|
||||||
**********
|
|
||||||
|
|
||||||
*Release date: Feb 17, 2020*
|
|
||||||
|
|
||||||
- **FIXED:** fixed compatibility issue with CurrentUserDefault in Django Rest Framework 3.11
|
|
||||||
- **FIXED:** respect `USERNAME_FIELD` in `generate_swagger` command (:pr:`486`)
|
|
||||||
|
|
||||||
**Support was dropped for Python 3.5, Django 2.0, Django 2.1, DRF 3.7**
|
|
||||||
|
|
||||||
**********
|
**********
|
||||||
**1.17.0**
|
**1.17.0**
|
||||||
**********
|
**********
|
||||||
|
|
|
||||||
|
|
@ -212,8 +212,7 @@ Schema generation of ``serializers.SerializerMethodField`` is supported in two w
|
||||||
Serializer ``Meta`` nested class
|
Serializer ``Meta`` nested class
|
||||||
********************************
|
********************************
|
||||||
|
|
||||||
You can define some per-serializer or per-field options by adding a ``Meta`` class to your ``Serializer`` or
|
You can define some per-serializer options by adding a ``Meta`` class to your serializer, e.g.:
|
||||||
serializer ``Field``, e.g.:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
@ -237,64 +236,6 @@ The available options are:
|
||||||
which are converted to Swagger ``Schema`` attribute names according to :func:`.make_swagger_name`.
|
which are converted to Swagger ``Schema`` attribute names according to :func:`.make_swagger_name`.
|
||||||
Attribute names and values must conform to the `OpenAPI 2.0 specification <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject>`_.
|
Attribute names and values must conform to the `OpenAPI 2.0 specification <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject>`_.
|
||||||
|
|
||||||
Suppose you wanted to model an email using a `JSONField` to store the subject and body for performance reasons:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from django.contrib.postgres.fields import JSONField
|
|
||||||
|
|
||||||
class Email(models.Model):
|
|
||||||
# Store data as JSON, but the data should be made up of
|
|
||||||
# an object that has two properties, "subject" and "body"
|
|
||||||
# Example:
|
|
||||||
# {
|
|
||||||
# "subject": "My Title",
|
|
||||||
# "body": "The body of the message.",
|
|
||||||
# }
|
|
||||||
message = JSONField()
|
|
||||||
|
|
||||||
To instruct ``drf-yasg`` to output an OpenAPI schema that matches this, create a custom ``JSONField``:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
class EmailMessageField(serializers.JSONField):
|
|
||||||
class Meta:
|
|
||||||
swagger_schema_fields = {
|
|
||||||
"type": openapi.TYPE_OBJECT,
|
|
||||||
"title": "Email",
|
|
||||||
"properties": {
|
|
||||||
"subject": openapi.Schema(
|
|
||||||
title="Email subject",
|
|
||||||
type=openapi.TYPE_STRING,
|
|
||||||
),
|
|
||||||
"body": openapi.Schema(
|
|
||||||
title="Email body",
|
|
||||||
type=openapi.TYPE_STRING,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
"required": ["subject", "body"],
|
|
||||||
}
|
|
||||||
|
|
||||||
class EmailSerializer(ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Email
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
message = EmailMessageField()
|
|
||||||
|
|
||||||
.. Warning::
|
|
||||||
|
|
||||||
Overriding a default ``Field`` generated by a ``ModelSerializer`` will also override automatically
|
|
||||||
generated validators for that ``Field``. To add ``Serializer`` validation back in manually, see the relevant
|
|
||||||
`DRF Validators`_ and `DRF Fields`_ documentation.
|
|
||||||
|
|
||||||
One example way to do this is to set the ``default_validators`` attribute on a field.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
class EmailMessageField(serializers.JSONField):
|
|
||||||
default_validators = [my_custom_email_validator]
|
|
||||||
...
|
|
||||||
|
|
||||||
*************************
|
*************************
|
||||||
Subclassing and extending
|
Subclassing and extending
|
||||||
|
|
@ -448,5 +389,3 @@ A second example, of a :class:`~.inspectors.FieldInspector` that removes the ``t
|
||||||
|
|
||||||
|
|
||||||
.. _Python 3 type hinting: https://docs.python.org/3/library/typing.html
|
.. _Python 3 type hinting: https://docs.python.org/3/library/typing.html
|
||||||
.. _DRF Validators: https://www.django-rest-framework.org/api-guide/validators/
|
|
||||||
.. _DRF Fields: https://www.django-rest-framework.org/api-guide/fields/#validators
|
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,3 @@
|
||||||
-r lint.txt
|
-r lint.txt
|
||||||
|
|
||||||
tox-battery>=0.5
|
tox-battery>=0.5
|
||||||
django-oauth-toolkit
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
Pillow>=4.3.0
|
Pillow>=4.3.0
|
||||||
django-filter>=1.1.0,<2.0; python_version == "2.7"
|
django-filter>=1.1.0,<2.0; python_version == "2.7"
|
||||||
django-filter>=1.1.0; python_version >= "3.5"
|
django-filter>=1.1.0; python_version >= "3.5"
|
||||||
djangorestframework-camel-case>=1.1.2
|
#djangorestframework-camel-case>=0.2.0
|
||||||
|
# tempory replacement of broken lib
|
||||||
|
-e git+https://github.com/tfranzel/djangorestframework-camel-case.git@bd556d38fa7382acadfe91d93d92d99c663248a9#egg=djangorestframework_camel_case
|
||||||
djangorestframework-recursive>=0.1.2
|
djangorestframework-recursive>=0.1.2
|
||||||
dj-database-url>=0.4.2
|
dj-database-url>=0.4.2
|
||||||
user_agents>=1.1.0
|
user_agents>=1.1.0
|
||||||
django-cors-headers
|
|
||||||
|
|
|
||||||
2
setup.py
2
setup.py
|
|
@ -19,7 +19,7 @@ with io.open('README.rst', encoding='utf-8') as readme:
|
||||||
requirements = read_req('base.txt')
|
requirements = read_req('base.txt')
|
||||||
requirements_validation = read_req('validation.txt')
|
requirements_validation = read_req('validation.txt')
|
||||||
|
|
||||||
py3_supported_range = (5, 8)
|
py3_supported_range = (5, 7)
|
||||||
|
|
||||||
# convert inclusive range to exclusive range
|
# convert inclusive range to exclusive range
|
||||||
py3_supported_range = (py3_supported_range[0], py3_supported_range[1] + 1)
|
py3_supported_range = (py3_supported_range[0], py3_supported_range[1] + 1)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from six import binary_type, raise_from, text_type
|
from six import raise_from
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
|
|
@ -176,14 +176,7 @@ class SaneYamlDumper(yaml.SafeDumper):
|
||||||
node.flow_style = best_style
|
node.flow_style = best_style
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def represent_text(self, text):
|
|
||||||
if "\n" in text:
|
|
||||||
return self.represent_scalar('tag:yaml.org,2002:str', text, style='|')
|
|
||||||
return self.represent_scalar('tag:yaml.org,2002:str', text)
|
|
||||||
|
|
||||||
|
|
||||||
SaneYamlDumper.add_representer(binary_type, SaneYamlDumper.represent_text)
|
|
||||||
SaneYamlDumper.add_representer(text_type, SaneYamlDumper.represent_text)
|
|
||||||
SaneYamlDumper.add_representer(OrderedDict, SaneYamlDumper.represent_odict)
|
SaneYamlDumper.add_representer(OrderedDict, SaneYamlDumper.represent_odict)
|
||||||
SaneYamlDumper.add_multi_representer(OrderedDict, SaneYamlDumper.represent_odict)
|
SaneYamlDumper.add_multi_representer(OrderedDict, SaneYamlDumper.represent_odict)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -382,21 +382,8 @@ def find_limits(field):
|
||||||
def decimal_field_type(field):
|
def decimal_field_type(field):
|
||||||
return openapi.TYPE_NUMBER if decimal_as_float(field) else openapi.TYPE_STRING
|
return openapi.TYPE_NUMBER if decimal_as_float(field) else openapi.TYPE_STRING
|
||||||
|
|
||||||
def recurse_one_to_one(field, visited_set=None):
|
|
||||||
if visited_set is None:
|
|
||||||
visited_set = set()
|
|
||||||
if field in visited_set:
|
|
||||||
return None #cycle?
|
|
||||||
if isinstance(field, models.OneToOneField):
|
|
||||||
tgt = field.target_field
|
|
||||||
visited_set.add(field)
|
|
||||||
return recurse_one_to_one(tgt, visited_set=visited_set)
|
|
||||||
else:
|
|
||||||
tmp = get_basic_type_info(field)
|
|
||||||
return tmp['type']
|
|
||||||
|
|
||||||
model_field_to_basic_type = [
|
model_field_to_basic_type = [
|
||||||
(models.OneToOneField, (recurse_one_to_one, None)),
|
|
||||||
(models.AutoField, (openapi.TYPE_INTEGER, None)),
|
(models.AutoField, (openapi.TYPE_INTEGER, None)),
|
||||||
(models.BinaryField, (openapi.TYPE_STRING, openapi.FORMAT_BINARY)),
|
(models.BinaryField, (openapi.TYPE_STRING, openapi.FORMAT_BINARY)),
|
||||||
(models.BooleanField, (openapi.TYPE_BOOLEAN, None)),
|
(models.BooleanField, (openapi.TYPE_BOOLEAN, None)),
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ class Command(BaseCommand):
|
||||||
if user:
|
if user:
|
||||||
# Only call get_user_model if --user was passed in order to
|
# Only call get_user_model if --user was passed in order to
|
||||||
# avoid crashing if auth is not configured in the project
|
# avoid crashing if auth is not configured in the project
|
||||||
user = get_user_model().objects.get(**{get_user_model().USERNAME_FIELD: user})
|
user = get_user_model().objects.get(username=user)
|
||||||
|
|
||||||
mock = mock or private or (user is not None) or (api_version is not None)
|
mock = mock or private or (user is not None) or (api_version is not None)
|
||||||
if mock and not api_url:
|
if mock and not api_url:
|
||||||
|
|
|
||||||
|
|
@ -470,7 +470,7 @@ class Schema(SwaggerDict):
|
||||||
:type properties: dict[str,Schema or SchemaRef]
|
:type properties: dict[str,Schema or SchemaRef]
|
||||||
:param additional_properties: allow wildcard properties not listed in `properties`
|
:param additional_properties: allow wildcard properties not listed in `properties`
|
||||||
:type additional_properties: bool or Schema or SchemaRef
|
:type additional_properties: bool or Schema or SchemaRef
|
||||||
:param list[str] required: list of required property names
|
:param list[str] required: list of requried property names
|
||||||
:param items: type of array items, only valid if `type` is ``array``
|
:param items: type of array items, only valid if `type` is ``array``
|
||||||
:type items: Schema or SchemaRef
|
:type items: Schema or SchemaRef
|
||||||
:param default: only valid when insider another ``Schema``\\ 's ``properties``;
|
:param default: only valid when insider another ``Schema``\\ 's ``properties``;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
|
@ -96,8 +95,8 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=unset, request_bo
|
||||||
* a ``Serializer`` class or instance will be converted into a :class:`.Schema` and treated as above
|
* a ``Serializer`` class or instance will be converted into a :class:`.Schema` and treated as above
|
||||||
* a :class:`.Response` object will be used as-is; however if its ``schema`` attribute is a ``Serializer``,
|
* a :class:`.Response` object will be used as-is; however if its ``schema`` attribute is a ``Serializer``,
|
||||||
it will automatically be converted into a :class:`.Schema`
|
it will automatically be converted into a :class:`.Schema`
|
||||||
:type responses: dict[int or str, (drf_yasg.openapi.Schema or drf_yasg.openapi.SchemaRef or
|
:type responses: dict[str,(drf_yasg.openapi.Schema or drf_yasg.openapi.SchemaRef or drf_yasg.openapi.Response or
|
||||||
drf_yasg.openapi.Response or str or rest_framework.serializers.Serializer)]
|
str or rest_framework.serializers.Serializer)]
|
||||||
|
|
||||||
:param list[type[drf_yasg.inspectors.FieldInspector]] field_inspectors: extra serializer and field inspectors; these
|
:param list[type[drf_yasg.inspectors.FieldInspector]] field_inspectors: extra serializer and field inspectors; these
|
||||||
will be tried before :attr:`.ViewInspector.field_inspectors` on the :class:`.inspectors.SwaggerAutoSchema`
|
will be tried before :attr:`.ViewInspector.field_inspectors` on the :class:`.inspectors.SwaggerAutoSchema`
|
||||||
|
|
@ -375,16 +374,10 @@ def get_consumes(parser_classes):
|
||||||
parser_classes = [pc for pc in parser_classes if not issubclass(pc, FileUploadParser)]
|
parser_classes = [pc for pc in parser_classes if not issubclass(pc, FileUploadParser)]
|
||||||
media_types = [parser.media_type for parser in parser_classes or []]
|
media_types = [parser.media_type for parser in parser_classes or []]
|
||||||
non_form_media_types = [encoding for encoding in media_types if not is_form_media_type(encoding)]
|
non_form_media_types = [encoding for encoding in media_types if not is_form_media_type(encoding)]
|
||||||
# Because swagger Parameter objects don't support complex data types (nested objects, arrays),
|
|
||||||
# we can't use those unless we are sure the view *only* accepts form data
|
|
||||||
# This means that a view won't support file upload in swagger unless it explicitly
|
|
||||||
# sets its parser classes to include only form parsers
|
|
||||||
if len(non_form_media_types) == 0:
|
if len(non_form_media_types) == 0:
|
||||||
return media_types
|
return media_types
|
||||||
|
else:
|
||||||
# If the form accepts both form data and another type, like json (which is the default config),
|
return non_form_media_types
|
||||||
# we will render its input as a Schema and thus it file parameters will be read-only
|
|
||||||
return non_form_media_types
|
|
||||||
|
|
||||||
|
|
||||||
def get_produces(renderer_classes):
|
def get_produces(renderer_classes):
|
||||||
|
|
@ -445,9 +438,6 @@ def force_real_str(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||||
if type(s) != str:
|
if type(s) != str:
|
||||||
s = '' + s
|
s = '' + s
|
||||||
|
|
||||||
# Remove common indentation to get the correct Markdown rendering
|
|
||||||
s = textwrap.dedent(s)
|
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -483,10 +473,7 @@ def get_field_default(field):
|
||||||
try:
|
try:
|
||||||
if hasattr(default, 'set_context'):
|
if hasattr(default, 'set_context'):
|
||||||
default.set_context(field)
|
default.set_context(field)
|
||||||
if getattr(default, 'requires_context', False):
|
default = default()
|
||||||
default = default(field)
|
|
||||||
else:
|
|
||||||
default = default()
|
|
||||||
except Exception: # pragma: no cover
|
except Exception: # pragma: no cover
|
||||||
logger.warning("default for %s is callable but it raised an exception when "
|
logger.warning("default for %s is callable but it raised an exception when "
|
||||||
"called; 'default' will not be set on schema", field, exc_info=True)
|
"called; 'default' will not be set on schema", field, exc_info=True)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from articles.models import Article, ArticleGroup
|
from articles.models import Article, ArticleGroup
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,16 @@ LOGGING = {
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'django': {
|
'django': {
|
||||||
|
'handlers': ['console_log'],
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'propagate': False,
|
||||||
|
},
|
||||||
|
'django.db.backends': {
|
||||||
|
'handlers': ['console_log'],
|
||||||
|
'level': 'INFO',
|
||||||
|
'propagate': False,
|
||||||
|
},
|
||||||
|
'django.template': {
|
||||||
'handlers': ['console_log'],
|
'handlers': ['console_log'],
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ swagger_info = openapi.Info(
|
||||||
default_version='v1',
|
default_version='v1',
|
||||||
description="""This is a demo project for the [drf-yasg](https://github.com/axnsan12/drf-yasg) Django Rest Framework library.
|
description="""This is a demo project for the [drf-yasg](https://github.com/axnsan12/drf-yasg) Django Rest Framework library.
|
||||||
|
|
||||||
The `swagger-ui` view can be found [here](/cached/swagger).
|
The `swagger-ui` view can be found [here](/cached/swagger).
|
||||||
The `ReDoc` view can be found [here](/cached/redoc).
|
The `ReDoc` view can be found [here](/cached/redoc).
|
||||||
The swagger YAML document can be found [here](/cached/swagger.yaml).
|
The swagger YAML document can be found [here](/cached/swagger.yaml).
|
||||||
|
|
||||||
You can log in using the pre-existing `admin` user with password `passwordadmin`.""", # noqa
|
You can log in using the pre-existing `admin` user with password `passwordadmin`.""", # noqa
|
||||||
terms_of_service="https://www.google.com/policies/terms/",
|
terms_of_service="https://www.google.com/policies/terms/",
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import sys
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password
|
||||||
from django.db import migrations, IntegrityError, transaction
|
from django.db import migrations, IntegrityError
|
||||||
|
|
||||||
|
|
||||||
def add_default_user(apps, schema_editor):
|
def add_default_user(apps, schema_editor):
|
||||||
|
|
@ -13,15 +13,14 @@ def add_default_user(apps, schema_editor):
|
||||||
User = apps.get_model(settings.AUTH_USER_MODEL)
|
User = apps.get_model(settings.AUTH_USER_MODEL)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
admin = User(
|
||||||
admin = User(
|
username=username,
|
||||||
username=username,
|
email=email,
|
||||||
email=email,
|
password=make_password(password),
|
||||||
password=make_password(password),
|
is_superuser=True,
|
||||||
is_superuser=True,
|
is_staff=True
|
||||||
is_staff=True
|
)
|
||||||
)
|
admin.save()
|
||||||
admin.save()
|
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
sys.stdout.write(" User '%s <%s>' already exists..." % (username, email))
|
sys.stdout.write(" User '%s <%s>' already exists..." % (username, email))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
swagger: '2.0'
|
swagger: '2.0'
|
||||||
info:
|
info:
|
||||||
title: Snippets API
|
title: Snippets API
|
||||||
description: |-
|
description: "This is a demo project for the [drf-yasg](https://github.com/axnsan12/drf-yasg)\
|
||||||
This is a demo project for the [drf-yasg](https://github.com/axnsan12/drf-yasg) Django Rest Framework library.
|
\ Django Rest Framework library.\n\nThe `swagger-ui` view can be found [here](/cached/swagger).\
|
||||||
|
\ \nThe `ReDoc` view can be found [here](/cached/redoc). \nThe swagger YAML\
|
||||||
The `swagger-ui` view can be found [here](/cached/swagger).
|
\ document can be found [here](/cached/swagger.yaml). \n\nYou can log in using\
|
||||||
The `ReDoc` view can be found [here](/cached/redoc).
|
\ the pre-existing `admin` user with password `passwordadmin`."
|
||||||
The swagger YAML document can be found [here](/cached/swagger.yaml).
|
|
||||||
|
|
||||||
You can log in using the pre-existing `admin` user with password `passwordadmin`.
|
|
||||||
termsOfService: https://www.google.com/policies/terms/
|
termsOfService: https://www.google.com/policies/terms/
|
||||||
contact:
|
contact:
|
||||||
email: contact@snippets.local
|
email: contact@snippets.local
|
||||||
|
|
@ -1505,9 +1502,7 @@ definitions:
|
||||||
readOnly: true
|
readOnly: true
|
||||||
help_text_example_3:
|
help_text_example_3:
|
||||||
title: Help text example 3
|
title: Help text example 3
|
||||||
description: |2
|
description: "\n docstring is set so should appear in swagger as fallback\n\
|
||||||
|
\ :return:\n "
|
||||||
docstring is set so should appear in swagger as fallback
|
|
||||||
:return:
|
|
||||||
type: integer
|
type: integer
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ from django.conf.urls import url
|
||||||
from django.contrib.postgres import fields as postgres_fields
|
from django.contrib.postgres import fields as postgres_fields
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.inspect import get_func_args
|
from django.utils.inspect import get_func_args
|
||||||
from django_fake_model import models as fake_models
|
|
||||||
from rest_framework import routers, serializers, viewsets
|
from rest_framework import routers, serializers, viewsets
|
||||||
from rest_framework.decorators import api_view
|
from rest_framework.decorators import api_view
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from django_fake_model import models as fake_models
|
||||||
from drf_yasg import codecs, openapi
|
from drf_yasg import codecs, openapi
|
||||||
from drf_yasg.codecs import yaml_sane_load
|
from drf_yasg.codecs import yaml_sane_load
|
||||||
from drf_yasg.errors import SwaggerGenerationError
|
from drf_yasg.errors import SwaggerGenerationError
|
||||||
|
|
@ -334,21 +334,3 @@ def test_optional_return_type(py_type, expected_type):
|
||||||
swagger = generator.get_schema(None, True)
|
swagger = generator.get_schema(None, True)
|
||||||
property_schema = swagger["definitions"]["OptionalMethod"]["properties"]["x"]
|
property_schema = swagger["definitions"]["OptionalMethod"]["properties"]["x"]
|
||||||
assert property_schema == openapi.Schema(title='X', type=expected_type, readOnly=True)
|
assert property_schema == openapi.Schema(title='X', type=expected_type, readOnly=True)
|
||||||
|
|
||||||
|
|
||||||
EXPECTED_DESCRIPTION = """\
|
|
||||||
description: |-
|
|
||||||
This is a demo project for the [drf-yasg](https://github.com/axnsan12/drf-yasg) Django Rest Framework library.
|
|
||||||
|
|
||||||
The `swagger-ui` view can be found [here](/cached/swagger).
|
|
||||||
The `ReDoc` view can be found [here](/cached/redoc).
|
|
||||||
The swagger YAML document can be found [here](/cached/swagger.yaml).
|
|
||||||
|
|
||||||
You can log in using the pre-existing `admin` user with password `passwordadmin`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def test_multiline_strings(call_generate_swagger):
|
|
||||||
output = call_generate_swagger(format='yaml')
|
|
||||||
print("|\n|".join(output.splitlines()[:20]))
|
|
||||||
assert EXPECTED_DESCRIPTION in output
|
|
||||||
|
|
|
||||||
16
tox.ini
16
tox.ini
|
|
@ -5,9 +5,11 @@ isolated_build_env = .package
|
||||||
|
|
||||||
# https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django
|
# https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django
|
||||||
envlist =
|
envlist =
|
||||||
py36-django{111,22}-drf{38,39},
|
py27-django111-drf39-typing,
|
||||||
py37-django22-drf{38,39,310,311},
|
py27-django111-drf{38,39},
|
||||||
py38-django{22,3}-drf{310,311},
|
py{35,36}-django{111,21,22}-drf{38,39},
|
||||||
|
py37-django{21,22}-drf{38,39,310},
|
||||||
|
py38-django22-drf310,
|
||||||
djmaster, lint, docs
|
djmaster, lint, docs
|
||||||
skip_missing_interpreters = true
|
skip_missing_interpreters = true
|
||||||
|
|
||||||
|
|
@ -18,21 +20,21 @@ deps =
|
||||||
[testenv]
|
[testenv]
|
||||||
deps =
|
deps =
|
||||||
django111: Django>=1.11,<2.0
|
django111: Django>=1.11,<2.0
|
||||||
|
django111: django-cors-headers>=2.1.0
|
||||||
django111: django-oauth-toolkit>=1.1.0,<1.2.0
|
django111: django-oauth-toolkit>=1.1.0,<1.2.0
|
||||||
|
|
||||||
django21: Django>=2.1,<2.2
|
django21: Django>=2.1,<2.2
|
||||||
|
django21: django-cors-headers>=2.1.0
|
||||||
django21: django-oauth-toolkit>=1.2.0
|
django21: django-oauth-toolkit>=1.2.0
|
||||||
|
|
||||||
django22: Django>=2.2,<2.3
|
django22: Django>=2.2,<2.3
|
||||||
|
django22: django-cors-headers>=2.1.0
|
||||||
django22: django-oauth-toolkit>=1.2.0
|
django22: django-oauth-toolkit>=1.2.0
|
||||||
|
|
||||||
django3: Django>=2.2,<2.3
|
|
||||||
django3: django-oauth-toolkit>=1.2.0
|
|
||||||
|
|
||||||
drf38: djangorestframework>=3.8,<3.9
|
drf38: djangorestframework>=3.8,<3.9
|
||||||
drf39: djangorestframework>=3.9,<3.10
|
drf39: djangorestframework>=3.9,<3.10
|
||||||
drf310: djangorestframework>=3.10,<3.11
|
drf310: djangorestframework>=3.10
|
||||||
drf311: djangorestframework>=3.11,<3.12
|
|
||||||
|
|
||||||
typing: typing>=3.6.6
|
typing: typing>=3.6.6
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue