uipath 2.1.49__py3-none-any.whl → 2.1.51__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.
@@ -5,6 +5,7 @@ from .attachments_service import AttachmentsService
5
5
  from .buckets_service import BucketsService
6
6
  from .connections_service import ConnectionsService
7
7
  from .context_grounding_service import ContextGroundingService
8
+ from .entities_service import EntitiesService
8
9
  from .folder_service import FolderService
9
10
  from .jobs_service import JobsService
10
11
  from .llm_gateway_service import UiPathLlmChatService, UiPathOpenAIService
@@ -25,4 +26,5 @@ __all__ = [
25
26
  "UiPathOpenAIService",
26
27
  "UiPathLlmChatService",
27
28
  "FolderService",
29
+ "EntitiesService",
28
30
  ]
@@ -1,4 +1,3 @@
1
- import json
2
1
  from typing import Any, List, Optional, Tuple, Union
3
2
 
4
3
  import httpx
@@ -353,7 +352,7 @@ class ContextGroundingService(FolderContext, BaseService):
353
352
  response = self.request(
354
353
  spec.method,
355
354
  spec.endpoint,
356
- content=spec.content,
355
+ json=spec.json,
357
356
  )
358
357
 
359
358
  return TypeAdapter(List[ContextGroundingQueryResponse]).validate_python(
@@ -403,7 +402,7 @@ class ContextGroundingService(FolderContext, BaseService):
403
402
  response = await self.request_async(
404
403
  spec.method,
405
404
  spec.endpoint,
406
- content=spec.content,
405
+ json=spec.json,
407
406
  )
408
407
 
409
408
  return TypeAdapter(List[ContextGroundingQueryResponse]).validate_python(
@@ -592,21 +591,19 @@ class ContextGroundingService(FolderContext, BaseService):
592
591
  return RequestSpec(
593
592
  method="POST",
594
593
  endpoint=Endpoint("/ecs_/v2/indexes/create"),
595
- content=json.dumps(
596
- {
597
- "name": name,
598
- "description": description,
599
- "dataSource": {
600
- "@odata.type": ORCHESTRATOR_STORAGE_BUCKET_DATA_SOURCE,
601
- "folder": storage_bucket_folder_path,
602
- "bucketName": storage_bucket_name,
603
- "fileNameGlob": file_name_glob
604
- if file_name_glob is not None
605
- else "*",
606
- "directoryPath": "/",
607
- },
608
- }
609
- ),
594
+ json={
595
+ "name": name,
596
+ "description": description,
597
+ "dataSource": {
598
+ "@odata.type": ORCHESTRATOR_STORAGE_BUCKET_DATA_SOURCE,
599
+ "folder": storage_bucket_folder_path,
600
+ "bucketName": storage_bucket_name,
601
+ "fileNameGlob": file_name_glob
602
+ if file_name_glob is not None
603
+ else "*",
604
+ "directoryPath": "/",
605
+ },
606
+ },
610
607
  headers={
611
608
  **header_folder(folder_key, None),
612
609
  },
@@ -657,12 +654,10 @@ class ContextGroundingService(FolderContext, BaseService):
657
654
  return RequestSpec(
658
655
  method="POST",
659
656
  endpoint=Endpoint("/ecs_/v1/search"),
660
- content=json.dumps(
661
- {
662
- "query": {"query": query, "numberOfResults": number_of_results},
663
- "schema": {"name": name},
664
- }
665
- ),
657
+ json={
658
+ "query": {"query": query, "numberOfResults": number_of_results},
659
+ "schema": {"name": name},
660
+ },
666
661
  headers={
667
662
  **header_folder(folder_key, None),
668
663
  },
@@ -0,0 +1,383 @@
1
+ from typing import Any, List, Optional, Type
2
+
3
+ from httpx import Response
4
+
5
+ from .._config import Config
6
+ from .._execution_context import ExecutionContext
7
+ from .._utils import Endpoint, RequestSpec
8
+ from ..models.entities import (
9
+ Entity,
10
+ EntityRecord,
11
+ EntityRecordsBatchResponse,
12
+ )
13
+ from ..tracing import traced
14
+ from ._base_service import BaseService
15
+
16
+
17
+ class EntitiesService(BaseService):
18
+ """Service for managing UiPath Data Service entities.
19
+
20
+ Entities are database tables in UiPath Data Service that can store
21
+ structured data for automation processes.
22
+ """
23
+
24
+ def __init__(self, config: Config, execution_context: ExecutionContext) -> None:
25
+ super().__init__(config=config, execution_context=execution_context)
26
+
27
+ @traced(name="entity_retrieve", run_type="uipath")
28
+ def retrieve(self, entity_key: str) -> Entity:
29
+ """Retrieve an entity by its key.
30
+
31
+ Args:
32
+ entity_key (str): The unique key/identifier of the entity.
33
+
34
+ Returns:
35
+ Entity: The entity with all its metadata and field definitions.
36
+ """
37
+ spec = self._retrieve_spec(entity_key)
38
+ response = self.request(spec.method, spec.endpoint)
39
+
40
+ return Entity.model_validate(response.json())
41
+
42
+ @traced(name="entity_retrieve", run_type="uipath")
43
+ async def retrieve_async(self, entity_key: str) -> Entity:
44
+ """Asynchronously retrieve an entity by its key.
45
+
46
+ Args:
47
+ entity_key (str): The unique key/identifier of the entity.
48
+
49
+ Returns:
50
+ Entity: The entity with all its metadata and field definitions.
51
+ """
52
+ spec = self._retrieve_spec(entity_key)
53
+
54
+ response = await self.request_async(spec.method, spec.endpoint)
55
+
56
+ return Entity.model_validate(response.json())
57
+
58
+ @traced(name="list_entities", run_type="uipath")
59
+ def list_entities(self) -> List[Entity]:
60
+ """List all entities in the Data Service.
61
+
62
+ Returns:
63
+ List[Entity]: A list of all entities with their metadata and field definitions.
64
+ """
65
+ spec = self._list_entities_spec()
66
+ response = self.request(spec.method, spec.endpoint)
67
+
68
+ entities_data = response.json()
69
+ return [Entity.model_validate(entity) for entity in entities_data]
70
+
71
+ @traced(name="list_entities", run_type="uipath")
72
+ async def list_entities_async(self) -> List[Entity]:
73
+ """Asynchronously list all entities in the Data Service.
74
+
75
+ Returns:
76
+ List[Entity]: A list of all entities with their metadata and field definitions.
77
+ """
78
+ spec = self._list_entities_spec()
79
+ response = await self.request_async(spec.method, spec.endpoint)
80
+
81
+ entities_data = response.json()
82
+ return [Entity.model_validate(entity) for entity in entities_data]
83
+
84
+ @traced(name="entity_list_records", run_type="uipath")
85
+ def list_records(
86
+ self,
87
+ entity_key: str,
88
+ schema: Optional[Type[Any]] = None, # Optional schema
89
+ start: Optional[int] = None,
90
+ limit: Optional[int] = None,
91
+ ) -> List[EntityRecord]:
92
+ """List records from an entity with optional pagination and schema validation.
93
+
94
+ Args:
95
+ entity_key (str): The unique key/identifier of the entity.
96
+ schema (Optional[Type[Any]]): Optional schema class for additional validation of records.
97
+ start (Optional[int]): Starting index for pagination.
98
+ limit (Optional[int]): Maximum number of records to return.
99
+
100
+ Returns:
101
+ List[EntityRecord]: A list of entity records.
102
+ """
103
+ # Example method to generate the API request specification (mocked here)
104
+ spec = self._list_records_spec(entity_key, start, limit)
105
+
106
+ # Make the HTTP request (assumes self.request exists)
107
+ response = self.request(spec.method, spec.endpoint, params=spec.params)
108
+
109
+ # Parse the response JSON and extract the "value" field
110
+ records_data = response.json().get("value", [])
111
+
112
+ # Validate and wrap records
113
+ return [
114
+ EntityRecord.from_data(data=record, model=schema) for record in records_data
115
+ ]
116
+
117
+ @traced(name="entity_list_records", run_type="uipath")
118
+ async def list_records_async(
119
+ self,
120
+ entity_key: str,
121
+ schema: Optional[Type[Any]] = None, # Optional schema
122
+ start: Optional[int] = None,
123
+ limit: Optional[int] = None,
124
+ ) -> List[EntityRecord]:
125
+ """Asynchronously list records from an entity with optional pagination and schema validation.
126
+
127
+ Args:
128
+ entity_key (str): The unique key/identifier of the entity.
129
+ schema (Optional[Type[Any]]): Optional schema class for additional validation of records.
130
+ start (Optional[int]): Starting index for pagination.
131
+ limit (Optional[int]): Maximum number of records to return.
132
+
133
+ Returns:
134
+ List[EntityRecord]: A list of entity records.
135
+ """
136
+ spec = self._list_records_spec(entity_key, start, limit)
137
+
138
+ # Make the HTTP request (assumes self.request exists)
139
+ response = await self.request_async(
140
+ spec.method, spec.endpoint, params=spec.params
141
+ )
142
+
143
+ # Parse the response JSON and extract the "value" field
144
+ records_data = response.json().get("value", [])
145
+
146
+ # Validate and wrap records
147
+ return [
148
+ EntityRecord.from_data(data=record, model=schema) for record in records_data
149
+ ]
150
+
151
+ @traced(name="entity_record_insert_batch", run_type="uipath")
152
+ def insert_records(
153
+ self,
154
+ entity_key: str,
155
+ records: List[Any],
156
+ schema: Optional[Type[Any]] = None,
157
+ ) -> EntityRecordsBatchResponse:
158
+ """Insert multiple records into an entity in a single batch operation.
159
+
160
+ Args:
161
+ entity_key (str): The unique key/identifier of the entity.
162
+ records (List[Any]): List of records to insert.
163
+ schema (Optional[Type[Any]]): Optional schema class for validation of records.
164
+
165
+ Returns:
166
+ EntityRecordsBatchResponse: Response containing successful and failed record operations.
167
+ """
168
+ spec = self._insert_batch_spec(entity_key, records)
169
+ response = self.request(spec.method, spec.endpoint, json=spec.json)
170
+
171
+ return self.validate_entity_batch(response, schema)
172
+
173
+ @traced(name="entity_record_insert_batch", run_type="uipath")
174
+ async def insert_records_async(
175
+ self,
176
+ entity_key: str,
177
+ records: List[Any],
178
+ schema: Optional[Type[Any]] = None,
179
+ ) -> EntityRecordsBatchResponse:
180
+ """Asynchronously insert multiple records into an entity in a single batch operation.
181
+
182
+ Args:
183
+ entity_key (str): The unique key/identifier of the entity.
184
+ records (List[Any]): List of records to insert.
185
+ schema (Optional[Type[Any]]): Optional schema class for validation of records.
186
+
187
+ Returns:
188
+ EntityRecordsBatchResponse: Response containing successful and failed record operations.
189
+ """
190
+ spec = self._insert_batch_spec(entity_key, records)
191
+ response = await self.request_async(spec.method, spec.endpoint, json=spec.json)
192
+
193
+ return self.validate_entity_batch(response, schema)
194
+
195
+ @traced(name="entity_record_update_batch", run_type="uipath")
196
+ def update_records(
197
+ self,
198
+ entity_key: str,
199
+ records: List[Any],
200
+ schema: Optional[Type[Any]] = None,
201
+ ) -> EntityRecordsBatchResponse:
202
+ """Update multiple records in an entity in a single batch operation.
203
+
204
+ Args:
205
+ entity_key (str): The unique key/identifier of the entity.
206
+ records (List[Any]): List of records to update.
207
+ schema (Optional[Type[Any]]): Optional schema class for validation of records.
208
+
209
+ Returns:
210
+ EntityRecordsBatchResponse: Response containing successful and failed record operations.
211
+ """
212
+ valid_records = [
213
+ EntityRecord.from_data(data=record.model_dump(by_alias=True), model=schema)
214
+ for record in records
215
+ ]
216
+
217
+ spec = self._update_batch_spec(entity_key, valid_records)
218
+ response = self.request(spec.method, spec.endpoint, json=spec.json)
219
+
220
+ return self.validate_entity_batch(response, schema)
221
+
222
+ @traced(name="entity_record_update_batch", run_type="uipath")
223
+ async def update_records_async(
224
+ self,
225
+ entity_key: str,
226
+ records: List[Any],
227
+ schema: Optional[Type[Any]] = None,
228
+ ) -> EntityRecordsBatchResponse:
229
+ """Asynchronously update multiple records in an entity in a single batch operation.
230
+
231
+ Args:
232
+ entity_key (str): The unique key/identifier of the entity.
233
+ records (List[Any]): List of records to update.
234
+ schema (Optional[Type[Any]]): Optional schema class for validation of records.
235
+
236
+ Returns:
237
+ EntityRecordsBatchResponse: Response containing successful and failed record operations.
238
+ """
239
+ valid_records = [
240
+ EntityRecord.from_data(data=record.model_dump(by_alias=True), model=schema)
241
+ for record in records
242
+ ]
243
+
244
+ spec = self._update_batch_spec(entity_key, valid_records)
245
+ response = await self.request_async(spec.method, spec.endpoint, json=spec.json)
246
+
247
+ return self.validate_entity_batch(response, schema)
248
+
249
+ @traced(name="entity_record_delete_batch", run_type="uipath")
250
+ def delete_records(
251
+ self,
252
+ entity_key: str,
253
+ record_ids: List[str],
254
+ ) -> EntityRecordsBatchResponse:
255
+ """Delete multiple records from an entity in a single batch operation.
256
+
257
+ Args:
258
+ entity_key (str): The unique key/identifier of the entity.
259
+ record_ids (List[str]): List of record IDs to delete.
260
+
261
+ Returns:
262
+ EntityRecordsBatchResponse: Response containing successful and failed record operations.
263
+ """
264
+ spec = self._delete_batch_spec(entity_key, record_ids)
265
+ response = self.request(spec.method, spec.endpoint, json=spec.json)
266
+
267
+ delete_records_response = EntityRecordsBatchResponse.model_validate(
268
+ response.json()
269
+ )
270
+
271
+ return delete_records_response
272
+
273
+ @traced(name="entity_record_delete_batch", run_type="uipath")
274
+ async def delete_records_async(
275
+ self,
276
+ entity_key: str,
277
+ record_ids: List[str],
278
+ ) -> EntityRecordsBatchResponse:
279
+ """Asynchronously delete multiple records from an entity in a single batch operation.
280
+
281
+ Args:
282
+ entity_key (str): The unique key/identifier of the entity.
283
+ record_ids (List[str]): List of record IDs to delete.
284
+
285
+ Returns:
286
+ EntityRecordsBatchResponse: Response containing successful and failed record operations.
287
+ """
288
+ spec = self._delete_batch_spec(entity_key, record_ids)
289
+ response = await self.request_async(spec.method, spec.endpoint, json=spec.json)
290
+
291
+ delete_records_response = EntityRecordsBatchResponse.model_validate(
292
+ response.json()
293
+ )
294
+
295
+ return delete_records_response
296
+
297
+ def validate_entity_batch(
298
+ self,
299
+ batch_response: Response,
300
+ schema: Optional[Type[Any]] = None,
301
+ ) -> EntityRecordsBatchResponse:
302
+ # Validate the response format
303
+ insert_records_response = EntityRecordsBatchResponse.model_validate(
304
+ batch_response.json()
305
+ )
306
+
307
+ # Validate individual records
308
+ validated_successful_records = [
309
+ EntityRecord.from_data(
310
+ data=successful_record.model_dump(by_alias=True), model=schema
311
+ )
312
+ for successful_record in insert_records_response.success_records
313
+ ]
314
+
315
+ validated_failed_records = [
316
+ EntityRecord.from_data(
317
+ data=failed_record.model_dump(by_alias=True), model=schema
318
+ )
319
+ for failed_record in insert_records_response.failure_records
320
+ ]
321
+
322
+ return EntityRecordsBatchResponse(
323
+ success_records=validated_successful_records,
324
+ failure_records=validated_failed_records,
325
+ )
326
+
327
+ def _retrieve_spec(
328
+ self,
329
+ entity_key: str,
330
+ ) -> RequestSpec:
331
+ return RequestSpec(
332
+ method="GET",
333
+ endpoint=Endpoint(f"datafabric_/api/Entity/{entity_key}"),
334
+ )
335
+
336
+ def _list_entities_spec(self) -> RequestSpec:
337
+ return RequestSpec(
338
+ method="GET",
339
+ endpoint=Endpoint("datafabric_/api/Entity"),
340
+ )
341
+
342
+ def _list_records_spec(
343
+ self,
344
+ entity_key: str,
345
+ start: Optional[int] = None,
346
+ limit: Optional[int] = None,
347
+ ) -> RequestSpec:
348
+ return RequestSpec(
349
+ method="GET",
350
+ endpoint=Endpoint(
351
+ f"datafabric_/api/EntityService/entity/{entity_key}/read"
352
+ ),
353
+ params=({"start": start, "limit": limit}),
354
+ )
355
+
356
+ def _insert_batch_spec(self, entity_key: str, records: List[Any]) -> RequestSpec:
357
+ return RequestSpec(
358
+ method="POST",
359
+ endpoint=Endpoint(
360
+ f"datafabric_/api/EntityService/entity/{entity_key}/insert-batch"
361
+ ),
362
+ json=[record.__dict__ for record in records],
363
+ )
364
+
365
+ def _update_batch_spec(
366
+ self, entity_key: str, records: List[EntityRecord]
367
+ ) -> RequestSpec:
368
+ return RequestSpec(
369
+ method="POST",
370
+ endpoint=Endpoint(
371
+ f"datafabric_/api/EntityService/entity/{entity_key}/update-batch"
372
+ ),
373
+ json=[record.model_dump(by_alias=True) for record in records],
374
+ )
375
+
376
+ def _delete_batch_spec(self, entity_key: str, record_ids: List[str]) -> RequestSpec:
377
+ return RequestSpec(
378
+ method="POST",
379
+ endpoint=Endpoint(
380
+ f"datafabric_/api/EntityService/entity/{entity_key}/delete-batch"
381
+ ),
382
+ json=record_ids,
383
+ )
@@ -1,4 +1,3 @@
1
- import json
2
1
  import os
3
2
  import shutil
4
3
  import tempfile
@@ -81,7 +80,7 @@ class JobsService(FolderContext, BaseService):
81
80
  spec.method,
82
81
  url=spec.endpoint,
83
82
  headers=spec.headers,
84
- content=spec.content,
83
+ json=spec.json,
85
84
  )
86
85
 
87
86
  async def resume_async(
@@ -142,7 +141,7 @@ class JobsService(FolderContext, BaseService):
142
141
  spec.method,
143
142
  url=spec.endpoint,
144
143
  headers=spec.headers,
145
- content=spec.content,
144
+ json=spec.json,
146
145
  )
147
146
 
148
147
  @property
@@ -412,7 +411,7 @@ class JobsService(FolderContext, BaseService):
412
411
  endpoint=Endpoint(
413
412
  f"/orchestrator_/api/JobTriggers/DeliverPayload/{inbox_id}"
414
413
  ),
415
- content=json.dumps({"payload": payload}),
414
+ json={"payload": payload},
416
415
  headers={
417
416
  **header_folder(folder_key, folder_path),
418
417
  },
@@ -16,7 +16,6 @@ Classes:
16
16
  UiPathLlmChatService: Service using UiPath's normalized API format
17
17
  """
18
18
 
19
- import json
20
19
  from typing import Any, Dict, List, Optional, Union
21
20
 
22
21
  from pydantic import BaseModel
@@ -195,7 +194,7 @@ class UiPathOpenAIService(BaseService):
195
194
  response = await self.request_async(
196
195
  "POST",
197
196
  endpoint,
198
- content=json.dumps({"input": input}),
197
+ json={"input": input},
199
198
  params={"api-version": API_VERSION},
200
199
  headers=DEFAULT_LLM_HEADERS,
201
200
  )
@@ -322,7 +321,7 @@ class UiPathOpenAIService(BaseService):
322
321
  response = await self.request_async(
323
322
  "POST",
324
323
  endpoint,
325
- content=json.dumps(request_body),
324
+ json=request_body,
326
325
  params={"api-version": API_VERSION},
327
326
  headers=DEFAULT_LLM_HEADERS,
328
327
  )
@@ -534,7 +533,7 @@ class UiPathLlmChatService(BaseService):
534
533
  response = await self.request_async(
535
534
  "POST",
536
535
  endpoint,
537
- content=json.dumps(request_body),
536
+ json=request_body,
538
537
  params={"api-version": NORMALIZED_API_VERSION},
539
538
  headers=headers,
540
539
  )
uipath/_uipath.py CHANGED
@@ -13,6 +13,7 @@ from ._services import (
13
13
  BucketsService,
14
14
  ConnectionsService,
15
15
  ContextGroundingService,
16
+ EntitiesService,
16
17
  FolderService,
17
18
  JobsService,
18
19
  ProcessesService,
@@ -134,3 +135,7 @@ class UiPath:
134
135
  @property
135
136
  def llm(self) -> UiPathLlmChatService:
136
137
  return UiPathLlmChatService(self._config, self._execution_context)
138
+
139
+ @property
140
+ def entities(self) -> EntitiesService:
141
+ return EntitiesService(self._config, self._execution_context)