uipath 2.1.124__py3-none-any.whl → 2.1.125__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.

Potentially problematic release.


This version of uipath might be problematic. Click here for more details.

@@ -1,10 +1,14 @@
1
+ import json
1
2
  import os
3
+ from pathlib import Path
2
4
  from typing import Optional
3
5
  from urllib.parse import urlparse
4
6
 
5
7
  import click
6
8
  from dotenv import load_dotenv
7
9
 
10
+ from ..._config import UiPathConfig
11
+ from ..._utils._bindings import ResourceOverwrite
8
12
  from ..._utils.constants import DOTENV_FILE
9
13
  from ..spinner import Spinner
10
14
 
@@ -116,3 +120,37 @@ def clean_directory(directory: str) -> None:
116
120
 
117
121
  def load_environment_variables():
118
122
  load_dotenv(dotenv_path=os.path.join(os.getcwd(), DOTENV_FILE), override=True)
123
+
124
+
125
+ async def read_resource_overwrites_from_file(
126
+ directory_path: Optional[Path] = None,
127
+ ) -> dict[str, ResourceOverwrite]:
128
+ """Read resource overwrites from a JSON file."""
129
+ config_file_name = UiPathConfig.config_file_name
130
+ if directory_path is not None:
131
+ file_path = Path(f"{directory_path}/{config_file_name}")
132
+ else:
133
+ file_path = Path(f"{config_file_name}")
134
+
135
+ overwrites_dict = {}
136
+
137
+ try:
138
+ with open(file_path, "r") as f:
139
+ data = json.load(f)
140
+ resource_overwrites = (
141
+ data.get("runtime", {})
142
+ .get("internalArguments", {})
143
+ .get("resourceOverwrites", {})
144
+ )
145
+
146
+ for key, value in resource_overwrites.items():
147
+ overwrite = ResourceOverwrite.model_validate(value)
148
+ overwrites_dict[key] = overwrite
149
+
150
+ # Return empty dict if file doesn't exist or invalid json
151
+ except FileNotFoundError:
152
+ pass
153
+ except json.JSONDecodeError:
154
+ pass
155
+
156
+ return overwrites_dict
@@ -1,12 +1,18 @@
1
1
  import json
2
2
  import os
3
+ from enum import Enum
3
4
  from functools import wraps
4
5
  from pathlib import PurePath
5
6
  from typing import Any, Callable, List, Optional, Union
6
7
 
8
+ import click
7
9
  from pydantic import BaseModel, ConfigDict, Field, field_validator
8
10
 
9
- from uipath._utils.constants import HEADER_SW_LOCK_KEY
11
+ from uipath import UiPath
12
+ from uipath._cli._utils._console import ConsoleLogger
13
+ from uipath._config import UiPathConfig
14
+ from uipath._utils._bindings import ResourceOverwrite
15
+ from uipath._utils.constants import ENV_TENANT_ID, HEADER_SW_LOCK_KEY, HEADER_TENANT_ID
10
16
  from uipath.models.exceptions import EnrichedException
11
17
  from uipath.tracing import traced
12
18
 
@@ -131,6 +137,54 @@ class LockInfo(BaseModel):
131
137
  solution_lock_key: Optional[str] = Field(alias="solutionLockKey")
132
138
 
133
139
 
140
+ class Severity(str, Enum):
141
+ """Severity level for virtual resource operation results."""
142
+
143
+ SUCCESS = "success"
144
+ ATTENTION = "attention"
145
+ WARN = "warn"
146
+
147
+
148
+ class VirtualResourceRequest(BaseModel):
149
+ model_config = ConfigDict(
150
+ populate_by_name=True,
151
+ )
152
+
153
+ kind: str = Field(alias="kind")
154
+ name: str = Field(alias="name")
155
+ type: Optional[str] = Field(default=None, alias="type")
156
+ activity_name: Optional[str] = Field(default=None, alias="activityName")
157
+ api_version: Optional[str] = Field(default=None, alias="apiVersion")
158
+
159
+
160
+ class VirtualResourceResult(BaseModel):
161
+ """Result of a virtual resource creation operation.
162
+
163
+ Attributes:
164
+ severity: The severity level (log, warn or attention)
165
+ message: The result message with styling
166
+ """
167
+
168
+ severity: Severity
169
+ message: str
170
+
171
+
172
+ class ResourceOverwriteData(BaseModel):
173
+ """Represents the overwrite details from the API response.
174
+
175
+ Attributes:
176
+ name: The name of the resource being overwritten
177
+ folder_path: The folder path of the overwrite resource
178
+ """
179
+
180
+ model_config = ConfigDict(
181
+ populate_by_name=True,
182
+ )
183
+
184
+ name: str = Field(alias="name")
185
+ folder_path: str = Field(alias="folderPath")
186
+
187
+
134
188
  def get_folder_by_name(
135
189
  structure: ProjectStructure, folder_name: str
136
190
  ) -> Optional[ProjectFolder]:
@@ -232,9 +286,7 @@ def with_lock_retry(func: Callable[..., Any]) -> Callable[..., Any]:
232
286
  return await func(self, *args, **kwargs)
233
287
  except EnrichedException as e:
234
288
  if e.status_code == 423:
235
- from uipath._cli._utils._console import ConsoleLogger
236
-
237
- console = ConsoleLogger()
289
+ console = ConsoleLogger().get_instance()
238
290
  console.error(
239
291
  "The project is temporarily locked. This could be due to modifications or active processes. Please wait a moment and try again."
240
292
  )
@@ -284,16 +336,189 @@ class StudioSolutionsClient:
284
336
 
285
337
 
286
338
  class StudioClient:
287
- def __init__(self, project_id: str):
288
- from uipath import UiPath
289
-
290
- self.uipath: UiPath = UiPath()
339
+ def __init__(self, project_id: str, uipath: Optional[UiPath] = None):
340
+ self.uipath: UiPath = uipath or UiPath()
291
341
  self.file_operations_base_url: str = (
292
342
  f"/studio_/backend/api/Project/{project_id}/FileOperations"
293
343
  )
294
344
  self._lock_operations_base_url: str = (
295
345
  f"/studio_/backend/api/Project/{project_id}/Lock"
296
346
  )
347
+ self._project_id = project_id
348
+ self._solution_id_cache: Optional[str] = None
349
+ self._resources_cache: Optional[List[dict[str, Any]]] = None
350
+
351
+ async def _get_solution_id(self) -> str:
352
+ # implement property cache logic as coroutines are not supported
353
+ if self._solution_id_cache is not None:
354
+ return self._solution_id_cache
355
+ response = await self.uipath.api_client.request_async(
356
+ "GET",
357
+ url=f"/studio_/backend/api/Project/{self._project_id}",
358
+ scoped="org",
359
+ )
360
+ self._solution_id_cache = response.json()["solutionId"]
361
+ return self._solution_id_cache
362
+
363
+ async def _get_existing_resources(self) -> List[dict[str, Any]]:
364
+ if self._resources_cache is not None:
365
+ return self._resources_cache
366
+
367
+ solution_id = await self._get_solution_id()
368
+ response = await self.uipath.api_client.request_async(
369
+ "GET",
370
+ url=f"/studio_/backend/api/resourcebuilder/solutions/{solution_id}/entities",
371
+ scoped="org",
372
+ )
373
+ resources_data = response.json().get("resources", [])
374
+ self._resources_cache = [
375
+ {"name": r.get("name"), "kind": r.get("kind")} for r in resources_data
376
+ ]
377
+ return self._resources_cache
378
+
379
+ async def get_resource_overwrites(self) -> dict[str, ResourceOverwrite]:
380
+ """Get resource overwrites from the solution.
381
+
382
+ Returns:
383
+ dict[str, ResourceOverwrite]: Dict of resource overwrites
384
+ """
385
+ if not os.path.exists(UiPathConfig.bindings_file_path):
386
+ return {}
387
+
388
+ with open(UiPathConfig.bindings_file_path, "rb") as f:
389
+ file_content = f.read()
390
+
391
+ solution_id = await self._get_solution_id()
392
+ tenant_id = os.getenv(ENV_TENANT_ID, None)
393
+
394
+ files = [
395
+ (
396
+ "file",
397
+ (
398
+ os.path.basename(UiPathConfig.bindings_file_path),
399
+ file_content,
400
+ "application/json",
401
+ ),
402
+ )
403
+ ]
404
+
405
+ response = await self.uipath.api_client.request_async(
406
+ "POST",
407
+ url=f"/studio_/backend/api/resourcebuilder/{solution_id}/binding-overwrites",
408
+ scoped="org",
409
+ headers={HEADER_TENANT_ID: tenant_id},
410
+ files=files,
411
+ )
412
+ data = response.json()
413
+ overwrites = {}
414
+
415
+ for key, value in data.items():
416
+ overwrites[key] = ResourceOverwrite.model_validate(value)
417
+
418
+ return overwrites
419
+
420
+ async def create_virtual_resource(
421
+ self, virtual_resource_request: VirtualResourceRequest
422
+ ) -> VirtualResourceResult:
423
+ """Create a virtual resource or return appropriate status if it already exists.
424
+
425
+ Args:
426
+ virtual_resource_request: The virtual resource request details
427
+
428
+ Returns:
429
+ VirtualResourceResult: Result indicating the operation status and a formatted message
430
+ """
431
+ # Build base message with resource details
432
+ base_message_parts = [
433
+ f"Resource {click.style(virtual_resource_request.name, fg='cyan')}",
434
+ f" (kind: {click.style(virtual_resource_request.kind, fg='yellow')}",
435
+ ]
436
+
437
+ if virtual_resource_request.type:
438
+ base_message_parts.append(
439
+ f", type: {click.style(virtual_resource_request.type, fg='yellow')}"
440
+ )
441
+
442
+ if virtual_resource_request.activity_name:
443
+ base_message_parts.append(
444
+ f", activity: {click.style(virtual_resource_request.activity_name, fg='yellow')}"
445
+ )
446
+
447
+ base_message_parts.append(")")
448
+ base_message = "".join(base_message_parts)
449
+
450
+ existing_resources = await self._get_existing_resources()
451
+
452
+ # Check if resource with same kind and name exists
453
+ existing_same_kind = next(
454
+ (
455
+ r
456
+ for r in existing_resources
457
+ if r["name"] == virtual_resource_request.name
458
+ and r["kind"] == virtual_resource_request.kind
459
+ ),
460
+ None,
461
+ )
462
+ if existing_same_kind:
463
+ message = f"{base_message} already exists. Skipping..."
464
+ return VirtualResourceResult(severity=Severity.ATTENTION, message=message)
465
+
466
+ # Check if resource with same name but different kind exists
467
+ existing_diff_kind = next(
468
+ (
469
+ r
470
+ for r in existing_resources
471
+ if r["name"] == virtual_resource_request.name
472
+ and r["kind"] != virtual_resource_request.kind
473
+ ),
474
+ None,
475
+ )
476
+ if existing_diff_kind:
477
+ message = (
478
+ f"Cannot create {base_message}. "
479
+ f"A resource with this name already exists with kind {click.style(existing_diff_kind['kind'], fg='yellow')}. "
480
+ f"Consider renaming the resource in code."
481
+ )
482
+ return VirtualResourceResult(severity=Severity.WARN, message=message)
483
+
484
+ # Create the virtual resource
485
+ solution_id = await self._get_solution_id()
486
+ response = await self.uipath.api_client.request_async(
487
+ "POST",
488
+ url=f"/studio_/backend/api/resourcebuilder/solutions/{solution_id}/resources/virtual",
489
+ scoped="org",
490
+ json=virtual_resource_request.model_dump(exclude_none=True),
491
+ )
492
+ resource_key = response.json()["key"]
493
+ await self._update_resource_specs(
494
+ resource_key, new_specs={"name": virtual_resource_request.name}
495
+ )
496
+
497
+ # Update cache with newly created resource
498
+ if self._resources_cache is not None:
499
+ self._resources_cache.append(
500
+ {
501
+ "name": virtual_resource_request.name,
502
+ "kind": virtual_resource_request.kind,
503
+ }
504
+ )
505
+
506
+ message = f"{base_message} created successfully."
507
+ return VirtualResourceResult(severity=Severity.SUCCESS, message=message)
508
+
509
+ async def _update_resource_specs(
510
+ self, resource_key: str, new_specs: dict[str, Any]
511
+ ):
512
+ solution_id = await self._get_solution_id()
513
+ tenant_id = os.getenv(ENV_TENANT_ID, None)
514
+
515
+ await self.uipath.api_client.request_async(
516
+ "PATCH",
517
+ url=f"/studio_/backend/api/resourcebuilder/solutions/{solution_id}/resources/{resource_key}/configuration",
518
+ scoped="org",
519
+ json=new_specs,
520
+ headers={HEADER_TENANT_ID: tenant_id},
521
+ )
297
522
 
298
523
  @traced(name="get_project_structure", run_type="uipath")
299
524
  async def get_project_structure_async(self) -> ProjectStructure:
uipath/_cli/cli_debug.py CHANGED
@@ -7,6 +7,9 @@ from typing import Optional
7
7
  import click
8
8
 
9
9
  from uipath._cli._utils._debug import setup_debugging
10
+ from uipath._cli._utils._studio_project import StudioClient
11
+ from uipath._config import UiPathConfig
12
+ from uipath._utils._bindings import ResourceOverwritesContext
10
13
  from uipath.tracing import LlmOpsHttpExporter
11
14
 
12
15
  from .._utils.constants import (
@@ -121,7 +124,7 @@ def debug(
121
124
  if debug_context.job_id:
122
125
  runtime_factory.add_span_exporter(LlmOpsHttpExporter())
123
126
 
124
- async def execute():
127
+ async def execute_debug_runtime():
125
128
  async with UiPathDebugRuntime.from_debug_context(
126
129
  factory=runtime_factory,
127
130
  context=debug_context,
@@ -129,6 +132,20 @@ def debug(
129
132
  ) as debug_runtime:
130
133
  await debug_runtime.execute()
131
134
 
135
+ async def execute():
136
+ project_id = UiPathConfig.project_id
137
+
138
+ if project_id:
139
+ studio_client = StudioClient(project_id)
140
+
141
+ async with ResourceOverwritesContext(
142
+ lambda: studio_client.get_resource_overwrites()
143
+ ) as ctx:
144
+ console.info(f"Applied {ctx.overwrites_count} overwrite(s)")
145
+ await execute_debug_runtime()
146
+ else:
147
+ await execute_debug_runtime()
148
+
132
149
  asyncio.run(execute())
133
150
  except Exception as e:
134
151
  console.error(
uipath/_cli/cli_eval.py CHANGED
@@ -13,9 +13,11 @@ from uipath._cli._evals._runtime import (
13
13
  )
14
14
  from uipath._cli._runtime._runtime_factory import generate_runtime_factory
15
15
  from uipath._cli._utils._folders import get_personal_workspace_key_async
16
+ from uipath._cli._utils._studio_project import StudioClient
16
17
  from uipath._cli.middlewares import Middlewares
17
18
  from uipath._config import UiPathConfig
18
19
  from uipath._events._event_bus import EventBus
20
+ from uipath._utils._bindings import ResourceOverwritesContext
19
21
  from uipath.eval._helpers import auto_discover_entrypoint
20
22
  from uipath.tracing import LlmOpsHttpExporter
21
23
 
@@ -155,7 +157,25 @@ def eval(
155
157
  runtime_factory = generate_runtime_factory()
156
158
  if eval_context.job_id:
157
159
  runtime_factory.add_span_exporter(LlmOpsHttpExporter())
158
- asyncio.run(evaluate(runtime_factory, eval_context, event_bus))
160
+
161
+ async def execute_eval():
162
+ project_id = UiPathConfig.project_id
163
+
164
+ if project_id:
165
+ studio_client = StudioClient(project_id)
166
+
167
+ async with ResourceOverwritesContext(
168
+ lambda: studio_client.get_resource_overwrites()
169
+ ) as ctx:
170
+ console.info(
171
+ f"Applied {ctx.overwrites_count} resource overwrite(s)"
172
+ )
173
+ await evaluate(runtime_factory, eval_context, event_bus)
174
+ else:
175
+ # Fall back to execution without overwrites
176
+ await evaluate(runtime_factory, eval_context, event_bus)
177
+
178
+ asyncio.run(execute_eval())
159
179
 
160
180
  except Exception as e:
161
181
  console.error(
uipath/_cli/cli_run.py CHANGED
@@ -7,7 +7,9 @@ from typing import Optional
7
7
  import click
8
8
 
9
9
  from uipath._cli._runtime._runtime_factory import generate_runtime_factory
10
+ from uipath._cli._utils._common import read_resource_overwrites_from_file
10
11
  from uipath._cli._utils._debug import setup_debugging
12
+ from uipath._utils._bindings import ResourceOverwritesContext
11
13
  from uipath.tracing import JsonLinesFileExporter, LlmOpsHttpExporter
12
14
 
13
15
  from .._utils.constants import (
@@ -123,7 +125,17 @@ def run(
123
125
  if trace_file:
124
126
  runtime_factory.add_span_exporter(JsonLinesFileExporter(trace_file))
125
127
 
126
- result = await runtime_factory.execute(context)
128
+ if context.job_id:
129
+ async with ResourceOverwritesContext(
130
+ lambda: read_resource_overwrites_from_file(context.runtime_dir)
131
+ ) as ctx:
132
+ console.info(
133
+ f"Applied {ctx.overwrites_count} resource overwrite(s)"
134
+ )
135
+
136
+ result = await runtime_factory.execute(context)
137
+ else:
138
+ result = await runtime_factory.execute(context)
127
139
 
128
140
  if not context.job_id:
129
141
  console.info(result.output)
uipath/_config.py CHANGED
@@ -24,6 +24,12 @@ class ConfigurationManager:
24
24
 
25
25
  return Path(UIPATH_BINDINGS_FILE)
26
26
 
27
+ @property
28
+ def config_file_name(self) -> str:
29
+ from uipath._utils.constants import UIPATH_CONFIG_FILE
30
+
31
+ return UIPATH_CONFIG_FILE
32
+
27
33
  @property
28
34
  def project_id(self) -> Optional[str]:
29
35
  from uipath._utils.constants import ENV_UIPATH_PROJECT_ID
@@ -40,5 +46,11 @@ class ConfigurationManager:
40
46
  def is_studio_project(self) -> bool:
41
47
  return self.project_id is not None
42
48
 
49
+ @property
50
+ def job_key(self) -> Optional[str]:
51
+ from uipath._utils.constants import ENV_JOB_KEY
52
+
53
+ return os.getenv(ENV_JOB_KEY, None)
54
+
43
55
 
44
56
  UiPathConfig = ConfigurationManager()
@@ -19,8 +19,6 @@ from tenacity import (
19
19
  wait_exponential,
20
20
  )
21
21
 
22
- from uipath._utils._read_overwrites import OverwritesManager
23
-
24
22
  from .._config import Config
25
23
  from .._execution_context import ExecutionContext
26
24
  from .._utils import UiPathUrl, user_agent_value
@@ -56,7 +54,6 @@ class BaseService:
56
54
  self._client = Client(**client_kwargs)
57
55
  self._client_async = AsyncClient(**client_kwargs)
58
56
 
59
- self._overwrites_manager = OverwritesManager()
60
57
  self._logger.debug(f"HEADERS: {self.default_headers}")
61
58
 
62
59
  super().__init__()
@@ -6,7 +6,6 @@ from .._config import Config
6
6
  from .._execution_context import ExecutionContext
7
7
  from .._folder_context import FolderContext
8
8
  from .._utils import Endpoint, RequestSpec, header_folder, infer_bindings
9
- from .._utils._read_overwrites import OverwritesManager
10
9
  from ..models import Asset, UserAsset
11
10
  from ..tracing._traced import traced
12
11
  from ._base_service import BaseService
@@ -21,7 +20,6 @@ class AssetsService(FolderContext, BaseService):
21
20
 
22
21
  def __init__(self, config: Config, execution_context: ExecutionContext) -> None:
23
22
  super().__init__(config=config, execution_context=execution_context)
24
- self._overwrites_manager = OverwritesManager()
25
23
  self._base_url = "assets"
26
24
 
27
25
  @traced(
uipath/_utils/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
+ from ._bindings import get_inferred_bindings_names, infer_bindings
1
2
  from ._endpoint import Endpoint
2
- from ._infer_bindings import get_inferred_bindings_names, infer_bindings
3
3
  from ._logs import setup_logging
4
4
  from ._request_override import header_folder
5
5
  from ._request_spec import RequestSpec
@@ -0,0 +1,109 @@
1
+ import functools
2
+ import inspect
3
+ from contextvars import ContextVar, Token
4
+ from typing import Any, Callable, Coroutine, Optional, TypeVar
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field
7
+
8
+ T = TypeVar("T")
9
+
10
+
11
+ class ResourceOverwrite(BaseModel):
12
+ """Represents a resource overwrite configuration.
13
+
14
+ Attributes:
15
+ overwrite_name: The name of the resource being overwritten
16
+ overwrite_folder_path: The folder path of the overwrite resource
17
+ """
18
+
19
+ model_config = ConfigDict(
20
+ populate_by_name=True,
21
+ )
22
+
23
+ overwrite_name: str = Field(alias="name")
24
+ overwrite_folder_path: str = Field(alias="folderPath")
25
+
26
+
27
+ _resource_overwrites: ContextVar[Optional[dict[str, ResourceOverwrite]]] = ContextVar(
28
+ "resource_overwrites", default=None
29
+ )
30
+
31
+
32
+ class ResourceOverwritesContext:
33
+ def __init__(
34
+ self,
35
+ get_overwrites_callable: Callable[
36
+ [], Coroutine[Any, Any, dict[str, ResourceOverwrite]]
37
+ ],
38
+ ):
39
+ self.get_overwrites_callable = get_overwrites_callable
40
+ self._token: Optional[Token[Optional[dict[str, ResourceOverwrite]]]] = None
41
+ self.overwrites_count = 0
42
+
43
+ async def __aenter__(self) -> "ResourceOverwritesContext":
44
+ overwrites = await self.get_overwrites_callable()
45
+ self._token = _resource_overwrites.set(overwrites)
46
+ self.overwrites_count = len(overwrites)
47
+ return self
48
+
49
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
50
+ if self._token:
51
+ _resource_overwrites.reset(self._token)
52
+
53
+
54
+ def infer_bindings(
55
+ resource_type: str,
56
+ name: str = "name",
57
+ folder_path: str = "folder_path",
58
+ ignore: bool = False,
59
+ ) -> Callable[..., Any]:
60
+ def decorator(func: Callable[..., Any]):
61
+ @functools.wraps(func)
62
+ def wrapper(*args, **kwargs):
63
+ # convert both args and kwargs to single dict
64
+ sig = inspect.signature(func)
65
+ bound = sig.bind_partial(*args, **kwargs)
66
+ bound.apply_defaults()
67
+ all_args = dict(bound.arguments)
68
+
69
+ # Get overwrites from context variable
70
+ context_overwrites = _resource_overwrites.get()
71
+
72
+ if context_overwrites is not None:
73
+ resource_name = all_args.get(name)
74
+ resource_folder_path = all_args.get(folder_path)
75
+
76
+ key = f"{resource_type}.{resource_name}"
77
+ # try to apply folder path, fallback to resource_type.resource_name
78
+ if resource_folder_path:
79
+ key = (
80
+ f"{key}.{resource_folder_path}"
81
+ if f"{key}.{resource_folder_path}" in context_overwrites
82
+ else key
83
+ )
84
+
85
+ matched_overwrite = context_overwrites.get(key)
86
+
87
+ # Apply the matched overwrite
88
+ if matched_overwrite is not None:
89
+ if name in sig.parameters:
90
+ all_args[name] = matched_overwrite.overwrite_name
91
+ if folder_path in sig.parameters:
92
+ all_args[folder_path] = matched_overwrite.overwrite_folder_path
93
+
94
+ return func(**all_args)
95
+
96
+ wrapper._should_infer_bindings = not ignore # type: ignore
97
+ wrapper._infer_bindings_mappings = {"name": name, "folder_path": folder_path} # type: ignore
98
+ return wrapper
99
+
100
+ return decorator
101
+
102
+
103
+ def get_inferred_bindings_names(cls: T):
104
+ inferred_bindings = {}
105
+ for name, method in inspect.getmembers(cls, inspect.isfunction):
106
+ if hasattr(method, "_should_infer_bindings") and method._should_infer_bindings:
107
+ inferred_bindings[name] = method._infer_bindings_mappings # type: ignore
108
+
109
+ return inferred_bindings
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath
3
- Version: 2.1.124
3
+ Version: 2.1.125
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
@@ -1,5 +1,5 @@
1
1
  uipath/__init__.py,sha256=IaeKItOOQXMa95avueJ3dAq-XcRHyZVNjcCGwlSB000,634
2
- uipath/_config.py,sha256=YEiLmpHeeT2K_CinSVWr9aIWU6txfkgAUPP-jqxa9R0,990
2
+ uipath/_config.py,sha256=wLE_DLB4d-tHDAA6biyv8hzCZ2RmYS--fab8t2EAjqI,1298
3
3
  uipath/_execution_context.py,sha256=Qo8VMUFgtiL-40KsZrvul5bGv1CRERle_fCw1ORCggY,2374
4
4
  uipath/_folder_context.py,sha256=D-bgxdwpwJP4b_QdVKcPODYh15kMDrOar2xNonmMSm4,1861
5
5
  uipath/_uipath.py,sha256=ycu11bjIUx5priRkB3xSRcilugHuSmfSN4Nq6Yz88gk,3702
@@ -8,10 +8,10 @@ uipath/_cli/README.md,sha256=GLtCfbeIKZKNnGTCsfSVqRQ27V1btT1i2bSAyW_xZl4,474
8
8
  uipath/_cli/__init__.py,sha256=rEk5GEldWxhjfe7R4DiDDXsc6O4GMUX86CyuUDU4QCY,2471
9
9
  uipath/_cli/cli_add.py,sha256=7XpyeXIVnocNTJg_Wo1GeDFSoHDu8ACaYx__eYpiXzY,3690
10
10
  uipath/_cli/cli_auth.py,sha256=CzetSRqSUvMs02PtI4w5Vi_0fv_ETA307bB2vXalWzY,2628
11
- uipath/_cli/cli_debug.py,sha256=-s6Nmy0DnDyITjZAf6f71hZ1YDDt0Yl57XklEkuL0FU,4068
11
+ uipath/_cli/cli_debug.py,sha256=6I3NutFahQ7nvbxUIgW8bmKeoShVf8RCvco3XU0kfTk,4796
12
12
  uipath/_cli/cli_deploy.py,sha256=KPCmQ0c_NYD5JofSDao5r6QYxHshVCRxlWDVnQvlp5w,645
13
13
  uipath/_cli/cli_dev.py,sha256=nEfpjw1PZ72O6jmufYWVrueVwihFxDPOeJakdvNHdOA,2146
14
- uipath/_cli/cli_eval.py,sha256=odAZtE8jfT9Yl3UyJgN6WJJcImt32iSJyi_uw1BTUtg,5404
14
+ uipath/_cli/cli_eval.py,sha256=lRNP9kHxIsgdo2tl0bQraCMYLSyANS9VlAOJMr_JdEA,6229
15
15
  uipath/_cli/cli_init.py,sha256=39sQnIHol46D5ce4MBJRrD_8KOqvK1IyYhgn42_XYIM,7545
16
16
  uipath/_cli/cli_invoke.py,sha256=m-te-EjhDpk_fhFDkt-yQFzmjEHGo5lQDGEQWxSXisQ,4395
17
17
  uipath/_cli/cli_new.py,sha256=9378NYUBc9j-qKVXV7oja-jahfJhXBg8zKVyaon7ctY,2102
@@ -20,7 +20,7 @@ uipath/_cli/cli_publish.py,sha256=DgyfcZjvfV05Ldy0Pk5y_Le_nT9JduEE_x-VpIc_Kq0,64
20
20
  uipath/_cli/cli_pull.py,sha256=nV-OCdue_7C6x4f8jRoTYSnM-BgsWVsZUVibkgnogDU,2117
21
21
  uipath/_cli/cli_push.py,sha256=5J-dhDilsYrlYg1aV1eWOU84QC_PlwTi9tI3UZptg1k,3743
22
22
  uipath/_cli/cli_register.py,sha256=5-Asb8DSTR4W6M3TDi4U-AKXYOCZ3l2vcTuMOybDHEo,1465
23
- uipath/_cli/cli_run.py,sha256=9vbmSG_FzS0x8KNNzSrST37FKjUOzhXPjl8xTm2ZEqQ,4203
23
+ uipath/_cli/cli_run.py,sha256=-pSuoPEfT-NzOmxLgNUtMvkYY-Lhk-dO5qv6UZkmkKU,4797
24
24
  uipath/_cli/middlewares.py,sha256=tb0c4sU1SCYi0PNs956Qmk24NDk0C0mBfVQmTcyORE0,5000
25
25
  uipath/_cli/spinner.py,sha256=bS-U_HA5yne11ejUERu7CQoXmWdabUD2bm62EfEdV8M,1107
26
26
  uipath/_cli/_auth/_auth_server.py,sha256=v_b8KNwn0tAv8jxpeKdllOVzl31q9AcdwpE_koAK_w4,7235
@@ -86,7 +86,7 @@ uipath/_cli/_templates/[Content_Types].xml.template,sha256=bYsKDz31PkIF9QksjgAY_
86
86
  uipath/_cli/_templates/custom_evaluator.py.template,sha256=OuYQb8ScAOK7Qwz4FYwdETlC2NonEhLF5DXGnsYOzHg,2313
87
87
  uipath/_cli/_templates/main.py.template,sha256=QB62qX5HKDbW4lFskxj7h9uuxBITnTWqu_DE6asCwcU,476
88
88
  uipath/_cli/_templates/package.nuspec.template,sha256=YZyLc-u_EsmIoKf42JsLQ55OGeFmb8VkIU2VF7DFbtw,359
89
- uipath/_cli/_utils/_common.py,sha256=fSZkps1sjOXRyWn8GqmQfGqYAZ_tVua6dgT18Lpscds,3467
89
+ uipath/_cli/_utils/_common.py,sha256=RVLfHIRJ7mUIxpV61lwqGqQbr1QIhJ8cb5r_GKZzpws,4628
90
90
  uipath/_cli/_utils/_console.py,sha256=scvnrrFoFX6CE451K-PXKV7UN0DUkInbOtDZ5jAdPP0,10070
91
91
  uipath/_cli/_utils/_constants.py,sha256=AXeVidtHUFiODrkB2BCX_bqDL-bUzRg-Ieh1-2cCrGA,1374
92
92
  uipath/_cli/_utils/_debug.py,sha256=zamzIR4VgbdKADAE4gbmjxDsbgF7wvdr7C5Dqp744Oc,1739
@@ -97,7 +97,7 @@ uipath/_cli/_utils/_parse_ast.py,sha256=24YL28qK5Ss2O26IlzZ2FgEC_ZazXld_u3vkj8zV
97
97
  uipath/_cli/_utils/_processes.py,sha256=q7DfEKHISDWf3pngci5za_z0Pbnf_shWiYEcTOTCiyk,1855
98
98
  uipath/_cli/_utils/_project_files.py,sha256=i3F94aYekpM7PHVC3FrC1-lRBw-Tpe9XihN7pjCUkys,21812
99
99
  uipath/_cli/_utils/_resources.py,sha256=0MpEZWaY2oDDoxOVVTOXrTWpuwhQyypLcM8TgnXFQq0,577
100
- uipath/_cli/_utils/_studio_project.py,sha256=2QzB9lyDlWukWMlFbAyv-DXhhGBK973Bsl3ZbiIambg,18286
100
+ uipath/_cli/_utils/_studio_project.py,sha256=kEjCFyP-pm9mVOR-C-makoZ_vbgQRHfu8kRZfRsJino,26308
101
101
  uipath/_cli/_utils/_tracing.py,sha256=2igb03j3EHjF_A406UhtCKkPfudVfFPjUq5tXUEG4oo,1541
102
102
  uipath/_cli/_utils/_uv_helpers.py,sha256=6SvoLnZPoKIxW0sjMvD1-ENV_HOXDYzH34GjBqwT138,3450
103
103
  uipath/_cli/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -111,10 +111,10 @@ uipath/_resources/CLI_REFERENCE.md,sha256=PNVZINTXDSW4XN8QtxV3kS2WLreR7UyLfSso1_
111
111
  uipath/_resources/REQUIRED_STRUCTURE.md,sha256=3laqGiNa3kauJ7jRI1d7w_fWKUDkqYBjcTT_6_8FAGk,1417
112
112
  uipath/_resources/SDK_REFERENCE.md,sha256=lvQxxdsHi-kzur2C1L4fJ6cEvjVdJPUNSX8UMofgqUQ,19485
113
113
  uipath/_services/__init__.py,sha256=_LNy4u--VlhVtTO66bULbCoBjyJBTuyh9jnzjWrv-h4,1140
114
- uipath/_services/_base_service.py,sha256=x9-9jhPzn9Z16KRdFHhJNvV-FZHvTniMsDfxlS4Cutk,5782
114
+ uipath/_services/_base_service.py,sha256=6yGNEZ-px6lVR9l4wiMr8NDSeLrZU6nmjUlRp3lMDi8,5665
115
115
  uipath/_services/actions_service.py,sha256=2RPMR-hFMsOlqEyjIf3aF7-lrf57jdrSD0pBjj0Kyko,16040
116
116
  uipath/_services/api_client.py,sha256=kGm04ijk9AOEQd2BMxvQg-2QoB8dmyoDwFFDPyutAGw,1966
117
- uipath/_services/assets_service.py,sha256=mcnjbxW1JL_lk_FlWyaVQyfz9qYlHTJngBJPxF8Jric,12201
117
+ uipath/_services/assets_service.py,sha256=Z46_Nm4X7R0JcwF_Fph-5GwQ_qhQHRKJltCtwo3J8Yo,12090
118
118
  uipath/_services/attachments_service.py,sha256=NPQYK7CGjfBaNT_1S5vEAfODmOChTbQZforllFM2ofU,26678
119
119
  uipath/_services/buckets_service.py,sha256=FGWhJ3ewMEAahcSPY60wtFB0_qwAfaQAaAjqrC52VDk,44603
120
120
  uipath/_services/connections_service.py,sha256=tKJHHOKQYKR6LkgB-V_2d0vFpLEdFeMzwj_xmBVHUDw,18416
@@ -128,12 +128,11 @@ uipath/_services/jobs_service.py,sha256=tTZNsdZKN3uP7bWPQyBCpJeQxTfuOWbKYOR4L-_y
128
128
  uipath/_services/llm_gateway_service.py,sha256=vRnx5MSSkxxR0Xw4_km0_aDBrWgkZmyJ1QRBp_anfog,24995
129
129
  uipath/_services/processes_service.py,sha256=O_uHgQ1rnwiV5quG0OQqabAnE6Rf6cWrMENYY2jKWt8,8585
130
130
  uipath/_services/queues_service.py,sha256=VaG3dWL2QK6AJBOLoW2NQTpkPfZjsqsYPl9-kfXPFzA,13534
131
- uipath/_utils/__init__.py,sha256=VdcpnENJIa0R6Y26NoxY64-wUVyvb4pKfTh1wXDQeMk,526
131
+ uipath/_utils/__init__.py,sha256=EhATIyHXvey01-2NPfkYVZepe-oEh2e5k7v2eQSGLqc,520
132
132
  uipath/_utils/_auth.py,sha256=5R30ALuRrIatf_0Lk-AETJvt6ora7h0R7yeDdliW1Lg,2524
133
+ uipath/_utils/_bindings.py,sha256=KDo1VdtGjZ4lnklwQysFI_sy3_PFNZIHnihtUjDlzNI,3735
133
134
  uipath/_utils/_endpoint.py,sha256=yYHwqbQuJIevpaTkdfYJS9CrtlFeEyfb5JQK5osTCog,2489
134
- uipath/_utils/_infer_bindings.py,sha256=eCxfUjd37fOFZ6vOfKl2BhWVUt7iSSJ-VQ0-nDTBcaA,1836
135
135
  uipath/_utils/_logs.py,sha256=QNo2YnUT1ANFHNEzYWv6PzX11438HPjo9MweQYS9UnU,408
136
- uipath/_utils/_read_overwrites.py,sha256=OQgG9ycPpFnLub5ELQdX9V2Fyh6F9_zDR3xoYagJaMI,5287
137
136
  uipath/_utils/_request_override.py,sha256=fIVHzgHVXITUlWcp8osNBwIafM1qm4_ejx0ng5UzfJ4,573
138
137
  uipath/_utils/_request_spec.py,sha256=iCtBLqtbWUpFG5g1wtIZBzSupKsfaRLiQFoFc_4B70Q,747
139
138
  uipath/_utils/_ssl_context.py,sha256=xSYitos0eJc9cPHzNtHISX9PBvL6D2vas5G_GiBdLp8,1783
@@ -225,8 +224,8 @@ uipath/tracing/_utils.py,sha256=emsQRgYu-P1gj1q7XUPJD94mOa12JvhheRkuZJpLd9Y,1505
225
224
  uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
226
225
  uipath/utils/_endpoints_manager.py,sha256=tnF_FiCx8qI2XaJDQgYkMN_gl9V0VqNR1uX7iawuLp8,8230
227
226
  uipath/utils/dynamic_schema.py,sha256=w0u_54MoeIAB-mf3GmwX1A_X8_HDrRy6p998PvX9evY,3839
228
- uipath-2.1.124.dist-info/METADATA,sha256=n6KKj2X088M0x2A4gwgZKxErG_9FP5kgmAYpMe7UujU,6626
229
- uipath-2.1.124.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
230
- uipath-2.1.124.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
231
- uipath-2.1.124.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
232
- uipath-2.1.124.dist-info/RECORD,,
227
+ uipath-2.1.125.dist-info/METADATA,sha256=PFJv_XJNWdOSugtGeBceOV_hdA-_yMdyumhnlwb_vTM,6626
228
+ uipath-2.1.125.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
229
+ uipath-2.1.125.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
230
+ uipath-2.1.125.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
231
+ uipath-2.1.125.dist-info/RECORD,,
@@ -1,51 +0,0 @@
1
- import functools
2
- import inspect
3
- from typing import Any, Callable, TypeVar
4
-
5
- from ._read_overwrites import read_resource_overwrites
6
-
7
- T = TypeVar("T")
8
-
9
-
10
- def infer_bindings(
11
- resource_type: str,
12
- name: str = "name",
13
- folder_path: str = "folder_path",
14
- ignore: bool = False,
15
- ) -> Callable[..., Any]:
16
- def decorator(func: Callable[..., Any]):
17
- @functools.wraps(func)
18
- def wrapper(*args, **kwargs):
19
- # convert both args and kwargs to single dict
20
- sig = inspect.signature(func)
21
- bound = sig.bind_partial(*args, **kwargs)
22
- bound.apply_defaults()
23
- all_args = dict(bound.arguments)
24
-
25
- if name in all_args or folder_path in all_args:
26
- with read_resource_overwrites(
27
- resource_type,
28
- all_args.get(name), # type: ignore
29
- all_args.get(folder_path, None),
30
- ) as (name_overwrite_or_default, folder_path_overwrite_or_default):
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
35
-
36
- return func(**all_args)
37
-
38
- wrapper._should_infer_bindings = not ignore # type: ignore
39
- wrapper._infer_bindings_mappings = {"name": name, "folder_path": folder_path} # type: ignore
40
- return wrapper
41
-
42
- return decorator
43
-
44
-
45
- def get_inferred_bindings_names(cls: T):
46
- inferred_bindings = {}
47
- for name, method in inspect.getmembers(cls, inspect.isfunction):
48
- if hasattr(method, "_should_infer_bindings") and method._should_infer_bindings:
49
- inferred_bindings[name] = method._infer_bindings_mappings # type: ignore
50
-
51
- return inferred_bindings
@@ -1,144 +0,0 @@
1
- import json
2
- from contextlib import contextmanager
3
- from pathlib import Path
4
- from typing import Any, Dict, Generator, Optional, Tuple
5
-
6
-
7
- class OverwritesManager:
8
- """Manages overwrites for different resource types and methods.
9
-
10
- This class handles reading and accessing bindings overwrites from a JSON file.
11
- The overwrites are stored under the 'resourceOverwrites' key, where each key is a
12
- resource key (e.g., 'asset.MyAssetKeyFromBindingsJson') and the value contains
13
- 'name' and 'folderPath' fields.
14
-
15
- This is a singleton class to ensure only one instance exists throughout the application.
16
- """
17
-
18
- _instance = None
19
- _overwrites_file_path: Path = Path("__uipath/uipath.json")
20
- _runtime_overwrites: Dict[str, Any] = {}
21
-
22
- def __new__(
23
- cls, overwrites_file_path: Optional[Path] = None
24
- ) -> "OverwritesManager":
25
- """Create or return the singleton instance.
26
-
27
- Args:
28
- overwrites_file_path: Optional path to the overwrites JSON file.
29
- If not provided, defaults to 'uipath.json' in the project root.
30
-
31
- Returns:
32
- The singleton instance of OverwritesManager.
33
- """
34
- if cls._instance is None:
35
- cls._instance = super().__new__(cls)
36
- cls._instance._overwrites_file_path = (
37
- overwrites_file_path or cls._overwrites_file_path
38
- )
39
- cls._instance._read_overwrites_file()
40
- elif (
41
- overwrites_file_path
42
- and overwrites_file_path != cls._instance._overwrites_file_path
43
- ):
44
- # If a new file path is provided and it's different from the current one,
45
- # update the path and re-read the file
46
- cls._instance._overwrites_file_path = overwrites_file_path
47
- cls._instance._read_overwrites_file()
48
- return cls._instance
49
-
50
- def _read_overwrites_file(self) -> None:
51
- """Read the overwrites JSON file and cache the data.
52
-
53
- Raises:
54
- FileNotFoundError: If the overwrites file doesn't exist.
55
- json.JSONDecodeError: If the file contains invalid JSON.
56
- """
57
- try:
58
- with open(self._overwrites_file_path, "r") as f:
59
- data = json.load(f)
60
- self._runtime_overwrites = (
61
- data.get("runtime", {})
62
- .get("internalArguments", {})
63
- .get("resourceOverwrites", {})
64
- )
65
- except FileNotFoundError:
66
- self._runtime_overwrites = {}
67
-
68
- def get_overwrite(
69
- self, resource_type: str, resource_name: str, folder_path: Optional[str] = None
70
- ) -> Optional[Tuple[str, str]]:
71
- """Get an overwrite value for a specific resource.
72
-
73
- Args:
74
- resource_type: The type of resource (e.g., 'process', 'asset').
75
- resource_name: The name of the resource.
76
-
77
- Returns:
78
- A tuple of (name, folder_path) if found, None otherwise.
79
- """
80
- if folder_path:
81
- key = f"{resource_type}.{resource_name}.{folder_path}"
82
- else:
83
- key = f"{resource_type}.{resource_name}"
84
-
85
- if key not in self._runtime_overwrites:
86
- return None
87
-
88
- overwrite = self._runtime_overwrites[key]
89
- return (
90
- overwrite.get("name", resource_name),
91
- overwrite.get("folderPath", ""),
92
- )
93
-
94
- def get_and_apply_overwrite(
95
- self, resource_type: str, resource_name: str, folder_path: Optional[str] = None
96
- ) -> Tuple[Any, Any]:
97
- """Get and apply overwrites for a resource, falling back to provided values if no overwrites exist.
98
-
99
- Args:
100
- resource_type: The type of resource (e.g., 'process', 'asset').
101
- resource_name: The name of the resource.
102
- folder_path: Optional folder path to use if no overwrite exists.
103
-
104
- Returns:
105
- A tuple of (name, folder_path) with overwritten values if available,
106
- otherwise the original values.
107
- """
108
- overwrite = self.get_overwrite(resource_type, resource_name, folder_path)
109
- if overwrite:
110
- resource_name, folder_path = overwrite
111
- return resource_name, folder_path or None
112
-
113
-
114
- @contextmanager
115
- def read_resource_overwrites(
116
- resource_type: str,
117
- resource_name: str,
118
- folder_path: Optional[str] = None,
119
- overwrites_file_path: Optional[Path] = None,
120
- ) -> Generator[Tuple[str, str], None, None]:
121
- """Context manager for reading and applying resource overwrites.
122
-
123
- Args:
124
- resource_type: The type of resource (e.g., 'process', 'asset').
125
- resource_name: The name of the resource.
126
- folder_path: Optional folder path to use if no overwrite exists.
127
- overwrites_file_path: Optional path to the overwrites JSON file.
128
-
129
- Yields:
130
- A tuple of (name, folder_path) with overwritten values if available,
131
- otherwise the original values.
132
-
133
- Example:
134
- ```python
135
- with read_resource_overwrites("asset", "MyAsset") as (name, folder_path):
136
- # Use name and folder_path here
137
- pass
138
- ```
139
- """
140
- manager = OverwritesManager(overwrites_file_path)
141
- try:
142
- yield manager.get_and_apply_overwrite(resource_type, resource_name, folder_path)
143
- finally:
144
- pass