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

Support OpenAPI 3.0.0 specs #621

Merged
merged 5 commits into from
Sep 11, 2018
Merged

Support OpenAPI 3.0.0 specs #621

merged 5 commits into from
Sep 11, 2018

Conversation

dtkav
Copy link
Collaborator

@dtkav dtkav commented Jul 11, 2018

Fixes #420

Changes proposed in this pull request:

  • support openapi version 3

Architecture:

  • creates an AbstractOperation class, which defines the interface for what an Operation is
  • Implements this interface with Swagger2Operation and OpenAPIOperation classes
  • apis/abstract.py uses the correct operation class based on the version of the spec

@coveralls
Copy link

coveralls commented Jul 11, 2018

Coverage Status

Coverage decreased (-0.6%) to 99.217% when pulling 1ccca75 on dtkav:oas3 into 86b5059 on zalando:dev-2.0.


func.assert_called_with(p1='123')


def test_query_sanitazion(query_sanitazion):
app_client = query_sanitazion.app.test_client()
l = LogCapture()
#l = LogCapture()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This tests is pretty nasty - I'm thinking of just removing it.

@@ -280,11 +290,13 @@ def test_nullable_parameter(simple_app):
'/v1.0/nullable-parameters?time_start={}'.format(time_start))
assert json.loads(resp.data.decode('utf-8', 'replace')) == time_start

resp = app_client.post('/v1.0/nullable-parameters', data={"post_param": 'None'})
assert json.loads(resp.data.decode('utf-8', 'replace')) == 'it was None'
# XXX this has not valid OAS3 equivalent as far as I can tell
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I could use help figuring out the correct behavior here.
It seems like there should be something that iterates through form parameters and replaces "null" or "None" with None? Does this need to be recursive? Is it only for form encoded request bodies? Can form parameters have recursive definitions, or are they guaranteed to be flat?

@dtkav dtkav mentioned this pull request Jul 11, 2018
connexion/operations/openapi.py Show resolved Hide resolved
connexion/operations/openapi.py Outdated Show resolved Hide resolved
@dtkav
Copy link
Collaborator Author

dtkav commented Jul 17, 2018

Another architecture improvement that would simplify the oas3 work in #627

@dtkav dtkav force-pushed the oas3 branch 4 times, most recently from 64d674d to d79ae00 Compare July 24, 2018 05:36
@dtkav dtkav force-pushed the oas3 branch 2 times, most recently from 975567a to 8ce099e Compare August 10, 2018 08:29
@dtkav dtkav force-pushed the dev-2.0 branch 2 times, most recently from 0621fb8 to 99ac95f Compare August 24, 2018 03:57
@dtkav dtkav changed the title WIP: support openapi spec version 3 Support openapi spec version 3 Aug 24, 2018
@dtkav dtkav changed the title Support openapi spec version 3 Support OpenAPI v3 Aug 24, 2018
@dtkav dtkav changed the title Support OpenAPI v3 Support OpenAPI 3.0.0 specs Aug 24, 2018
@dtkav dtkav changed the title Support OpenAPI 3.0.0 specs WIP: Support OpenAPI 3.0.0 specs Aug 27, 2018
@dtkav dtkav changed the title WIP: Support OpenAPI 3.0.0 specs Support OpenAPI 3.0.0 specs Aug 29, 2018
spec_params = self.schema.get('properties', {}).keys()
return validate_parameter_list(request_params, spec_params)

def coerce_types(self, param_schema, value, parameter_name=None):
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think I can refactor this code out a bit.

Copy link
Contributor

@ioggstream ioggstream left a comment

Choose a reason for hiding this comment

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

Generally ok! Minor fixes proposed.

@@ -150,6 +157,13 @@ def _set_base_path(self, base_path):
# type: (AnyStr) -> None
if base_path is None:
self.base_path = canonical_base_path(self.specification.get('basePath', ''))
if self.spec_version >= (3, 0, 0):
Copy link
Contributor

Choose a reason for hiding this comment

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

You have already checked the spec_version. Why not delegate to a validate_spec method?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sorry, I'm not sure what you are suggesting here. Could you elaborate?
Technically this version check doesn't actually need to be here (the servers field won't exist in any valid swagger 2 specs), but it is more explicit. I'm trying not to just casually mix swagger2/openapi3 specific code. Most of that separation happens in the Swagger2Operation/OpenAPIOperation classes, but this is one of the few places in AbstractAPI that needs to be "version aware" in order to maintain the current API.

try:
version_string = spec.get('openapi') or spec.get('swagger')
except AttributeError:
raise InvalidSpecification('Unable to get spec version')
Copy link
Contributor

Choose a reason for hiding this comment

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

Show the bad string

raise XXXException("Unable to get spec version from: %r" % spec)

Copy link
Collaborator Author

@dtkav dtkav Sep 11, 2018

Choose a reason for hiding this comment

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

I disagree with this one. If we get this exception, then it means we couldn't find either of openapi / swagger keys in the spec. Printing the whole spec here may dump several pages of text to their terminal, and it won't be useful because it won't show them the absence of the required field.
I'll happily make this error more verbose though - let me know if that would address your concern.

connexion/decorators/uri_parsing.py Outdated Show resolved Hide resolved
connexion/apis/abstract.py Show resolved Hide resolved
connexion/apis/abstract.py Outdated Show resolved Hide resolved
@dtkav
Copy link
Collaborator Author

dtkav commented Sep 11, 2018

I'm going to to ahead and merge this (yay!), but it will only be in dev-2.0, so I'm happy to continue to address suggestions and fixes there. We'll make sure that branch is rock solid cutting the next major release.

FYI the Codacy problems are due to the use of "assert" in the new unit tests. I've added a separate PR to remove those codacy checks.

@dtkav dtkav merged commit d263417 into spec-first:dev-2.0 Sep 11, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants