vellum-ai 0.13.27__py3-none-any.whl → 0.14.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vellum/client/core/client_wrapper.py +1 -1
- vellum/workflows/constants.py +8 -3
- vellum/workflows/descriptors/exceptions.py +2 -0
- vellum/workflows/descriptors/tests/test_utils.py +21 -0
- vellum/workflows/descriptors/utils.py +3 -3
- vellum/workflows/errors/types.py +4 -1
- vellum/workflows/expressions/accessor.py +4 -3
- vellum/workflows/expressions/begins_with.py +3 -2
- vellum/workflows/expressions/between.py +4 -3
- vellum/workflows/expressions/coalesce_expression.py +2 -2
- vellum/workflows/expressions/contains.py +10 -2
- vellum/workflows/expressions/does_not_begin_with.py +3 -2
- vellum/workflows/expressions/does_not_contain.py +6 -2
- vellum/workflows/expressions/does_not_end_with.py +3 -2
- vellum/workflows/expressions/ends_with.py +3 -2
- vellum/workflows/expressions/greater_than.py +3 -2
- vellum/workflows/expressions/greater_than_or_equal_to.py +3 -2
- vellum/workflows/expressions/in_.py +2 -1
- vellum/workflows/expressions/is_blank.py +2 -1
- vellum/workflows/expressions/is_nil.py +2 -2
- vellum/workflows/expressions/is_not_blank.py +2 -1
- vellum/workflows/expressions/is_not_nil.py +2 -2
- vellum/workflows/expressions/is_not_undefined.py +2 -2
- vellum/workflows/expressions/is_undefined.py +2 -2
- vellum/workflows/expressions/less_than.py +3 -2
- vellum/workflows/expressions/less_than_or_equal_to.py +3 -2
- vellum/workflows/expressions/not_between.py +4 -3
- vellum/workflows/expressions/not_in.py +2 -1
- vellum/workflows/nodes/bases/base.py +21 -7
- vellum/workflows/nodes/bases/tests/test_base_node.py +84 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +3 -3
- vellum/workflows/nodes/core/map_node/node.py +5 -0
- vellum/workflows/nodes/core/map_node/tests/test_node.py +22 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +8 -3
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +19 -9
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +68 -2
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +30 -7
- vellum/workflows/outputs/base.py +21 -19
- vellum/workflows/ports/port.py +14 -5
- vellum/workflows/references/external_input.py +2 -2
- vellum/workflows/references/lazy.py +2 -2
- vellum/workflows/references/output.py +7 -7
- vellum/workflows/runner/runner.py +20 -15
- vellum/workflows/state/base.py +2 -2
- vellum/workflows/state/tests/test_state.py +7 -11
- vellum/workflows/utils/vellum_variables.py +3 -0
- vellum/workflows/workflows/base.py +20 -0
- vellum/workflows/workflows/tests/__init__.py +0 -0
- vellum/workflows/workflows/tests/test_base_workflow.py +80 -0
- {vellum_ai-0.13.27.dist-info → vellum_ai-0.14.0.dist-info}/METADATA +2 -1
- {vellum_ai-0.13.27.dist-info → vellum_ai-0.14.0.dist-info}/RECORD +57 -54
- vellum_cli/push.py +15 -1
- vellum_cli/tests/test_push.py +44 -0
- vellum_ee/workflows/display/nodes/base_node_display.py +2 -2
- {vellum_ai-0.13.27.dist-info → vellum_ai-0.14.0.dist-info}/LICENSE +0 -0
- {vellum_ai-0.13.27.dist-info → vellum_ai-0.14.0.dist-info}/WHEEL +0 -0
- {vellum_ai-0.13.27.dist-info → vellum_ai-0.14.0.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,7 @@ class BaseClientWrapper:
|
|
18
18
|
headers: typing.Dict[str, str] = {
|
19
19
|
"X-Fern-Language": "Python",
|
20
20
|
"X-Fern-SDK-Name": "vellum-ai",
|
21
|
-
"X-Fern-SDK-Version": "0.
|
21
|
+
"X-Fern-SDK-Version": "0.14.0",
|
22
22
|
}
|
23
23
|
headers["X_API_KEY"] = self.api_key
|
24
24
|
return headers
|
vellum/workflows/constants.py
CHANGED
@@ -4,11 +4,11 @@ from typing import Any, cast
|
|
4
4
|
|
5
5
|
class _UndefMeta(type):
|
6
6
|
def __repr__(cls) -> str:
|
7
|
-
return "
|
7
|
+
return "undefined"
|
8
8
|
|
9
9
|
def __getattribute__(cls, name: str) -> Any:
|
10
10
|
if name == "__class__":
|
11
|
-
# ensures that
|
11
|
+
# ensures that undefined.__class__ == undefined
|
12
12
|
return cls
|
13
13
|
|
14
14
|
return super().__getattribute__(name)
|
@@ -17,7 +17,12 @@ class _UndefMeta(type):
|
|
17
17
|
return False
|
18
18
|
|
19
19
|
|
20
|
-
class
|
20
|
+
class undefined(metaclass=_UndefMeta):
|
21
|
+
"""
|
22
|
+
A singleton class that represents an `undefined` value, mirroring the behavior of the `undefined`
|
23
|
+
value in TypeScript.
|
24
|
+
"""
|
25
|
+
|
21
26
|
pass
|
22
27
|
|
23
28
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import pytest
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.utils import resolve_value
|
4
|
+
from vellum.workflows.errors.types import WorkflowError, WorkflowErrorCode
|
4
5
|
from vellum.workflows.nodes.bases.base import BaseNode
|
5
6
|
from vellum.workflows.references.constant import ConstantValueReference
|
6
7
|
from vellum.workflows.state.base import BaseState
|
@@ -77,6 +78,24 @@ class DummyNode(BaseNode[FixtureState]):
|
|
77
78
|
(FixtureState.zeta["foo"], "bar"),
|
78
79
|
(ConstantValueReference(1), 1),
|
79
80
|
(FixtureState.theta[0], "baz"),
|
81
|
+
(
|
82
|
+
ConstantValueReference(
|
83
|
+
WorkflowError(
|
84
|
+
message="This is a test",
|
85
|
+
code=WorkflowErrorCode.USER_DEFINED_ERROR,
|
86
|
+
)
|
87
|
+
).contains("test"),
|
88
|
+
True,
|
89
|
+
),
|
90
|
+
(
|
91
|
+
ConstantValueReference(
|
92
|
+
WorkflowError(
|
93
|
+
message="This is a test",
|
94
|
+
code=WorkflowErrorCode.USER_DEFINED_ERROR,
|
95
|
+
)
|
96
|
+
).does_not_contain("test"),
|
97
|
+
False,
|
98
|
+
),
|
80
99
|
],
|
81
100
|
ids=[
|
82
101
|
"or",
|
@@ -122,6 +141,8 @@ class DummyNode(BaseNode[FixtureState]):
|
|
122
141
|
"accessor",
|
123
142
|
"constants",
|
124
143
|
"list_index",
|
144
|
+
"error_contains",
|
145
|
+
"error_does_not_contain",
|
125
146
|
],
|
126
147
|
)
|
127
148
|
def test_resolve_value__happy_path(descriptor, expected_value):
|
@@ -5,7 +5,7 @@ from typing import Any, Dict, Optional, Sequence, Set, TypeVar, Union, cast, ove
|
|
5
5
|
|
6
6
|
from pydantic import BaseModel
|
7
7
|
|
8
|
-
from vellum.workflows.constants import
|
8
|
+
from vellum.workflows.constants import undefined
|
9
9
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
10
10
|
from vellum.workflows.state.base import BaseState
|
11
11
|
|
@@ -93,10 +93,10 @@ def resolve_value(
|
|
93
93
|
|
94
94
|
def is_unresolved(value: Any) -> bool:
|
95
95
|
"""
|
96
|
-
Recursively checks if a value has an unresolved value, represented by
|
96
|
+
Recursively checks if a value has an unresolved value, represented by undefined.
|
97
97
|
"""
|
98
98
|
|
99
|
-
if value is
|
99
|
+
if value is undefined:
|
100
100
|
return True
|
101
101
|
|
102
102
|
if dataclasses.is_dataclass(value):
|
vellum/workflows/errors/types.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
2
|
from enum import Enum
|
3
|
-
from typing import Dict
|
3
|
+
from typing import Any, Dict
|
4
4
|
|
5
5
|
from vellum.client.types.vellum_error import VellumError
|
6
6
|
from vellum.client.types.vellum_error_code_enum import VellumErrorCodeEnum
|
@@ -26,6 +26,9 @@ class WorkflowError:
|
|
26
26
|
message: str
|
27
27
|
code: WorkflowErrorCode
|
28
28
|
|
29
|
+
def __contains__(self, item: Any) -> bool:
|
30
|
+
return item in self.message
|
31
|
+
|
29
32
|
|
30
33
|
_VELLUM_ERROR_CODE_TO_WORKFLOW_ERROR_CODE: Dict[VellumErrorCodeEnum, WorkflowErrorCode] = {
|
31
34
|
"INVALID_REQUEST": WorkflowErrorCode.INVALID_INPUTS,
|
@@ -6,6 +6,7 @@ from pydantic import BaseModel, GetCoreSchemaHandler
|
|
6
6
|
from pydantic_core import core_schema
|
7
7
|
|
8
8
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
9
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
9
10
|
from vellum.workflows.descriptors.utils import resolve_value
|
10
11
|
from vellum.workflows.state.base import BaseState
|
11
12
|
|
@@ -32,13 +33,13 @@ class AccessorExpression(BaseDescriptor[Any]):
|
|
32
33
|
|
33
34
|
if dataclasses.is_dataclass(base):
|
34
35
|
if isinstance(self._field, int):
|
35
|
-
raise
|
36
|
+
raise InvalidExpressionException("Cannot access field by index on a dataclass")
|
36
37
|
|
37
38
|
return getattr(base, self._field)
|
38
39
|
|
39
40
|
if isinstance(base, BaseModel):
|
40
41
|
if isinstance(self._field, int):
|
41
|
-
raise
|
42
|
+
raise InvalidExpressionException("Cannot access field by index on a BaseModel")
|
42
43
|
|
43
44
|
return getattr(base, self._field)
|
44
45
|
|
@@ -49,7 +50,7 @@ class AccessorExpression(BaseDescriptor[Any]):
|
|
49
50
|
index = int(self._field)
|
50
51
|
return base[index]
|
51
52
|
|
52
|
-
raise
|
53
|
+
raise InvalidExpressionException(f"Cannot get field {self._field} from {base}")
|
53
54
|
|
54
55
|
@classmethod
|
55
56
|
def __get_pydantic_core_schema__(
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -23,9 +24,9 @@ class BeginsWithExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
23
24
|
lhs = resolve_value(self._lhs, state)
|
24
25
|
rhs = resolve_value(self._rhs, state)
|
25
26
|
if not isinstance(lhs, str):
|
26
|
-
raise
|
27
|
+
raise InvalidExpressionException(f"Expected LHS to be a string, got {type(lhs)}")
|
27
28
|
|
28
29
|
if not isinstance(rhs, str):
|
29
|
-
raise
|
30
|
+
raise InvalidExpressionException(f"Expected RHS to be a string, got {type(rhs)}")
|
30
31
|
|
31
32
|
return lhs.startswith(rhs)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -25,14 +26,14 @@ class BetweenExpression(BaseDescriptor[bool], Generic[_V, _S, _E]):
|
|
25
26
|
def resolve(self, state: "BaseState") -> bool:
|
26
27
|
value = resolve_value(self._value, state)
|
27
28
|
if not isinstance(value, (int, float)):
|
28
|
-
raise
|
29
|
+
raise InvalidExpressionException(f"Expected a numeric value, got: {value.__class__.__name__}")
|
29
30
|
|
30
31
|
start = resolve_value(self._start, state)
|
31
32
|
if not isinstance(start, (int, float)):
|
32
|
-
raise
|
33
|
+
raise InvalidExpressionException(f"Expected a numeric start value, got: {start.__class__.__name__}")
|
33
34
|
|
34
35
|
end = resolve_value(self._end, state)
|
35
36
|
if not isinstance(end, (int, float)):
|
36
|
-
raise
|
37
|
+
raise InvalidExpressionException(f"Expected a numeric end value, got: {end.__class__.__name__}")
|
37
38
|
|
38
39
|
return start <= value <= end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import TypeVar, Union
|
2
2
|
|
3
|
-
from vellum.workflows.constants import
|
3
|
+
from vellum.workflows.constants import undefined
|
4
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
6
6
|
from vellum.workflows.state.base import BaseState
|
@@ -27,7 +27,7 @@ class CoalesceExpression(BaseDescriptor[Union[LHS, RHS]]):
|
|
27
27
|
|
28
28
|
def resolve(self, state: "BaseState") -> Union[LHS, RHS]:
|
29
29
|
lhs = resolve_value(self._lhs, state)
|
30
|
-
if lhs is not
|
30
|
+
if lhs is not undefined and lhs is not None:
|
31
31
|
return lhs
|
32
32
|
|
33
33
|
return resolve_value(self._rhs, state)
|
@@ -1,7 +1,10 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
|
+
from vellum.workflows.constants import undefined
|
3
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
6
|
from vellum.workflows.descriptors.utils import resolve_value
|
7
|
+
from vellum.workflows.errors.types import WorkflowError
|
5
8
|
from vellum.workflows.state.base import BaseState
|
6
9
|
|
7
10
|
LHS = TypeVar("LHS")
|
@@ -23,8 +26,13 @@ class ContainsExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
23
26
|
# Support any type that implements the in operator
|
24
27
|
# https://app.shortcut.com/vellum/story/4658
|
25
28
|
lhs = resolve_value(self._lhs, state)
|
26
|
-
|
27
|
-
|
29
|
+
# assumes that lack of is also false
|
30
|
+
if lhs is undefined:
|
31
|
+
return False
|
32
|
+
if not isinstance(lhs, (list, tuple, set, dict, str, WorkflowError)):
|
33
|
+
raise InvalidExpressionException(
|
34
|
+
f"Expected a LHS that supported `contains`, got `{lhs.__class__.__name__}`"
|
35
|
+
)
|
28
36
|
|
29
37
|
rhs = resolve_value(self._rhs, state)
|
30
38
|
return rhs in lhs
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -23,9 +24,9 @@ class DoesNotBeginWithExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
23
24
|
lhs = resolve_value(self._lhs, state)
|
24
25
|
rhs = resolve_value(self._rhs, state)
|
25
26
|
if not isinstance(lhs, str):
|
26
|
-
raise
|
27
|
+
raise InvalidExpressionException(f"Expected LHS to be a string, got {type(lhs)}")
|
27
28
|
|
28
29
|
if not isinstance(rhs, str):
|
29
|
-
raise
|
30
|
+
raise InvalidExpressionException(f"Expected RHS to be a string, got {type(rhs)}")
|
30
31
|
|
31
32
|
return not lhs.startswith(rhs)
|
@@ -1,7 +1,9 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
6
|
+
from vellum.workflows.errors.types import WorkflowError
|
5
7
|
from vellum.workflows.state.base import BaseState
|
6
8
|
|
7
9
|
LHS = TypeVar("LHS")
|
@@ -23,8 +25,10 @@ class DoesNotContainExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
23
25
|
# Support any type that implements the not in operator
|
24
26
|
# https://app.shortcut.com/vellum/story/4658
|
25
27
|
lhs = resolve_value(self._lhs, state)
|
26
|
-
if not isinstance(lhs, (list, tuple, set, dict, str)):
|
27
|
-
raise
|
28
|
+
if not isinstance(lhs, (list, tuple, set, dict, str, WorkflowError)):
|
29
|
+
raise InvalidExpressionException(
|
30
|
+
f"Expected a LHS that supported `contains`, got `{lhs.__class__.__name__}`"
|
31
|
+
)
|
28
32
|
|
29
33
|
rhs = resolve_value(self._rhs, state)
|
30
34
|
return rhs not in lhs
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -23,9 +24,9 @@ class DoesNotEndWithExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
23
24
|
lhs = resolve_value(self._lhs, state)
|
24
25
|
rhs = resolve_value(self._rhs, state)
|
25
26
|
if not isinstance(lhs, str):
|
26
|
-
raise
|
27
|
+
raise InvalidExpressionException(f"Expected LHS to be a string, got {type(lhs)}")
|
27
28
|
|
28
29
|
if not isinstance(rhs, str):
|
29
|
-
raise
|
30
|
+
raise InvalidExpressionException(f"Expected RHS to be a string, got {type(rhs)}")
|
30
31
|
|
31
32
|
return not lhs.endswith(rhs)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -23,9 +24,9 @@ class EndsWithExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
23
24
|
lhs = resolve_value(self._lhs, state)
|
24
25
|
rhs = resolve_value(self._rhs, state)
|
25
26
|
if not isinstance(lhs, str):
|
26
|
-
raise
|
27
|
+
raise InvalidExpressionException(f"Expected LHS to be a string, got {type(lhs)}")
|
27
28
|
|
28
29
|
if not isinstance(rhs, str):
|
29
|
-
raise
|
30
|
+
raise InvalidExpressionException(f"Expected RHS to be a string, got {type(rhs)}")
|
30
31
|
|
31
32
|
return lhs.endswith(rhs)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -24,10 +25,10 @@ class GreaterThanExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
24
25
|
# https://app.shortcut.com/vellum/story/4658
|
25
26
|
lhs = resolve_value(self._lhs, state)
|
26
27
|
if not isinstance(lhs, (int, float)):
|
27
|
-
raise
|
28
|
+
raise InvalidExpressionException(f"Expected a numeric lhs value, got: {lhs.__class__.__name__}")
|
28
29
|
|
29
30
|
rhs = resolve_value(self._rhs, state)
|
30
31
|
if not isinstance(rhs, (int, float)):
|
31
|
-
raise
|
32
|
+
raise InvalidExpressionException(f"Expected a numeric rhs value, got: {rhs.__class__.__name__}")
|
32
33
|
|
33
34
|
return lhs > rhs
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -24,10 +25,10 @@ class GreaterThanOrEqualToExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
24
25
|
# https://app.shortcut.com/vellum/story/4658
|
25
26
|
lhs = resolve_value(self._lhs, state)
|
26
27
|
if not isinstance(lhs, (int, float)):
|
27
|
-
raise
|
28
|
+
raise InvalidExpressionException(f"Expected a numeric lhs value, got: {lhs.__class__.__name__}")
|
28
29
|
|
29
30
|
rhs = resolve_value(self._rhs, state)
|
30
31
|
if not isinstance(rhs, (int, float)):
|
31
|
-
raise
|
32
|
+
raise InvalidExpressionException(f"Expected a numeric rhs value, got: {rhs.__class__.__name__}")
|
32
33
|
|
33
34
|
return lhs >= rhs
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -26,6 +27,6 @@ class InExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
26
27
|
|
27
28
|
rhs = resolve_value(self._rhs, state)
|
28
29
|
if not isinstance(rhs, (list, tuple, set, dict, str)):
|
29
|
-
raise
|
30
|
+
raise InvalidExpressionException(f"Expected a RHS that supported in, got: {rhs.__class__.__name__}")
|
30
31
|
|
31
32
|
return lhs in rhs
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -19,6 +20,6 @@ class IsBlankExpression(BaseDescriptor[bool], Generic[_T]):
|
|
19
20
|
def resolve(self, state: "BaseState") -> bool:
|
20
21
|
expression = resolve_value(self._expression, state)
|
21
22
|
if not isinstance(expression, str):
|
22
|
-
raise
|
23
|
+
raise InvalidExpressionException(f"Expected a string expression, got: {expression.__class__.__name__}")
|
23
24
|
|
24
25
|
return len(expression) == 0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
|
-
from vellum.workflows.constants import
|
3
|
+
from vellum.workflows.constants import undefined
|
4
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
6
6
|
from vellum.workflows.state.base import BaseState
|
@@ -19,4 +19,4 @@ class IsNilExpression(BaseDescriptor[bool], Generic[_T]):
|
|
19
19
|
|
20
20
|
def resolve(self, state: "BaseState") -> bool:
|
21
21
|
expression = resolve_value(self._expression, state)
|
22
|
-
return expression is None or expression is
|
22
|
+
return expression is None or expression is undefined
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -19,6 +20,6 @@ class IsNotBlankExpression(BaseDescriptor[bool], Generic[_T]):
|
|
19
20
|
def resolve(self, state: "BaseState") -> bool:
|
20
21
|
expression = resolve_value(self._expression, state)
|
21
22
|
if not isinstance(expression, str):
|
22
|
-
raise
|
23
|
+
raise InvalidExpressionException(f"Expected a string expression, got: {expression.__class__.__name__}")
|
23
24
|
|
24
25
|
return len(expression) != 0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
|
-
from vellum.workflows.constants import
|
3
|
+
from vellum.workflows.constants import undefined
|
4
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
6
6
|
from vellum.workflows.state.base import BaseState
|
@@ -19,4 +19,4 @@ class IsNotNilExpression(BaseDescriptor[bool], Generic[_T]):
|
|
19
19
|
|
20
20
|
def resolve(self, state: "BaseState") -> bool:
|
21
21
|
expression = resolve_value(self._expression, state)
|
22
|
-
return expression is not None and expression is not
|
22
|
+
return expression is not None and expression is not undefined
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
|
-
from vellum.workflows.constants import
|
3
|
+
from vellum.workflows.constants import undefined
|
4
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
6
6
|
from vellum.workflows.state.base import BaseState
|
@@ -19,4 +19,4 @@ class IsNotUndefinedExpression(BaseDescriptor[bool], Generic[_T]):
|
|
19
19
|
|
20
20
|
def resolve(self, state: "BaseState") -> bool:
|
21
21
|
expression = resolve_value(self._expression, state)
|
22
|
-
return expression is not
|
22
|
+
return expression is not undefined
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
|
-
from vellum.workflows.constants import
|
3
|
+
from vellum.workflows.constants import undefined
|
4
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
6
6
|
from vellum.workflows.state.base import BaseState
|
@@ -19,4 +19,4 @@ class IsUndefinedExpression(BaseDescriptor[bool], Generic[_T]):
|
|
19
19
|
|
20
20
|
def resolve(self, state: "BaseState") -> bool:
|
21
21
|
expression = resolve_value(self._expression, state)
|
22
|
-
return expression is
|
22
|
+
return expression is undefined
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -24,10 +25,10 @@ class LessThanExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
24
25
|
# https://app.shortcut.com/vellum/story/4658
|
25
26
|
lhs = resolve_value(self._lhs, state)
|
26
27
|
if not isinstance(lhs, (int, float)):
|
27
|
-
raise
|
28
|
+
raise InvalidExpressionException(f"Expected a numeric lhs value, got: {lhs.__class__.__name__}")
|
28
29
|
|
29
30
|
rhs = resolve_value(self._rhs, state)
|
30
31
|
if not isinstance(rhs, (int, float)):
|
31
|
-
raise
|
32
|
+
raise InvalidExpressionException(f"Expected a numeric rhs value, got: {rhs.__class__.__name__}")
|
32
33
|
|
33
34
|
return lhs < rhs
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -24,10 +25,10 @@ class LessThanOrEqualToExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
24
25
|
# https://app.shortcut.com/vellum/story/4658
|
25
26
|
lhs = resolve_value(self._lhs, state)
|
26
27
|
if not isinstance(lhs, (int, float)):
|
27
|
-
raise
|
28
|
+
raise InvalidExpressionException(f"Expected a numeric lhs value, got: {lhs.__class__.__name__}")
|
28
29
|
|
29
30
|
rhs = resolve_value(self._rhs, state)
|
30
31
|
if not isinstance(rhs, (int, float)):
|
31
|
-
raise
|
32
|
+
raise InvalidExpressionException(f"Expected a numeric rhs value, got: {rhs.__class__.__name__}")
|
32
33
|
|
33
34
|
return lhs <= rhs
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -25,14 +26,14 @@ class NotBetweenExpression(BaseDescriptor[bool], Generic[_V, _S, _E]):
|
|
25
26
|
def resolve(self, state: "BaseState") -> bool:
|
26
27
|
value = resolve_value(self._value, state)
|
27
28
|
if not isinstance(value, (int, float)):
|
28
|
-
raise
|
29
|
+
raise InvalidExpressionException(f"Expected a numeric value, got: {value.__class__.__name__}")
|
29
30
|
|
30
31
|
start = resolve_value(self._start, state)
|
31
32
|
if not isinstance(start, (int, float)):
|
32
|
-
raise
|
33
|
+
raise InvalidExpressionException(f"Expected a numeric start value, got: {start.__class__.__name__}")
|
33
34
|
|
34
35
|
end = resolve_value(self._end, state)
|
35
36
|
if not isinstance(end, (int, float)):
|
36
|
-
raise
|
37
|
+
raise InvalidExpressionException(f"Expected a numeric end value, got: {end.__class__.__name__}")
|
37
38
|
|
38
39
|
return value < start or value > end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from typing import Generic, TypeVar, Union
|
2
2
|
|
3
3
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
4
|
+
from vellum.workflows.descriptors.exceptions import InvalidExpressionException
|
4
5
|
from vellum.workflows.descriptors.utils import resolve_value
|
5
6
|
from vellum.workflows.state.base import BaseState
|
6
7
|
|
@@ -26,6 +27,6 @@ class NotInExpression(BaseDescriptor[bool], Generic[LHS, RHS]):
|
|
26
27
|
|
27
28
|
rhs = resolve_value(self._rhs, state)
|
28
29
|
if not isinstance(rhs, (list, tuple, set, dict, str)):
|
29
|
-
raise
|
30
|
+
raise InvalidExpressionException(f"Expected a RHS that supported contains, got: {rhs.__class__.__name__}")
|
30
31
|
|
31
32
|
return lhs not in rhs
|
@@ -5,7 +5,7 @@ from types import MappingProxyType
|
|
5
5
|
from uuid import UUID
|
6
6
|
from typing import Any, Dict, Generic, Iterator, Optional, Set, Tuple, Type, TypeVar, Union, cast, get_args
|
7
7
|
|
8
|
-
from vellum.workflows.constants import
|
8
|
+
from vellum.workflows.constants import undefined
|
9
9
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
10
10
|
from vellum.workflows.descriptors.utils import is_unresolved, resolve_value
|
11
11
|
from vellum.workflows.errors.types import WorkflowErrorCode
|
@@ -43,7 +43,23 @@ class BaseNodeMeta(type):
|
|
43
43
|
# TODO: Inherit the inner Output classes from every base class.
|
44
44
|
# https://app.shortcut.com/vellum/story/4007/support-auto-inheriting-parent-node-outputs
|
45
45
|
|
46
|
-
if "Outputs"
|
46
|
+
if "Outputs" in dct:
|
47
|
+
outputs_class = dct["Outputs"]
|
48
|
+
if not any(issubclass(base, BaseOutputs) for base in outputs_class.__bases__):
|
49
|
+
parent_outputs_class = next(
|
50
|
+
(base.Outputs for base in bases if hasattr(base, "Outputs")),
|
51
|
+
BaseOutputs, # Default to BaseOutputs only if no parent has Outputs
|
52
|
+
)
|
53
|
+
|
54
|
+
# Filter out object from bases while preserving other inheritance
|
55
|
+
filtered_bases = tuple(base for base in outputs_class.__bases__ if base is not object)
|
56
|
+
|
57
|
+
dct["Outputs"] = type(
|
58
|
+
f"{name}.Outputs",
|
59
|
+
(parent_outputs_class,) + filtered_bases,
|
60
|
+
{**outputs_class.__dict__, "__module__": dct["__module__"]},
|
61
|
+
)
|
62
|
+
else:
|
47
63
|
for base in reversed(bases):
|
48
64
|
if hasattr(base, "Outputs"):
|
49
65
|
dct["Outputs"] = type(
|
@@ -165,7 +181,7 @@ class BaseNodeMeta(type):
|
|
165
181
|
if attr_name in yielded_attr_names:
|
166
182
|
continue
|
167
183
|
|
168
|
-
attr_value = getattr(resolved_cls, attr_name,
|
184
|
+
attr_value = getattr(resolved_cls, attr_name, undefined)
|
169
185
|
if not isinstance(attr_value, NodeReference):
|
170
186
|
continue
|
171
187
|
|
@@ -255,17 +271,15 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
|
|
255
271
|
return False
|
256
272
|
|
257
273
|
if cls.merge_behavior == MergeBehavior.AWAIT_ATTRIBUTES:
|
258
|
-
is_ready = True
|
259
274
|
for descriptor in cls.node_class:
|
260
275
|
if not descriptor.instance:
|
261
276
|
continue
|
262
277
|
|
263
278
|
resolved_value = resolve_value(descriptor.instance, state, path=descriptor.name)
|
264
279
|
if is_unresolved(resolved_value):
|
265
|
-
|
266
|
-
break
|
280
|
+
return False
|
267
281
|
|
268
|
-
return
|
282
|
+
return True
|
269
283
|
|
270
284
|
if cls.merge_behavior == MergeBehavior.AWAIT_ANY:
|
271
285
|
return True
|