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

Issue:
Update common
Ref:
* https://github.com/fractal-analytics-platform/fractal-common/pull/32
Fix dataset-edit command
It has several obsolete arguments.


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdf70e935..b6996aed7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@
 * Update `fractal task edit` command (\#439).
 * Disable `argparse` abbreviation for CLI commands (\#441).
 * Improve task-collection log formatting (\#443).
+* Update `DatasetUpdate` schema (\#461).
 
 # 1.0.5
 
diff --git a/fractal/cmd/__init__.py b/fractal/cmd/__init__.py
index 7f8c67ae2..6b6a3d124 100644
--- a/fractal/cmd/__init__.py
+++ b/fractal/cmd/__init__.py
@@ -99,13 +99,11 @@ async def dataset(
     elif subcmd == "edit":
         project_id = int(kwargs.pop("project_id"))
         dataset_id = int(kwargs.pop("dataset_id"))
-
-        dataset_update_dict = kwargs
         iface = await dataset_edit(
             client,
             project_id=project_id,
             dataset_id=dataset_id,
-            dataset_update_dict=dataset_update_dict,
+            **kwargs,
         )
     elif subcmd == "delete":
         iface = await dataset_delete(client, **kwargs)
diff --git a/fractal/cmd/_dataset.py b/fractal/cmd/_dataset.py
index eb7d9417b..3757c5904 100644
--- a/fractal/cmd/_dataset.py
+++ b/fractal/cmd/_dataset.py
@@ -1,7 +1,6 @@
 import json
 import os
-from typing import Any
-from typing import Dict
+from typing import Optional
 
 from rich.table import Table
 
@@ -69,18 +68,31 @@ async def dataset_edit(
     *,
     project_id: int,
     dataset_id: int,
-    dataset_update_dict: Dict[str, Any],
+    new_name: Optional[str] = None,
+    new_type: Optional[str] = None,
+    meta_file: Optional[str] = None,
+    make_read_only: bool = False,
+    remove_read_only: bool = False,
+    **kwargs,
 ) -> BaseInterface:
 
-    metadata_filename = dataset_update_dict.get("metadata")
-    if metadata_filename == "none":
-        dataset_update_dict.update(meta={})
-    elif metadata_filename is not None:
-        meta = json.loads(metadata_filename)
+    # Prepare payload
+    dataset_update_dict = {}
+    if new_name:
+        dataset_update_dict["name"] = new_name
+    if new_type:
+        dataset_update_dict["type"] = new_type
+    if meta_file:
+        with open(meta_file, "r") as f:
+            meta = json.load(f)
         dataset_update_dict.update(meta=meta)
-
+    if make_read_only:
+        dataset_update_dict["read_only"] = True
+    if remove_read_only:
+        dataset_update_dict["read_only"] = False
     dataset_update = DatasetUpdate(**dataset_update_dict)
     payload = dataset_update.dict(exclude_unset=True)
+
     if not payload:
         return PrintInterface(retcode=1, data="Nothing to update")
 
diff --git a/fractal/common b/fractal/common
index d9ebfb51d..5459d8135 160000
--- a/fractal/common
+++ b/fractal/common
@@ -1,1 +1,1 @@
-Subproject commit d9ebfb51d99e9bca76b0e162791b7c0e5e2ea286
+Subproject commit 5459d81353ebbd7c8da2b6f35dbef4b130232f1a
diff --git a/fractal/parser.py b/fractal/parser.py
index 28d1183f5..062a7c480 100644
--- a/fractal/parser.py
+++ b/fractal/parser.py
@@ -176,28 +176,33 @@
 )
 dataset_edit_parser.add_argument("project_id", type=int, help="Project ID")
 dataset_edit_parser.add_argument("dataset_id", type=int, help="Dataset ID")
-dataset_edit_parser.add_argument("--name", help="New name of dataset")
-dataset_edit_parser.add_argument("--path", help="New path of dataset")
 dataset_edit_parser.add_argument(
-    "--metadata",
-    help=(
-        "Path to file containing dataset metadata in JSON format. "
-        "(Set to `none` to clear)"
-    ),
+    "--new-name",
+    help="New name of dataset",
+    type=str,
+)
+dataset_edit_parser.add_argument(
+    "--new-type",
+    help="Dataset type",
+    type=str,
 )
 dataset_edit_parser.add_argument(
-    "--read-only",
-    dest="read_only",
+    "--meta-file",
+    help="Path to JSON file with new metadata to replace the current ones",
+)
+dataset_edit_parser_read = dataset_edit_parser.add_mutually_exclusive_group()
+dataset_edit_parser_read.add_argument(
+    "--make-read-only",
     help="Set read-only flag of dataset",
     action="store_true",
+    required=False,
 )
-dataset_edit_parser.add_argument(
-    "--read-write",
-    dest="read_only",
-    help="Set read-only flag of dataset (0 for False, 1 for True)",
-    action="store_false",
+dataset_edit_parser_read.add_argument(
+    "--remove-read-only",
+    help="Remove read-only flag of dataset",
+    action="store_true",
+    required=False,
 )
-dataset_edit_parser.add_argument("-t", "--type", help="Dataset type")
 
 # dataset show
 dataset_show_parser = dataset_subparsers.add_parser(
diff --git a/poetry.lock b/poetry.lock
index 2d2008fcf..8b5dbfdce 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -692,7 +692,7 @@ slurm = ["clusterfutures (>=0.5,<0.6)"]
 type = "git"
 url = "https://github.com/fractal-analytics-platform/fractal-server.git"
 reference = "main"
-resolved_reference = "c3cfede3c570068f38ad637eeaacfa5df97fbd91"
+resolved_reference = "61363175e555262861fe761aadbf994fcd0e1dfa"
 
 [[package]]
 name = "greenlet"


Test patch:
diff --git a/tests/test_dataset.py b/tests/test_dataset.py
index feeecf84f..d53747bcb 100644
--- a/tests/test_dataset.py
+++ b/tests/test_dataset.py
@@ -1,3 +1,5 @@
+import json
+
 import pytest
 
 
@@ -47,15 +49,61 @@ async def test_edit_dataset(register_user, invoke, tmp_path):
     project_id = res.data["id"]
     dataset_id = res.data["dataset_list"][0]["id"]
 
+    TYPE = "this_new_type"
+    NAME = "this_new_name"
+    META = {"something": "else"}
+    META_FILE = str(tmp_path / "meta.json")
+    with open(META_FILE, "w") as f:
+        json.dump(META, f)
+
+    res = await invoke(
+        f"dataset edit {project_id} {dataset_id} --new-name {NAME}"
+    )
+    res.show()
+    assert res.data["name"] == NAME
+    assert res.retcode == 0
+
     res = await invoke(
-        f"dataset edit {project_id} {dataset_id} --type newtype"
+        f"dataset edit {project_id} {dataset_id} --new-type {TYPE}"
     )
     res.show()
-    assert res.data["type"] == "newtype"
+    assert res.data["name"] == NAME
+    assert res.data["type"] == TYPE
     assert res.retcode == 0
 
-    # TODO more extensively test partial updates and test that arguments not
-    # provided are indeed not updated
+    res = await invoke(
+        f"dataset edit {project_id} {dataset_id} --make-read-only"
+    )
+    res.show()
+    assert res.data["name"] == NAME
+    assert res.data["type"] == TYPE
+    assert res.data["read_only"]
+    assert res.retcode == 0
+
+    res = await invoke(
+        f"dataset edit {project_id} {dataset_id} --remove-read-only"
+    )
+    res.show()
+    assert res.data["name"] == NAME
+    assert res.data["type"] == TYPE
+    assert not res.data["read_only"]
+    assert res.retcode == 0
+
+    res = await invoke(
+        f"dataset edit {project_id} {dataset_id} --meta-file {META_FILE}"
+    )
+    res.show()
+    assert res.data["name"] == NAME
+    assert res.data["type"] == TYPE
+    assert res.data["meta"] == META
+    assert not res.data["read_only"]
+    assert res.retcode == 0
+
+    with pytest.raises(SystemExit):
+        res = await invoke(
+            f"dataset edit {project_id} {dataset_id} "
+            "--make-read-only --remove-read-only"
+        )
 
 
 async def test_delete_dataset(register_user, invoke, tmp_path):