我有下面的装饰函数( serialize_request来自api-client-pydantic的简化版本),它应该在一个函数上使用,该函数接受任意数量的pydantic模型作为参数。它用传递给它的参数初始化这些模型,然后使用这些模型作为参数调用包装函数。
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等工具识别新参数并在弹出帮助中显示它们。例如,使用以下模型和功能:
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和类似的工具识别由修饰器设置的“新”参数,并使它们表现得好像参数是直接在函数上设置的一样。
发布于 2022-07-04 04:59:33
不,在Python当前的输入系统中没有这样的方法。
这些都是你需要用到的材料:
但你所描述的远远超出了他们的能力。
https://stackoverflow.com/questions/71327196
复制相似问题