Skip to content

feat: Serialize model query parameters with style=form, explode=true BNCH-18023 #39

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

Merged
merged 2 commits into from
Jan 27, 2021

Conversation

forest-benchling
Copy link

@forest-benchling forest-benchling commented Jan 26, 2021

Fixes openapi-generators#295.

Upstream PR: openapi-generators#316

When I pulled this change into openapi-specs and made the changes in https://github.com/benchling/openapi-specs/pull/138, the generated code looked like this:

def _get_kwargs(
    *,
    client: Client,
    next_token: Union[Unset, None, str] = UNSET,
    page_size: Union[Unset, None, int] = 50,
    sort: Union[Unset, None, ListCustomEntitiesSort] = ListCustomEntitiesSort.MODIFIEDATDESC,
    modified_at: Union[Unset, None, str] = UNSET,
    name: Union[Unset, None, str] = UNSET,
    name_includes: Union[Unset, None, str] = UNSET,
    folder_id: Union[Unset, None, str] = UNSET,
    mentioned_in: Union[Unset, None, List[str]] = UNSET,
    project_id: Union[Unset, None, str] = UNSET,
    registry_id: Union[Unset, None, str] = UNSET,
    schema_id: Union[Unset, None, str] = UNSET,
    schema_field: Union[Unset, None, ListCustomEntitiesSchemaField] = UNSET,
    archive_reason: Union[Unset, None, str] = UNSET,
    mentions: Union[Unset, None, List[str]] = UNSET,
    ids: Union[Unset, None, str] = UNSET,
    entity_registry_idsany_of: Union[Unset, None, str] = UNSET,
) -> Dict[str, Any]:
    url = "{}/custom-entities".format(client.base_url)

    headers: Dict[str, Any] = client.get_headers()

    json_sort: Union[Unset, None, int] = UNSET
    if not isinstance(sort, Unset):
        json_sort = sort.value if sort else None

    json_mentioned_in: Union[Unset, None, List[Any]] = UNSET
    if not isinstance(mentioned_in, Unset):
        if mentioned_in is None:
            json_mentioned_in = None
        else:
            json_mentioned_in = mentioned_in

    json_schema_field: Union[Unset, None, Dict[str, Any]] = UNSET
    if not isinstance(schema_field, Unset):
        json_schema_field = schema_field.to_dict() if schema_field else None

    json_mentions: Union[Unset, None, List[Any]] = UNSET
    if not isinstance(mentions, Unset):
        if mentions is None:
            json_mentions = None
        else:
            json_mentions = mentions

    params: Dict[str, Any] = {}
    if not isinstance(next_token, Unset) and next_token is not None:
        params["nextToken"] = next_token
    if not isinstance(page_size, Unset) and page_size is not None:
        params["pageSize"] = page_size
    if not isinstance(json_sort, Unset) and json_sort is not None:
        params["sort"] = json_sort
    if not isinstance(modified_at, Unset) and modified_at is not None:
        params["modifiedAt"] = modified_at
    if not isinstance(name, Unset) and name is not None:
        params["name"] = name
    if not isinstance(name_includes, Unset) and name_includes is not None:
        params["nameIncludes"] = name_includes
    if not isinstance(folder_id, Unset) and folder_id is not None:
        params["folderId"] = folder_id
    if not isinstance(json_mentioned_in, Unset) and json_mentioned_in is not None:
        params["mentionedIn"] = json_mentioned_in
    if not isinstance(project_id, Unset) and project_id is not None:
        params["projectId"] = project_id
    if not isinstance(registry_id, Unset) and registry_id is not None:
        params["registryId"] = registry_id
    if not isinstance(schema_id, Unset) and schema_id is not None:
        params["schemaId"] = schema_id
    if not isinstance(json_schema_field, Unset) and json_schema_field is not None:
        params.update(json_schema_field)
    if not isinstance(archive_reason, Unset) and archive_reason is not None:
        params["archiveReason"] = archive_reason
    if not isinstance(json_mentions, Unset) and json_mentions is not None:
        params["mentions"] = json_mentions
    if not isinstance(ids, Unset) and ids is not None:
        params["ids"] = ids
    if not isinstance(entity_registry_idsany_of, Unset) and entity_registry_idsany_of is not None:
        params["entityRegistryIds.anyOf"] = entity_registry_idsany_of

    return {
        "url": url,
        "headers": headers,
        "cookies": client.get_cookies(),
        "timeout": client.get_timeout(),
        "params": params,
    }

This should allow us to do schema field queries with by passing in a dict

{
	"schemaField.field1": "value1",
	"schemaField.field2": "value2",
}

@forest-benchling forest-benchling changed the title Explode feat: Explode BNCH-18023 Jan 26, 2021
@forest-benchling forest-benchling changed the title feat: Explode BNCH-18023 feat: Serialize model query parameters with style=form, explode=true BNCH-18023 Jan 26, 2021
@@ -20,6 +20,7 @@ class ModelProperty(Property):
_json_type_string: ClassVar[str] = "Dict[str, Any]"

template: ClassVar[str] = "model_property.pyi"
is_dict: ClassVar[bool] = True
Copy link
Author

Choose a reason for hiding this comment

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

not that happy with this, but couldn't think of a better way

Copy link

Choose a reason for hiding this comment

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

We might want a more broad type here in the future, as arrays and other might need more special handling but honestly this is "good enough" for now.

Copy link

Choose a reason for hiding this comment

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

What is this for, to tell if the property is a ModelProperty?

Other places on the codegen check if property.template is set to tell if it's a templated (modeled) property (as opposed to a primitive one). Maybe something similar could be used here?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah. Right now it only applies to ModelProperties, not any other type of property.

@@ -20,6 +20,7 @@ class ModelProperty(Property):
_json_type_string: ClassVar[str] = "Dict[str, Any]"

template: ClassVar[str] = "model_property.pyi"
is_dict: ClassVar[bool] = True
Copy link

Choose a reason for hiding this comment

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

We might want a more broad type here in the future, as arrays and other might need more special handling but honestly this is "good enough" for now.

Copy link

@packyg packyg left a comment

Choose a reason for hiding this comment

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

What is the style=form, expload=true referenced in the PR title?

@@ -20,6 +20,7 @@ class ModelProperty(Property):
_json_type_string: ClassVar[str] = "Dict[str, Any]"

template: ClassVar[str] = "model_property.pyi"
is_dict: ClassVar[bool] = True
Copy link

Choose a reason for hiding this comment

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

What is this for, to tell if the property is a ModelProperty?

Other places on the codegen check if property.template is set to tell if it's a templated (modeled) property (as opposed to a primitive one). Maybe something similar could be used here?

{% set property_name = "json_" + property.python_name if property.template else property.python_name %}
if {% if not property.required %}not isinstance({{ property_name }}, Unset) and {% endif %}{{ property_name }} is not None:
{% if property.is_dict %}
params.update({{ property_name }})
Copy link

Choose a reason for hiding this comment

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

Does this do the prefixing as expected?

I think I would expect something like

Suggested change
params.update({{ property_name }})
params.update({
f"{property.name}.{p}": v, for p, v in {{ property_name }}.items()
})

in order for it to build the params with e.g. schemaField.Plasmid=seq_XYZ instead of just Plasmid=seq_XYZ

Copy link
Author

Choose a reason for hiding this comment

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

It does not handle the prefixing. According to the OpenAPI spec, the parameter name itself does not show up at all in the serialization.

See https://swagger.io/specification/ under "Style Examples"

@forest-benchling
Copy link
Author

forest-benchling commented Jan 26, 2021

What is the style=form, expload=true referenced in the PR title?

Sorry, it's a bit abstruse, it's OpenAPI terminology for how to serialize query parameters. And is currently the default (and only) behavior in openapi-python-client. @packyg

Base automatically changed from forest-model-property to main-v.0.7.3 January 27, 2021 14:35
@forest-benchling
Copy link
Author

Commit history got messed up because I changed the base from upstream to main-0.v.7.3. Will redo this

@forest-benchling forest-benchling changed the title feat: Serialize model query parameters with style=form, explode=true BNCH-18023 feat: Serialize serializing model query parameters with style=form, explode=true BNCH-18023 Jan 27, 2021
@forest-benchling forest-benchling changed the title feat: Serialize serializing model query parameters with style=form, explode=true BNCH-18023 feat: Serialize model query parameters with style=form, explode=true BNCH-18023 Jan 27, 2021
Copy link

@packyg packyg left a comment

Choose a reason for hiding this comment

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

Just the one thing

@@ -27,6 +27,7 @@ class ModelProperty(Property):
additional_properties: Union[bool, Property]

template: ClassVar[str] = "model_property.pyi"
json_is_dict: ClassVar[bool] = True
Copy link

@packyg packyg Jan 27, 2021

Choose a reason for hiding this comment

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

You should add this classvar to the parent class to be consistent:

json_is_dict: ClassVar[bool] = False

It's not erroring now because Jinja is permissive, but if you were to do property.json_is_dict outside of a template, it would error for non-model properties.

@forest-benchling forest-benchling merged commit b0109cd into main-v.0.7.3 Jan 27, 2021
@forest-benchling forest-benchling deleted the forest-explode branch January 27, 2021 22:39
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.

Support for Free-Form Query Parameters
3 participants