uipath 2.1.75__py3-none-any.whl → 2.1.76__py3-none-any.whl
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.
- uipath/_cli/_evals/_console_progress_reporter.py +36 -36
- uipath/_cli/_evals/_models/_exceptions.py +5 -0
- uipath/_cli/_evals/_runtime.py +51 -25
- uipath/_cli/cli_eval.py +20 -5
- uipath/_events/_events.py +16 -2
- uipath/_services/connections_service.py +218 -3
- uipath/_uipath.py +10 -1
- uipath/_utils/_infer_bindings.py +4 -2
- uipath/telemetry/_track.py +2 -2
- {uipath-2.1.75.dist-info → uipath-2.1.76.dist-info}/METADATA +1 -1
- {uipath-2.1.75.dist-info → uipath-2.1.76.dist-info}/RECORD +14 -13
- {uipath-2.1.75.dist-info → uipath-2.1.76.dist-info}/WHEEL +0 -0
- {uipath-2.1.75.dist-info → uipath-2.1.76.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.75.dist-info → uipath-2.1.76.dist-info}/licenses/LICENSE +0 -0
@@ -75,15 +75,10 @@ class ConsoleProgressReporter:
|
|
75
75
|
result.append(" - No evaluators", style="dim")
|
76
76
|
self.console.print(result)
|
77
77
|
|
78
|
-
def _extract_error_message(self,
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
if error_message:
|
83
|
-
return str(error_message) or "Execution failed"
|
84
|
-
return "Execution failed"
|
85
|
-
|
86
|
-
def _display_failed_evaluation(self, eval_name: str, error_msg: str) -> None:
|
78
|
+
def _extract_error_message(self, payload: EvalRunUpdatedEvent) -> str:
|
79
|
+
return str(payload.exception_details.exception) or "Execution failed" # type: ignore
|
80
|
+
|
81
|
+
def _display_failed_evaluation(self, eval_name: str) -> None:
|
87
82
|
"""Display results for a failed evaluation."""
|
88
83
|
from rich.text import Text
|
89
84
|
|
@@ -92,11 +87,6 @@ class ConsoleProgressReporter:
|
|
92
87
|
result.append(eval_name, style="bold white")
|
93
88
|
self.console.print(result)
|
94
89
|
|
95
|
-
error_text = Text()
|
96
|
-
error_text.append(" ", style="")
|
97
|
-
error_text.append(error_msg, style="red")
|
98
|
-
self.console.print(error_text)
|
99
|
-
|
100
90
|
def start_display(self):
|
101
91
|
"""Start the display."""
|
102
92
|
if not self.display_started:
|
@@ -122,37 +112,47 @@ class ConsoleProgressReporter:
|
|
122
112
|
except Exception as e:
|
123
113
|
logger.error(f"Failed to handle create eval run event: {e}")
|
124
114
|
|
115
|
+
def _display_logs_panel(self, eval_name: str, logs, error_msg: str = "") -> None:
|
116
|
+
"""Display execution logs panel with optional exception at the end."""
|
117
|
+
self.console.print(
|
118
|
+
Rule(
|
119
|
+
f"[dim italic]Execution Logs: {eval_name}[/dim italic]",
|
120
|
+
style="dim",
|
121
|
+
align="center",
|
122
|
+
)
|
123
|
+
)
|
124
|
+
|
125
|
+
if logs:
|
126
|
+
for record in logs:
|
127
|
+
self.console.print(f" [dim]{record.getMessage()}[/dim]")
|
128
|
+
elif not error_msg:
|
129
|
+
self.console.print(" [dim italic]No execution logs[/dim italic]")
|
130
|
+
|
131
|
+
if error_msg:
|
132
|
+
self.console.print(f" [red]{error_msg}[/red]")
|
133
|
+
|
134
|
+
self.console.print(Rule(style="dim"))
|
135
|
+
|
125
136
|
async def handle_update_eval_run(self, payload: EvalRunUpdatedEvent) -> None:
|
126
137
|
"""Handle evaluation run updates."""
|
127
138
|
try:
|
128
139
|
if payload.success:
|
129
|
-
# Store results for final display
|
130
140
|
self.eval_results_by_name[payload.eval_item.name] = payload.eval_results
|
131
141
|
self._display_successful_evaluation(
|
132
142
|
payload.eval_item.name, payload.eval_results
|
133
143
|
)
|
144
|
+
self._display_logs_panel(payload.eval_item.name, payload.logs)
|
134
145
|
else:
|
135
|
-
error_msg = self._extract_error_message(payload
|
136
|
-
self._display_failed_evaluation(payload.eval_item.name
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
)
|
146
|
-
)
|
147
|
-
|
148
|
-
if len(logs) > 0:
|
149
|
-
for record in logs:
|
150
|
-
log_line = f" [dim]{record.getMessage()}[/dim]"
|
151
|
-
self.console.print(log_line)
|
152
|
-
else:
|
153
|
-
self.console.print(" [dim italic]No execution logs[/dim italic]")
|
154
|
-
|
155
|
-
self.console.print(Rule(style="dim"))
|
146
|
+
error_msg = self._extract_error_message(payload)
|
147
|
+
self._display_failed_evaluation(payload.eval_item.name)
|
148
|
+
|
149
|
+
if payload.exception_details.runtime_exception: # type: ignore
|
150
|
+
self._display_logs_panel(
|
151
|
+
payload.eval_item.name, payload.logs, error_msg
|
152
|
+
)
|
153
|
+
else:
|
154
|
+
self.console.print(f" [red]{error_msg}[/red]")
|
155
|
+
self.console.print()
|
156
156
|
except Exception as e:
|
157
157
|
logger.error(f"Console reporter error: {e}")
|
158
158
|
|
uipath/_cli/_evals/_runtime.py
CHANGED
@@ -11,6 +11,7 @@ from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
|
11
11
|
|
12
12
|
from ..._events._event_bus import EventBus
|
13
13
|
from ..._events._events import (
|
14
|
+
EvalItemExceptionDetails,
|
14
15
|
EvalRunCreatedEvent,
|
15
16
|
EvalRunUpdatedEvent,
|
16
17
|
EvalSetRunCreatedEvent,
|
@@ -31,6 +32,7 @@ from .._runtime._logging import ExecutionLogHandler
|
|
31
32
|
from .._utils._eval_set import EvalHelpers
|
32
33
|
from ._evaluator_factory import EvaluatorFactory
|
33
34
|
from ._models._evaluation_set import EvaluationItem, EvaluationSet
|
35
|
+
from ._models._exceptions import EvaluationRuntimeException
|
34
36
|
from ._models._output import (
|
35
37
|
EvaluationResultDto,
|
36
38
|
EvaluationRunResult,
|
@@ -232,8 +234,7 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
232
234
|
wait_for_completion=False,
|
233
235
|
)
|
234
236
|
except Exception as e:
|
235
|
-
|
236
|
-
eval_item._error_message = error_msg # type: ignore[attr-defined]
|
237
|
+
exception_details = EvalItemExceptionDetails(exception=e)
|
237
238
|
|
238
239
|
for evaluator in evaluators:
|
239
240
|
evaluator_counts[evaluator.id] += 1
|
@@ -242,18 +243,28 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
242
243
|
0.0 - evaluator_averages[evaluator.id]
|
243
244
|
) / count
|
244
245
|
|
246
|
+
eval_run_updated_event = EvalRunUpdatedEvent(
|
247
|
+
execution_id=self.execution_id,
|
248
|
+
eval_item=eval_item,
|
249
|
+
eval_results=[],
|
250
|
+
success=False,
|
251
|
+
agent_output={},
|
252
|
+
agent_execution_time=0.0,
|
253
|
+
exception_details=exception_details,
|
254
|
+
spans=[],
|
255
|
+
logs=[],
|
256
|
+
)
|
257
|
+
if isinstance(e, EvaluationRuntimeException):
|
258
|
+
eval_run_updated_event.spans = e.spans
|
259
|
+
eval_run_updated_event.logs = e.logs
|
260
|
+
eval_run_updated_event.exception_details.exception = ( # type: ignore
|
261
|
+
e.root_exception
|
262
|
+
)
|
263
|
+
eval_run_updated_event.exception_details.runtime_exception = True # type: ignore
|
264
|
+
|
245
265
|
await event_bus.publish(
|
246
266
|
EvaluationEvents.UPDATE_EVAL_RUN,
|
247
|
-
|
248
|
-
execution_id=self.execution_id,
|
249
|
-
eval_item=eval_item,
|
250
|
-
eval_results=[],
|
251
|
-
success=False,
|
252
|
-
agent_output={},
|
253
|
-
agent_execution_time=0.0,
|
254
|
-
spans=[],
|
255
|
-
logs=[],
|
256
|
-
),
|
267
|
+
eval_run_updated_event,
|
257
268
|
wait_for_completion=False,
|
258
269
|
)
|
259
270
|
|
@@ -274,6 +285,17 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
274
285
|
)
|
275
286
|
return self.context.result
|
276
287
|
|
288
|
+
def _get_and_clear_execution_data(
|
289
|
+
self, execution_id: str
|
290
|
+
) -> tuple[List[ReadableSpan], list[logging.LogRecord]]:
|
291
|
+
spans = self.span_exporter.get_spans(execution_id)
|
292
|
+
self.span_exporter.clear(execution_id)
|
293
|
+
|
294
|
+
logs = self.logs_exporter.get_logs(execution_id)
|
295
|
+
self.logs_exporter.clear(execution_id)
|
296
|
+
|
297
|
+
return spans, logs
|
298
|
+
|
277
299
|
async def execute_runtime(
|
278
300
|
self, eval_item: EvaluationItem
|
279
301
|
) -> UiPathEvalRunExecutionOutput:
|
@@ -284,6 +306,9 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
284
306
|
is_eval_run=True,
|
285
307
|
log_handler=self._setup_execution_logging(eval_item_id),
|
286
308
|
)
|
309
|
+
if runtime_context.execution_id is None:
|
310
|
+
raise ValueError("execution_id must be set for eval runs")
|
311
|
+
|
287
312
|
attributes = {
|
288
313
|
"evalId": eval_item.id,
|
289
314
|
"span_type": "eval",
|
@@ -292,21 +317,22 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
292
317
|
attributes["execution.id"] = runtime_context.execution_id
|
293
318
|
|
294
319
|
start_time = time()
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
320
|
+
try:
|
321
|
+
result = await self.factory.execute_in_root_span(
|
322
|
+
runtime_context, root_span=eval_item.name, attributes=attributes
|
323
|
+
)
|
324
|
+
except Exception as e:
|
325
|
+
spans, logs = self._get_and_clear_execution_data(
|
326
|
+
runtime_context.execution_id
|
327
|
+
)
|
328
|
+
raise EvaluationRuntimeException(
|
329
|
+
spans=spans,
|
330
|
+
logs=logs,
|
331
|
+
root_exception=e,
|
332
|
+
) from e
|
299
333
|
|
300
334
|
end_time = time()
|
301
|
-
|
302
|
-
if runtime_context.execution_id is None:
|
303
|
-
raise ValueError("execution_id must be set for eval runs")
|
304
|
-
|
305
|
-
spans = self.span_exporter.get_spans(runtime_context.execution_id)
|
306
|
-
self.span_exporter.clear(runtime_context.execution_id)
|
307
|
-
|
308
|
-
logs = self.logs_exporter.get_logs(runtime_context.execution_id)
|
309
|
-
self.logs_exporter.clear(runtime_context.execution_id)
|
335
|
+
spans, logs = self._get_and_clear_execution_data(runtime_context.execution_id)
|
310
336
|
|
311
337
|
if result is None:
|
312
338
|
raise ValueError("Execution result cannot be None for eval runs")
|
uipath/_cli/cli_eval.py
CHANGED
@@ -17,6 +17,7 @@ from uipath._cli._runtime._contracts import (
|
|
17
17
|
UiPathRuntimeFactory,
|
18
18
|
)
|
19
19
|
from uipath._cli._runtime._runtime import UiPathScriptRuntime
|
20
|
+
from uipath._cli._utils._constants import UIPATH_PROJECT_ID
|
20
21
|
from uipath._cli._utils._folders import get_personal_workspace_key_async
|
21
22
|
from uipath._cli.middlewares import Middlewares
|
22
23
|
from uipath._events._event_bus import EventBus
|
@@ -39,6 +40,22 @@ class LiteralOption(click.Option):
|
|
39
40
|
raise click.BadParameter(value) from e
|
40
41
|
|
41
42
|
|
43
|
+
def setup_reporting_prereq(no_report: bool) -> bool:
|
44
|
+
if no_report:
|
45
|
+
return False
|
46
|
+
|
47
|
+
if not os.getenv(UIPATH_PROJECT_ID, False):
|
48
|
+
console.warning(
|
49
|
+
"UIPATH_PROJECT_ID environment variable not set. Results will no be reported to Studio Web."
|
50
|
+
)
|
51
|
+
return False
|
52
|
+
if not os.getenv("UIPATH_FOLDER_KEY"):
|
53
|
+
os.environ["UIPATH_FOLDER_KEY"] = asyncio.run(
|
54
|
+
get_personal_workspace_key_async()
|
55
|
+
)
|
56
|
+
return True
|
57
|
+
|
58
|
+
|
42
59
|
@click.command()
|
43
60
|
@click.argument("entrypoint", required=False)
|
44
61
|
@click.argument("eval_set", required=False)
|
@@ -79,10 +96,7 @@ def eval(
|
|
79
96
|
workers: Number of parallel workers for running evaluations
|
80
97
|
no_report: Do not report the evaluation results
|
81
98
|
"""
|
82
|
-
|
83
|
-
os.environ["UIPATH_FOLDER_KEY"] = asyncio.run(
|
84
|
-
get_personal_workspace_key_async()
|
85
|
-
)
|
99
|
+
should_register_progress_reporter = setup_reporting_prereq(no_report)
|
86
100
|
|
87
101
|
result = Middlewares.next(
|
88
102
|
"eval",
|
@@ -92,6 +106,7 @@ def eval(
|
|
92
106
|
no_report=no_report,
|
93
107
|
workers=workers,
|
94
108
|
execution_output_file=output_file,
|
109
|
+
register_progress_reporter=should_register_progress_reporter,
|
95
110
|
)
|
96
111
|
|
97
112
|
if result.error_message:
|
@@ -100,7 +115,7 @@ def eval(
|
|
100
115
|
if result.should_continue:
|
101
116
|
event_bus = EventBus()
|
102
117
|
|
103
|
-
if
|
118
|
+
if should_register_progress_reporter:
|
104
119
|
progress_reporter = StudioWebProgressReporter(LlmOpsHttpExporter())
|
105
120
|
asyncio.run(progress_reporter.subscribe_to_eval_runtime_events(event_bus))
|
106
121
|
|
uipath/_events/_events.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import enum
|
2
2
|
import logging
|
3
|
-
from typing import Any, List, Union
|
3
|
+
from typing import Any, List, Optional, Union
|
4
4
|
|
5
5
|
from opentelemetry.sdk.trace import ReadableSpan
|
6
|
-
from pydantic import BaseModel, ConfigDict
|
6
|
+
from pydantic import BaseModel, ConfigDict, model_validator
|
7
7
|
|
8
8
|
from uipath._cli._evals._models._evaluation_set import EvaluationItem
|
9
9
|
from uipath.eval.models import EvalItemResult
|
@@ -29,6 +29,13 @@ class EvalRunCreatedEvent(BaseModel):
|
|
29
29
|
eval_item: EvaluationItem
|
30
30
|
|
31
31
|
|
32
|
+
class EvalItemExceptionDetails(BaseModel):
|
33
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
34
|
+
|
35
|
+
runtime_exception: bool = False
|
36
|
+
exception: Exception
|
37
|
+
|
38
|
+
|
32
39
|
class EvalRunUpdatedEvent(BaseModel):
|
33
40
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
34
41
|
|
@@ -40,6 +47,13 @@ class EvalRunUpdatedEvent(BaseModel):
|
|
40
47
|
agent_execution_time: float
|
41
48
|
spans: List[ReadableSpan]
|
42
49
|
logs: List[logging.LogRecord]
|
50
|
+
exception_details: Optional[EvalItemExceptionDetails] = None
|
51
|
+
|
52
|
+
@model_validator(mode="after")
|
53
|
+
def validate_exception_details(self):
|
54
|
+
if not self.success and self.exception_details is None:
|
55
|
+
raise ValueError("exception_details must be provided when success is False")
|
56
|
+
return self
|
43
57
|
|
44
58
|
|
45
59
|
class EvalSetRunUpdatedEvent(BaseModel):
|
@@ -1,14 +1,17 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
|
-
from typing import Any, Dict
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
|
+
|
5
|
+
from httpx import Response
|
4
6
|
|
5
7
|
from .._config import Config
|
6
8
|
from .._execution_context import ExecutionContext
|
7
|
-
from .._utils import Endpoint, RequestSpec, infer_bindings
|
9
|
+
from .._utils import Endpoint, RequestSpec, header_folder, infer_bindings
|
8
10
|
from ..models import Connection, ConnectionToken, EventArguments
|
9
11
|
from ..models.connections import ConnectionTokenType
|
10
12
|
from ..tracing._traced import traced
|
11
13
|
from ._base_service import BaseService
|
14
|
+
from .folder_service import FolderService
|
12
15
|
|
13
16
|
logger: logging.Logger = logging.getLogger("uipath")
|
14
17
|
|
@@ -20,9 +23,16 @@ class ConnectionsService(BaseService):
|
|
20
23
|
and secure token management.
|
21
24
|
"""
|
22
25
|
|
23
|
-
def __init__(
|
26
|
+
def __init__(
|
27
|
+
self,
|
28
|
+
config: Config,
|
29
|
+
execution_context: ExecutionContext,
|
30
|
+
folders_service: FolderService,
|
31
|
+
) -> None:
|
24
32
|
super().__init__(config=config, execution_context=execution_context)
|
33
|
+
self._folders_service = folders_service
|
25
34
|
|
35
|
+
@infer_bindings(resource_type="connection", name="key")
|
26
36
|
@traced(
|
27
37
|
name="connections_retrieve",
|
28
38
|
run_type="uipath",
|
@@ -45,6 +55,117 @@ class ConnectionsService(BaseService):
|
|
45
55
|
response = self.request(spec.method, url=spec.endpoint)
|
46
56
|
return Connection.model_validate(response.json())
|
47
57
|
|
58
|
+
@traced(name="connections_list", run_type="uipath")
|
59
|
+
def list(
|
60
|
+
self,
|
61
|
+
*,
|
62
|
+
name: Optional[str] = None,
|
63
|
+
folder_path: Optional[str] = None,
|
64
|
+
folder_key: Optional[str] = None,
|
65
|
+
connector_key: Optional[str] = None,
|
66
|
+
skip: Optional[int] = None,
|
67
|
+
top: Optional[int] = None,
|
68
|
+
) -> List[Connection]:
|
69
|
+
"""Lists all connections with optional filtering.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
name: Optional connection name to filter (supports partial matching)
|
73
|
+
folder_path: Optional folder path for filtering connections
|
74
|
+
folder_key: Optional folder key (mutually exclusive with folder_path)
|
75
|
+
connector_key: Optional connector key to filter by specific connector type
|
76
|
+
skip: Number of records to skip (for pagination)
|
77
|
+
top: Maximum number of records to return
|
78
|
+
|
79
|
+
Returns:
|
80
|
+
List[Connection]: List of connection instances
|
81
|
+
|
82
|
+
Raises:
|
83
|
+
ValueError: If both folder_path and folder_key are provided together, or if
|
84
|
+
folder_path is provided but cannot be resolved to a folder_key
|
85
|
+
|
86
|
+
Examples:
|
87
|
+
>>> # List all connections
|
88
|
+
>>> connections = sdk.connections.list()
|
89
|
+
|
90
|
+
>>> # Find connections by name
|
91
|
+
>>> salesforce_conns = sdk.connections.list(name="Salesforce")
|
92
|
+
|
93
|
+
>>> # List all Slack connections in Finance folder
|
94
|
+
>>> connections = sdk.connections.list(
|
95
|
+
... folder_path="Finance",
|
96
|
+
... connector_key="uipath-slack"
|
97
|
+
... )
|
98
|
+
"""
|
99
|
+
spec = self._list_spec(
|
100
|
+
name=name,
|
101
|
+
folder_path=folder_path,
|
102
|
+
folder_key=folder_key,
|
103
|
+
connector_key=connector_key,
|
104
|
+
skip=skip,
|
105
|
+
top=top,
|
106
|
+
)
|
107
|
+
response = self.request(
|
108
|
+
spec.method, url=spec.endpoint, params=spec.params, headers=spec.headers
|
109
|
+
)
|
110
|
+
|
111
|
+
return self._parse_and_validate_list_response(response)
|
112
|
+
|
113
|
+
@traced(name="connections_list", run_type="uipath")
|
114
|
+
async def list_async(
|
115
|
+
self,
|
116
|
+
*,
|
117
|
+
name: Optional[str] = None,
|
118
|
+
folder_path: Optional[str] = None,
|
119
|
+
folder_key: Optional[str] = None,
|
120
|
+
connector_key: Optional[str] = None,
|
121
|
+
skip: Optional[int] = None,
|
122
|
+
top: Optional[int] = None,
|
123
|
+
) -> List[Connection]:
|
124
|
+
"""Asynchronously lists all connections with optional filtering.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
name: Optional connection name to filter (supports partial matching)
|
128
|
+
folder_path: Optional folder path for filtering connections
|
129
|
+
folder_key: Optional folder key (mutually exclusive with folder_path)
|
130
|
+
connector_key: Optional connector key to filter by specific connector type
|
131
|
+
skip: Number of records to skip (for pagination)
|
132
|
+
top: Maximum number of records to return
|
133
|
+
|
134
|
+
Returns:
|
135
|
+
List[Connection]: List of connection instances
|
136
|
+
|
137
|
+
Raises:
|
138
|
+
ValueError: If both folder_path and folder_key are provided together, or if
|
139
|
+
folder_path is provided but cannot be resolved to a folder_key
|
140
|
+
|
141
|
+
Examples:
|
142
|
+
>>> # List all connections
|
143
|
+
>>> connections = await sdk.connections.list_async()
|
144
|
+
|
145
|
+
>>> # Find connections by name
|
146
|
+
>>> salesforce_conns = await sdk.connections.list_async(name="Salesforce")
|
147
|
+
|
148
|
+
>>> # List all Slack connections in Finance folder
|
149
|
+
>>> connections = await sdk.connections.list_async(
|
150
|
+
... folder_path="Finance",
|
151
|
+
... connector_key="uipath-slack"
|
152
|
+
... )
|
153
|
+
"""
|
154
|
+
spec = self._list_spec(
|
155
|
+
name=name,
|
156
|
+
folder_path=folder_path,
|
157
|
+
folder_key=folder_key,
|
158
|
+
connector_key=connector_key,
|
159
|
+
skip=skip,
|
160
|
+
top=top,
|
161
|
+
)
|
162
|
+
response = await self.request_async(
|
163
|
+
spec.method, url=spec.endpoint, params=spec.params, headers=spec.headers
|
164
|
+
)
|
165
|
+
|
166
|
+
return self._parse_and_validate_list_response(response)
|
167
|
+
|
168
|
+
@infer_bindings(resource_type="connection", name="key")
|
48
169
|
@traced(
|
49
170
|
name="connections_retrieve",
|
50
171
|
run_type="uipath",
|
@@ -213,3 +334,97 @@ class ConnectionsService(BaseService):
|
|
213
334
|
endpoint=Endpoint(f"/connections_/api/v1/Connections/{key}/token"),
|
214
335
|
params={"tokenType": token_type.value},
|
215
336
|
)
|
337
|
+
|
338
|
+
def _parse_and_validate_list_response(self, response: Response) -> List[Connection]:
|
339
|
+
"""Parse and validate the list response from the API.
|
340
|
+
|
341
|
+
Handles both OData response format (with 'value' field) and raw list responses.
|
342
|
+
|
343
|
+
Args:
|
344
|
+
response: The HTTP response from the API
|
345
|
+
|
346
|
+
Returns:
|
347
|
+
List of validated Connection instances
|
348
|
+
"""
|
349
|
+
data = response.json()
|
350
|
+
|
351
|
+
# Handle both OData responses (dict with 'value') and raw list responses
|
352
|
+
if isinstance(data, dict):
|
353
|
+
connections_data = data.get("value", [])
|
354
|
+
elif isinstance(data, list):
|
355
|
+
connections_data = data
|
356
|
+
else:
|
357
|
+
connections_data = []
|
358
|
+
|
359
|
+
return [Connection.model_validate(conn) for conn in connections_data]
|
360
|
+
|
361
|
+
def _list_spec(
|
362
|
+
self,
|
363
|
+
name: Optional[str] = None,
|
364
|
+
folder_path: Optional[str] = None,
|
365
|
+
folder_key: Optional[str] = None,
|
366
|
+
connector_key: Optional[str] = None,
|
367
|
+
skip: Optional[int] = None,
|
368
|
+
top: Optional[int] = None,
|
369
|
+
) -> RequestSpec:
|
370
|
+
"""Build the request specification for listing connections.
|
371
|
+
|
372
|
+
Args:
|
373
|
+
name: Optional connection name to filter (supports partial matching)
|
374
|
+
folder_path: Optional folder path for filtering connections
|
375
|
+
folder_key: Optional folder key (mutually exclusive with folder_path)
|
376
|
+
connector_key: Optional connector key to filter by specific connector type
|
377
|
+
skip: Number of records to skip (for pagination)
|
378
|
+
top: Maximum number of records to return
|
379
|
+
|
380
|
+
Returns:
|
381
|
+
RequestSpec with endpoint, params, and headers configured
|
382
|
+
|
383
|
+
Raises:
|
384
|
+
ValueError: If both folder_path and folder_key are provided together, or if
|
385
|
+
folder_path is provided but cannot be resolved to a folder_key
|
386
|
+
"""
|
387
|
+
# Validate mutual exclusivity of folder_path and folder_key
|
388
|
+
if folder_path is not None and folder_key is not None:
|
389
|
+
raise ValueError(
|
390
|
+
"folder_path and folder_key are mutually exclusive and cannot be provided together"
|
391
|
+
)
|
392
|
+
|
393
|
+
# Resolve folder_path to folder_key if needed
|
394
|
+
resolved_folder_key = folder_key
|
395
|
+
if not resolved_folder_key and folder_path:
|
396
|
+
resolved_folder_key = self._folders_service.retrieve_key(
|
397
|
+
folder_path=folder_path
|
398
|
+
)
|
399
|
+
if not resolved_folder_key:
|
400
|
+
raise ValueError(f"Folder with path '{folder_path}' not found")
|
401
|
+
|
402
|
+
# Build OData filters
|
403
|
+
filters = []
|
404
|
+
if name:
|
405
|
+
# Escape single quotes in name for OData
|
406
|
+
escaped_name = name.replace("'", "''")
|
407
|
+
filters.append(f"contains(Name, '{escaped_name}')")
|
408
|
+
if connector_key:
|
409
|
+
filters.append(f"connector/key eq '{connector_key}'")
|
410
|
+
|
411
|
+
params = {}
|
412
|
+
if filters:
|
413
|
+
params["$filter"] = " and ".join(filters)
|
414
|
+
if skip is not None:
|
415
|
+
params["$skip"] = str(skip)
|
416
|
+
if top is not None:
|
417
|
+
params["$top"] = str(top)
|
418
|
+
|
419
|
+
# Always expand connector and folder for complete information
|
420
|
+
params["$expand"] = "connector,folder"
|
421
|
+
|
422
|
+
# Use header_folder which handles validation
|
423
|
+
headers = header_folder(resolved_folder_key, None)
|
424
|
+
|
425
|
+
return RequestSpec(
|
426
|
+
method="GET",
|
427
|
+
endpoint=Endpoint("/connections_/api/v1/Connections"),
|
428
|
+
params=params,
|
429
|
+
headers=headers,
|
430
|
+
)
|
uipath/_uipath.py
CHANGED
@@ -60,6 +60,7 @@ class UiPath:
|
|
60
60
|
self._folders_service: Optional[FolderService] = None
|
61
61
|
self._buckets_service: Optional[BucketsService] = None
|
62
62
|
self._attachments_service: Optional[AttachmentsService] = None
|
63
|
+
self._connections_service: Optional[ConnectionsService] = None
|
63
64
|
|
64
65
|
setup_logging(debug)
|
65
66
|
self._execution_context = ExecutionContext()
|
@@ -98,7 +99,15 @@ class UiPath:
|
|
98
99
|
|
99
100
|
@property
|
100
101
|
def connections(self) -> ConnectionsService:
|
101
|
-
|
102
|
+
if not self._connections_service:
|
103
|
+
if not self._folders_service:
|
104
|
+
self._folders_service = FolderService(
|
105
|
+
self._config, self._execution_context
|
106
|
+
)
|
107
|
+
self._connections_service = ConnectionsService(
|
108
|
+
self._config, self._execution_context, self._folders_service
|
109
|
+
)
|
110
|
+
return self._connections_service
|
102
111
|
|
103
112
|
@property
|
104
113
|
def context_grounding(self) -> ContextGroundingService:
|
uipath/_utils/_infer_bindings.py
CHANGED
@@ -28,8 +28,10 @@ def infer_bindings(
|
|
28
28
|
all_args.get(name), # type: ignore
|
29
29
|
all_args.get(folder_path, None),
|
30
30
|
) as (name_overwrite_or_default, folder_path_overwrite_or_default):
|
31
|
-
|
32
|
-
|
31
|
+
if name in sig.parameters:
|
32
|
+
all_args[name] = name_overwrite_or_default
|
33
|
+
if folder_path in sig.parameters:
|
34
|
+
all_args[folder_path] = folder_path_overwrite_or_default
|
33
35
|
|
34
36
|
return func(**all_args)
|
35
37
|
|
uipath/telemetry/_track.py
CHANGED
@@ -2,7 +2,7 @@ import json
|
|
2
2
|
import os
|
3
3
|
from functools import wraps
|
4
4
|
from importlib.metadata import version
|
5
|
-
from logging import
|
5
|
+
from logging import WARNING, LogRecord, getLogger
|
6
6
|
from typing import Any, Callable, Dict, Optional, Union
|
7
7
|
|
8
8
|
from azure.monitor.opentelemetry import configure_azure_monitor
|
@@ -102,7 +102,7 @@ class _TelemetryClient:
|
|
102
102
|
)
|
103
103
|
|
104
104
|
_logger.addHandler(_AzureMonitorOpenTelemetryEventHandler())
|
105
|
-
_logger.setLevel(
|
105
|
+
_logger.setLevel(WARNING)
|
106
106
|
|
107
107
|
_TelemetryClient._initialized = True
|
108
108
|
except Exception:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: uipath
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.76
|
4
4
|
Summary: Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools.
|
5
5
|
Project-URL: Homepage, https://uipath.com
|
6
6
|
Project-URL: Repository, https://github.com/UiPath/uipath-python
|
@@ -2,14 +2,14 @@ uipath/__init__.py,sha256=IaeKItOOQXMa95avueJ3dAq-XcRHyZVNjcCGwlSB000,634
|
|
2
2
|
uipath/_config.py,sha256=pi3qxPzDTxMEstj_XkGOgKJqD6RTHHv7vYv8sS_-d5Q,92
|
3
3
|
uipath/_execution_context.py,sha256=Qo8VMUFgtiL-40KsZrvul5bGv1CRERle_fCw1ORCggY,2374
|
4
4
|
uipath/_folder_context.py,sha256=D-bgxdwpwJP4b_QdVKcPODYh15kMDrOar2xNonmMSm4,1861
|
5
|
-
uipath/_uipath.py,sha256=
|
5
|
+
uipath/_uipath.py,sha256=xvBwczfjrvrB96ZK7wo0IgDcPDQWuEqu4dioH9CKd4k,5021
|
6
6
|
uipath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
uipath/_cli/README.md,sha256=GLtCfbeIKZKNnGTCsfSVqRQ27V1btT1i2bSAyW_xZl4,474
|
8
8
|
uipath/_cli/__init__.py,sha256=2RUgXYd8uJaYjA67xWb0w4IZuBmZoY8G1ccNmEQk9oM,2343
|
9
9
|
uipath/_cli/cli_auth.py,sha256=ZEA0Fwoo77Ez9ctpRAIq7sbAwj8F4OouAbMp1g1OvjM,2601
|
10
10
|
uipath/_cli/cli_deploy.py,sha256=KPCmQ0c_NYD5JofSDao5r6QYxHshVCRxlWDVnQvlp5w,645
|
11
11
|
uipath/_cli/cli_dev.py,sha256=nEfpjw1PZ72O6jmufYWVrueVwihFxDPOeJakdvNHdOA,2146
|
12
|
-
uipath/_cli/cli_eval.py,sha256=
|
12
|
+
uipath/_cli/cli_eval.py,sha256=Tg9mEf0T4qkp_YpcqJVxmPp69JkjHF68teX4CM061F0,5444
|
13
13
|
uipath/_cli/cli_init.py,sha256=Ac3-9tIH3rpikIX1ehWTo7InW5tjVNoz_w6fjvgLK4w,7052
|
14
14
|
uipath/_cli/cli_invoke.py,sha256=m-te-EjhDpk_fhFDkt-yQFzmjEHGo5lQDGEQWxSXisQ,4395
|
15
15
|
uipath/_cli/cli_new.py,sha256=9378NYUBc9j-qKVXV7oja-jahfJhXBg8zKVyaon7ctY,2102
|
@@ -44,13 +44,14 @@ uipath/_cli/_dev/_terminal/_styles/terminal.tcss,sha256=ktVpKwXIXw2VZp8KIZD6fO9i
|
|
44
44
|
uipath/_cli/_dev/_terminal/_utils/_chat.py,sha256=YUZxYVdmEManwHDuZsczJT1dWIYE1dVBgABlurwMFcE,8493
|
45
45
|
uipath/_cli/_dev/_terminal/_utils/_exporter.py,sha256=oI6D_eMwrh_2aqDYUh4GrJg8VLGrLYhDahR-_o0uJns,4144
|
46
46
|
uipath/_cli/_dev/_terminal/_utils/_logger.py,sha256=_ipTl_oAiMF9I7keGt2AAFAMz40DNLVMVkoiq-07UAU,2943
|
47
|
-
uipath/_cli/_evals/_console_progress_reporter.py,sha256=
|
47
|
+
uipath/_cli/_evals/_console_progress_reporter.py,sha256=HgB6pdMyoS6YVwuI3EpM2LBcH3U69nrdaTyNgPG8ssg,9304
|
48
48
|
uipath/_cli/_evals/_evaluator_factory.py,sha256=Gycv94VtGOpMir_Gba-UoiAyrSRfbSfe8_pTfjzcA9Q,3875
|
49
49
|
uipath/_cli/_evals/_progress_reporter.py,sha256=kX7rNSa-QCLXIzK-vb9Jjf-XLEtucdeiQPgPlSkpp2U,16778
|
50
|
-
uipath/_cli/_evals/_runtime.py,sha256=
|
50
|
+
uipath/_cli/_evals/_runtime.py,sha256=dz3mpZCLxwnLEdkwLo6W7qzBuVAklx6LMWtd4OMRk9w,15489
|
51
51
|
uipath/_cli/_evals/_models/_evaluation_set.py,sha256=XgPNLWciE4FgCYzZXV2kRYHzdtbc33FWSQmZQqVSdMk,4747
|
52
52
|
uipath/_cli/_evals/_models/_evaluator.py,sha256=fuC3UOYwPD4d_wdynHeLSCzbu82golNAnnPnxC8Y4rk,3315
|
53
53
|
uipath/_cli/_evals/_models/_evaluator_base_params.py,sha256=lTYKOV66tcjW85KHTyOdtF1p1VDaBNemrMAvH8bFIFc,382
|
54
|
+
uipath/_cli/_evals/_models/_exceptions.py,sha256=-oXLTDa4ab9Boa34ZxuUrCezf8ajIGrIEUVwZnmBASE,195
|
54
55
|
uipath/_cli/_evals/_models/_output.py,sha256=DmwFXh1YdLiMXyXmyoZr_4hgrrv3oiHbrrtIWMqGfsg,3145
|
55
56
|
uipath/_cli/_evals/_models/_sw_reporting.py,sha256=tSBLQFAdOIun8eP0vsqt56K6bmCZz_uMaWI3hskg_24,536
|
56
57
|
uipath/_cli/_evals/_models/_trajectory_span.py,sha256=8ukM8sB9rvzBMHfC_gnexAC3xlp4uMDevKZrRzcgrm4,3637
|
@@ -87,7 +88,7 @@ uipath/_cli/_utils/_tracing.py,sha256=2igb03j3EHjF_A406UhtCKkPfudVfFPjUq5tXUEG4o
|
|
87
88
|
uipath/_cli/_utils/_uv_helpers.py,sha256=6SvoLnZPoKIxW0sjMvD1-ENV_HOXDYzH34GjBqwT138,3450
|
88
89
|
uipath/_events/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
89
90
|
uipath/_events/_event_bus.py,sha256=4-VzstyX69cr7wT1EY7ywp-Ndyz2CyemD3Wk_-QmRpo,5496
|
90
|
-
uipath/_events/_events.py,sha256=
|
91
|
+
uipath/_events/_events.py,sha256=EzDfzpVm-EIH27Onad5mo8Go6-WB3S6_-6zZQ7qV58w,1811
|
91
92
|
uipath/_resources/AGENTS.md,sha256=YWhWuX9XIbyVhVT3PnPc4Of3_q6bsNJcuzYu3N8f_Ug,25850
|
92
93
|
uipath/_services/__init__.py,sha256=eYZElMfYDQTQU6MMjIke5J-GGT9pzLD5QfbwLiTQkEE,1037
|
93
94
|
uipath/_services/_base_service.py,sha256=x9-9jhPzn9Z16KRdFHhJNvV-FZHvTniMsDfxlS4Cutk,5782
|
@@ -96,7 +97,7 @@ uipath/_services/api_client.py,sha256=kGm04ijk9AOEQd2BMxvQg-2QoB8dmyoDwFFDPyutAG
|
|
96
97
|
uipath/_services/assets_service.py,sha256=pG0Io--SeiRRQmfUWPQPl1vq3csZlQgx30LBNKRmmF8,12145
|
97
98
|
uipath/_services/attachments_service.py,sha256=NPQYK7CGjfBaNT_1S5vEAfODmOChTbQZforllFM2ofU,26678
|
98
99
|
uipath/_services/buckets_service.py,sha256=5s8tuivd7GUZYj774DDUYTa0axxlUuesc4EBY1V5sdk,18496
|
99
|
-
uipath/_services/connections_service.py,sha256=
|
100
|
+
uipath/_services/connections_service.py,sha256=EbM4ywaJsvafPEhL5bLZDWLMOUK1UyDVLRc4vZgu3Fo,15905
|
100
101
|
uipath/_services/context_grounding_service.py,sha256=Pjx-QQQEiSKD-hY6ityj3QUSALN3fIcKLLHr_NZ0d_g,37117
|
101
102
|
uipath/_services/documents_service.py,sha256=UnFS8EpOZ_Ng2TZk3OiJJ3iNANvFs7QxuoG_v-lQj6c,24815
|
102
103
|
uipath/_services/entities_service.py,sha256=QKCLE6wRgq3HZraF-M2mljy-8il4vsNHrQhUgkewVVk,14028
|
@@ -107,7 +108,7 @@ uipath/_services/processes_service.py,sha256=O_uHgQ1rnwiV5quG0OQqabAnE6Rf6cWrMEN
|
|
107
108
|
uipath/_services/queues_service.py,sha256=VaG3dWL2QK6AJBOLoW2NQTpkPfZjsqsYPl9-kfXPFzA,13534
|
108
109
|
uipath/_utils/__init__.py,sha256=VdcpnENJIa0R6Y26NoxY64-wUVyvb4pKfTh1wXDQeMk,526
|
109
110
|
uipath/_utils/_endpoint.py,sha256=yYHwqbQuJIevpaTkdfYJS9CrtlFeEyfb5JQK5osTCog,2489
|
110
|
-
uipath/_utils/_infer_bindings.py,sha256=
|
111
|
+
uipath/_utils/_infer_bindings.py,sha256=eCxfUjd37fOFZ6vOfKl2BhWVUt7iSSJ-VQ0-nDTBcaA,1836
|
111
112
|
uipath/_utils/_logs.py,sha256=adfX_0UAn3YBeKJ8DQDeZs94rJyHGQO00uDfkaTpNWQ,510
|
112
113
|
uipath/_utils/_read_overwrites.py,sha256=OQgG9ycPpFnLub5ELQdX9V2Fyh6F9_zDR3xoYagJaMI,5287
|
113
114
|
uipath/_utils/_request_override.py,sha256=fIVHzgHVXITUlWcp8osNBwIafM1qm4_ejx0ng5UzfJ4,573
|
@@ -159,15 +160,15 @@ uipath/models/processes.py,sha256=bV31xTyF0hRWZmwy3bWj5L8dBD9wttWxfJjwzhjETmk,19
|
|
159
160
|
uipath/models/queues.py,sha256=gnbeEyYlHtdqdxBalio0lw8mq-78YBG9MPMSkv1BWOg,6934
|
160
161
|
uipath/telemetry/__init__.py,sha256=Wna32UFzZR66D-RzTKlPWlvji9i2HJb82NhHjCCXRjY,61
|
161
162
|
uipath/telemetry/_constants.py,sha256=uRDuEZayBYtBA0tMx-2AS_D-oiVA7oKgp9zid9jNats,763
|
162
|
-
uipath/telemetry/_track.py,sha256=
|
163
|
+
uipath/telemetry/_track.py,sha256=N7EMUJi8cnpZqlVL-B746MGvH1hk3urqWbV0T67UDB8,4660
|
163
164
|
uipath/tracing/__init__.py,sha256=GKRINyWdHVrDsI-8mrZDLdf0oey6GHGlNZTOADK-kgc,224
|
164
165
|
uipath/tracing/_otel_exporters.py,sha256=c0GKU_oUrAwrOrqbyu64c55z1TR6xk01d3y5fLUN1lU,3215
|
165
166
|
uipath/tracing/_traced.py,sha256=yBIY05PCCrYyx50EIHZnwJaKNdHPNx-YTR1sHQl0a98,19901
|
166
167
|
uipath/tracing/_utils.py,sha256=qd7N56tg6VXQ9pREh61esBgUWLNA0ssKsE0QlwrRWFM,11974
|
167
168
|
uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
|
168
169
|
uipath/utils/_endpoints_manager.py,sha256=iRTl5Q0XAm_YgcnMcJOXtj-8052sr6jpWuPNz6CgT0Q,8408
|
169
|
-
uipath-2.1.
|
170
|
-
uipath-2.1.
|
171
|
-
uipath-2.1.
|
172
|
-
uipath-2.1.
|
173
|
-
uipath-2.1.
|
170
|
+
uipath-2.1.76.dist-info/METADATA,sha256=zT48rJq2Cbsdva0uAbrjk7eNsLGxBiq2YTjp327fJg8,6593
|
171
|
+
uipath-2.1.76.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
172
|
+
uipath-2.1.76.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
|
173
|
+
uipath-2.1.76.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
|
174
|
+
uipath-2.1.76.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|