Repository: bentoml/BentoML

Issue:
feature(cli): support parsing space for deletion
### Feature request

Right now we don't support parsing space

```python
bentoml models delete model1 model2 ...
```
will fail.

Note that we can already do

```python
bentoml models delete model1,model2
```

### Motivation

_No response_

### Other

_No response_


Discussion:
Could I try this feature?
yes please go ahead. Feel free to ping me if you run into any issues.

Some place to start with:
- https://github.com/bentoml/BentoML/blob/main/src/bentoml_cli/models.py and https://github.com/bentoml/BentoML/blob/main/src/bentoml_cli/bentos.py
I have some questions to clarify this issue.

1. When I read the document, https://docs.bentoml.org/en/latest/reference/cli.html#bentoml-models-delete
there is already multiple model deletion feature.
`e.g.: benotml models delete iris_clf:v1,iris_clf:v2`
What is the goal of this issue?
I guess bentoml wants another way of deletion adding existing one. (seperate mutiple models with ',' or ' ')
If not, let me know and please clarify more about this issue.

2. Also, `b models delete model1 model2 ...` here, b means bentoml? 

3. You wrote two reference files `models.py` and `bentos.py`. Both has a similar feature of deletion. Do you intend to make feature about not only model deletion but also bentos.py?






1. I don't think we parse space correctly
	```bash
	b models delete iris_clf:v1 iris_clf:v2
	```
	So ideally we should be able to do this with different model as well
	```bash
	b models delete model1:asdf model2:v2
	```
2. ah yes force of habit I have `b` as an alias to `bentoml`.
3. Yes. they are similar. You can make two PR, one for parsing multiple models, then the second one is for multiple bentos

ps: I will clarify in the description.
(the above deleted comment was made in error; please disregard)

Resolving patch:
diff --git a/src/bentoml_cli/bentos.py b/src/bentoml_cli/bentos.py
--- a/src/bentoml_cli/bentos.py
+++ b/src/bentoml_cli/bentos.py
@@ -35,7 +35,11 @@ def parse_delete_targets_argument_callback(
 ) -> list[str]:
     if value is None:
         return value
-    delete_targets = value.split(",")
+    value = " ".join(value)
+    if "," in value:
+        delete_targets = value.split(",")
+    else:
+        delete_targets = value.split()
     delete_targets = list(map(str.strip, delete_targets))
     for delete_target in delete_targets:
         if not (
@@ -145,7 +149,7 @@ def list_bentos(bento_name: str, output: str) -> None:  # type: ignore (not acce
     @cli.command()
     @click.argument(
         "delete_targets",
-        type=click.STRING,
+        nargs=-1,
         callback=parse_delete_targets_argument_callback,
         required=True,
     )
@@ -163,7 +167,8 @@ def delete(delete_targets: list[str], yes: bool) -> None:  # type: ignore (not a
         Examples:
             * Delete single bento bundle by "name:version", e.g: `bentoml delete IrisClassifier:v1`
             * Bulk delete all bento bundles with a specific name, e.g.: `bentoml delete IrisClassifier`
-            * Bulk delete multiple bento bundles by name and version, separated by ",", e.g.: `benotml delete Irisclassifier:v1,MyPredictService:v2`
+            * Bulk delete multiple bento bundles by name and version, separated by ",", e.g.: `bentoml delete Irisclassifier:v1,MyPredictService:v2`
+            * Bulk delete multiple bento bundles by name and version, separated by " ", e.g.: `bentoml delete Irisclassifier:v1 MyPredictService:v2`
             * Bulk delete without confirmation, e.g.: `bentoml delete IrisClassifier --yes`
         """
 
diff --git a/src/bentoml_cli/models.py b/src/bentoml_cli/models.py
--- a/src/bentoml_cli/models.py
+++ b/src/bentoml_cli/models.py
@@ -24,7 +24,11 @@ def parse_delete_targets_argument_callback(
 ) -> t.Any:
     if value is None:
         return value
-    delete_targets = value.split(",")
+    value = " ".join(value)
+    if "," in value:
+        delete_targets = value.split(",")
+    else:
+        delete_targets = value.split()
     delete_targets = list(map(str.strip, delete_targets))
     for delete_target in delete_targets:
         if not (
@@ -136,7 +140,7 @@ def list_models(model_name: str, output: str) -> None:  # type: ignore (not acce
     @model_cli.command()
     @click.argument(
         "delete_targets",
-        type=click.STRING,
+        nargs=-1,
         callback=parse_delete_targets_argument_callback,
         required=True,
     )
@@ -154,7 +158,8 @@ def delete(delete_targets: str, yes: bool) -> None:  # type: ignore (not accesse
         Examples:
             * Delete single model by "name:version", e.g: `bentoml models delete iris_clf:v1`
             * Bulk delete all models with a specific name, e.g.: `bentoml models delete iris_clf`
-            * Bulk delete multiple models by name and version, separated by ",", e.g.: `benotml models delete iris_clf:v1,iris_clf:v2`
+            * Bulk delete multiple models by name and version, separated by ",", e.g.: `bentoml models delete iris_clf:v1,iris_clf:v2`
+            * Bulk delete multiple models by name and version, separated by " ", e.g.: `bentoml models delete iris_clf:v1 iris_clf:v2`
             * Bulk delete without confirmation, e.g.: `bentoml models delete IrisClassifier --yes`
         """  # noqa
 


Test patch: