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

@@ -10,7 +10,7 @@ from dotenv import load_dotenv
10
10
 
11
11
  from ._oidc_utils import get_auth_config
12
12
 
13
- load_dotenv()
13
+ load_dotenv(override=True)
14
14
 
15
15
  # Server port
16
16
  PORT = 6234
uipath/_cli/cli_auth.py CHANGED
@@ -15,7 +15,7 @@ from ._auth._utils import update_auth_file, update_env_file
15
15
  from ._utils._common import environment_options
16
16
  from ._utils._console import ConsoleLogger
17
17
 
18
- load_dotenv()
18
+ load_dotenv(override=True)
19
19
  console = ConsoleLogger()
20
20
 
21
21
 
uipath/_cli/cli_invoke.py CHANGED
@@ -20,7 +20,7 @@ from ._utils._folders import get_personal_workspace_info
20
20
  from ._utils._processes import get_release_info
21
21
 
22
22
  logger = logging.getLogger(__name__)
23
- load_dotenv()
23
+ load_dotenv(override=True)
24
24
  console = ConsoleLogger()
25
25
  client = httpx.Client(follow_redirects=True, timeout=30.0)
26
26
 
uipath/_cli/cli_run.py CHANGED
@@ -23,7 +23,7 @@ from ._utils._console import ConsoleLogger
23
23
  from .middlewares import MiddlewareResult, Middlewares
24
24
 
25
25
  console = ConsoleLogger()
26
- load_dotenv()
26
+ load_dotenv(override=True)
27
27
 
28
28
 
29
29
  def python_run_middleware(
@@ -5,7 +5,7 @@ from dotenv import load_dotenv
5
5
 
6
6
  from ._utils.constants import ENV_JOB_ID, ENV_JOB_KEY, ENV_ROBOT_KEY
7
7
 
8
- load_dotenv()
8
+ load_dotenv(override=True)
9
9
 
10
10
 
11
11
  class ExecutionContext:
uipath/_folder_context.py CHANGED
@@ -10,7 +10,7 @@ from ._utils.constants import (
10
10
  HEADER_FOLDER_PATH,
11
11
  )
12
12
 
13
- load_dotenv()
13
+ load_dotenv(override=True)
14
14
 
15
15
 
16
16
  class FolderContext:
@@ -1,6 +1,6 @@
1
1
  import inspect
2
2
  from logging import getLogger
3
- from typing import Any, Union
3
+ from typing import Any, Literal, Union
4
4
 
5
5
  from httpx import (
6
6
  URL,
@@ -22,7 +22,7 @@ from uipath._utils._read_overwrites import OverwritesManager
22
22
 
23
23
  from .._config import Config
24
24
  from .._execution_context import ExecutionContext
25
- from .._utils import user_agent_value
25
+ from .._utils import UiPathUrl, user_agent_value
26
26
  from .._utils.constants import HEADER_USER_AGENT
27
27
 
28
28
 
@@ -39,24 +39,17 @@ class BaseService:
39
39
  self._logger = getLogger("uipath")
40
40
  self._config = config
41
41
  self._execution_context = execution_context
42
- self._tenant_scope_client = Client(
43
- base_url=self._config.base_url,
44
- headers=Headers(self.default_headers),
45
- timeout=30.0,
46
- )
47
- self._tenant_scope_client_async = AsyncClient(
48
- base_url=self._config.base_url,
49
- headers=Headers(self.default_headers),
50
- timeout=30.0,
51
- )
52
- org_scope_base_url = self.__get_org_scope_base_url()
53
- self._org_scope_client = Client(
54
- base_url=org_scope_base_url,
42
+
43
+ self._url = UiPathUrl(self._config.base_url)
44
+
45
+ self._client = Client(
46
+ base_url=self._url.base_url,
55
47
  headers=Headers(self.default_headers),
56
48
  timeout=30.0,
57
49
  )
58
- self._org_scope_client_async = AsyncClient(
59
- base_url=org_scope_base_url,
50
+
51
+ self._client_async = AsyncClient(
52
+ base_url=self._url.base_url,
60
53
  headers=Headers(self.default_headers),
61
54
  timeout=30.0,
62
55
  )
@@ -77,12 +70,12 @@ class BaseService:
77
70
  self,
78
71
  method: str,
79
72
  url: Union[URL, str],
73
+ *,
74
+ scoped: Literal["org", "tenant"] = "tenant",
80
75
  **kwargs: Any,
81
76
  ) -> Response:
82
77
  self._logger.debug(f"Request: {method} {url}")
83
- self._logger.debug(
84
- f"HEADERS: {kwargs.get('headers', self._tenant_scope_client.headers)}"
85
- )
78
+ self._logger.debug(f"HEADERS: {kwargs.get('headers', self._client.headers)}")
86
79
 
87
80
  try:
88
81
  stack = inspect.stack()
@@ -104,10 +97,13 @@ class BaseService:
104
97
  specific_component = (
105
98
  f"{module_name}.{function_name}" if module_name and function_name else ""
106
99
  )
107
- headers = kwargs.get("headers", {})
108
- headers[HEADER_USER_AGENT] = user_agent_value(specific_component)
109
100
 
110
- response = self._tenant_scope_client.request(method, url, **kwargs)
101
+ kwargs.setdefault("headers", {})
102
+ kwargs["headers"][HEADER_USER_AGENT] = user_agent_value(specific_component)
103
+
104
+ scoped_url = self._url.scope_url(str(url), scoped)
105
+
106
+ response = self._client.request(method, scoped_url, **kwargs)
111
107
  response.raise_for_status()
112
108
 
113
109
  return response
@@ -123,96 +119,51 @@ class BaseService:
123
119
  self,
124
120
  method: str,
125
121
  url: Union[URL, str],
122
+ *,
123
+ scoped: Literal["org", "tenant"] = "tenant",
126
124
  **kwargs: Any,
127
125
  ) -> Response:
128
126
  self._logger.debug(f"Request: {method} {url}")
129
127
  self._logger.debug(
130
- f"HEADERS: {kwargs.get('headers', self._tenant_scope_client.headers)}"
128
+ f"HEADERS: {kwargs.get('headers', self._client_async.headers)}"
131
129
  )
132
130
 
133
- try:
134
- stack = inspect.stack()
135
-
136
- # use the third frame because of the retry decorator
137
- caller_frame = stack[3].frame
138
- function_name = caller_frame.f_code.co_name
139
-
140
- if "self" in caller_frame.f_locals:
141
- module_name = type(caller_frame.f_locals["self"]).__name__
142
- elif "cls" in caller_frame.f_locals:
143
- module_name = caller_frame.f_locals["cls"].__name__
144
- else:
145
- module_name = ""
146
- except Exception:
147
- function_name = ""
148
- module_name = ""
149
-
150
- specific_component = (
151
- f"{module_name}.{function_name}" if module_name and function_name else ""
131
+ kwargs.setdefault("headers", {})
132
+ kwargs["headers"][HEADER_USER_AGENT] = user_agent_value(
133
+ self._specific_component
152
134
  )
153
- headers = kwargs.get("headers", {})
154
- headers[HEADER_USER_AGENT] = user_agent_value(specific_component)
155
135
 
156
- response = await self._tenant_scope_client_async.request(method, url, **kwargs)
136
+ scoped_url = self._url.scope_url(str(url), scoped)
137
+
138
+ response = await self._client_async.request(method, scoped_url, **kwargs)
157
139
  response.raise_for_status()
158
140
 
159
141
  return response
160
142
 
161
- def request_org_scope(
162
- self,
163
- method: str,
164
- url: Union[URL, str],
165
- **kwargs: Any,
166
- ) -> Response:
167
- self._logger.debug(f"Request: {method} {url}")
168
- self._logger.debug(
169
- f"HEADERS: {kwargs.get('headers', self._tenant_scope_client.headers)}"
170
- )
171
-
172
- try:
173
- stack = inspect.stack()
174
-
175
- # use the third frame because of the retry decorator
176
- caller_frame = stack[3].frame
177
- function_name = caller_frame.f_code.co_name
178
-
179
- if "self" in caller_frame.f_locals:
180
- module_name = type(caller_frame.f_locals["self"]).__name__
181
- elif "cls" in caller_frame.f_locals:
182
- module_name = caller_frame.f_locals["cls"].__name__
183
- else:
184
- module_name = ""
185
- except Exception:
186
- function_name = ""
187
- module_name = ""
188
-
189
- specific_component = (
190
- f"{module_name}.{function_name}" if module_name and function_name else ""
191
- )
192
- headers = kwargs.get("headers", {})
193
- headers[HEADER_USER_AGENT] = user_agent_value(specific_component)
194
-
195
- response = self._org_scope_client.request(method, url, **kwargs)
196
- response.raise_for_status()
143
+ @property
144
+ def default_headers(self) -> dict[str, str]:
145
+ return {
146
+ "Accept": "application/json",
147
+ "Content-Type": "application/json",
148
+ **self.auth_headers,
149
+ **self.custom_headers,
150
+ }
197
151
 
198
- return response
152
+ @property
153
+ def auth_headers(self) -> dict[str, str]:
154
+ header = f"Bearer {self._config.secret}"
155
+ return {"Authorization": header}
199
156
 
200
- async def request_org_scope_async(
201
- self,
202
- method: str,
203
- url: Union[URL, str],
204
- **kwargs: Any,
205
- ) -> Response:
206
- self._logger.debug(f"Request: {method} {url}")
207
- self._logger.debug(
208
- f"HEADERS: {kwargs.get('headers', self._tenant_scope_client.headers)}"
209
- )
157
+ @property
158
+ def custom_headers(self) -> dict[str, str]:
159
+ return {}
210
160
 
161
+ @property
162
+ def _specific_component(self) -> str:
211
163
  try:
212
164
  stack = inspect.stack()
213
165
 
214
- # use the third frame because of the retry decorator
215
- caller_frame = stack[3].frame
166
+ caller_frame = stack[4].frame
216
167
  function_name = caller_frame.f_code.co_name
217
168
 
218
169
  if "self" in caller_frame.f_locals:
@@ -228,34 +179,5 @@ class BaseService:
228
179
  specific_component = (
229
180
  f"{module_name}.{function_name}" if module_name and function_name else ""
230
181
  )
231
- headers = kwargs.get("headers", {})
232
- headers[HEADER_USER_AGENT] = user_agent_value(specific_component)
233
-
234
- response = await self._org_scope_client_async.request(method, url, **kwargs)
235
- response.raise_for_status()
236
-
237
- return response
238
-
239
- @property
240
- def default_headers(self) -> dict[str, str]:
241
- return {
242
- "Accept": "application/json",
243
- "Content-Type": "application/json",
244
- **self.auth_headers,
245
- **self.custom_headers,
246
- }
247
-
248
- @property
249
- def auth_headers(self) -> dict[str, str]:
250
- header = f"Bearer {self._config.secret}"
251
- return {"Authorization": header}
252
-
253
- @property
254
- def custom_headers(self) -> dict[str, str]:
255
- return {}
256
182
 
257
- def __get_org_scope_base_url(self) -> str:
258
- base_url = str(self._config.base_url)
259
- if base_url.endswith("/"):
260
- base_url = base_url[:-1]
261
- return base_url.rsplit("/", 1)[0] + "/"
183
+ return specific_component
@@ -349,8 +349,12 @@ class ActionsService(FolderContext, BaseService):
349
349
  raise Exception("appName or appKey is required")
350
350
  spec = _retrieve_app_key_spec(app_name=app_name)
351
351
 
352
- response = await self.request_org_scope_async(
353
- spec.method, spec.endpoint, params=spec.params, headers=spec.headers
352
+ response = await self.request_async(
353
+ spec.method,
354
+ spec.endpoint,
355
+ params=spec.params,
356
+ headers=spec.headers,
357
+ scoped="org",
354
358
  )
355
359
  try:
356
360
  deployed_app = self._extract_deployed_app(
@@ -382,8 +386,12 @@ class ActionsService(FolderContext, BaseService):
382
386
 
383
387
  spec = _retrieve_app_key_spec(app_name=app_name)
384
388
 
385
- response = self.request_org_scope(
386
- spec.method, spec.endpoint, params=spec.params, headers=spec.headers
389
+ response = self.request(
390
+ spec.method,
391
+ spec.endpoint,
392
+ params=spec.params,
393
+ headers=spec.headers,
394
+ scoped="org",
387
395
  )
388
396
 
389
397
  try:
@@ -28,7 +28,7 @@ class ApiClient(FolderContext, BaseService):
28
28
  ) -> Response:
29
29
  if kwargs.get("include_folder_headers", False):
30
30
  kwargs["headers"] = {
31
- **kwargs.get("headers", self._tenant_scope_client.headers),
31
+ **kwargs.get("headers", self._client.headers),
32
32
  **self.folder_headers,
33
33
  }
34
34
 
@@ -45,7 +45,7 @@ class ApiClient(FolderContext, BaseService):
45
45
  ) -> Response:
46
46
  if kwargs.get("include_folder_headers", False):
47
47
  kwargs["headers"] = {
48
- **kwargs.get("headers", self._tenant_scope_client_async.headers),
48
+ **kwargs.get("headers", self._client_async.headers),
49
49
  **self.folder_headers,
50
50
  }
51
51
 
@@ -53,37 +53,3 @@ class ApiClient(FolderContext, BaseService):
53
53
  del kwargs["include_folder_headers"]
54
54
 
55
55
  return await super().request_async(method, url, **kwargs)
56
-
57
- def request_org_scope(
58
- self,
59
- method: str,
60
- url: Union[URL, str],
61
- **kwargs: Any,
62
- ) -> Response:
63
- if kwargs.get("include_folder_headers", False):
64
- kwargs["headers"] = {
65
- **kwargs.get("headers", self._org_scope_client.headers),
66
- **self.folder_headers,
67
- }
68
-
69
- if "include_folder_headers" in kwargs:
70
- del kwargs["include_folder_headers"]
71
-
72
- return super().request_org_scope(method, url, **kwargs)
73
-
74
- async def request_org_scope_async(
75
- self,
76
- method: str,
77
- url: Union[URL, str],
78
- **kwargs: Any,
79
- ) -> Response:
80
- if kwargs.get("include_folder_headers", False):
81
- kwargs["headers"] = {
82
- **kwargs.get("headers", self._org_scope_client_async.headers),
83
- **self.folder_headers,
84
- }
85
-
86
- if "include_folder_headers" in kwargs:
87
- del kwargs["include_folder_headers"]
88
-
89
- return await super().request_org_scope_async(method, url, **kwargs)
@@ -7,7 +7,7 @@ from .._execution_context import ExecutionContext
7
7
  from .._folder_context import FolderContext
8
8
  from .._utils import Endpoint, RequestSpec, header_folder, infer_bindings
9
9
  from .._utils._read_overwrites import OverwritesManager, read_resource_overwrites
10
- from ..models import UserAsset
10
+ from ..models import Asset, UserAsset
11
11
  from ..tracing._traced import traced
12
12
  from ._base_service import BaseService
13
13
 
@@ -34,7 +34,7 @@ class AssetsService(FolderContext, BaseService):
34
34
  *,
35
35
  folder_key: Optional[str] = None,
36
36
  folder_path: Optional[str] = None,
37
- ) -> UserAsset:
37
+ ) -> UserAsset | Asset:
38
38
  """Retrieve an asset by its name.
39
39
 
40
40
  Related Activity: [Get Asset](https://docs.uipath.com/activities/other/latest/workflow/get-robot-asset)
@@ -56,6 +56,11 @@ class AssetsService(FolderContext, BaseService):
56
56
  client.assets.retrieve(name="MyAsset")
57
57
  ```
58
58
  """
59
+ try:
60
+ is_user = self._execution_context.robot_key is not None
61
+ except ValueError:
62
+ is_user = False
63
+
59
64
  with read_resource_overwrites("asset", name, folder_path) as (
60
65
  overwritten_name,
61
66
  overwritten_folder_path,
@@ -68,11 +73,15 @@ class AssetsService(FolderContext, BaseService):
68
73
  response = self.request(
69
74
  spec.method,
70
75
  url=spec.endpoint,
76
+ params=spec.params,
71
77
  content=spec.content,
72
78
  headers=spec.headers,
73
79
  )
74
80
 
75
- return UserAsset.model_validate(response.json())
81
+ if is_user:
82
+ return UserAsset.model_validate(response.json())
83
+ else:
84
+ return Asset.model_validate(response.json()["value"][0])
76
85
 
77
86
  @traced(
78
87
  name="assets_retrieve", run_type="uipath", hide_input=True, hide_output=True
@@ -83,7 +92,7 @@ class AssetsService(FolderContext, BaseService):
83
92
  *,
84
93
  folder_key: Optional[str] = None,
85
94
  folder_path: Optional[str] = None,
86
- ) -> UserAsset:
95
+ ) -> UserAsset | Asset:
87
96
  """Asynchronously retrieve an asset by its name.
88
97
 
89
98
  Related Activity: [Get Asset](https://docs.uipath.com/activities/other/latest/workflow/get-robot-asset)
@@ -96,6 +105,11 @@ class AssetsService(FolderContext, BaseService):
96
105
  Returns:
97
106
  UserAsset: The asset data.
98
107
  """
108
+ try:
109
+ is_user = self._execution_context.robot_key is not None
110
+ except ValueError:
111
+ is_user = False
112
+
99
113
  with read_resource_overwrites("asset", name, folder_path) as (
100
114
  overwritten_name,
101
115
  overwritten_folder_path,
@@ -108,11 +122,15 @@ class AssetsService(FolderContext, BaseService):
108
122
  response = await self.request_async(
109
123
  spec.method,
110
124
  url=spec.endpoint,
125
+ params=spec.params,
111
126
  content=spec.content,
112
127
  headers=spec.headers,
113
128
  )
114
129
 
115
- return UserAsset.model_validate(response.json())
130
+ if is_user:
131
+ return UserAsset.model_validate(response.json())
132
+ else:
133
+ return Asset.model_validate(response.json()["value"][0])
116
134
 
117
135
  @infer_bindings()
118
136
  @traced(
@@ -138,7 +156,18 @@ class AssetsService(FolderContext, BaseService):
138
156
 
139
157
  Returns:
140
158
  Optional[str]: The decrypted credential password.
159
+
160
+ Raises:
161
+ ValueError: If the method is called for a user asset.
141
162
  """
163
+ try:
164
+ is_user = self._execution_context.robot_key is not None
165
+ except ValueError:
166
+ is_user = False
167
+
168
+ if not is_user:
169
+ raise ValueError("This method can only be used for robot assets.")
170
+
142
171
  with read_resource_overwrites("asset", name, folder_path) as (
143
172
  overwritten_name,
144
173
  overwritten_folder_path,
@@ -185,7 +214,17 @@ class AssetsService(FolderContext, BaseService):
185
214
  Returns:
186
215
  Optional[str]: The decrypted credential password.
187
216
 
217
+ Raises:
218
+ ValueError: If the method is called for a user asset.
188
219
  """
220
+ try:
221
+ is_user = self._execution_context.robot_key is not None
222
+ except ValueError:
223
+ is_user = False
224
+
225
+ if not is_user:
226
+ raise ValueError("This method can only be used for robot assets.")
227
+
189
228
  with read_resource_overwrites("asset", name, folder_path) as (
190
229
  overwritten_name,
191
230
  overwritten_folder_path,
@@ -224,7 +263,18 @@ class AssetsService(FolderContext, BaseService):
224
263
 
225
264
  Returns:
226
265
  Response: The HTTP response confirming the update.
266
+
267
+ Raises:
268
+ ValueError: If the method is called for a user asset.
227
269
  """
270
+ try:
271
+ is_user = self._execution_context.robot_key is not None
272
+ except ValueError:
273
+ is_user = False
274
+
275
+ if not is_user:
276
+ raise ValueError("This method can only be used for robot assets.")
277
+
228
278
  with read_resource_overwrites("asset", robot_asset.name or "", folder_path) as (
229
279
  overwritten_name,
230
280
  overwritten_folder_path,
@@ -288,14 +338,29 @@ class AssetsService(FolderContext, BaseService):
288
338
  folder_key: Optional[str] = None,
289
339
  folder_path: Optional[str] = None,
290
340
  ) -> RequestSpec:
341
+ try:
342
+ robot_key = self._execution_context.robot_key
343
+ except ValueError:
344
+ robot_key = None
345
+
346
+ if robot_key is None:
347
+ return RequestSpec(
348
+ method="GET",
349
+ endpoint=Endpoint(
350
+ "/orchestrator_/odata/Assets/UiPath.Server.Configuration.OData.GetFiltered",
351
+ ),
352
+ params={"$filter": f"Name eq '{name}'", "$top": 1},
353
+ headers={
354
+ **header_folder(folder_key, folder_path),
355
+ },
356
+ )
357
+
291
358
  return RequestSpec(
292
359
  method="POST",
293
360
  endpoint=Endpoint(
294
361
  "/orchestrator_/odata/Assets/UiPath.Server.Configuration.OData.GetRobotAssetByNameForRobotKey"
295
362
  ),
296
- content=str(
297
- {"assetName": name, "robotKey": self._execution_context.robot_key}
298
- ),
363
+ content=str({"assetName": name, "robotKey": robot_key}),
299
364
  headers={
300
365
  **header_folder(folder_key, folder_path),
301
366
  },
@@ -55,7 +55,7 @@ class BucketsService(FolderContext, BaseService):
55
55
  name=name, key=key, folder_key=folder_key, folder_path=folder_path
56
56
  )
57
57
  spec = self._retrieve_readUri_spec(
58
- bucket, blob_file_path, folder_key=folder_key, folder_path=folder_path
58
+ bucket.id, blob_file_path, folder_key=folder_key, folder_path=folder_path
59
59
  )
60
60
  result = self.request(
61
61
  spec.method,
@@ -112,10 +112,8 @@ class BucketsService(FolderContext, BaseService):
112
112
  name=name, key=key, folder_key=folder_key, folder_path=folder_path
113
113
  )
114
114
 
115
- bucket_id = bucket["Id"]
116
-
117
115
  spec = self._retrieve_writeri_spec(
118
- bucket_id,
116
+ bucket.id,
119
117
  content_type,
120
118
  blob_file_path,
121
119
  folder_key=folder_key,
@@ -175,10 +173,8 @@ class BucketsService(FolderContext, BaseService):
175
173
  name=name, key=key, folder_key=folder_key, folder_path=folder_path
176
174
  )
177
175
 
178
- bucket_id = bucket["Id"]
179
-
180
176
  spec = self._retrieve_writeri_spec(
181
- bucket_id,
177
+ bucket.id,
182
178
  content_type,
183
179
  blob_file_path,
184
180
  folder_key=folder_key,
@@ -245,10 +241,9 @@ class BucketsService(FolderContext, BaseService):
245
241
  bucket = self.retrieve(
246
242
  name=name, key=key, folder_key=folder_key, folder_path=folder_path
247
243
  )
248
- bucket_id = bucket["Id"]
249
244
 
250
245
  spec = self._retrieve_writeri_spec(
251
- bucket_id,
246
+ bucket.id,
252
247
  content_type,
253
248
  blob_file_path,
254
249
  folder_key=folder_key,
@@ -262,6 +262,6 @@ class JobsService(FolderContext, BaseService):
262
262
  return RequestSpec(
263
263
  method="GET",
264
264
  endpoint=Endpoint(
265
- f"orchestrator_/odata/Jobs/UiPath.Server.Configuration.OData.GetByKey(identifier={job_key})"
265
+ f"/orchestrator_/odata/Jobs/UiPath.Server.Configuration.OData.GetByKey(identifier={job_key})"
266
266
  ),
267
267
  )
uipath/_uipath.py CHANGED
@@ -26,7 +26,7 @@ from ._utils.constants import (
26
26
  )
27
27
  from .models.errors import BaseUrlMissingError, SecretMissingError
28
28
 
29
- load_dotenv()
29
+ load_dotenv(override=True)
30
30
 
31
31
 
32
32
  class UiPath:
uipath/_utils/__init__.py CHANGED
@@ -3,6 +3,7 @@ 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
6
+ from ._url import UiPathUrl
6
7
  from ._user_agent import header_user_agent, user_agent_value
7
8
 
8
9
  __all__ = [
@@ -14,4 +15,5 @@ __all__ = [
14
15
  "infer_bindings",
15
16
  "header_user_agent",
16
17
  "user_agent_value",
18
+ "UiPathUrl",
17
19
  ]
@@ -10,9 +10,9 @@ def header_folder(
10
10
  raise ValueError("Only one of folder_key or folder_path can be provided")
11
11
 
12
12
  headers = {}
13
- if folder_key is not None:
13
+ if folder_key is not None and folder_key != "":
14
14
  headers[HEADER_FOLDER_KEY] = folder_key
15
- if folder_path is not None:
15
+ if folder_path is not None and folder_path != "":
16
16
  headers[HEADER_FOLDER_PATH] = folder_path
17
17
 
18
18
  return headers
uipath/_utils/_url.py ADDED
@@ -0,0 +1,85 @@
1
+ from typing import Literal
2
+ from urllib.parse import urlparse
3
+
4
+
5
+ class UiPathUrl:
6
+ """A class that represents a UiPath URL.
7
+
8
+ This class is used to parse and manipulate UiPath URLs.
9
+
10
+ >>> url = UiPathUrl("https://test.uipath.com/org/tenant")
11
+ >>> url.base_url
12
+ 'https://test.uipath.com'
13
+ >>> url.org_name
14
+ 'org'
15
+ >>> url.tenant_name
16
+ 'tenant'
17
+
18
+ Args:
19
+ url (str): The URL to parse.
20
+ """
21
+
22
+ def __init__(self, url: str):
23
+ self._url = url
24
+
25
+ def __str__(self):
26
+ return self._url
27
+
28
+ def __repr__(self):
29
+ return f"UiPathUrl({self._url})"
30
+
31
+ def __eq__(self, other: object):
32
+ if not isinstance(other, UiPathUrl):
33
+ return NotImplemented
34
+
35
+ return self._url == str(other)
36
+
37
+ def __ne__(self, other: object):
38
+ if not isinstance(other, UiPathUrl):
39
+ return NotImplemented
40
+
41
+ return self._url != str(other)
42
+
43
+ def __hash__(self):
44
+ return hash(self._url)
45
+
46
+ @property
47
+ def base_url(self):
48
+ parsed = urlparse(self._url)
49
+
50
+ return f"{parsed.scheme}://{parsed.hostname}{f':{parsed.port}' if parsed.port else ''}"
51
+
52
+ @property
53
+ def org_name(self):
54
+ return self._org_tenant_names[0]
55
+
56
+ @property
57
+ def tenant_name(self):
58
+ return self._org_tenant_names[1]
59
+
60
+ def scope_url(self, url: str, scoped: Literal["org", "tenant"] = "tenant") -> str:
61
+ if not self._is_relative_url(url):
62
+ return url
63
+
64
+ parts = [self.org_name]
65
+ if scoped == "tenant":
66
+ parts.append(self.tenant_name)
67
+ parts.append(url.strip("/"))
68
+
69
+ return "/".join(parts)
70
+
71
+ @property
72
+ def _org_tenant_names(self):
73
+ parsed = urlparse(self._url)
74
+
75
+ try:
76
+ org_name, tenant_name = parsed.path.strip("/").split("/")
77
+ except ValueError:
78
+ return "", ""
79
+
80
+ return org_name, tenant_name
81
+
82
+ def _is_relative_url(self, url: str) -> bool:
83
+ parsed = urlparse(url)
84
+
85
+ return parsed.hostname is None and parsed.path == url
@@ -9,7 +9,7 @@ ENV_JOB_ID = "UIPATH_JOB_ID"
9
9
  ENV_ROBOT_KEY = "UIPATH_ROBOT_KEY"
10
10
  ENV_TENANT_ID = "UIPATH_TENANT_ID"
11
11
  ENV_ORGANIZATION_ID = "UIPATH_ORGANIZATION_ID"
12
- ENV_TELEMETRY_ENABLED = "TELEMETRY_ENABLED"
12
+ ENV_TELEMETRY_ENABLED = "UIPATH_TELEMETRY_ENABLED"
13
13
 
14
14
  # Headers
15
15
  HEADER_FOLDER_KEY = "x-uipath-folderkey"
uipath/models/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from .action_schema import ActionSchema
2
2
  from .actions import Action
3
- from .assets import UserAsset
3
+ from .assets import Asset, UserAsset
4
4
  from .buckets import Bucket
5
5
  from .connections import Connection, ConnectionToken
6
6
  from .context_grounding import ContextGroundingQueryResponse
@@ -25,6 +25,7 @@ from .queues import (
25
25
 
26
26
  __all__ = [
27
27
  "Action",
28
+ "Asset",
28
29
  "UserAsset",
29
30
  "ContextGroundingQueryResponse",
30
31
  "ContextGroundingIndex",
uipath/models/assets.py CHANGED
@@ -46,3 +46,25 @@ class UserAsset(BaseModel):
46
46
  default=None, alias="ConnectionData"
47
47
  )
48
48
  id: Optional[int] = Field(default=None, alias="Id")
49
+
50
+
51
+ class Asset(BaseModel):
52
+ model_config = ConfigDict(
53
+ validate_by_name=True,
54
+ validate_by_alias=True,
55
+ use_enum_values=True,
56
+ arbitrary_types_allowed=True,
57
+ extra="allow",
58
+ )
59
+ key: Optional[str] = Field(default=None, alias="Key")
60
+ description: Optional[str] = Field(default=None, alias="Description")
61
+ name: Optional[str] = Field(default=None, alias="Name")
62
+ value: Optional[str] = Field(default=None, alias="Value")
63
+ value_type: Optional[str] = Field(default=None, alias="ValueType")
64
+ string_value: Optional[str] = Field(default=None, alias="StringValue")
65
+ bool_value: Optional[bool] = Field(default=None, alias="BoolValue")
66
+ int_value: Optional[int] = Field(default=None, alias="IntValue")
67
+ credential_username: Optional[str] = Field(default=None, alias="CredentialUsername")
68
+ credential_password: Optional[str] = Field(default=None, alias="CredentialPassword")
69
+ external_name: Optional[str] = Field(default=None, alias="ExternalName")
70
+ credential_store_id: Optional[int] = Field(default=None, alias="CredentialStoreId")
@@ -2,10 +2,15 @@ _CONNECTION_STRING = ""
2
2
 
3
3
  _APP_INSIGHTS_EVENT_MARKER_ATTRIBUTE = "APPLICATION_INSIGHTS_EVENT_MARKER_ATTRIBUTE"
4
4
  _OTEL_RESOURCE_ATTRIBUTES = "OTEL_RESOURCE_ATTRIBUTES"
5
- _SDK_VERSION = "SDK_VERSION"
5
+ _SDK_VERSION = "SdkVersion"
6
6
 
7
7
  _CODE_FILEPATH = "code.filepath"
8
8
  _CODE_FUNCTION = "code.function"
9
9
  _CODE_LINENO = "code.lineno"
10
10
 
11
- _UNKNOWN = "unknown"
11
+ _CLOUD_ORG_ID = "CloudOrganizationId"
12
+ _CLOUD_TENANT_ID = "CloudTenantId"
13
+ _CLOUD_URL = "CloudUrl"
14
+ _APP_NAME = "ApplicationName"
15
+
16
+ _UNKNOWN = ""
@@ -16,6 +16,10 @@ from .._utils.constants import (
16
16
  )
17
17
  from ._constants import (
18
18
  _APP_INSIGHTS_EVENT_MARKER_ATTRIBUTE,
19
+ _APP_NAME,
20
+ _CLOUD_ORG_ID,
21
+ _CLOUD_TENANT_ID,
22
+ _CLOUD_URL,
19
23
  _CODE_FILEPATH,
20
24
  _CODE_FUNCTION,
21
25
  _CODE_LINENO,
@@ -34,9 +38,10 @@ class _AzureMonitorOpenTelemetryEventHandler(LoggingHandler):
34
38
  def _get_attributes(record: LogRecord) -> Attributes:
35
39
  attributes = dict(LoggingHandler._get_attributes(record) or {})
36
40
  attributes[_APP_INSIGHTS_EVENT_MARKER_ATTRIBUTE] = True
37
- attributes[ENV_TENANT_ID] = os.getenv(ENV_TENANT_ID, _UNKNOWN)
38
- attributes[ENV_ORGANIZATION_ID] = os.getenv(ENV_ORGANIZATION_ID, _UNKNOWN)
39
- attributes[ENV_BASE_URL] = os.getenv(ENV_BASE_URL, _UNKNOWN)
41
+ attributes[_CLOUD_TENANT_ID] = os.getenv(ENV_TENANT_ID, _UNKNOWN)
42
+ attributes[_CLOUD_ORG_ID] = os.getenv(ENV_ORGANIZATION_ID, _UNKNOWN)
43
+ attributes[_CLOUD_URL] = os.getenv(ENV_BASE_URL, _UNKNOWN)
44
+ attributes[_APP_NAME] = "UiPath.Sdk"
40
45
  attributes[_SDK_VERSION] = version("uipath")
41
46
 
42
47
  if _CODE_FILEPATH in attributes:
@@ -87,7 +92,7 @@ class _TelemetryClient:
87
92
 
88
93
  _TelemetryClient._initialize()
89
94
 
90
- _logger.info(name, extra=attrs)
95
+ _logger.info(f"Sdk.{name.capitalize()}", extra=attrs)
91
96
 
92
97
 
93
98
  def track(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath
3
- Version: 2.0.52
3
+ Version: 2.0.54
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,22 +1,22 @@
1
1
  uipath/__init__.py,sha256=IaeKItOOQXMa95avueJ3dAq-XcRHyZVNjcCGwlSB000,634
2
2
  uipath/_config.py,sha256=pi3qxPzDTxMEstj_XkGOgKJqD6RTHHv7vYv8sS_-d5Q,92
3
- uipath/_execution_context.py,sha256=JkmMH51ck4p-JQtgJeDvpBP-BZNIN_1h3Qlo8QrPr-w,2421
4
- uipath/_folder_context.py,sha256=oxX7o8ilU9sA_vEKLr2sZZCHnvRwJ0_as-LOMc4hxc4,1908
5
- uipath/_uipath.py,sha256=6gBDQWyh3u6Nc1q306DERjS_oCKn0VwrfFLaPJqwfYA,3650
3
+ uipath/_execution_context.py,sha256=XyfEcdPN-PmM97yO7OVS8Do28N-vpTnQPJrkp8pEpRA,2434
4
+ uipath/_folder_context.py,sha256=UMMoU1VWEfYHAZW3Td2SIFYhw5dYsmaaKFhW_JEm6oc,1921
5
+ uipath/_uipath.py,sha256=mx2L_e7gBm1UI-Q3HQ-GKV55KK4eGi8w3EPpUG2ZWVM,3663
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=vGz3vJHkUvgK9_lKdzqiwwHkge1TCALRiOzGGwyr-8E,1885
9
- uipath/_cli/cli_auth.py,sha256=kbZzJ6wLcHM1nlqaEZDGHuMJmhlYxxY_yt1OR_DbdbE,3955
9
+ uipath/_cli/cli_auth.py,sha256=mIavWQ2zG3hWbjDxTVyGlHKq165liaI2Texbb1kHsTE,3968
10
10
  uipath/_cli/cli_deploy.py,sha256=KPCmQ0c_NYD5JofSDao5r6QYxHshVCRxlWDVnQvlp5w,645
11
11
  uipath/_cli/cli_init.py,sha256=6qIjGFwfmeDs_7yzDqfl4zdnpDzlIjPAth0dY7kAP04,3736
12
- uipath/_cli/cli_invoke.py,sha256=k_T5IG5vm1uO_WEphmV-cMl5Weu04HDNnvGCmSSDQK4,3799
12
+ uipath/_cli/cli_invoke.py,sha256=IjndcDWBpvAqGCRanQU1vfmxaBF8FhyZ7gWuZqwjHrU,3812
13
13
  uipath/_cli/cli_new.py,sha256=9378NYUBc9j-qKVXV7oja-jahfJhXBg8zKVyaon7ctY,2102
14
14
  uipath/_cli/cli_pack.py,sha256=8Ahk0vr_8eqMsq9ehhYWNfeII0VIiZVBXMpRF7Dbvtg,15018
15
15
  uipath/_cli/cli_publish.py,sha256=Ba0TJ1TSfuQbLU2AIgtM8QWkLHgr4tsAP1CaX12113U,6010
16
- uipath/_cli/cli_run.py,sha256=CoXx7lKUCq-wbACT5mJByx3FGc1GGe-m40nDt4qGa64,5215
16
+ uipath/_cli/cli_run.py,sha256=XS8IsfnS9d9zxl7rjUWVFsRWjuQTtO48H1EYFR_5CMc,5228
17
17
  uipath/_cli/middlewares.py,sha256=IiJgjsqrJVKSXx4RcIKHWoH-SqWqpHPbhzkQEybmAos,3937
18
18
  uipath/_cli/spinner.py,sha256=bS-U_HA5yne11ejUERu7CQoXmWdabUD2bm62EfEdV8M,1107
19
- uipath/_cli/_auth/_auth_server.py,sha256=GRdjXUcvZO2O2GecolFJ8uMv7_DUD_VXeBJpElqmtIQ,7034
19
+ uipath/_cli/_auth/_auth_server.py,sha256=W0KabhR-RB_uUqGX2dyNM0Juvrh-TABW3A-1cEom3uM,7047
20
20
  uipath/_cli/_auth/_models.py,sha256=sYMCfvmprIqnZxStlD_Dxx2bcxgn0Ri4D7uwemwkcNg,948
21
21
  uipath/_cli/_auth/_oidc_utils.py,sha256=WaX9jDlXrlX6yD8i8gsocV8ngjaT72Xd1tvsZMmSbco,2127
22
22
  uipath/_cli/_auth/_portal_service.py,sha256=80W0cn3rx6NEi_b15aSQ0ZQWFv7Om7SaOlkUUk2k7pA,7240
@@ -40,31 +40,32 @@ uipath/_cli/_utils/_input_args.py,sha256=pyQhEcQXHdFHYTVNzvfWp439aii5StojoptnmCv
40
40
  uipath/_cli/_utils/_parse_ast.py,sha256=3XVjnhJNnSfjXlitct91VOtqSl0l-sqDpoWww28mMc0,20663
41
41
  uipath/_cli/_utils/_processes.py,sha256=iCGNf1y_K_r3bdmX9VWA70UP20bdUzKlMRrAxkdkdm4,1669
42
42
  uipath/_services/__init__.py,sha256=VPbwLDsvN26nWZgvR-8_-tc3i0rk5doqjTJbSrK0nN4,818
43
- uipath/_services/_base_service.py,sha256=i4f-4rkORhEIa6EWiSBUGlfFftAqKrRdjcV7fCGBYSY,8246
44
- uipath/_services/actions_service.py,sha256=DaWXbbLHVC-bVtxhMBm3Zfhx6IP8s9mviOTgK5g_CAQ,15883
45
- uipath/_services/api_client.py,sha256=1hYLc_90dQzCGnqqirEHpPqvL3Gkv2sSKoeOV_iTmlk,2903
46
- uipath/_services/assets_service.py,sha256=TXuL8dHCVLHb3AC2QixrwGz0Rjs70GHKTKg-S20sA_U,11115
47
- uipath/_services/buckets_service.py,sha256=VfgupGPeOFH3kBG6LJa7cWkliOuVBgdSEfApnKOcoM4,17619
43
+ uipath/_services/_base_service.py,sha256=y-QATIRF9JnUFKIwmjOWMHlE2BrJYgD8y4sGAve2kEM,5338
44
+ uipath/_services/actions_service.py,sha256=LYKvG4VxNGQgZ46AzGK9kI1Txb-YmVvZj5ScPOue8Ls,15989
45
+ uipath/_services/api_client.py,sha256=hcof0EMa4-phEHD1WlO7Tdfzq6aL18Sbi2aBE7lJm1w,1821
46
+ uipath/_services/assets_service.py,sha256=gfQLCchT6evsmhip1-coX6oFbshoKUWlxwGrS6DGcHU,13200
47
+ uipath/_services/buckets_service.py,sha256=xTIAEs7EbpyZYqd7PG1q0emOOBM_Ca0rVoH417g2bl0,17521
48
48
  uipath/_services/connections_service.py,sha256=qh-HNL_GJsyPUD0wSJZRF8ZdrTE9l4HrIilmXGK6dDk,4581
49
49
  uipath/_services/context_grounding_service.py,sha256=wRYPnpTFeZunS88OggRZ9qRaILHKdoEP_6VUCaF-Xw0,24097
50
50
  uipath/_services/folder_service.py,sha256=HtsBoBejvMuIZ-9gocAG9B8uKOFsAAD4WUozta-isXk,1673
51
- uipath/_services/jobs_service.py,sha256=MsJlu1egvHKZhHdammp4Xo9iJzceWquW4qIWT-nPBws,8214
51
+ uipath/_services/jobs_service.py,sha256=_i3op3Xo3mdQdma7AbGQI35NVwj85B4idAHFZ12C_oI,8215
52
52
  uipath/_services/llm_gateway_service.py,sha256=ySg3sflIoXmY9K7txlSm7bkuI2qzBT0kAKmGlFBk5KA,12032
53
53
  uipath/_services/processes_service.py,sha256=12tflrzTNvtA0xGteQwrIZ0s-jCTinTv7gktder5tRE,5659
54
54
  uipath/_services/queues_service.py,sha256=VaG3dWL2QK6AJBOLoW2NQTpkPfZjsqsYPl9-kfXPFzA,13534
55
- uipath/_utils/__init__.py,sha256=y8asYKjU5j3v72TbgShEpUafAAJXJ6bngqdzXIl-Lhk,481
55
+ uipath/_utils/__init__.py,sha256=VdcpnENJIa0R6Y26NoxY64-wUVyvb4pKfTh1wXDQeMk,526
56
56
  uipath/_utils/_endpoint.py,sha256=yYHwqbQuJIevpaTkdfYJS9CrtlFeEyfb5JQK5osTCog,2489
57
57
  uipath/_utils/_infer_bindings.py,sha256=ysAftopcCBj4ojYyeVwbSl20qYhCDmqyldCinj6sICM,905
58
58
  uipath/_utils/_logs.py,sha256=adfX_0UAn3YBeKJ8DQDeZs94rJyHGQO00uDfkaTpNWQ,510
59
59
  uipath/_utils/_read_overwrites.py,sha256=dODvjNnDjcYOxVKnt0KqqqXmysULLBObKaEF8gJteg4,5149
60
- uipath/_utils/_request_override.py,sha256=_vibG78vEDWS3JKg2cJ5l6tpoBMLChUOauiqL1ozFPc,530
60
+ uipath/_utils/_request_override.py,sha256=fIVHzgHVXITUlWcp8osNBwIafM1qm4_ejx0ng5UzfJ4,573
61
61
  uipath/_utils/_request_spec.py,sha256=iCtBLqtbWUpFG5g1wtIZBzSupKsfaRLiQFoFc_4B70Q,747
62
+ uipath/_utils/_url.py,sha256=2PnINXuEPbhd9mlojJJdupm-sOrgV29o5DbWuaFrc-0,2039
62
63
  uipath/_utils/_user_agent.py,sha256=pVJkFYacGwaQBomfwWVAvBQgdBUo62e4n3-fLIajWUU,563
63
- uipath/_utils/constants.py,sha256=6jtBwOXhf6LPM6fTNAf3rh--j6Ls2W5lIYieBTSLoQM,866
64
- uipath/models/__init__.py,sha256=tQF2CbEjmB_1sqL1lJrtVe3K2o8F0LKzzoXKiUUBqxc,1178
64
+ uipath/_utils/constants.py,sha256=CKv-kTC8Fzu6E_KY9jD_fSt0Gbycn9sZg4O_3pzq2fo,873
65
+ uipath/models/__init__.py,sha256=4851NXFml-lNumkjiiauGLlCb-yFViG2HX-NVh8Nt8Y,1198
65
66
  uipath/models/action_schema.py,sha256=lKDhP7Eix23fFvfQrqqNmSOiPyyNF6tiRpUu0VZIn_M,714
66
67
  uipath/models/actions.py,sha256=ekSH4YUQR4KPOH-heBm9yOgOfirndx0In4_S4VYWeEU,2993
67
- uipath/models/assets.py,sha256=8ZPImmJ-1u5KqdR1UBgZnGjSBW-Nr81Ruq_5Uav417A,1841
68
+ uipath/models/assets.py,sha256=Q-7_xmm503XHTKgCDrDtXsFl3VWBSVSyiWYW0mZjsnA,2942
68
69
  uipath/models/buckets.py,sha256=N3Lj_dVCv709-ywhOOdyCSvsuLn41eGuAfSiik6Q6F8,1285
69
70
  uipath/models/connections.py,sha256=perIqW99YEg_0yWZPdpZlmNpZcwY_toR1wkqDUBdAN0,2014
70
71
  uipath/models/context_grounding.py,sha256=S9PeOlFlw7VxzzJVR_Fs28OObW3MLHUPCFqNgkEz24k,1315
@@ -77,14 +78,14 @@ uipath/models/llm_gateway.py,sha256=0sl5Wtve94V14H3AHwmJSoXAhoc-Fai3wJxP8HrnBPg,
77
78
  uipath/models/processes.py,sha256=Atvfrt6X4TYST3iA62jpS_Uxc3hg6uah11p-RaKZ6dk,2029
78
79
  uipath/models/queues.py,sha256=N_s0GKucbyjh0RnO8SxPk6wlRgvq8KIIYsfaoIY46tM,6446
79
80
  uipath/telemetry/__init__.py,sha256=Wna32UFzZR66D-RzTKlPWlvji9i2HJb82NhHjCCXRjY,61
80
- uipath/telemetry/_constants.py,sha256=wULKBQDsr_wcc6Hl3lWLMughrPn48S7zGmTOMiESz3I,312
81
- uipath/telemetry/_track.py,sha256=N2KHCXNaC7nsxI2oqHj8zYkBqyMJSNkadek53TmL_og,3738
81
+ uipath/telemetry/_constants.py,sha256=UftH_cYzB260IwlDOafDJHYRbIUXL6_K0rdavG6cxjM,432
82
+ uipath/telemetry/_track.py,sha256=v0e3hgwtetMsUco4yosBzNU00Ek5SI9RxUTumrTTNyo,3872
82
83
  uipath/tracing/__init__.py,sha256=GimSzv6qkCOlHOG1WtjYKJsZqcXpA28IgoXfR33JhiA,139
83
84
  uipath/tracing/_otel_exporters.py,sha256=x0PDPmDKJcxashsuehVsSsqBCzRr6WsNFaq_3_HS5F0,3014
84
85
  uipath/tracing/_traced.py,sha256=GFxOp73jk0vGTN_H7YZOOsEl9rVLaEhXGztMiYKIA-8,16634
85
86
  uipath/tracing/_utils.py,sha256=5SwsTGpHkIouXBndw-u8eCLnN4p7LM8DsTCCuf2jJgs,10165
86
- uipath-2.0.52.dist-info/METADATA,sha256=dCTRBp4flmPG4H5CPIV06TF6ENiCBy-a4lGOT3ZN6AU,6304
87
- uipath-2.0.52.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
88
- uipath-2.0.52.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
89
- uipath-2.0.52.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
90
- uipath-2.0.52.dist-info/RECORD,,
87
+ uipath-2.0.54.dist-info/METADATA,sha256=cEs9a2B8OKtGc7iE2247tX1ihUFr8Z8BwdmA05Q5UU8,6304
88
+ uipath-2.0.54.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
89
+ uipath-2.0.54.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
90
+ uipath-2.0.54.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
91
+ uipath-2.0.54.dist-info/RECORD,,