11import asyncio
22import os
33import uuid
4- from typing import Any , Dict , List , Optional , Tuple
4+ from typing import Any , Dict , List , Optional
55
66from uipath .core .tracing import traced
77
@@ -395,12 +395,12 @@ async def create_async(
395395 Raises:
396396 Exception: If neither app_name nor app_key is provided for app-specific actions
397397 """
398- app_folder_path = app_folder_path if app_folder_path else self ._folder_path
399-
400398 (key , action_schema ) = (
401399 (app_key , None )
402400 if app_key
403- else await self ._get_app_key_and_schema_async (app_name , app_folder_path )
401+ else await self ._get_app_key_and_schema_async (
402+ app_name , app_folder_path , app_folder_key
403+ )
404404 )
405405 spec = _create_spec (
406406 title = title ,
@@ -481,12 +481,10 @@ def create(
481481 Raises:
482482 Exception: If neither app_name nor app_key is provided for app-specific actions
483483 """
484- app_folder_path = app_folder_path if app_folder_path else self ._folder_path
485-
486484 (key , action_schema ) = (
487485 (app_key , None )
488486 if app_key
489- else self ._get_app_key_and_schema (app_name , app_folder_path )
487+ else self ._get_app_key_and_schema (app_name , app_folder_path , app_folder_key )
490488 )
491489 spec = _create_spec (
492490 title = title ,
@@ -588,8 +586,11 @@ async def retrieve_async(
588586 return Task .model_validate (response .json ())
589587
590588 async def _get_app_key_and_schema_async (
591- self , app_name : Optional [str ], app_folder_path : Optional [str ]
592- ) -> Tuple [str , Optional [TaskSchema ]]:
589+ self ,
590+ app_name : str | None ,
591+ app_folder_path : str | None ,
592+ app_folder_key : str | None ,
593+ ) -> tuple [str , TaskSchema | None ]:
593594 if not app_name :
594595 raise Exception ("appName or appKey is required" )
595596 spec = _retrieve_app_key_spec (app_name = app_name )
@@ -603,7 +604,7 @@ async def _get_app_key_and_schema_async(
603604 )
604605 try :
605606 deployed_app = self ._extract_deployed_app (
606- response .json ()["deployed" ], app_folder_path
607+ response .json ()["deployed" ], app_name , app_folder_path , app_folder_key
607608 )
608609 action_schema = deployed_app ["actionSchema" ]
609610 deployed_app_key = deployed_app ["systemName" ]
@@ -624,8 +625,11 @@ async def _get_app_key_and_schema_async(
624625 raise Exception ("Failed to deserialize action schema" ) from KeyError
625626
626627 def _get_app_key_and_schema (
627- self , app_name : Optional [str ], app_folder_path : Optional [str ]
628- ) -> Tuple [str , Optional [TaskSchema ]]:
628+ self ,
629+ app_name : str | None ,
630+ app_folder_path : str | None ,
631+ app_folder_key : str | None ,
632+ ) -> tuple [str , TaskSchema | None ]:
629633 if not app_name :
630634 raise Exception ("appName or appKey is required" )
631635
@@ -641,7 +645,7 @@ def _get_app_key_and_schema(
641645
642646 try :
643647 deployed_app = self ._extract_deployed_app (
644- response .json ()["deployed" ], app_folder_path
648+ response .json ()["deployed" ], app_name , app_folder_path , app_folder_key
645649 )
646650 action_schema = deployed_app ["actionSchema" ]
647651 deployed_app_key = deployed_app ["systemName" ]
@@ -661,27 +665,45 @@ def _get_app_key_and_schema(
661665 except KeyError :
662666 raise Exception ("Failed to deserialize action schema" ) from KeyError
663667
664- # should be removed after folder filtering support is added on apps API
665668 def _extract_deployed_app (
666- self , deployed_apps : List [Dict [str , Any ]], app_folder_path : Optional [str ]
667- ) -> Dict [str , Any ]:
668- if len (deployed_apps ) > 1 and not app_folder_path :
669- raise Exception ("Multiple app schemas found" )
670- try :
671- if app_folder_path :
672- return next (
673- app
674- for app in deployed_apps
675- if app ["deploymentFolder" ]["fullyQualifiedName" ] == app_folder_path
676- )
677- else :
669+ self ,
670+ deployed_apps : list [dict [str , Any ]],
671+ app_name : str ,
672+ app_folder_path : str | None ,
673+ app_folder_key : str | None ,
674+ ) -> dict [str , Any ]:
675+ # try extracting the requested app schema. folder path has priority over folder key
676+ filtered_apps_by_name = [
677+ app for app in deployed_apps if app ["deploymentTitle" ] == app_name
678+ ]
679+ if len (filtered_apps_by_name ) < 1 :
680+ raise Exception (f"App '{ app_name } ' was not found in the current tenant" )
681+
682+ # priority: app_folder_path -> app_folder_key -> self._folder_path -> self._folder_key
683+ candidates = [
684+ (app_folder_path , "fullyQualifiedName" , "fully qualified name" ),
685+ (app_folder_key , "key" , "identifier" ),
686+ (self ._folder_path , "fullyQualifiedName" , "fully qualified name" ),
687+ (self ._folder_key , "key" , "identifier" ),
688+ ]
689+
690+ for value , field , label in candidates :
691+ if not value :
692+ continue
693+ try :
678694 return next (
679695 app
680- for app in deployed_apps
681- if app ["deploymentFolder" ]["key" ] == self . _folder_key
696+ for app in filtered_apps_by_name
697+ if app ["deploymentFolder" ][field ] == value
682698 )
683- except StopIteration :
684- raise KeyError from StopIteration
699+ except StopIteration :
700+ raise Exception (
701+ f"App '{ app_name } ' was not found in folder with { label } '{ value } '"
702+ ) from StopIteration
703+
704+ raise Exception (
705+ f"App '{ app_name } ' was found but no folder key or folder path was provided to select a deployment"
706+ )
685707
686708 @property
687709 def custom_headers (self ) -> Dict [str , str ]:
0 commit comments