openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[BUG][PYTHON][ALL?] Query parameter list are not serialized correctly

Open BaptisteSaves opened this issue 1 year ago • 7 comments

Bug Report Checklist

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [x] Have you validated the input using an OpenAPI validator (example)?
  • [x] Have you tested with the latest master to confirm the issue still exists?
  • [x] Have you searched for related issues/PRs?
  • [x] What's the actual output vs expected output?
  • [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

When having a query parameter that is a list, the typing is not handled (Any) and multi is not set. Because of that the serialized parameters are not as expected Actual param=value1,value2 Expected param=value1&param=value2

openapi-generator version

7.5.0

OpenAPI declaration file content or url

openapi: 3.1.0
info:
  title: My spec
  version: 1.0.0
paths:
  /api/issue:
    get:
      parameters:
      - in: query
        name: my_params
        required: false
        schema:
          anyOf:
          - items:
              type: string
            type: array
          - type: 'null'
      responses:
        '200':
          content:
            application/json:
              schema:
                type: string
          description: Successful Response
Generation Details

Simple generation in 7.3.0 with -g python

Steps to reproduce

Generated code is

    @validate_call
    def api_issue_get(
        self,
        my_params: Optional[List[Any]] = None,

instead of

    @validate_call
    def api_issue_get(
        self,
        my_params: Optional[List[str]] = None,
values = DefaultApi()._api_issue_get_serialize(my_params=["value1", "value2"], _request_auth=None,_content_type=None,_headers=None,_host_index=None)
assert values[1] != '/api/issue?my_params=value1,value2'
assert values[1] == '/api/issue?my_params=value1&my_params=value2'
Related issues/PRs

Did not find any

Suggest a fix

I can push a PR but I need guidance on how to fix this.

From what I understand:

  • In this method of the python generator, the CodegenParameter represents the Array but its items field is null instead of containing the string schema

Trying to track why CodegenParameter does not have items:

  • Here items is not set because it is not an enum.

Why are we not moving both lines outside of the condition ?

            codegenParameter.items = codegenProperty.items;
            codegenParameter.mostInnerItems = codegenProperty.mostInnerItems;

BaptisteSaves avatar Apr 24 '24 12:04 BaptisteSaves

thanks for reporting the issue. have you tried the latest master as well?

snapshot version can be found in project's readme

wing328 avatar Apr 30 '24 09:04 wing328

@wing328 I tried it with openapitools/openapi-generator-cli:latest today

BaptisteSaves avatar Apr 30 '24 16:04 BaptisteSaves

        schema:
          anyOf:
          - items:
              type: string
            type: array
          - type: 'null'

if you replace with it with just an array of string (igoring nullable at the moment), does it work?

wing328 avatar Apr 30 '24 16:04 wing328

Yes this will work fine.

I understand the anyOf: -null part is not really useful in this context but the spec file is generated so we cannot fix it that way.

openapi: 3.1.0
info:
  title: My spec
  version: 1.0.0
paths:
  /api/issue:
    get:
      parameters:
      - in: query
        name: my_params
        required: false
        schema:
          items:
            type: string
          type: array
      responses:
        '200':
          content:
            application/json:
              schema:
                type: string
          description: Successful Response

BaptisteSaves avatar May 02 '24 13:05 BaptisteSaves

can you please give it another try?

looks to be working in my end (anyOf in this case is simplified to just array of string)


    @validate_call
    def api_issue_get(
        self,
        my_params: Optional[List[StrictStr]] = None,
        _request_timeout: Union[
            None,
            Annotated[StrictFloat, Field(gt=0)],
            Tuple[
                Annotated[StrictFloat, Field(gt=0)],
                Annotated[StrictFloat, Field(gt=0)]
            ]
        ] = None,
        _request_auth: Optional[Dict[StrictStr, Any]] = None,
        _content_type: Optional[StrictStr] = None,
        _headers: Optional[Dict[StrictStr, Any]] = None,
        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
    ) -> str:
        """api_issue_get


        :param my_params:
        :type my_params: List[str]
        :param _request_timeout: timeout setting for this request. If one
                                 number provided, it will be total request
                                 timeout. It can also be a pair (tuple) of


wing328 avatar May 06 '24 06:05 wing328

I am not sure how you can get a different result than me so I gave the whole project that shows the any

Maybe the latest docker is not really latest ?

> cat sdk_test.yaml
openapi: 3.1.0
info:
  title: My spec
  version: 1.0.0
paths:
  /api/issue:
    get:
      parameters:
      - in: query
        name: my_params
        required: false
        schema:
          anyOf:
          - items:
              type: string
            type: array
          - type: 'null'
      responses:
        '200':
          content:
            application/json:
              schema:
                type: string
          description: Successful Response
         
> docker run -v "${PWD}:/local" openapitools/openapi-generator-cli:latest generate -i /local/sdk_test.yaml -g python -o /local/openapi_client

[main] WARN  o.o.codegen.DefaultCodegen - Generation using 3.1.0 specs is in development and is not officially supported yet. If you would like to expedite development, please consider woking on the open issues in the 3.1.0 project: https://github.com/orgs/OpenAPITools/projects/4/views/1 and reach out to our team on Slack at https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g
[main] INFO  o.o.codegen.DefaultGenerator - Generating with dryRun=false
[main] INFO  o.o.c.ignore.CodegenIgnoreProcessor - Output directory (/local/openapi_client) does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO  o.o.codegen.DefaultGenerator - OpenAPI Generator: python (client)
[main] INFO  o.o.codegen.DefaultGenerator - Generator 'python' is considered stable.
[main] INFO  o.o.c.l.AbstractPythonCodegen - Environment variable PYTHON_POST_PROCESS_FILE not defined so the Python code may not be properly formatted. To define it, try 'export PYTHON_POST_PROCESS_FILE="/usr/local/bin/yapf -i"' (Linux/Mac)
[main] INFO  o.o.c.l.AbstractPythonCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
[main] INFO  o.o.c.languages.PythonClientCodegen - Environment variable PYTHON_POST_PROCESS_FILE not defined so the Python code may not be properly formatted. To define it, try 'export PYTHON_POST_PROCESS_FILE="/usr/local/bin/yapf -i"' (Linux/Mac)
[main] INFO  o.o.c.languages.PythonClientCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
[main] WARN  o.o.codegen.DefaultCodegen - Generation using 3.1.0 specs is in development and is not officially supported yet. If you would like to expedite development, please consider woking on the open issues in the 3.1.0 project: https://github.com/orgs/OpenAPITools/projects/4/views/1 and reach out to our team on Slack at https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g
[main] INFO  o.o.codegen.utils.URLPathUtils - 'host' (OAS 2.0) or 'servers' (OAS 3.0) not defined in the spec. Default to [http://localhost] for server URL [http://localhost/]
[main] INFO  o.o.codegen.utils.URLPathUtils - 'host' (OAS 2.0) or 'servers' (OAS 3.0) not defined in the spec. Default to [http://localhost] for server URL [http://localhost/]
[main] WARN  o.o.codegen.DefaultCodegen - Empty operationId found for path: get /api/issue. Renamed to auto-generated operationId: apiIssueGet
[main] WARN  o.o.c.l.AbstractPythonCodegen - Codegen property is null (e.g. map/dict of undefined type). Default to typing.Any.
[main] INFO  o.o.codegen.utils.URLPathUtils - 'host' (OAS 2.0) or 'servers' (OAS 3.0) not defined in the spec. Default to [http://localhost] for server URL [http://localhost/]
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/api/default_api.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/test/test_default_api.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/docs/DefaultApi.md
[main] INFO  o.o.codegen.utils.URLPathUtils - 'host' (OAS 2.0) or 'servers' (OAS 3.0) not defined in the spec. Default to [http://localhost] for server URL [http://localhost/]
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/README.md
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/tox.ini
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/test-requirements.txt
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/requirements.txt
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/setup.cfg
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/git_push.sh
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/.gitignore
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/.travis.yml
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/.github/workflows/python.yml
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/.gitlab-ci.yml
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/setup.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/pyproject.toml
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/py.typed
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/configuration.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/__init__.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/models/__init__.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/api/__init__.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/exceptions.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/test/__init__.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/api_client.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/api_response.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/openapi_client/rest.py
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/.openapi-generator-ignore
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/.openapi-generator/VERSION
[main] INFO  o.o.codegen.TemplateManager - writing file /local/openapi_client/.openapi-generator/FILES
################################################################################
# Thanks for using OpenAPI Generator.                                          #
# Please consider donation to help us maintain this project 🙏                 #
# https://opencollective.com/openapi_generator/donate                          #
################################################################################
>cat openapi_client/openapi_client/api/default_api.py

    @validate_call
    def api_issue_get(
        self,
        my_params: Optional[List[Any]] = None,
        _request_timeout: Union[
            None,
            Annotated[StrictFloat, Field(gt=0)],
            Tuple[
                Annotated[StrictFloat, Field(gt=0)],
                Annotated[StrictFloat, Field(gt=0)]
            ]
        ] = None,
        _request_auth: Optional[Dict[StrictStr, Any]] = None,
        _content_type: Optional[StrictStr] = None,
        _headers: Optional[Dict[StrictStr, Any]] = None,
        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
    ) -> str:
        """api_issue_get


        :param my_params:

BaptisteSaves avatar May 07 '24 12:05 BaptisteSaves

did you perform a docker pull to get the latest openapitools/openapi-generator-cli:latest which is updated whenever there's a change to the master ?

wing328 avatar May 08 '24 03:05 wing328

@wing328 I guess I did not. Yes it seems fixed on the latest build. Sorry about that.

BaptisteSaves avatar May 10 '24 06:05 BaptisteSaves

@BaptisteSaves no problem bro. Can you please PM me via Slack when you've time?

https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g

wing328 avatar May 10 '24 12:05 wing328