vellum-ai 0.9.16rc2__py3-none-any.whl → 0.9.16rc4__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/plugins/__init__.py +0 -0
- vellum/plugins/pydantic.py +74 -0
- vellum/plugins/utils.py +19 -0
- vellum/plugins/vellum_mypy.py +639 -3
- vellum/workflows/README.md +90 -0
- vellum/workflows/__init__.py +5 -0
- vellum/workflows/constants.py +43 -0
- vellum/workflows/descriptors/__init__.py +0 -0
- vellum/workflows/descriptors/base.py +339 -0
- vellum/workflows/descriptors/tests/test_utils.py +83 -0
- vellum/workflows/descriptors/utils.py +90 -0
- vellum/workflows/edges/__init__.py +5 -0
- vellum/workflows/edges/edge.py +23 -0
- vellum/workflows/emitters/__init__.py +5 -0
- vellum/workflows/emitters/base.py +14 -0
- vellum/workflows/environment/__init__.py +5 -0
- vellum/workflows/environment/environment.py +7 -0
- vellum/workflows/errors/__init__.py +6 -0
- vellum/workflows/errors/types.py +20 -0
- vellum/workflows/events/__init__.py +31 -0
- vellum/workflows/events/node.py +125 -0
- vellum/workflows/events/tests/__init__.py +0 -0
- vellum/workflows/events/tests/test_event.py +216 -0
- vellum/workflows/events/types.py +52 -0
- vellum/workflows/events/utils.py +5 -0
- vellum/workflows/events/workflow.py +139 -0
- vellum/workflows/exceptions.py +15 -0
- vellum/workflows/expressions/__init__.py +0 -0
- vellum/workflows/expressions/accessor.py +52 -0
- vellum/workflows/expressions/and_.py +32 -0
- vellum/workflows/expressions/begins_with.py +31 -0
- vellum/workflows/expressions/between.py +38 -0
- vellum/workflows/expressions/coalesce_expression.py +41 -0
- vellum/workflows/expressions/contains.py +30 -0
- vellum/workflows/expressions/does_not_begin_with.py +31 -0
- vellum/workflows/expressions/does_not_contain.py +30 -0
- vellum/workflows/expressions/does_not_end_with.py +31 -0
- vellum/workflows/expressions/does_not_equal.py +25 -0
- vellum/workflows/expressions/ends_with.py +31 -0
- vellum/workflows/expressions/equals.py +25 -0
- vellum/workflows/expressions/greater_than.py +33 -0
- vellum/workflows/expressions/greater_than_or_equal_to.py +33 -0
- vellum/workflows/expressions/in_.py +31 -0
- vellum/workflows/expressions/is_blank.py +24 -0
- vellum/workflows/expressions/is_not_blank.py +24 -0
- vellum/workflows/expressions/is_not_null.py +21 -0
- vellum/workflows/expressions/is_not_undefined.py +22 -0
- vellum/workflows/expressions/is_null.py +21 -0
- vellum/workflows/expressions/is_undefined.py +22 -0
- vellum/workflows/expressions/less_than.py +33 -0
- vellum/workflows/expressions/less_than_or_equal_to.py +33 -0
- vellum/workflows/expressions/not_between.py +38 -0
- vellum/workflows/expressions/not_in.py +31 -0
- vellum/workflows/expressions/or_.py +32 -0
- vellum/workflows/graph/__init__.py +3 -0
- vellum/workflows/graph/graph.py +131 -0
- vellum/workflows/graph/tests/__init__.py +0 -0
- vellum/workflows/graph/tests/test_graph.py +437 -0
- vellum/workflows/inputs/__init__.py +5 -0
- vellum/workflows/inputs/base.py +55 -0
- vellum/workflows/logging.py +14 -0
- vellum/workflows/nodes/__init__.py +46 -0
- vellum/workflows/nodes/bases/__init__.py +7 -0
- vellum/workflows/nodes/bases/base.py +332 -0
- vellum/workflows/nodes/bases/base_subworkflow_node/__init__.py +5 -0
- vellum/workflows/nodes/bases/base_subworkflow_node/node.py +10 -0
- vellum/workflows/nodes/bases/tests/__init__.py +0 -0
- vellum/workflows/nodes/bases/tests/test_base_node.py +125 -0
- vellum/workflows/nodes/core/__init__.py +16 -0
- vellum/workflows/nodes/core/error_node/__init__.py +5 -0
- vellum/workflows/nodes/core/error_node/node.py +26 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/__init__.py +5 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +73 -0
- vellum/workflows/nodes/core/map_node/__init__.py +5 -0
- vellum/workflows/nodes/core/map_node/node.py +147 -0
- vellum/workflows/nodes/core/map_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/core/map_node/tests/test_node.py +65 -0
- vellum/workflows/nodes/core/retry_node/__init__.py +5 -0
- vellum/workflows/nodes/core/retry_node/node.py +106 -0
- vellum/workflows/nodes/core/retry_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/core/retry_node/tests/test_node.py +93 -0
- vellum/workflows/nodes/core/templating_node/__init__.py +5 -0
- vellum/workflows/nodes/core/templating_node/custom_filters.py +12 -0
- vellum/workflows/nodes/core/templating_node/exceptions.py +2 -0
- vellum/workflows/nodes/core/templating_node/node.py +123 -0
- vellum/workflows/nodes/core/templating_node/render.py +55 -0
- vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +21 -0
- vellum/workflows/nodes/core/try_node/__init__.py +5 -0
- vellum/workflows/nodes/core/try_node/node.py +110 -0
- vellum/workflows/nodes/core/try_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/core/try_node/tests/test_node.py +82 -0
- vellum/workflows/nodes/displayable/__init__.py +31 -0
- vellum/workflows/nodes/displayable/api_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/api_node/node.py +44 -0
- vellum/workflows/nodes/displayable/bases/__init__.py +11 -0
- vellum/workflows/nodes/displayable/bases/api_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +70 -0
- vellum/workflows/nodes/displayable/bases/base_prompt_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +60 -0
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/constants.py +13 -0
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +118 -0
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +98 -0
- vellum/workflows/nodes/displayable/bases/search_node.py +90 -0
- vellum/workflows/nodes/displayable/code_execution_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/code_execution_node/node.py +197 -0
- vellum/workflows/nodes/displayable/code_execution_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/__init__.py +0 -0
- vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/main.py +3 -0
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +111 -0
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +10 -0
- vellum/workflows/nodes/displayable/conditional_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/conditional_node/node.py +25 -0
- vellum/workflows/nodes/displayable/final_output_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/final_output_node/node.py +43 -0
- vellum/workflows/nodes/displayable/guardrail_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/guardrail_node/node.py +97 -0
- vellum/workflows/nodes/displayable/inline_prompt_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/inline_prompt_node/node.py +41 -0
- vellum/workflows/nodes/displayable/merge_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/merge_node/node.py +10 -0
- vellum/workflows/nodes/displayable/prompt_deployment_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +45 -0
- vellum/workflows/nodes/displayable/search_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/search_node/node.py +26 -0
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/__init__.py +5 -0
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +156 -0
- vellum/workflows/nodes/displayable/tests/__init__.py +0 -0
- vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py +148 -0
- vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py +134 -0
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +80 -0
- vellum/workflows/nodes/utils.py +27 -0
- vellum/workflows/outputs/__init__.py +6 -0
- vellum/workflows/outputs/base.py +196 -0
- vellum/workflows/ports/__init__.py +7 -0
- vellum/workflows/ports/node_ports.py +75 -0
- vellum/workflows/ports/port.py +75 -0
- vellum/workflows/ports/utils.py +40 -0
- vellum/workflows/references/__init__.py +17 -0
- vellum/workflows/references/environment_variable.py +20 -0
- vellum/workflows/references/execution_count.py +20 -0
- vellum/workflows/references/external_input.py +49 -0
- vellum/workflows/references/input.py +7 -0
- vellum/workflows/references/lazy.py +55 -0
- vellum/workflows/references/node.py +43 -0
- vellum/workflows/references/output.py +78 -0
- vellum/workflows/references/state_value.py +23 -0
- vellum/workflows/references/vellum_secret.py +15 -0
- vellum/workflows/references/workflow_input.py +41 -0
- vellum/workflows/resolvers/__init__.py +5 -0
- vellum/workflows/resolvers/base.py +15 -0
- vellum/workflows/runner/__init__.py +5 -0
- vellum/workflows/runner/runner.py +588 -0
- vellum/workflows/runner/types.py +18 -0
- vellum/workflows/state/__init__.py +5 -0
- vellum/workflows/state/base.py +327 -0
- vellum/workflows/state/context.py +18 -0
- vellum/workflows/state/encoder.py +57 -0
- vellum/workflows/state/store.py +28 -0
- vellum/workflows/state/tests/__init__.py +0 -0
- vellum/workflows/state/tests/test_state.py +113 -0
- vellum/workflows/types/__init__.py +0 -0
- vellum/workflows/types/core.py +91 -0
- vellum/workflows/types/generics.py +14 -0
- vellum/workflows/types/stack.py +39 -0
- vellum/workflows/types/tests/__init__.py +0 -0
- vellum/workflows/types/tests/test_utils.py +76 -0
- vellum/workflows/types/utils.py +164 -0
- vellum/workflows/utils/__init__.py +0 -0
- vellum/workflows/utils/names.py +13 -0
- vellum/workflows/utils/tests/__init__.py +0 -0
- vellum/workflows/utils/tests/test_names.py +15 -0
- vellum/workflows/utils/tests/test_vellum_variables.py +25 -0
- vellum/workflows/utils/vellum_variables.py +81 -0
- vellum/workflows/vellum_client.py +18 -0
- vellum/workflows/workflows/__init__.py +5 -0
- vellum/workflows/workflows/base.py +365 -0
- {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/METADATA +2 -1
- {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/RECORD +245 -7
- vellum_cli/__init__.py +72 -0
- vellum_cli/aliased_group.py +103 -0
- vellum_cli/config.py +96 -0
- vellum_cli/image_push.py +112 -0
- vellum_cli/logger.py +36 -0
- vellum_cli/pull.py +73 -0
- vellum_cli/push.py +121 -0
- vellum_cli/tests/test_config.py +100 -0
- vellum_cli/tests/test_pull.py +152 -0
- vellum_ee/workflows/__init__.py +0 -0
- vellum_ee/workflows/display/__init__.py +0 -0
- vellum_ee/workflows/display/base.py +73 -0
- vellum_ee/workflows/display/nodes/__init__.py +4 -0
- vellum_ee/workflows/display/nodes/base_node_display.py +116 -0
- vellum_ee/workflows/display/nodes/base_node_vellum_display.py +36 -0
- vellum_ee/workflows/display/nodes/get_node_display_class.py +25 -0
- vellum_ee/workflows/display/nodes/tests/__init__.py +0 -0
- vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +47 -0
- vellum_ee/workflows/display/nodes/types.py +18 -0
- vellum_ee/workflows/display/nodes/utils.py +33 -0
- vellum_ee/workflows/display/nodes/vellum/__init__.py +32 -0
- vellum_ee/workflows/display/nodes/vellum/api_node.py +205 -0
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +71 -0
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py +217 -0
- vellum_ee/workflows/display/nodes/vellum/final_output_node.py +61 -0
- vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +49 -0
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +170 -0
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +99 -0
- vellum_ee/workflows/display/nodes/vellum/map_node.py +100 -0
- vellum_ee/workflows/display/nodes/vellum/merge_node.py +48 -0
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +68 -0
- vellum_ee/workflows/display/nodes/vellum/search_node.py +193 -0
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +58 -0
- vellum_ee/workflows/display/nodes/vellum/templating_node.py +67 -0
- vellum_ee/workflows/display/nodes/vellum/tests/__init__.py +0 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +106 -0
- vellum_ee/workflows/display/nodes/vellum/try_node.py +38 -0
- vellum_ee/workflows/display/nodes/vellum/utils.py +76 -0
- vellum_ee/workflows/display/tests/__init__.py +0 -0
- vellum_ee/workflows/display/tests/workflow_serialization/__init__.py +0 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +426 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +607 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +1175 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +235 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +511 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +372 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +272 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +289 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +354 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +123 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +84 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +233 -0
- vellum_ee/workflows/display/types.py +46 -0
- vellum_ee/workflows/display/utils/__init__.py +0 -0
- vellum_ee/workflows/display/utils/tests/__init__.py +0 -0
- vellum_ee/workflows/display/utils/tests/test_uuids.py +16 -0
- vellum_ee/workflows/display/utils/uuids.py +24 -0
- vellum_ee/workflows/display/utils/vellum.py +121 -0
- vellum_ee/workflows/display/vellum.py +357 -0
- vellum_ee/workflows/display/workflows/__init__.py +5 -0
- vellum_ee/workflows/display/workflows/base_workflow_display.py +302 -0
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +32 -0
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py +386 -0
- {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/LICENSE +0 -0
- {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/WHEEL +0 -0
- {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
<p align="center">
|
2
|
+
<h1 align="center">
|
3
|
+
Vellum Workflows SDK
|
4
|
+
</h1>
|
5
|
+
<p align="center">
|
6
|
+
<a href="https://docs.vellum.ai/developers/workflows-sdk">Learn more</a>
|
7
|
+
·
|
8
|
+
<a href="https://www.vellum.ai/landing-pages/request-demo">Talk to us</a>
|
9
|
+
</p>
|
10
|
+
</p>
|
11
|
+
|
12
|
+
# Introduction
|
13
|
+
|
14
|
+
The Vellum Workflows SDK is a framework for defining and executing complex AI systems as graphs.
|
15
|
+
|
16
|
+
The Vellum Workflows SDK provides a declarative python syntax for both defining and executing the control flow of graphs.
|
17
|
+
Unlike other graph execution frameworks, which are functional or event-driven in nature, Vellum's Workflows SDK defines the control flow of a graph
|
18
|
+
statically and makes use of strict typing. This means that the structure of the graph is known ahead of time, and you get all the benefits of type
|
19
|
+
safety and intellisense. This ultimately makes it easier to build more predictable and robust AI systems.
|
20
|
+
|
21
|
+
Unique amongst other frameworks, Vellum's Workflows SDK also allows you to _visualize, edit, and execute_ your graph in a UI, pushing and pulling changes from
|
22
|
+
code to UI and vice versa.
|
23
|
+
|
24
|
+
|
25
|
+
## Core Features
|
26
|
+
- **Nodes**: Nodes are the basic building blocks of a graph. They represent a single task or function that can be executed.
|
27
|
+
- **Graph Syntax**: An intuitive declarative syntax for defining the control flow of a graph.
|
28
|
+
- **Inputs and Outputs**: Both the Workflow itslef and individual Nodes can take in inputs and produce outputs, which can be used to pass information between nodes.
|
29
|
+
- **State**: Nodes can read and write to the graph's global state, which can be used to share information between nodes without defining explicit inputs and outputs.
|
30
|
+
- **Advanced Control Flow**: Support for looping, conditionals, paralellism, state forking, and more.
|
31
|
+
- **Streaming**: Nodes can stream output values back to the runner, allowing for long-running tasks like chat completions to return partial results.
|
32
|
+
- **Human-in-the-loop**: Nodes can wait for External Inputs, allowing for a pause in the Workflow until a human or external system provides input.
|
33
|
+
- **UI Integration**: Push and pull changes from code to Vellum's UI and vice versa, allowing for rapid testing and iteration.
|
34
|
+
|
35
|
+
## Quickstart
|
36
|
+
|
37
|
+
1. Install the Vellum Workflows SDK:
|
38
|
+
|
39
|
+
```bash
|
40
|
+
pip install vellum-ai
|
41
|
+
```
|
42
|
+
|
43
|
+
2. Import the Vellum Workflows SDK and define your first Workflow:
|
44
|
+
|
45
|
+
```python
|
46
|
+
# my_workflow.py
|
47
|
+
|
48
|
+
from workflows import BaseWorkflow
|
49
|
+
from workflows.nodes import BaseNode
|
50
|
+
|
51
|
+
|
52
|
+
class MyNode(BaseNode):
|
53
|
+
|
54
|
+
class Outputs(BaseNode.Outputs):
|
55
|
+
result: str
|
56
|
+
|
57
|
+
def run(self):
|
58
|
+
return self.Outputs(result="Hello, World!")
|
59
|
+
|
60
|
+
|
61
|
+
class MyWorkflow(BaseWorkflow):
|
62
|
+
graph = MyNode
|
63
|
+
|
64
|
+
class Outputs(BaseWorkflow.Outputs):
|
65
|
+
result = MyNode.Outputs.result
|
66
|
+
|
67
|
+
|
68
|
+
if __name__ == "__main__":
|
69
|
+
workflow = MyWorkflow()
|
70
|
+
result = workflow.run()
|
71
|
+
|
72
|
+
print(result.outputs.result)
|
73
|
+
|
74
|
+
```
|
75
|
+
3. Run it!
|
76
|
+
|
77
|
+
```bash
|
78
|
+
python my_workflow.py
|
79
|
+
|
80
|
+
Note: To use most out-of-box Nodes, and to push/pull to/from the Velłum UI, you'll need a Vellum account and API key. [Talk to us](https://www.vellum.ai/landing-pages/request-demo) or visit our [pricing page](https://www.vellum.ai/pricing) for more information.
|
81
|
+
|
82
|
+
|
83
|
+
## Documentation
|
84
|
+
Complete documentation for the Vellum Workflows SDK can be found at https://docs.vellum.ai/developers/workflows-sdk.
|
85
|
+
|
86
|
+
|
87
|
+
## Stability
|
88
|
+
|
89
|
+
This SDK is currently in <Availability type="beta" /> and is subject to change. If you'd like to pariticpate in
|
90
|
+
our beta program, please [contact us](https://docs.vellum.ai/home/getting-started/support).
|
@@ -0,0 +1,43 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
from typing import Any, cast
|
3
|
+
|
4
|
+
|
5
|
+
class _UndefMeta(type):
|
6
|
+
def __repr__(cls) -> str:
|
7
|
+
return "UNDEF"
|
8
|
+
|
9
|
+
def __getattribute__(cls, name: str) -> Any:
|
10
|
+
if name == "__class__":
|
11
|
+
# ensures that UNDEF.__class__ == UNDEF
|
12
|
+
return cls
|
13
|
+
|
14
|
+
return super().__getattribute__(name)
|
15
|
+
|
16
|
+
def __bool__(cls) -> bool:
|
17
|
+
return False
|
18
|
+
|
19
|
+
|
20
|
+
class UNDEF(metaclass=_UndefMeta):
|
21
|
+
pass
|
22
|
+
|
23
|
+
|
24
|
+
LATEST_RELEASE_TAG = "LATEST"
|
25
|
+
|
26
|
+
OMIT = cast(Any, ...)
|
27
|
+
|
28
|
+
|
29
|
+
class APIRequestMethod(Enum):
|
30
|
+
GET = "GET"
|
31
|
+
POST = "POST"
|
32
|
+
PUT = "PUT"
|
33
|
+
DELETE = "DELETE"
|
34
|
+
PATCH = "PATCH"
|
35
|
+
OPTIONS = "OPTIONS"
|
36
|
+
HEAD = "HEAD"
|
37
|
+
CONNECT = "CONNECT"
|
38
|
+
TRACE = "TRACE"
|
39
|
+
|
40
|
+
|
41
|
+
class AuthorizationType(Enum):
|
42
|
+
BEARER_TOKEN = "BEARER_TOKEN"
|
43
|
+
API_KEY = "API_KEY"
|
File without changes
|
@@ -0,0 +1,339 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Generic, Optional, Tuple, Type, TypeVar, Union, cast, overload
|
2
|
+
|
3
|
+
if TYPE_CHECKING:
|
4
|
+
from vellum.workflows.expressions.accessor import AccessorExpression
|
5
|
+
from vellum.workflows.expressions.and_ import AndExpression
|
6
|
+
from vellum.workflows.expressions.begins_with import BeginsWithExpression
|
7
|
+
from vellum.workflows.expressions.between import BetweenExpression
|
8
|
+
from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
|
9
|
+
from vellum.workflows.expressions.contains import ContainsExpression
|
10
|
+
from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
|
11
|
+
from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
|
12
|
+
from vellum.workflows.expressions.does_not_end_with import DoesNotEndWithExpression
|
13
|
+
from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
|
14
|
+
from vellum.workflows.expressions.ends_with import EndsWithExpression
|
15
|
+
from vellum.workflows.expressions.equals import EqualsExpression
|
16
|
+
from vellum.workflows.expressions.greater_than import GreaterThanExpression
|
17
|
+
from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
|
18
|
+
from vellum.workflows.expressions.in_ import InExpression
|
19
|
+
from vellum.workflows.expressions.is_blank import IsBlankExpression
|
20
|
+
from vellum.workflows.expressions.is_not_blank import IsNotBlankExpression
|
21
|
+
from vellum.workflows.expressions.is_not_null import IsNotNullExpression
|
22
|
+
from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
|
23
|
+
from vellum.workflows.expressions.is_null import IsNullExpression
|
24
|
+
from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
|
25
|
+
from vellum.workflows.expressions.less_than import LessThanExpression
|
26
|
+
from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
|
27
|
+
from vellum.workflows.expressions.not_between import NotBetweenExpression
|
28
|
+
from vellum.workflows.expressions.not_in import NotInExpression
|
29
|
+
from vellum.workflows.expressions.or_ import OrExpression
|
30
|
+
from vellum.workflows.nodes.bases import BaseNode
|
31
|
+
from vellum.workflows.state.base import BaseState
|
32
|
+
|
33
|
+
_T = TypeVar("_T")
|
34
|
+
_O = TypeVar("_O")
|
35
|
+
_O2 = TypeVar("_O2")
|
36
|
+
|
37
|
+
|
38
|
+
class BaseDescriptor(Generic[_T]):
|
39
|
+
_name: str
|
40
|
+
_types: Tuple[Type[_T], ...]
|
41
|
+
_instance: Optional[_T]
|
42
|
+
|
43
|
+
def __init__(self, *, name: str, types: Tuple[Type[_T], ...], instance: Optional[_T] = None) -> None:
|
44
|
+
self._name = name
|
45
|
+
self._types = types
|
46
|
+
self._instance = instance
|
47
|
+
|
48
|
+
@property
|
49
|
+
def name(self) -> str:
|
50
|
+
return self._name
|
51
|
+
|
52
|
+
@property
|
53
|
+
def types(self) -> Tuple[Type[_T], ...]:
|
54
|
+
return self._types
|
55
|
+
|
56
|
+
@property
|
57
|
+
def instance(self) -> Optional[_T]:
|
58
|
+
return self._instance
|
59
|
+
|
60
|
+
def resolve(self, state: "BaseState") -> _T:
|
61
|
+
raise NotImplementedError("Descriptor must implement resolve method")
|
62
|
+
|
63
|
+
def __eq__(self, other: object) -> bool:
|
64
|
+
if not isinstance(other, type(self)):
|
65
|
+
return False
|
66
|
+
return self._name == other._name
|
67
|
+
|
68
|
+
def __hash__(self) -> int:
|
69
|
+
return hash(self._name)
|
70
|
+
|
71
|
+
@overload
|
72
|
+
def __get__(self, instance: "BaseNode", owner: Type["BaseNode"]) -> _T: ...
|
73
|
+
|
74
|
+
@overload
|
75
|
+
def __get__(self, instance: Any, owner: Optional[Type]) -> "BaseDescriptor[_T]": ...
|
76
|
+
|
77
|
+
def __get__(self, instance: Any, owner: Optional[Type]) -> Union["BaseDescriptor[_T]", _T]:
|
78
|
+
if not instance:
|
79
|
+
return self
|
80
|
+
|
81
|
+
if instance.__class__.__name__ == "BaseNode":
|
82
|
+
node = cast("BaseNode", instance)
|
83
|
+
return self.resolve(node.state)
|
84
|
+
|
85
|
+
return self
|
86
|
+
|
87
|
+
# TODO: We should figure out how to remove these dynamic imports
|
88
|
+
# https://app.shortcut.com/vellum/story/4504
|
89
|
+
@overload
|
90
|
+
def __or__(self, other: "BaseDescriptor[_O]") -> "OrExpression[_T, _O]": ...
|
91
|
+
|
92
|
+
@overload
|
93
|
+
def __or__(self, other: _O) -> "OrExpression[_T, _O]": ...
|
94
|
+
|
95
|
+
def __or__(self, other: "Union[BaseDescriptor[_O], _O]") -> "OrExpression[_T, _O]":
|
96
|
+
from vellum.workflows.expressions.or_ import OrExpression
|
97
|
+
|
98
|
+
return OrExpression(lhs=self, rhs=other)
|
99
|
+
|
100
|
+
@overload
|
101
|
+
def __and__(self, other: "BaseDescriptor[_O]") -> "AndExpression[_T, _O]": ...
|
102
|
+
|
103
|
+
@overload
|
104
|
+
def __and__(self, other: _O) -> "AndExpression[_T, _O]": ...
|
105
|
+
|
106
|
+
def __and__(self, other: "Union[BaseDescriptor[_O], _O]") -> "AndExpression[_T, _O]":
|
107
|
+
from vellum.workflows.expressions.and_ import AndExpression
|
108
|
+
|
109
|
+
return AndExpression(lhs=self, rhs=other)
|
110
|
+
|
111
|
+
@overload
|
112
|
+
def coalesce(self, other: "BaseDescriptor[_O]") -> "CoalesceExpression[_T, _O]": ...
|
113
|
+
|
114
|
+
@overload
|
115
|
+
def coalesce(self, other: _O) -> "CoalesceExpression[_T, _O]": ...
|
116
|
+
|
117
|
+
def coalesce(self, other: "Union[BaseDescriptor[_O], _O]") -> "CoalesceExpression[_T, _O]":
|
118
|
+
from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
|
119
|
+
|
120
|
+
return CoalesceExpression(lhs=self, rhs=other)
|
121
|
+
|
122
|
+
def __getitem__(self, field: str) -> "AccessorExpression":
|
123
|
+
from vellum.workflows.expressions.accessor import AccessorExpression
|
124
|
+
|
125
|
+
return AccessorExpression(base=self, field=field)
|
126
|
+
|
127
|
+
@overload
|
128
|
+
def equals(self, other: "BaseDescriptor[_O]") -> "EqualsExpression[_T, _O]": ...
|
129
|
+
|
130
|
+
@overload
|
131
|
+
def equals(self, other: _O) -> "EqualsExpression[_T, _O]": ...
|
132
|
+
|
133
|
+
def equals(self, other: "Union[BaseDescriptor[_O], _O]") -> "EqualsExpression[_T, _O]":
|
134
|
+
from vellum.workflows.expressions.equals import EqualsExpression
|
135
|
+
|
136
|
+
return EqualsExpression(lhs=self, rhs=other)
|
137
|
+
|
138
|
+
@overload
|
139
|
+
def does_not_equal(self, other: "BaseDescriptor[_O]") -> "DoesNotEqualExpression[_T, _O]": ...
|
140
|
+
|
141
|
+
@overload
|
142
|
+
def does_not_equal(self, other: _O) -> "DoesNotEqualExpression[_T, _O]": ...
|
143
|
+
|
144
|
+
def does_not_equal(self, other: "Union[BaseDescriptor[_O], _O]") -> "DoesNotEqualExpression[_T, _O]":
|
145
|
+
from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
|
146
|
+
|
147
|
+
return DoesNotEqualExpression(lhs=self, rhs=other)
|
148
|
+
|
149
|
+
@overload
|
150
|
+
def less_than(self, other: "BaseDescriptor[_O]") -> "LessThanExpression[_T, _O]": ...
|
151
|
+
|
152
|
+
@overload
|
153
|
+
def less_than(self, other: _O) -> "LessThanExpression[_T, _O]": ...
|
154
|
+
|
155
|
+
def less_than(self, other: "Union[BaseDescriptor[_O], _O]") -> "LessThanExpression[_T, _O]":
|
156
|
+
from vellum.workflows.expressions.less_than import LessThanExpression
|
157
|
+
|
158
|
+
return LessThanExpression(lhs=self, rhs=other)
|
159
|
+
|
160
|
+
@overload
|
161
|
+
def greater_than(self, other: "BaseDescriptor[_O]") -> "GreaterThanExpression[_T, _O]": ...
|
162
|
+
|
163
|
+
@overload
|
164
|
+
def greater_than(self, other: _O) -> "GreaterThanExpression[_T, _O]": ...
|
165
|
+
|
166
|
+
def greater_than(self, other: "Union[BaseDescriptor[_O], _O]") -> "GreaterThanExpression[_T, _O]":
|
167
|
+
from vellum.workflows.expressions.greater_than import GreaterThanExpression
|
168
|
+
|
169
|
+
return GreaterThanExpression(lhs=self, rhs=other)
|
170
|
+
|
171
|
+
@overload
|
172
|
+
def less_than_or_equal_to(self, other: "BaseDescriptor[_O]") -> "LessThanOrEqualToExpression[_T, _O]": ...
|
173
|
+
|
174
|
+
@overload
|
175
|
+
def less_than_or_equal_to(self, other: _O) -> "LessThanOrEqualToExpression[_T, _O]": ...
|
176
|
+
|
177
|
+
def less_than_or_equal_to(self, other: "Union[BaseDescriptor[_O], _O]") -> "LessThanOrEqualToExpression[_T, _O]":
|
178
|
+
from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
|
179
|
+
|
180
|
+
return LessThanOrEqualToExpression(lhs=self, rhs=other)
|
181
|
+
|
182
|
+
@overload
|
183
|
+
def greater_than_or_equal_to(self, other: "BaseDescriptor[_O]") -> "GreaterThanOrEqualToExpression[_T, _O]": ...
|
184
|
+
|
185
|
+
@overload
|
186
|
+
def greater_than_or_equal_to(self, other: _O) -> "GreaterThanOrEqualToExpression[_T, _O]": ...
|
187
|
+
|
188
|
+
def greater_than_or_equal_to(
|
189
|
+
self, other: "Union[BaseDescriptor[_O], _O]"
|
190
|
+
) -> "GreaterThanOrEqualToExpression[_T, _O]":
|
191
|
+
from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
|
192
|
+
|
193
|
+
return GreaterThanOrEqualToExpression(lhs=self, rhs=other)
|
194
|
+
|
195
|
+
@overload
|
196
|
+
def contains(self, other: "BaseDescriptor[_O]") -> "ContainsExpression[_T, _O]": ...
|
197
|
+
|
198
|
+
@overload
|
199
|
+
def contains(self, other: _O) -> "ContainsExpression[_T, _O]": ...
|
200
|
+
|
201
|
+
def contains(self, other: "Union[BaseDescriptor[_O], _O]") -> "ContainsExpression[_T, _O]":
|
202
|
+
from vellum.workflows.expressions.contains import ContainsExpression
|
203
|
+
|
204
|
+
return ContainsExpression(lhs=self, rhs=other)
|
205
|
+
|
206
|
+
@overload
|
207
|
+
def begins_with(self, other: "BaseDescriptor[_O]") -> "BeginsWithExpression[_T, _O]": ...
|
208
|
+
|
209
|
+
@overload
|
210
|
+
def begins_with(self, other: _O) -> "BeginsWithExpression[_T, _O]": ...
|
211
|
+
|
212
|
+
def begins_with(self, other: "Union[BaseDescriptor[_O], _O]") -> "BeginsWithExpression[_T, _O]":
|
213
|
+
from vellum.workflows.expressions.begins_with import BeginsWithExpression
|
214
|
+
|
215
|
+
return BeginsWithExpression(lhs=self, rhs=other)
|
216
|
+
|
217
|
+
@overload
|
218
|
+
def ends_with(self, other: "BaseDescriptor[_O]") -> "EndsWithExpression[_T, _O]": ...
|
219
|
+
|
220
|
+
@overload
|
221
|
+
def ends_with(self, other: _O) -> "EndsWithExpression[_T, _O]": ...
|
222
|
+
|
223
|
+
def ends_with(self, other: "Union[BaseDescriptor[_O], _O]") -> "EndsWithExpression[_T, _O]":
|
224
|
+
from vellum.workflows.expressions.ends_with import EndsWithExpression
|
225
|
+
|
226
|
+
return EndsWithExpression(lhs=self, rhs=other)
|
227
|
+
|
228
|
+
@overload
|
229
|
+
def does_not_contain(self, other: "BaseDescriptor[_O]") -> "DoesNotContainExpression[_T, _O]": ...
|
230
|
+
|
231
|
+
@overload
|
232
|
+
def does_not_contain(self, other: _O) -> "DoesNotContainExpression[_T, _O]": ...
|
233
|
+
|
234
|
+
def does_not_contain(self, other: "Union[BaseDescriptor[_O], _O]") -> "DoesNotContainExpression[_T, _O]":
|
235
|
+
from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
|
236
|
+
|
237
|
+
return DoesNotContainExpression(lhs=self, rhs=other)
|
238
|
+
|
239
|
+
@overload
|
240
|
+
def does_not_begin_with(self, other: "BaseDescriptor[_O]") -> "DoesNotBeginWithExpression[_T, _O]": ...
|
241
|
+
|
242
|
+
@overload
|
243
|
+
def does_not_begin_with(self, other: _O) -> "DoesNotBeginWithExpression[_T, _O]": ...
|
244
|
+
|
245
|
+
def does_not_begin_with(self, other: "Union[BaseDescriptor[_O], _O]") -> "DoesNotBeginWithExpression[_T, _O]":
|
246
|
+
from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
|
247
|
+
|
248
|
+
return DoesNotBeginWithExpression(lhs=self, rhs=other)
|
249
|
+
|
250
|
+
@overload
|
251
|
+
def does_not_end_with(self, other: "BaseDescriptor[_O]") -> "DoesNotEndWithExpression[_T, _O]": ...
|
252
|
+
|
253
|
+
@overload
|
254
|
+
def does_not_end_with(self, other: _O) -> "DoesNotEndWithExpression[_T, _O]": ...
|
255
|
+
|
256
|
+
def does_not_end_with(self, other: "Union[BaseDescriptor[_O], _O]") -> "DoesNotEndWithExpression[_T, _O]":
|
257
|
+
from vellum.workflows.expressions.does_not_end_with import DoesNotEndWithExpression
|
258
|
+
|
259
|
+
return DoesNotEndWithExpression(lhs=self, rhs=other)
|
260
|
+
|
261
|
+
def is_none(self) -> "IsNullExpression":
|
262
|
+
from vellum.workflows.expressions.is_null import IsNullExpression
|
263
|
+
|
264
|
+
return IsNullExpression(expression=self)
|
265
|
+
|
266
|
+
def is_not_none(self) -> "IsNotNullExpression":
|
267
|
+
from vellum.workflows.expressions.is_not_null import IsNotNullExpression
|
268
|
+
|
269
|
+
return IsNotNullExpression(expression=self)
|
270
|
+
|
271
|
+
def is_undefined(self) -> "IsUndefinedExpression":
|
272
|
+
from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
|
273
|
+
|
274
|
+
return IsUndefinedExpression(expression=self)
|
275
|
+
|
276
|
+
def is_not_undefined(self) -> "IsNotUndefinedExpression":
|
277
|
+
from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
|
278
|
+
|
279
|
+
return IsNotUndefinedExpression(expression=self)
|
280
|
+
|
281
|
+
@overload
|
282
|
+
def in_(self, other: "BaseDescriptor[_O]") -> "InExpression[_T, _O]": ...
|
283
|
+
|
284
|
+
@overload
|
285
|
+
def in_(self, other: _O) -> "InExpression[_T, _O]": ...
|
286
|
+
|
287
|
+
def in_(self, other: "Union[BaseDescriptor[_O], _O]") -> "InExpression[_T, _O]":
|
288
|
+
from vellum.workflows.expressions.in_ import InExpression
|
289
|
+
|
290
|
+
return InExpression(lhs=self, rhs=other)
|
291
|
+
|
292
|
+
@overload
|
293
|
+
def not_in(self, other: "BaseDescriptor[_O]") -> "NotInExpression[_T, _O]": ...
|
294
|
+
|
295
|
+
@overload
|
296
|
+
def not_in(self, other: _O) -> "NotInExpression[_T, _O]": ...
|
297
|
+
|
298
|
+
def not_in(self, other: "Union[BaseDescriptor[_O], _O]") -> "NotInExpression[_T, _O]":
|
299
|
+
from vellum.workflows.expressions.not_in import NotInExpression
|
300
|
+
|
301
|
+
return NotInExpression(lhs=self, rhs=other)
|
302
|
+
|
303
|
+
@overload
|
304
|
+
def between(self, start: "BaseDescriptor[_O]", end: "BaseDescriptor[_O2]") -> "BetweenExpression[_T, _O, _O2]": ...
|
305
|
+
|
306
|
+
@overload
|
307
|
+
def between(self, start: _O, end: _O2) -> "BetweenExpression[_T, _O, _O2]": ...
|
308
|
+
|
309
|
+
def between(
|
310
|
+
self, start: "Union[BaseDescriptor[_O], _O]", end: "Union[BaseDescriptor[_O2], _O2]"
|
311
|
+
) -> "BetweenExpression[_T, _O, _O2]":
|
312
|
+
from vellum.workflows.expressions.between import BetweenExpression
|
313
|
+
|
314
|
+
return BetweenExpression(value=self, start=start, end=end)
|
315
|
+
|
316
|
+
@overload
|
317
|
+
def not_between(
|
318
|
+
self, start: "BaseDescriptor[_O]", end: "BaseDescriptor[_O2]"
|
319
|
+
) -> "NotBetweenExpression[_T, _O, _O2]": ...
|
320
|
+
|
321
|
+
@overload
|
322
|
+
def not_between(self, start: _O, end: _O2) -> "NotBetweenExpression[_T, _O, _O2]": ...
|
323
|
+
|
324
|
+
def not_between(
|
325
|
+
self, start: "Union[BaseDescriptor[_O], _O]", end: "Union[BaseDescriptor[_O2], _O2]"
|
326
|
+
) -> "NotBetweenExpression[_T, _O, _O2]":
|
327
|
+
from vellum.workflows.expressions.not_between import NotBetweenExpression
|
328
|
+
|
329
|
+
return NotBetweenExpression(value=self, start=start, end=end)
|
330
|
+
|
331
|
+
def is_blank(self) -> "IsBlankExpression":
|
332
|
+
from vellum.workflows.expressions.is_blank import IsBlankExpression
|
333
|
+
|
334
|
+
return IsBlankExpression(expression=self)
|
335
|
+
|
336
|
+
def is_not_blank(self) -> "IsNotBlankExpression":
|
337
|
+
from vellum.workflows.expressions.is_not_blank import IsNotBlankExpression
|
338
|
+
|
339
|
+
return IsNotBlankExpression(expression=self)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from vellum.workflows.descriptors.utils import resolve_value
|
4
|
+
from vellum.workflows.state.base import BaseState
|
5
|
+
|
6
|
+
|
7
|
+
class FixtureState(BaseState):
|
8
|
+
alpha = 1
|
9
|
+
beta = 2
|
10
|
+
|
11
|
+
gamma = "hello"
|
12
|
+
delta = "el"
|
13
|
+
|
14
|
+
epsilon = 3
|
15
|
+
zeta = {
|
16
|
+
"foo": "bar",
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
@pytest.mark.parametrize(
|
21
|
+
["descriptor", "expected_value"],
|
22
|
+
[
|
23
|
+
(FixtureState.alpha | FixtureState.beta, 1),
|
24
|
+
(FixtureState.alpha & FixtureState.beta, 2),
|
25
|
+
(FixtureState.beta.coalesce(FixtureState.alpha), 2),
|
26
|
+
(FixtureState.alpha.equals(FixtureState.beta), False),
|
27
|
+
(FixtureState.alpha.does_not_equal(FixtureState.beta), True),
|
28
|
+
(FixtureState.alpha.less_than(FixtureState.beta), True),
|
29
|
+
(FixtureState.alpha.greater_than(FixtureState.beta), False),
|
30
|
+
(FixtureState.alpha.less_than_or_equal_to(FixtureState.beta), True),
|
31
|
+
(FixtureState.alpha.greater_than_or_equal_to(FixtureState.beta), False),
|
32
|
+
(FixtureState.gamma.contains(FixtureState.delta), True),
|
33
|
+
(FixtureState.gamma.begins_with(FixtureState.delta), False),
|
34
|
+
(FixtureState.gamma.ends_with(FixtureState.delta), False),
|
35
|
+
(FixtureState.gamma.does_not_contain(FixtureState.delta), False),
|
36
|
+
(FixtureState.gamma.does_not_begin_with(FixtureState.delta), True),
|
37
|
+
(FixtureState.gamma.does_not_end_with(FixtureState.delta), True),
|
38
|
+
(FixtureState.alpha.is_none(), False),
|
39
|
+
(FixtureState.alpha.is_not_none(), True),
|
40
|
+
(FixtureState.delta.in_(FixtureState.gamma), True),
|
41
|
+
(FixtureState.delta.not_in(FixtureState.gamma), False),
|
42
|
+
(FixtureState.alpha.between(FixtureState.beta, FixtureState.epsilon), False),
|
43
|
+
(FixtureState.alpha.not_between(FixtureState.beta, FixtureState.epsilon), True),
|
44
|
+
(FixtureState.delta.is_blank(), False),
|
45
|
+
(FixtureState.delta.is_not_blank(), True),
|
46
|
+
(
|
47
|
+
FixtureState.alpha.equals(FixtureState.alpha)
|
48
|
+
| FixtureState.alpha.equals(FixtureState.beta) & FixtureState.alpha.equals(FixtureState.beta),
|
49
|
+
True,
|
50
|
+
),
|
51
|
+
(FixtureState.zeta["foo"], "bar"),
|
52
|
+
],
|
53
|
+
ids=[
|
54
|
+
"or",
|
55
|
+
"and",
|
56
|
+
"coalesce",
|
57
|
+
"eq",
|
58
|
+
"dne",
|
59
|
+
"less_than",
|
60
|
+
"greater_than",
|
61
|
+
"less_than_or_equal_to",
|
62
|
+
"greater_than_or_equal_to",
|
63
|
+
"contains",
|
64
|
+
"begins_with",
|
65
|
+
"ends_with",
|
66
|
+
"does_not_contain",
|
67
|
+
"does_not_begin_with",
|
68
|
+
"does_not_end_with",
|
69
|
+
"is_none",
|
70
|
+
"is_not_none",
|
71
|
+
"in_",
|
72
|
+
"not_in",
|
73
|
+
"between",
|
74
|
+
"not_between",
|
75
|
+
"is_blank",
|
76
|
+
"is_not_blank",
|
77
|
+
"or_and",
|
78
|
+
"accessor",
|
79
|
+
],
|
80
|
+
)
|
81
|
+
def test_resolve_value__happy_path(descriptor, expected_value):
|
82
|
+
actual_value = resolve_value(descriptor, FixtureState())
|
83
|
+
assert actual_value == expected_value
|
@@ -0,0 +1,90 @@
|
|
1
|
+
from collections.abc import Mapping
|
2
|
+
import dataclasses
|
3
|
+
import inspect
|
4
|
+
from typing import Any, Dict, Optional, Sequence, Set, TypeVar, Union, cast, overload
|
5
|
+
|
6
|
+
from pydantic import BaseModel
|
7
|
+
|
8
|
+
from vellum.workflows.descriptors.base import BaseDescriptor
|
9
|
+
from vellum.workflows.state.base import BaseState
|
10
|
+
|
11
|
+
_T = TypeVar("_T")
|
12
|
+
|
13
|
+
|
14
|
+
@overload
|
15
|
+
def resolve_value(
|
16
|
+
value: BaseDescriptor[_T], state: BaseState, path: str = "", memo: Optional[Dict[str, Any]] = None
|
17
|
+
) -> _T: ...
|
18
|
+
|
19
|
+
|
20
|
+
@overload
|
21
|
+
def resolve_value(value: _T, state: BaseState, path: str = "", memo: Optional[Dict[str, Any]] = None) -> _T: ...
|
22
|
+
|
23
|
+
|
24
|
+
def resolve_value(
|
25
|
+
value: Union[BaseDescriptor[_T], _T], state: BaseState, path: str = "", memo: Optional[Dict[str, Any]] = None
|
26
|
+
) -> _T:
|
27
|
+
"""
|
28
|
+
Recursively resolves Descriptor's until we have a constant value, using BaseState.
|
29
|
+
|
30
|
+
The nonideal casts in this method are due to the `isinstance` calls detaching types
|
31
|
+
from the `_T` generic.
|
32
|
+
"""
|
33
|
+
|
34
|
+
if inspect.isclass(value):
|
35
|
+
return cast(_T, value)
|
36
|
+
|
37
|
+
if isinstance(value, BaseDescriptor):
|
38
|
+
resolved_value = value.resolve(state)
|
39
|
+
if memo is not None:
|
40
|
+
memo[path] = resolved_value
|
41
|
+
return resolved_value
|
42
|
+
|
43
|
+
if isinstance(value, property) or callable(value):
|
44
|
+
return cast(_T, value)
|
45
|
+
|
46
|
+
if isinstance(value, (str, bytes)):
|
47
|
+
return cast(_T, value)
|
48
|
+
|
49
|
+
if dataclasses.is_dataclass(value):
|
50
|
+
# The `inspect.isclass` check above prevents `value` from being a class.
|
51
|
+
dataclass_value = dataclasses.replace( # type: ignore[type-var]
|
52
|
+
value,
|
53
|
+
**{
|
54
|
+
field.name: resolve_value(getattr(value, field.name), state, path=f"{path}.{field.name}", memo=memo)
|
55
|
+
for field in dataclasses.fields(value)
|
56
|
+
},
|
57
|
+
)
|
58
|
+
return cast(_T, dataclass_value)
|
59
|
+
|
60
|
+
if isinstance(value, BaseModel):
|
61
|
+
pydantic_value = value.model_copy(
|
62
|
+
update={
|
63
|
+
key: resolve_value(getattr(value, key), state, path=f"{path}.{key}", memo=memo)
|
64
|
+
for key in value.dict().keys()
|
65
|
+
}
|
66
|
+
)
|
67
|
+
return cast(_T, pydantic_value)
|
68
|
+
|
69
|
+
if isinstance(value, Mapping):
|
70
|
+
mapped_value = type(value)( # type: ignore[call-arg]
|
71
|
+
{
|
72
|
+
dict_key: resolve_value(dict_value, state, path=f"{path}.{dict_key}", memo=memo)
|
73
|
+
for dict_key, dict_value in value.items()
|
74
|
+
}
|
75
|
+
)
|
76
|
+
return cast(_T, mapped_value)
|
77
|
+
|
78
|
+
if isinstance(value, Sequence):
|
79
|
+
sequence_value = type(value)(
|
80
|
+
resolve_value(seq_value, state, path=f"{path}.{index}", memo=memo) for index, seq_value in enumerate(value)
|
81
|
+
) # type: ignore[call-arg]
|
82
|
+
return cast(_T, sequence_value)
|
83
|
+
|
84
|
+
if isinstance(value, Set):
|
85
|
+
set_value = type(value)(
|
86
|
+
resolve_value(set_value, state, path=f"{path}.{index}", memo=memo) for index, set_value in enumerate(value)
|
87
|
+
)
|
88
|
+
return cast(_T, set_value)
|
89
|
+
|
90
|
+
return value
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Any, Type
|
2
|
+
|
3
|
+
if TYPE_CHECKING:
|
4
|
+
from vellum.workflows.nodes.bases import BaseNode
|
5
|
+
from vellum.workflows.ports.port import Port
|
6
|
+
|
7
|
+
|
8
|
+
class Edge:
|
9
|
+
def __init__(self, from_port: "Port", to_node: Type["BaseNode"]):
|
10
|
+
self.from_port = from_port
|
11
|
+
self.to_node = to_node
|
12
|
+
|
13
|
+
def __eq__(self, other: Any) -> bool:
|
14
|
+
if not isinstance(other, Edge):
|
15
|
+
return False
|
16
|
+
|
17
|
+
return self.from_port == other.from_port and self.to_node == other.to_node
|
18
|
+
|
19
|
+
def __hash__(self) -> int:
|
20
|
+
return hash((self.from_port, self.to_node))
|
21
|
+
|
22
|
+
def __repr__(self) -> str:
|
23
|
+
return f"{self.from_port} >> {self.to_node}"
|