From cae8a25c442fb40106e26f393493613745c21ddd Mon Sep 17 00:00:00 2001 From: Fabio Zadrozny Date: Thu, 28 Nov 2024 14:28:46 -0300 Subject: [PATCH] Fixes when listing actions/show progress when creating input. --- docs/changelog.md | 6 +++- .../src/sema4ai_code/robo/collect_actions.py | 29 +++++++++++++++---- .../sema4ai_code/robo/collect_actions_ast.py | 26 ++++++++++++----- .../sema4ai_code/robocorp_language_server.py | 2 +- .../robo/test_list_actions.py | 4 ++- .../vscode-client/src/robo/actionInputs.ts | 27 +++++++++++++++++ 6 files changed, 78 insertions(+), 16 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index f25f31a8..1431ed5f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,7 +7,11 @@ - New icons for the extension. - Aligned the release details for the extension - Update Agent CLI to `0.2.1` -- Add `Start Data Server` and `Stop Data Server` commands +- Add `Start Data Server` and `Stop Data Server` commands +- Search for actions/queries/predictions considering all glob patterns supported by `sema4ai.actions`. +- Use `package.yaml` directory as the `cwd` when searching for actions/queries/predictions if available (otherwise imports could fail). +- Show progress when creating the input file for an action/query/prediction. + ## New in 2.8.1 (2024-11-21) - Version bump due to error in deploy pipeline. diff --git a/sema4ai/src/sema4ai_code/robo/collect_actions.py b/sema4ai/src/sema4ai_code/robo/collect_actions.py index bc8860ed..8a608253 100644 --- a/sema4ai/src/sema4ai_code/robo/collect_actions.py +++ b/sema4ai/src/sema4ai_code/robo/collect_actions.py @@ -156,7 +156,11 @@ def _execute_within_user_env( def _call_sema4ai_actions( - pm: PluginManager, monitor: IMonitor, argument: str, uri: str + pm: PluginManager, + monitor: IMonitor, + argument: str, + uri: str, + cwd: str | None = None, ) -> ActionResult: """Note: the way this works is that we'll launch a separate script using the user environment to collect the actions information. @@ -183,13 +187,26 @@ def _call_sema4ai_actions( "--skip-lint", ] + search_cwd_from: str = "" if not path.is_dir(): # If a file is given, we'll use the glob to list the actions just in that file. args.append("--glob") args.append(file_name) - cwd = str(path.parent) + search_cwd_from = str(path.parent) else: - cwd = str(path) + search_cwd_from = str(path) + + if cwd is None: + p = Path(search_cwd_from) + while True: + if (p / "package.yaml").exists(): + cwd = str(p) + break + if not p.parent or p.parent == p: + # Couldn't find package.yaml, use the directory where we started searching from! + cwd = search_cwd_from + break + p = p.parent return _execute_within_user_env(pm, uri, args, monitor, cwd) @@ -230,9 +247,11 @@ def _get_actions_version( def collect_actions_full_and_slow( - pm: PluginManager, uri: str, monitor: IMonitor + pm: PluginManager, uri: str, action_package_yaml_directory: str, monitor: IMonitor ) -> ActionResult: - return _call_sema4ai_actions(pm, monitor, "list", uri) + return _call_sema4ai_actions( + pm, monitor, "list", uri, cwd=action_package_yaml_directory + ) def get_metadata(pm: PluginManager, uri: str, monitor: IMonitor) -> ActionResult[dict]: diff --git a/sema4ai/src/sema4ai_code/robo/collect_actions_ast.py b/sema4ai/src/sema4ai_code/robo/collect_actions_ast.py index ba37fd7a..01632e25 100644 --- a/sema4ai/src/sema4ai_code/robo/collect_actions_ast.py +++ b/sema4ai/src/sema4ai_code/robo/collect_actions_ast.py @@ -124,19 +124,29 @@ def _make_action_info( } +DEFAULT_ACTION_SEARCH_GLOB = ( + "*action*.py|*query*.py|*queries*.py|*predict*.py|*datasource*.py|*data_source*.py" +) + +globs = DEFAULT_ACTION_SEARCH_GLOB.split("|") + + def iter_actions(root_directory: Path) -> Iterator[ActionInfoTypedDict]: """ Iterates over the actions just by using the AST (this means that it doesn't give complete information, rather, it is a fast way to provide just simple metadata such as the action name and location). """ + import fnmatch + f: Path for f in _collect_py_files(root_directory): - if "action" in f.name: - try: - for funcdef, decorator_id in _collect_actions_from_file(f): - yield _make_action_info( - uris.from_fs_path(str(f)), funcdef, decorator_id - ) - except Exception: - log.error(f"Unable to collect @actions from {f}") + for glob in globs: + if fnmatch.fnmatch(f.name, glob): + try: + for funcdef, decorator_id in _collect_actions_from_file(f): + yield _make_action_info( + uris.from_fs_path(str(f)), funcdef, decorator_id + ) + except Exception: + log.error(f"Unable to collect @action/@query/@predict from {f}") diff --git a/sema4ai/src/sema4ai_code/robocorp_language_server.py b/sema4ai/src/sema4ai_code/robocorp_language_server.py index 8ece782b..4cc810d8 100644 --- a/sema4ai/src/sema4ai_code/robocorp_language_server.py +++ b/sema4ai/src/sema4ai_code/robocorp_language_server.py @@ -789,7 +789,7 @@ def _list_actions_full_and_slow( ) result = collect_actions_full_and_slow( - self._pm, action_package_uri, monitor + self._pm, action_package_uri, action_package_yaml_directory, monitor ) if not result.success: return result.as_dict() diff --git a/sema4ai/tests/sema4ai_code_tests/robo/test_list_actions.py b/sema4ai/tests/sema4ai_code_tests/robo/test_list_actions.py index c7b35530..94b9191d 100644 --- a/sema4ai/tests/sema4ai_code_tests/robo/test_list_actions.py +++ b/sema4ai/tests/sema4ai_code_tests/robo/test_list_actions.py @@ -282,6 +282,8 @@ def test_list_actions_full( extract_info, ) + root: Path + uri: str actions_version, pm, monitor, uri, root = actions_version_fixture action_path = root / "my_action.py" @@ -289,7 +291,7 @@ def test_list_actions_full( uri = uris.from_fs_path(str(root)) - result = collect_actions_full_and_slow(pm, uri, monitor) + result = collect_actions_full_and_slow(pm, uri, str(root), monitor) assert result.success, result.message lst = result.result assert lst diff --git a/sema4ai/vscode-client/src/robo/actionInputs.ts b/sema4ai/vscode-client/src/robo/actionInputs.ts index 340f58b2..6b0bc437 100644 --- a/sema4ai/vscode-client/src/robo/actionInputs.ts +++ b/sema4ai/vscode-client/src/robo/actionInputs.ts @@ -54,8 +54,35 @@ export const createActionInputs = async ( actionName: string, targetInput: string, actionPackageYamlDirectory: string +): Promise => { + const result = await window.withProgress( + { + location: vscode.ProgressLocation.Window, + title: "Creating input file", + cancellable: false, + }, + async (progress) => { + return await _createActionInputs( + actionFileUri, + actionName, + targetInput, + actionPackageYamlDirectory, + progress + ); + } + ); + return result; +}; + +const _createActionInputs = async ( + actionFileUri: vscode.Uri, + actionName: string, + targetInput: string, + actionPackageYamlDirectory: string, + progress: vscode.Progress<{ message?: string; increment?: number }> ): Promise => { try { + progress.report({ message: "Listing actions/queries/predictions in the package" }); const result: any = await langServer.sendRequest("listActionsFullAndSlow", { action_package_uri: actionFileUri.toString(), action_package_yaml_directory: actionPackageYamlDirectory,