使用functools.wraps函数与一些不同的参数列表

发布于 2025-02-08 07:17:33 字数 1196 浏览 2 评论 0原文

我想做这样的事情:

def need_session(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        session = SessionLocal()
        try:
            func(session, *args, **kwargs)
        finally:
            session.close()

我正在使用wraps函数,因为我正在使用草莓,取决于参数类型。

如您所见,给出了func一个额外的session参数。

我该如何完成这项工作?

如果我尝试使用具有上面装饰器装饰的功能的草莓运行GraphQl Server,则会给我这个错误:

TypeError:无法解决突变场。意外的类型'< class'sqlalchemy.orm.session.session'>'

如果我将装饰器更改为:

def need_session(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        session = SessionLocal()
        kwargs['session'] = session
        try:
            func(*args, **kwargs)
        finally:
            session.close()

并将装饰的函数的参数列表更改为:

def some_func(some_arg: SomeClass, **kwargs):
    ...

我仍然会遇到此错误:

strawberry.exceptions.missingargumentsAnnotationsError:缺少参数的注释“ Kwargs”字段“ login_user”,您是否忘记了添加它?

I want to do something like this:

def need_session(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        session = SessionLocal()
        try:
            func(session, *args, **kwargs)
        finally:
            session.close()

I'm using the wraps function, because I'm using Strawberry, which depends on argument types.

As you can see, func is given an extra session argument.

How can I make this work?

If I try to run a GraphQL server using Strawberry that has functions that are decorated using the decorator above, it gives me this error:

TypeError: Mutation fields cannot be resolved. Unexpected type '<class 'sqlalchemy.orm.session.Session'>'

If I change the decorator to this:

def need_session(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        session = SessionLocal()
        kwargs['session'] = session
        try:
            func(*args, **kwargs)
        finally:
            session.close()

And change the decorated function's argument list to:

def some_func(some_arg: SomeClass, **kwargs):
    ...

I still get this error:

strawberry.exceptions.MissingArgumentsAnnotationsError: Missing annotation for argument "kwargs" in field "login_user", did you forget to add it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

纵情客 2025-02-15 07:17:33

为什么错误

您会得到此例外,因为草莓不支持** kwargs,每个strawberry.field.field必须为所有参数提供注释。它们由strawberry.type装饰器处理,因此您无法修改功能签名。

可能的解决方案1:

您可以通过编写架构扩展名来提供草莓信息内部的会话。

示例:

from strawberry.extensions import Extension
from mydb import get_db_session


class DbSessionMiddleWare(Extension):
    def on_request_start(self):
        self.execution_context.context["db"] = get_db_session()

    def on_request_end(self):
        self.execution_context.context["db"].close()

schema = strawberry.Schema(
    query=Queries,
    mutation=Mutations,
    extensions=[
        DbSessionMiddleWare,
    ],
)

一些解析器:

from strawberry.types import Info


def resolve_name(info: Info):
    name = info.context['db'].execute("SELECT ...")

可能的解决方案2:

您可以用自己的装饰器包裹草莓装饰器,并根据需要注入一些注释。
请记住,您应该清除任何*args** kwargs从功能签名的其他方式,草莓会抱怨这一点。

例子:

from strawberry.arguments import StrawberryArgument, StrawberryAnnotation, UNSET
import inspect

def create_strawberry_argument(
    python_name: str, graphql_name: str, type_, default=None
):
    return StrawberryArgument(
        python_name=python_name,
        graphql_name=graphql_name,
        type_annotation=StrawberryAnnotation(type_),
        default=default or UNSET,
    )

def hide_args_kwargs(field):

    sig = inspect.signature(field)
    cleared = tuple(
        p for p in sig.parameters.values() if p.name not in ("kwargs", "args")
    )
    field.__signature__ = inspect.signature(field).replace(parameters=(cleared))
    return field

def inject_mutation(field, arguments: tuple[str, type]):
    field = hide_args_kwargs(field)
    field = strawberry.mutation(field, description=field.__doc__)
    for arg_tuple in arguments:
        arg = create_strawberry_argument(arg_tuple[0], arg_tuple[0], arg_tuple[1])
        field.arguments.append(arg)
    return field

@inject_mutation(('arg2', int))
def some_resolver(info, arg1, **kwargs) -> SomeOutputType:
    f = kwargs.get('arg2', None)

Why the error?

You get this exception because Strawberry doesn't support **kwargs and every strawberry.field must have annotations for all arguments. And they are processed by the strawberry.type decorator, so you can’t modify the function signature.

Possible solution 1:

You can provide the session inside the Strawberry Info by writing a schema extension.

Example:

from strawberry.extensions import Extension
from mydb import get_db_session


class DbSessionMiddleWare(Extension):
    def on_request_start(self):
        self.execution_context.context["db"] = get_db_session()

    def on_request_end(self):
        self.execution_context.context["db"].close()

schema = strawberry.Schema(
    query=Queries,
    mutation=Mutations,
    extensions=[
        DbSessionMiddleWare,
    ],
)

Some resolver:

from strawberry.types import Info


def resolve_name(info: Info):
    name = info.context['db'].execute("SELECT ...")

Possible solution 2:

You can wrap Strawberry decorators with your own decorator and inject some annotations as you wish.
Remember that you should clear any *args or **kwargs from the function signature other ways strawberry would complain about this.

Example:

from strawberry.arguments import StrawberryArgument, StrawberryAnnotation, UNSET
import inspect

def create_strawberry_argument(
    python_name: str, graphql_name: str, type_, default=None
):
    return StrawberryArgument(
        python_name=python_name,
        graphql_name=graphql_name,
        type_annotation=StrawberryAnnotation(type_),
        default=default or UNSET,
    )

def hide_args_kwargs(field):

    sig = inspect.signature(field)
    cleared = tuple(
        p for p in sig.parameters.values() if p.name not in ("kwargs", "args")
    )
    field.__signature__ = inspect.signature(field).replace(parameters=(cleared))
    return field

def inject_mutation(field, arguments: tuple[str, type]):
    field = hide_args_kwargs(field)
    field = strawberry.mutation(field, description=field.__doc__)
    for arg_tuple in arguments:
        arg = create_strawberry_argument(arg_tuple[0], arg_tuple[0], arg_tuple[1])
        field.arguments.append(arg)
    return field

@inject_mutation(('arg2', int))
def some_resolver(info, arg1, **kwargs) -> SomeOutputType:
    f = kwargs.get('arg2', None)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文