This commit is contained in:
Iliyan Angelov
2025-09-19 11:58:53 +03:00
parent 306b20e24a
commit 6b247e5b9f
11423 changed files with 1500615 additions and 778 deletions

View File

@@ -0,0 +1,82 @@
from collections import OrderedDict
from datetime import time, timedelta
from decimal import Decimal
from uuid import UUID
import yaml
from django.utils.safestring import SafeString
from rest_framework.exceptions import ErrorDetail
from rest_framework.renderers import BaseRenderer, JSONRenderer
class OpenApiYamlRenderer(BaseRenderer):
media_type = 'application/vnd.oai.openapi'
format = 'yaml'
def render(self, data, accepted_media_type=None, renderer_context=None):
# disable yaml advanced feature 'alias' for clean, portable, and readable output
class Dumper(yaml.SafeDumper):
def ignore_aliases(self, data):
return True
def error_detail_representer(dumper, data):
return dumper.represent_dict({'string': str(data), 'code': data.code})
Dumper.add_representer(ErrorDetail, error_detail_representer)
def multiline_str_representer(dumper, data):
scalar = dumper.represent_str(data)
scalar.style = '|' if '\n' in data else None
return scalar
Dumper.add_representer(str, multiline_str_representer)
def decimal_representer(dumper, data):
# prevent emitting "!! float" tags on fractionless decimals
value = f'{data:f}'
if '.' in value:
return dumper.represent_scalar('tag:yaml.org,2002:float', value)
else:
return dumper.represent_scalar('tag:yaml.org,2002:int', value)
Dumper.add_representer(Decimal, decimal_representer)
def timedelta_representer(dumper, data):
return dumper.represent_str(str(data.total_seconds()))
Dumper.add_representer(timedelta, timedelta_representer)
def time_representer(dumper, data):
return dumper.represent_str(data.isoformat())
Dumper.add_representer(time, time_representer)
def uuid_representer(dumper, data):
return dumper.represent_str(str(data))
Dumper.add_representer(UUID, uuid_representer)
def safestring_representer(dumper, data):
return dumper.represent_str(data)
Dumper.add_representer(SafeString, safestring_representer)
def ordereddict_representer(dumper, data):
return dumper.represent_dict(dict(data))
Dumper.add_representer(OrderedDict, ordereddict_representer)
return yaml.dump(
data,
default_flow_style=False,
sort_keys=False,
allow_unicode=True,
Dumper=Dumper
).encode('utf-8')
class OpenApiYamlRenderer2(OpenApiYamlRenderer):
media_type = 'application/yaml'
class OpenApiJsonRenderer(JSONRenderer):
media_type = 'application/vnd.oai.openapi+json'
def get_indent(self, accepted_media_type, renderer_context):
return super().get_indent(accepted_media_type, renderer_context) or 4
class OpenApiJsonRenderer2(OpenApiJsonRenderer):
media_type = 'application/json'