2026-01-22 11:55:42 +08:00

114 lines
2.9 KiB
Python

from dataclasses import dataclass
from typing import Any, Dict, List, Optional
@dataclass(frozen=True)
class MissingParam:
name: str
type: Optional[str]
description: Optional[str]
@dataclass(frozen=True)
class ResolvedParams:
params: Dict[str, Any]
@dataclass(frozen=True)
class MissingParams:
missing: List[MissingParam]
class ParameterResolver:
TYPE_MAP = {
"string": str,
"integer": int,
"number": (int, float),
"boolean": bool,
"array": list,
"object": dict,
}
def __init__(self, schema: Dict[str, dict]):
self.schema = schema
def resolve(self, params: Dict[str, Any]):
validated = {}
missing = []
for name, spec in self.schema.items():
required = spec.get("required", False)
default = spec.get("default")
expected_type = spec.get("type")
enum = spec.get("enum")
description = spec.get("description")
if name in params:
value = params[name]
else:
if required:
missing.append(
MissingParam(
name=name,
type=expected_type,
description=description,
)
)
continue
value = default
if value is None:
validated[name] = value
continue
# 类型校验
if expected_type:
py_type = self.TYPE_MAP.get(expected_type)
if py_type and not isinstance(value, py_type):
missing.append(
MissingParam(
name=name,
type=expected_type,
description=f"Invalid type, expected {expected_type}",
)
)
continue
# enum 校验
if enum and value not in enum:
missing.append(
MissingParam(
name=name,
type=expected_type,
description=f"Invalid value, must be one of {enum}",
)
)
continue
validated[name] = value
if missing:
return MissingParams(missing=missing)
return ResolvedParams(params=validated)
if __name__ == '__main__':
params = {'a': 12312, 'op': '*', 'b': 233}
schema = {
"a": {
"type": "int or float",
"required": True,
"description": "计算左值"
},
"op": {
"type": "str",
"required": True,
"description": "计算方法",
"enum": ["+", "-", "*", "/"]
},
"b": {
"type": "int or float",
"required": True,
"description": "计算左值"
}
}
p = ParameterResolver(schema)
x = p.resolve(params)
print(x)