uipath-core 0.1.5__tar.gz → 0.1.7__tar.gz

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.
Files changed (59) hide show
  1. {uipath_core-0.1.5 → uipath_core-0.1.7}/.github/workflows/publish-dev.yml +16 -4
  2. {uipath_core-0.1.5 → uipath_core-0.1.7}/PKG-INFO +1 -1
  3. {uipath_core-0.1.5 → uipath_core-0.1.7}/pyproject.toml +1 -1
  4. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/guardrails/__init__.py +2 -0
  5. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/guardrails/_deterministic_guardrails_service.py +8 -5
  6. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/guardrails/_evaluators.py +6 -6
  7. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/guardrails/guardrails.py +12 -3
  8. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/tracing/decorators.py +14 -0
  9. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/guardrails/test_deterministic_guardrails_service.py +45 -32
  10. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/tracing/test_traced.py +158 -0
  11. {uipath_core-0.1.5 → uipath_core-0.1.7}/uv.lock +1 -1
  12. {uipath_core-0.1.5 → uipath_core-0.1.7}/.cursorrules +0 -0
  13. {uipath_core-0.1.5 → uipath_core-0.1.7}/.editorconfig +0 -0
  14. {uipath_core-0.1.5 → uipath_core-0.1.7}/.gitattributes +0 -0
  15. {uipath_core-0.1.5 → uipath_core-0.1.7}/.github/workflows/cd.yml +0 -0
  16. {uipath_core-0.1.5 → uipath_core-0.1.7}/.github/workflows/ci.yml +0 -0
  17. {uipath_core-0.1.5 → uipath_core-0.1.7}/.github/workflows/commitlint.yml +0 -0
  18. {uipath_core-0.1.5 → uipath_core-0.1.7}/.github/workflows/lint.yml +0 -0
  19. {uipath_core-0.1.5 → uipath_core-0.1.7}/.github/workflows/test.yml +0 -0
  20. {uipath_core-0.1.5 → uipath_core-0.1.7}/.gitignore +0 -0
  21. {uipath_core-0.1.5 → uipath_core-0.1.7}/.pre-commit-config.yaml +0 -0
  22. {uipath_core-0.1.5 → uipath_core-0.1.7}/.python-version +0 -0
  23. {uipath_core-0.1.5 → uipath_core-0.1.7}/.vscode/extensions.json +0 -0
  24. {uipath_core-0.1.5 → uipath_core-0.1.7}/.vscode/launch.json +0 -0
  25. {uipath_core-0.1.5 → uipath_core-0.1.7}/.vscode/settings.json +0 -0
  26. {uipath_core-0.1.5 → uipath_core-0.1.7}/CONTRIBUTING.md +0 -0
  27. {uipath_core-0.1.5 → uipath_core-0.1.7}/LICENSE +0 -0
  28. {uipath_core-0.1.5 → uipath_core-0.1.7}/README.md +0 -0
  29. {uipath_core-0.1.5 → uipath_core-0.1.7}/justfile +0 -0
  30. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/__init__.py +0 -0
  31. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/__init__.py +0 -0
  32. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/async_stream.py +0 -0
  33. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/citation.py +0 -0
  34. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/content.py +0 -0
  35. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/conversation.py +0 -0
  36. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/error.py +0 -0
  37. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/event.py +0 -0
  38. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/exchange.py +0 -0
  39. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/interrupt.py +0 -0
  40. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/message.py +0 -0
  41. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/meta.py +0 -0
  42. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/chat/tool.py +0 -0
  43. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/errors/__init__.py +0 -0
  44. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/errors/errors.py +0 -0
  45. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/py.typed +0 -0
  46. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/tracing/__init__.py +0 -0
  47. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/tracing/_utils.py +0 -0
  48. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/tracing/exporters.py +0 -0
  49. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/tracing/processors.py +0 -0
  50. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/tracing/span_utils.py +0 -0
  51. {uipath_core-0.1.5 → uipath_core-0.1.7}/src/uipath/core/tracing/trace_manager.py +0 -0
  52. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/__init__.py +0 -0
  53. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/conftest.py +0 -0
  54. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/tracing/test_external_integration.py +0 -0
  55. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/tracing/test_serialization.py +0 -0
  56. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/tracing/test_span_nesting.py +0 -0
  57. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/tracing/test_span_registry.py +0 -0
  58. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/tracing/test_trace_manager.py +0 -0
  59. {uipath_core-0.1.5 → uipath_core-0.1.7}/tests/tracing/test_tracing_utils.py +0 -0
@@ -60,9 +60,14 @@ jobs:
60
60
 
61
61
  Write-Output "Package version set to $DEV_VERSION"
62
62
 
63
+ $startMarker = "<!-- DEV_PACKAGE_START -->"
64
+ $endMarker = "<!-- DEV_PACKAGE_END -->"
65
+
63
66
  $dependencyMessage = @"
67
+ $startMarker
64
68
  ## Development Package
65
69
 
70
+ - Use ``uipath pack --nolock`` to get the latest dev build from this PR (requires version range).
66
71
  - Add this package as a dependency in your pyproject.toml:
67
72
 
68
73
  ``````toml
@@ -83,7 +88,13 @@ jobs:
83
88
 
84
89
  [tool.uv.sources]
85
90
  $PROJECT_NAME = { index = "testpypi" }
91
+
92
+ [tool.uv]
93
+ override-dependencies = [
94
+ "$PROJECT_NAME>=$MIN_VERSION,<$MAX_VERSION",
95
+ ]
86
96
  ``````
97
+ $endMarker
87
98
  "@
88
99
 
89
100
  # Get the owner and repo from the GitHub repository
@@ -101,10 +112,11 @@ jobs:
101
112
  $pr = Invoke-RestMethod -Uri $prUri -Method Get -Headers $headers
102
113
  $currentBody = $pr.body
103
114
 
104
- # Check if there's already a development package section
105
- if ($currentBody -match '## Development Package') {
106
- # Replace the existing section with the new dependency message
107
- $newBody = $currentBody -replace '## Development Package(\r?\n|.)*?(?=##|$)', $dependencyMessage
115
+ # Check if markers already exist in the PR description
116
+ $markerPattern = "(?s)$([regex]::Escape($startMarker)).*?$([regex]::Escape($endMarker))"
117
+ if ($currentBody -match $markerPattern) {
118
+ # Replace everything between markers (including markers)
119
+ $newBody = $currentBody -replace $markerPattern, $dependencyMessage
108
120
  } else {
109
121
  # Append the dependency message to the end of the description
110
122
  $newBody = if ($currentBody) { "$currentBody`n`n$dependencyMessage" } else { $dependencyMessage }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath-core
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: UiPath Core abstractions
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-core-python
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "uipath-core"
3
- version = "0.1.5"
3
+ version = "0.1.7"
4
4
  description = "UiPath Core abstractions"
5
5
  readme = { file = "README.md", content-type = "text/markdown" }
6
6
  requires-python = ">=3.11"
@@ -16,6 +16,7 @@ from .guardrails import (
16
16
  GuardrailScope,
17
17
  GuardrailSelector,
18
18
  GuardrailValidationResult,
19
+ GuardrailValidationResultType,
19
20
  NumberRule,
20
21
  Rule,
21
22
  SelectorType,
@@ -43,4 +44,5 @@ __all__ = [
43
44
  "GuardrailScope",
44
45
  "GuardrailSelector",
45
46
  "GuardrailValidationResult",
47
+ "GuardrailValidationResultType",
46
48
  ]
@@ -16,6 +16,7 @@ from .guardrails import (
16
16
  DeterministicGuardrail,
17
17
  FieldSource,
18
18
  GuardrailValidationResult,
19
+ GuardrailValidationResultType,
19
20
  NumberRule,
20
21
  SpecificFieldsSelector,
21
22
  UniversalRule,
@@ -38,7 +39,7 @@ class DeterministicGuardrailsService(BaseModel):
38
39
  # Output rules will be evaluated during post-execution
39
40
  if has_output_rule:
40
41
  return GuardrailValidationResult(
41
- validation_passed=True,
42
+ result=GuardrailValidationResultType.PASSED,
42
43
  reason="Guardrail contains output-dependent rules that will be evaluated during post-execution",
43
44
  )
44
45
  return self._evaluate_deterministic_guardrail(
@@ -64,7 +65,7 @@ class DeterministicGuardrailsService(BaseModel):
64
65
  # Only input rules exist and they should have been evaluated during pre-execution
65
66
  if not has_output_rule:
66
67
  return GuardrailValidationResult(
67
- validation_passed=True,
68
+ result=GuardrailValidationResultType.PASSED,
68
69
  reason="Guardrail contains only input-dependent rules that were evaluated during pre-execution",
69
70
  )
70
71
 
@@ -128,15 +129,17 @@ class DeterministicGuardrailsService(BaseModel):
128
129
  passed, reason = evaluate_universal_rule(rule, output_data)
129
130
  else:
130
131
  return GuardrailValidationResult(
131
- validation_passed=False,
132
+ result=GuardrailValidationResultType.VALIDATION_FAILED,
132
133
  reason=f"Unknown rule type: {type(rule)}",
133
134
  )
134
135
 
135
136
  if not passed:
136
137
  return GuardrailValidationResult(
137
- validation_passed=False, reason=reason or "Rule validation failed"
138
+ result=GuardrailValidationResultType.VALIDATION_FAILED,
139
+ reason=reason or "Rule validation failed",
138
140
  )
139
141
 
140
142
  return GuardrailValidationResult(
141
- validation_passed=True, reason="All deterministic guardrail rules passed"
143
+ result=GuardrailValidationResultType.PASSED,
144
+ reason="All deterministic guardrail rules passed",
142
145
  )
@@ -288,13 +288,13 @@ def evaluate_universal_rule(
288
288
 
289
289
  Universal rules trigger based on the apply_to scope and execution phase:
290
290
  - Pre-execution (empty output_data):
291
- - INPUT: triggers (validation_passed = False)
292
- - OUTPUT: does not trigger (validation_passed = True)
293
- - INPUT_AND_OUTPUT: triggers (validation_passed = False)
291
+ - INPUT: triggers (result = VALIDATION_FAILED)
292
+ - OUTPUT: does not trigger (result = PASSED)
293
+ - INPUT_AND_OUTPUT: triggers (result = VALIDATION_FAILED)
294
294
  - Post-execution (output_data has data):
295
- - INPUT: does not trigger (validation_passed = True)
296
- - OUTPUT: triggers (validation_passed = False)
297
- - INPUT_AND_OUTPUT: triggers (validation_passed = False)
295
+ - INPUT: does not trigger (result = PASSED)
296
+ - OUTPUT: triggers (result = VALIDATION_FAILED)
297
+ - INPUT_AND_OUTPUT: triggers (result = VALIDATION_FAILED)
298
298
  """
299
299
  # Determine if this is pre-execution (no output data) or post-execution
300
300
  is_pre_execution = not output_data or len(output_data) == 0
@@ -6,18 +6,27 @@ from typing import Annotated, Callable, Literal
6
6
  from pydantic import BaseModel, ConfigDict, Field
7
7
 
8
8
 
9
+ class GuardrailValidationResultType(str, Enum):
10
+ """Guardrail validation result type enumeration."""
11
+
12
+ PASSED = "passed"
13
+ VALIDATION_FAILED = "validation_failed"
14
+ ENTITLEMENTS_MISSING = "entitlements_missing"
15
+ FEATURE_DISABLED = "feature_disabled"
16
+
17
+
9
18
  class GuardrailValidationResult(BaseModel):
10
19
  """Result returned from validating input with a given guardrail.
11
20
 
12
21
  Attributes:
13
- validation_passed: Indicates whether the input data passed the guardrail validation.
22
+ result: The validation result type.
14
23
  reason: Textual explanation describing why the validation passed or failed.
15
24
  """
16
25
 
17
26
  model_config = ConfigDict(populate_by_name=True)
18
27
 
19
- validation_passed: bool = Field(
20
- alias="validation_passed", description="Whether the input passed validation."
28
+ result: GuardrailValidationResultType = Field(
29
+ alias="result", description="Validation result."
21
30
  )
22
31
  reason: str = Field(
23
32
  alias="reason", description="Explanation for the validation result."
@@ -6,7 +6,9 @@ import random
6
6
  from functools import wraps
7
7
  from typing import Any, Callable, Optional
8
8
 
9
+ from opentelemetry import context as context_api
9
10
  from opentelemetry import trace
11
+ from opentelemetry.context import _SUPPRESS_INSTRUMENTATION_KEY
10
12
  from opentelemetry.trace import NonRecordingSpan, SpanContext, TraceFlags
11
13
  from opentelemetry.trace.status import StatusCode
12
14
 
@@ -78,6 +80,8 @@ def _opentelemetry_traced(
78
80
  # --------- Sync wrapper ---------
79
81
  @wraps(func)
80
82
  def sync_wrapper(*args: Any, **kwargs: Any) -> Any:
83
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
84
+ return func(*args, **kwargs)
81
85
  span_cm, span = get_span()
82
86
  try:
83
87
  # Set input attributes BEFORE execution
@@ -113,6 +117,8 @@ def _opentelemetry_traced(
113
117
  # --------- Async wrapper ---------
114
118
  @wraps(func)
115
119
  async def async_wrapper(*args: Any, **kwargs: Any) -> Any:
120
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
121
+ return await func(*args, **kwargs)
116
122
  span_cm, span = get_span()
117
123
  try:
118
124
  # Set input attributes BEFORE execution
@@ -148,6 +154,10 @@ def _opentelemetry_traced(
148
154
  # --------- Generator wrapper ---------
149
155
  @wraps(func)
150
156
  def generator_wrapper(*args: Any, **kwargs: Any) -> Any:
157
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
158
+ for item in func(*args, **kwargs):
159
+ yield item
160
+ return
151
161
  span_cm, span = get_span()
152
162
  try:
153
163
  # Set input attributes BEFORE execution
@@ -186,6 +196,10 @@ def _opentelemetry_traced(
186
196
  # --------- Async generator wrapper ---------
187
197
  @wraps(func)
188
198
  async def async_generator_wrapper(*args: Any, **kwargs: Any) -> Any:
199
+ if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY):
200
+ async for item in func(*args, **kwargs):
201
+ yield item
202
+ return
189
203
  span_cm, span = get_span()
190
204
  try:
191
205
  # Set input attributes BEFORE execution
@@ -13,6 +13,7 @@ from uipath.core.guardrails import (
13
13
  FieldSource,
14
14
  GuardrailScope,
15
15
  GuardrailSelector,
16
+ GuardrailValidationResultType,
16
17
  NumberRule,
17
18
  SpecificFieldsSelector,
18
19
  UniversalRule,
@@ -79,7 +80,7 @@ class TestDeterministicGuardrailsService:
79
80
  guardrail=deterministic_guardrail,
80
81
  )
81
82
 
82
- assert result.validation_passed is True
83
+ assert result.result == GuardrailValidationResultType.PASSED
83
84
  assert (
84
85
  result.reason
85
86
  == "Guardrail contains only input-dependent rules that were evaluated during pre-execution"
@@ -145,7 +146,7 @@ class TestDeterministicGuardrailsService:
145
146
  guardrail=deterministic_guardrail,
146
147
  )
147
148
 
148
- assert result.validation_passed is False
149
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
149
150
  assert (
150
151
  result.reason
151
152
  == "Input data didn't match the guardrail condition: [age] comparing function [(n): n < 21.0]"
@@ -213,7 +214,7 @@ class TestDeterministicGuardrailsService:
213
214
  guardrail=deterministic_guardrail,
214
215
  )
215
216
 
216
- assert result.validation_passed is False
217
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
217
218
  assert (
218
219
  result.reason
219
220
  == "Input data didn't match the guardrail condition: [isActive] comparing function [(b): b is not True]"
@@ -259,7 +260,7 @@ class TestDeterministicGuardrailsService:
259
260
  guardrail=deterministic_guardrail,
260
261
  )
261
262
 
262
- assert result.validation_passed is True
263
+ assert result.result == GuardrailValidationResultType.PASSED
263
264
  assert (
264
265
  result.reason
265
266
  == "Guardrail contains only input-dependent rules that were evaluated during pre-execution"
@@ -317,7 +318,7 @@ class TestDeterministicGuardrailsService:
317
318
  guardrail=deterministic_guardrail,
318
319
  )
319
320
 
320
- assert result.validation_passed is False
321
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
321
322
  assert (
322
323
  result.reason
323
324
  == 'Input data didn\'t match the guardrail condition: [userName] comparing function [(s): not bool(re.search(".*te.*3.*", s))]'
@@ -363,7 +364,7 @@ class TestDeterministicGuardrailsService:
363
364
  guardrail=deterministic_guardrail,
364
365
  )
365
366
 
366
- assert result.validation_passed is True
367
+ assert result.result == GuardrailValidationResultType.PASSED
367
368
  assert (
368
369
  result.reason
369
370
  == "Guardrail contains only input-dependent rules that were evaluated during pre-execution"
@@ -421,7 +422,7 @@ class TestDeterministicGuardrailsService:
421
422
  guardrail=deterministic_guardrail,
422
423
  )
423
424
 
424
- assert result.validation_passed is False
425
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
425
426
 
426
427
  def test_evaluate_post_deterministic_guardrail_word_contains_substring_detects_violation(
427
428
  self,
@@ -475,7 +476,7 @@ class TestDeterministicGuardrailsService:
475
476
  guardrail=deterministic_guardrail,
476
477
  )
477
478
 
478
- assert result.validation_passed is False
479
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
479
480
  assert (
480
481
  result.reason
481
482
  == 'Input data didn\'t match the guardrail condition: [userName] comparing function [(s): "dre" in s]'
@@ -519,7 +520,7 @@ class TestDeterministicGuardrailsService:
519
520
  guardrail=deterministic_guardrail,
520
521
  )
521
522
 
522
- assert result.validation_passed is True
523
+ assert result.result == GuardrailValidationResultType.PASSED
523
524
  assert (
524
525
  result.reason
525
526
  == "Guardrail contains only input-dependent rules that were evaluated during pre-execution"
@@ -575,7 +576,7 @@ class TestDeterministicGuardrailsService:
575
576
  guardrail=deterministic_guardrail,
576
577
  )
577
578
 
578
- assert result.validation_passed is False
579
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
579
580
 
580
581
  def test_should_trigger_policy_pre_execution_only_some_rules_not_met_returns_false(
581
582
  self,
@@ -598,7 +599,7 @@ class TestDeterministicGuardrailsService:
598
599
  guardrail=guardrail,
599
600
  )
600
601
 
601
- assert result.validation_passed is False
602
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
602
603
 
603
604
  def test_should_ignore_post_execution_guardrail_for_pre_execution_returns_false(
604
605
  self,
@@ -620,7 +621,7 @@ class TestDeterministicGuardrailsService:
620
621
  )
621
622
 
622
623
  # Should fail because post-execution guardrail needs output data
623
- assert result.validation_passed is True
624
+ assert result.result == GuardrailValidationResultType.PASSED
624
625
 
625
626
  def test_should_trigger_policy_post_execution_guardrail_for_pre_execution_returns_false(
626
627
  self,
@@ -646,7 +647,7 @@ class TestDeterministicGuardrailsService:
646
647
  )
647
648
 
648
649
  # Pre-execution guardrail should still pass in post-execution
649
- assert result.validation_passed is True
650
+ assert result.result == GuardrailValidationResultType.PASSED
650
651
 
651
652
  def test_should_trigger_policy_post_execution_with_output_fields_all_conditions_met_returns_true(
652
653
  self,
@@ -671,7 +672,7 @@ class TestDeterministicGuardrailsService:
671
672
  guardrail=guardrail,
672
673
  )
673
674
 
674
- assert result.validation_passed is True
675
+ assert result.result == GuardrailValidationResultType.PASSED
675
676
 
676
677
  def test_should_trigger_policy_post_execution_with_output_fields_input_conditions_not_met_returns_false(
677
678
  self,
@@ -696,7 +697,7 @@ class TestDeterministicGuardrailsService:
696
697
  guardrail=guardrail,
697
698
  )
698
699
 
699
- assert result.validation_passed is False
700
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
700
701
 
701
702
  def test_should_trigger_policy_post_execution_with_output_fields_output_conditions_not_met_returns_false(
702
703
  self,
@@ -721,7 +722,7 @@ class TestDeterministicGuardrailsService:
721
722
  guardrail=guardrail,
722
723
  )
723
724
 
724
- assert result.validation_passed is False
725
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
725
726
 
726
727
  def test_should_trigger_policy_post_execution_multiple_rules_all_conditions_must_be_met_returns_true(
727
728
  self,
@@ -746,7 +747,7 @@ class TestDeterministicGuardrailsService:
746
747
  guardrail=guardrail,
747
748
  )
748
749
 
749
- assert result.validation_passed is True
750
+ assert result.result == GuardrailValidationResultType.PASSED
750
751
 
751
752
  def test_should_trigger_policy_post_execution_rule_with_multiple_conditions_all_must_be_met_returns_true(
752
753
  self,
@@ -771,7 +772,7 @@ class TestDeterministicGuardrailsService:
771
772
  guardrail=guardrail,
772
773
  )
773
774
 
774
- assert result.validation_passed is True
775
+ assert result.result == GuardrailValidationResultType.PASSED
775
776
 
776
777
  def test_should_trigger_policy_post_execution_rule_with_multiple_conditions_one_condition_not_met_returns_false(
777
778
  self,
@@ -796,7 +797,7 @@ class TestDeterministicGuardrailsService:
796
797
  guardrail=guardrail,
797
798
  )
798
799
 
799
- assert result.validation_passed is False
800
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
800
801
 
801
802
  def test_should_trigger_policy_post_execution_with_all_fields_selector_output_schema_has_fields_returns_true(
802
803
  self,
@@ -840,7 +841,7 @@ class TestDeterministicGuardrailsService:
840
841
  guardrail=guardrail,
841
842
  )
842
843
 
843
- assert result.validation_passed is True
844
+ assert result.result == GuardrailValidationResultType.PASSED
844
845
 
845
846
  def test_should_trigger_policy_post_execution_with_all_fields_selector_empty_output_schema_returns_true(
846
847
  self,
@@ -880,7 +881,7 @@ class TestDeterministicGuardrailsService:
880
881
  guardrail=guardrail,
881
882
  )
882
883
 
883
- assert result.validation_passed is True
884
+ assert result.result == GuardrailValidationResultType.PASSED
884
885
 
885
886
  def test_should_trigger_policy_pre_execution_always_rule_with_input_apply_to_returns_true(
886
887
  self,
@@ -899,7 +900,9 @@ class TestDeterministicGuardrailsService:
899
900
  guardrail=guardrail,
900
901
  )
901
902
 
902
- assert result.validation_passed is False # Should trigger
903
+ assert (
904
+ result.result == GuardrailValidationResultType.VALIDATION_FAILED
905
+ ) # Should trigger
903
906
 
904
907
  def test_should_trigger_policy_pre_execution_always_rule_with_output_apply_to_returns_false(
905
908
  self,
@@ -920,7 +923,9 @@ class TestDeterministicGuardrailsService:
920
923
  guardrail=guardrail,
921
924
  )
922
925
 
923
- assert result.validation_passed is True # Should not trigger
926
+ assert (
927
+ result.result == GuardrailValidationResultType.PASSED
928
+ ) # Should not trigger
924
929
 
925
930
  def test_should_trigger_policy_pre_execution_always_rule_with_input_and_output_apply_to_returns_true(
926
931
  self,
@@ -941,7 +946,9 @@ class TestDeterministicGuardrailsService:
941
946
  guardrail=guardrail,
942
947
  )
943
948
 
944
- assert result.validation_passed is False # Should trigger
949
+ assert (
950
+ result.result == GuardrailValidationResultType.VALIDATION_FAILED
951
+ ) # Should trigger
945
952
 
946
953
  def test_should_trigger_policy_post_execution_always_rule_with_input_apply_to_returns_false(
947
954
  self,
@@ -966,7 +973,9 @@ class TestDeterministicGuardrailsService:
966
973
  guardrail=guardrail,
967
974
  )
968
975
 
969
- assert result.validation_passed is True # Should not trigger
976
+ assert (
977
+ result.result == GuardrailValidationResultType.PASSED
978
+ ) # Should not trigger
970
979
 
971
980
  def test_should_trigger_policy_post_execution_always_rule_with_output_apply_to_returns_true(
972
981
  self,
@@ -991,7 +1000,9 @@ class TestDeterministicGuardrailsService:
991
1000
  guardrail=guardrail,
992
1001
  )
993
1002
 
994
- assert result.validation_passed is False # Should trigger
1003
+ assert (
1004
+ result.result == GuardrailValidationResultType.VALIDATION_FAILED
1005
+ ) # Should trigger
995
1006
 
996
1007
  def test_should_trigger_policy_post_execution_always_rule_with_input_and_output_apply_to_returns_true(
997
1008
  self,
@@ -1016,7 +1027,9 @@ class TestDeterministicGuardrailsService:
1016
1027
  guardrail=guardrail,
1017
1028
  )
1018
1029
 
1019
- assert result.validation_passed is False # Should trigger
1030
+ assert (
1031
+ result.result == GuardrailValidationResultType.VALIDATION_FAILED
1032
+ ) # Should trigger
1020
1033
 
1021
1034
  # Helper methods to create guardrails
1022
1035
 
@@ -1226,7 +1239,7 @@ class TestDeterministicGuardrailsService:
1226
1239
  guardrail=deterministic_guardrail,
1227
1240
  )
1228
1241
 
1229
- assert result.validation_passed is True
1242
+ assert result.result == GuardrailValidationResultType.PASSED
1230
1243
  assert (
1231
1244
  result.reason
1232
1245
  == "Guardrail contains only input-dependent rules that were evaluated during pre-execution"
@@ -1284,7 +1297,7 @@ class TestDeterministicGuardrailsService:
1284
1297
  guardrail=deterministic_guardrail,
1285
1298
  )
1286
1299
 
1287
- assert result.validation_passed is True
1300
+ assert result.result == GuardrailValidationResultType.PASSED
1288
1301
  assert result.reason == "All deterministic guardrail rules passed"
1289
1302
 
1290
1303
  def test_evaluate_post_deterministic_guardrail_only_always_rule_fails(
@@ -1322,7 +1335,7 @@ class TestDeterministicGuardrailsService:
1322
1335
  guardrail=deterministic_guardrail,
1323
1336
  )
1324
1337
 
1325
- assert result.validation_passed is False
1338
+ assert result.result == GuardrailValidationResultType.VALIDATION_FAILED
1326
1339
 
1327
1340
  def test_evaluate_post_deterministic_guardrail_only_input_rules_passes(
1328
1341
  self,
@@ -1370,7 +1383,7 @@ class TestDeterministicGuardrailsService:
1370
1383
  guardrail=deterministic_guardrail,
1371
1384
  )
1372
1385
 
1373
- assert result.validation_passed is True
1386
+ assert result.result == GuardrailValidationResultType.PASSED
1374
1387
  assert (
1375
1388
  result.reason
1376
1389
  == "Guardrail contains only input-dependent rules that were evaluated during pre-execution"
@@ -1434,7 +1447,7 @@ class TestDeterministicGuardrailsService:
1434
1447
  guardrail=deterministic_guardrail,
1435
1448
  )
1436
1449
 
1437
- assert result.validation_passed is True
1450
+ assert result.result == GuardrailValidationResultType.PASSED
1438
1451
 
1439
1452
  def _create_guardrail_with_always_rule(
1440
1453
  self, apply_to: ApplyTo
@@ -816,3 +816,161 @@ async def test_non_recording_traced_async_generator_function(setup_tracer):
816
816
  spans = exporter.get_exported_spans()
817
817
 
818
818
  assert len(spans) == 0
819
+
820
+
821
+ # --------- Suppress Instrumentation Tests ---------
822
+
823
+
824
+ def test_suppress_instrumentation_sync_function(setup_tracer):
825
+ """Test that suppress_instrumentation prevents spans from being created for sync functions."""
826
+ from opentelemetry.instrumentation.utils import suppress_instrumentation
827
+
828
+ exporter, provider = setup_tracer
829
+
830
+ @traced()
831
+ def sample_function(x, y):
832
+ return x + y
833
+
834
+ # Call without suppression - should create span
835
+ result = sample_function(2, 3)
836
+ assert result == 5
837
+
838
+ spans = exporter.get_exported_spans()
839
+ assert len(spans) == 1
840
+
841
+ exporter.clear_exported_spans()
842
+
843
+ # Call with suppression - should NOT create span
844
+ with suppress_instrumentation():
845
+ result = sample_function(4, 5)
846
+ assert result == 9
847
+
848
+ provider.shutdown()
849
+ spans = exporter.get_exported_spans()
850
+ assert len(spans) == 0
851
+
852
+
853
+ @pytest.mark.asyncio
854
+ async def test_suppress_instrumentation_async_function(setup_tracer):
855
+ """Test that suppress_instrumentation prevents spans from being created for async functions."""
856
+ from opentelemetry.instrumentation.utils import suppress_instrumentation
857
+
858
+ exporter, provider = setup_tracer
859
+
860
+ @traced()
861
+ async def sample_async_function(x, y):
862
+ return x * y
863
+
864
+ # Call without suppression - should create span
865
+ result = await sample_async_function(2, 3)
866
+ assert result == 6
867
+
868
+ await sleep(0.1)
869
+ spans = exporter.get_exported_spans()
870
+ assert len(spans) == 1
871
+
872
+ exporter.clear_exported_spans()
873
+
874
+ # Call with suppression - should NOT create span
875
+ with suppress_instrumentation():
876
+ result = await sample_async_function(4, 5)
877
+ assert result == 20
878
+
879
+ provider.shutdown()
880
+ await sleep(0.1)
881
+ spans = exporter.get_exported_spans()
882
+ assert len(spans) == 0
883
+
884
+
885
+ def test_suppress_instrumentation_generator_function(setup_tracer):
886
+ """Test that suppress_instrumentation prevents spans from being created for generator functions."""
887
+ from opentelemetry.instrumentation.utils import suppress_instrumentation
888
+
889
+ exporter, provider = setup_tracer
890
+
891
+ @traced()
892
+ def sample_generator_function(n):
893
+ for i in range(n):
894
+ yield i
895
+
896
+ # Call without suppression - should create span
897
+ results = list(sample_generator_function(3))
898
+ assert results == [0, 1, 2]
899
+
900
+ spans = exporter.get_exported_spans()
901
+ assert len(spans) == 1
902
+
903
+ exporter.clear_exported_spans()
904
+
905
+ # Call with suppression - should NOT create span
906
+ with suppress_instrumentation():
907
+ results = list(sample_generator_function(4))
908
+ assert results == [0, 1, 2, 3]
909
+
910
+ provider.shutdown()
911
+ spans = exporter.get_exported_spans()
912
+ assert len(spans) == 0
913
+
914
+
915
+ @pytest.mark.asyncio
916
+ async def test_suppress_instrumentation_async_generator_function(setup_tracer):
917
+ """Test that suppress_instrumentation prevents spans from being created for async generator functions."""
918
+ from opentelemetry.instrumentation.utils import suppress_instrumentation
919
+
920
+ exporter, provider = setup_tracer
921
+
922
+ @traced()
923
+ async def sample_async_generator_function(n):
924
+ for i in range(n):
925
+ yield i
926
+
927
+ # Call without suppression - should create span
928
+ results = [item async for item in sample_async_generator_function(3)]
929
+ assert results == [0, 1, 2]
930
+
931
+ spans = exporter.get_exported_spans()
932
+ assert len(spans) == 1
933
+
934
+ exporter.clear_exported_spans()
935
+
936
+ # Call with suppression - should NOT create span
937
+ with suppress_instrumentation():
938
+ results = [item async for item in sample_async_generator_function(4)]
939
+ assert results == [0, 1, 2, 3]
940
+
941
+ provider.shutdown()
942
+ spans = exporter.get_exported_spans()
943
+ assert len(spans) == 0
944
+
945
+
946
+ def test_suppress_instrumentation_nested_functions(setup_tracer):
947
+ """Test that suppress_instrumentation prevents spans for nested traced function calls."""
948
+ from opentelemetry.instrumentation.utils import suppress_instrumentation
949
+
950
+ exporter, provider = setup_tracer
951
+
952
+ @traced()
953
+ def inner_function(x):
954
+ return x * 2
955
+
956
+ @traced()
957
+ def outer_function(x):
958
+ return inner_function(x) + 1
959
+
960
+ # Call without suppression - should create 2 spans
961
+ result = outer_function(5)
962
+ assert result == 11
963
+
964
+ spans = exporter.get_exported_spans()
965
+ assert len(spans) == 2
966
+
967
+ exporter.clear_exported_spans()
968
+
969
+ # Call with suppression - should NOT create any spans
970
+ with suppress_instrumentation():
971
+ result = outer_function(10)
972
+ assert result == 21
973
+
974
+ provider.shutdown()
975
+ spans = exporter.get_exported_spans()
976
+ assert len(spans) == 0
@@ -991,7 +991,7 @@ wheels = [
991
991
 
992
992
  [[package]]
993
993
  name = "uipath-core"
994
- version = "0.1.5"
994
+ version = "0.1.7"
995
995
  source = { editable = "." }
996
996
  dependencies = [
997
997
  { name = "opentelemetry-instrumentation" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes