Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ wheels/

.cache/*
.cache

.claude
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath-core"
version = "0.3.1"
version = "0.3.2"
description = "UiPath Core abstractions"
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
Expand Down
8 changes: 8 additions & 0 deletions src/uipath/core/errors/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ class UiPathFaultedTriggerError(Exception):

category: ErrorCategory
message: str
detail: str

def __init__(self, category: ErrorCategory, message: str, detail: str = ""):
"""Initialize the UiPathFaultedTriggerError."""
self.category = category
self.message = message
self.detail = detail
super().__init__(f"{message}: {detail}" if detail else message)


class UiPathPendingTriggerError(UiPathFaultedTriggerError):
Expand Down
Empty file added tests/errors/__init__.py
Empty file.
65 changes: 65 additions & 0 deletions tests/errors/test_trigger_errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""Tests for UiPath trigger error classes."""

from uipath.core.errors import (
ErrorCategory,
UiPathFaultedTriggerError,
UiPathPendingTriggerError,
)


class TestUiPathFaultedTriggerError:
"""Test UiPathFaultedTriggerError constructor and behavior."""

def test_init_with_detail(self) -> None:
"""Test that category, message, and detail are stored and str includes both."""
err = UiPathFaultedTriggerError(
category=ErrorCategory.USER,
message="Something failed",
detail="missing input",
)
assert err.category == ErrorCategory.USER
assert err.message == "Something failed"
assert err.detail == "missing input"
assert str(err) == "Something failed: missing input"

def test_init_without_detail(self) -> None:
"""Test that detail defaults to empty string and str is just the message."""
err = UiPathFaultedTriggerError(
category=ErrorCategory.SYSTEM,
message="Internal error",
)
assert err.category == ErrorCategory.SYSTEM
assert err.message == "Internal error"
assert err.detail == ""
assert str(err) == "Internal error"

def test_is_exception(self) -> None:
"""Test that the error can be raised and caught as an Exception."""
with __import__("pytest").raises(UiPathFaultedTriggerError, match="boom"):
raise UiPathFaultedTriggerError(
category=ErrorCategory.DEPLOYMENT,
message="boom",
)


class TestUiPathPendingTriggerError:
"""Test UiPathPendingTriggerError inherits correctly."""

def test_inherits_faulted_trigger_error(self) -> None:
"""Test that PendingTriggerError is a subclass of FaultedTriggerError."""
err = UiPathPendingTriggerError(
category=ErrorCategory.UNKNOWN,
message="Pending",
detail="waiting for response",
)
assert isinstance(err, UiPathFaultedTriggerError)
assert err.category == ErrorCategory.UNKNOWN
assert str(err) == "Pending: waiting for response"

def test_catchable_as_faulted(self) -> None:
"""Test that PendingTriggerError can be caught as FaultedTriggerError."""
with __import__("pytest").raises(UiPathFaultedTriggerError):
raise UiPathPendingTriggerError(
category=ErrorCategory.USER,
message="still pending",
)
15 changes: 9 additions & 6 deletions tests/tracing/test_span_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ def test_filter_drops_non_matching_spans(self):
mock_exporter.export.return_value = SpanExportResult.SUCCESS

settings = UiPathTraceSettings(
span_filter=lambda span: span.attributes is not None
and span.attributes.get("keep") is True
span_filter=lambda span: (
span.attributes is not None and span.attributes.get("keep") is True
)
)
trace_manager = UiPathTraceManager()
trace_manager.add_span_exporter(mock_exporter, batch=False, settings=settings)
Expand Down Expand Up @@ -208,12 +209,14 @@ def test_different_filters_per_exporter(self):
mock_exporter_b.export.return_value = SpanExportResult.SUCCESS

settings_a = UiPathTraceSettings(
span_filter=lambda span: span.attributes is not None
and span.attributes.get("dest") == "a"
span_filter=lambda span: (
span.attributes is not None and span.attributes.get("dest") == "a"
)
)
settings_b = UiPathTraceSettings(
span_filter=lambda span: span.attributes is not None
and span.attributes.get("dest") == "b"
span_filter=lambda span: (
span.attributes is not None and span.attributes.get("dest") == "b"
)
)

trace_manager = UiPathTraceManager()
Expand Down
Loading