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

removes passing reference paths in nested field metadata #363

Merged
merged 2 commits into from
Feb 3, 2019

Conversation

Bangertm
Copy link
Collaborator

field2property now ignores a ref key in field metadata and relies
only on the field autoreferencing capability

Self referencing instances of marshmallow.fields.Nested that are
unbound cannot be passed to field2property, which means that the
schema argument of OpenAPI.schema2jsonschema and
OpenAPI.schema2parameters must be a schema instance and not a
schema class

del parameter['schema']
resolved += self.openapi.schema2parameters(
schema_cls,
schema_instance,
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 change is to prevent a schema like SelfReferencingSchema passed as a query string parameter from throwing an error due to unbound nested self referencing fields. It is not valid to have a self referencing schema in that location, but at least it doesn't throw an error.

@Bangertm Bangertm force-pushed the remove-metadata-references branch from 855909a to acf318b Compare January 25, 2019 21:12
@lafrech lafrech self-requested a review January 27, 2019 16:09
Copy link
Member

@lafrech lafrech left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks.

@lafrech
Copy link
Member

lafrech commented Jan 27, 2019

Some tests fail. From a quick look, it is due to an undeterministic order. I relaunched py37-marshmallow2 after the failure and it passed.

I don't understand how it is related to this change and why it used to work, I don't have much time to look at it right now, but I think the order doesn't matter and the test could be modified to not rely on the order.

@lafrech
Copy link
Member

lafrech commented Jan 27, 2019

Hint: I think making PetSchema ordered would solve this.

class PetSchema(Schema):

    class Meta:
        ordered = True

I'd still be interested to understand what changed in this PR that triggered this.

@Bangertm
Copy link
Collaborator Author

I think it has to be the change from using the schema class to using an instance that I referenced above. Not sure what the mechanism would be though.

I could just back out that change. The end result of having nested fields in a query string location is invalid by definition. So we could (should?) just raise an error if an invalid field is in a query location. We already kind of do that with many=True:

assert not getattr(schema, 'many', False), \
"Schemas with many=True are only supported for 'json' location (aka 'in: body')"

We can just add a check for invalid fields in a query location such as Nested, List and Dict.

@lafrech
Copy link
Member

lafrech commented Jan 28, 2019

I think you can have a Nested field in a query location if you use a custom parser such as the NestedQueryFlaskParser here.

Or maybe I'm confused.

@Bangertm
Copy link
Collaborator Author

This looks like a change between OpenAPI v2 and v3. In v2 only primitive types are supported:

Query parameters only support primitive types. You can have an array, but the items must be a primitive value type. Objects are not supported.

In v3 they can be objects:

Query parameters can be primitive values, arrays and objects.

In which case, nesting is perfectly fine. Sorting this out is probably going to take a little more thought.

I noticed that other tests are using res.sort(key=lambda param: param['name'])

def test_schema_query_instance(self, openapi):
class UserSchema(Schema):
name = fields.Str()
email = fields.Email()
res = openapi.schema2parameters(UserSchema(), default_in='query')
assert len(res) == 2
res.sort(key=lambda param: param['name'])
assert res[0]['name'] == 'email'
assert res[0]['in'] == 'query'
assert res[1]['name'] == 'name'
assert res[1]['in'] == 'query'

So I can probably do that too.

@Bangertm Bangertm force-pushed the remove-metadata-references branch from 0e1264b to f617648 Compare January 28, 2019 17:05
@lafrech
Copy link
Member

lafrech commented Jan 28, 2019

TBH, I never even wondered if this was OpenAPI compliant... Shame on me. Let's be permissive and don't force the user to be compliant, especially if something is acceptable in v3 and not in v2.

res.sort(key=lambda param: param['name'])

is fine as well. More explicit than the Meta approach.

@Bangertm
Copy link
Collaborator Author

Forgot to look at the failing test before commenting just instancing PetSchema on as in input to schema2parameters on the expected value is good enough to eliminate the problem.

I think there is something not quite right about the nested query string parameters are handled, but it's also likely to be a relatively uncommon use case.

@sloria sloria added this to the 1.0 milestone Jan 29, 2019
field2property now ignores a ref key in field metadata and relies
only on the field autoreferencing capability

Self referencing instances of `marshmallow.fields.Nested` that are
unbound cannot be passed to field2property, which means that the
`schema` argument of `OpenAPI.schema2jsonschema` and
`OpenAPI.schema2parameters` must be a schema instance and not a
schema class
@Bangertm Bangertm force-pushed the remove-metadata-references branch from f617648 to 88eba0f Compare January 31, 2019 21:12
@lafrech
Copy link
Member

lafrech commented Feb 1, 2019

OK, I don't understand why passing an instance solves the problem but as long as it does...

Should we specify in OpenAPI.schema2jsonschema and OpenAPI.schema2parameters that only instances are accepted?

@sloria
Copy link
Member

sloria commented Feb 3, 2019

Should we specify in OpenAPI.schema2jsonschema and OpenAPI.schema2parameters that only instances are accepted?

Looks like @Bangertm already did that for schema2jsonschema.

:param Schema schema: A marshmallow Schema instance

Would be good to document that for schema2parameters as well, but it's not a blocker to merging.

@sloria sloria merged commit 35287af into marshmallow-code:dev Feb 3, 2019
@sloria
Copy link
Member

sloria commented Feb 3, 2019

@Bangertm @lafrech All issues and PRs for 1.0 have been resolved! 🎉 I think we're good to release. Unless there are any objections, I'll plan to release 1.0 in the next day or two. 🚢 🇮🇹

@lafrech
Copy link
Member

lafrech commented Feb 4, 2019

Great. I'm also eager to get this released.

I couldn't help but proposing a last-minute breaking change: #381.

@lafrech
Copy link
Member

lafrech commented Feb 6, 2019

Guys, I've been trying the latest apispec revision on a huge project of ours to identify potential issues before we release.

I've been spending a great deal of time diving into (my own) legacy spaghetti code dealing with pathological cases of auto-generated inheritance schemas that would generate all kinds of errors and warnings. The code is now a mess, but I think I'm done with the test and I got it to work by simply overriding MarshmallowPlugin.schema_helper and passing a custom schema_name_resolver, which is how this is intended to work.

This means I validate it works in my use case. In fact, the auto-registration feature will allow me to remove a lot of code that will become useless. Great. Thanks again @Bangertm for the work on this.

I wanted to conclude that this is good to go, but there's #383 I didn't have the time to investigate.

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.

3 participants