From 77f87b4b42a27aed297131fb53affb11c04ba51a Mon Sep 17 00:00:00 2001 From: maddogghoek Date: Wed, 24 Dec 2025 11:45:22 -0600 Subject: [PATCH 1/2] - Improve error handling and reporting around project name - Allow mulitple images to be uploaded in a single upload command - Improve upload command documentation --- roboflow/core/workspace.py | 5 +++-- roboflow/roboflowpy.py | 30 +++++++++++++++++------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/roboflow/core/workspace.py b/roboflow/core/workspace.py index de5fcca4..f29752b9 100644 --- a/roboflow/core/workspace.py +++ b/roboflow/core/workspace.py @@ -86,10 +86,11 @@ def project(self, project_id): if self.__api_key in DEMO_KEYS: return Project(self.__api_key, {}, self.model_format) - # project_id = project_id.replace(self.url + "/", "") + if not project_id: + raise RuntimeError(f"Project id is required but none was specified.") if "/" in project_id: - raise RuntimeError(f"The {project_id} project is not available in this ({self.url}) workspace") + raise RuntimeError(f"{project_id=} cannot contain a '/', use workspace argument to change the URL.") dataset_info = rfapi.get_project(self.__api_key, self.url, project_id) dataset_info = dataset_info["project"] diff --git a/roboflow/roboflowpy.py b/roboflow/roboflowpy.py index 70cf6db9..9922753c 100755 --- a/roboflow/roboflowpy.py +++ b/roboflow/roboflowpy.py @@ -72,16 +72,18 @@ def upload_image(args): rf = roboflow.Roboflow() workspace = rf.workspace(args.workspace) project = workspace.project(args.project) - project.single_upload( - image_path=args.imagefile, - annotation_path=args.annotation, - annotation_labelmap=args.labelmap, - split=args.split, - num_retry_uploads=args.num_retries, - batch_name=args.batch, - tag_names=args.tag_names.split(",") if args.tag_names else [], - is_prediction=args.is_prediction, - ) + tag_names = args.tag_names.split(",") if args.tag_names else [] + for image_path in args.imagefile: + project.single_upload( + image_path=image_path, + annotation_path=args.annotation, + annotation_labelmap=args.labelmap, + split=args.split, + num_retry_uploads=args.num_retries, + batch_name=args.batch, + tag_names=tag_names, + is_prediction=args.is_prediction, + ) def upload_model(args): @@ -263,10 +265,11 @@ def _add_download_parser(subparsers): def _add_upload_parser(subparsers): - upload_parser = subparsers.add_parser("upload", help="Upload a single image to a dataset") + upload_parser = subparsers.add_parser("upload", help="Upload one or more images to a dataset") upload_parser.add_argument( "imagefile", - help="path to image file", + nargs="+", + help="path to one or more image files to upload", ) upload_parser.add_argument( "-w", @@ -276,7 +279,8 @@ def _add_upload_parser(subparsers): upload_parser.add_argument( "-p", dest="project", - help="project_id to upload the image into", + required=True, + help="project_id to upload the image into (required)", ) upload_parser.add_argument( "-a", From 77e9f8070c7acf36233be557c5ae5ebbcc7675a8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 24 Dec 2025 18:05:24 +0000 Subject: [PATCH 2/2] =?UTF-8?q?fix(pre=5Fcommit):=20=F0=9F=8E=A8=20auto=20?= =?UTF-8?q?format=20pre-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roboflow/core/workspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roboflow/core/workspace.py b/roboflow/core/workspace.py index f29752b9..73ed1244 100644 --- a/roboflow/core/workspace.py +++ b/roboflow/core/workspace.py @@ -87,7 +87,7 @@ def project(self, project_id): return Project(self.__api_key, {}, self.model_format) if not project_id: - raise RuntimeError(f"Project id is required but none was specified.") + raise RuntimeError("Project id is required but none was specified.") if "/" in project_id: raise RuntimeError(f"{project_id=} cannot contain a '/', use workspace argument to change the URL.")