Skip to content

Commit

Permalink
add loop component 🎁🎄
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigosnader authored Dec 24, 2024
1 parent d31be29 commit 0d65b9e
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions src/backend/base/langflow/components/logic/loop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from langflow.custom import Component
from langflow.io import DataInput, Output
from langflow.schema import Data


class IteratorComponent(Component):
display_name = "Loop"
description = (
"Iterates over a list of Data objects, outputting one item at a time and aggregating results from loop inputs."
)
icon = "infinity"

inputs = [
DataInput(
name="data",
display_name="Data",
info="The initial list of Data objects to iterate over."
),
DataInput(
name="loop",
display_name="Loop Input",
info="Data to aggregate during the iteration."
)
]

outputs = [
Output(display_name="Item", name="item", method="item_output"),
Output(display_name="Done", name="done", method="done_output")
]

def initialize_data(self):
"""Initialize the data list, context index, and aggregated list."""
if not self.ctx.get(f"{self._id}_initialized", False):
# Ensure data is a list of Data objects
if isinstance(self.data, Data):
data_list = [self.data]
elif isinstance(self.data, list):
data_list = self.data
else:
raise ValueError("The 'data' input must be a list of Data objects or a single Data object.")

Check failure on line 40 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (TRY003)

src/backend/base/langflow/components/logic/loop.py:40:23: TRY003 Avoid specifying long messages outside the exception class

Check failure on line 40 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (EM101)

src/backend/base/langflow/components/logic/loop.py:40:34: EM101 Exception must not use a string literal, assign to variable first

# Store the initial data and context variables
self.update_ctx({
f"{self._id}_data": data_list,
f"{self._id}_index": 0,
f"{self._id}_aggregated": [],
f"{self._id}_initialized": True
})

def item_output(self) -> Data:
"""Output the next item in the list."""
self.initialize_data()

# Get data list and current index
data_list = self.ctx.get(f"{self._id}_data", [])
current_index = self.ctx.get(f"{self._id}_index", 0)

if current_index < len(data_list):
# Output current item
current_item = data_list[current_index]
self.update_ctx({f"{self._id}_index": current_index + 1})
print("item_output:", current_item)

Check failure on line 62 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (T201)

src/backend/base/langflow/components/logic/loop.py:62:13: T201 `print` found
return current_item
else:

Check failure on line 64 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (RET505)

src/backend/base/langflow/components/logic/loop.py:64:9: RET505 Unnecessary `else` after `return` statement
# No more items to output
self.stop("item")
return

Check failure on line 67 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (RET502)

src/backend/base/langflow/components/logic/loop.py:67:13: RET502 Do not implicitly `return None` in function able to return non-`None` value

def done_output(self) -> Data:
"""Return the aggregated list once all items are processed."""
self.initialize_data()

# Get data list and aggregated list
data_list = self.ctx.get(f"{self._id}_data", [])
aggregated = self.ctx.get(f"{self._id}_aggregated", [])

# Check if loop input is provided
loop_input = self.loop
if loop_input:
# Append loop input to aggregated list
aggregated.append(loop_input)
self.update_ctx({f"{self._id}_aggregated": aggregated})

# Check if aggregation is complete
if len(aggregated) >= len(data_list):
print("done_output:", aggregated)

Check failure on line 86 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (T201)

src/backend/base/langflow/components/logic/loop.py:86:13: T201 `print` found
return [data for data in aggregated]

Check failure on line 87 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (C416)

src/backend/base/langflow/components/logic/loop.py:87:20: C416 Unnecessary list comprehension (rewrite using `list()`)
else:

Check failure on line 88 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (RET505)

src/backend/base/langflow/components/logic/loop.py:88:9: RET505 Unnecessary `else` after `return` statement
# Not all items have been processed yet
self.stop("done")
return

Check failure on line 91 in src/backend/base/langflow/components/logic/loop.py

View workflow job for this annotation

GitHub Actions / Ruff Style Check (3.12)

Ruff (RET502)

src/backend/base/langflow/components/logic/loop.py:91:13: RET502 Do not implicitly `return None` in function able to return non-`None` value

0 comments on commit 0d65b9e

Please sign in to comment.