Skip to content

Commit

Permalink
Add snapshot tests for OpenAPI schema generators.
Browse files Browse the repository at this point in the history
  • Loading branch information
surenkov committed Jan 4, 2024
1 parent 6a674cb commit f497411
Show file tree
Hide file tree
Showing 10 changed files with 905 additions and 15 deletions.
20 changes: 10 additions & 10 deletions django_pydantic_field/v2/rest_framework/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
import typing as ty

import pydantic
import weakref
from rest_framework import serializers
from rest_framework.schemas import openapi, utils as drf_schema_utils
from rest_framework.schemas import openapi
from rest_framework.schemas import utils as drf_schema_utils
from rest_framework.test import APIRequestFactory

from . import fields, parsers, renderers
from ..utils import get_origin_type

if ty.TYPE_CHECKING:
from collections.abc import Iterable
Expand Down Expand Up @@ -59,11 +60,12 @@ def get_request_body(self, path, method):
schema_content = {}

for parser, ct in zip(self.view.parser_classes, self.request_media_types):
if isinstance(parser(), parsers.SchemaParser):
if issubclass(get_origin_type(parser), parsers.SchemaParser):
parser_schema = self.collected_adapter_schema_refs[repr(parser)]
schema_content[ct] = {"schema": parser_schema}
else:
schema_content[ct] = request_schema
parser_schema = request_schema

schema_content[ct] = {"schema": parser_schema}

return {"content": schema_content}

Expand All @@ -84,7 +86,7 @@ def get_responses(self, path, method):

schema_content = {}
for renderer, ct in zip(self.view.renderer_classes, self.response_media_types):
if isinstance(renderer(), renderers.SchemaRenderer):
if issubclass(get_origin_type(renderer), renderers.SchemaRenderer):
renderer_schema = {"schema": self.collected_adapter_schema_refs[repr(renderer)]}
if is_list_view:
renderer_schema = self._get_paginated_schema(renderer_schema)
Expand All @@ -106,8 +108,7 @@ def map_parsers(self, path: str, method: str) -> list[str]:

for parser in self.view.parser_classes:
media_types.append(parser.media_type)
instance = parser()
if isinstance(instance, parsers.SchemaParser):
if issubclass(get_origin_type(parser), parsers.SchemaParser):
schema_parsers.append(parser)

if schema_parsers:
Expand All @@ -124,8 +125,7 @@ def map_renderers(self, path: str, method: str) -> list[str]:

for renderer in self.view.renderer_classes:
media_types.append(renderer.media_type)
instance = renderer()
if isinstance(instance, renderers.SchemaRenderer):
if issubclass(get_origin_type(renderer), renderers.SchemaRenderer):
schema_renderers.append(renderer)

if schema_renderers:
Expand Down
9 changes: 9 additions & 0 deletions django_pydantic_field/v2/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import typing as ty
from collections import ChainMap

from django_pydantic_field.compat import typing

if ty.TYPE_CHECKING:
from collections.abc import Mapping

Expand Down Expand Up @@ -39,6 +41,13 @@ def get_local_namespace(cls) -> dict[str, ty.Any]:
return {}


def get_origin_type(cls: type):
origin_tp = typing.get_origin(cls)
if origin_tp is not None:
return origin_tp
return cls


if sys.version_info >= (3, 9):

def evaluate_forward_ref(ref: ty.ForwardRef, ns: Mapping[str, ty.Any]) -> ty.Any:
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ test = [
"dj-database-url~=2.0",
"djangorestframework>=3,<4",
"pyyaml",
"syrupy>=3,<5",
]
ci = [
'psycopg[binary]>=3.1,<4; python_version>="3.9"',
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import typing as t
from datetime import date
from syrupy.extensions.json import JSONSnapshotExtension

import pydantic
import pytest
Expand Down Expand Up @@ -70,3 +71,8 @@ def mysql_backend(settings):
)
def available_database_backends(request, settings):
yield request.param(settings)


@pytest.fixture
def snapshot_json(snapshot):
return snapshot.use_extension(JSONSnapshotExtension)
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
{
"components": {
"schemas": {
"InnerSchema": {
"properties": {
"stub_int": {
"default": 1,
"title": "Stub Int",
"type": "integer"
},
"stub_list": {
"items": {
"format": "date",
"type": "string"
},
"title": "Stub List",
"type": "array"
},
"stub_str": {
"title": "Stub Str",
"type": "string"
}
},
"required": [
"stub_str",
"stub_list"
],
"title": "InnerSchema",
"type": "object"
},
"Sample": {
"properties": {
"field": {
"items": {
"$ref": "#/components/schemas/InnerSchema"
},
"type": "array"
}
},
"required": [
"field"
],
"type": "object"
}
}
},
"info": {
"title": "",
"version": ""
},
"openapi": "3.0.2",
"paths": {
"/class": {
"get": {
"description": "",
"operationId": "retrieveSample",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"$ref": "#/components/schemas/Sample"
},
"text/html": {
"$ref": "#/components/schemas/Sample"
}
},
"description": ""
}
},
"tags": [
"class"
]
},
"patch": {
"description": "",
"operationId": "partialUpdateSample",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Sample"
}
},
"application/x-www-form-urlencoded": {
"schema": {
"$ref": "#/components/schemas/Sample"
}
},
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/Sample"
}
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"$ref": "#/components/schemas/Sample"
},
"text/html": {
"$ref": "#/components/schemas/Sample"
}
},
"description": ""
}
},
"tags": [
"class"
]
},
"put": {
"description": "",
"operationId": "updateSample",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Sample"
}
},
"application/x-www-form-urlencoded": {
"schema": {
"$ref": "#/components/schemas/Sample"
}
},
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/Sample"
}
}
}
},
"responses": {
"200": {
"content": {
"application/json": {
"$ref": "#/components/schemas/Sample"
},
"text/html": {
"$ref": "#/components/schemas/Sample"
}
},
"description": ""
}
},
"tags": [
"class"
]
}
},
"/func": {
"get": {
"description": "",
"operationId": "listsample_views",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"items": {
"schema": {
"items": {
"$ref": "#/components/schemas/InnerSchema"
},
"type": "array"
}
},
"type": "array"
}
},
"description": ""
}
},
"tags": [
"func"
]
},
"post": {
"description": "",
"operationId": "createsample_view",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InnerSchema"
}
}
}
},
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/InnerSchema"
},
"type": "array"
}
}
},
"description": ""
}
},
"tags": [
"func"
]
}
}
}
}
Loading

0 comments on commit f497411

Please sign in to comment.