Uh oh!
There was an error while loading. Please reload this page.
feat: Add allOf support for model definitions BNCH-18722 - #12
Conversation
Combines the child elements into one, without class heirarchy, mixins, etc
packyg
commented
Dec 5, 2020
@adamrp is a non-blocking reviewer - just spreading context on the codegen/SDK |
There was a problem hiding this comment.
What a journey. Thanks for all your efforts on this @packyg.
I generated a client with this and tried running a subset of our integration tests and they fail. In general, this PR looks OK to me but in 296ffb6 we introduce something like if not isinstance(some_prop, Unset): which is causing an error.
For example in list_boxes.py generated from this:
json_sort: Union[Unset, ListBoxesSort] = UNSET
if not isinstance(sort, Unset):
json_sort = sort
Causes TypeError: isinstance() arg 2 must be a type or tuple of types. I think we need to be using sort == UNSET.
Something to visit next week as we close in on syncing everything up.
| new_optional_props = [op for op in self.optional_properties if op.name != prop.name] | ||
| self.optional_properties.clear() | ||
| self.optional_properties.extend(new_optional_props) |
There was a problem hiding this comment.
out of curiosity, what's the difference between this and
self.optional_properties = [op for op in self.optional_properties if op.name != prop.name]
?
There was a problem hiding this comment.
@dtkav There isn't, except this class is marked with @attr.s(auto_attribs=True, frozen=True) so errors if I attempt to set the property
packyg
commented
Dec 7, 2020
Hmm I'll need to look at this more. The upstream is using the |
adamrp
commented
Dec 7, 2020
Don't quote me on this, but I think |
packyg
commented
Dec 7, 2020
That's what I don't understand - |
adamrp
left a comment
There was a problem hiding this comment.
Approving, although I wish I knew why isinstance is failing... 🤔
bowenwr
commented
Dec 7, 2020
In my example it's because The generated client is looking for Maybe we could persuade the maintainers to also check |
@bowenwr We don't want them to do that, at least for JSON serialization, do we? If we did that it would be treating As for URL and QS parameters -that's a different story, I could see the use in treating Still don't know why checking As far as for now - I think it'd be OK for us to use this implementation detail in the SDK since it's so tightly coupled to the generated client. |
bowenwr
commented
Dec 7, 2020
Yes, this is the case to which I'm referring. Specifically a query param. For JSON serialization, you're correct.
It's imported. Generated endpoint: fromtypingimportAny, Dict, Optional, Unionimporthttpxfrom ...clientimportClientfrom ...models.bad_request_errorimportBadRequestErrorfrom ...models.box_listimportBoxListfrom ...models.list_boxes_sortimportListBoxesSortfrom ...typesimportUNSET, Response, Unsetdef_get_kwargs(
*,
client: Client,
page_size: Union[Unset, int] =50,
next_token: Union[Unset, str] =UNSET,
sort: Union[Unset, ListBoxesSort] =ListBoxesSort.MODIFIEDATDESC,
schema_id: Union[Unset, str] =UNSET,
modified_at: Union[Unset, str] =UNSET,
name: Union[Unset, str] =UNSET,
name_includes: Union[Unset, str] =UNSET,
empty_positions: Union[Unset, int] =UNSET,
empty_positionsgte: Union[Unset, int] =UNSET,
empty_positionsgt: Union[Unset, int] =UNSET,
empty_positionslte: Union[Unset, int] =UNSET,
empty_positionslt: Union[Unset, int] =UNSET,
empty_containers: Union[Unset, int] =UNSET,
empty_containersgte: Union[Unset, int] =UNSET,
empty_containersgt: Union[Unset, int] =UNSET,
empty_containerslte: Union[Unset, int] =UNSET,
empty_containerslt: Union[Unset, int] =UNSET,
ancestor_storage_id: Union[Unset, str] =UNSET,
storage_contents_id: Union[Unset, str] =UNSET,
storage_contents_ids: Union[Unset, str] =UNSET,
archive_reason: Union[Unset, str] =UNSET,
ids: Union[Unset, str] =UNSET,
barcodes: Union[Unset, str] =UNSET,
) ->Dict[str, Any]:
url="{}/boxes".format(client.base_url)
headers: Dict[str, Any] =client.get_headers()
json_sort: Union[Unset, ListBoxesSort] =UNSETifnotisinstance(sort, Unset):
json_sort=sortparams: Dict[str, Any] = {}
ifpage_sizeisnotUNSET:
params["pageSize"] =page_sizeifnext_tokenisnotUNSET:
params["nextToken"] =next_tokenifsortisnotUNSET:
params["sort"] =json_sortifschema_idisnotUNSET:
params["schemaId"] =schema_idifmodified_atisnotUNSET:
params["modifiedAt"] =modified_atifnameisnotUNSET:
params["name"] =nameifname_includesisnotUNSET:
params["nameIncludes"] =name_includesifempty_positionsisnotUNSET:
params["emptyPositions"] =empty_positionsifempty_positionsgteisnotUNSET:
params["emptyPositions.gte"] =empty_positionsgteifempty_positionsgtisnotUNSET:
params["emptyPositions.gt"] =empty_positionsgtifempty_positionslteisnotUNSET:
params["emptyPositions.lte"] =empty_positionslteifempty_positionsltisnotUNSET:
params["emptyPositions.lt"] =empty_positionsltifempty_containersisnotUNSET:
params["emptyContainers"] =empty_containersifempty_containersgteisnotUNSET:
params["emptyContainers.gte"] =empty_containersgteifempty_containersgtisnotUNSET:
params["emptyContainers.gt"] =empty_containersgtifempty_containerslteisnotUNSET:
params["emptyContainers.lte"] =empty_containerslteifempty_containersltisnotUNSET:
params["emptyContainers.lt"] =empty_containersltifancestor_storage_idisnotUNSET:
params["ancestorStorageId"] =ancestor_storage_idifstorage_contents_idisnotUNSET:
params["storageContentsId"] =storage_contents_idifstorage_contents_idsisnotUNSET:
params["storageContentsIds"] =storage_contents_idsifarchive_reasonisnotUNSET:
params["archiveReason"] =archive_reasonifidsisnotUNSET:
params["ids"] =idsifbarcodesisnotUNSET:
params["barcodes"] =barcodesreturn {
"url": url,
"headers": headers,
"cookies": client.get_cookies(),
"timeout": client.get_timeout(),
"params": params,
}
def_parse_response(*, response: httpx.Response) ->Optional[Union[BoxList, BadRequestError]]:
ifresponse.status_code==200:
response_200=BoxList.from_dict(response.json())
returnresponse_200ifresponse.status_code==400:
response_400=BadRequestError.from_dict(response.json())
returnresponse_400returnNonedef_build_response(*, response: httpx.Response) ->Response[Union[BoxList, BadRequestError]]:
returnResponse(
status_code=response.status_code,
content=response.content,
headers=response.headers,
parsed=_parse_response(response=response),
)
defsync_detailed(
*,
client: Client,
page_size: Union[Unset, int] =50,
next_token: Union[Unset, str] =UNSET,
sort: Union[Unset, ListBoxesSort] =ListBoxesSort.MODIFIEDATDESC,
schema_id: Union[Unset, str] =UNSET,
modified_at: Union[Unset, str] =UNSET,
name: Union[Unset, str] =UNSET,
name_includes: Union[Unset, str] =UNSET,
empty_positions: Union[Unset, int] =UNSET,
empty_positionsgte: Union[Unset, int] =UNSET,
empty_positionsgt: Union[Unset, int] =UNSET,
empty_positionslte: Union[Unset, int] =UNSET,
empty_positionslt: Union[Unset, int] =UNSET,
empty_containers: Union[Unset, int] =UNSET,
empty_containersgte: Union[Unset, int] =UNSET,
empty_containersgt: Union[Unset, int] =UNSET,
empty_containerslte: Union[Unset, int] =UNSET,
empty_containerslt: Union[Unset, int] =UNSET,
ancestor_storage_id: Union[Unset, str] =UNSET,
storage_contents_id: Union[Unset, str] =UNSET,
storage_contents_ids: Union[Unset, str] =UNSET,
archive_reason: Union[Unset, str] =UNSET,
ids: Union[Unset, str] =UNSET,
barcodes: Union[Unset, str] =UNSET,
) ->Response[Union[BoxList, BadRequestError]]:
kwargs=_get_kwargs(
client=client,
page_size=page_size,
next_token=next_token,
sort=sort,
schema_id=schema_id,
modified_at=modified_at,
name=name,
name_includes=name_includes,
empty_positions=empty_positions,
empty_positionsgte=empty_positionsgte,
empty_positionsgt=empty_positionsgt,
empty_positionslte=empty_positionslte,
empty_positionslt=empty_positionslt,
empty_containers=empty_containers,
empty_containersgte=empty_containersgte,
empty_containersgt=empty_containersgt,
empty_containerslte=empty_containerslte,
empty_containerslt=empty_containerslt,
ancestor_storage_id=ancestor_storage_id,
storage_contents_id=storage_contents_id,
storage_contents_ids=storage_contents_ids,
archive_reason=archive_reason,
ids=ids,
barcodes=barcodes,
)
response=httpx.get(
**kwargs,
)
return_build_response(response=response)
defsync(
*,
client: Client,
page_size: Union[Unset, int] =50,
next_token: Union[Unset, str] =UNSET,
sort: Union[Unset, ListBoxesSort] =ListBoxesSort.MODIFIEDATDESC,
schema_id: Union[Unset, str] =UNSET,
modified_at: Union[Unset, str] =UNSET,
name: Union[Unset, str] =UNSET,
name_includes: Union[Unset, str] =UNSET,
empty_positions: Union[Unset, int] =UNSET,
empty_positionsgte: Union[Unset, int] =UNSET,
empty_positionsgt: Union[Unset, int] =UNSET,
empty_positionslte: Union[Unset, int] =UNSET,
empty_positionslt: Union[Unset, int] =UNSET,
empty_containers: Union[Unset, int] =UNSET,
empty_containersgte: Union[Unset, int] =UNSET,
empty_containersgt: Union[Unset, int] =UNSET,
empty_containerslte: Union[Unset, int] =UNSET,
empty_containerslt: Union[Unset, int] =UNSET,
ancestor_storage_id: Union[Unset, str] =UNSET,
storage_contents_id: Union[Unset, str] =UNSET,
storage_contents_ids: Union[Unset, str] =UNSET,
archive_reason: Union[Unset, str] =UNSET,
ids: Union[Unset, str] =UNSET,
barcodes: Union[Unset, str] =UNSET,
) ->Optional[Union[BoxList, BadRequestError]]:
""" List boxes """returnsync_detailed(
client=client,
page_size=page_size,
next_token=next_token,
sort=sort,
schema_id=schema_id,
modified_at=modified_at,
name=name,
name_includes=name_includes,
empty_positions=empty_positions,
empty_positionsgte=empty_positionsgte,
empty_positionsgt=empty_positionsgt,
empty_positionslte=empty_positionslte,
empty_positionslt=empty_positionslt,
empty_containers=empty_containers,
empty_containersgte=empty_containersgte,
empty_containersgt=empty_containersgt,
empty_containerslte=empty_containerslte,
empty_containerslt=empty_containerslt,
ancestor_storage_id=ancestor_storage_id,
storage_contents_id=storage_contents_id,
storage_contents_ids=storage_contents_ids,
archive_reason=archive_reason,
ids=ids,
barcodes=barcodes,
).parsedasyncdefasyncio_detailed(
*,
client: Client,
page_size: Union[Unset, int] =50,
next_token: Union[Unset, str] =UNSET,
sort: Union[Unset, ListBoxesSort] =ListBoxesSort.MODIFIEDATDESC,
schema_id: Union[Unset, str] =UNSET,
modified_at: Union[Unset, str] =UNSET,
name: Union[Unset, str] =UNSET,
name_includes: Union[Unset, str] =UNSET,
empty_positions: Union[Unset, int] =UNSET,
empty_positionsgte: Union[Unset, int] =UNSET,
empty_positionsgt: Union[Unset, int] =UNSET,
empty_positionslte: Union[Unset, int] =UNSET,
empty_positionslt: Union[Unset, int] =UNSET,
empty_containers: Union[Unset, int] =UNSET,
empty_containersgte: Union[Unset, int] =UNSET,
empty_containersgt: Union[Unset, int] =UNSET,
empty_containerslte: Union[Unset, int] =UNSET,
empty_containerslt: Union[Unset, int] =UNSET,
ancestor_storage_id: Union[Unset, str] =UNSET,
storage_contents_id: Union[Unset, str] =UNSET,
storage_contents_ids: Union[Unset, str] =UNSET,
archive_reason: Union[Unset, str] =UNSET,
ids: Union[Unset, str] =UNSET,
barcodes: Union[Unset, str] =UNSET,
) ->Response[Union[BoxList, BadRequestError]]:
kwargs=_get_kwargs(
client=client,
page_size=page_size,
next_token=next_token,
sort=sort,
schema_id=schema_id,
modified_at=modified_at,
name=name,
name_includes=name_includes,
empty_positions=empty_positions,
empty_positionsgte=empty_positionsgte,
empty_positionsgt=empty_positionsgt,
empty_positionslte=empty_positionslte,
empty_positionslt=empty_positionslt,
empty_containers=empty_containers,
empty_containersgte=empty_containersgte,
empty_containersgt=empty_containersgt,
empty_containerslte=empty_containerslte,
empty_containerslt=empty_containerslt,
ancestor_storage_id=ancestor_storage_id,
storage_contents_id=storage_contents_id,
storage_contents_ids=storage_contents_ids,
archive_reason=archive_reason,
ids=ids,
barcodes=barcodes,
)
asyncwithhttpx.AsyncClient() as_client:
response=await_client.get(**kwargs)
return_build_response(response=response)
asyncdefasyncio(
*,
client: Client,
page_size: Union[Unset, int] =50,
next_token: Union[Unset, str] =UNSET,
sort: Union[Unset, ListBoxesSort] =ListBoxesSort.MODIFIEDATDESC,
schema_id: Union[Unset, str] =UNSET,
modified_at: Union[Unset, str] =UNSET,
name: Union[Unset, str] =UNSET,
name_includes: Union[Unset, str] =UNSET,
empty_positions: Union[Unset, int] =UNSET,
empty_positionsgte: Union[Unset, int] =UNSET,
empty_positionsgt: Union[Unset, int] =UNSET,
empty_positionslte: Union[Unset, int] =UNSET,
empty_positionslt: Union[Unset, int] =UNSET,
empty_containers: Union[Unset, int] =UNSET,
empty_containersgte: Union[Unset, int] =UNSET,
empty_containersgt: Union[Unset, int] =UNSET,
empty_containerslte: Union[Unset, int] =UNSET,
empty_containerslt: Union[Unset, int] =UNSET,
ancestor_storage_id: Union[Unset, str] =UNSET,
storage_contents_id: Union[Unset, str] =UNSET,
storage_contents_ids: Union[Unset, str] =UNSET,
archive_reason: Union[Unset, str] =UNSET,
ids: Union[Unset, str] =UNSET,
barcodes: Union[Unset, str] =UNSET,
) ->Optional[Union[BoxList, BadRequestError]]:
""" List boxes """return (
awaitasyncio_detailed(
client=client,
page_size=page_size,
next_token=next_token,
sort=sort,
schema_id=schema_id,
modified_at=modified_at,
name=name,
name_includes=name_includes,
empty_positions=empty_positions,
empty_positionsgte=empty_positionsgte,
empty_positionsgt=empty_positionsgt,
empty_positionslte=empty_positionslte,
empty_positionslt=empty_positionslt,
empty_containers=empty_containers,
empty_containersgte=empty_containersgte,
empty_containersgt=empty_containersgt,
empty_containerslte=empty_containerslte,
empty_containerslt=empty_containerslt,
ancestor_storage_id=ancestor_storage_id,
storage_contents_id=storage_contents_id,
storage_contents_ids=storage_contents_ids,
archive_reason=archive_reason,
ids=ids,
barcodes=barcodes,
)
).parsed |
bowenwr
commented
Dec 7, 2020
To be clear, the comments about |
Collapses the child elements into one, without class heirarchy, mixins, etc This is a replaying of 2670d11 (first implementation) and 9f5b95a (a bugfix) onto the new `main-v.0.7.0`, modified for the refactored upstream. This should bring `main-v.0.7.1` up to par with `main` for the features we implemented in our fork (dropping our `Unset` implementation for theirs)
Collapses the child elements into one, without class heirarchy, mixins, etc This is a replaying of 2670d11 (first implementation) and 9f5b95a (a bugfix) onto the new `main-v.0.7.0`, modified for the refactored upstream. This should bring `main-v.0.7.1` up to par with `main` for the features we implemented in our fork (dropping our `Unset` implementation for theirs)
Collapses the child elements into one, without class heirarchy, mixins, etc This is a replaying of 2670d11 (first implementation) and 9f5b95a (a bugfix) onto the new `main-v.0.7.0`, modified for the refactored upstream. This should bring `main-v.0.7.1` up to par with `main` for the features we implemented in our fork (dropping our `Unset` implementation for theirs)
Collapses the child elements into one, without class heirarchy, mixins, etc This is a replaying of 2670d11 (first implementation) and 9f5b95a (a bugfix) onto the new `main-v.0.7.0`, modified for the refactored upstream. This should bring `main-v.0.7.1` up to par with `main` for the features we implemented in our fork (dropping our `Unset` implementation for theirs)
Collapses the child elements into one, without class heirarchy, mixins, etc This is a replaying of 2670d11 (first implementation) and 9f5b95a (a bugfix) onto the new `main-v.0.7.0`, modified for the refactored upstream. This should bring `main-v.0.7.1` up to par with `main` for the features we implemented in our fork (dropping our `Unset` implementation for theirs)
Collapses the child elements into one, without class heirarchy, mixins, etc
This is a replaying of 2670d11 (first implementation) and 9f5b95a (a bugfix) onto the new
main-v.0.7.0, modified for the refactored upstream.This should bring
main-v.0.7.0up to par withmainfor the features we implemented in our fork (dropping ourUnsetimplementation for theirs)We cannot really cut over to the upstream until a couple of issues are addressed:
Add additional property support by subscripting model openapi-generators/openapi-python-client#252 - fixes enums in QS params. The current upstream would break listing endpoints as it would request e.g.
/api/v2/custom-entities?pageSize=2&sort=ListCustomEntitiesSort.MODIFIEDATDESCBugfix: Implement __str__ for enum props to fix query string openapi-generators/openapi-python-client#259 - adds
additionalPropertiessupport. The current upstream switched from dicts to empty models for unmodeled properties so we can't read or write entity schema fields with the current upstream.See also: openapi-generators#98 (upstream issue by @dtkav) that this implements - we should try upstreaming this if all goes well