如何在flask全局上下文g中添加python类型注释? [英] How can I add python type annotations to the flask global context g?

查看:181
本文介绍了如何在flask全局上下文g中添加python类型注释?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个装饰器,可以将用户添加到烧瓶全局上下文g中:

 class User:
    def __init__(self, user_data) -> None:
        self.username: str = user_data["username"]
        self.email: str = user_data["email"]

def login_required(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        user_data = get_user_data()
        user = User(user_data)
        g.user = User(user_data)

        return f(*args, **kwargs)

    return wrap
 

我想在控制器中访问g.user时知道g.user的类型(用户).我怎样才能做到这一点? (我正在使用pyright)

解决方案

我在对动态添加的属性进行类型检查中遇到了类似的问题

一个>.一种解决方案是使用 typing.TYPE_CHECKING :

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from flask.ctx import _AppCtxGlobals

    class MyGlobals(_AppCtxGlobals):
        user: 'User'

    g = MyGlobals()
else:
    from flask import g

现在例如

reveal_type(g.user)

会发射

note: Revealed type is 'myapp.User'

如果自定义类型应在多个模块中重用,则可以为flask引入部分存根.存根的位置取决于类型检查器,例如mypyMYPY_PATH环境变量读取自定义存根,pyright在项目根目录等中查找typings目录.部分存根的示例:

# _typeshed/flask/__init__.pyi

from typing import Any
from flask.ctx import _AppCtxGlobals
from models import User


def __getattr__(name: str) -> Any: ...  # incomplete


class MyGlobals(_AppCtxGlobals):
    user: User
    def __getattr__(self, name: str) -> Any: ...  # incomplete


g: MyGlobals

I have a decorator which adds a user onto the flask global context g:

class User:
    def __init__(self, user_data) -> None:
        self.username: str = user_data["username"]
        self.email: str = user_data["email"]

def login_required(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        user_data = get_user_data()
        user = User(user_data)
        g.user = User(user_data)

        return f(*args, **kwargs)

    return wrap

I want the type (User) of g.user to be known when I access g.user in the controllers. How can I achieve this? (I am using pyright)

I had a similar issue described in Typechecking dynamically added attributes. One solution is to add the custom type hints using typing.TYPE_CHECKING:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from flask.ctx import _AppCtxGlobals

    class MyGlobals(_AppCtxGlobals):
        user: 'User'

    g = MyGlobals()
else:
    from flask import g

Now e.g.

reveal_type(g.user)

will emit

note: Revealed type is 'myapp.User'

If the custom types should be reused in multiple modules, you can introduce a partial stub for flask. The location of the stubs is dependent on the type checker, e.g. mypy reads custom stubs from the MYPY_PATH environment variable, pyright looks for a typings directory in the project root dir etc. Example of a partial stub:

# _typeshed/flask/__init__.pyi

from typing import Any
from flask.ctx import _AppCtxGlobals
from models import User


def __getattr__(name: str) -> Any: ...  # incomplete


class MyGlobals(_AppCtxGlobals):
    user: User
    def __getattr__(self, name: str) -> Any: ...  # incomplete


g: MyGlobals

这篇关于如何在flask全局上下文g中添加python类型注释?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆