diff --git a/src/kaggle/api/kaggle_api_extended.py b/src/kaggle/api/kaggle_api_extended.py index fbe5dc5d..21fee7c8 100644 --- a/src/kaggle/api/kaggle_api_extended.py +++ b/src/kaggle/api/kaggle_api_extended.py @@ -6096,7 +6096,7 @@ def dataset_create_version_cli( elif result.status.lower() == "ok": print("Dataset version is being created. Please check progress at " + result.url) else: - print("Dataset version creation error: " + result.error) + raise ValueError("Dataset version creation error: " + result.error) def dataset_delete(self, owner_slug: str | None, dataset_slug: str, no_confirm: bool = False) -> bool: """Deletes a dataset. @@ -6374,7 +6374,7 @@ def dataset_create_new_cli( else: print("Your private Dataset is being created. Please check " "progress at " + result.url) else: - print("Dataset creation error: " + result.error) + raise ValueError("Dataset creation error: " + result.error) def _resume_marker_path(self, outfile): """Path of the sidecar file that records the identity of an in-progress download.""" @@ -7481,7 +7481,7 @@ def kernels_push_cli(self, folder, timeout, acc, no_run=False): # Shouldn't happen but didn't test exhaustively print("Kernel version successfully %s. %s %s" % (outcome, where, result.url)) else: - print("Kernel push error: " + result.error) + raise ValueError("Kernel push error: " + result.error) def kernels_pull(self, kernel, path, metadata=False, quiet=True): """Pulls a kernel to a specified path. @@ -8254,7 +8254,7 @@ def model_create_new_cli(self, folder=None): if result.id: print("Your model was created. Id={}. Url={}".format(result.id, result.url)) else: - print("Model creation error: " + result.error) + raise ValueError("Model creation error: " + result.error) def model_delete(self, model: str, no_confirm: bool) -> Optional[ApiDeleteModelResponse]: """Deletes a model. @@ -8292,7 +8292,7 @@ def model_delete_cli(self, model, no_confirm): return if result.error: - print("Model deletion error: " + result.error) + raise ValueError("Model deletion error: " + result.error) else: print("The model was deleted.") @@ -8382,7 +8382,7 @@ def model_update_cli(self, folder=None): if result.id: print("Your model was updated. Id={}. Url={}".format(result.id, result.url)) else: - print("Model update error: " + result.error) + raise ValueError("Model update error: " + result.error) def model_instance_get(self, model_instance: str) -> ApiModelInstance: """Gets a model instance. @@ -8611,7 +8611,7 @@ def model_instance_create_cli(self, folder, quiet=False, dir_mode="skip", ignore if result.id: print("Your model instance was created. Id={}. Url={}".format(result.id, result.url)) else: - print("Model instance creation error: " + result.error) + raise ValueError("Model instance creation error: " + result.error) def model_instance_delete(self, model_instance: str, no_confirm: bool = False) -> Optional[ApiDeleteModelResponse]: """Deletes a model instance. @@ -8654,7 +8654,7 @@ def model_instance_delete_cli(self, model_instance, no_confirm): return if len(result.error) > 0: - print("Model instance deletion error: " + result.error) + raise ValueError("Model instance deletion error: " + result.error) else: print("The model instance was deleted.") @@ -8860,7 +8860,7 @@ def model_instance_update_cli(self, folder=None): if len(result.error) == 0: print("Your model instance was updated. Id={}. Url={}".format(result.id, result.url)) else: - print("Model update error: " + result.error) + raise ValueError("Model update error: " + result.error) def model_instance_version_create( self, @@ -8936,7 +8936,7 @@ def model_instance_version_create_cli( if result.id != 0: print("Your model instance version was created. Url={}".format(result.url)) else: - print("Model instance version creation error: " + result.error) + raise ValueError("Model instance version creation error: " + result.error) def model_instance_version_download( self, @@ -9188,7 +9188,7 @@ def model_instance_version_delete_cli(self, model_instance_version, no_confirm): return if len(result.error) > 0: - print("Model instance version deletion error: " + result.error) + raise ValueError("Model instance version deletion error: " + result.error) else: print("The model instance version was deleted.") diff --git a/tests/unit/test_cli_write_errors.py b/tests/unit/test_cli_write_errors.py new file mode 100644 index 00000000..ecf76642 --- /dev/null +++ b/tests/unit/test_cli_write_errors.py @@ -0,0 +1,36 @@ +import unittest +from types import SimpleNamespace +from unittest.mock import patch + +from kaggle.api.kaggle_api_extended import KaggleApi + +# (cli wrapper, library method it calls, positional args for the wrapper) +WRAPPERS = [ + ("dataset_create_version_cli", "dataset_create_version", ("folder", "notes")), + ("dataset_create_new_cli", "dataset_create_new", ("folder",)), + ("kernels_push_cli", "kernels_push", ("folder", None, None)), + ("model_create_new_cli", "model_create_new", ("folder",)), + ("model_delete_cli", "model_delete", ("owner/model", True)), + ("model_update_cli", "model_update", ("folder",)), + ("model_instance_create_cli", "model_instance_create", ("folder",)), + ("model_instance_delete_cli", "model_instance_delete", ("o/m/f/i", True)), + ("model_instance_update_cli", "model_instance_update", ("folder",)), + ("model_instance_version_create_cli", "model_instance_version_create", ("o/m/f/i", "folder")), + ("model_instance_version_delete_cli", "model_instance_version_delete", ("o/m/f/i/1", True)), +] + + +class TestCliWriteErrors(unittest.TestCase): + """A server-side error must reach cli.main() as ValueError so the command exits 1, not 0.""" + + def test_server_error_raises(self): + api = KaggleApi.__new__(KaggleApi) + result = SimpleNamespace(error="boom", id=0, status="error", invalidTags=None, ref="", url="") + for wrapper, method, args in WRAPPERS: + with self.subTest(wrapper=wrapper), patch.object(KaggleApi, method, return_value=result): + with self.assertRaisesRegex(ValueError, "error: boom"): + getattr(api, wrapper)(*args) + + +if __name__ == "__main__": + unittest.main()