uipath 2.1.43__py3-none-any.whl → 2.1.45__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/_runtime.py +18 -53
- uipath/_cli/_runtime/_contracts.py +89 -36
- uipath/_cli/_runtime/_runtime.py +26 -259
- uipath/_cli/_runtime/_script_executor.py +254 -0
- uipath/_cli/cli_dev.py +4 -2
- uipath/_cli/cli_eval.py +27 -33
- uipath/_cli/cli_run.py +43 -140
- uipath/_services/processes_service.py +2 -2
- uipath/models/errors.py +2 -2
- {uipath-2.1.43.dist-info → uipath-2.1.45.dist-info}/METADATA +1 -1
- {uipath-2.1.43.dist-info → uipath-2.1.45.dist-info}/RECORD +14 -13
- {uipath-2.1.43.dist-info → uipath-2.1.45.dist-info}/WHEEL +0 -0
- {uipath-2.1.43.dist-info → uipath-2.1.45.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.43.dist-info → uipath-2.1.45.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,254 @@
|
|
1
|
+
"""Python script runtime implementation for executing and managing python scripts."""
|
2
|
+
|
3
|
+
import importlib.util
|
4
|
+
import inspect
|
5
|
+
import os
|
6
|
+
from dataclasses import asdict, is_dataclass
|
7
|
+
from typing import Any, Dict, Type, TypeVar, cast, get_type_hints
|
8
|
+
|
9
|
+
from pydantic import BaseModel
|
10
|
+
|
11
|
+
from ._contracts import (
|
12
|
+
UiPathErrorCategory,
|
13
|
+
UiPathRuntimeError,
|
14
|
+
)
|
15
|
+
|
16
|
+
T = TypeVar("T")
|
17
|
+
|
18
|
+
|
19
|
+
class ScriptExecutor:
|
20
|
+
def __init__(self, entrypoint: str):
|
21
|
+
self.entrypoint = entrypoint
|
22
|
+
self.validate_entrypoint()
|
23
|
+
|
24
|
+
async def __call__(self, input: Any) -> Any:
|
25
|
+
return await self._execute_python_script(input)
|
26
|
+
|
27
|
+
def validate_entrypoint(self) -> None:
|
28
|
+
"""Validate runtime inputs."""
|
29
|
+
if not self.entrypoint:
|
30
|
+
raise UiPathRuntimeError(
|
31
|
+
"ENTRYPOINT_MISSING",
|
32
|
+
"No entrypoint specified",
|
33
|
+
"Please provide a path to a Python script.",
|
34
|
+
UiPathErrorCategory.USER,
|
35
|
+
)
|
36
|
+
|
37
|
+
if not os.path.exists(self.entrypoint):
|
38
|
+
raise UiPathRuntimeError(
|
39
|
+
"ENTRYPOINT_NOT_FOUND",
|
40
|
+
"Script not found",
|
41
|
+
f"Script not found at path {self.entrypoint}.",
|
42
|
+
UiPathErrorCategory.USER,
|
43
|
+
)
|
44
|
+
|
45
|
+
async def _execute_python_script(self, input_data: Any) -> Any:
|
46
|
+
"""Execute the Python script with the given input."""
|
47
|
+
spec = importlib.util.spec_from_file_location("dynamic_module", self.entrypoint)
|
48
|
+
if not spec or not spec.loader:
|
49
|
+
raise UiPathRuntimeError(
|
50
|
+
"IMPORT_ERROR",
|
51
|
+
"Module import failed",
|
52
|
+
f"Could not load spec for {self.entrypoint}",
|
53
|
+
UiPathErrorCategory.USER,
|
54
|
+
)
|
55
|
+
|
56
|
+
module = importlib.util.module_from_spec(spec)
|
57
|
+
try:
|
58
|
+
spec.loader.exec_module(module)
|
59
|
+
except Exception as e:
|
60
|
+
raise UiPathRuntimeError(
|
61
|
+
"MODULE_EXECUTION_ERROR",
|
62
|
+
"Module execution failed",
|
63
|
+
f"Error executing module: {str(e)}",
|
64
|
+
UiPathErrorCategory.USER,
|
65
|
+
) from e
|
66
|
+
|
67
|
+
for func_name in ["main", "run", "execute"]:
|
68
|
+
if hasattr(module, func_name):
|
69
|
+
main_func = getattr(module, func_name)
|
70
|
+
sig = inspect.signature(main_func)
|
71
|
+
params = list(sig.parameters.values())
|
72
|
+
|
73
|
+
# Check if the function is asynchronous
|
74
|
+
is_async = inspect.iscoroutinefunction(main_func)
|
75
|
+
|
76
|
+
# Case 1: No parameters
|
77
|
+
if not params:
|
78
|
+
try:
|
79
|
+
result = await main_func() if is_async else main_func()
|
80
|
+
return (
|
81
|
+
self._convert_from_class(result)
|
82
|
+
if result is not None
|
83
|
+
else {}
|
84
|
+
)
|
85
|
+
except Exception as e:
|
86
|
+
raise UiPathRuntimeError(
|
87
|
+
"FUNCTION_EXECUTION_ERROR",
|
88
|
+
f"Error executing {func_name} function",
|
89
|
+
f"Error: {str(e)}",
|
90
|
+
UiPathErrorCategory.USER,
|
91
|
+
) from e
|
92
|
+
|
93
|
+
input_param = params[0]
|
94
|
+
input_type = input_param.annotation
|
95
|
+
|
96
|
+
# Case 2: Class, dataclass, or Pydantic model parameter
|
97
|
+
if input_type != inspect.Parameter.empty and (
|
98
|
+
is_dataclass(input_type)
|
99
|
+
or self._is_pydantic_model(input_type)
|
100
|
+
or hasattr(input_type, "__annotations__")
|
101
|
+
):
|
102
|
+
try:
|
103
|
+
valid_type = cast(Type[Any], input_type)
|
104
|
+
typed_input = self._convert_to_class(input_data, valid_type)
|
105
|
+
result = (
|
106
|
+
await main_func(typed_input)
|
107
|
+
if is_async
|
108
|
+
else main_func(typed_input)
|
109
|
+
)
|
110
|
+
return (
|
111
|
+
self._convert_from_class(result)
|
112
|
+
if result is not None
|
113
|
+
else {}
|
114
|
+
)
|
115
|
+
except Exception as e:
|
116
|
+
raise UiPathRuntimeError(
|
117
|
+
"FUNCTION_EXECUTION_ERROR",
|
118
|
+
f"Error executing {func_name} function with typed input",
|
119
|
+
f"Error: {str(e)}",
|
120
|
+
UiPathErrorCategory.USER,
|
121
|
+
) from e
|
122
|
+
|
123
|
+
# Case 3: Dict parameter
|
124
|
+
else:
|
125
|
+
try:
|
126
|
+
result = (
|
127
|
+
await main_func(input_data)
|
128
|
+
if is_async
|
129
|
+
else main_func(input_data)
|
130
|
+
)
|
131
|
+
return (
|
132
|
+
self._convert_from_class(result)
|
133
|
+
if result is not None
|
134
|
+
else {}
|
135
|
+
)
|
136
|
+
except Exception as e:
|
137
|
+
raise UiPathRuntimeError(
|
138
|
+
"FUNCTION_EXECUTION_ERROR",
|
139
|
+
f"Error executing {func_name} function with dictionary input",
|
140
|
+
f"Error: {str(e)}",
|
141
|
+
UiPathErrorCategory.USER,
|
142
|
+
) from e
|
143
|
+
|
144
|
+
raise UiPathRuntimeError(
|
145
|
+
"ENTRYPOINT_FUNCTION_MISSING",
|
146
|
+
"No entry function found",
|
147
|
+
f"No main function (main, run, or execute) found in {self.entrypoint}",
|
148
|
+
UiPathErrorCategory.USER,
|
149
|
+
)
|
150
|
+
|
151
|
+
def _convert_to_class(self, data: Dict[str, Any], cls: Type[T]) -> T:
|
152
|
+
"""Convert a dictionary to either a dataclass, Pydantic model, or regular class instance."""
|
153
|
+
# Handle Pydantic models
|
154
|
+
try:
|
155
|
+
if inspect.isclass(cls) and issubclass(cls, BaseModel):
|
156
|
+
return cls.model_validate(data)
|
157
|
+
except TypeError:
|
158
|
+
# issubclass can raise TypeError if cls is not a class
|
159
|
+
pass
|
160
|
+
|
161
|
+
# Handle dataclasses
|
162
|
+
if is_dataclass(cls):
|
163
|
+
field_types = get_type_hints(cls)
|
164
|
+
converted_data = {}
|
165
|
+
|
166
|
+
for field_name, field_type in field_types.items():
|
167
|
+
if field_name not in data:
|
168
|
+
continue
|
169
|
+
|
170
|
+
value = data[field_name]
|
171
|
+
if (
|
172
|
+
is_dataclass(field_type)
|
173
|
+
or self._is_pydantic_model(field_type)
|
174
|
+
or hasattr(field_type, "__annotations__")
|
175
|
+
) and isinstance(value, dict):
|
176
|
+
typed_field = cast(Type[Any], field_type)
|
177
|
+
value = self._convert_to_class(value, typed_field)
|
178
|
+
converted_data[field_name] = value
|
179
|
+
|
180
|
+
return cls(**converted_data)
|
181
|
+
|
182
|
+
# Handle regular classes
|
183
|
+
else:
|
184
|
+
sig = inspect.signature(cls.__init__)
|
185
|
+
params = sig.parameters
|
186
|
+
|
187
|
+
init_args = {}
|
188
|
+
|
189
|
+
for param_name, param in params.items():
|
190
|
+
if param_name == "self":
|
191
|
+
continue
|
192
|
+
|
193
|
+
if param_name in data:
|
194
|
+
value = data[param_name]
|
195
|
+
param_type = (
|
196
|
+
param.annotation
|
197
|
+
if param.annotation != inspect.Parameter.empty
|
198
|
+
else Any
|
199
|
+
)
|
200
|
+
|
201
|
+
if (
|
202
|
+
is_dataclass(param_type)
|
203
|
+
or self._is_pydantic_model(param_type)
|
204
|
+
or hasattr(param_type, "__annotations__")
|
205
|
+
) and isinstance(value, dict):
|
206
|
+
typed_param = cast(Type[Any], param_type)
|
207
|
+
value = self._convert_to_class(value, typed_param)
|
208
|
+
|
209
|
+
init_args[param_name] = value
|
210
|
+
elif param.default != inspect.Parameter.empty:
|
211
|
+
init_args[param_name] = param.default
|
212
|
+
|
213
|
+
return cls(**init_args)
|
214
|
+
|
215
|
+
def _is_pydantic_model(self, cls: Type[Any]) -> bool:
|
216
|
+
"""Safely check if a class is a Pydantic model."""
|
217
|
+
try:
|
218
|
+
return inspect.isclass(cls) and issubclass(cls, BaseModel)
|
219
|
+
except TypeError:
|
220
|
+
# issubclass can raise TypeError if cls is not a class
|
221
|
+
return False
|
222
|
+
|
223
|
+
def _convert_from_class(self, obj: Any) -> Dict[str, Any]:
|
224
|
+
"""Convert a class instance (dataclass, Pydantic model, or regular) to a dictionary."""
|
225
|
+
if obj is None:
|
226
|
+
return {}
|
227
|
+
|
228
|
+
# Handle Pydantic models
|
229
|
+
if isinstance(obj, BaseModel):
|
230
|
+
return obj.model_dump()
|
231
|
+
|
232
|
+
# Handle dataclasses
|
233
|
+
elif is_dataclass(obj):
|
234
|
+
# Make sure obj is an instance, not a class
|
235
|
+
if isinstance(obj, type):
|
236
|
+
return {}
|
237
|
+
return asdict(obj)
|
238
|
+
|
239
|
+
# Handle regular classes
|
240
|
+
elif hasattr(obj, "__dict__"):
|
241
|
+
result = {}
|
242
|
+
for key, value in obj.__dict__.items():
|
243
|
+
# Skip private attributes
|
244
|
+
if not key.startswith("_"):
|
245
|
+
if (
|
246
|
+
isinstance(value, BaseModel)
|
247
|
+
or hasattr(value, "__dict__")
|
248
|
+
or is_dataclass(value)
|
249
|
+
):
|
250
|
+
result[key] = self._convert_from_class(value)
|
251
|
+
else:
|
252
|
+
result[key] = value
|
253
|
+
return result
|
254
|
+
return {} if obj is None else {str(type(obj).__name__): str(obj)} # Fallback
|
uipath/_cli/cli_dev.py
CHANGED
@@ -6,7 +6,7 @@ import click
|
|
6
6
|
|
7
7
|
from uipath._cli._dev._terminal import UiPathDevTerminal
|
8
8
|
from uipath._cli._runtime._contracts import UiPathRuntimeContext, UiPathRuntimeFactory
|
9
|
-
from uipath._cli._runtime._runtime import
|
9
|
+
from uipath._cli._runtime._runtime import UiPathScriptRuntime
|
10
10
|
from uipath._cli._utils._console import ConsoleLogger
|
11
11
|
from uipath._cli._utils._debug import setup_debugging
|
12
12
|
from uipath._cli.cli_init import init # type: ignore[attr-defined]
|
@@ -53,7 +53,9 @@ def dev(interface: Optional[str], debug: bool, debug_port: int) -> None:
|
|
53
53
|
|
54
54
|
try:
|
55
55
|
if interface == "terminal":
|
56
|
-
runtime_factory = UiPathRuntimeFactory(
|
56
|
+
runtime_factory = UiPathRuntimeFactory(
|
57
|
+
UiPathScriptRuntime, UiPathRuntimeContext
|
58
|
+
)
|
57
59
|
app = UiPathDevTerminal(runtime_factory)
|
58
60
|
asyncio.run(app.run_async())
|
59
61
|
else:
|
uipath/_cli/cli_eval.py
CHANGED
@@ -10,15 +10,16 @@ import click
|
|
10
10
|
from uipath._cli._evals._runtime import UiPathEvalContext, UiPathEvalRuntime
|
11
11
|
from uipath._cli._runtime._contracts import (
|
12
12
|
UiPathRuntimeContext,
|
13
|
-
UiPathRuntimeContextBuilder,
|
14
13
|
UiPathRuntimeFactory,
|
15
14
|
)
|
16
|
-
from uipath._cli._runtime._runtime import
|
15
|
+
from uipath._cli._runtime._runtime import UiPathScriptRuntime
|
17
16
|
from uipath._cli.middlewares import MiddlewareResult, Middlewares
|
17
|
+
from uipath.eval._helpers import auto_discover_entrypoint
|
18
18
|
|
19
19
|
from .._utils.constants import ENV_JOB_ID
|
20
20
|
from ..telemetry import track
|
21
21
|
from ._utils._console import ConsoleLogger
|
22
|
+
from ._utils._eval_set import EvalHelpers
|
22
23
|
|
23
24
|
console = ConsoleLogger()
|
24
25
|
|
@@ -39,42 +40,35 @@ def eval_agent_middleware(
|
|
39
40
|
no_report: bool = False,
|
40
41
|
**kwargs,
|
41
42
|
) -> MiddlewareResult:
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
**kwargs,
|
61
|
-
**base_context.model_dump(),
|
62
|
-
)
|
43
|
+
"""Middleware to run an evaluation set against the agent."""
|
44
|
+
timestamp = datetime.now(timezone.utc).strftime("%M-%H-%d-%m-%Y")
|
45
|
+
|
46
|
+
eval_context = UiPathEvalContext.with_defaults()
|
47
|
+
eval_context.no_report = no_report
|
48
|
+
eval_context.workers = workers
|
49
|
+
eval_context.eval_set = eval_set or EvalHelpers.auto_discover_eval_set()
|
50
|
+
eval_context.eval_ids = eval_ids
|
51
|
+
eval_context.execution_output_file = (
|
52
|
+
f"evals/results/{timestamp}.json" if not os.getenv("UIPATH_JOB_KEY") else None
|
53
|
+
)
|
54
|
+
|
55
|
+
runtime_entrypoint = entrypoint or auto_discover_entrypoint()
|
56
|
+
|
57
|
+
def generate_runtime_context(**context_kwargs) -> UiPathRuntimeContext:
|
58
|
+
runtime_context = UiPathRuntimeContext.with_defaults(**context_kwargs)
|
59
|
+
runtime_context.entrypoint = runtime_entrypoint
|
60
|
+
return runtime_context
|
63
61
|
|
64
62
|
try:
|
65
|
-
runtime_factory = UiPathRuntimeFactory(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
.with_entrypoint(entrypoint)
|
70
|
-
.with_entrypoint(entrypoint)
|
71
|
-
.mark_eval_run()
|
72
|
-
.build()
|
63
|
+
runtime_factory = UiPathRuntimeFactory(
|
64
|
+
UiPathScriptRuntime,
|
65
|
+
UiPathRuntimeContext,
|
66
|
+
context_generator=generate_runtime_context,
|
73
67
|
)
|
74
68
|
|
75
69
|
async def execute():
|
76
|
-
async with UiPathEvalRuntime.
|
77
|
-
factory=runtime_factory, context=
|
70
|
+
async with UiPathEvalRuntime.from_eval_context(
|
71
|
+
factory=runtime_factory, context=eval_context
|
78
72
|
) as eval_runtime:
|
79
73
|
await eval_runtime.execute()
|
80
74
|
|
uipath/_cli/cli_run.py
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# type: ignore
|
2
2
|
import asyncio
|
3
3
|
import os
|
4
|
-
import traceback
|
5
4
|
from os import environ as env
|
6
|
-
from typing import Optional
|
5
|
+
from typing import Optional
|
7
6
|
|
8
7
|
import click
|
9
8
|
|
@@ -15,138 +14,16 @@ from .._utils.constants import (
|
|
15
14
|
from ..telemetry import track
|
16
15
|
from ._runtime._contracts import (
|
17
16
|
UiPathRuntimeContext,
|
18
|
-
UiPathRuntimeContextBuilder,
|
19
17
|
UiPathRuntimeError,
|
20
18
|
UiPathRuntimeFactory,
|
21
19
|
)
|
22
|
-
from ._runtime._runtime import
|
20
|
+
from ._runtime._runtime import UiPathScriptRuntime
|
23
21
|
from ._utils._console import ConsoleLogger
|
24
|
-
from .middlewares import
|
22
|
+
from .middlewares import Middlewares
|
25
23
|
|
26
24
|
console = ConsoleLogger()
|
27
25
|
|
28
26
|
|
29
|
-
def python_run_middleware(
|
30
|
-
entrypoint: Optional[str],
|
31
|
-
input: Optional[str],
|
32
|
-
resume: bool,
|
33
|
-
**kwargs,
|
34
|
-
) -> MiddlewareResult:
|
35
|
-
"""Middleware to handle Python script execution.
|
36
|
-
|
37
|
-
Args:
|
38
|
-
entrypoint: Path to the Python script to execute
|
39
|
-
input: JSON string with input data
|
40
|
-
resume: Flag indicating if this is a resume execution
|
41
|
-
debug: Enable debugging with debugpy
|
42
|
-
debug_port: Port for debug server (default: 5678)
|
43
|
-
|
44
|
-
Returns:
|
45
|
-
MiddlewareResult with execution status and messages
|
46
|
-
"""
|
47
|
-
if not entrypoint:
|
48
|
-
return MiddlewareResult(
|
49
|
-
should_continue=False,
|
50
|
-
error_message="""No entrypoint specified. Please provide a path to a Python script.
|
51
|
-
Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""",
|
52
|
-
)
|
53
|
-
|
54
|
-
if not os.path.exists(entrypoint):
|
55
|
-
return MiddlewareResult(
|
56
|
-
should_continue=False,
|
57
|
-
error_message=f"""Script not found at path {entrypoint}.
|
58
|
-
Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""",
|
59
|
-
)
|
60
|
-
|
61
|
-
try:
|
62
|
-
runtime_factory = UiPathRuntimeFactory(UiPathRuntime, UiPathRuntimeContext)
|
63
|
-
context = (
|
64
|
-
UiPathRuntimeContextBuilder()
|
65
|
-
.with_defaults(**kwargs)
|
66
|
-
.with_entrypoint(entrypoint)
|
67
|
-
.with_input(input)
|
68
|
-
.with_resume(resume)
|
69
|
-
.build()
|
70
|
-
)
|
71
|
-
|
72
|
-
asyncio.run(runtime_factory.execute(context))
|
73
|
-
|
74
|
-
return MiddlewareResult(should_continue=False)
|
75
|
-
|
76
|
-
except UiPathRuntimeError as e:
|
77
|
-
return MiddlewareResult(
|
78
|
-
should_continue=False,
|
79
|
-
error_message=f"Error: {e.error_info.title} - {e.error_info.detail}",
|
80
|
-
should_include_stacktrace=False,
|
81
|
-
)
|
82
|
-
except Exception as e:
|
83
|
-
# Handle unexpected errors
|
84
|
-
return MiddlewareResult(
|
85
|
-
should_continue=False,
|
86
|
-
error_message=f"Error: Unexpected error occurred - {str(e)}",
|
87
|
-
should_include_stacktrace=True,
|
88
|
-
)
|
89
|
-
|
90
|
-
|
91
|
-
def run_core(
|
92
|
-
entrypoint: Optional[str],
|
93
|
-
resume: bool,
|
94
|
-
input: Optional[str] = None,
|
95
|
-
input_file: Optional[str] = None,
|
96
|
-
execution_output_file: Optional[str] = None,
|
97
|
-
logs_file: Optional[str] = None,
|
98
|
-
**kwargs,
|
99
|
-
) -> Tuple[bool, Optional[str], Optional[str]]:
|
100
|
-
"""Core execution logic that can be called programmatically.
|
101
|
-
|
102
|
-
Args:
|
103
|
-
entrypoint: Path to the Python script to execute
|
104
|
-
input: JSON string with input data
|
105
|
-
resume: Flag indicating if this is a resume execution
|
106
|
-
input_file: Path to input JSON file
|
107
|
-
execution_output_file: Path to execution output file
|
108
|
-
logs_file: Path where execution output will be written
|
109
|
-
**kwargs: Additional arguments to be forwarded to the middleware
|
110
|
-
|
111
|
-
Returns:
|
112
|
-
Tuple containing:
|
113
|
-
- success: True if execution was successful
|
114
|
-
- error_message: Error message if any
|
115
|
-
- info_message: Info message if any
|
116
|
-
"""
|
117
|
-
# Process through middleware chain
|
118
|
-
result = Middlewares.next(
|
119
|
-
"run",
|
120
|
-
entrypoint,
|
121
|
-
input,
|
122
|
-
resume,
|
123
|
-
input_file=input_file,
|
124
|
-
execution_output_file=execution_output_file,
|
125
|
-
logs_file=logs_file,
|
126
|
-
**kwargs,
|
127
|
-
)
|
128
|
-
|
129
|
-
if result.should_continue:
|
130
|
-
result = python_run_middleware(
|
131
|
-
entrypoint=entrypoint,
|
132
|
-
input=input,
|
133
|
-
resume=resume,
|
134
|
-
input_file=input_file,
|
135
|
-
execution_output_file=execution_output_file,
|
136
|
-
logs_file=logs_file,
|
137
|
-
**kwargs,
|
138
|
-
)
|
139
|
-
|
140
|
-
if result.should_continue:
|
141
|
-
return False, "Could not process the request with any available handler.", None
|
142
|
-
|
143
|
-
return (
|
144
|
-
not bool(result.error_message),
|
145
|
-
result.error_message,
|
146
|
-
result.info_message,
|
147
|
-
)
|
148
|
-
|
149
|
-
|
150
27
|
@click.command()
|
151
28
|
@click.argument("entrypoint", required=False)
|
152
29
|
@click.argument("input", required=False, default="{}")
|
@@ -198,27 +75,53 @@ def run(
|
|
198
75
|
if not setup_debugging(debug, debug_port):
|
199
76
|
console.error(f"Failed to start debug server on port {debug_port}")
|
200
77
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
78
|
+
result = Middlewares.next(
|
79
|
+
"run",
|
80
|
+
entrypoint,
|
81
|
+
input,
|
82
|
+
resume,
|
205
83
|
input_file=input_file,
|
206
84
|
execution_output_file=output_file,
|
207
85
|
debug=debug,
|
208
86
|
debug_port=debug_port,
|
209
87
|
)
|
210
88
|
|
211
|
-
if error_message:
|
212
|
-
console.error(error_message
|
213
|
-
if not success: # If there was an error and execution failed
|
214
|
-
console.error(traceback.format_exc())
|
215
|
-
click.get_current_context().exit(1)
|
216
|
-
|
217
|
-
if info_message:
|
218
|
-
console.info(info_message)
|
89
|
+
if result.error_message:
|
90
|
+
console.error(result.error_message)
|
219
91
|
|
220
|
-
if
|
221
|
-
|
92
|
+
if result.should_continue:
|
93
|
+
if not entrypoint:
|
94
|
+
console.error("""No entrypoint specified. Please provide a path to a Python script.
|
95
|
+
Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""")
|
96
|
+
|
97
|
+
if not os.path.exists(entrypoint):
|
98
|
+
console.error(f"""Script not found at path {entrypoint}.
|
99
|
+
Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""")
|
100
|
+
|
101
|
+
try:
|
102
|
+
runtime_factory = UiPathRuntimeFactory(
|
103
|
+
UiPathScriptRuntime, UiPathRuntimeContext
|
104
|
+
)
|
105
|
+
context = UiPathRuntimeContext.with_defaults(
|
106
|
+
entrypoint=entrypoint,
|
107
|
+
input=input,
|
108
|
+
input_file=input_file,
|
109
|
+
resume=resume,
|
110
|
+
execution_output_file=output_file,
|
111
|
+
debug=debug,
|
112
|
+
)
|
113
|
+
|
114
|
+
asyncio.run(runtime_factory.execute(context))
|
115
|
+
|
116
|
+
except UiPathRuntimeError as e:
|
117
|
+
console.error(f"{e.error_info.title} - {e.error_info.detail}")
|
118
|
+
except Exception as e:
|
119
|
+
# Handle unexpected errors
|
120
|
+
console.error(
|
121
|
+
f"Error: Unexpected error occurred - {str(e)}", include_traceback=True
|
122
|
+
)
|
123
|
+
|
124
|
+
console.success("Successful execution.")
|
222
125
|
|
223
126
|
|
224
127
|
if __name__ == "__main__":
|
@@ -7,7 +7,7 @@ from .._config import Config
|
|
7
7
|
from .._execution_context import ExecutionContext
|
8
8
|
from .._folder_context import FolderContext
|
9
9
|
from .._utils import Endpoint, RequestSpec, header_folder, infer_bindings
|
10
|
-
from .._utils.constants import
|
10
|
+
from .._utils.constants import ENV_JOB_KEY, HEADER_JOB_KEY
|
11
11
|
from ..models.job import Job
|
12
12
|
from ..tracing._traced import traced
|
13
13
|
from . import AttachmentsService
|
@@ -241,7 +241,7 @@ class ProcessesService(FolderContext, BaseService):
|
|
241
241
|
**header_folder(folder_key, folder_path),
|
242
242
|
},
|
243
243
|
)
|
244
|
-
job_key = os.environ.get(
|
244
|
+
job_key = os.environ.get(ENV_JOB_KEY, None)
|
245
245
|
if job_key:
|
246
246
|
request_scope.headers[HEADER_JOB_KEY] = job_key
|
247
247
|
return request_scope
|
uipath/models/errors.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class BaseUrlMissingError(Exception):
|
2
2
|
def __init__(
|
3
3
|
self,
|
4
|
-
message="Authentication required. Please run \033[1muipath auth\033[22m.",
|
4
|
+
message="Authentication required. Please run \033[1muipath auth\033[22m or set the base URL via the UIPATH_URL environment variable.",
|
5
5
|
):
|
6
6
|
self.message = message
|
7
7
|
super().__init__(self.message)
|
@@ -10,7 +10,7 @@ class BaseUrlMissingError(Exception):
|
|
10
10
|
class SecretMissingError(Exception):
|
11
11
|
def __init__(
|
12
12
|
self,
|
13
|
-
message="Authentication required. Please run \033[1muipath auth\033[22m.",
|
13
|
+
message="Authentication required. Please run \033[1muipath auth\033[22m or set the UIPATH_ACCESS_TOKEN environment variable to a valid access token.",
|
14
14
|
):
|
15
15
|
self.message = message
|
16
16
|
super().__init__(self.message)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: uipath
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.45
|
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
|