formatting issues fixed

This commit is contained in:
SwiftyOS
2025-06-30 11:34:44 +02:00
parent d1b8dcd298
commit 31bcdb97a7
11 changed files with 194 additions and 179 deletions

View File

@@ -8,9 +8,9 @@ from backend.sdk import (
CredentialsMetaInput,
Dict,
List,
Requests,
SchemaField,
String,
requests,
)
from ._config import exa
@@ -66,7 +66,7 @@ class ExaAnswerBlock(Block):
output_schema=ExaAnswerBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
url = "https://api.exa.ai/answer"
@@ -86,8 +86,7 @@ class ExaAnswerBlock(Block):
try:
# Note: This endpoint doesn't support streaming in our block implementation
# If stream=True is requested, we still make a regular request
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
response = await Requests().post(url, headers=headers, json=payload)
data = response.json()
yield "answer", data.get("answer", "")

View File

@@ -6,9 +6,9 @@ from backend.sdk import (
BlockSchema,
CredentialsMetaInput,
List,
Requests,
SchemaField,
String,
Requests,
)
from ._config import exa

View File

@@ -10,9 +10,9 @@ from backend.sdk import (
CredentialsMetaInput,
Integer,
List,
Requests,
SchemaField,
String,
Requests,
)
from ._config import exa

View File

@@ -10,9 +10,9 @@ from backend.sdk import (
CredentialsMetaInput,
Integer,
List,
Requests,
SchemaField,
String,
Requests,
)
from ._config import exa

View File

@@ -11,9 +11,9 @@ from backend.sdk import (
Integer,
List,
Optional,
Requests,
SchemaField,
String,
requests,
)
from ._config import exa
@@ -69,7 +69,7 @@ class ExaCreateWebsetBlock(Block):
output_schema=ExaCreateWebsetBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
url = "https://api.exa.ai/websets/v0/websets"
@@ -97,8 +97,7 @@ class ExaCreateWebsetBlock(Block):
payload["metadata"] = input_data.metadata
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
response = await Requests().post(url, headers=headers, json=payload)
data = response.json()
yield "webset_id", data.get("id", "")
@@ -154,7 +153,7 @@ class ExaUpdateWebsetBlock(Block):
output_schema=ExaUpdateWebsetBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
url = f"https://api.exa.ai/websets/v0/websets/{input_data.webset_id}"
@@ -169,8 +168,7 @@ class ExaUpdateWebsetBlock(Block):
payload["metadata"] = input_data.metadata
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
response = await Requests().post(url, headers=headers, json=payload)
data = response.json()
yield "webset_id", data.get("id", "")
@@ -227,7 +225,7 @@ class ExaListWebsetsBlock(Block):
output_schema=ExaListWebsetsBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
url = "https://api.exa.ai/websets/v0/websets"
@@ -242,8 +240,7 @@ class ExaListWebsetsBlock(Block):
params["cursor"] = input_data.cursor
try:
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
response = await Requests().get(url, headers=headers, params=params)
data = response.json()
yield "websets", data.get("data", [])
@@ -313,7 +310,7 @@ class ExaGetWebsetBlock(Block):
output_schema=ExaGetWebsetBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
url = f"https://api.exa.ai/websets/v0/websets/{input_data.webset_id}"
@@ -326,8 +323,7 @@ class ExaGetWebsetBlock(Block):
params["expand[]"] = "items"
try:
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
response = await Requests().get(url, headers=headers, params=params)
data = response.json()
yield "webset_id", data.get("id", "")
@@ -387,7 +383,7 @@ class ExaDeleteWebsetBlock(Block):
output_schema=ExaDeleteWebsetBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
url = f"https://api.exa.ai/websets/v0/websets/{input_data.webset_id}"
@@ -396,8 +392,7 @@ class ExaDeleteWebsetBlock(Block):
}
try:
response = requests.delete(url, headers=headers)
response.raise_for_status()
response = await Requests().delete(url, headers=headers)
data = response.json()
yield "webset_id", data.get("id", "")
@@ -448,7 +443,7 @@ class ExaCancelWebsetBlock(Block):
output_schema=ExaCancelWebsetBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
url = f"https://api.exa.ai/websets/v0/websets/{input_data.webset_id}/cancel"
@@ -457,8 +452,7 @@ class ExaCancelWebsetBlock(Block):
}
try:
response = requests.post(url, headers=headers)
response.raise_for_status()
response = await Requests().post(url, headers=headers)
data = response.json()
yield "webset_id", data.get("id", "")

View File

@@ -91,7 +91,7 @@ class ExampleSDKBlock(Block):
test_credentials=TEST_CREDENTIALS,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
try:

View File

@@ -114,7 +114,7 @@ class ExampleWebhookSDKBlock(Block):
),
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
try:
# Extract webhook payload
payload = input_data.payload

View File

@@ -51,6 +51,6 @@ class SimpleExampleBlock(Block):
output_schema=SimpleExampleBlock.Output,
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
result = input_data.text * input_data.count
yield "result", result

View File

@@ -29,7 +29,8 @@ from backend.sdk import (
class TestBasicBlockCreation:
"""Test creating basic blocks using the SDK."""
def test_simple_block(self):
@pytest.mark.asyncio
async def test_simple_block(self):
"""Test creating a simple block without any decorators."""
class SimpleBlock(Block):
@@ -51,7 +52,7 @@ class TestBasicBlockCreation:
output_schema=SimpleBlock.Output,
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
result = input_data.text * input_data.count
yield "result", result
@@ -61,15 +62,16 @@ class TestBasicBlockCreation:
assert BlockCategory.TEXT in block.categories
# Test execution
outputs = list(
block.run(
SimpleBlock.Input(text="Hello ", count=3),
)
)
outputs = []
async for name, value in block.run(
SimpleBlock.Input(text="Hello ", count=3),
):
outputs.append((name, value))
assert len(outputs) == 1
assert outputs[0] == ("result", "Hello Hello Hello ")
def test_block_with_credentials(self):
@pytest.mark.asyncio
async def test_block_with_credentials(self):
"""Test creating a block that requires credentials."""
class APIBlock(Block):
@@ -96,7 +98,7 @@ class TestBasicBlockCreation:
output_schema=APIBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
# Simulate API call
@@ -116,25 +118,26 @@ class TestBasicBlockCreation:
# Create and test the block
block = APIBlock()
outputs = list(
block.run(
APIBlock.Input(
credentials={ # type: ignore
"provider": "test_api",
"id": "test-creds",
"type": "api_key",
},
query="test query",
),
credentials=test_creds,
)
)
outputs = []
async for name, value in block.run(
APIBlock.Input(
credentials={ # type: ignore
"provider": "test_api",
"id": "test-creds",
"type": "api_key",
},
query="test query",
),
credentials=test_creds,
):
outputs.append((name, value))
assert len(outputs) == 2
assert outputs[0] == ("response", "API response for: test query")
assert outputs[1] == ("authenticated", True)
def test_block_with_multiple_outputs(self):
@pytest.mark.asyncio
async def test_block_with_multiple_outputs(self):
"""Test block that yields multiple outputs."""
class MultiOutputBlock(Block):
@@ -158,7 +161,7 @@ class TestBasicBlockCreation:
output_schema=MultiOutputBlock.Output,
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
text = input_data.text
yield "uppercase", text.upper()
yield "lowercase", text.lower()
@@ -167,7 +170,9 @@ class TestBasicBlockCreation:
# Test the block
block = MultiOutputBlock()
outputs = list(block.run(MultiOutputBlock.Input(text="Hello World")))
outputs = []
async for name, value in block.run(MultiOutputBlock.Input(text="Hello World")):
outputs.append((name, value))
assert len(outputs) == 4
assert ("uppercase", "HELLO WORLD") in outputs
@@ -189,7 +194,8 @@ class TestBlockWithProvider:
.build()
)
def test_block_using_provider(self):
@pytest.mark.asyncio
async def test_block_using_provider(self):
"""Test block that uses a registered provider."""
class TestServiceBlock(Block):
@@ -216,7 +222,7 @@ class TestBlockWithProvider:
output_schema=TestServiceBlock.Output,
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
# The provider name should match
@@ -233,19 +239,19 @@ class TestBlockWithProvider:
# Test the block
block = TestServiceBlock()
outputs = dict(
block.run(
TestServiceBlock.Input(
credentials={ # type: ignore
"provider": "test_service",
"id": "test-service-creds",
"type": "api_key",
},
action="test action",
),
credentials=creds,
)
)
outputs = {}
async for name, value in block.run(
TestServiceBlock.Input(
credentials={ # type: ignore
"provider": "test_service",
"id": "test-service-creds",
"type": "api_key",
},
action="test action",
),
credentials=creds,
):
outputs[name] = value
assert outputs["result"] == "Performed: test action"
assert outputs["provider_name"] == "test_service"
@@ -254,7 +260,8 @@ class TestBlockWithProvider:
class TestComplexBlockScenarios:
"""Test more complex block scenarios."""
def test_block_with_optional_fields(self):
@pytest.mark.asyncio
async def test_block_with_optional_fields(self):
"""Test block with optional input fields."""
# Optional is already imported at the module level
@@ -288,40 +295,41 @@ class TestComplexBlockScenarios:
output_schema=OptionalFieldBlock.Output,
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
yield "has_optional", input_data.optional_field is not None
yield "optional_value", input_data.optional_field
yield "default_value", input_data.optional_with_default
# Test with optional field provided
block = OptionalFieldBlock()
outputs = dict(
block.run(
OptionalFieldBlock.Input(
required_field="test",
optional_field="provided",
)
outputs = {}
async for name, value in block.run(
OptionalFieldBlock.Input(
required_field="test",
optional_field="provided",
)
)
):
outputs[name] = value
assert outputs["has_optional"] is True
assert outputs["optional_value"] == "provided"
assert outputs["default_value"] == "default value"
# Test without optional field
outputs = dict(
block.run(
OptionalFieldBlock.Input(
required_field="test",
)
outputs = {}
async for name, value in block.run(
OptionalFieldBlock.Input(
required_field="test",
)
)
):
outputs[name] = value
assert outputs["has_optional"] is False
assert outputs["optional_value"] is None
assert outputs["default_value"] == "default value"
def test_block_with_complex_types(self):
@pytest.mark.asyncio
async def test_block_with_complex_types(self):
"""Test block with complex input/output types."""
from backend.sdk import BaseModel, Dict, List
@@ -352,7 +360,7 @@ class TestComplexBlockScenarios:
output_schema=ComplexBlock.Output,
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
yield "item_count", len(input_data.items)
yield "total_value", sum(input_data.mapping.values())
@@ -366,20 +374,21 @@ class TestComplexBlockScenarios:
# Test the block
block = ComplexBlock()
outputs = dict(
block.run(
ComplexBlock.Input(
items=["apple", "banana", "orange"],
mapping={"apple": 5, "banana": 3, "orange": 4},
)
outputs = {}
async for name, value in block.run(
ComplexBlock.Input(
items=["apple", "banana", "orange"],
mapping={"apple": 5, "banana": 3, "orange": 4},
)
)
):
outputs[name] = value
assert outputs["item_count"] == 3
assert outputs["total_value"] == 12
assert outputs["combined"] == ["apple: 5", "banana: 3", "orange: 4"]
def test_block_error_handling(self):
@pytest.mark.asyncio
async def test_block_error_handling(self):
"""Test block error handling."""
class ErrorHandlingBlock(Block):
@@ -407,7 +416,7 @@ class TestComplexBlockScenarios:
output_schema=ErrorHandlingBlock.Output,
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
if input_data.should_error:
raise ValueError("Intentional error triggered")
@@ -420,22 +429,31 @@ class TestComplexBlockScenarios:
# Test normal operation
block = ErrorHandlingBlock()
outputs = dict(block.run(ErrorHandlingBlock.Input(value=5, should_error=False)))
outputs = {}
async for name, value in block.run(
ErrorHandlingBlock.Input(value=5, should_error=False)
):
outputs[name] = value
assert outputs["result"] == 10
assert outputs["error_message"] is None
# Test with negative value
outputs = dict(
block.run(ErrorHandlingBlock.Input(value=-5, should_error=False))
)
outputs = {}
async for name, value in block.run(
ErrorHandlingBlock.Input(value=-5, should_error=False)
):
outputs[name] = value
assert outputs["result"] == 0
assert outputs["error_message"] == "Value must be non-negative"
# Test with error
with pytest.raises(ValueError, match="Intentional error triggered"):
list(block.run(ErrorHandlingBlock.Input(value=5, should_error=True)))
async for _ in block.run(
ErrorHandlingBlock.Input(value=5, should_error=True)
):
pass
if __name__ == "__main__":

View File

@@ -487,11 +487,11 @@ class TestSDKImports:
def test_utility_imports(self):
"""Test utility imports."""
from backend.sdk import BaseModel, json, requests
from backend.sdk import BaseModel, Requests, json
assert json is not None
assert BaseModel is not None
assert requests is not None
assert Requests is not None
def test_integration_imports(self):
"""Test integration imports."""

View File

@@ -124,7 +124,7 @@ class TestWebhookBlock(Block):
),
)
def run(
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
# Simulate webhook registration
@@ -150,7 +150,8 @@ class TestWebhookBlockCreation:
.build()
)
def test_basic_webhook_block(self):
@pytest.mark.asyncio
async def test_basic_webhook_block(self):
"""Test creating a basic webhook block."""
block = TestWebhookBlock()
@@ -168,27 +169,28 @@ class TestWebhookBlockCreation:
title="Test Webhook Key",
)
outputs = dict(
block.run(
TestWebhookBlock.Input(
credentials={ # type: ignore
"provider": "test_webhooks",
"id": "test-webhook-creds",
"type": "api_key",
},
webhook_url="https://example.com/webhook",
resource_id="resource_123",
events=[TestWebhookTypes.CREATED, TestWebhookTypes.UPDATED],
),
credentials=test_creds,
)
)
outputs = {}
async for name, value in block.run(
TestWebhookBlock.Input(
credentials={ # type: ignore
"provider": "test_webhooks",
"id": "test-webhook-creds",
"type": "api_key",
},
webhook_url="https://example.com/webhook",
resource_id="resource_123",
events=[TestWebhookTypes.CREATED, TestWebhookTypes.UPDATED],
),
credentials=test_creds,
):
outputs[name] = value
assert outputs["webhook_id"] == "webhook_resource_123"
assert outputs["is_active"] is True
assert outputs["event_count"] == 2
def test_webhook_block_with_filters(self):
@pytest.mark.asyncio
async def test_webhook_block_with_filters(self):
"""Test webhook block with event filters."""
class EventFilterModel(BaseModel):
@@ -233,7 +235,7 @@ class TestWebhookBlockCreation:
),
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
filters = input_data.filters
filter_parts = []
@@ -256,19 +258,19 @@ class TestWebhookBlockCreation:
)
# Test with default filters
outputs = dict(
block.run(
FilteredWebhookBlock.Input(
credentials={ # type: ignore
"provider": "test_webhooks",
"id": "test-creds",
"type": "api_key",
},
resource="test_resource",
),
credentials=test_creds,
)
)
outputs = {}
async for name, value in block.run(
FilteredWebhookBlock.Input(
credentials={ # type: ignore
"provider": "test_webhooks",
"id": "test-creds",
"type": "api_key",
},
resource="test_resource",
),
credentials=test_creds,
):
outputs[name] = value
assert outputs["webhook_active"] is True
assert "2 severity levels" in outputs["filter_summary"]
@@ -279,20 +281,20 @@ class TestWebhookBlockCreation:
severity_levels=["error", "critical"],
)
outputs = dict(
block.run(
FilteredWebhookBlock.Input(
credentials={ # type: ignore
"provider": "test_webhooks",
"id": "test-creds",
"type": "api_key",
},
resource="test_resource",
filters=custom_filters,
),
credentials=test_creds,
)
)
outputs = {}
async for name, value in block.run(
FilteredWebhookBlock.Input(
credentials={ # type: ignore
"provider": "test_webhooks",
"id": "test-creds",
"type": "api_key",
},
resource="test_resource",
filters=custom_filters,
),
credentials=test_creds,
):
outputs[name] = value
assert "system events" in outputs["filter_summary"]
assert "2 severity levels" in outputs["filter_summary"]
@@ -335,7 +337,8 @@ class TestWebhookManagerIntegration:
assert managers["webhook_service_1"] == WebhookManager1
assert managers["webhook_service_2"] == WebhookManager2
def test_webhook_block_with_provider_manager(self):
@pytest.mark.asyncio
async def test_webhook_block_with_provider_manager(self):
"""Test webhook block using a provider's webhook manager."""
# Register provider with webhook manager
(
@@ -378,7 +381,7 @@ class TestWebhookManagerIntegration:
),
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
# Get the webhook manager for this provider
managers = AutoRegistry.get_webhook_managers()
manager_class = managers.get("integrated_webhooks")
@@ -398,19 +401,19 @@ class TestWebhookManagerIntegration:
title="Integrated Key",
)
outputs = dict(
block.run(
IntegratedWebhookBlock.Input(
credentials={ # type: ignore
"provider": "integrated_webhooks",
"id": "integrated-creds",
"type": "api_key",
},
target="test_target",
),
credentials=test_creds,
)
)
outputs = {}
async for name, value in block.run(
IntegratedWebhookBlock.Input(
credentials={ # type: ignore
"provider": "integrated_webhooks",
"id": "integrated-creds",
"type": "api_key",
},
target="test_target",
),
credentials=test_creds,
):
outputs[name] = value
assert outputs["status"] == "configured"
assert outputs["manager_type"] == "TestWebhooksManager"
@@ -419,7 +422,8 @@ class TestWebhookManagerIntegration:
class TestWebhookEventHandling:
"""Test webhook event handling in blocks."""
def test_webhook_event_processing_block(self):
@pytest.mark.asyncio
async def test_webhook_event_processing_block(self):
"""Test a block that processes webhook events."""
class WebhookEventBlock(Block):
@@ -447,7 +451,7 @@ class TestWebhookEventHandling:
output_schema=WebhookEventBlock.Output,
)
def run(self, input_data: Input, **kwargs) -> BlockOutput:
async def run(self, input_data: Input, **kwargs) -> BlockOutput:
# Process based on event type
event_type = input_data.event_type
payload = input_data.payload
@@ -473,28 +477,28 @@ class TestWebhookEventHandling:
block = WebhookEventBlock()
# Test created event
outputs = dict(
block.run(
WebhookEventBlock.Input(
event_type="created",
payload={"id": "123", "name": "Test Item"},
)
outputs = {}
async for name, value in block.run(
WebhookEventBlock.Input(
event_type="created",
payload={"id": "123", "name": "Test Item"},
)
)
):
outputs[name] = value
assert outputs["processed"] is True
assert "New item created: 123" in outputs["event_summary"]
assert outputs["action_required"] is True
# Test updated event
outputs = dict(
block.run(
WebhookEventBlock.Input(
event_type="updated",
payload={"id": "456", "changes": ["name", "status"]},
)
outputs = {}
async for name, value in block.run(
WebhookEventBlock.Input(
event_type="updated",
payload={"id": "456", "changes": ["name", "status"]},
)
)
):
outputs[name] = value
assert outputs["processed"] is True
assert "Item updated: 456" in outputs["event_summary"]