首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使pyright/PyCharm识别装饰器设置的参数

使pyright/PyCharm识别装饰器设置的参数
EN

Stack Overflow用户
提问于 2022-03-02 17:59:54
回答 1查看 710关注 0票数 2

我有下面的装饰函数( serialize_request来自api-client-pydantic的简化版本),它应该在一个函数上使用,该函数接受任意数量的pydantic模型作为参数。它用传递给它的参数初始化这些模型,然后使用这些模型作为参数调用包装函数。

代码语言:javascript
复制
def serialize(extra_kwargs: Dict[str, Any] = None) -> Callable:
    extra_kw = extra_kwargs or {"by_alias": True, "exclude_none": True}

    def decorator(func: Callable) -> Callable:
        map_schemas = {}
        map_params = {}
        parameters = []

        for arg_name, arg_type in get_type_hints(func).items():
            if arg_name == "return":
                continue
            map_schemas[arg_name] = arg_type
            if inspect.isclass(arg_type) and issubclass(arg_type, BaseModel):
                # the model's signature contains only aliases
                arg_fields = list(arg_type.__fields__.keys())
                arg_params = inspect.signature(arg_type).parameters
                map_params[arg_name] = set(list(arg_params.keys()) + arg_fields)
                parameters.extend(list(arg_params.values()))

        @wraps(func)
        def wrap(*args, **kwargs):
            if map_schemas:
                data, origin_kwargs = {}, {}
                for arg_name, arg_type in map_schemas.items():
                    if inspect.isclass(arg_type) and issubclass(arg_type, BaseModel):
                        arg_kwargs = {
                            k: v for k, v in kwargs.items() if k in map_params[arg_name]
                        }
                        data[arg_name] = parse_obj_as(arg_type, arg_kwargs).dict(
                            **extra_kw
                        )
                    else:
                        val = kwargs.get(arg_name)
                        if val is not None:
                            origin_kwargs[arg_name] = val
                new_kwargs = {**origin_kwargs, **data} or kwargs
                return func(*args, **new_kwargs)
            return func(*args, **kwargs)

        # Override signature
        if parameters:
            sig = inspect.signature(func)
            _self_param = sig.parameters.get("self")
            self_param = [_self_param] if _self_param else []
            sig = sig.replace(parameters=tuple(self_param + parameters))
            wrap.__signature__ = sig  # type: ignore

        return wrap

    return decorator

通过覆盖签名,ipython等工具识别新参数并在弹出帮助中显示它们。例如,使用以下模型和功能:

代码语言:javascript
复制
class ModelA(BaseModel):
    a: str
    b: int


class ModelB(BaseModel):
    one: float
    two: Optional[str] = None


@serialize()
def foo(model_a: ModelA, model_b: ModelB):
    print(model_a)
    print(model_b)

在PyCharm中:

在纯ipython中:

但是pyright不认识它们,并显示了一个错误:

我不知道PyCharm内部使用什么,但它也不承认新的参数。但是,它没有显示错误,它只是接受任何有效的参数,也没有:

现在,我的问题是,是否有某种方法可以使pyright/PyCharm和类似的工具识别由修饰器设置的“新”参数,并使它们表现得好像参数是直接在函数上设置的一样。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-04 04:59:33

不,在Python当前的输入系统中没有这样的方法。

这些都是你需要用到的材料:

但你所描述的远远超出了他们的能力。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71327196

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档