Fastapi: Unexpected response with the verification of the modified Enum class

Created on 25 Nov 2020  Â·  5Comments  Â·  Source: tiangolo/fastapi

Example

For string enum generation, there is a convenient way as the Python official docs said:

from enum import Enum,auto
class Enum0(str,Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name
    A = auto()
    B = auto()

And this enum class is equivalent to the following:

class Enum1(str,Enum):
    A = 'A'
    B = 'B'

Both of them work with the below FastAPI code(change type hint to each class before run):

from fastapi import FastAPI

app = FastAPI()
@app.get("/model/{mod}")
async def model(mod:Enum0):
    return {'msg':mod,'val':mod.value}

However, when I write a self-defined enum class like this:

class Enum2(str,Enum):
    def __init__(self):
        self._value_ = self.name
        super().__init__()
    A = ()
    B = ()

It doesn't work with the previous model(mod) callable.

Description

  • Open the browser and call the endpoint /model/A.
  • It returns a JSON with {"detail":[{"loc":["path","mod"],"msg":"value is not a valid enumeration member; permitted: 'A', 'B'","type":"type_error.enum","ctx":{"enum_values":["A","B"]}}]}.
  • But I expected it to return {"msg":"A","val":"A"}.
  • I compared the Enum1 and the Enum2, and can not find any valuable difference.

Environment

  • OS: Windows 10 x64, 10.0.19042.630
  • FastAPI Version: 0.61.2
  • Python Version: 3.8.5 x64

Additional context

question

Most helpful comment

Your Enum2 doesn't work in pydantic for the same reason the following code doesn't work without pydantic:

from enum import Enum

class​ ​Enum2​(​str​,​Enum​):
    ​def​ ​__init__​(​self​):
        ​self​.​_value_​ ​=​ ​self​.​name​
        ​super​().​__init__​()
    ​A​ ​=​ ()
    ​B​ ​=​ ()

Enum2('A') # ValueError: 'A' is not a valid Enum2

You could argue that this is a bug in either your code, or a bug in the enum library, but either way it doesn't work

All 5 comments

Do you mean to be doing

A = auto()
B = auto()

Instead?

Looking further into this, I don't think it's possible to do what you are trying to do, due to limitations in python's enum library. This is due to the name for an enum being set after the value is retrieved. This limitation has nothing to do with fastapi or pydantic

@Mause I mean, why the effect was different between example Enum0 and Enum2? Logically they do the same thing and generate the same result. It maybe something wrong when the Pydantic loads the enum class, but I'm not sure how to dive into it.

Your Enum2 doesn't work in pydantic for the same reason the following code doesn't work without pydantic:

from enum import Enum

class​ ​Enum2​(​str​,​Enum​):
    ​def​ ​__init__​(​self​):
        ​self​.​_value_​ ​=​ ​self​.​name​
        ​super​().​__init__​()
    ​A​ ​=​ ()
    ​B​ ​=​ ()

Enum2('A') # ValueError: 'A' is not a valid Enum2

You could argue that this is a bug in either your code, or a bug in the enum library, but either way it doesn't work

@Mause Thanks. I think your code shows the problem that my code broke the relationship between enum class and enum members.

Was this page helpful?
0 / 5 - 0 ratings