Skip to content

nullable int model parameter treated as a file in multipart with 0.17.0, causing httpx AttributeError #926

@johnthagen

Description

@johnthagen

Describe the bug

After upgrading the client to 0.17.0 and testing out, I noticed that Multipart client handling seems to have broken.

The code in 0.16.0 was rougly:

        api.sync_detailed(
            id,
            client=client,
            multipart_data=TRequest(parent=2),
        )

And with 0.17.0, usage updated to:

        api.sync_detailed(
            id,
            client=client,
            body=TRequest(parent=2),
        )

Is this not actually being serialized to multipart at some point? The type signatures all matched, so I thought I was using it correctly. I also see in the generated sync_detailed() that _get_kwargs() calls _body = body.to_multipart() so is it right to assume that multipart should happen transparently?

The model in question has parameters of type, File, str, bool, and int.

I was hoping the stacktrace might help illuminate what could be happening:

    api.sync_detailed(
  File "main.py", line 92, in sync_detailed
    response = client.get_httpx_client().request(
  File "/python3.10/site-packages/httpx/_client.py", line 828, in request
    return self.send(request, auth=auth, follow_redirects=follow_redirects)
  File "/python3.10/site-packages/httpx/_client.py", line 915, in send
    response = self._send_handling_auth(
  File "/python3.10/site-packages/httpx/_client.py", line 943, in _send_handling_auth
    response = self._send_handling_redirects(
  File "/python3.10/site-packages/httpx/_client.py", line 980, in _send_handling_redirects
    response = self._send_single_request(request)
  File "/python3.10/site-packages/httpx/_client.py", line 1016, in _send_single_request
    response = transport.handle_request(request)
  File "/python3.10/site-packages/httpx/_transports/default.py", line 231, in handle_request
    resp = self._pool.handle_request(req)
  File "/python3.10/site-packages/httpcore/_sync/connection_pool.py", line 268, in handle_request
    raise exc
  File "/python3.10/site-packages/httpcore/_sync/connection_pool.py", line 251, in handle_request
    response = connection.handle_request(request)
  File "/python3.10/site-packages/httpcore/_sync/connection.py", line 103, in handle_request
    return self._connection.handle_request(request)
  File "/python3.10/site-packages/httpcore/_sync/http11.py", line 133, in handle_request
    raise exc
  File "/python3.10/site-packages/httpcore/_sync/http11.py", line 94, in handle_request
    self._send_request_body(**kwargs)
  File "/python3.10/site-packages/httpcore/_sync/http11.py", line 154, in _send_request_body
    for chunk in request.stream:
  File "/python3.10/site-packages/httpx/_multipart.py", line 264, in __iter__
    for chunk in self.iter_chunks():
  File "/python3.10/site-packages/httpx/_multipart.py", line 230, in iter_chunks
    yield from field.render()
  File "/python3.10/site-packages/httpx/_multipart.py", line 190, in render
    yield from self.render_data()
  File "/python3.10/site-packages/httpx/_multipart.py", line 183, in render_data
    chunk = self.file.read(self.CHUNK_SIZE)
AttributeError: 'int' object has no attribute 'read'. Did you mean: 'real'?

OpenAPI Spec File

(Minimimized)

  /t/{id}/:
    patch:
      operationId: 
      description: |-
        T
      parameters:
      - in: path
        name: id
        schema:
          type: integer
        description: 
        required: true
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TRequest'
      security:
      - jwtAuth: []
      - basicAuth: []
      - cookieAuth: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TModel'
          description: ''
components:
  schemas:
    TRequest:
      type: object
      properties:
        file:
          type: string
          format: binary
        label:
          type: string
          minLength: 1
        flag:
          type: boolean
        project:
          type: integer
        parent:
          type: integer
          nullable: true

Desktop:

  • OS: macOS 13.6
  • Python Version: 3.10.13
  • openapi-python-client version: 0.17.0

Additional context

  • httpx 0.26.0
  • OpenAPI schema 3.0.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions