Repository: fractal-analytics-platform/fractal-client (language: python)

Issue:
Add `fractal workflow list` (list workflows for a given project)

Add `fractal workflow list` (list workflows for a given project)



Discussion / hints:

Fix patch:
diff --git a/fractal/client/cmd/__init__.py b/fractal/client/cmd/__init__.py
index ea9d9c767..abc4f4b82 100644
--- a/fractal/client/cmd/__init__.py
+++ b/fractal/client/cmd/__init__.py
@@ -23,6 +23,7 @@
 from ._workflow import workflow_apply
 from ._workflow import workflow_delete
 from ._workflow import workflow_edit
+from ._workflow import workflow_list
 from ._workflow import workflow_new
 from ._workflow import workflow_remove_task
 from ._workflow import workflow_show
@@ -149,6 +150,8 @@ async def workflow(
         iface = await workflow_show(client, **kwargs)
     elif subcmd == "new":
         iface = await workflow_new(client, batch=batch, **kwargs)
+    elif subcmd == "list":
+        iface = await workflow_list(client, batch=batch, **kwargs)
     elif subcmd == "edit":
         iface = await workflow_edit(client, **kwargs)
     elif subcmd == "delete":
diff --git a/fractal/client/cmd/_workflow.py b/fractal/client/cmd/_workflow.py
index 06ed095b4..40fe99196 100644
--- a/fractal/client/cmd/_workflow.py
+++ b/fractal/client/cmd/_workflow.py
@@ -41,6 +41,20 @@ async def workflow_new(
         return RichJsonInterface(retcode=0, data=workflow.dict())
 
 
+async def workflow_list(
+    client: AuthClient,
+    project_id: int,
+    batch: bool = False,
+    **kwargs,
+) -> RichJsonInterface:
+
+    res = await client.get(
+        f"{settings.BASE_URL}/project/{project_id}/workflows/"
+    )
+    workflow_list = check_response(res, expected_status_code=200)
+    return RichJsonInterface(retcode=0, data=workflow_list)
+
+
 async def workflow_delete(
     client: AuthClient,
     *,
diff --git a/fractal/client/parser.py b/fractal/client/parser.py
index 5a0421a19..9f8e70f89 100644
--- a/fractal/client/parser.py
+++ b/fractal/client/parser.py
@@ -292,6 +292,15 @@
     help="Project ID",
 )
 
+# workflow list
+workflow_list_parser = workflow_subparsers.add_parser(
+    "list", help="List workflows for given project"
+)
+workflow_list_parser.add_argument(
+    "project_id",
+    help="Project ID",
+)
+
 # workflow delete
 workflow_new_parser = workflow_subparsers.add_parser(
     "delete", help="Delete workflow"


Test patch:
diff --git a/tests/test_workflow.py b/tests/test_workflow.py
index 5c4777a25..2f387eb32 100644
--- a/tests/test_workflow.py
+++ b/tests/test_workflow.py
@@ -19,6 +19,56 @@ async def test_workflow_new(clear_db, testserver, register_user, invoke):
     assert res_wf.data["project_id"] == res_pj.data["id"]
 
 
+async def test_workflow_list(clear_db, testserver, register_user, invoke):
+    PROJECT_NAME = "project_name"
+    PROJECT_PATH = "project_path"
+    res_pj = await invoke(f"project new {PROJECT_NAME} {PROJECT_PATH}")
+    project_id = res_pj.data["id"]
+    debug(project_id)
+
+    res_wf = await invoke(f"workflow new WF1 {project_id}")
+    res_wf.show()
+    assert res_wf.retcode == 0
+
+    res_wf = await invoke(f"workflow new WF2 {project_id}")
+    res_wf.show()
+    assert res_wf.retcode == 0
+
+    res_list = await invoke(f"workflow list {project_id}")
+    debug(res_list)
+    debug(res_list.data)
+    assert res_list.retcode == 0
+    assert len(res_list.data) == 2
+
+
+async def test_workflow_list_when_two_projects_exist(
+    clear_db, testserver, register_user, invoke, tmp_path
+):
+    res_pj1 = await invoke(f"project new PRJ1 {str(tmp_path)}/prj1")
+    res_pj2 = await invoke(f"project new PRJ2 {str(tmp_path)}/prj2")
+    project_id_1 = res_pj1.data["id"]
+    project_id_2 = res_pj2.data["id"]
+
+    NUM_WF_PROJECT_1 = 2
+    NUM_WF_PROJECT_2 = 4
+
+    for wf in range(NUM_WF_PROJECT_1):
+        res_wf = await invoke(f"workflow new WF{wf} {project_id_1}")
+        assert res_wf.retcode == 0
+
+    for wf in range(NUM_WF_PROJECT_2):
+        res_wf = await invoke(f"workflow new WF{wf} {project_id_2}")
+        assert res_wf.retcode == 0
+
+    res_list_1 = await invoke(f"workflow list {project_id_1}")
+    assert res_list_1.retcode == 0
+    assert len(res_list_1.data) == NUM_WF_PROJECT_1
+
+    res_list_2 = await invoke(f"workflow list {project_id_2}")
+    assert res_list_2.retcode == 0
+    assert len(res_list_2.data) == NUM_WF_PROJECT_2
+
+
 async def test_add_task(
     clear_db,
     testserver,