How do I get static code analysis type support for enums (not just runtime support)?

I’m going through the FastAPI documentation tutorial and there’s a section where I create an enum for a path parameter (Path Parameters - FastAPI). My code ends up looking like this when I copy and paste it from the page:

from enum import Enum

from fastapi import FastAPI


class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


app = FastAPI()


@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name == ModelName.alexnet:
        return {"model_name": model_name, "message": "Deep Learning FTW!"}

    if model_name.value == "lenet":
        return {"model_name": model_name, "message": "LeCNN all the images"}

    return {"model_name": model_name, "message": "Have some residuals"}

I’m a bit new to Python still, especially trying to understand how type hints work. Coming from other programming languages, a few of which are compiled, I was expecting to be able to get type hinting hints in my code editor (VS Code in this case) if I accidentally tried to assign the wrong type to an enum value. And I expected my code editor to be able to warn me about this using a linter or some other static code analysis tool, so that I wouldn’t have to run the code to get an error.

For example, I expected this to produce a warning in VS Code:

# switch str to int
class ModelName(int, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"

But it doesn’t:

<tried to post screenshots but can’t because I’m new>

I do get an error as I try to boot up the application, which is still pretty helpful. At least this would, for example, prevent my application from starting, resulting in it failing health checks, before any production traffic is shifted over to it:

...
class ModelName(int, Enum):
  File "/home/matt/.pyenv/versions/3.10.5/lib/python3.10/enum.py", line 289, in __new__
    enum_member = __new__(enum_class, *args)
ValueError: invalid literal for int() with base 10: 'alexnet'

I do have autopep8 installed under my dev dependencies in my pyproject.toml file. VS Code prompted me to install a static analysis tool when I first tried to use “Format Document”, and it automatically installed that dependency when I accepted the prompt. I think I do have static code analysis working in VS Code in general, because some other errors do cause warnings:

<tried to post screenshot but can’t because I’m new>

Is this feature something the type hinting system in Python is meant to support? To be able to detect problems like this before code is executed?

1 Like

In my experience, python’s enums are pretty bad with typing. For example, pylance doesn’t respect the return type of _generate_next_value_ (however, mypy does).

Such cases require some work which I’d love to do if I knew a bit more details. If any core dev is reading it and wants to assist a little bit – I would greatly appreciate it!

I checked: both mypy (v0.971) and pylance (v2022.7.40) on python 3.11.0b4 do not give any errors even in strict mode for the following code:

from enum import Enum

class A(int, Enum):
    a = "such_string"
    b = 1

class B(str, Enum):
    a = "such_string"
    b = 1

1 Like

This does not solve your specific issue but if you want to improve the support of enums (and especially StrEnum) in vscode, I would greatly appreciate if you (and everyone reading it) added a thumbs up to this post:

It is closed but only because the maintainer doesn’t want to implement better support for enums until we get enough people putting thumbs up.

1 Like

Thanks for the replies. I’d say this is pretty low on my list of priorities. While I don’t get VS Code warnings about the error, it does raise an error as soon as I run the application. That’s still pretty good for me. I was just mentioning this here because I find diving deep into stuff like this can be useful for learning.

It looks like the maintainers at Pyright does not respect `_generate_next_value_` overrides in enums · Issue #3742 · microsoft/pyright · GitHub disagreed regarding how important this one. Maybe this is one of those situations where it isn’t worth the effort to try to add typing. Maybe Python is too dynamic for this.

That issue is actually an example of why you shouldn’t give up your hopes. Eric Traut has reversed his decision and has already implemented it!

Wow, that’s neat.

This is addressed in pyright 1.1.264, which I just published. It will also be included in a future release of pylance.

So do you mind clarifying something for me? I don’t yet understand Python enough to know whether this change in pyright affects what I was doing here. Does it? And if so, how would this change in pyright translate to a different experience in VS Code? Would I wait for the VS Code extension maintainers to package it in an extension update? Does the Pylance extension depend on pyright as a way of implementing static code analysis?

Sadly, this one doesn’t. It does help us to check whether we’re using MyEnum.enum_member.value correctly if we use enum.auto().

Pylance is dependent on pyright. That update above will be available in pylance in its august release but it’s already available in pyright.

I suggest you try other linters such as flake8 for your issue. If none of them detect your error, you could ask mypy/pyright maintainers or even submit a pull request.