Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(parsers): ignore sibling elements of $ref according to OpenAPI 3.0 specification #11

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions spec2sdk/parsers/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,14 @@ def resolve_reference(reference: str) -> dict:

return self._resolved_references[reference_id]

return {
new_key: new_value
for key, value in schema.items()
for new_key, new_value in (
resolve_reference(value) if key == "$ref" else {key: resolve_value(value)}
).items()
}
# Object containing $ref cannot be extended with additional properties
# and any properties added SHALL be ignored.
# https://spec.openapis.org/oas/v3.0.0.html#reference-object
return (
resolve_reference(schema["$ref"])
if "$ref" in schema
Comment on lines +74 to +76

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to ignore any extra properties silently or throw an exception when that happens?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to ignore extra properties. It's validator responsibility to raise an exception. Unfortunately, in our case validator runs after JSON schema resolving. This should be fixed in the future.

else {key: resolve_value(value) for key, value in schema.items()}
)

def parse(self, url: str) -> dict:
schema_loader = SchemaLoader(schema_url=url)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"components": {
"schemas": {
"HealthStatus": {
"description": "Schema description",
"properties": {
"status": {
"type": "string"
}
},
"type": "object"
}
}
},
"info": {
"title": "Example API",
"version": "1.0"
},
"openapi": "3.0.0",
"paths": {
"/health": {
"get": {
"operationId": "healthCheck",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"description": "Schema description",
"properties": {
"status": {
"type": "string"
}
},
"type": "object",
"x-schema-name": "HealthStatus"
}
}
},
"description": "Successful response"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
openapi: 3.0.0

info:
title: Example API
version: '1.0'

paths:
/health:
get:
operationId: healthCheck
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/HealthStatus'
description: Response content description
nullable: true

components:
schemas:
HealthStatus:
description: Schema description
type: object
properties:
status:
type: string
2 changes: 1 addition & 1 deletion tests/parsers/resolver/test_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
TEST_DATA_DIR = Path(__file__).parent / "test_data"


@pytest.mark.parametrize("test_data_name", ("local_references", "remote_references"))
@pytest.mark.parametrize("test_data_name", ("local_references", "remote_references", "references_with_siblings"))
def test_resolve_references(test_data_name: str):
data_dir = TEST_DATA_DIR / test_data_name
spec_path = data_dir / "input" / "api.yml"
Expand Down