vellum-ai 0.12.13__py3-none-any.whl → 0.12.15__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/__init__.py +9 -0
- vellum/client/__init__.py +2 -6
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/environment.py +3 -3
- vellum/client/resources/ad_hoc/client.py +2 -6
- vellum/client/resources/container_images/client.py +0 -8
- vellum/client/resources/metric_definitions/client.py +2 -6
- vellum/client/resources/workflows/client.py +8 -8
- vellum/client/types/__init__.py +6 -0
- vellum/client/types/audio_prompt_block.py +29 -0
- vellum/client/types/function_call_prompt_block.py +30 -0
- vellum/client/types/image_prompt_block.py +29 -0
- vellum/client/types/prompt_block.py +12 -1
- vellum/client/types/workflow_push_response.py +1 -0
- vellum/plugins/pydantic.py +12 -2
- vellum/types/audio_prompt_block.py +3 -0
- vellum/types/function_call_prompt_block.py +3 -0
- vellum/types/image_prompt_block.py +3 -0
- vellum/workflows/descriptors/tests/test_utils.py +3 -0
- vellum/workflows/nodes/bases/base.py +4 -1
- vellum/workflows/nodes/bases/base_adornment_node.py +75 -0
- vellum/workflows/nodes/bases/tests/test_base_node.py +13 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +2 -0
- vellum/workflows/nodes/core/map_node/node.py +49 -45
- vellum/workflows/nodes/core/retry_node/node.py +10 -45
- vellum/workflows/nodes/core/try_node/node.py +12 -84
- vellum/workflows/nodes/utils.py +44 -1
- vellum/workflows/references/constant.py +21 -0
- vellum/workflows/runner/runner.py +4 -3
- vellum/workflows/types/cycle_map.py +34 -0
- vellum/workflows/workflows/base.py +4 -11
- {vellum_ai-0.12.13.dist-info → vellum_ai-0.12.15.dist-info}/METADATA +2 -2
- {vellum_ai-0.12.13.dist-info → vellum_ai-0.12.15.dist-info}/RECORD +52 -39
- vellum_cli/config.py +4 -0
- vellum_cli/pull.py +20 -5
- vellum_cli/push.py +7 -0
- vellum_cli/tests/test_pull.py +19 -1
- vellum_ee/workflows/display/nodes/vellum/__init__.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/base_node.py +18 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +10 -41
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +4 -14
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +174 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +2 -10
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +2 -10
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +5 -19
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +2 -8
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +14 -25
- vellum_ee/workflows/server/__init__.py +0 -0
- vellum_ee/workflows/server/virtual_file_loader.py +42 -0
- {vellum_ai-0.12.13.dist-info → vellum_ai-0.12.15.dist-info}/LICENSE +0 -0
- {vellum_ai-0.12.13.dist-info → vellum_ai-0.12.15.dist-info}/WHEEL +0 -0
- {vellum_ai-0.12.13.dist-info → vellum_ai-0.12.15.dist-info}/entry_points.txt +0 -0
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
from deepdiff import DeepDiff
|
2
|
+
|
3
|
+
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
4
|
+
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
5
|
+
|
6
|
+
from tests.workflows.basic_generic_node.workflow import BasicGenericNodeWorkflow
|
7
|
+
|
8
|
+
|
9
|
+
def test_serialize_workflow(vellum_client):
|
10
|
+
# GIVEN a Workflow that uses a generic node
|
11
|
+
# WHEN we serialize it
|
12
|
+
workflow_display = get_workflow_display(
|
13
|
+
base_display_class=VellumWorkflowDisplay, workflow_class=BasicGenericNodeWorkflow
|
14
|
+
)
|
15
|
+
|
16
|
+
serialized_workflow: dict = workflow_display.serialize()
|
17
|
+
|
18
|
+
# THEN we should get a serialized representation of the Workflow
|
19
|
+
assert serialized_workflow.keys() == {
|
20
|
+
"workflow_raw_data",
|
21
|
+
"input_variables",
|
22
|
+
"output_variables",
|
23
|
+
}
|
24
|
+
|
25
|
+
# AND its input variables should be what we expect
|
26
|
+
input_variables = serialized_workflow["input_variables"]
|
27
|
+
assert len(input_variables) == 1
|
28
|
+
assert not DeepDiff(
|
29
|
+
[
|
30
|
+
{
|
31
|
+
"id": "a07c2273-34a7-42b5-bcad-143b6127cc8a",
|
32
|
+
"key": "input",
|
33
|
+
"type": "STRING",
|
34
|
+
"default": None,
|
35
|
+
"required": True,
|
36
|
+
"extensions": {"color": None},
|
37
|
+
},
|
38
|
+
],
|
39
|
+
input_variables,
|
40
|
+
ignore_order=True,
|
41
|
+
)
|
42
|
+
|
43
|
+
# AND its output variables should be what we expect
|
44
|
+
output_variables = serialized_workflow["output_variables"]
|
45
|
+
assert len(output_variables) == 1
|
46
|
+
assert not DeepDiff(
|
47
|
+
[
|
48
|
+
{"id": "2b6389d0-266a-4be4-843e-4e543dd3d727", "key": "output", "type": "STRING"},
|
49
|
+
],
|
50
|
+
output_variables,
|
51
|
+
ignore_order=True,
|
52
|
+
)
|
53
|
+
|
54
|
+
# AND its raw data should be what we expect
|
55
|
+
workflow_raw_data = serialized_workflow["workflow_raw_data"]
|
56
|
+
assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
|
57
|
+
assert len(workflow_raw_data["edges"]) == 2
|
58
|
+
assert len(workflow_raw_data["nodes"]) == 3
|
59
|
+
|
60
|
+
# AND each node should be serialized correctly
|
61
|
+
entrypoint_node = workflow_raw_data["nodes"][0]
|
62
|
+
assert entrypoint_node == {
|
63
|
+
"id": "f1e4678f-c470-400b-a40e-c8922cc99a86",
|
64
|
+
"type": "ENTRYPOINT",
|
65
|
+
"inputs": [],
|
66
|
+
"data": {"label": "Entrypoint Node", "source_handle_id": "40201804-8beb-43ad-8873-a027759512f1"},
|
67
|
+
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
68
|
+
"definition": {
|
69
|
+
"name": "BaseNode",
|
70
|
+
"module": [
|
71
|
+
"vellum",
|
72
|
+
"workflows",
|
73
|
+
"nodes",
|
74
|
+
"bases",
|
75
|
+
"base",
|
76
|
+
],
|
77
|
+
"bases": [],
|
78
|
+
},
|
79
|
+
}
|
80
|
+
|
81
|
+
api_node = workflow_raw_data["nodes"][1]
|
82
|
+
assert not DeepDiff(
|
83
|
+
{
|
84
|
+
"id": "c2ed23f7-f6cb-4a56-a91c-2e5f9d8fda7f",
|
85
|
+
"type": "GENERIC",
|
86
|
+
},
|
87
|
+
api_node,
|
88
|
+
)
|
89
|
+
|
90
|
+
final_output_node = workflow_raw_data["nodes"][2]
|
91
|
+
assert not DeepDiff(
|
92
|
+
{
|
93
|
+
"id": "50e3b446-afcd-4a5d-8c6f-5f05eaf2200e",
|
94
|
+
"type": "TERMINAL",
|
95
|
+
"data": {
|
96
|
+
"label": "Final Output",
|
97
|
+
"name": "output",
|
98
|
+
"target_handle_id": "8bd9f4f3-9f66-4d95-8e84-529b0002c531",
|
99
|
+
"output_id": "2b6389d0-266a-4be4-843e-4e543dd3d727",
|
100
|
+
"output_type": "STRING",
|
101
|
+
"node_input_id": "7a9f2d3a-0b23-4bd4-b567-e9493135b727",
|
102
|
+
},
|
103
|
+
"inputs": [
|
104
|
+
{
|
105
|
+
"id": "7a9f2d3a-0b23-4bd4-b567-e9493135b727",
|
106
|
+
"key": "node_input",
|
107
|
+
"value": {
|
108
|
+
"rules": [
|
109
|
+
{
|
110
|
+
"type": "NODE_OUTPUT",
|
111
|
+
"data": {
|
112
|
+
"node_id": "c2ed23f7-f6cb-4a56-a91c-2e5f9d8fda7f",
|
113
|
+
"output_id": "0a9c7a80-fc89-4a71-aac0-66489e4ddb85",
|
114
|
+
},
|
115
|
+
}
|
116
|
+
],
|
117
|
+
"combinator": "OR",
|
118
|
+
},
|
119
|
+
}
|
120
|
+
],
|
121
|
+
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
122
|
+
"definition": {
|
123
|
+
"name": "FinalOutputNode",
|
124
|
+
"module": ["vellum", "workflows", "nodes", "displayable", "final_output_node", "node"],
|
125
|
+
"bases": [
|
126
|
+
{"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"], "bases": []}
|
127
|
+
],
|
128
|
+
},
|
129
|
+
},
|
130
|
+
final_output_node,
|
131
|
+
ignore_order=True,
|
132
|
+
)
|
133
|
+
|
134
|
+
# AND each edge should be serialized correctly
|
135
|
+
serialized_edges = workflow_raw_data["edges"]
|
136
|
+
assert not DeepDiff(
|
137
|
+
[
|
138
|
+
{
|
139
|
+
"id": "445dd2de-82b2-482b-89f6-5f49d8eb21a9",
|
140
|
+
"source_node_id": "f1e4678f-c470-400b-a40e-c8922cc99a86",
|
141
|
+
"source_handle_id": "40201804-8beb-43ad-8873-a027759512f1",
|
142
|
+
"target_node_id": "c2ed23f7-f6cb-4a56-a91c-2e5f9d8fda7f",
|
143
|
+
"target_handle_id": "b7bfb298-959a-4d2b-8b85-bbd0d2522703",
|
144
|
+
"type": "DEFAULT",
|
145
|
+
},
|
146
|
+
{
|
147
|
+
"id": "b741c861-cf67-4649-b9ef-b43a4add72b1",
|
148
|
+
"source_node_id": "c2ed23f7-f6cb-4a56-a91c-2e5f9d8fda7f",
|
149
|
+
"source_handle_id": "89dccfa5-cc1a-4612-bd87-86cb444f6dd4",
|
150
|
+
"target_node_id": "50e3b446-afcd-4a5d-8c6f-5f05eaf2200e",
|
151
|
+
"target_handle_id": "8bd9f4f3-9f66-4d95-8e84-529b0002c531",
|
152
|
+
"type": "DEFAULT",
|
153
|
+
},
|
154
|
+
],
|
155
|
+
serialized_edges,
|
156
|
+
ignore_order=True,
|
157
|
+
)
|
158
|
+
|
159
|
+
# AND the display data should be what we expect
|
160
|
+
display_data = workflow_raw_data["display_data"]
|
161
|
+
assert display_data == {
|
162
|
+
"viewport": {
|
163
|
+
"x": 0.0,
|
164
|
+
"y": 0.0,
|
165
|
+
"zoom": 1.0,
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
# AND the definition should be what we expect
|
170
|
+
definition = workflow_raw_data["definition"]
|
171
|
+
assert definition == {
|
172
|
+
"name": "BasicGenericNodeWorkflow",
|
173
|
+
"module": ["tests", "workflows", "basic_generic_node", "workflow"],
|
174
|
+
}
|
@@ -1,8 +1,5 @@
|
|
1
|
-
from unittest import mock
|
2
|
-
|
3
1
|
from deepdiff import DeepDiff
|
4
2
|
|
5
|
-
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
6
3
|
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
7
4
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
8
5
|
|
@@ -15,12 +12,7 @@ def test_serialize_workflow():
|
|
15
12
|
workflow_display = get_workflow_display(
|
16
13
|
base_display_class=VellumWorkflowDisplay, workflow_class=BasicInlineSubworkflowWorkflow
|
17
14
|
)
|
18
|
-
|
19
|
-
# TODO: Support serialization of BaseNode
|
20
|
-
# https://app.shortcut.com/vellum/story/4871/support-serialization-of-base-node
|
21
|
-
with mock.patch.object(BaseNodeVellumDisplay, "serialize") as mocked_serialize:
|
22
|
-
mocked_serialize.return_value = {"type": "MOCKED"}
|
23
|
-
serialized_workflow: dict = workflow_display.serialize()
|
15
|
+
serialized_workflow: dict = workflow_display.serialize()
|
24
16
|
|
25
17
|
# THEN we should get a serialized representation of the Workflow
|
26
18
|
assert serialized_workflow.keys() == {
|
@@ -156,7 +148,7 @@ def test_serialize_workflow():
|
|
156
148
|
"bases": [],
|
157
149
|
},
|
158
150
|
},
|
159
|
-
{"type": "
|
151
|
+
{"id": "1381c078-efa2-4255-89a1-7b4cb742c7fc", "type": "GENERIC"},
|
160
152
|
{
|
161
153
|
"id": "a773c3a5-78cb-4250-8d29-7282e8a579d3",
|
162
154
|
"type": "TERMINAL",
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
from unittest import mock
|
2
|
-
|
3
1
|
from deepdiff import DeepDiff
|
4
2
|
|
5
|
-
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
6
3
|
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
7
4
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
8
5
|
|
@@ -13,12 +10,7 @@ def test_serialize_workflow():
|
|
13
10
|
# GIVEN a Workflow that uses a MapNode
|
14
11
|
# WHEN we serialize it
|
15
12
|
workflow_display = get_workflow_display(base_display_class=VellumWorkflowDisplay, workflow_class=SimpleMapExample)
|
16
|
-
|
17
|
-
# TODO: Support serialization of BaseNode
|
18
|
-
# https://app.shortcut.com/vellum/story/4871/support-serialization-of-base-node
|
19
|
-
with mock.patch.object(BaseNodeVellumDisplay, "serialize") as mocked_serialize:
|
20
|
-
mocked_serialize.return_value = {"type": "MOCKED"}
|
21
|
-
serialized_workflow: dict = workflow_display.serialize()
|
13
|
+
serialized_workflow: dict = workflow_display.serialize()
|
22
14
|
|
23
15
|
# THEN we should get a serialized representation of the Workflow
|
24
16
|
assert serialized_workflow.keys() == {
|
@@ -141,7 +133,7 @@ def test_serialize_workflow():
|
|
141
133
|
"bases": [],
|
142
134
|
},
|
143
135
|
},
|
144
|
-
{"type": "
|
136
|
+
{"id": "baf6d316-dc75-41e8-96c0-015aede96309", "type": "GENERIC"},
|
145
137
|
{
|
146
138
|
"id": "6f4883b2-70b1-4e1c-ae15-7d0f5aec810b",
|
147
139
|
"type": "TERMINAL",
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
from unittest import mock
|
2
|
-
|
3
1
|
from deepdiff import DeepDiff
|
4
2
|
|
5
|
-
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
6
3
|
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
7
4
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
8
5
|
|
@@ -15,12 +12,7 @@ def test_serialize_workflow__await_all():
|
|
15
12
|
workflow_display = get_workflow_display(
|
16
13
|
base_display_class=VellumWorkflowDisplay, workflow_class=AwaitAllPassingWorkflow
|
17
14
|
)
|
18
|
-
|
19
|
-
# TODO: Support serialization of BaseNode
|
20
|
-
# https://app.shortcut.com/vellum/story/4871/support-serialization-of-base-node
|
21
|
-
with mock.patch.object(BaseNodeVellumDisplay, "serialize") as mocked_serialize:
|
22
|
-
mocked_serialize.return_value = {"type": "MOCKED"}
|
23
|
-
serialized_workflow: dict = workflow_display.serialize()
|
15
|
+
serialized_workflow: dict = workflow_display.serialize()
|
24
16
|
|
25
17
|
# THEN we should get a serialized representation of the Workflow
|
26
18
|
assert serialized_workflow.keys() == {
|
@@ -76,18 +68,12 @@ def test_serialize_workflow__await_all():
|
|
76
68
|
},
|
77
69
|
}
|
78
70
|
|
79
|
-
passthrough_nodes = [node for node in workflow_raw_data["nodes"] if node["type"] == "
|
71
|
+
passthrough_nodes = [node for node in workflow_raw_data["nodes"] if node["type"] == "GENERIC"]
|
80
72
|
assert not DeepDiff(
|
81
73
|
[
|
82
|
-
{
|
83
|
-
|
84
|
-
},
|
85
|
-
{
|
86
|
-
"type": "MOCKED",
|
87
|
-
},
|
88
|
-
{
|
89
|
-
"type": "MOCKED",
|
90
|
-
},
|
74
|
+
{"id": "127ef456-91bc-43c6-bd8b-1772db5e3cb5", "type": "GENERIC"},
|
75
|
+
{"id": "59243c65-053f-4ea6-9157-3f3edb1477bf", "type": "GENERIC"},
|
76
|
+
{"id": "634f0202-9ea9-4c62-b152-1a58c595cffb", "type": "GENERIC"},
|
91
77
|
],
|
92
78
|
passthrough_nodes,
|
93
79
|
ignore_order=True,
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
from unittest import mock
|
2
|
-
|
3
1
|
from deepdiff import DeepDiff
|
4
2
|
|
5
|
-
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
6
3
|
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
7
4
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
8
5
|
|
@@ -13,10 +10,7 @@ def test_serialize_workflow():
|
|
13
10
|
# GIVEN a Workflow with a TryNode
|
14
11
|
# WHEN we serialize it
|
15
12
|
workflow_display = get_workflow_display(base_display_class=VellumWorkflowDisplay, workflow_class=SimpleTryExample)
|
16
|
-
|
17
|
-
with mock.patch.object(BaseNodeVellumDisplay, "serialize") as mocked_serialize:
|
18
|
-
mocked_serialize.return_value = {"type": "MOCKED"}
|
19
|
-
serialized_workflow: dict = workflow_display.serialize()
|
13
|
+
serialized_workflow: dict = workflow_display.serialize()
|
20
14
|
|
21
15
|
# THEN we should get a serialized representation of the Workflow
|
22
16
|
assert serialized_workflow.keys() == {
|
@@ -82,4 +76,4 @@ def test_serialize_workflow():
|
|
82
76
|
}
|
83
77
|
|
84
78
|
try_node = workflow_raw_data["nodes"][1]
|
85
|
-
assert try_node == {"type": "
|
79
|
+
assert try_node == {"id": "1381c078-efa2-4255-89a1-7b4cb742c7fc", "type": "GENERIC"}
|
vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
import pytest
|
2
|
-
from unittest import mock
|
3
2
|
|
4
3
|
from deepdiff import DeepDiff
|
5
4
|
|
6
|
-
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
7
5
|
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
8
6
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
9
7
|
|
@@ -13,17 +11,12 @@ from tests.workflows.complex_final_output_node.missing_workflow_output import Mi
|
|
13
11
|
|
14
12
|
def test_serialize_workflow__missing_final_output_node():
|
15
13
|
# GIVEN a Workflow that is missing a Terminal Node
|
14
|
+
workflow_display = get_workflow_display(
|
15
|
+
base_display_class=VellumWorkflowDisplay, workflow_class=MissingFinalOutputNodeWorkflow
|
16
|
+
)
|
16
17
|
|
17
|
-
#
|
18
|
-
|
19
|
-
with mock.patch.object(BaseNodeVellumDisplay, "serialize") as mocked_serialize:
|
20
|
-
mocked_serialize.return_value = {"type": "MOCKED"}
|
21
|
-
workflow_display = get_workflow_display(
|
22
|
-
base_display_class=VellumWorkflowDisplay, workflow_class=MissingFinalOutputNodeWorkflow
|
23
|
-
)
|
24
|
-
|
25
|
-
# WHEN we serialize it
|
26
|
-
serialized_workflow: dict = workflow_display.serialize()
|
18
|
+
# WHEN we serialize it
|
19
|
+
serialized_workflow: dict = workflow_display.serialize()
|
27
20
|
|
28
21
|
# THEN we should get a serialized representation of the Workflow
|
29
22
|
assert serialized_workflow.keys() == {
|
@@ -97,9 +90,10 @@ def test_serialize_workflow__missing_final_output_node():
|
|
97
90
|
},
|
98
91
|
}
|
99
92
|
|
100
|
-
passthrough_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "
|
93
|
+
passthrough_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "GENERIC")
|
101
94
|
assert passthrough_node == {
|
102
|
-
"
|
95
|
+
"id": "32d88cab-e9fa-4a56-9bc2-fb6e1fd0897f",
|
96
|
+
"type": "GENERIC",
|
103
97
|
}
|
104
98
|
|
105
99
|
final_output_nodes = [node for node in workflow_raw_data["nodes"] if node["type"] == "TERMINAL"]
|
@@ -218,17 +212,12 @@ def test_serialize_workflow__missing_final_output_node():
|
|
218
212
|
|
219
213
|
def test_serialize_workflow__missing_workflow_output():
|
220
214
|
# GIVEN a Workflow that contains a terminal node that is unreferenced by the Workflow's Outputs
|
215
|
+
workflow_display = get_workflow_display(
|
216
|
+
base_display_class=VellumWorkflowDisplay, workflow_class=MissingWorkflowOutputWorkflow
|
217
|
+
)
|
221
218
|
|
222
|
-
#
|
223
|
-
|
224
|
-
|
225
|
-
mocked_serialize.return_value = {"type": "MOCKED"}
|
226
|
-
workflow_display = get_workflow_display(
|
227
|
-
base_display_class=VellumWorkflowDisplay, workflow_class=MissingWorkflowOutputWorkflow
|
228
|
-
)
|
229
|
-
|
230
|
-
# WHEN we serialize it, it should throw an error
|
231
|
-
with pytest.raises(ValueError) as exc_info:
|
232
|
-
workflow_display.serialize()
|
219
|
+
# WHEN we serialize it, it should throw an error
|
220
|
+
with pytest.raises(ValueError) as exc_info:
|
221
|
+
workflow_display.serialize()
|
233
222
|
|
234
223
|
assert exc_info.value.args[0] == "Unable to serialize terminal nodes that are not referenced by workflow outputs."
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import importlib
|
2
|
+
|
3
|
+
|
4
|
+
class VirtualFileLoader(importlib.abc.Loader):
|
5
|
+
def __init__(self, code: str, is_package: bool):
|
6
|
+
self.code = code
|
7
|
+
self.is_package = is_package
|
8
|
+
|
9
|
+
def create_module(self, spec):
|
10
|
+
return None # use default module creation
|
11
|
+
|
12
|
+
def exec_module(self, module):
|
13
|
+
if not self.is_package:
|
14
|
+
exec(self.code, module.__dict__)
|
15
|
+
|
16
|
+
|
17
|
+
class VirtualFileFinder(importlib.abc.MetaPathFinder, importlib.abc.Loader):
|
18
|
+
def __init__(self, files: dict[str, str], namespace: str):
|
19
|
+
self.files = files
|
20
|
+
self.namespace = namespace
|
21
|
+
|
22
|
+
def find_spec(self, fullname, path, target=None):
|
23
|
+
# Do the namespacing on the fly to avoid having to copy the file dict
|
24
|
+
prefixed_name = fullname if fullname.startswith(self.namespace) else f"{self.namespace}.{fullname}"
|
25
|
+
|
26
|
+
key_name = "__init__" if fullname == self.namespace else fullname.replace(f"{self.namespace}.", "")
|
27
|
+
|
28
|
+
files_key = f"{key_name.replace('.', '/')}.py"
|
29
|
+
if not self.files.get(files_key):
|
30
|
+
files_key = f"{key_name.replace('.', '/')}/__init__.py"
|
31
|
+
|
32
|
+
file = self.files.get(files_key)
|
33
|
+
is_package = "__init__" in files_key
|
34
|
+
|
35
|
+
if file:
|
36
|
+
return importlib.machinery.ModuleSpec(
|
37
|
+
prefixed_name,
|
38
|
+
VirtualFileLoader(file, is_package),
|
39
|
+
origin=prefixed_name,
|
40
|
+
is_package=is_package,
|
41
|
+
)
|
42
|
+
return None
|
File without changes
|
File without changes
|
File without changes
|