1 year ago

#71475

test-img

Freddy The Horse

Pyright type error with Flask error handler

I'm working my way towards strict type checking using Pyright, and I'm running into an issue with a Flask error handler. I'm not yet familiar enough with type hints to know if this is an error in my code, in Pyright, or in Flask's type hints.

This is the code causing me issues:

from werkzeug.exceptions import NotFound

def init_app(app: Flask):
    app.register_error_handler(NotFound, page_not_found_handler)

def page_not_found_handler(e: Exception):
    return render_template("404.html"), 404

The above code generates this type error in VSCode:

Argument of type "(e: Exception) -> tuple[str, Literal[404]]" cannot be assigned to parameter "f" of type "ErrorHandlerCallable" in function "register_error_handler"
  Type "(e: Exception) -> tuple[str, Literal[404]]" cannot be assigned to type "ErrorHandlerCallable"
    Function return type "tuple[str, Literal[404]]" is incompatible with type "ResponseReturnValue[Unknown]"
      Type "tuple[str, Literal[404]]" cannot be assigned to type "ResponseReturnValue[Unknown]"
        "tuple[str, Literal[404]]" is incompatible with "Response"
        Type "tuple[str, Literal[404]]" cannot be assigned to type "AnyStr@ResponseValue"
        "tuple[str, Literal[404]]" is incompatible with "Dict[str, Any]"
        "tuple[str, Literal[404]]" is incompatible with "Generator[AnyStr@ResponseValue, None, None]"
        Tuple entry 1 is incorrect typePylancereportGeneralTypeIssues

I can improve the problem by adding an explicit return type to my error handler:

def page_not_found_handler(e: Exception) -> flask.typing.ResponseReturnValue:
    ....

This removes the previous error and replaces it with this one:

Expression of type "tuple[str, Literal[404]]" cannot be assigned to return type "ResponseReturnValue[Unknown]"
  Type "tuple[str, Literal[404]]" cannot be assigned to type "ResponseReturnValue[Unknown]"
    "tuple[str, Literal[404]]" is incompatible with "Response"
    Type "tuple[str, Literal[404]]" cannot be assigned to type "AnyStr@ResponseValue"
    "tuple[str, Literal[404]]" is incompatible with "Dict[str, Any]"
    "tuple[str, Literal[404]]" is incompatible with "Generator[AnyStr@ResponseValue, None, None]"
    Tuple entry 1 is incorrect type
      Type "str" cannot be assigned to type "ResponseValue[Unknown]"
        "str" is incompatible with "Response"

So I looked into the flask.typing.ResponseValue type. It's a union type defined like this:

# The possible types that are directly convertible or are a Response object.
ResponseValue = t.Union[
    "Response",
    t.AnyStr,
    t.Dict[str, t.Any],  # any jsonify-able dict
    t.Generator[t.AnyStr, None, None],
]

As an experiment, I modified the version of flask.typing in my virtual environment and added str to the possible values. This removed all of the errors.

Why aren't str and AnyStr compatible here? It seems to me that AnyStr should be able to accept a str value.

If this isn't an issue with my code, is it a Flask or a Pyright problem?

Thanks!

python

flask

python-typing

pyright

0 Answers

Your Answer

Accepted video resources