From d9f58a51744edcfa4d765ce1efa84253283b92d3 Mon Sep 17 00:00:00 2001 From: Thorsten Franzel Date: Thu, 9 Jan 2020 13:32:59 +0100 Subject: [PATCH 1/3] add failing test for yaml alias usage --- tests/schemas/test_openapi.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/schemas/test_openapi.py b/tests/schemas/test_openapi.py index 03eb9de7a9..1de15fd274 100644 --- a/tests/schemas/test_openapi.py +++ b/tests/schemas/test_openapi.py @@ -6,7 +6,7 @@ from rest_framework import filters, generics, pagination, routers, serializers from rest_framework.compat import uritemplate from rest_framework.parsers import JSONParser, MultiPartParser -from rest_framework.renderers import JSONRenderer +from rest_framework.renderers import JSONRenderer, OpenAPIRenderer from rest_framework.request import Request from rest_framework.schemas.openapi import AutoSchema, SchemaGenerator @@ -434,6 +434,19 @@ class View(generics.CreateAPIView): assert len(success_response['content'].keys()) == 1 assert 'application/json' in success_response['content'] + def test_openapi_yaml_rendering_without_aliases(self): + renderer = OpenAPIRenderer() + + reused_object = {'test': 'test'} + data = { + 'o1': reused_object, + 'o2': reused_object, + } + assert ( + renderer.render(data) == b'o1:\n test: test\no2:\n test: test\n' or + renderer.render(data) == b'o2:\n test: test\no1:\n test: test\n' # py <= 3.5 + ) + def test_serializer_filefield(self): path = '/{id}/' method = 'POST' From 124aef9b1ff2921fab983d7c269d330af6b4dbc3 Mon Sep 17 00:00:00 2001 From: Thorsten Franzel Date: Thu, 9 Jan 2020 13:43:41 +0100 Subject: [PATCH 2/3] Disable yaml aliases for generateschema --- rest_framework/renderers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 29ac90ea8e..7bec98cc5a 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -1053,6 +1053,8 @@ def __init__(self): assert yaml, 'Using OpenAPIRenderer, but `pyyaml` is not installed.' def render(self, data, media_type=None, renderer_context=None): + # disable yaml advanced feature 'alias' for clean, portable, and readable output + yaml.Dumper.ignore_aliases = lambda *args: True return yaml.dump(data, default_flow_style=False, sort_keys=False).encode('utf-8') From 49659a042743af4f37ae0a97e15843feb5deae54 Mon Sep 17 00:00:00 2001 From: Thorsten Franzel Date: Fri, 10 Jan 2020 12:39:26 +0100 Subject: [PATCH 3/3] use custom yaml dumper instead of changing global settings --- rest_framework/renderers.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 7bec98cc5a..a96fa6e65d 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -1054,8 +1054,10 @@ def __init__(self): def render(self, data, media_type=None, renderer_context=None): # disable yaml advanced feature 'alias' for clean, portable, and readable output - yaml.Dumper.ignore_aliases = lambda *args: True - return yaml.dump(data, default_flow_style=False, sort_keys=False).encode('utf-8') + class Dumper(yaml.Dumper): + def ignore_aliases(self, data): + return True + return yaml.dump(data, default_flow_style=False, sort_keys=False, Dumper=Dumper).encode('utf-8') class JSONOpenAPIRenderer(BaseRenderer):