fastapi icon indicating copy to clipboard operation
fastapi copied to clipboard

Query parameter type is not instantiated using __new__

Open chbndrhnns opened this issue 2 years ago • 2 comments

First Check

  • [X] I added a very descriptive title to this issue.
  • [X] I used the GitHub search to find a similar issue and didn't find it.
  • [X] I searched the FastAPI documentation, with the integrated search.
  • [X] I already searched in Google "How to X in FastAPI" and didn't find any information.
  • [X] I already read and followed all the tutorial in the docs and didn't find an answer.
  • [X] I already checked if it is not related to FastAPI but to Pydantic.
  • [X] I already checked if it is not related to FastAPI but to Swagger UI.
  • [X] I already checked if it is not related to FastAPI but to ReDoc.

Commit to Help

  • [X] I commit to help with one of those options 👆

Example Code

from datetime import datetime

import fastapi
import httpx
import pytest
from fastapi import FastAPI

app = FastAPI()


class CustomDate(datetime):
    def __new__(cls, *args, **kwargs):
        try:
            parsed = datetime.strptime(args[0], "%Y-%m-%dT%H:%M:%S.%f%z")
            return super().__new__(cls, parsed.year + 1, month=parsed.month,
                                   day=parsed.day)
        except TypeError:
            return super().__new__(cls, *args, **kwargs)


@app.get("/")
async def get(begin: CustomDate = fastapi.Query()):
    return {"data": begin}


@pytest.fixture
def anyio_backend():
    return "asyncio"




def test_can_create_CustomDate():
    timestamp = "2022-10-20T18:25:43.511Z"
    assert str(CustomDate(timestamp)).startswith("2023")


@pytest.mark.anyio
async def test_():
    timestamp = "2022-10-20T18:25:43.511Z"

    async with httpx.AsyncClient(app=app, base_url="http://127.0.0.1") as client:
        res = await client.get("/", params={"begin": timestamp})
        assert res.status_code == 200
        assert res.json()["data"].startswith("2023")

Description

I have a simple subclass of datetime.datetime with customized parsing. (Please ignore the specifics, I just wanted to highlight the problem). The __new__ method of my subclass is not being called which means the customized parsing is not happening when using the type as an annotation on a query parameter.

The reason why I am doing it is to make use of the FastAPI validations and not needing to validate the value further down in my code. I can re-create the instance manually to trigger the __new__ method and then fail manually but this feels strange.

Operating System

macOS

Operating System Details

No response

FastAPI Version

0.89.1

Python Version

3.9.6

Additional Context

No response

chbndrhnns avatar Jan 11 '23 09:01 chbndrhnns

It's better to use DI to create specific type

yinziyan1206 avatar Jan 11 '23 17:01 yinziyan1206

It's better to use DI to create specific type

Better how? At least the current behaviour is unexpected to me.

chbndrhnns avatar Jan 11 '23 18:01 chbndrhnns