Skip to content

[Python] Added Ability to Initialize Models by Passing in Dictionaries - #11125

Merged
spacether merged 7 commits into
OpenAPITools:masterfrom
Bandwidth-Sandbox:ckoegel-py-models
Mar 9, 2022
Merged

[Python] Added Ability to Initialize Models by Passing in Dictionaries#11125
spacether merged 7 commits into
OpenAPITools:masterfrom
Bandwidth-Sandbox:ckoegel-py-models

Conversation

@ckoegel

@ckoegel ckoegel commented Dec 14, 2021

Copy link
Copy Markdown
Contributor

Python models created from openapi schema do not accept positional objects as arguments. More information about what the goal of this PR is can be found at this issue. This was mostly caused by the invalid_pos_args.mustache file instantly raising an error if positional arguments were passed in. This has been updated to accept dictionaries as a valid positional argument. The dictionaries are merged into the kwargs dictionary that the function uses to initialize. This allows users to pass in dictionaries to create models, which was previously allowed with the ** operator, but this allows for an alternative method of creating these objects.

The main function of this PR allows for the creation of nested objects. The setattr function called when initializing the model validates the type of each kwarg before setting the attribute, meaning if nested dictionaries are passed in, the validate_and_convert_types function will raise a type error if those nested dictionaries need to be used in the creation of another object since their types do not match. The solution for this was already partially implemented, since the validate_and_convert_types function has logic to attempt to convert non-matching attribute types, but this needed to be modified to allow for attempting to convert dictionaries. Once the logic was added to allow a dictionary to be converted, the logic within attempt_convert_item automatically uses the dictionary to initialize a new instance of its respective model. This allows for any amount of nested dictionaries to be passed into a model initialization and their corresponding models be created. Errors will still be thrown if the positional arguments are incorrectly formatted, or if the model that needs to be created from a dictionary does not match the dictionary's contents.

This can be validated by using this spec and this command: java -jar ./modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g python -i messaging.json -o sdk/ in the root of the project to generate an SDK. Then running the FastApi app below and making a POST to the endpoint with the body below should successfully create both a BandwidthCallbackMessage and a BandwidthMessage, which can be seen in the output of the FastApi app.

FastApi App:

from fastapi import FastAPI, Request

from openapi_client.model.bandwidth_callback_message import BandwidthCallbackMessage

app = FastAPI()

@app.post('/msg-resp')
async def rec_message(request: Request):
    body = await request.json()
    bw_callback = BandwidthCallbackMessage(body)
    print("Type of request: ", type(bw_callback))
    print("Type of callback message: ", type(bw_callback.message))
    print("Request: \n", bw_callback)
    return 200

Request Body:

{
    "time": "2021-12-14T19:48:29.806Z",
    "type": "message-received",
    "to": "+19195551234",
    "description": "Incoming message received",
    "message": {
        "id": "id-abcd",
        "owner": "+19195551234",
        "applicationId": "app-id-abcd",
        "time": "2021-12-14T19:48:29.641Z",
        "segmentCount": 1,
        "direction": "in",
        "to": [
            "+19195551234"
        ],
        "from": "+19195554321",
        "text": "Hello World"
    }
}

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
    ./mvnw clean package 
    ./bin/generate-samples.sh
    ./bin/utils/export_docs_generators.sh
    
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    For Windows users, please run the script in Git BASH.
  • File the PR against the correct branch: master (5.3.0), 6.0.x
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

@taxpon (2017/07) @frol (2017/07) @mbohlool (2017/07) @cbornet (2017/09) @kenjones-cisco (2017/11) @tomplus (2018/10) @Jyhess (2019/01) @arun-nalla (2019/11) @spacether (2019/11)

@ckoegel
ckoegel marked this pull request as ready for review December 14, 2021 21:28
@ckoegel
ckoegel marked this pull request as draft December 15, 2021 16:35
@ckoegel
ckoegel marked this pull request as ready for review December 15, 2021 18:27
@wing328 wing328 added this to the 5.4.0 milestone Dec 29, 2021
@wing328 wing328 modified the milestones: 5.4.0, 6.0.0 Jan 31, 2022

@spacether spacether left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks good. Thank you for your PR!

@spacether
spacether merged commit fd1ede6 into OpenAPITools:master Mar 9, 2022
@ckoegel
ckoegel deleted the ckoegel-py-models branch July 11, 2023 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants