parent
73bd7a136d
commit
a2c21539f7
10
README.rst
10
README.rst
|
|
@ -5,7 +5,7 @@
|
||||||
drf-yasg - Yet another Swagger generator
|
drf-yasg - Yet another Swagger generator
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
|travis| |nbsp| |codecov|
|
|travis| |nbsp| |codecov| |nbsp| |rtd-badge| |nbsp| |pypi-version|
|
||||||
|
|
||||||
Generate **real** Swagger/OpenAPI 2.0 specifications from a Django Rest Framework API.
|
Generate **real** Swagger/OpenAPI 2.0 specifications from a Django Rest Framework API.
|
||||||
|
|
||||||
|
|
@ -358,5 +358,13 @@ https://drf-yasg.readthedocs.io/en/latest/
|
||||||
:target: https://codecov.io/gh/axnsan12/drf-yasg
|
:target: https://codecov.io/gh/axnsan12/drf-yasg
|
||||||
:alt: Codecov
|
:alt: Codecov
|
||||||
|
|
||||||
|
.. |pypi-version| image:: https://img.shields.io/pypi/v/drf-yasg.svg
|
||||||
|
:target: https://pypi.org/project/drf-yasg/
|
||||||
|
:alt: PyPI
|
||||||
|
|
||||||
|
.. |rtd-badge| image:: https://img.shields.io/readthedocs/drf-yasg.svg
|
||||||
|
:target: https://drf-yasg.readthedocs.io/
|
||||||
|
:alt: ReadTheDocs
|
||||||
|
|
||||||
.. |nbsp| unicode:: 0xA0
|
.. |nbsp| unicode:: 0xA0
|
||||||
:trim:
|
:trim:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,14 @@ Changelog
|
||||||
#########
|
#########
|
||||||
|
|
||||||
|
|
||||||
|
*********
|
||||||
|
**1.0.4**
|
||||||
|
*********
|
||||||
|
|
||||||
|
- **FIX:** fixed improper generation of YAML references
|
||||||
|
- **FEATURE:** added ``query_serializer`` parameter to
|
||||||
|
:func:`@swagger_auto_schema <.swagger_auto_schema>` (:issue:`16`, :pr:`17`)
|
||||||
|
|
||||||
*********
|
*********
|
||||||
**1.0.3**
|
**1.0.3**
|
||||||
*********
|
*********
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,11 @@ nitpick_ignore = [
|
||||||
('py:obj', 'APIView'),
|
('py:obj', 'APIView'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# even though the package should be already installed, the sphinx build on RTD
|
||||||
|
# for some reason needs the sources dir to be in the path in order for viewcode to work
|
||||||
sys.path.insert(0, os.path.abspath('../src'))
|
sys.path.insert(0, os.path.abspath('../src'))
|
||||||
|
|
||||||
|
# activate the Django testproj to be able to succesfully import drf_yasg
|
||||||
sys.path.insert(0, os.path.abspath('../testproj'))
|
sys.path.insert(0, os.path.abspath('../testproj'))
|
||||||
os.putenv('DJANGO_SETTINGS_MODULE', 'testproj.settings')
|
os.putenv('DJANGO_SETTINGS_MODULE', 'testproj.settings')
|
||||||
|
|
||||||
|
|
@ -204,11 +208,13 @@ from django.conf import settings # noqa: E402
|
||||||
|
|
||||||
settings.configure()
|
settings.configure()
|
||||||
|
|
||||||
|
# instantiate a SchemaView in the views module to make it available to autodoc
|
||||||
import drf_yasg.views # noqa: E402
|
import drf_yasg.views # noqa: E402
|
||||||
|
|
||||||
# instantiate a SchemaView in the views module to make it available to autodoc
|
|
||||||
drf_yasg.views.SchemaView = drf_yasg.views.get_schema_view(None)
|
drf_yasg.views.SchemaView = drf_yasg.views.get_schema_view(None)
|
||||||
|
|
||||||
|
# custom interpreted role for linking to GitHub issues and pull requests
|
||||||
|
# use as :issue:`14` or :pr:`17`
|
||||||
gh_issue_uri = "https://github.com/axnsan12/drf-yasg/issues/%d"
|
gh_issue_uri = "https://github.com/axnsan12/drf-yasg/issues/%d"
|
||||||
gh_pr_uri = "https://github.com/axnsan12/drf-yasg/pull/%d"
|
gh_pr_uri = "https://github.com/axnsan12/drf-yasg/pull/%d"
|
||||||
|
|
||||||
|
|
|
||||||
6
setup.py
6
setup.py
|
|
@ -3,6 +3,7 @@
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import sys
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
import distutils.core
|
import distutils.core
|
||||||
|
|
||||||
|
|
@ -21,6 +22,7 @@ def _install_setup_requires(attrs):
|
||||||
dist.fetch_build_eggs(dist.setup_requires)
|
dist.fetch_build_eggs(dist.setup_requires)
|
||||||
|
|
||||||
|
|
||||||
|
if 'sdist' in sys.argv:
|
||||||
try:
|
try:
|
||||||
# try to install setuptools_scm before setuptools does it, otherwise our monkey patch below will come too early
|
# try to install setuptools_scm before setuptools does it, otherwise our monkey patch below will come too early
|
||||||
# (setuptools_scm adds find_files hooks into setuptools on install)
|
# (setuptools_scm adds find_files hooks into setuptools on install)
|
||||||
|
|
@ -29,8 +31,8 @@ except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# see https://github.com/pypa/setuptools_scm/issues/190, setuptools_scm includes ALL versioned files from the git
|
# see https://github.com/pypa/setuptools_scm/issues/190, setuptools_scm includes ALL versioned files from
|
||||||
# repo into the sdist by default, and there is no easy way to provide an opt-out;
|
# the git repo into the sdist by default, and there is no easy way to provide an opt-out;
|
||||||
# this hack is ugly but does the job; because this is not really a documented interface of the module,
|
# this hack is ugly but does the job; because this is not really a documented interface of the module,
|
||||||
# the setuptools_scm version should remain pinned to ensure it keeps working
|
# the setuptools_scm version should remain pinned to ensure it keeps working
|
||||||
import setuptools_scm.integration
|
import setuptools_scm.integration
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,10 @@ class OpenAPICodecJson(_OpenAPICodec):
|
||||||
class SaneYamlDumper(yaml.SafeDumper):
|
class SaneYamlDumper(yaml.SafeDumper):
|
||||||
"""YamlDumper class usable for dumping ``OrderedDict`` and list instances in a standard way."""
|
"""YamlDumper class usable for dumping ``OrderedDict`` and list instances in a standard way."""
|
||||||
|
|
||||||
|
def ignore_aliases(self, data):
|
||||||
|
"""Disable YAML references."""
|
||||||
|
return True
|
||||||
|
|
||||||
def increase_indent(self, flow=False, indentless=False, **kwargs):
|
def increase_indent(self, flow=False, indentless=False, **kwargs):
|
||||||
"""https://stackoverflow.com/a/39681672
|
"""https://stackoverflow.com/a/39681672
|
||||||
|
|
||||||
|
|
@ -152,6 +156,7 @@ def yaml_sane_dump(data, binary):
|
||||||
* OrderedDicts are dumped as regular mappings instead of non-standard !!odict
|
* OrderedDicts are dumped as regular mappings instead of non-standard !!odict
|
||||||
* multi-line mapping style instead of json-like inline style
|
* multi-line mapping style instead of json-like inline style
|
||||||
* list elements are indented into their parents
|
* list elements are indented into their parents
|
||||||
|
* YAML references/aliases are disabled
|
||||||
|
|
||||||
:param dict data: the data to be serializers
|
:param dict data: the data to be serializers
|
||||||
:param bool binary: True to return a utf-8 encoded binary object, False to return a string
|
:param bool binary: True to return a utf-8 encoded binary object, False to return a string
|
||||||
|
|
|
||||||
|
|
@ -115,15 +115,19 @@ class SwaggerDict(OrderedDict):
|
||||||
setattr(self, attr, val)
|
setattr(self, attr, val)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _as_odict(obj):
|
def _as_odict(obj, memo):
|
||||||
"""Implementation detail of :meth:`.as_odict`"""
|
"""Implementation detail of :meth:`.as_odict`"""
|
||||||
|
if id(obj) in memo:
|
||||||
|
return memo[id(obj)]
|
||||||
|
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
result = OrderedDict()
|
result = OrderedDict()
|
||||||
|
memo[id(obj)] = result
|
||||||
for attr, val in obj.items():
|
for attr, val in obj.items():
|
||||||
result[attr] = SwaggerDict._as_odict(val)
|
result[attr] = SwaggerDict._as_odict(val, memo)
|
||||||
return result
|
return result
|
||||||
elif isinstance(obj, (list, tuple)):
|
elif isinstance(obj, (list, tuple)):
|
||||||
return type(obj)(SwaggerDict._as_odict(elem) for elem in obj)
|
return type(obj)(SwaggerDict._as_odict(elem, memo) for elem in obj)
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
@ -132,7 +136,7 @@ class SwaggerDict(OrderedDict):
|
||||||
|
|
||||||
:rtype: OrderedDict
|
:rtype: OrderedDict
|
||||||
"""
|
"""
|
||||||
return SwaggerDict._as_odict(self)
|
return SwaggerDict._as_odict(self, {})
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self):
|
||||||
# for pickle supprt; this skips calls to all SwaggerDict __init__ methods and relies
|
# for pickle supprt; this skips calls to all SwaggerDict __init__ methods and relies
|
||||||
|
|
|
||||||
|
|
@ -380,7 +380,7 @@ paths:
|
||||||
- name: data
|
- name: data
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
schema: &id001
|
schema:
|
||||||
required:
|
required:
|
||||||
- username
|
- username
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -390,7 +390,13 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: ''
|
description: ''
|
||||||
schema: *id001
|
schema:
|
||||||
|
required:
|
||||||
|
- username
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
consumes:
|
consumes:
|
||||||
- application/json
|
- application/json
|
||||||
tags:
|
tags:
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,18 @@ def test_json_codec_roundtrip(codec_json, generator, validate_schema):
|
||||||
def test_yaml_codec_roundtrip(codec_yaml, generator, validate_schema):
|
def test_yaml_codec_roundtrip(codec_yaml, generator, validate_schema):
|
||||||
swagger = generator.get_schema(None, True)
|
swagger = generator.get_schema(None, True)
|
||||||
yaml_bytes = codec_yaml.encode(swagger)
|
yaml_bytes = codec_yaml.encode(swagger)
|
||||||
assert b'omap' not in yaml_bytes
|
assert b'omap' not in yaml_bytes # ensure no ugly !!omap is outputted
|
||||||
|
assert b'&id' not in yaml_bytes and b'*id' not in yaml_bytes # ensure no YAML references are generated
|
||||||
validate_schema(yaml.safe_load(yaml_bytes.decode('utf-8')))
|
validate_schema(yaml.safe_load(yaml_bytes.decode('utf-8')))
|
||||||
|
|
||||||
|
|
||||||
|
def test_yaml_and_json_match(codec_yaml, codec_json, generator):
|
||||||
|
swagger = generator.get_schema(None, True)
|
||||||
|
yaml_schema = yaml.safe_load(codec_yaml.encode(swagger).decode('utf-8'))
|
||||||
|
json_schema = json.loads(codec_json.encode(swagger).decode('utf-8'))
|
||||||
|
assert yaml_schema == json_schema
|
||||||
|
|
||||||
|
|
||||||
def test_basepath_only():
|
def test_basepath_only():
|
||||||
generator = OpenAPISchemaGenerator(
|
generator = OpenAPISchemaGenerator(
|
||||||
info=openapi.Info(title="Test generator", default_version="v1"),
|
info=openapi.Info(title="Test generator", default_version="v1"),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue