mirror of
https://github.com/deepset-ai/haystack.git
synced 2025-12-29 07:59:27 +00:00
feat: Change Pipeline.add_component to fail when reusing Component instances (#6847)
* Change Pipeline.add_component to fail when reusing Component instances * Change variable name and store Pipeline instance in it * Fix tests
This commit is contained in:
parent
d90b0de124
commit
76d324a149
@ -147,6 +147,12 @@ class ComponentMeta(type):
|
||||
if run_signature.parameters[param].default != inspect.Parameter.empty:
|
||||
socket_kwargs["default_value"] = run_signature.parameters[param].default
|
||||
instance.__haystack_input__[param] = InputSocket(**socket_kwargs)
|
||||
|
||||
# Since a Component can't be used in multiple Pipelines at the same time
|
||||
# we need to know if it's already owned by a Pipeline when adding it to one.
|
||||
# We use this flag to check that.
|
||||
instance.__haystack_added_to_pipeline__ = None
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
|
||||
@ -190,10 +190,19 @@ class Pipeline:
|
||||
f"'{type(instance)}' doesn't seem to be a component. Is this class decorated with @component?"
|
||||
)
|
||||
|
||||
if getattr(instance, "__haystack_added_to_pipeline__", None):
|
||||
msg = (
|
||||
"Component has already been added in another Pipeline. "
|
||||
"Components can't be shared between Pipelines. Create a new instance instead."
|
||||
)
|
||||
raise PipelineError(msg)
|
||||
|
||||
# Create the component's input and output sockets
|
||||
input_sockets = getattr(instance, "__haystack_input__", {})
|
||||
output_sockets = getattr(instance, "__haystack_output__", {})
|
||||
|
||||
setattr(instance, "__haystack_added_to_pipeline__", self)
|
||||
|
||||
# Add component to the graph, disconnected
|
||||
logger.debug("Adding component '%s' (%s)", name, instance)
|
||||
self.graph.add_node(
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
---
|
||||
enhancements:
|
||||
- |
|
||||
Change `Pipeline.add_component()` to fail if the `Component` instance has already been added in another `Pipeline`.
|
||||
@ -338,11 +338,12 @@ def test_connect_receiver_socket_does_not_exist():
|
||||
def test_connect_many_outputs_to_the_same_input():
|
||||
add_1 = AddFixedValue()
|
||||
add_2 = AddFixedValue()
|
||||
add_3 = AddFixedValue()
|
||||
|
||||
pipe = Pipeline()
|
||||
pipe.add_component("first", add_1)
|
||||
pipe.add_component("second", add_2)
|
||||
pipe.add_component("third", add_2)
|
||||
pipe.add_component("third", add_3)
|
||||
pipe.connect("first.result", "second.value")
|
||||
with pytest.raises(PipelineConnectError, match=r"second.value is already connected to \['first'\]"):
|
||||
pipe.connect("third.result", "second.value")
|
||||
|
||||
@ -24,8 +24,6 @@ def test_pipeline_equally_long_branches():
|
||||
pipeline.connect("add_two", "multiplexer.value")
|
||||
pipeline.connect("add_one", "multiplexer.value")
|
||||
|
||||
pipeline.draw(Path(__file__).parent / Path(__file__).name.replace(".py", ".png"))
|
||||
|
||||
results = pipeline.run({"multiplexer": {"value": 0}})
|
||||
assert results == {"remainder": {"remainder_is_0": 0}}
|
||||
|
||||
|
||||
@ -7,14 +7,27 @@ from typing import Optional
|
||||
import pytest
|
||||
|
||||
from haystack.core.component.sockets import InputSocket, OutputSocket
|
||||
from haystack.core.errors import PipelineError, PipelineMaxLoops, PipelineRuntimeError
|
||||
from haystack.core.errors import PipelineError, PipelineRuntimeError
|
||||
from haystack.core.pipeline import Pipeline
|
||||
from haystack.testing.factory import component_class
|
||||
from haystack.testing.sample_components import AddFixedValue, Double, Sum, Threshold
|
||||
from haystack.testing.sample_components import AddFixedValue, Double
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
|
||||
def test_add_component_to_different_pipelines():
|
||||
first_pipe = Pipeline()
|
||||
second_pipe = Pipeline()
|
||||
some_component = component_class("Some")()
|
||||
|
||||
assert some_component.__haystack_added_to_pipeline__ is None
|
||||
first_pipe.add_component("some", some_component)
|
||||
assert some_component.__haystack_added_to_pipeline__ is first_pipe
|
||||
|
||||
with pytest.raises(PipelineError):
|
||||
second_pipe.add_component("some", some_component)
|
||||
|
||||
|
||||
def test_run_with_component_that_does_not_return_dict():
|
||||
BrokenComponent = component_class(
|
||||
"BrokenComponent", input_types={"a": int}, output_types={"b": int}, output=1 # type:ignore
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user