We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
List ChoiceField choices in Swagger as enum
### Environment
* Python version:  3.7.3
* NetBox version:  2.7.2

### Proposed Functionality

Based on this specification https://swagger.io/docs/specification/data-models/enums/ the ChoiceField choices for label and value can (and should) be listed as enums.

### Use Case

Proper generation of API model from openapi specification for 3rd party projects without requirement to query OPTIONS for each endpoint to receive extra data from django. For example we are generating Java API for Netbox based on openapi spec from Netbox. Also having the choices listed on api/docs Swagger UI is very helpful when browsing through the API docs.

### Database Changes

None

### External Dependencies

None

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `netbox/utilities/custom_inspectors.py`
Content:
```
1 from django.contrib.postgres.fields import JSONField
2 from drf_yasg import openapi
3 from drf_yasg.inspectors import FieldInspector, NotHandled, PaginatorInspector, FilterInspector, SwaggerAutoSchema
4 from drf_yasg.utils import get_serializer_ref_name
5 from rest_framework.fields import ChoiceField
6 from rest_framework.relations import ManyRelatedField
7 from taggit_serializer.serializers import TagListSerializerField
8 
9 from dcim.api.serializers import InterfaceSerializer as DeviceInterfaceSerializer
10 from extras.api.customfields import CustomFieldsSerializer
11 from utilities.api import ChoiceField, SerializedPKRelatedField, WritableNestedSerializer
12 from virtualization.api.serializers import InterfaceSerializer as VirtualMachineInterfaceSerializer
13 
14 # this might be ugly, but it limits drf_yasg-specific code to this file
15 DeviceInterfaceSerializer.Meta.ref_name = 'DeviceInterface'
16 VirtualMachineInterfaceSerializer.Meta.ref_name = 'VirtualMachineInterface'
17 
18 
19 class NetBoxSwaggerAutoSchema(SwaggerAutoSchema):
20     writable_serializers = {}
21 
22     def get_request_serializer(self):
23         serializer = super().get_request_serializer()
24 
25         if serializer is not None and self.method in self.implicit_body_methods:
26             properties = {}
27             for child_name, child in serializer.fields.items():
28                 if isinstance(child, (ChoiceField, WritableNestedSerializer)):
29                     properties[child_name] = None
30                 elif isinstance(child, ManyRelatedField) and isinstance(child.child_relation, SerializedPKRelatedField):
31                     properties[child_name] = None
32 
33             if properties:
34                 if type(serializer) not in self.writable_serializers:
35                     writable_name = 'Writable' + type(serializer).__name__
36                     meta_class = getattr(type(serializer), 'Meta', None)
37                     if meta_class:
38                         ref_name = 'Writable' + get_serializer_ref_name(serializer)
39                         writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name})
40                         properties['Meta'] = writable_meta
41 
42                     self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties)
43 
44                 writable_class = self.writable_serializers[type(serializer)]
45                 serializer = writable_class()
46 
47         return serializer
48 
49 
50 class SerializedPKRelatedFieldInspector(FieldInspector):
51     def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):
52         SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)
53         if isinstance(field, SerializedPKRelatedField):
54             return self.probe_field_inspectors(field.serializer(), ChildSwaggerType, use_references)
55 
56         return NotHandled
57 
58 
59 class TagListFieldInspector(FieldInspector):
60     def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):
61         SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)
62         if isinstance(field, TagListSerializerField):
63             child_schema = self.probe_field_inspectors(field.child, ChildSwaggerType, use_references)
64             return SwaggerType(
65                 type=openapi.TYPE_ARRAY,
66                 items=child_schema,
67             )
68 
69         return NotHandled
70 
71 
72 class CustomChoiceFieldInspector(FieldInspector):
73     def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):
74         # this returns a callable which extracts title, description and other stuff
75         # https://drf-yasg.readthedocs.io/en/stable/_modules/drf_yasg/inspectors/base.html#FieldInspector._get_partial_types
76         SwaggerType, _ = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)
77 
78         if isinstance(field, ChoiceField):
79             value_schema = openapi.Schema(type=openapi.TYPE_STRING)
80 
81             choices = list(field._choices.keys())
82             if set([None] + choices) == {None, True, False}:
83                 # DeviceType.subdevice_role, Device.face and InterfaceConnection.connection_status all need to be
84                 # differentiated since they each have subtly different values in their choice keys.
85                 # - subdevice_role and connection_status are booleans, although subdevice_role includes None
86                 # - face is an integer set {0, 1} which is easily confused with {False, True}
87                 schema_type = openapi.TYPE_STRING
88                 if all(type(x) == bool for x in [c for c in choices if c is not None]):
89                     schema_type = openapi.TYPE_BOOLEAN
90                 value_schema = openapi.Schema(type=schema_type)
91                 value_schema['x-nullable'] = True
92 
93             if isinstance(choices[0], int):
94                 # Change value_schema for IPAddressFamilyChoices, RackWidthChoices
95                 value_schema = openapi.Schema(type=openapi.TYPE_INTEGER)
96 
97             schema = SwaggerType(type=openapi.TYPE_OBJECT, required=["label", "value"], properties={
98                 "label": openapi.Schema(type=openapi.TYPE_STRING),
99                 "value": value_schema
100             })
101 
102             return schema
103 
104         elif isinstance(field, CustomFieldsSerializer):
105             schema = SwaggerType(type=openapi.TYPE_OBJECT)
106             return schema
107 
108         return NotHandled
109 
110 
111 class NullableBooleanFieldInspector(FieldInspector):
112     def process_result(self, result, method_name, obj, **kwargs):
113 
114         if isinstance(result, openapi.Schema) and isinstance(obj, ChoiceField) and result.type == 'boolean':
115             keys = obj.choices.keys()
116             if set(keys) == {None, True, False}:
117                 result['x-nullable'] = True
118                 result.type = 'boolean'
119 
120         return result
121 
122 
123 class JSONFieldInspector(FieldInspector):
124     """Required because by default, Swagger sees a JSONField as a string and not dict
125     """
126     def process_result(self, result, method_name, obj, **kwargs):
127         if isinstance(result, openapi.Schema) and isinstance(obj, JSONField):
128             result.type = 'dict'
129         return result
130 
131 
132 class IdInFilterInspector(FilterInspector):
133     def process_result(self, result, method_name, obj, **kwargs):
134         if isinstance(result, list):
135             params = [p for p in result if isinstance(p, openapi.Parameter) and p.name == 'id__in']
136             for p in params:
137                 p.type = 'string'
138 
139         return result
140 
141 
142 class NullablePaginatorInspector(PaginatorInspector):
143     def process_result(self, result, method_name, obj, **kwargs):
144         if method_name == 'get_paginated_response' and isinstance(result, openapi.Schema):
145             next = result.properties['next']
146             if isinstance(next, openapi.Schema):
147                 next['x-nullable'] = True
148             previous = result.properties['previous']
149             if isinstance(previous, openapi.Schema):
150                 previous['x-nullable'] = True
151 
152         return result
153
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/netbox/utilities/custom_inspectors.py b/netbox/utilities/custom_inspectors.py
--- a/netbox/utilities/custom_inspectors.py
+++ b/netbox/utilities/custom_inspectors.py
@@ -76,26 +76,28 @@
         SwaggerType, _ = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)
 
         if isinstance(field, ChoiceField):
-            value_schema = openapi.Schema(type=openapi.TYPE_STRING)
+            choices = field._choices
+            choice_value = list(choices.keys())
+            choice_label = list(choices.values())
+            value_schema = openapi.Schema(type=openapi.TYPE_STRING, enum=choice_value)
 
-            choices = list(field._choices.keys())
-            if set([None] + choices) == {None, True, False}:
+            if set([None] + choice_value) == {None, True, False}:
                 # DeviceType.subdevice_role, Device.face and InterfaceConnection.connection_status all need to be
                 # differentiated since they each have subtly different values in their choice keys.
                 # - subdevice_role and connection_status are booleans, although subdevice_role includes None
                 # - face is an integer set {0, 1} which is easily confused with {False, True}
                 schema_type = openapi.TYPE_STRING
-                if all(type(x) == bool for x in [c for c in choices if c is not None]):
+                if all(type(x) == bool for x in [c for c in choice_value if c is not None]):
                     schema_type = openapi.TYPE_BOOLEAN
-                value_schema = openapi.Schema(type=schema_type)
+                value_schema = openapi.Schema(type=schema_type, enum=choice_value)
                 value_schema['x-nullable'] = True
 
-            if isinstance(choices[0], int):
+            if isinstance(choice_value[0], int):
                 # Change value_schema for IPAddressFamilyChoices, RackWidthChoices
-                value_schema = openapi.Schema(type=openapi.TYPE_INTEGER)
+                value_schema = openapi.Schema(type=openapi.TYPE_INTEGER, enum=choice_value)
 
             schema = SwaggerType(type=openapi.TYPE_OBJECT, required=["label", "value"], properties={
-                "label": openapi.Schema(type=openapi.TYPE_STRING),
+                "label": openapi.Schema(type=openapi.TYPE_STRING, enum=choice_label),
                 "value": value_schema
             })

{"golden_diff": "diff --git a/netbox/utilities/custom_inspectors.py b/netbox/utilities/custom_inspectors.py\n--- a/netbox/utilities/custom_inspectors.py\n+++ b/netbox/utilities/custom_inspectors.py\n@@ -76,26 +76,28 @@\n         SwaggerType, _ = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)\n \n         if isinstance(field, ChoiceField):\n-            value_schema = openapi.Schema(type=openapi.TYPE_STRING)\n+            choices = field._choices\n+            choice_value = list(choices.keys())\n+            choice_label = list(choices.values())\n+            value_schema = openapi.Schema(type=openapi.TYPE_STRING, enum=choice_value)\n \n-            choices = list(field._choices.keys())\n-            if set([None] + choices) == {None, True, False}:\n+            if set([None] + choice_value) == {None, True, False}:\n                 # DeviceType.subdevice_role, Device.face and InterfaceConnection.connection_status all need to be\n                 # differentiated since they each have subtly different values in their choice keys.\n                 # - subdevice_role and connection_status are booleans, although subdevice_role includes None\n                 # - face is an integer set {0, 1} which is easily confused with {False, True}\n                 schema_type = openapi.TYPE_STRING\n-                if all(type(x) == bool for x in [c for c in choices if c is not None]):\n+                if all(type(x) == bool for x in [c for c in choice_value if c is not None]):\n                     schema_type = openapi.TYPE_BOOLEAN\n-                value_schema = openapi.Schema(type=schema_type)\n+                value_schema = openapi.Schema(type=schema_type, enum=choice_value)\n                 value_schema['x-nullable'] = True\n \n-            if isinstance(choices[0], int):\n+            if isinstance(choice_value[0], int):\n                 # Change value_schema for IPAddressFamilyChoices, RackWidthChoices\n-                value_schema = openapi.Schema(type=openapi.TYPE_INTEGER)\n+                value_schema = openapi.Schema(type=openapi.TYPE_INTEGER, enum=choice_value)\n \n             schema = SwaggerType(type=openapi.TYPE_OBJECT, required=[\"label\", \"value\"], properties={\n-                \"label\": openapi.Schema(type=openapi.TYPE_STRING),\n+                \"label\": openapi.Schema(type=openapi.TYPE_STRING, enum=choice_label),\n                 \"value\": value_schema\n             })\n", "issue": "List ChoiceField choices in Swagger as enum\n### Environment\r\n* Python version:  3.7.3\r\n* NetBox version:  2.7.2\r\n\r\n### Proposed Functionality\r\n\r\nBased on this specification https://swagger.io/docs/specification/data-models/enums/ the ChoiceField choices for label and value can (and should) be listed as enums.\r\n\r\n### Use Case\r\n\r\nProper generation of API model from openapi specification for 3rd party projects without requirement to query OPTIONS for each endpoint to receive extra data from django. For example we are generating Java API for Netbox based on openapi spec from Netbox. Also having the choices listed on api/docs Swagger UI is very helpful when browsing through the API docs.\r\n\r\n### Database Changes\r\n\r\nNone\r\n\r\n### External Dependencies\r\n\r\nNone\n", "before_files": [{"content": "from django.contrib.postgres.fields import JSONField\nfrom drf_yasg import openapi\nfrom drf_yasg.inspectors import FieldInspector, NotHandled, PaginatorInspector, FilterInspector, SwaggerAutoSchema\nfrom drf_yasg.utils import get_serializer_ref_name\nfrom rest_framework.fields import ChoiceField\nfrom rest_framework.relations import ManyRelatedField\nfrom taggit_serializer.serializers import TagListSerializerField\n\nfrom dcim.api.serializers import InterfaceSerializer as DeviceInterfaceSerializer\nfrom extras.api.customfields import CustomFieldsSerializer\nfrom utilities.api import ChoiceField, SerializedPKRelatedField, WritableNestedSerializer\nfrom virtualization.api.serializers import InterfaceSerializer as VirtualMachineInterfaceSerializer\n\n# this might be ugly, but it limits drf_yasg-specific code to this file\nDeviceInterfaceSerializer.Meta.ref_name = 'DeviceInterface'\nVirtualMachineInterfaceSerializer.Meta.ref_name = 'VirtualMachineInterface'\n\n\nclass NetBoxSwaggerAutoSchema(SwaggerAutoSchema):\n    writable_serializers = {}\n\n    def get_request_serializer(self):\n        serializer = super().get_request_serializer()\n\n        if serializer is not None and self.method in self.implicit_body_methods:\n            properties = {}\n            for child_name, child in serializer.fields.items():\n                if isinstance(child, (ChoiceField, WritableNestedSerializer)):\n                    properties[child_name] = None\n                elif isinstance(child, ManyRelatedField) and isinstance(child.child_relation, SerializedPKRelatedField):\n                    properties[child_name] = None\n\n            if properties:\n                if type(serializer) not in self.writable_serializers:\n                    writable_name = 'Writable' + type(serializer).__name__\n                    meta_class = getattr(type(serializer), 'Meta', None)\n                    if meta_class:\n                        ref_name = 'Writable' + get_serializer_ref_name(serializer)\n                        writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name})\n                        properties['Meta'] = writable_meta\n\n                    self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties)\n\n                writable_class = self.writable_serializers[type(serializer)]\n                serializer = writable_class()\n\n        return serializer\n\n\nclass SerializedPKRelatedFieldInspector(FieldInspector):\n    def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):\n        SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)\n        if isinstance(field, SerializedPKRelatedField):\n            return self.probe_field_inspectors(field.serializer(), ChildSwaggerType, use_references)\n\n        return NotHandled\n\n\nclass TagListFieldInspector(FieldInspector):\n    def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):\n        SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)\n        if isinstance(field, TagListSerializerField):\n            child_schema = self.probe_field_inspectors(field.child, ChildSwaggerType, use_references)\n            return SwaggerType(\n                type=openapi.TYPE_ARRAY,\n                items=child_schema,\n            )\n\n        return NotHandled\n\n\nclass CustomChoiceFieldInspector(FieldInspector):\n    def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):\n        # this returns a callable which extracts title, description and other stuff\n        # https://drf-yasg.readthedocs.io/en/stable/_modules/drf_yasg/inspectors/base.html#FieldInspector._get_partial_types\n        SwaggerType, _ = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)\n\n        if isinstance(field, ChoiceField):\n            value_schema = openapi.Schema(type=openapi.TYPE_STRING)\n\n            choices = list(field._choices.keys())\n            if set([None] + choices) == {None, True, False}:\n                # DeviceType.subdevice_role, Device.face and InterfaceConnection.connection_status all need to be\n                # differentiated since they each have subtly different values in their choice keys.\n                # - subdevice_role and connection_status are booleans, although subdevice_role includes None\n                # - face is an integer set {0, 1} which is easily confused with {False, True}\n                schema_type = openapi.TYPE_STRING\n                if all(type(x) == bool for x in [c for c in choices if c is not None]):\n                    schema_type = openapi.TYPE_BOOLEAN\n                value_schema = openapi.Schema(type=schema_type)\n                value_schema['x-nullable'] = True\n\n            if isinstance(choices[0], int):\n                # Change value_schema for IPAddressFamilyChoices, RackWidthChoices\n                value_schema = openapi.Schema(type=openapi.TYPE_INTEGER)\n\n            schema = SwaggerType(type=openapi.TYPE_OBJECT, required=[\"label\", \"value\"], properties={\n                \"label\": openapi.Schema(type=openapi.TYPE_STRING),\n                \"value\": value_schema\n            })\n\n            return schema\n\n        elif isinstance(field, CustomFieldsSerializer):\n            schema = SwaggerType(type=openapi.TYPE_OBJECT)\n            return schema\n\n        return NotHandled\n\n\nclass NullableBooleanFieldInspector(FieldInspector):\n    def process_result(self, result, method_name, obj, **kwargs):\n\n        if isinstance(result, openapi.Schema) and isinstance(obj, ChoiceField) and result.type == 'boolean':\n            keys = obj.choices.keys()\n            if set(keys) == {None, True, False}:\n                result['x-nullable'] = True\n                result.type = 'boolean'\n\n        return result\n\n\nclass JSONFieldInspector(FieldInspector):\n    \"\"\"Required because by default, Swagger sees a JSONField as a string and not dict\n    \"\"\"\n    def process_result(self, result, method_name, obj, **kwargs):\n        if isinstance(result, openapi.Schema) and isinstance(obj, JSONField):\n            result.type = 'dict'\n        return result\n\n\nclass IdInFilterInspector(FilterInspector):\n    def process_result(self, result, method_name, obj, **kwargs):\n        if isinstance(result, list):\n            params = [p for p in result if isinstance(p, openapi.Parameter) and p.name == 'id__in']\n            for p in params:\n                p.type = 'string'\n\n        return result\n\n\nclass NullablePaginatorInspector(PaginatorInspector):\n    def process_result(self, result, method_name, obj, **kwargs):\n        if method_name == 'get_paginated_response' and isinstance(result, openapi.Schema):\n            next = result.properties['next']\n            if isinstance(next, openapi.Schema):\n                next['x-nullable'] = True\n            previous = result.properties['previous']\n            if isinstance(previous, openapi.Schema):\n                previous['x-nullable'] = True\n\n        return result\n", "path": "netbox/utilities/custom_inspectors.py"}], "after_files": [{"content": "from django.contrib.postgres.fields import JSONField\nfrom drf_yasg import openapi\nfrom drf_yasg.inspectors import FieldInspector, NotHandled, PaginatorInspector, FilterInspector, SwaggerAutoSchema\nfrom drf_yasg.utils import get_serializer_ref_name\nfrom rest_framework.fields import ChoiceField\nfrom rest_framework.relations import ManyRelatedField\nfrom taggit_serializer.serializers import TagListSerializerField\n\nfrom dcim.api.serializers import InterfaceSerializer as DeviceInterfaceSerializer\nfrom extras.api.customfields import CustomFieldsSerializer\nfrom utilities.api import ChoiceField, SerializedPKRelatedField, WritableNestedSerializer\nfrom virtualization.api.serializers import InterfaceSerializer as VirtualMachineInterfaceSerializer\n\n# this might be ugly, but it limits drf_yasg-specific code to this file\nDeviceInterfaceSerializer.Meta.ref_name = 'DeviceInterface'\nVirtualMachineInterfaceSerializer.Meta.ref_name = 'VirtualMachineInterface'\n\n\nclass NetBoxSwaggerAutoSchema(SwaggerAutoSchema):\n    writable_serializers = {}\n\n    def get_request_serializer(self):\n        serializer = super().get_request_serializer()\n\n        if serializer is not None and self.method in self.implicit_body_methods:\n            properties = {}\n            for child_name, child in serializer.fields.items():\n                if isinstance(child, (ChoiceField, WritableNestedSerializer)):\n                    properties[child_name] = None\n                elif isinstance(child, ManyRelatedField) and isinstance(child.child_relation, SerializedPKRelatedField):\n                    properties[child_name] = None\n\n            if properties:\n                if type(serializer) not in self.writable_serializers:\n                    writable_name = 'Writable' + type(serializer).__name__\n                    meta_class = getattr(type(serializer), 'Meta', None)\n                    if meta_class:\n                        ref_name = 'Writable' + get_serializer_ref_name(serializer)\n                        writable_meta = type('Meta', (meta_class,), {'ref_name': ref_name})\n                        properties['Meta'] = writable_meta\n\n                    self.writable_serializers[type(serializer)] = type(writable_name, (type(serializer),), properties)\n\n                writable_class = self.writable_serializers[type(serializer)]\n                serializer = writable_class()\n\n        return serializer\n\n\nclass SerializedPKRelatedFieldInspector(FieldInspector):\n    def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):\n        SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)\n        if isinstance(field, SerializedPKRelatedField):\n            return self.probe_field_inspectors(field.serializer(), ChildSwaggerType, use_references)\n\n        return NotHandled\n\n\nclass TagListFieldInspector(FieldInspector):\n    def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):\n        SwaggerType, ChildSwaggerType = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)\n        if isinstance(field, TagListSerializerField):\n            child_schema = self.probe_field_inspectors(field.child, ChildSwaggerType, use_references)\n            return SwaggerType(\n                type=openapi.TYPE_ARRAY,\n                items=child_schema,\n            )\n\n        return NotHandled\n\n\nclass CustomChoiceFieldInspector(FieldInspector):\n    def field_to_swagger_object(self, field, swagger_object_type, use_references, **kwargs):\n        # this returns a callable which extracts title, description and other stuff\n        # https://drf-yasg.readthedocs.io/en/stable/_modules/drf_yasg/inspectors/base.html#FieldInspector._get_partial_types\n        SwaggerType, _ = self._get_partial_types(field, swagger_object_type, use_references, **kwargs)\n\n        if isinstance(field, ChoiceField):\n            choices = field._choices\n            choice_value = list(choices.keys())\n            choice_label = list(choices.values())\n            value_schema = openapi.Schema(type=openapi.TYPE_STRING, enum=choice_value)\n\n            if set([None] + choice_value) == {None, True, False}:\n                # DeviceType.subdevice_role, Device.face and InterfaceConnection.connection_status all need to be\n                # differentiated since they each have subtly different values in their choice keys.\n                # - subdevice_role and connection_status are booleans, although subdevice_role includes None\n                # - face is an integer set {0, 1} which is easily confused with {False, True}\n                schema_type = openapi.TYPE_STRING\n                if all(type(x) == bool for x in [c for c in choice_value if c is not None]):\n                    schema_type = openapi.TYPE_BOOLEAN\n                value_schema = openapi.Schema(type=schema_type, enum=choice_value)\n                value_schema['x-nullable'] = True\n\n            if isinstance(choice_value[0], int):\n                # Change value_schema for IPAddressFamilyChoices, RackWidthChoices\n                value_schema = openapi.Schema(type=openapi.TYPE_INTEGER, enum=choice_value)\n\n            schema = SwaggerType(type=openapi.TYPE_OBJECT, required=[\"label\", \"value\"], properties={\n                \"label\": openapi.Schema(type=openapi.TYPE_STRING, enum=choice_label),\n                \"value\": value_schema\n            })\n\n            return schema\n\n        elif isinstance(field, CustomFieldsSerializer):\n            schema = SwaggerType(type=openapi.TYPE_OBJECT)\n            return schema\n\n        return NotHandled\n\n\nclass NullableBooleanFieldInspector(FieldInspector):\n    def process_result(self, result, method_name, obj, **kwargs):\n\n        if isinstance(result, openapi.Schema) and isinstance(obj, ChoiceField) and result.type == 'boolean':\n            keys = obj.choices.keys()\n            if set(keys) == {None, True, False}:\n                result['x-nullable'] = True\n                result.type = 'boolean'\n\n        return result\n\n\nclass JSONFieldInspector(FieldInspector):\n    \"\"\"Required because by default, Swagger sees a JSONField as a string and not dict\n    \"\"\"\n    def process_result(self, result, method_name, obj, **kwargs):\n        if isinstance(result, openapi.Schema) and isinstance(obj, JSONField):\n            result.type = 'dict'\n        return result\n\n\nclass IdInFilterInspector(FilterInspector):\n    def process_result(self, result, method_name, obj, **kwargs):\n        if isinstance(result, list):\n            params = [p for p in result if isinstance(p, openapi.Parameter) and p.name == 'id__in']\n            for p in params:\n                p.type = 'string'\n\n        return result\n\n\nclass NullablePaginatorInspector(PaginatorInspector):\n    def process_result(self, result, method_name, obj, **kwargs):\n        if method_name == 'get_paginated_response' and isinstance(result, openapi.Schema):\n            next = result.properties['next']\n            if isinstance(next, openapi.Schema):\n                next['x-nullable'] = True\n            previous = result.properties['previous']\n            if isinstance(previous, openapi.Schema):\n                previous['x-nullable'] = True\n\n        return result\n", "path": "netbox/utilities/custom_inspectors.py"}]}