uipath 2.1.111__py3-none-any.whl → 2.1.112__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.
- uipath/_cli/_debug/_bridge.py +194 -33
- uipath/_cli/_debug/_runtime.py +6 -2
- uipath/_cli/_runtime/_contracts.py +1 -1
- uipath/_resources/SDK_REFERENCE.md +5 -5
- uipath/_services/documents_service.py +279 -107
- uipath/models/documents.py +28 -2
- {uipath-2.1.111.dist-info → uipath-2.1.112.dist-info}/METADATA +1 -1
- {uipath-2.1.111.dist-info → uipath-2.1.112.dist-info}/RECORD +11 -11
- {uipath-2.1.111.dist-info → uipath-2.1.112.dist-info}/WHEEL +0 -0
- {uipath-2.1.111.dist-info → uipath-2.1.112.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.111.dist-info → uipath-2.1.112.dist-info}/licenses/LICENSE +0 -0
uipath/_cli/_debug/_bridge.py
CHANGED
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from enum import Enum
|
|
7
|
-
from typing import Any, Dict, List, Optional, Set
|
|
7
|
+
from typing import Any, Dict, List, Literal, Optional, Set
|
|
8
8
|
|
|
9
9
|
from pydantic import BaseModel
|
|
10
10
|
from pysignalr.client import SignalRClient
|
|
@@ -123,7 +123,7 @@ class UiPathDebugBridge(ABC):
|
|
|
123
123
|
pass
|
|
124
124
|
|
|
125
125
|
@abstractmethod
|
|
126
|
-
def get_breakpoints(self) -> List[str]:
|
|
126
|
+
def get_breakpoints(self) -> List[str] | Literal["*"]:
|
|
127
127
|
"""Get nodes to suspend execution at.
|
|
128
128
|
|
|
129
129
|
Returns:
|
|
@@ -220,7 +220,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
|
|
|
220
220
|
"""Print error."""
|
|
221
221
|
self.console.print()
|
|
222
222
|
self.console.print("[red]─" * 40)
|
|
223
|
-
self.console.print(
|
|
223
|
+
self.console.print("[red]✗ Error[/red]")
|
|
224
224
|
self.console.print("[red]─" * 40)
|
|
225
225
|
|
|
226
226
|
# Truncate very long errors
|
|
@@ -228,7 +228,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
|
|
|
228
228
|
if len(error) > 500:
|
|
229
229
|
error_display = error[:500] + "\n[dim]... (truncated)"
|
|
230
230
|
|
|
231
|
-
self.console.print(f"[
|
|
231
|
+
self.console.print(f"[red]{error_display}[/red]")
|
|
232
232
|
self.console.print("[red]─" * 40)
|
|
233
233
|
|
|
234
234
|
async def wait_for_resume(self) -> Any:
|
|
@@ -252,21 +252,14 @@ class ConsoleDebugBridge(UiPathDebugBridge):
|
|
|
252
252
|
# These commands don't resume execution, loop again
|
|
253
253
|
continue
|
|
254
254
|
|
|
255
|
-
# Reset step modes if continuing
|
|
256
|
-
if command_result["command"] == DebugCommand.CONTINUE:
|
|
257
|
-
self.state.step_mode = False
|
|
258
|
-
|
|
259
|
-
if command_result["command"] == DebugCommand.QUIT:
|
|
260
|
-
raise DebuggerQuitException("User requested exit")
|
|
261
|
-
|
|
262
255
|
# Commands that resume execution: CONTINUE, STEP
|
|
263
256
|
self.console.print()
|
|
264
257
|
return command_result
|
|
265
258
|
|
|
266
|
-
def get_breakpoints(self) -> List[str]:
|
|
259
|
+
def get_breakpoints(self) -> List[str] | Literal["*"]:
|
|
267
260
|
"""Get nodes to suspend execution at."""
|
|
268
261
|
if self.state.step_mode:
|
|
269
|
-
return
|
|
262
|
+
return "*" # Suspend at all nodes
|
|
270
263
|
return list(self.state.breakpoints) # Only suspend at breakpoints
|
|
271
264
|
|
|
272
265
|
def _parse_command(self, user_input: str) -> Dict[str, Any]:
|
|
@@ -283,6 +276,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
|
|
|
283
276
|
args = parts[1:] if len(parts) > 1 else []
|
|
284
277
|
|
|
285
278
|
if cmd in ["c", "continue"]:
|
|
279
|
+
self.state.step_mode = False
|
|
286
280
|
return {"command": DebugCommand.CONTINUE, "args": None}
|
|
287
281
|
|
|
288
282
|
elif cmd in ["s", "step"]:
|
|
@@ -318,7 +312,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
|
|
|
318
312
|
}
|
|
319
313
|
|
|
320
314
|
elif cmd in ["q", "quit", "exit"]:
|
|
321
|
-
raise
|
|
315
|
+
raise DebuggerQuitException("User requested exit")
|
|
322
316
|
|
|
323
317
|
elif cmd in ["h", "help", "?"]:
|
|
324
318
|
self._print_help()
|
|
@@ -465,26 +459,75 @@ class SignalRDebugBridge(UiPathDebugBridge):
|
|
|
465
459
|
self._client = SignalRClient(self.hub_url, headers=all_headers)
|
|
466
460
|
|
|
467
461
|
# Register event handlers
|
|
468
|
-
self._client.on("
|
|
462
|
+
self._client.on("Start", self._handle_start)
|
|
463
|
+
self._client.on("Resume", self._handle_resume)
|
|
464
|
+
self._client.on("Step", self._handle_step)
|
|
465
|
+
self._client.on("AddBreakpoints", self._handle_add_breakpoints)
|
|
466
|
+
self._client.on("RemoveBreakpoints", self._handle_remove_breakpoints)
|
|
467
|
+
self._client.on("Quit", self._handle_quit)
|
|
469
468
|
self._client.on_open(self._handle_open)
|
|
470
469
|
self._client.on_close(self._handle_close)
|
|
471
470
|
self._client.on_error(self._handle_error)
|
|
472
471
|
|
|
473
|
-
|
|
474
|
-
|
|
472
|
+
self._run_task = asyncio.create_task(self._client.run())
|
|
473
|
+
|
|
474
|
+
async def cleanup_run_task() -> str:
|
|
475
|
+
error_message = (
|
|
476
|
+
"Failed to establish WebSocket connection within 10s timeout"
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
if self._run_task:
|
|
480
|
+
if not self._run_task.done():
|
|
481
|
+
self._run_task.cancel()
|
|
482
|
+
try:
|
|
483
|
+
await self._run_task
|
|
484
|
+
except asyncio.CancelledError:
|
|
485
|
+
pass # Expected on cancel
|
|
486
|
+
except Exception as task_error:
|
|
487
|
+
error_msg = str(task_error).strip()
|
|
488
|
+
error_detail = f": {error_msg}" if error_msg else ""
|
|
489
|
+
return f"{error_message}: {type(task_error).__name__}{error_detail}"
|
|
490
|
+
|
|
491
|
+
return error_message
|
|
492
|
+
|
|
493
|
+
try:
|
|
494
|
+
# Wait for connection with timeout
|
|
495
|
+
await asyncio.wait_for(self._connected_event.wait(), timeout=10.0)
|
|
496
|
+
except asyncio.TimeoutError as e:
|
|
497
|
+
# Clean up on timeout
|
|
498
|
+
raise RuntimeError(await cleanup_run_task()) from e
|
|
499
|
+
except Exception:
|
|
500
|
+
# Clean up on any other error
|
|
501
|
+
await cleanup_run_task()
|
|
502
|
+
raise
|
|
475
503
|
|
|
476
|
-
#
|
|
477
|
-
|
|
504
|
+
# Check if run_task failed
|
|
505
|
+
if self._run_task.done():
|
|
506
|
+
exception = self._run_task.exception()
|
|
507
|
+
if exception:
|
|
508
|
+
raise exception
|
|
478
509
|
|
|
479
510
|
async def disconnect(self) -> None:
|
|
480
511
|
"""Close SignalR connection."""
|
|
481
|
-
if
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
512
|
+
if not self._client:
|
|
513
|
+
return
|
|
514
|
+
|
|
515
|
+
# Cancel the run task first
|
|
516
|
+
if self._run_task and not self._run_task.done():
|
|
517
|
+
self._run_task.cancel()
|
|
518
|
+
try:
|
|
519
|
+
await self._run_task
|
|
520
|
+
except (Exception, asyncio.CancelledError):
|
|
521
|
+
pass
|
|
522
|
+
|
|
523
|
+
# Try to close the client cleanly
|
|
524
|
+
try:
|
|
525
|
+
if hasattr(self._client, "_transport"):
|
|
526
|
+
transport = self._client._transport
|
|
527
|
+
if transport and hasattr(transport, "_ws") and transport._ws:
|
|
485
528
|
await transport._ws.close()
|
|
486
|
-
|
|
487
|
-
|
|
529
|
+
except Exception as e:
|
|
530
|
+
logger.warning(f"Error closing SignalR WebSocket: {e}")
|
|
488
531
|
|
|
489
532
|
async def emit_execution_started(self, execution_id: str, **kwargs) -> None:
|
|
490
533
|
"""Send execution started event."""
|
|
@@ -541,6 +584,9 @@ class SignalRDebugBridge(UiPathDebugBridge):
|
|
|
541
584
|
error: str,
|
|
542
585
|
) -> None:
|
|
543
586
|
"""Send execution error event."""
|
|
587
|
+
if not self._connected_event.is_set():
|
|
588
|
+
return
|
|
589
|
+
|
|
544
590
|
logger.error(f"Execution error: {execution_id} - {error}")
|
|
545
591
|
await self._send(
|
|
546
592
|
"OnExecutionError",
|
|
@@ -558,24 +604,139 @@ class SignalRDebugBridge(UiPathDebugBridge):
|
|
|
558
604
|
logger.info("Resume command received")
|
|
559
605
|
return self._resume_data
|
|
560
606
|
|
|
561
|
-
def get_breakpoints(self) -> List[str]:
|
|
607
|
+
def get_breakpoints(self) -> List[str] | Literal["*"]:
|
|
562
608
|
"""Get nodes to suspend execution at."""
|
|
563
609
|
if self.state.step_mode:
|
|
564
|
-
return
|
|
610
|
+
return "*" # Suspend at all nodes
|
|
565
611
|
return list(self.state.breakpoints) # Only suspend at breakpoints
|
|
566
612
|
|
|
567
|
-
async def _send(self,
|
|
568
|
-
"""Send message to SignalR hub.
|
|
613
|
+
async def _send(self, event_name: str, data: Dict[str, Any]) -> None:
|
|
614
|
+
"""Send message to SignalR hub via SendCommand.
|
|
615
|
+
|
|
616
|
+
Args:
|
|
617
|
+
event_name: The event/command name (e.g., "OnExecutionStarted")
|
|
618
|
+
data: The data payload to send
|
|
619
|
+
"""
|
|
569
620
|
if not self._client:
|
|
570
621
|
raise RuntimeError("SignalR client not connected")
|
|
622
|
+
try:
|
|
623
|
+
# Wrap the event in SendCommand protocol
|
|
624
|
+
# Server expects: SendCommand(event_name, json_string_of_data)
|
|
625
|
+
data_json = json.dumps(data)
|
|
626
|
+
arguments: list[Any] = [event_name, data_json]
|
|
627
|
+
await self._client.send(method="SendCommand", arguments=arguments)
|
|
628
|
+
logger.debug(f"Sent command: {event_name} with data: {data}")
|
|
629
|
+
except Exception as e:
|
|
630
|
+
logger.error(f"Error sending command {event_name} to SignalR hub: {e}")
|
|
631
|
+
|
|
632
|
+
async def _handle_start(self, args: list[Any]) -> None:
|
|
633
|
+
"""Handle Start command from SignalR server.
|
|
571
634
|
|
|
572
|
-
|
|
635
|
+
Args:
|
|
636
|
+
args: List containing command arguments, typically [dict_with_args]
|
|
637
|
+
"""
|
|
638
|
+
logger.info(f"Start command received with args: {args}")
|
|
639
|
+
if not args or len(args) == 0:
|
|
640
|
+
logger.warning("Start command received with empty args.")
|
|
641
|
+
return
|
|
642
|
+
|
|
643
|
+
command_args = args[0] if isinstance(args[0], dict) else {}
|
|
644
|
+
self.state.breakpoints = set(command_args.get("breakpoints", []))
|
|
645
|
+
step_mode = command_args.get("enableStepMode", False)
|
|
646
|
+
self.state.step_mode = step_mode
|
|
573
647
|
|
|
574
648
|
async def _handle_resume(self, args: list[Any]) -> None:
|
|
575
|
-
"""Handle
|
|
576
|
-
|
|
577
|
-
|
|
649
|
+
"""Handle Resume command from SignalR server.
|
|
650
|
+
|
|
651
|
+
Args:
|
|
652
|
+
args: List containing command arguments
|
|
653
|
+
"""
|
|
654
|
+
logger.info(f"Resume command received with args: {args}")
|
|
655
|
+
command_args = args[0] if args and len(args) > 0 else {}
|
|
656
|
+
|
|
657
|
+
if self._resume_event:
|
|
658
|
+
self._resume_data = command_args
|
|
578
659
|
self._resume_event.set()
|
|
660
|
+
logger.info("Resume event set")
|
|
661
|
+
else:
|
|
662
|
+
logger.warning("Resume command received but no resume event is waiting")
|
|
663
|
+
|
|
664
|
+
async def _handle_step(self, args: list[Any]) -> None:
|
|
665
|
+
"""Handle Step command from SignalR server.
|
|
666
|
+
|
|
667
|
+
Args:
|
|
668
|
+
args: List containing command arguments
|
|
669
|
+
"""
|
|
670
|
+
logger.info(f"Step command received with args: {args}")
|
|
671
|
+
self.state.step_mode = True
|
|
672
|
+
logger.info("Step mode enabled")
|
|
673
|
+
|
|
674
|
+
async def _handle_add_breakpoints(self, args: list[Any]) -> None:
|
|
675
|
+
"""Handle AddBreakpoints command from SignalR server.
|
|
676
|
+
|
|
677
|
+
Args:
|
|
678
|
+
args: List containing command arguments with breakpoints list
|
|
679
|
+
"""
|
|
680
|
+
logger.info(f"AddBreakpoints command received with args: {args}")
|
|
681
|
+
if not args or len(args) == 0:
|
|
682
|
+
logger.warning("AddBreakpoints command received with empty args.")
|
|
683
|
+
return
|
|
684
|
+
|
|
685
|
+
command_args = args[0] if isinstance(args[0], dict) else {}
|
|
686
|
+
break_points = command_args.get("breakpoints", [])
|
|
687
|
+
|
|
688
|
+
for bp in break_points:
|
|
689
|
+
node_name = (
|
|
690
|
+
bp.get("node", {}).get("name")
|
|
691
|
+
if isinstance(bp.get("node"), dict)
|
|
692
|
+
else None
|
|
693
|
+
)
|
|
694
|
+
if node_name:
|
|
695
|
+
self.state.add_breakpoint(node_name)
|
|
696
|
+
logger.info(f"Breakpoint set at: {node_name}")
|
|
697
|
+
else:
|
|
698
|
+
logger.warning(f"Breakpoint command received without node name: {bp}")
|
|
699
|
+
|
|
700
|
+
async def _handle_remove_breakpoints(self, args: list[Any]) -> None:
|
|
701
|
+
"""Handle RemoveBreakpoints command from SignalR server.
|
|
702
|
+
|
|
703
|
+
Args:
|
|
704
|
+
args: List containing command arguments with breakpoints list
|
|
705
|
+
"""
|
|
706
|
+
logger.info(f"RemoveBreakpoints command received with args: {args}")
|
|
707
|
+
if not args or len(args) == 0:
|
|
708
|
+
self.state.clear_all_breakpoints()
|
|
709
|
+
logger.info("All breakpoints cleared")
|
|
710
|
+
return
|
|
711
|
+
|
|
712
|
+
command_args = args[0] if isinstance(args[0], dict) else {}
|
|
713
|
+
break_points = command_args.get("breakpoints", [])
|
|
714
|
+
|
|
715
|
+
if not break_points:
|
|
716
|
+
self.state.clear_all_breakpoints()
|
|
717
|
+
logger.info("All breakpoints cleared")
|
|
718
|
+
else:
|
|
719
|
+
for bp in break_points:
|
|
720
|
+
node_name = (
|
|
721
|
+
bp.get("node", {}).get("name")
|
|
722
|
+
if isinstance(bp.get("node"), dict)
|
|
723
|
+
else None
|
|
724
|
+
)
|
|
725
|
+
if node_name:
|
|
726
|
+
self.state.remove_breakpoint(node_name)
|
|
727
|
+
logger.info(f"Breakpoint removed: {node_name}")
|
|
728
|
+
|
|
729
|
+
async def _handle_quit(self, args: list[Any]) -> None:
|
|
730
|
+
"""Handle Quit command from SignalR server.
|
|
731
|
+
|
|
732
|
+
Args:
|
|
733
|
+
args: List containing command arguments
|
|
734
|
+
"""
|
|
735
|
+
if args:
|
|
736
|
+
logger.info(f"Quit command received from server with args: {args}")
|
|
737
|
+
else:
|
|
738
|
+
logger.info("Quit command received from server")
|
|
739
|
+
raise DebuggerQuitException("Quit command received from server")
|
|
579
740
|
|
|
580
741
|
async def _handle_open(self) -> None:
|
|
581
742
|
"""Handle SignalR connection open."""
|
uipath/_cli/_debug/_runtime.py
CHANGED
|
@@ -35,6 +35,7 @@ class UiPathDebugRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
|
35
35
|
self.context: UiPathRuntimeContext = context
|
|
36
36
|
self.factory: UiPathRuntimeFactory[T, C] = factory
|
|
37
37
|
self.debug_bridge: UiPathDebugBridge = debug_bridge
|
|
38
|
+
self.execution_id: str = context.job_id or "default"
|
|
38
39
|
self._inner_runtime: Optional[T] = None
|
|
39
40
|
|
|
40
41
|
@classmethod
|
|
@@ -57,7 +58,7 @@ class UiPathDebugRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
|
57
58
|
raise RuntimeError("Failed to create inner runtime")
|
|
58
59
|
|
|
59
60
|
await self.debug_bridge.emit_execution_started(
|
|
60
|
-
execution_id=self.
|
|
61
|
+
execution_id=self.execution_id
|
|
61
62
|
)
|
|
62
63
|
|
|
63
64
|
# Try to stream events from inner runtime
|
|
@@ -78,8 +79,11 @@ class UiPathDebugRuntime(UiPathBaseRuntime, Generic[T, C]):
|
|
|
78
79
|
|
|
79
80
|
except Exception as e:
|
|
80
81
|
# Emit execution error
|
|
82
|
+
self.context.result = UiPathRuntimeResult(
|
|
83
|
+
status=UiPathRuntimeStatus.FAULTED,
|
|
84
|
+
)
|
|
81
85
|
await self.debug_bridge.emit_execution_error(
|
|
82
|
-
execution_id=self.
|
|
86
|
+
execution_id=self.execution_id,
|
|
83
87
|
error=str(e),
|
|
84
88
|
)
|
|
85
89
|
raise
|
|
@@ -382,7 +382,7 @@ class UiPathRuntimeContext(BaseModel):
|
|
|
382
382
|
log_handler: Optional[logging.Handler] = None
|
|
383
383
|
chat_handler: Optional[UiPathConversationHandler] = None
|
|
384
384
|
is_conversational: Optional[bool] = None
|
|
385
|
-
breakpoints: Optional[List[str]] = None
|
|
385
|
+
breakpoints: Optional[List[str] | Literal["*"]] = None
|
|
386
386
|
|
|
387
387
|
model_config = {"arbitrary_types_allowed": True, "extra": "allow"}
|
|
388
388
|
|
|
@@ -127,19 +127,19 @@ Documents service
|
|
|
127
127
|
# 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).
|
|
128
128
|
sdk.documents.create_validation_action(action_title: str, action_priority: <enum 'ActionPriority, action_catalog: str, action_folder: str, storage_bucket_name: str, storage_bucket_directory_path: str, extraction_response: uipath.models.documents.ExtractionResponse) -> uipath.models.documents.ValidationAction
|
|
129
129
|
|
|
130
|
-
#
|
|
130
|
+
# Asynchronous version of the [`create_validation_action`][uipath._services.documents_service.DocumentsService.create_validation_action] method.
|
|
131
131
|
sdk.documents.create_validation_action_async(action_title: str, action_priority: <enum 'ActionPriority, action_catalog: str, action_folder: str, storage_bucket_name: str, storage_bucket_directory_path: str, extraction_response: uipath.models.documents.ExtractionResponse) -> uipath.models.documents.ValidationAction
|
|
132
132
|
|
|
133
133
|
# Extract predicted data from a document using an IXP project.
|
|
134
|
-
sdk.documents.extract(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None) -> uipath.models.documents.ExtractionResponse
|
|
134
|
+
sdk.documents.extract(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None, project_type: <enum 'ProjectType="IXP", document_type_name: Optional[str]=None) -> typing.Union[uipath.models.documents.ExtractionResponse, uipath.models.documents.ExtractionResponseIXP]
|
|
135
135
|
|
|
136
|
-
# Asynchronously
|
|
137
|
-
sdk.documents.extract_async(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None) -> uipath.models.documents.ExtractionResponse
|
|
136
|
+
# Asynchronously version of the [`extract`][uipath._services.documents_service.DocumentsService.extract] method.
|
|
137
|
+
sdk.documents.extract_async(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None, project_type: <enum 'ProjectType="IXP", document_type_name: Optional[str]=None) -> typing.Union[uipath.models.documents.ExtractionResponse, uipath.models.documents.ExtractionResponseIXP]
|
|
138
138
|
|
|
139
139
|
# Get the result of a validation action.
|
|
140
140
|
sdk.documents.get_validation_result(validation_action: uipath.models.documents.ValidationAction) -> uipath.models.documents.ValidatedResult
|
|
141
141
|
|
|
142
|
-
#
|
|
142
|
+
# Asynchronous version of the [`get_validation_result`][uipath._services.documents_service.DocumentsService.get_validation_result] method.
|
|
143
143
|
sdk.documents.get_validation_result_async(validation_action: uipath.models.documents.ValidationAction) -> uipath.models.documents.ValidatedResult
|
|
144
144
|
|
|
145
145
|
```
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import time
|
|
3
|
+
from contextlib import nullcontext
|
|
3
4
|
from pathlib import Path
|
|
4
|
-
from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Tuple
|
|
5
|
+
from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Tuple, Union
|
|
5
6
|
from uuid import UUID
|
|
6
7
|
|
|
7
8
|
from httpx._types import FileContent
|
|
@@ -13,6 +14,8 @@ from .._utils import Endpoint
|
|
|
13
14
|
from ..models.documents import (
|
|
14
15
|
ActionPriority,
|
|
15
16
|
ExtractionResponse,
|
|
17
|
+
ExtractionResponseIXP,
|
|
18
|
+
ProjectType,
|
|
16
19
|
ValidatedResult,
|
|
17
20
|
ValidationAction,
|
|
18
21
|
)
|
|
@@ -41,11 +44,13 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
41
44
|
"X-UiPath-Internal-ConsumptionSourceType": "CodedAgents",
|
|
42
45
|
}
|
|
43
46
|
|
|
44
|
-
def _get_project_id_by_name(
|
|
47
|
+
def _get_project_id_by_name(
|
|
48
|
+
self, project_name: str, project_type: ProjectType
|
|
49
|
+
) -> str:
|
|
45
50
|
response = self.request(
|
|
46
51
|
"GET",
|
|
47
52
|
url=Endpoint("/du_/api/framework/projects"),
|
|
48
|
-
params={"api-version": 1.1, "type":
|
|
53
|
+
params={"api-version": 1.1, "type": project_type.value},
|
|
49
54
|
headers=self._get_common_headers(),
|
|
50
55
|
)
|
|
51
56
|
|
|
@@ -58,11 +63,13 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
58
63
|
except StopIteration:
|
|
59
64
|
raise ValueError(f"Project '{project_name}' not found.") from None
|
|
60
65
|
|
|
61
|
-
async def _get_project_id_by_name_async(
|
|
66
|
+
async def _get_project_id_by_name_async(
|
|
67
|
+
self, project_name: str, project_type: ProjectType
|
|
68
|
+
) -> str:
|
|
62
69
|
response = await self.request_async(
|
|
63
70
|
"GET",
|
|
64
71
|
url=Endpoint("/du_/api/framework/projects"),
|
|
65
|
-
params={"api-version": 1.1, "type":
|
|
72
|
+
params={"api-version": 1.1, "type": project_type.value},
|
|
66
73
|
headers=self._get_common_headers(),
|
|
67
74
|
)
|
|
68
75
|
|
|
@@ -93,8 +100,10 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
93
100
|
)
|
|
94
101
|
return {tag["name"] for tag in response.json().get("tags", [])}
|
|
95
102
|
|
|
96
|
-
def _get_project_id_and_validate_tag(
|
|
97
|
-
|
|
103
|
+
def _get_project_id_and_validate_tag(
|
|
104
|
+
self, project_name: str, project_type: ProjectType, tag: str
|
|
105
|
+
) -> str:
|
|
106
|
+
project_id = self._get_project_id_by_name(project_name, project_type)
|
|
98
107
|
tags = self._get_project_tags(project_id)
|
|
99
108
|
if tag not in tags:
|
|
100
109
|
raise ValueError(
|
|
@@ -104,9 +113,11 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
104
113
|
return project_id
|
|
105
114
|
|
|
106
115
|
async def _get_project_id_and_validate_tag_async(
|
|
107
|
-
self, project_name: str, tag: str
|
|
116
|
+
self, project_name: str, project_type: ProjectType, tag: str
|
|
108
117
|
) -> str:
|
|
109
|
-
project_id = await self._get_project_id_by_name_async(
|
|
118
|
+
project_id = await self._get_project_id_by_name_async(
|
|
119
|
+
project_name, project_type
|
|
120
|
+
)
|
|
110
121
|
tags = await self._get_project_tags_async(project_id)
|
|
111
122
|
if tag not in tags:
|
|
112
123
|
raise ValueError(
|
|
@@ -147,16 +158,71 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
147
158
|
)
|
|
148
159
|
).json()["documentId"]
|
|
149
160
|
|
|
161
|
+
def _get_document_type_id(
|
|
162
|
+
self,
|
|
163
|
+
project_id: str,
|
|
164
|
+
document_type_name: Optional[str],
|
|
165
|
+
project_type: ProjectType,
|
|
166
|
+
) -> str:
|
|
167
|
+
if project_type == ProjectType.IXP:
|
|
168
|
+
return str(UUID(int=0))
|
|
169
|
+
|
|
170
|
+
response = self.request(
|
|
171
|
+
"GET",
|
|
172
|
+
url=Endpoint(f"/du_/api/framework/projects/{project_id}/document-types"),
|
|
173
|
+
params={"api-version": 1.1},
|
|
174
|
+
headers=self._get_common_headers(),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
return next(
|
|
179
|
+
extractor["id"]
|
|
180
|
+
for extractor in response.json().get("documentTypes", [])
|
|
181
|
+
if extractor["name"].lower() == document_type_name.lower() # type: ignore
|
|
182
|
+
)
|
|
183
|
+
except StopIteration:
|
|
184
|
+
raise ValueError(
|
|
185
|
+
f"Document type '{document_type_name}' not found."
|
|
186
|
+
) from None
|
|
187
|
+
|
|
188
|
+
async def _get_document_type_id_async(
|
|
189
|
+
self,
|
|
190
|
+
project_id: str,
|
|
191
|
+
document_type_name: Optional[str],
|
|
192
|
+
project_type: ProjectType,
|
|
193
|
+
) -> str:
|
|
194
|
+
if project_type == ProjectType.IXP:
|
|
195
|
+
return str(UUID(int=0))
|
|
196
|
+
|
|
197
|
+
response = await self.request_async(
|
|
198
|
+
"GET",
|
|
199
|
+
url=Endpoint(f"/du_/api/framework/projects/{project_id}/document-types"),
|
|
200
|
+
params={"api-version": 1.1},
|
|
201
|
+
headers=self._get_common_headers(),
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
return next(
|
|
206
|
+
extractor["id"]
|
|
207
|
+
for extractor in response.json().get("documentTypes", [])
|
|
208
|
+
if extractor["name"].lower() == document_type_name.lower() # type: ignore
|
|
209
|
+
)
|
|
210
|
+
except StopIteration:
|
|
211
|
+
raise ValueError(
|
|
212
|
+
f"Document type '{document_type_name}' not found."
|
|
213
|
+
) from None
|
|
214
|
+
|
|
150
215
|
def _start_extraction(
|
|
151
216
|
self,
|
|
152
217
|
project_id: str,
|
|
153
218
|
tag: str,
|
|
219
|
+
document_type_id: str,
|
|
154
220
|
document_id: str,
|
|
155
221
|
) -> str:
|
|
156
222
|
return self.request(
|
|
157
223
|
"POST",
|
|
158
224
|
url=Endpoint(
|
|
159
|
-
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{
|
|
225
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/extraction/start"
|
|
160
226
|
),
|
|
161
227
|
params={"api-version": 1.1},
|
|
162
228
|
headers=self._get_common_headers(),
|
|
@@ -167,13 +233,14 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
167
233
|
self,
|
|
168
234
|
project_id: str,
|
|
169
235
|
tag: str,
|
|
236
|
+
document_type_id: str,
|
|
170
237
|
document_id: str,
|
|
171
238
|
) -> str:
|
|
172
239
|
return (
|
|
173
240
|
await self.request_async(
|
|
174
241
|
"POST",
|
|
175
242
|
url=Endpoint(
|
|
176
|
-
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{
|
|
243
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/extraction/start"
|
|
177
244
|
),
|
|
178
245
|
params={"api-version": 1.1},
|
|
179
246
|
headers=self._get_common_headers(),
|
|
@@ -183,7 +250,7 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
183
250
|
|
|
184
251
|
def _wait_for_operation(
|
|
185
252
|
self,
|
|
186
|
-
result_getter: Callable[[], Tuple[
|
|
253
|
+
result_getter: Callable[[], Tuple[Any, Optional[Any], Optional[Any]]],
|
|
187
254
|
wait_statuses: List[str],
|
|
188
255
|
success_status: str,
|
|
189
256
|
) -> Any:
|
|
@@ -195,19 +262,23 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
195
262
|
status in wait_statuses
|
|
196
263
|
and (time.monotonic() - start_time) < POLLING_TIMEOUT
|
|
197
264
|
):
|
|
198
|
-
status, result = result_getter()
|
|
265
|
+
status, error, result = result_getter()
|
|
199
266
|
time.sleep(POLLING_INTERVAL)
|
|
200
267
|
|
|
201
268
|
if status != success_status:
|
|
202
269
|
if time.monotonic() - start_time >= POLLING_TIMEOUT:
|
|
203
270
|
raise TimeoutError("Operation timed out.")
|
|
204
|
-
raise RuntimeError(
|
|
271
|
+
raise RuntimeError(
|
|
272
|
+
f"Operation failed with status: {status}, error: {error}"
|
|
273
|
+
)
|
|
205
274
|
|
|
206
275
|
return result
|
|
207
276
|
|
|
208
277
|
async def _wait_for_operation_async(
|
|
209
278
|
self,
|
|
210
|
-
result_getter: Callable[
|
|
279
|
+
result_getter: Callable[
|
|
280
|
+
[], Awaitable[Tuple[Any, Optional[Any], Optional[Any]]]
|
|
281
|
+
],
|
|
211
282
|
wait_statuses: List[str],
|
|
212
283
|
success_status: str,
|
|
213
284
|
) -> Any:
|
|
@@ -219,55 +290,80 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
219
290
|
status in wait_statuses
|
|
220
291
|
and (time.monotonic() - start_time) < POLLING_TIMEOUT
|
|
221
292
|
):
|
|
222
|
-
status, result = await result_getter()
|
|
293
|
+
status, error, result = await result_getter()
|
|
223
294
|
await asyncio.sleep(POLLING_INTERVAL)
|
|
224
295
|
|
|
225
296
|
if status != success_status:
|
|
226
297
|
if time.monotonic() - start_time >= POLLING_TIMEOUT:
|
|
227
298
|
raise TimeoutError("Operation timed out.")
|
|
228
|
-
raise RuntimeError(
|
|
299
|
+
raise RuntimeError(
|
|
300
|
+
f"Operation failed with status: {status}, error: {error}"
|
|
301
|
+
)
|
|
229
302
|
|
|
230
303
|
return result
|
|
231
304
|
|
|
232
305
|
def _wait_for_extraction(
|
|
233
|
-
self,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
306
|
+
self,
|
|
307
|
+
project_id: str,
|
|
308
|
+
tag: str,
|
|
309
|
+
document_type_id: str,
|
|
310
|
+
operation_id: str,
|
|
311
|
+
project_type: ProjectType,
|
|
312
|
+
) -> Union[ExtractionResponse, ExtractionResponseIXP]:
|
|
313
|
+
def result_getter() -> Tuple[str, str, Any]:
|
|
314
|
+
result = self.request(
|
|
315
|
+
method="GET",
|
|
316
|
+
url=Endpoint(
|
|
317
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/extraction/result/{operation_id}"
|
|
318
|
+
),
|
|
319
|
+
params={"api-version": 1.1},
|
|
320
|
+
headers=self._get_common_headers(),
|
|
321
|
+
).json()
|
|
322
|
+
return (
|
|
323
|
+
result["status"],
|
|
324
|
+
result.get("error", None),
|
|
247
325
|
result.get("result", None),
|
|
248
|
-
)
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
extraction_response = self._wait_for_operation(
|
|
329
|
+
result_getter=result_getter,
|
|
249
330
|
wait_statuses=["NotStarted", "Running"],
|
|
250
331
|
success_status="Succeeded",
|
|
251
332
|
)
|
|
252
333
|
|
|
253
334
|
extraction_response["projectId"] = project_id
|
|
254
335
|
extraction_response["tag"] = tag
|
|
336
|
+
extraction_response["documentTypeId"] = document_type_id
|
|
337
|
+
|
|
338
|
+
if project_type == ProjectType.IXP:
|
|
339
|
+
return ExtractionResponseIXP.model_validate(extraction_response)
|
|
340
|
+
|
|
255
341
|
return ExtractionResponse.model_validate(extraction_response)
|
|
256
342
|
|
|
257
343
|
async def _wait_for_extraction_async(
|
|
258
|
-
self,
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
344
|
+
self,
|
|
345
|
+
project_id: str,
|
|
346
|
+
tag: str,
|
|
347
|
+
document_type_id: str,
|
|
348
|
+
operation_id: str,
|
|
349
|
+
project_type: ProjectType,
|
|
350
|
+
) -> Union[ExtractionResponse, ExtractionResponseIXP]:
|
|
351
|
+
async def result_getter() -> Tuple[str, str, Any]:
|
|
352
|
+
result = (
|
|
353
|
+
await self.request_async(
|
|
354
|
+
method="GET",
|
|
355
|
+
url=Endpoint(
|
|
356
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/extraction/result/{operation_id}"
|
|
357
|
+
),
|
|
358
|
+
params={"api-version": 1.1},
|
|
359
|
+
headers=self._get_common_headers(),
|
|
360
|
+
)
|
|
361
|
+
).json()
|
|
362
|
+
return (
|
|
363
|
+
result["status"],
|
|
364
|
+
result.get("error", None),
|
|
365
|
+
result.get("result", None),
|
|
268
366
|
)
|
|
269
|
-
json_result = result.json()
|
|
270
|
-
return json_result["status"], json_result.get("result", None)
|
|
271
367
|
|
|
272
368
|
extraction_response = await self._wait_for_operation_async(
|
|
273
369
|
result_getter=result_getter,
|
|
@@ -277,6 +373,11 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
277
373
|
|
|
278
374
|
extraction_response["projectId"] = project_id
|
|
279
375
|
extraction_response["tag"] = tag
|
|
376
|
+
extraction_response["documentTypeId"] = document_type_id
|
|
377
|
+
|
|
378
|
+
if project_type == ProjectType.IXP:
|
|
379
|
+
return ExtractionResponseIXP.model_validate(extraction_response)
|
|
380
|
+
|
|
280
381
|
return ExtractionResponse.model_validate(extraction_response)
|
|
281
382
|
|
|
282
383
|
@traced(name="documents_extract", run_type="uipath")
|
|
@@ -286,14 +387,18 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
286
387
|
tag: str,
|
|
287
388
|
file: Optional[FileContent] = None,
|
|
288
389
|
file_path: Optional[str] = None,
|
|
289
|
-
|
|
390
|
+
project_type: ProjectType = ProjectType.IXP,
|
|
391
|
+
document_type_name: Optional[str] = None,
|
|
392
|
+
) -> Union[ExtractionResponse, ExtractionResponseIXP]:
|
|
290
393
|
"""Extract predicted data from a document using an IXP project.
|
|
291
394
|
|
|
292
395
|
Args:
|
|
293
|
-
project_name (str): Name of the IXP
|
|
396
|
+
project_name (str): Name of the [IXP](https://docs.uipath.com/ixp/automation-cloud/latest/overview/managing-projects#creating-a-new-project)/[DU Modern](https://docs.uipath.com/document-understanding/automation-cloud/latest/user-guide/about-document-understanding) project.
|
|
294
397
|
tag (str): Tag of the published project version.
|
|
295
398
|
file (FileContent, optional): The document file to be processed.
|
|
296
399
|
file_path (str, optional): Path to the document file to be processed.
|
|
400
|
+
project_type (ProjectType, optional): Type of the project. Defaults to `ProjectType.IXP`.
|
|
401
|
+
document_type_name (str, optional): Document type name associated with the extractor to be used for extraction. Required if `project_type` is `ProjectType.MODERN`.
|
|
297
402
|
|
|
298
403
|
Note:
|
|
299
404
|
Either `file` or `file_path` must be provided, but not both.
|
|
@@ -302,38 +407,63 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
302
407
|
ExtractionResponse: The extraction result containing predicted data.
|
|
303
408
|
|
|
304
409
|
Examples:
|
|
410
|
+
IXP projects:
|
|
305
411
|
```python
|
|
306
412
|
with open("path/to/document.pdf", "rb") as file:
|
|
307
413
|
extraction_response = service.extract(
|
|
308
|
-
project_name="
|
|
414
|
+
project_name="MyIXPProjectName",
|
|
309
415
|
tag="live",
|
|
310
416
|
file=file,
|
|
311
417
|
)
|
|
312
418
|
```
|
|
419
|
+
|
|
420
|
+
DU Modern projects:
|
|
421
|
+
```python
|
|
422
|
+
with open("path/to/document.pdf", "rb") as file:
|
|
423
|
+
extraction_response = service.extract(
|
|
424
|
+
project_name="MyModernProjectName",
|
|
425
|
+
tag="Production",
|
|
426
|
+
file=file,
|
|
427
|
+
project_type=ProjectType.MODERN,
|
|
428
|
+
document_type_name="Receipts",
|
|
429
|
+
)
|
|
430
|
+
```
|
|
313
431
|
"""
|
|
314
432
|
if file is None and file_path is None:
|
|
315
433
|
raise ValueError("Either `file` or `file_path` must be provided")
|
|
316
434
|
if file is not None and file_path is not None:
|
|
317
435
|
raise ValueError("`file` and `file_path` are mutually exclusive")
|
|
436
|
+
if project_type == ProjectType.MODERN and document_type_name is None:
|
|
437
|
+
raise ValueError(
|
|
438
|
+
"`document_type_name` must be provided when `project_type` is `ProjectType.MODERN`"
|
|
439
|
+
)
|
|
318
440
|
|
|
319
441
|
project_id = self._get_project_id_and_validate_tag(
|
|
320
|
-
project_name=project_name, tag=tag
|
|
442
|
+
project_name=project_name, project_type=project_type, tag=tag
|
|
321
443
|
)
|
|
322
444
|
|
|
323
|
-
if file_path
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
445
|
+
with open(Path(file_path), "rb") if file_path else nullcontext(file) as handle:
|
|
446
|
+
document_id = self._start_digitization(project_id=project_id, file=handle) # type: ignore
|
|
447
|
+
|
|
448
|
+
document_type_id = self._get_document_type_id(
|
|
449
|
+
project_id=project_id,
|
|
450
|
+
document_type_name=document_type_name,
|
|
451
|
+
project_type=project_type,
|
|
452
|
+
)
|
|
330
453
|
|
|
331
454
|
operation_id = self._start_extraction(
|
|
332
|
-
project_id=project_id,
|
|
455
|
+
project_id=project_id,
|
|
456
|
+
tag=tag,
|
|
457
|
+
document_type_id=document_type_id,
|
|
458
|
+
document_id=document_id,
|
|
333
459
|
)
|
|
334
460
|
|
|
335
461
|
return self._wait_for_extraction(
|
|
336
|
-
project_id=project_id,
|
|
462
|
+
project_id=project_id,
|
|
463
|
+
tag=tag,
|
|
464
|
+
document_type_id=document_type_id,
|
|
465
|
+
operation_id=operation_id,
|
|
466
|
+
project_type=project_type,
|
|
337
467
|
)
|
|
338
468
|
|
|
339
469
|
@traced(name="documents_extract_async", run_type="uipath")
|
|
@@ -343,40 +473,55 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
343
473
|
tag: str,
|
|
344
474
|
file: Optional[FileContent] = None,
|
|
345
475
|
file_path: Optional[str] = None,
|
|
346
|
-
|
|
347
|
-
|
|
476
|
+
project_type: ProjectType = ProjectType.IXP,
|
|
477
|
+
document_type_name: Optional[str] = None,
|
|
478
|
+
) -> Union[ExtractionResponse, ExtractionResponseIXP]:
|
|
479
|
+
"""Asynchronously version of the [`extract`][uipath._services.documents_service.DocumentsService.extract] method."""
|
|
348
480
|
if file is None and file_path is None:
|
|
349
481
|
raise ValueError("Either `file` or `file_path` must be provided")
|
|
350
482
|
if file is not None and file_path is not None:
|
|
351
483
|
raise ValueError("`file` and `file_path` are mutually exclusive")
|
|
484
|
+
if project_type == ProjectType.MODERN and document_type_name is None:
|
|
485
|
+
raise ValueError(
|
|
486
|
+
"`document_type_name` must be provided when `project_type` is `ProjectType.MODERN`"
|
|
487
|
+
)
|
|
352
488
|
|
|
353
489
|
project_id = await self._get_project_id_and_validate_tag_async(
|
|
354
|
-
project_name=project_name, tag=tag
|
|
490
|
+
project_name=project_name, project_type=project_type, tag=tag
|
|
355
491
|
)
|
|
356
492
|
|
|
357
|
-
if file_path
|
|
358
|
-
with open(Path(file_path), "rb") as handle:
|
|
359
|
-
document_id = await self._start_digitization_async(
|
|
360
|
-
project_id=project_id, file=handle
|
|
361
|
-
)
|
|
362
|
-
else:
|
|
493
|
+
with open(Path(file_path), "rb") if file_path else nullcontext(file) as handle:
|
|
363
494
|
document_id = await self._start_digitization_async(
|
|
364
495
|
project_id=project_id,
|
|
365
|
-
file=
|
|
496
|
+
file=handle, # type: ignore
|
|
366
497
|
)
|
|
367
498
|
|
|
499
|
+
document_type_id = await self._get_document_type_id_async(
|
|
500
|
+
project_id=project_id,
|
|
501
|
+
document_type_name=document_type_name,
|
|
502
|
+
project_type=project_type,
|
|
503
|
+
)
|
|
504
|
+
|
|
368
505
|
operation_id = await self._start_extraction_async(
|
|
369
|
-
project_id=project_id,
|
|
506
|
+
project_id=project_id,
|
|
507
|
+
tag=tag,
|
|
508
|
+
document_type_id=document_type_id,
|
|
509
|
+
document_id=document_id,
|
|
370
510
|
)
|
|
371
511
|
|
|
372
512
|
return await self._wait_for_extraction_async(
|
|
373
|
-
project_id=project_id,
|
|
513
|
+
project_id=project_id,
|
|
514
|
+
tag=tag,
|
|
515
|
+
document_type_id=document_type_id,
|
|
516
|
+
operation_id=operation_id,
|
|
517
|
+
project_type=project_type,
|
|
374
518
|
)
|
|
375
519
|
|
|
376
520
|
def _start_validation(
|
|
377
521
|
self,
|
|
378
522
|
project_id: str,
|
|
379
523
|
tag: str,
|
|
524
|
+
document_type_id: str,
|
|
380
525
|
action_title: str,
|
|
381
526
|
action_priority: ActionPriority,
|
|
382
527
|
action_catalog: str,
|
|
@@ -388,7 +533,7 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
388
533
|
return self.request(
|
|
389
534
|
"POST",
|
|
390
535
|
url=Endpoint(
|
|
391
|
-
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{
|
|
536
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/validation/start"
|
|
392
537
|
),
|
|
393
538
|
params={"api-version": 1.1},
|
|
394
539
|
headers=self._get_common_headers(),
|
|
@@ -409,6 +554,7 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
409
554
|
self,
|
|
410
555
|
project_id: str,
|
|
411
556
|
tag: str,
|
|
557
|
+
document_type_id: str,
|
|
412
558
|
action_title: str,
|
|
413
559
|
action_priority: ActionPriority,
|
|
414
560
|
action_catalog: str,
|
|
@@ -421,7 +567,7 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
421
567
|
await self.request_async(
|
|
422
568
|
"POST",
|
|
423
569
|
url=Endpoint(
|
|
424
|
-
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{
|
|
570
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/validation/start"
|
|
425
571
|
),
|
|
426
572
|
params={"api-version": 1.1},
|
|
427
573
|
headers=self._get_common_headers(),
|
|
@@ -440,25 +586,25 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
440
586
|
).json()["operationId"]
|
|
441
587
|
|
|
442
588
|
def _get_validation_result(
|
|
443
|
-
self, project_id: str, tag: str, operation_id: str
|
|
589
|
+
self, project_id: str, tag: str, document_type_id: str, operation_id: str
|
|
444
590
|
) -> Dict: # type: ignore
|
|
445
591
|
return self.request(
|
|
446
592
|
method="GET",
|
|
447
593
|
url=Endpoint(
|
|
448
|
-
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{
|
|
594
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/validation/result/{operation_id}"
|
|
449
595
|
),
|
|
450
596
|
params={"api-version": 1.1},
|
|
451
597
|
headers=self._get_common_headers(),
|
|
452
598
|
).json()
|
|
453
599
|
|
|
454
600
|
async def _get_validation_result_async(
|
|
455
|
-
self, project_id: str, tag: str, operation_id: str
|
|
601
|
+
self, project_id: str, tag: str, document_type_id: str, operation_id: str
|
|
456
602
|
) -> Dict: # type: ignore
|
|
457
603
|
return (
|
|
458
604
|
await self.request_async(
|
|
459
605
|
method="GET",
|
|
460
606
|
url=Endpoint(
|
|
461
|
-
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{
|
|
607
|
+
f"/du_/api/framework/projects/{project_id}/{tag}/document-types/{document_type_id}/validation/result/{operation_id}"
|
|
462
608
|
),
|
|
463
609
|
params={"api-version": 1.1},
|
|
464
610
|
headers=self._get_common_headers(),
|
|
@@ -466,43 +612,58 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
466
612
|
).json()
|
|
467
613
|
|
|
468
614
|
def _wait_for_create_validation_action(
|
|
469
|
-
self, project_id: str, tag: str, operation_id: str
|
|
615
|
+
self, project_id: str, tag: str, document_type_id: str, operation_id: str
|
|
470
616
|
) -> ValidationAction:
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
617
|
+
def result_getter() -> Tuple[Any, Optional[Any], Optional[Any]]:
|
|
618
|
+
result = self._get_validation_result(
|
|
619
|
+
project_id=project_id,
|
|
620
|
+
tag=tag,
|
|
621
|
+
document_type_id=document_type_id,
|
|
622
|
+
operation_id=operation_id,
|
|
623
|
+
)
|
|
624
|
+
return (
|
|
625
|
+
result["status"],
|
|
626
|
+
result.get("error", None),
|
|
478
627
|
result.get("result", None),
|
|
479
|
-
)
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
response = self._wait_for_operation(
|
|
631
|
+
result_getter=result_getter,
|
|
480
632
|
wait_statuses=["NotStarted", "Running"],
|
|
481
633
|
success_status="Succeeded",
|
|
482
634
|
)
|
|
483
635
|
|
|
484
636
|
response["projectId"] = project_id
|
|
485
637
|
response["tag"] = tag
|
|
638
|
+
response["documentTypeId"] = document_type_id
|
|
486
639
|
response["operationId"] = operation_id
|
|
487
640
|
return ValidationAction.model_validate(response)
|
|
488
641
|
|
|
489
642
|
async def _wait_for_create_validation_action_async(
|
|
490
|
-
self, project_id: str, tag: str, operation_id: str
|
|
643
|
+
self, project_id: str, tag: str, document_type_id: str, operation_id: str
|
|
491
644
|
) -> ValidationAction:
|
|
492
|
-
async def
|
|
645
|
+
async def result_getter_async() -> Tuple[Any, Optional[Any], Optional[Any]]:
|
|
493
646
|
result = await self._get_validation_result_async(
|
|
494
|
-
project_id=project_id,
|
|
647
|
+
project_id=project_id,
|
|
648
|
+
tag=tag,
|
|
649
|
+
document_type_id=document_type_id,
|
|
650
|
+
operation_id=operation_id,
|
|
651
|
+
)
|
|
652
|
+
return (
|
|
653
|
+
result["status"],
|
|
654
|
+
result.get("error", None),
|
|
655
|
+
result.get("result", None),
|
|
495
656
|
)
|
|
496
|
-
return result["status"], result.get("result", None)
|
|
497
657
|
|
|
498
658
|
response = await self._wait_for_operation_async(
|
|
499
|
-
result_getter=
|
|
659
|
+
result_getter=result_getter_async,
|
|
500
660
|
wait_statuses=["NotStarted", "Running"],
|
|
501
661
|
success_status="Succeeded",
|
|
502
662
|
)
|
|
503
663
|
|
|
504
664
|
response["projectId"] = project_id
|
|
505
665
|
response["tag"] = tag
|
|
666
|
+
response["documentTypeId"] = document_type_id
|
|
506
667
|
response["operationId"] = operation_id
|
|
507
668
|
return ValidationAction.model_validate(response)
|
|
508
669
|
|
|
@@ -546,7 +707,8 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
546
707
|
"""
|
|
547
708
|
operation_id = self._start_validation(
|
|
548
709
|
project_id=extraction_response.project_id,
|
|
549
|
-
tag=extraction_response.tag,
|
|
710
|
+
tag=extraction_response.tag,
|
|
711
|
+
document_type_id=extraction_response.document_type_id,
|
|
550
712
|
action_title=action_title,
|
|
551
713
|
action_priority=action_priority,
|
|
552
714
|
action_catalog=action_catalog,
|
|
@@ -559,6 +721,7 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
559
721
|
return self._wait_for_create_validation_action(
|
|
560
722
|
project_id=extraction_response.project_id,
|
|
561
723
|
tag=extraction_response.tag,
|
|
724
|
+
document_type_id=extraction_response.document_type_id,
|
|
562
725
|
operation_id=operation_id,
|
|
563
726
|
)
|
|
564
727
|
|
|
@@ -573,11 +736,11 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
573
736
|
storage_bucket_directory_path: str,
|
|
574
737
|
extraction_response: ExtractionResponse,
|
|
575
738
|
) -> ValidationAction:
|
|
576
|
-
"""
|
|
577
|
-
# Add reference to sync method docstring
|
|
739
|
+
"""Asynchronous version of the [`create_validation_action`][uipath._services.documents_service.DocumentsService.create_validation_action] method."""
|
|
578
740
|
operation_id = await self._start_validation_async(
|
|
579
741
|
project_id=extraction_response.project_id,
|
|
580
|
-
tag=extraction_response.tag,
|
|
742
|
+
tag=extraction_response.tag,
|
|
743
|
+
document_type_id=extraction_response.document_type_id,
|
|
581
744
|
action_title=action_title,
|
|
582
745
|
action_priority=action_priority,
|
|
583
746
|
action_catalog=action_catalog,
|
|
@@ -590,6 +753,7 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
590
753
|
return await self._wait_for_create_validation_action_async(
|
|
591
754
|
project_id=extraction_response.project_id,
|
|
592
755
|
tag=extraction_response.tag,
|
|
756
|
+
document_type_id=extraction_response.document_type_id,
|
|
593
757
|
operation_id=operation_id,
|
|
594
758
|
)
|
|
595
759
|
|
|
@@ -613,17 +777,22 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
613
777
|
validated_result = service.get_validation_result(validation_action)
|
|
614
778
|
```
|
|
615
779
|
"""
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
780
|
+
|
|
781
|
+
def result_getter() -> Tuple[str, None, Any]:
|
|
782
|
+
result = self._get_validation_result(
|
|
783
|
+
project_id=validation_action.project_id,
|
|
784
|
+
tag=validation_action.tag,
|
|
785
|
+
document_type_id=validation_action.document_type_id,
|
|
786
|
+
operation_id=validation_action.operation_id,
|
|
787
|
+
)
|
|
788
|
+
return (
|
|
789
|
+
result["result"]["actionStatus"],
|
|
790
|
+
None,
|
|
625
791
|
result["result"].get("validatedExtractionResults", None),
|
|
626
|
-
)
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
response = self._wait_for_operation(
|
|
795
|
+
result_getter=result_getter,
|
|
627
796
|
wait_statuses=["Unassigned", "Pending"],
|
|
628
797
|
success_status="Completed",
|
|
629
798
|
)
|
|
@@ -634,16 +803,19 @@ class DocumentsService(FolderContext, BaseService):
|
|
|
634
803
|
async def get_validation_result_async(
|
|
635
804
|
self, validation_action: ValidationAction
|
|
636
805
|
) -> ValidatedResult:
|
|
637
|
-
"""
|
|
806
|
+
"""Asynchronous version of the [`get_validation_result`][uipath._services.documents_service.DocumentsService.get_validation_result] method."""
|
|
638
807
|
|
|
639
|
-
async def result_getter() -> Tuple[str, Any]:
|
|
808
|
+
async def result_getter() -> Tuple[str, None, Any]:
|
|
640
809
|
result = await self._get_validation_result_async(
|
|
641
810
|
project_id=validation_action.project_id,
|
|
642
811
|
tag=validation_action.tag,
|
|
812
|
+
document_type_id=validation_action.document_type_id,
|
|
643
813
|
operation_id=validation_action.operation_id,
|
|
644
814
|
)
|
|
645
|
-
return
|
|
646
|
-
"
|
|
815
|
+
return (
|
|
816
|
+
result["result"]["actionStatus"],
|
|
817
|
+
None,
|
|
818
|
+
result["result"].get("validatedExtractionResults", None),
|
|
647
819
|
)
|
|
648
820
|
|
|
649
821
|
response = await self._wait_for_operation_async(
|
uipath/models/documents.py
CHANGED
|
@@ -18,10 +18,25 @@ class FieldType(str, Enum):
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class ActionPriority(str, Enum):
|
|
21
|
+
"""Priority levels for validation actions. More details can be found in the [official documentation](https://docs.uipath.com/action-center/automation-cloud/latest/user-guide/create-document-validation-action#configuration)."""
|
|
22
|
+
|
|
21
23
|
LOW = "Low"
|
|
24
|
+
"""Low priority"""
|
|
22
25
|
MEDIUM = "Medium"
|
|
26
|
+
"""Medium priority"""
|
|
23
27
|
HIGH = "High"
|
|
28
|
+
"""High priority"""
|
|
24
29
|
CRITICAL = "Critical"
|
|
30
|
+
"""Critical priority"""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ProjectType(str, Enum):
|
|
34
|
+
"""Project types available and supported by Documents Service."""
|
|
35
|
+
|
|
36
|
+
IXP = "IXP"
|
|
37
|
+
"""Represents an [IXP](https://docs.uipath.com/ixp/automation-cloud/latest/overview/managing-projects#creating-a-new-project) project type."""
|
|
38
|
+
MODERN = "Modern"
|
|
39
|
+
"""Represents a [DU Modern](https://docs.uipath.com/document-understanding/automation-cloud/latest/user-guide/about-document-understanding) project type."""
|
|
25
40
|
|
|
26
41
|
|
|
27
42
|
class FieldValueProjection(BaseModel):
|
|
@@ -71,9 +86,9 @@ class ExtractionResponse(BaseModel):
|
|
|
71
86
|
|
|
72
87
|
Attributes:
|
|
73
88
|
extraction_result (ExtractionResult): The result of the extraction process.
|
|
74
|
-
data_projection (List[FieldGroupValueProjection]): A simplified projection of the extracted data.
|
|
75
89
|
project_id (str): The ID of the project associated with the extraction.
|
|
76
90
|
tag (str): The tag associated with the published model version.
|
|
91
|
+
document_type_id (str): The ID of the document type associated with the extraction.
|
|
77
92
|
"""
|
|
78
93
|
|
|
79
94
|
model_config = ConfigDict(
|
|
@@ -82,9 +97,19 @@ class ExtractionResponse(BaseModel):
|
|
|
82
97
|
)
|
|
83
98
|
|
|
84
99
|
extraction_result: ExtractionResult = Field(alias="extractionResult")
|
|
85
|
-
data_projection: List[FieldGroupValueProjection] = Field(alias="dataProjection")
|
|
86
100
|
project_id: str = Field(alias="projectId")
|
|
87
101
|
tag: str
|
|
102
|
+
document_type_id: str = Field(alias="documentTypeId")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class ExtractionResponseIXP(ExtractionResponse):
|
|
106
|
+
"""A model representing the response from a document extraction process for IXP projects.
|
|
107
|
+
|
|
108
|
+
Attributes:
|
|
109
|
+
data_projection (List[FieldGroupValueProjection]): A simplified projection of the extracted data.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
data_projection: List[FieldGroupValueProjection] = Field(alias="dataProjection")
|
|
88
113
|
|
|
89
114
|
|
|
90
115
|
class ValidationAction(BaseModel):
|
|
@@ -107,6 +132,7 @@ class ValidationAction(BaseModel):
|
|
|
107
132
|
action_status: str = Field(alias="actionStatus")
|
|
108
133
|
project_id: str = Field(alias="projectId")
|
|
109
134
|
tag: str
|
|
135
|
+
document_type_id: str = Field(alias="documentTypeId")
|
|
110
136
|
operation_id: str = Field(alias="operationId")
|
|
111
137
|
|
|
112
138
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uipath
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.112
|
|
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
|
|
@@ -34,8 +34,8 @@ uipath/_cli/_auth/auth_config.json,sha256=o8J5BBFwiEtjZLHpJ_64lvnTeYeRIHaJ-Bhg0Q
|
|
|
34
34
|
uipath/_cli/_auth/index.html,sha256=uGK0CDTP8Rys_p4O_Pbd2x4tz0frKNVcumjrXnal5Nc,22814
|
|
35
35
|
uipath/_cli/_auth/localhost.crt,sha256=oGl9oLLOiouHubAt39B4zEfylFvKEtbtr_43SIliXJc,1226
|
|
36
36
|
uipath/_cli/_auth/localhost.key,sha256=X31VYXD8scZtmGA837dGX5l6G-LXHLo5ItWJhZXaz3c,1679
|
|
37
|
-
uipath/_cli/_debug/_bridge.py,sha256=
|
|
38
|
-
uipath/_cli/_debug/_runtime.py,sha256=
|
|
37
|
+
uipath/_cli/_debug/_bridge.py,sha256=iF3lI73TRyVvQDf7Zb-HUxrVrW5oAnWOPT7JIFkFL_I,28433
|
|
38
|
+
uipath/_cli/_debug/_runtime.py,sha256=cGWoyQwHaKG5EQhYqTQfIuCX--n4PBijZQ9iXiOpRIc,5748
|
|
39
39
|
uipath/_cli/_dev/_terminal/__init__.py,sha256=di_RiN9Mcp9wqyKRRqXag28vbSw8_78mCnQZNn9H-Ss,14027
|
|
40
40
|
uipath/_cli/_dev/_terminal/_components/_chat.py,sha256=NLRoy49QScHiI-q0FGykkaU8ajv1d23fx7issSALcFA,4119
|
|
41
41
|
uipath/_cli/_dev/_terminal/_components/_details.py,sha256=FbLYtJ56gqHV6CIrpzO_n9Sk_YNg4nzRKTSsbj-DBPQ,17257
|
|
@@ -72,7 +72,7 @@ uipath/_cli/_evals/mocks/mockito_mocker.py,sha256=opwfELnvuh3krnPAg0MupkHTEmhCpQ
|
|
|
72
72
|
uipath/_cli/_evals/mocks/mocks.py,sha256=IrvhtTtIuU5geopvCRglNhxKoOcChnnjQZMoYygx0PU,2225
|
|
73
73
|
uipath/_cli/_push/models.py,sha256=K3k6QUMkiNIb3M4U0EgDlKz1UELxeMXLNVAj3qyhZ4U,470
|
|
74
74
|
uipath/_cli/_push/sw_file_handler.py,sha256=ivHj0qzCvEP45M3x-Oi2edO5I-uhyHzgnidDF3JRoTk,36192
|
|
75
|
-
uipath/_cli/_runtime/_contracts.py,sha256=
|
|
75
|
+
uipath/_cli/_runtime/_contracts.py,sha256=NU7cZerrpxYTlP8-pamMBytCTMmvWy7vxPMlzFv8aBA,36231
|
|
76
76
|
uipath/_cli/_runtime/_escalation.py,sha256=x3vI98qsfRA-fL_tNkRVTFXioM5Gv2w0GFcXJJ5eQtg,7981
|
|
77
77
|
uipath/_cli/_runtime/_hitl.py,sha256=JAwTUKvxO4HpnZMwE4E0AegAPw_uYOwgt0OYcu6EvTg,11474
|
|
78
78
|
uipath/_cli/_runtime/_logging.py,sha256=srjAi3Cy6g7b8WNHiYNjaZT4t40F3XRqquuoGd2kh4Y,14019
|
|
@@ -108,7 +108,7 @@ uipath/_resources/AGENTS.md,sha256=nRQNAVeEBaBvuMzXw8uXtMnGebLClUgwIMlgb8_qU9o,1
|
|
|
108
108
|
uipath/_resources/CLAUDE.md,sha256=kYsckFWTVe948z_fNWLysCHvi9_YpchBXl3s1Ek03lU,10
|
|
109
109
|
uipath/_resources/CLI_REFERENCE.md,sha256=M_SCtSjRhj1XwfgSFLfHJJahYXEd_CSQ_EnjLQAn-2Y,6470
|
|
110
110
|
uipath/_resources/REQUIRED_STRUCTURE.md,sha256=3laqGiNa3kauJ7jRI1d7w_fWKUDkqYBjcTT_6_8FAGk,1417
|
|
111
|
-
uipath/_resources/SDK_REFERENCE.md,sha256=
|
|
111
|
+
uipath/_resources/SDK_REFERENCE.md,sha256=xx6-FzXQpva0eeCeLgscrzaaWrVyFedxxACAD7xVlu4,18663
|
|
112
112
|
uipath/_services/__init__.py,sha256=_LNy4u--VlhVtTO66bULbCoBjyJBTuyh9jnzjWrv-h4,1140
|
|
113
113
|
uipath/_services/_base_service.py,sha256=x9-9jhPzn9Z16KRdFHhJNvV-FZHvTniMsDfxlS4Cutk,5782
|
|
114
114
|
uipath/_services/actions_service.py,sha256=2RPMR-hFMsOlqEyjIf3aF7-lrf57jdrSD0pBjj0Kyko,16040
|
|
@@ -118,7 +118,7 @@ uipath/_services/attachments_service.py,sha256=NPQYK7CGjfBaNT_1S5vEAfODmOChTbQZf
|
|
|
118
118
|
uipath/_services/buckets_service.py,sha256=5s8tuivd7GUZYj774DDUYTa0axxlUuesc4EBY1V5sdk,18496
|
|
119
119
|
uipath/_services/connections_service.py,sha256=tKJHHOKQYKR6LkgB-V_2d0vFpLEdFeMzwj_xmBVHUDw,18416
|
|
120
120
|
uipath/_services/context_grounding_service.py,sha256=Pjx-QQQEiSKD-hY6ityj3QUSALN3fIcKLLHr_NZ0d_g,37117
|
|
121
|
-
uipath/_services/documents_service.py,sha256=
|
|
121
|
+
uipath/_services/documents_service.py,sha256=2LZyGVYXtsC9ajsNpmLTmbgAXF13YeS4N_LObh4o4kA,31389
|
|
122
122
|
uipath/_services/entities_service.py,sha256=QKCLE6wRgq3HZraF-M2mljy-8il4vsNHrQhUgkewVVk,14028
|
|
123
123
|
uipath/_services/external_application_service.py,sha256=gZhnGgLn7ZYUZzZF7AumB14QEPanVY-D_02FqEcAFtw,5478
|
|
124
124
|
uipath/_services/folder_service.py,sha256=9JqgjKhWD-G_KUnfUTP2BADxL6OK9QNZsBsWZHAULdE,2749
|
|
@@ -204,7 +204,7 @@ uipath/models/buckets.py,sha256=N3Lj_dVCv709-ywhOOdyCSvsuLn41eGuAfSiik6Q6F8,1285
|
|
|
204
204
|
uipath/models/connections.py,sha256=jmzlfnddqlxjmiVhqsETRV6TQPH3fFqJGsygG0gUf7g,2745
|
|
205
205
|
uipath/models/context_grounding.py,sha256=3MaF2Fv2QYle8UUWvKGkCN5XGpx2T4a34fdbBqJ2fCs,1137
|
|
206
206
|
uipath/models/context_grounding_index.py,sha256=OhRyxZDHDSrEmBFK0-JLqMMMT64jir4XkHtQ54IKtc0,2683
|
|
207
|
-
uipath/models/documents.py,sha256=
|
|
207
|
+
uipath/models/documents.py,sha256=fLmo75okk1peDIiCmH3hmG8GbOte6fjkhwX8EaiOQJY,5124
|
|
208
208
|
uipath/models/entities.py,sha256=x6jbq4o_QhgL_pCgvHFsp9O8l333kQhn8e9ZCBs72UM,9823
|
|
209
209
|
uipath/models/errors.py,sha256=WCxxHBlLzLF17YxjqsFkkyBLwEQM_dc6fFU5qmBjD4A,597
|
|
210
210
|
uipath/models/exceptions.py,sha256=f71VsUyonK2uuH1Cs0tpP6f9dec6v6cffL1Z9EjTxm0,1870
|
|
@@ -224,8 +224,8 @@ uipath/tracing/_utils.py,sha256=zMjiKjNpSN3YQNEU4-u5AAvPtUsi8QuEqNLya89jfAU,1446
|
|
|
224
224
|
uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
|
|
225
225
|
uipath/utils/_endpoints_manager.py,sha256=tnF_FiCx8qI2XaJDQgYkMN_gl9V0VqNR1uX7iawuLp8,8230
|
|
226
226
|
uipath/utils/dynamic_schema.py,sha256=w0u_54MoeIAB-mf3GmwX1A_X8_HDrRy6p998PvX9evY,3839
|
|
227
|
-
uipath-2.1.
|
|
228
|
-
uipath-2.1.
|
|
229
|
-
uipath-2.1.
|
|
230
|
-
uipath-2.1.
|
|
231
|
-
uipath-2.1.
|
|
227
|
+
uipath-2.1.112.dist-info/METADATA,sha256=n-2HKHyHbL9qb7eTshpzMv_HAh1ZDEo754AeJ6MwXag,6626
|
|
228
|
+
uipath-2.1.112.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
229
|
+
uipath-2.1.112.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
|
|
230
|
+
uipath-2.1.112.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
|
|
231
|
+
uipath-2.1.112.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|