openapi-generators / openapi-python-client

Generate modern Python clients from OpenAPI
MIT License
1.28k stars 197 forks source link

Missing lazy import in post body to_multipart function #1051

Open mthanded opened 4 months ago

mthanded commented 4 months ago

Describe the bug It is possible to generate a model with a missing import leading to invalid python code.

The below to_multipart function is generated in the body for the create_upload_file_uploadfile__post model and references UploadConfig however it is not in scope.

def to_multipart(self) -> Dict[str, Any]:
        file = self.file.to_tuple()

        config: Union[Tuple[None, bytes, str], Unset]

        if isinstance(self.config, Unset):
            config = UNSET
        elif isinstance(self.config, UploadConfig):
            config = (None, json.dumps(self.config.to_dict()).encode(), "application/json")
        else:
            config = (None, str(self.config).encode(), "text/plain")

        field_dict: Dict[str, Any] = {}
        for prop_name, prop in self.additional_properties.items():
            field_dict[prop_name] = (None, str(prop).encode(), "text/plain")

        field_dict.update(
            {
                "file": file,
            }
        )
        if config is not UNSET:
            field_dict["config"] = config

        return field_dict

The function to_dict right above it in the file lazily imports UploadConfig

    def to_dict(self) -> Dict[str, Any]:
        from ..models.upload_config import UploadConfig

        file = self.file.to_tuple()

OpenAPI Spec File

{
    "openapi": "3.1.0",
    "info": {
        "title": "FastAPI",
        "version": "0.1.0"
    },
    "paths": {
        "/uploadfile/": {
            "post": {
                "summary": "Create Upload File",
                "operationId": "create_upload_file_uploadfile__post",
                "requestBody": {
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post"
                            }
                        }
                    },
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {}
                            }
                        }
                    },
                    "422": {
                        "description": "Validation Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HTTPValidationError"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "Body_create_upload_file_uploadfile__post": {
                "properties": {
                    "file": {
                        "type": "string",
                        "format": "binary",
                        "title": "File"
                    },
                    "config": {
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/UploadConfig"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    }
                },
                "type": "object",
                "required": [
                    "file"
                ],
                "title": "Body_create_upload_file_uploadfile__post"
            },
            "HTTPValidationError": {
                "properties": {
                    "detail": {
                        "items": {
                            "$ref": "#/components/schemas/ValidationError"
                        },
                        "type": "array",
                        "title": "Detail"
                    }
                },
                "type": "object",
                "title": "HTTPValidationError"
            },
            "UploadConfig": {
                "properties": {
                    "test": {
                        "type": "string",
                        "title": "Test",
                        "default": "test"
                    },
                    "config": {
                        "type": "object",
                        "title": "Config",
                        "default": {}
                    }
                },
                "type": "object",
                "title": "UploadConfig"
            },
            "ValidationError": {
                "properties": {
                    "loc": {
                        "items": {
                            "anyOf": [
                                {
                                    "type": "string"
                                },
                                {
                                    "type": "integer"
                                }
                            ]
                        },
                        "type": "array",
                        "title": "Location"
                    },
                    "msg": {
                        "type": "string",
                        "title": "Message"
                    },
                    "type": {
                        "type": "string",
                        "title": "Error Type"
                    }
                },
                "type": "object",
                "required": [
                    "loc",
                    "msg",
                    "type"
                ],
                "title": "ValidationError"
            }
        }
    }
}

Desktop (please complete the following information):

Additional context I have been able to fix this locally by modifying the following

https://github.com/openapi-generators/openapi-python-client/blob/73f92ea7da8daa758bb237daa7cc26030cd32225/openapi_python_client/templates/model.py.jinja#L131-L134

Solution is to add the lazy import template that is found in to_dict

https://github.com/openapi-generators/openapi-python-client/blob/73f92ea7da8daa758bb237daa7cc26030cd32225/openapi_python_client/templates/model.py.jinja#L126-L128