From a2c21539f783480e99177c64b0fb79bd61f3e318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=20V=C3=AEjdea?= Date: Sat, 16 Dec 2017 18:18:21 +0100 Subject: [PATCH] Prepare release 1.0.4 --- README.rst | 10 +++++++++- docs/changelog.rst | 8 ++++++++ docs/conf.py | 8 +++++++- setup.py | 32 +++++++++++++++++--------------- src/drf_yasg/codecs.py | 5 +++++ src/drf_yasg/openapi.py | 12 ++++++++---- tests/reference.yaml | 10 ++++++++-- tests/test_schema_generator.py | 10 +++++++++- 8 files changed, 71 insertions(+), 24 deletions(-) diff --git a/README.rst b/README.rst index aeeeee8f..76ddbb76 100644 --- a/README.rst +++ b/README.rst @@ -5,7 +5,7 @@ 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. @@ -358,5 +358,13 @@ https://drf-yasg.readthedocs.io/en/latest/ :target: https://codecov.io/gh/axnsan12/drf-yasg :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 :trim: diff --git a/docs/changelog.rst b/docs/changelog.rst index 42f537fa..d8f1158a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -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** ********* diff --git a/docs/conf.py b/docs/conf.py index 794ab321..1c9be100 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -196,7 +196,11 @@ ('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')) + +# activate the Django testproj to be able to succesfully import drf_yasg sys.path.insert(0, os.path.abspath('../testproj')) os.putenv('DJANGO_SETTINGS_MODULE', 'testproj.settings') @@ -204,11 +208,13 @@ settings.configure() +# instantiate a SchemaView in the views module to make it available to autodoc 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) +# 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_pr_uri = "https://github.com/axnsan12/drf-yasg/pull/%d" diff --git a/setup.py b/setup.py index cd9596b8..bf3e32be 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,7 @@ import io import os +import sys from setuptools import setup, find_packages import distutils.core @@ -21,23 +22,24 @@ def _install_setup_requires(attrs): dist.fetch_build_eggs(dist.setup_requires) -try: - # 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) - _install_setup_requires({'setup_requires': requirements_setup}) -except Exception: - pass +if 'sdist' in sys.argv: + try: + # 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) + _install_setup_requires({'setup_requires': requirements_setup}) + except Exception: + pass -try: - # see https://github.com/pypa/setuptools_scm/issues/190, setuptools_scm includes ALL versioned files from 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, - # the setuptools_scm version should remain pinned to ensure it keeps working - import setuptools_scm.integration + try: + # see https://github.com/pypa/setuptools_scm/issues/190, setuptools_scm includes ALL versioned files from + # 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, + # the setuptools_scm version should remain pinned to ensure it keeps working + import setuptools_scm.integration - setuptools_scm.integration.find_files = lambda _: [] -except ImportError: - pass + setuptools_scm.integration.find_files = lambda _: [] + except ImportError: + pass def read_req(req_file): diff --git a/src/drf_yasg/codecs.py b/src/drf_yasg/codecs.py index 2e4f4609..d2746a01 100644 --- a/src/drf_yasg/codecs.py +++ b/src/drf_yasg/codecs.py @@ -101,6 +101,10 @@ def _dump_dict(self, spec): class SaneYamlDumper(yaml.SafeDumper): """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): """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 * multi-line mapping style instead of json-like inline style * list elements are indented into their parents + * YAML references/aliases are disabled :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 diff --git a/src/drf_yasg/openapi.py b/src/drf_yasg/openapi.py index 3f886e20..7e6e34be 100644 --- a/src/drf_yasg/openapi.py +++ b/src/drf_yasg/openapi.py @@ -115,15 +115,19 @@ def _insert_extras__(self): setattr(self, attr, val) @staticmethod - def _as_odict(obj): + def _as_odict(obj, memo): """Implementation detail of :meth:`.as_odict`""" + if id(obj) in memo: + return memo[id(obj)] + if isinstance(obj, dict): result = OrderedDict() + memo[id(obj)] = result for attr, val in obj.items(): - result[attr] = SwaggerDict._as_odict(val) + result[attr] = SwaggerDict._as_odict(val, memo) return result 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 @@ -132,7 +136,7 @@ def as_odict(self): :rtype: OrderedDict """ - return SwaggerDict._as_odict(self) + return SwaggerDict._as_odict(self, {}) def __reduce__(self): # for pickle supprt; this skips calls to all SwaggerDict __init__ methods and relies diff --git a/tests/reference.yaml b/tests/reference.yaml index 516686d5..40bef95b 100644 --- a/tests/reference.yaml +++ b/tests/reference.yaml @@ -380,7 +380,7 @@ paths: - name: data in: body required: true - schema: &id001 + schema: required: - username type: object @@ -390,7 +390,13 @@ paths: responses: '201': description: '' - schema: *id001 + schema: + required: + - username + type: object + properties: + username: + type: string consumes: - application/json tags: diff --git a/tests/test_schema_generator.py b/tests/test_schema_generator.py index 15001b5c..5be34551 100644 --- a/tests/test_schema_generator.py +++ b/tests/test_schema_generator.py @@ -40,10 +40,18 @@ def test_json_codec_roundtrip(codec_json, generator, validate_schema): def test_yaml_codec_roundtrip(codec_yaml, generator, validate_schema): swagger = generator.get_schema(None, True) 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'))) +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(): generator = OpenAPISchemaGenerator( info=openapi.Info(title="Test generator", default_version="v1"),