|
@@ -9,7 +9,7 @@ from contextlib import contextmanager
|
|
|
from enum import Enum, auto
|
|
from enum import Enum, auto
|
|
|
from functools import reduce
|
|
from functools import reduce
|
|
|
from types import SimpleNamespace, NoneType
|
|
from types import SimpleNamespace, NoneType
|
|
|
-from typing import Annotated, Any, Callable, Iterator, Literal, overload
|
|
|
|
|
|
|
+from typing import Annotated, Any, Callable, Iterator, Literal, Self, final, overload
|
|
|
|
|
|
|
|
from pydantic import BaseModel, Field
|
|
from pydantic import BaseModel, Field
|
|
|
from pydantic_core import PydanticUndefined
|
|
from pydantic_core import PydanticUndefined
|
|
@@ -39,6 +39,11 @@ class Inputs(BaseModel):
|
|
|
class Outputs(BaseModel):
|
|
class Outputs(BaseModel):
|
|
|
"""Stub class describing result data"""
|
|
"""Stub class describing result data"""
|
|
|
|
|
|
|
|
|
|
+ @final
|
|
|
|
|
+ def validated(self) -> Self:
|
|
|
|
|
+ """Validate this output object, affirm that it is properly constructed"""
|
|
|
|
|
+ return self.model_validate(self, extra="forbid")
|
|
|
|
|
+
|
|
|
|
|
|
|
|
@dataclasses.dataclass
|
|
@dataclasses.dataclass
|
|
|
class Ref:
|
|
class Ref:
|
|
@@ -144,7 +149,6 @@ class Context(SimpleNamespace):
|
|
|
fields[name] = self(fld.default)
|
|
fields[name] = self(fld.default)
|
|
|
|
|
|
|
|
model = annotation(**fields)
|
|
model = annotation(**fields)
|
|
|
- _validate(model)
|
|
|
|
|
setattr(state, attr, model)
|
|
setattr(state, attr, model)
|
|
|
return model
|
|
return model
|
|
|
|
|
|
|
@@ -181,19 +185,3 @@ class Action(BaseModel, abc.ABC):
|
|
|
|
|
|
|
|
def cleanup(self, context: Context) -> None:
|
|
def cleanup(self, context: Context) -> None:
|
|
|
"""Optionally clean up after ourselves"""
|
|
"""Optionally clean up after ourselves"""
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-def _validate(model: BaseModel):
|
|
|
|
|
- """Perform the actual model validation that we sabotaged w/ required() and similar functions"""
|
|
|
|
|
- for k, fld in model.__pydantic_fields__.items():
|
|
|
|
|
- attr = getattr(model, k)
|
|
|
|
|
- if fld.annotation is None or isinstance(attr, fld.annotation):
|
|
|
|
|
- continue
|
|
|
|
|
-
|
|
|
|
|
- if isinstance(attr, (Ref, Factory, NoneType)):
|
|
|
|
|
- raise TypeError(f"fld '{k}' in {type(model).__qualname__} is unset")
|
|
|
|
|
-
|
|
|
|
|
- raise TypeError(
|
|
|
|
|
- f"field '{k}' in {type(model).__qualname__} is of the wrong type "
|
|
|
|
|
- f"(should be {fld.annotation})"
|
|
|
|
|
- )
|
|
|