uipath 2.1.68__py3-none-any.whl → 2.1.69__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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "client_id": "36dea5b8-e8bb-423d-8e7b-c808df8f1c00",
3
3
  "redirect_uri": "http://localhost:__PY_REPLACE_PORT__/oidc/login",
4
- "scope": "offline_access ProcessMining OrchestratorApiUserAccess StudioWebBackend IdentityServerApi ConnectionService DataService DocumentUnderstanding EnterpriseContextService Directory JamJamApi LLMGateway LLMOps OMS RCS.FolderAuthorization TM.Projects TM.TestCases TM.Requirements TM.TestSets",
4
+ "scope": "offline_access ProcessMining OrchestratorApiUserAccess StudioWebBackend IdentityServerApi ConnectionService DataService DocumentUnderstanding Du.Digitization.Api Du.Classification.Api Du.Extraction.Api Du.Validation.Api EnterpriseContextService Directory JamJamApi LLMGateway LLMOps OMS RCS.FolderAuthorization TM.Projects TM.TestCases TM.Requirements TM.TestSets",
5
5
  "port": 8104
6
6
  }
@@ -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 .documents_service import DocumentsService
8
9
  from .entities_service import EntitiesService
9
10
  from .folder_service import FolderService
10
11
  from .jobs_service import JobsService
@@ -19,6 +20,7 @@ __all__ = [
19
20
  "BucketsService",
20
21
  "ConnectionsService",
21
22
  "ContextGroundingService",
23
+ "DocumentsService",
22
24
  "ProcessesService",
23
25
  "ApiClient",
24
26
  "QueuesService",
@@ -0,0 +1,651 @@
1
+ import asyncio
2
+ import time
3
+ from pathlib import Path
4
+ from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Tuple
5
+ from uuid import UUID
6
+
7
+ from httpx._types import FileContent
8
+
9
+ from .._config import Config
10
+ from .._execution_context import ExecutionContext
11
+ from .._folder_context import FolderContext
12
+ from .._utils import Endpoint
13
+ from ..models.documents import (
14
+ ActionPriority,
15
+ ExtractionResponse,
16
+ ValidatedResult,
17
+ ValidationAction,
18
+ )
19
+ from ..tracing._traced import traced
20
+ from ._base_service import BaseService
21
+
22
+ POLLING_INTERVAL = 2 # seconds
23
+ POLLING_TIMEOUT = 300 # seconds
24
+
25
+
26
+ class DocumentsService(FolderContext, BaseService):
27
+ """Service for managing UiPath DocumentUnderstanding Document Operations.
28
+
29
+ This service provides methods to extract data from documents using UiPath's Document Understanding capabilities.
30
+ """
31
+
32
+ def __init__(self, config: Config, execution_context: ExecutionContext) -> None:
33
+ super().__init__(config=config, execution_context=execution_context)
34
+
35
+ def _get_common_headers(self) -> Dict[str, str]:
36
+ return {
37
+ "X-UiPath-Internal-ConsumptionSourceType": "CodedAgents",
38
+ }
39
+
40
+ def _get_project_id_by_name(self, project_name: str) -> str:
41
+ response = self.request(
42
+ "GET",
43
+ url=Endpoint("/du_/api/framework/projects"),
44
+ params={"api-version": 1.1, "type": "IXP"},
45
+ headers=self._get_common_headers(),
46
+ )
47
+
48
+ try:
49
+ return next(
50
+ project["id"]
51
+ for project in response.json()["projects"]
52
+ if project["name"] == project_name
53
+ )
54
+ except StopIteration:
55
+ raise ValueError(f"Project '{project_name}' not found.") from None
56
+
57
+ async def _get_project_id_by_name_async(self, project_name: str) -> str:
58
+ response = await self.request_async(
59
+ "GET",
60
+ url=Endpoint("/du_/api/framework/projects"),
61
+ params={"api-version": 1.1, "type": "IXP"},
62
+ headers=self._get_common_headers(),
63
+ )
64
+
65
+ try:
66
+ return next(
67
+ project["id"]
68
+ for project in response.json()["projects"]
69
+ if project["name"] == project_name
70
+ )
71
+ except StopIteration:
72
+ raise ValueError(f"Project '{project_name}' not found.") from None
73
+
74
+ def _get_project_tags(self, project_id: str) -> Set[str]:
75
+ response = self.request(
76
+ "GET",
77
+ url=Endpoint(f"/du_/api/framework/projects/{project_id}/tags"),
78
+ params={"api-version": 1.1},
79
+ headers=self._get_common_headers(),
80
+ )
81
+ return {tag["name"] for tag in response.json().get("tags", [])}
82
+
83
+ async def _get_project_tags_async(self, project_id: str) -> Set[str]:
84
+ response = await self.request_async(
85
+ "GET",
86
+ url=Endpoint(f"/du_/api/framework/projects/{project_id}/tags"),
87
+ params={"api-version": 1.1},
88
+ headers=self._get_common_headers(),
89
+ )
90
+ return {tag["name"] for tag in response.json().get("tags", [])}
91
+
92
+ def _get_project_id_and_validate_tag(self, project_name: str, tag: str) -> str:
93
+ project_id = self._get_project_id_by_name(project_name)
94
+ tags = self._get_project_tags(project_id)
95
+ if tag not in tags:
96
+ raise ValueError(
97
+ f"Tag '{tag}' not found in project '{project_name}'. Available tags: {tags}"
98
+ )
99
+
100
+ return project_id
101
+
102
+ async def _get_project_id_and_validate_tag_async(
103
+ self, project_name: str, tag: str
104
+ ) -> str:
105
+ project_id = await self._get_project_id_by_name_async(project_name)
106
+ tags = await self._get_project_tags_async(project_id)
107
+ if tag not in tags:
108
+ raise ValueError(
109
+ f"Tag '{tag}' not found in project '{project_name}'. Available tags: {tags}"
110
+ )
111
+
112
+ return project_id
113
+
114
+ def _start_digitization(
115
+ self,
116
+ project_id: str,
117
+ file: FileContent,
118
+ ) -> str:
119
+ return self.request(
120
+ "POST",
121
+ url=Endpoint(
122
+ f"/du_/api/framework/projects/{project_id}/digitization/start"
123
+ ),
124
+ params={"api-version": 1.1},
125
+ headers=self._get_common_headers(),
126
+ files={"File": file},
127
+ ).json()["documentId"]
128
+
129
+ async def _start_digitization_async(
130
+ self,
131
+ project_id: str,
132
+ file: FileContent,
133
+ ) -> str:
134
+ return (
135
+ await self.request_async(
136
+ "POST",
137
+ url=Endpoint(
138
+ f"/du_/api/framework/projects/{project_id}/digitization/start"
139
+ ),
140
+ params={"api-version": 1.1},
141
+ headers=self._get_common_headers(),
142
+ files={"File": file},
143
+ )
144
+ ).json()["documentId"]
145
+
146
+ def _start_extraction(
147
+ self,
148
+ project_id: str,
149
+ tag: str,
150
+ document_id: str,
151
+ ) -> str:
152
+ return self.request(
153
+ "POST",
154
+ url=Endpoint(
155
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/extraction/start"
156
+ ),
157
+ params={"api-version": 1.1},
158
+ headers=self._get_common_headers(),
159
+ json={"documentId": document_id},
160
+ ).json()["operationId"]
161
+
162
+ async def _start_extraction_async(
163
+ self,
164
+ project_id: str,
165
+ tag: str,
166
+ document_id: str,
167
+ ) -> str:
168
+ return (
169
+ await self.request_async(
170
+ "POST",
171
+ url=Endpoint(
172
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/extraction/start"
173
+ ),
174
+ params={"api-version": 1.1},
175
+ headers=self._get_common_headers(),
176
+ json={"documentId": document_id},
177
+ )
178
+ ).json()["operationId"]
179
+
180
+ def _wait_for_operation(
181
+ self,
182
+ result_getter: Callable[[], Tuple[str, Any]],
183
+ wait_statuses: List[str],
184
+ success_status: str,
185
+ ) -> Any:
186
+ start_time = time.monotonic()
187
+ status = wait_statuses[0]
188
+ result = None
189
+
190
+ while (
191
+ status in wait_statuses
192
+ and (time.monotonic() - start_time) < POLLING_TIMEOUT
193
+ ):
194
+ status, result = result_getter()
195
+ time.sleep(POLLING_INTERVAL)
196
+
197
+ if status != success_status:
198
+ if time.monotonic() - start_time >= POLLING_TIMEOUT:
199
+ raise TimeoutError("Operation timed out.")
200
+ raise RuntimeError(f"Operation failed with status: {status}")
201
+
202
+ return result
203
+
204
+ async def _wait_for_operation_async(
205
+ self,
206
+ result_getter: Callable[[], Awaitable[Tuple[str, Any]]],
207
+ wait_statuses: List[str],
208
+ success_status: str,
209
+ ) -> Any:
210
+ start_time = time.monotonic()
211
+ status = wait_statuses[0]
212
+ result = None
213
+
214
+ while (
215
+ status in wait_statuses
216
+ and (time.monotonic() - start_time) < POLLING_TIMEOUT
217
+ ):
218
+ status, result = await result_getter()
219
+ await asyncio.sleep(POLLING_INTERVAL)
220
+
221
+ if status != success_status:
222
+ if time.monotonic() - start_time >= POLLING_TIMEOUT:
223
+ raise TimeoutError("Operation timed out.")
224
+ raise RuntimeError(f"Operation failed with status: {status}")
225
+
226
+ return result
227
+
228
+ def _wait_for_extraction(
229
+ self, project_id: str, tag: str, operation_id: str
230
+ ) -> ExtractionResponse:
231
+ extraction_response = self._wait_for_operation(
232
+ result_getter=lambda: (
233
+ (
234
+ result := self.request(
235
+ method="GET",
236
+ url=Endpoint(
237
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/extraction/result/{operation_id}"
238
+ ),
239
+ params={"api-version": 1.1},
240
+ headers=self._get_common_headers(),
241
+ ).json()
242
+ )["status"],
243
+ result.get("result", None),
244
+ ),
245
+ wait_statuses=["NotStarted", "Running"],
246
+ success_status="Succeeded",
247
+ )
248
+
249
+ extraction_response["projectId"] = project_id
250
+ extraction_response["tag"] = tag
251
+ return ExtractionResponse.model_validate(extraction_response)
252
+
253
+ async def _wait_for_extraction_async(
254
+ self, project_id: str, tag: str, operation_id: str
255
+ ) -> ExtractionResponse:
256
+ async def result_getter() -> Tuple[str, Any]:
257
+ result = await self.request_async(
258
+ method="GET",
259
+ url=Endpoint(
260
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/extraction/result/{operation_id}"
261
+ ),
262
+ params={"api-version": 1.1},
263
+ headers=self._get_common_headers(),
264
+ )
265
+ json_result = result.json()
266
+ return json_result["status"], json_result.get("result", None)
267
+
268
+ extraction_response = await self._wait_for_operation_async(
269
+ result_getter=result_getter,
270
+ wait_statuses=["NotStarted", "Running"],
271
+ success_status="Succeeded",
272
+ )
273
+
274
+ extraction_response["projectId"] = project_id
275
+ extraction_response["tag"] = tag
276
+ return ExtractionResponse.model_validate(extraction_response)
277
+
278
+ @traced(name="documents_extract", run_type="uipath")
279
+ def extract(
280
+ self,
281
+ project_name: str,
282
+ tag: str,
283
+ file: Optional[FileContent] = None,
284
+ file_path: Optional[str] = None,
285
+ ) -> ExtractionResponse:
286
+ """Extract predicted data from a document using an IXP project.
287
+
288
+ Args:
289
+ project_name (str): Name of the IXP project. Details about IXP projects can be found in the [official documentation](https://docs.uipath.com/ixp/automation-cloud/latest/overview/managing-projects#creating-a-new-project).
290
+ tag (str): Tag of the published project version.
291
+ file (FileContent, optional): The document file to be processed.
292
+ file_path (str, optional): Path to the document file to be processed.
293
+
294
+ Note:
295
+ Either `file` or `file_path` must be provided, but not both.
296
+
297
+ Returns:
298
+ ExtractionResponse: The extraction result containing predicted data.
299
+
300
+ Examples:
301
+ ```python
302
+ with open("path/to/document.pdf", "rb") as file:
303
+ extraction_response = service.extract(
304
+ project_name="MyProject",
305
+ tag="live",
306
+ file=file,
307
+ )
308
+ ```
309
+ """
310
+ if file is None and file_path is None:
311
+ raise ValueError("Either `file` or `file_path` must be provided")
312
+ if file is not None and file_path is not None:
313
+ raise ValueError("`file` and `file_path` are mutually exclusive")
314
+
315
+ project_id = self._get_project_id_and_validate_tag(
316
+ project_name=project_name, tag=tag
317
+ )
318
+
319
+ if file_path is not None:
320
+ with open(Path(file_path), "rb") as handle:
321
+ document_id = self._start_digitization(
322
+ project_id=project_id, file=handle
323
+ )
324
+ else:
325
+ document_id = self._start_digitization(project_id=project_id, file=file) # type: ignore
326
+
327
+ operation_id = self._start_extraction(
328
+ project_id=project_id, tag=tag, document_id=document_id
329
+ )
330
+
331
+ return self._wait_for_extraction(
332
+ project_id=project_id, tag=tag, operation_id=operation_id
333
+ )
334
+
335
+ @traced(name="documents_extract_async", run_type="uipath")
336
+ async def extract_async(
337
+ self,
338
+ project_name: str,
339
+ tag: str,
340
+ file: Optional[FileContent] = None,
341
+ file_path: Optional[str] = None,
342
+ ) -> ExtractionResponse:
343
+ """Asynchronously extract predicted data from a document using an IXP project."""
344
+ if file is None and file_path is None:
345
+ raise ValueError("Either `file` or `file_path` must be provided")
346
+ if file is not None and file_path is not None:
347
+ raise ValueError("`file` and `file_path` are mutually exclusive")
348
+
349
+ project_id = await self._get_project_id_and_validate_tag_async(
350
+ project_name=project_name, tag=tag
351
+ )
352
+
353
+ if file_path is not None:
354
+ with open(Path(file_path), "rb") as handle:
355
+ document_id = await self._start_digitization_async(
356
+ project_id=project_id, file=handle
357
+ )
358
+ else:
359
+ document_id = await self._start_digitization_async(
360
+ project_id=project_id,
361
+ file=file, # type: ignore
362
+ )
363
+
364
+ operation_id = await self._start_extraction_async(
365
+ project_id=project_id, tag=tag, document_id=document_id
366
+ )
367
+
368
+ return await self._wait_for_extraction_async(
369
+ project_id=project_id, tag=tag, operation_id=operation_id
370
+ )
371
+
372
+ def _start_validation(
373
+ self,
374
+ project_id: str,
375
+ tag: str,
376
+ action_title: str,
377
+ action_priority: ActionPriority,
378
+ action_catalog: str,
379
+ action_folder: str,
380
+ storage_bucket_name: str,
381
+ storage_bucket_directory_path: str,
382
+ extraction_response: ExtractionResponse,
383
+ ) -> str:
384
+ return self.request(
385
+ "POST",
386
+ url=Endpoint(
387
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/validation/start"
388
+ ),
389
+ params={"api-version": 1.1},
390
+ headers=self._get_common_headers(),
391
+ json={
392
+ "extractionResult": extraction_response.extraction_result.model_dump(),
393
+ "documentId": extraction_response.extraction_result.document_id,
394
+ "actionTitle": action_title,
395
+ "actionPriority": action_priority,
396
+ "actionCatalog": action_catalog,
397
+ "actionFolder": action_folder,
398
+ "storageBucketName": storage_bucket_name,
399
+ "allowChangeOfDocumentType": True,
400
+ "storageBucketDirectoryPath": storage_bucket_directory_path,
401
+ },
402
+ ).json()["operationId"]
403
+
404
+ async def _start_validation_async(
405
+ self,
406
+ project_id: str,
407
+ tag: str,
408
+ action_title: str,
409
+ action_priority: ActionPriority,
410
+ action_catalog: str,
411
+ action_folder: str,
412
+ storage_bucket_name: str,
413
+ storage_bucket_directory_path: str,
414
+ extraction_response: ExtractionResponse,
415
+ ) -> str:
416
+ return (
417
+ await self.request_async(
418
+ "POST",
419
+ url=Endpoint(
420
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/validation/start"
421
+ ),
422
+ params={"api-version": 1.1},
423
+ headers=self._get_common_headers(),
424
+ json={
425
+ "extractionResult": extraction_response.extraction_result.model_dump(),
426
+ "documentId": extraction_response.extraction_result.document_id,
427
+ "actionTitle": action_title,
428
+ "actionPriority": action_priority,
429
+ "actionCatalog": action_catalog,
430
+ "actionFolder": action_folder,
431
+ "storageBucketName": storage_bucket_name,
432
+ "allowChangeOfDocumentType": True,
433
+ "storageBucketDirectoryPath": storage_bucket_directory_path,
434
+ },
435
+ )
436
+ ).json()["operationId"]
437
+
438
+ def _get_validation_result(
439
+ self, project_id: str, tag: str, operation_id: str
440
+ ) -> Dict: # type: ignore
441
+ return self.request(
442
+ method="GET",
443
+ url=Endpoint(
444
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/validation/result/{operation_id}"
445
+ ),
446
+ params={"api-version": 1.1},
447
+ headers=self._get_common_headers(),
448
+ ).json()
449
+
450
+ async def _get_validation_result_async(
451
+ self, project_id: str, tag: str, operation_id: str
452
+ ) -> Dict: # type: ignore
453
+ return (
454
+ await self.request_async(
455
+ method="GET",
456
+ url=Endpoint(
457
+ f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{UUID(int=0)}/validation/result/{operation_id}"
458
+ ),
459
+ params={"api-version": 1.1},
460
+ headers=self._get_common_headers(),
461
+ )
462
+ ).json()
463
+
464
+ def _wait_for_create_validation_action(
465
+ self, project_id: str, tag: str, operation_id: str
466
+ ) -> ValidationAction:
467
+ response = self._wait_for_operation(
468
+ lambda: (
469
+ (
470
+ result := self._get_validation_result(
471
+ project_id=project_id, tag=tag, operation_id=operation_id
472
+ )
473
+ )["status"],
474
+ result.get("result", None),
475
+ ),
476
+ wait_statuses=["NotStarted", "Running"],
477
+ success_status="Succeeded",
478
+ )
479
+
480
+ response["projectId"] = project_id
481
+ response["tag"] = tag
482
+ response["operationId"] = operation_id
483
+ return ValidationAction.model_validate(response)
484
+
485
+ async def _wait_for_create_validation_action_async(
486
+ self, project_id: str, tag: str, operation_id: str
487
+ ) -> ValidationAction:
488
+ async def result_getter() -> Tuple[str, Any]:
489
+ result = await self._get_validation_result_async(
490
+ project_id=project_id, tag=tag, operation_id=operation_id
491
+ )
492
+ return result["status"], result.get("result", None)
493
+
494
+ response = await self._wait_for_operation_async(
495
+ result_getter=result_getter,
496
+ wait_statuses=["NotStarted", "Running"],
497
+ success_status="Succeeded",
498
+ )
499
+
500
+ response["projectId"] = project_id
501
+ response["tag"] = tag
502
+ response["operationId"] = operation_id
503
+ return ValidationAction.model_validate(response)
504
+
505
+ @traced(name="documents_create_validation_action", run_type="uipath")
506
+ def create_validation_action(
507
+ self,
508
+ action_title: str,
509
+ action_priority: ActionPriority,
510
+ action_catalog: str,
511
+ action_folder: str,
512
+ storage_bucket_name: str,
513
+ storage_bucket_directory_path: str,
514
+ extraction_response: ExtractionResponse,
515
+ ) -> ValidationAction:
516
+ """Create a validation action for a document based on the extraction response. More details about validation actions can be found in the [official documentation](https://docs.uipath.com/ixp/automation-cloud/latest/user-guide/validating-extractions).
517
+
518
+ Args:
519
+ action_title (str): Title of the action.
520
+ action_priority (ActionPriority): Priority of the action.
521
+ action_catalog (str): Catalog of the action.
522
+ action_folder (str): Folder of the action.
523
+ storage_bucket_name (str): Name of the storage bucket.
524
+ storage_bucket_directory_path (str): Directory path in the storage bucket.
525
+ extraction_response (ExtractionResponse): The extraction result to be validated, typically obtained from the [`extract`][uipath._services.documents_service.DocumentsService.extract] method.
526
+
527
+ Returns:
528
+ ValidationAction: The created validation action.
529
+
530
+ Examples:
531
+ ```python
532
+ validation_action = service.create_validation_action(
533
+ action_title="Test Validation Action",
534
+ action_priority=ActionPriority.MEDIUM,
535
+ action_catalog="default_du_actions",
536
+ action_folder="Shared",
537
+ storage_bucket_name="TestBucket",
538
+ storage_bucket_directory_path="TestDirectory",
539
+ extraction_response=extraction_response,
540
+ )
541
+ ```
542
+ """
543
+ operation_id = self._start_validation(
544
+ project_id=extraction_response.project_id,
545
+ tag=extraction_response.tag, # should I validate tag again?
546
+ action_title=action_title,
547
+ action_priority=action_priority,
548
+ action_catalog=action_catalog,
549
+ action_folder=action_folder,
550
+ storage_bucket_name=storage_bucket_name,
551
+ storage_bucket_directory_path=storage_bucket_directory_path,
552
+ extraction_response=extraction_response,
553
+ )
554
+
555
+ return self._wait_for_create_validation_action(
556
+ project_id=extraction_response.project_id,
557
+ tag=extraction_response.tag,
558
+ operation_id=operation_id,
559
+ )
560
+
561
+ @traced(name="documents_create_validation_action_async", run_type="uipath")
562
+ async def create_validation_action_async(
563
+ self,
564
+ action_title: str,
565
+ action_priority: ActionPriority,
566
+ action_catalog: str,
567
+ action_folder: str,
568
+ storage_bucket_name: str,
569
+ storage_bucket_directory_path: str,
570
+ extraction_response: ExtractionResponse,
571
+ ) -> ValidationAction:
572
+ """Asynchronously create a validation action for a document based on the extraction response."""
573
+ # Add reference to sync method docstring
574
+ operation_id = await self._start_validation_async(
575
+ project_id=extraction_response.project_id,
576
+ tag=extraction_response.tag, # should I validate tag again?
577
+ action_title=action_title,
578
+ action_priority=action_priority,
579
+ action_catalog=action_catalog,
580
+ action_folder=action_folder,
581
+ storage_bucket_name=storage_bucket_name,
582
+ storage_bucket_directory_path=storage_bucket_directory_path,
583
+ extraction_response=extraction_response,
584
+ )
585
+
586
+ return await self._wait_for_create_validation_action_async(
587
+ project_id=extraction_response.project_id,
588
+ tag=extraction_response.tag,
589
+ operation_id=operation_id,
590
+ )
591
+
592
+ @traced(name="documents_get_validation_result", run_type="uipath")
593
+ def get_validation_result(
594
+ self, validation_action: ValidationAction
595
+ ) -> ValidatedResult:
596
+ """Get the result of a validation action.
597
+
598
+ Note:
599
+ This method will block until the validation action is completed, meaning the user has completed the validation in UiPath Action Center.
600
+
601
+ Args:
602
+ validation_action (ValidationAction): The validation action to get the result for, typically obtained from the [`create_validation_action`][uipath._services.documents_service.DocumentsService.create_validation_action] method.
603
+
604
+ Returns:
605
+ ValidatedResult: The result of the validation action.
606
+
607
+ Examples:
608
+ ```python
609
+ validated_result = service.get_validation_result(validation_action)
610
+ ```
611
+ """
612
+ response = self._wait_for_operation(
613
+ result_getter=lambda: (
614
+ (
615
+ result := self._get_validation_result(
616
+ project_id=validation_action.project_id,
617
+ tag=validation_action.tag,
618
+ operation_id=validation_action.operation_id,
619
+ )
620
+ )["result"]["actionStatus"],
621
+ result["result"].get("validatedExtractionResults", None),
622
+ ),
623
+ wait_statuses=["Unassigned", "Pending"],
624
+ success_status="Completed",
625
+ )
626
+
627
+ return ValidatedResult.model_validate(response)
628
+
629
+ @traced(name="documents_get_validation_result_async", run_type="uipath")
630
+ async def get_validation_result_async(
631
+ self, validation_action: ValidationAction
632
+ ) -> ValidatedResult:
633
+ """Asynchronously get the result of a validation action."""
634
+
635
+ async def result_getter() -> Tuple[str, Any]:
636
+ result = await self._get_validation_result_async(
637
+ project_id=validation_action.project_id,
638
+ tag=validation_action.tag,
639
+ operation_id=validation_action.operation_id,
640
+ )
641
+ return result["result"]["actionStatus"], result["result"].get(
642
+ "validatedExtractionResults", None
643
+ )
644
+
645
+ response = await self._wait_for_operation_async(
646
+ result_getter=result_getter,
647
+ wait_statuses=["Unassigned", "Pending"],
648
+ success_status="Completed",
649
+ )
650
+
651
+ return ValidatedResult.model_validate(response)
uipath/_uipath.py CHANGED
@@ -13,6 +13,7 @@ from ._services import (
13
13
  BucketsService,
14
14
  ConnectionsService,
15
15
  ContextGroundingService,
16
+ DocumentsService,
16
17
  EntitiesService,
17
18
  FolderService,
18
19
  JobsService,
@@ -114,6 +115,10 @@ class UiPath:
114
115
  self._buckets_service,
115
116
  )
116
117
 
118
+ @property
119
+ def documents(self) -> DocumentsService:
120
+ return DocumentsService(self._config, self._execution_context)
121
+
117
122
  @property
118
123
  def queues(self) -> QueuesService:
119
124
  return QueuesService(self._config, self._execution_context)
@@ -0,0 +1,127 @@
1
+ from enum import Enum
2
+ from typing import List, Optional
3
+
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+
6
+
7
+ class FieldType(str, Enum):
8
+ TEXT = "Text"
9
+ NUMBER = "Number"
10
+ DATE = "Date"
11
+ NAME = "Name"
12
+ ADDRESS = "Address"
13
+ KEYWORD = "Keyword"
14
+ SET = "Set"
15
+ BOOLEAN = "Boolean"
16
+ TABLE = "Table"
17
+ INTERNAL = "Internal"
18
+
19
+
20
+ class ActionPriority(str, Enum):
21
+ LOW = "Low"
22
+ MEDIUM = "Medium"
23
+ HIGH = "High"
24
+ CRITICAL = "Critical"
25
+
26
+
27
+ class FieldValueProjection(BaseModel):
28
+ model_config = ConfigDict(
29
+ serialize_by_alias=True,
30
+ validate_by_alias=True,
31
+ )
32
+
33
+ id: str
34
+ name: str
35
+ value: str
36
+ unformatted_value: str = Field(alias="unformattedValue")
37
+ confidence: float
38
+ ocr_confidence: float = Field(alias="ocrConfidence")
39
+ type: FieldType
40
+
41
+
42
+ class FieldGroupValueProjection(BaseModel):
43
+ model_config = ConfigDict(
44
+ serialize_by_alias=True,
45
+ validate_by_alias=True,
46
+ )
47
+
48
+ field_group_name: str = Field(alias="fieldGroupName")
49
+ field_values: List[FieldValueProjection] = Field(alias="fieldValues")
50
+
51
+
52
+ class ExtractionResult(BaseModel):
53
+ model_config = ConfigDict(
54
+ serialize_by_alias=True,
55
+ validate_by_alias=True,
56
+ )
57
+
58
+ document_id: str = Field(alias="DocumentId")
59
+ results_version: int = Field(alias="ResultsVersion")
60
+ results_document: dict = Field(alias="ResultsDocument") # type: ignore
61
+ extractor_payloads: Optional[List[dict]] = Field( # type: ignore
62
+ default=None, alias="ExtractorPayloads"
63
+ )
64
+ business_rules_results: Optional[List[dict]] = Field( # type: ignore
65
+ default=None, alias="BusinessRulesResults"
66
+ )
67
+
68
+
69
+ class ExtractionResponse(BaseModel):
70
+ """A model representing the response from a document extraction process.
71
+
72
+ Attributes:
73
+ extraction_result (ExtractionResult): The result of the extraction process.
74
+ data_projection (List[FieldGroupValueProjection]): A simplified projection of the extracted data.
75
+ project_id (str): The ID of the project associated with the extraction.
76
+ tag (str): The tag associated with the published model version.
77
+ """
78
+
79
+ model_config = ConfigDict(
80
+ serialize_by_alias=True,
81
+ validate_by_alias=True,
82
+ )
83
+
84
+ extraction_result: ExtractionResult = Field(alias="extractionResult")
85
+ data_projection: List[FieldGroupValueProjection] = Field(alias="dataProjection")
86
+ project_id: str = Field(alias="projectId")
87
+ tag: str
88
+
89
+
90
+ class ValidationAction(BaseModel):
91
+ """A model representing a validation action for a document.
92
+
93
+ Attributes:
94
+ action_data (dict): The data associated with the validation action.
95
+ action_status (str): The status of the validation action. Possible values can be found in the [official documentation](https://docs.uipath.com/action-center/automation-cloud/latest/user-guide/about-actions#action-statuses).
96
+ project_id (str): The ID of the project associated with the validation action.
97
+ tag (str): The tag associated with the published model version.
98
+ operation_id (str): The operation ID associated with the validation action.
99
+ """
100
+
101
+ model_config = ConfigDict(
102
+ serialize_by_alias=True,
103
+ validate_by_alias=True,
104
+ )
105
+
106
+ action_data: dict = Field(alias="actionData") # type: ignore
107
+ action_status: str = Field(alias="actionStatus")
108
+ project_id: str = Field(alias="projectId")
109
+ tag: str
110
+ operation_id: str = Field(alias="operationId")
111
+
112
+
113
+ class ValidatedResult(BaseModel):
114
+ """A model representing the result of a validation action.
115
+
116
+ Attributes:
117
+ document_id (str): The ID of the validated document.
118
+ results_document (dict): The validated results document.
119
+ """
120
+
121
+ model_config = ConfigDict(
122
+ serialize_by_alias=True,
123
+ validate_by_alias=True,
124
+ )
125
+
126
+ document_id: str = Field(alias="DocumentId")
127
+ results_document: dict = Field(alias="ResultsDocument") # type: ignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath
3
- Version: 2.1.68
3
+ Version: 2.1.69
4
4
  Summary: Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools.
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-python
@@ -2,7 +2,7 @@ uipath/__init__.py,sha256=IaeKItOOQXMa95avueJ3dAq-XcRHyZVNjcCGwlSB000,634
2
2
  uipath/_config.py,sha256=pi3qxPzDTxMEstj_XkGOgKJqD6RTHHv7vYv8sS_-d5Q,92
3
3
  uipath/_execution_context.py,sha256=Qo8VMUFgtiL-40KsZrvul5bGv1CRERle_fCw1ORCggY,2374
4
4
  uipath/_folder_context.py,sha256=D-bgxdwpwJP4b_QdVKcPODYh15kMDrOar2xNonmMSm4,1861
5
- uipath/_uipath.py,sha256=p2ccvWpzBXAGFSSF_YaaSWdEqzMmRt786d0pFWrCEwU,4463
5
+ uipath/_uipath.py,sha256=u01pAYrVYfwgAWGeSyD-3Eg33uNHFxhQaH1KAg9NSTA,4616
6
6
  uipath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  uipath/_cli/README.md,sha256=GLtCfbeIKZKNnGTCsfSVqRQ27V1btT1i2bSAyW_xZl4,474
8
8
  uipath/_cli/__init__.py,sha256=2RUgXYd8uJaYjA67xWb0w4IZuBmZoY8G1ccNmEQk9oM,2343
@@ -28,7 +28,7 @@ uipath/_cli/_auth/_oidc_utils.py,sha256=j9VCXai_dM9PF1WtoWEsXETvrWUjuTgU-dCJ3oRu
28
28
  uipath/_cli/_auth/_portal_service.py,sha256=vP82BhjA2D6E6y2wDcXqO1cM4thhPl6DeGsnNXCBdhA,9144
29
29
  uipath/_cli/_auth/_url_utils.py,sha256=Vr-eYbwW_ltmwkULNEAbn6LNsMHnT4uT1n_1zlqD4Ss,1503
30
30
  uipath/_cli/_auth/_utils.py,sha256=9nb76xe5XmDZ0TAncp-_1SKqL6FdwRi9eS3C2noN1lY,1591
31
- uipath/_cli/_auth/auth_config.json,sha256=UnAhdum8phjuZaZKE5KLp0IcPCbIltDEU1M_G8gVbos,443
31
+ uipath/_cli/_auth/auth_config.json,sha256=o8J5BBFwiEtjZLHpJ_64lvnTeYeRIHaJ-Bhg0QvcUX8,521
32
32
  uipath/_cli/_auth/index.html,sha256=uGK0CDTP8Rys_p4O_Pbd2x4tz0frKNVcumjrXnal5Nc,22814
33
33
  uipath/_cli/_auth/localhost.crt,sha256=oGl9oLLOiouHubAt39B4zEfylFvKEtbtr_43SIliXJc,1226
34
34
  uipath/_cli/_auth/localhost.key,sha256=X31VYXD8scZtmGA837dGX5l6G-LXHLo5ItWJhZXaz3c,1679
@@ -81,7 +81,7 @@ uipath/_events/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
81
  uipath/_events/_event_bus.py,sha256=4-VzstyX69cr7wT1EY7ywp-Ndyz2CyemD3Wk_-QmRpo,5496
82
82
  uipath/_events/_events.py,sha256=FhSqbEW4lcBp_QWcDsMtF5XtUtQ8S3rts6uEtMDmGbA,1252
83
83
  uipath/_resources/AGENTS.md,sha256=YWhWuX9XIbyVhVT3PnPc4Of3_q6bsNJcuzYu3N8f_Ug,25850
84
- uipath/_services/__init__.py,sha256=W08UO7ZBQRD8LBHsC6gaM4YBSUl8az0S4d6iZSKsdPE,965
84
+ uipath/_services/__init__.py,sha256=eYZElMfYDQTQU6MMjIke5J-GGT9pzLD5QfbwLiTQkEE,1037
85
85
  uipath/_services/_base_service.py,sha256=x9-9jhPzn9Z16KRdFHhJNvV-FZHvTniMsDfxlS4Cutk,5782
86
86
  uipath/_services/actions_service.py,sha256=2RPMR-hFMsOlqEyjIf3aF7-lrf57jdrSD0pBjj0Kyko,16040
87
87
  uipath/_services/api_client.py,sha256=kGm04ijk9AOEQd2BMxvQg-2QoB8dmyoDwFFDPyutAGw,1966
@@ -90,6 +90,7 @@ uipath/_services/attachments_service.py,sha256=NPQYK7CGjfBaNT_1S5vEAfODmOChTbQZf
90
90
  uipath/_services/buckets_service.py,sha256=5s8tuivd7GUZYj774DDUYTa0axxlUuesc4EBY1V5sdk,18496
91
91
  uipath/_services/connections_service.py,sha256=Gt8zPY4oA7cMYAU2LI3lBieoBpV81BOGelnzDWJl_V4,7931
92
92
  uipath/_services/context_grounding_service.py,sha256=kp7h6Hd-VUuTqiDO-G7IanmXhaq0XHjXUk0ISFev-5c,24835
93
+ uipath/_services/documents_service.py,sha256=UnFS8EpOZ_Ng2TZk3OiJJ3iNANvFs7QxuoG_v-lQj6c,24815
93
94
  uipath/_services/entities_service.py,sha256=QKCLE6wRgq3HZraF-M2mljy-8il4vsNHrQhUgkewVVk,14028
94
95
  uipath/_services/folder_service.py,sha256=9JqgjKhWD-G_KUnfUTP2BADxL6OK9QNZsBsWZHAULdE,2749
95
96
  uipath/_services/jobs_service.py,sha256=tTZNsdZKN3uP7bWPQyBCpJeQxTfuOWbKYOR4L-_yJo4,32736
@@ -139,6 +140,7 @@ uipath/models/buckets.py,sha256=N3Lj_dVCv709-ywhOOdyCSvsuLn41eGuAfSiik6Q6F8,1285
139
140
  uipath/models/connections.py,sha256=bTDg8xISSPmKB1GFNEEMD1OEZyBDFHfZVKqw4gab1pE,2524
140
141
  uipath/models/context_grounding.py,sha256=3MaF2Fv2QYle8UUWvKGkCN5XGpx2T4a34fdbBqJ2fCs,1137
141
142
  uipath/models/context_grounding_index.py,sha256=OhRyxZDHDSrEmBFK0-JLqMMMT64jir4XkHtQ54IKtc0,2683
143
+ uipath/models/documents.py,sha256=g3xAhZlGcLuD6a_DHcUQWoLdzh5dENulouYAwrjGHEw,3963
142
144
  uipath/models/entities.py,sha256=x6jbq4o_QhgL_pCgvHFsp9O8l333kQhn8e9ZCBs72UM,9823
143
145
  uipath/models/errors.py,sha256=WCxxHBlLzLF17YxjqsFkkyBLwEQM_dc6fFU5qmBjD4A,597
144
146
  uipath/models/exceptions.py,sha256=F0ITAhJsl6Agvmnv4nxvgY5oC_lrYIlxWTLs0yx859M,1636
@@ -156,8 +158,8 @@ uipath/tracing/_traced.py,sha256=yBIY05PCCrYyx50EIHZnwJaKNdHPNx-YTR1sHQl0a98,199
156
158
  uipath/tracing/_utils.py,sha256=qd7N56tg6VXQ9pREh61esBgUWLNA0ssKsE0QlwrRWFM,11974
157
159
  uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
158
160
  uipath/utils/_endpoints_manager.py,sha256=iRTl5Q0XAm_YgcnMcJOXtj-8052sr6jpWuPNz6CgT0Q,8408
159
- uipath-2.1.68.dist-info/METADATA,sha256=OCkfgVGObNPCBdNKlOpLLygiWar399jsvc4Cvr3y2g0,6482
160
- uipath-2.1.68.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
161
- uipath-2.1.68.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
162
- uipath-2.1.68.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
163
- uipath-2.1.68.dist-info/RECORD,,
161
+ uipath-2.1.69.dist-info/METADATA,sha256=Yg7phUzMOXp9v9pcXzwAFV-unPDnUurI0W0kkHrBv1A,6482
162
+ uipath-2.1.69.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
163
+ uipath-2.1.69.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
164
+ uipath-2.1.69.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
165
+ uipath-2.1.69.dist-info/RECORD,,