From 762467285c72fed16a854a7f932e51eb084ee913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=20V=C3=AEjdea?= Date: Mon, 14 Jan 2019 14:25:07 +0200 Subject: [PATCH] Keep dict key order for Python 3.7 --- src/drf_yasg/openapi.py | 4 ++-- src/drf_yasg/utils.py | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/drf_yasg/openapi.py b/src/drf_yasg/openapi.py index 51c526d..bfa13cd 100644 --- a/src/drf_yasg/openapi.py +++ b/src/drf_yasg/openapi.py @@ -10,7 +10,7 @@ from django.urls import get_script_prefix from django.utils.functional import Promise from inflection import camelize -from .utils import filter_none, force_real_str +from .utils import dict_has_ordered_keys, filter_none, force_real_str try: from collections import abc as collections_abc @@ -145,7 +145,7 @@ class SwaggerDict(OrderedDict): result = OrderedDict() memo[id(obj)] = result items = obj.items() - if not isinstance(obj, OrderedDict): + if not dict_has_ordered_keys(obj): items = sorted(items) for attr, val in items: result[attr] = SwaggerDict._as_odict(val, memo) diff --git a/src/drf_yasg/utils.py b/src/drf_yasg/utils.py index e69958d..dc8de25 100644 --- a/src/drf_yasg/utils.py +++ b/src/drf_yasg/utils.py @@ -1,5 +1,6 @@ import inspect import logging +import sys from collections import OrderedDict from django.db import models @@ -389,8 +390,7 @@ def get_produces(renderer_classes): def decimal_as_float(field): - """ - Returns true if ``field`` is a django-rest-framework DecimalField and its ``coerce_to_string`` attribute or the + """Returns true if ``field`` is a django-rest-framework DecimalField and its ``coerce_to_string`` attribute or the ``COERCE_DECIMAL_TO_STRING`` setting is set to ``False``. :rtype: bool @@ -401,8 +401,7 @@ def decimal_as_float(field): def get_serializer_ref_name(serializer): - """ - Get serializer's ref_name (or None for ModelSerializer if it is named 'NestedSerializer') + """Get serializer's ref_name (or None for ModelSerializer if it is named 'NestedSerializer') :param serializer: Serializer instance :return: Serializer's ``ref_name`` or ``None`` for inline serializer @@ -469,3 +468,16 @@ def get_field_default(field): default = serializers.empty return default + + +def dict_has_ordered_keys(obj): + """Check if a given object is a dict that maintains insertion order. + + :param obj: the dict object to check + :rtype: bool + """ + if sys.version_info >= (3, 7): + # the Python 3.7 language spec says that dict must maintain insertion order. + return isinstance(obj, dict) + + return isinstance(obj, OrderedDict)