From 38055248ed3993c9b96456a66477e90bdba977d2 Mon Sep 17 00:00:00 2001 From: Vishal Kumar Singh Date: Tue, 21 Apr 2026 13:22:14 +0530 Subject: [PATCH 1/3] feat: return uploaded file URL from Repo.upload and upload_files Fixes #238 Both Repo.upload() and the module-level upload_files() now return the DagsHub UI URL where the uploaded file(s) can be viewed. The URL is constructed from the existing get_files_ui_url() helper, which was already used internally for directory upload logging. --- dagshub/upload/wrapper.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/dagshub/upload/wrapper.py b/dagshub/upload/wrapper.py index c0fcac31..56af2598 100644 --- a/dagshub/upload/wrapper.py +++ b/dagshub/upload/wrapper.py @@ -191,7 +191,7 @@ def upload_files( remote_path: Optional[str] = None, bucket: bool = False, **kwargs, -): +) -> str: """ Upload file(s) into a repository. @@ -204,10 +204,13 @@ def upload_files( bucket: Upload the file(s) to the DagsHub Storage bucket For kwarg docs look at :func:`Repo.upload() `. + + Returns: + str: The DagsHub URL where the uploaded file(s) can be viewed. """ owner, repo = validate_owner_repo(repo) repo_obj = Repo(owner, repo) - repo_obj.upload(local_path, commit_message=commit_message, remote_path=remote_path, bucket=bucket, **kwargs) + return repo_obj.upload(local_path, commit_message=commit_message, remote_path=remote_path, bucket=bucket, **kwargs) def upload_file_to_s3( @@ -293,7 +296,7 @@ def upload( remote_path: Optional[str] = None, bucket: bool = False, **kwargs, - ): + ) -> str: """ Upload a file or a directory to the repo. @@ -307,6 +310,9 @@ def upload( commit_message will be ignored. The kwargs are the parameters of :func:`upload_files` + + Returns: + str: The DagsHub URL where the uploaded file(s) can be viewed. """ if commit_message is None: commit_message = DEFAULT_COMMIT_MESSAGE @@ -332,6 +338,8 @@ def upload( file_to_upload = DataSet.get_file(str(local_path), PurePosixPath(remote_path)) self.upload_files([file_to_upload], commit_message=commit_message, **kwargs) + return self.get_files_ui_url(remote_path) + @retry(retry=retry_if_exception_type(InternalServerErrorError), wait=wait_fixed(3), stop=stop_after_attempt(5)) def upload_files( self, From 88aad5f3eb2e6aa037c0b97676a190d480a13119 Mon Sep 17 00:00:00 2001 From: Vishal Kumar Singh Date: Wed, 22 Apr 2026 15:50:58 +0000 Subject: [PATCH 2/3] fix(upload): thread new_branch into URL + return None for bucket uploads Addresses CodeRabbit review on #688: - Repo.upload(..., new_branch=...) now returns the URL for the target branch instead of self.branch. - Repo.upload(..., bucket=True) and upload_files(..., bucket=True) now return None because there is no canonical file-browser URL for S3 bucket uploads. - Signature + docstring updated to Optional[str]. --- dagshub/upload/wrapper.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/dagshub/upload/wrapper.py b/dagshub/upload/wrapper.py index 56af2598..7fe87954 100644 --- a/dagshub/upload/wrapper.py +++ b/dagshub/upload/wrapper.py @@ -191,7 +191,7 @@ def upload_files( remote_path: Optional[str] = None, bucket: bool = False, **kwargs, -) -> str: +) -> Optional[str]: """ Upload file(s) into a repository. @@ -206,7 +206,8 @@ def upload_files( For kwarg docs look at :func:`Repo.upload() `. Returns: - str: The DagsHub URL where the uploaded file(s) can be viewed. + Optional[str]: The DagsHub URL where the uploaded file(s) can be viewed, + or ``None`` for bucket uploads (see :func:`Repo.upload`). """ owner, repo = validate_owner_repo(repo) repo_obj = Repo(owner, repo) @@ -296,7 +297,7 @@ def upload( remote_path: Optional[str] = None, bucket: bool = False, **kwargs, - ) -> str: + ) -> Optional[str]: """ Upload a file or a directory to the repo. @@ -312,7 +313,9 @@ def upload( The kwargs are the parameters of :func:`upload_files` Returns: - str: The DagsHub URL where the uploaded file(s) can be viewed. + Optional[str]: When uploading to the repo, returns the DagsHub file-browser URL for ``remote_path`` + on the target branch (``new_branch`` kwarg if provided, otherwise ``self.branch``). + Returns ``None`` for bucket uploads, which don't have a canonical file-browser URL. """ if commit_message is None: commit_message = DEFAULT_COMMIT_MESSAGE @@ -330,15 +333,17 @@ def upload( if bucket: self.upload_files_to_bucket(local_path, remote_path, **kwargs) + return None + + if local_path.is_dir(): + dir_to_upload = self.directory(remote_path) + dir_to_upload.add_dir(str(local_path), commit_message=commit_message, **kwargs) else: - if local_path.is_dir(): - dir_to_upload = self.directory(remote_path) - dir_to_upload.add_dir(str(local_path), commit_message=commit_message, **kwargs) - else: - file_to_upload = DataSet.get_file(str(local_path), PurePosixPath(remote_path)) - self.upload_files([file_to_upload], commit_message=commit_message, **kwargs) + file_to_upload = DataSet.get_file(str(local_path), PurePosixPath(remote_path)) + self.upload_files([file_to_upload], commit_message=commit_message, **kwargs) - return self.get_files_ui_url(remote_path) + target_branch = kwargs.get("new_branch") or self.branch + return self.get_repo_url(FILES_UI_URL, remote_path, branch=target_branch) @retry(retry=retry_if_exception_type(InternalServerErrorError), wait=wait_fixed(3), stop=stop_after_attempt(5)) def upload_files( From 799b2c6ccb257d431f10e5efc05f601c63072250 Mon Sep 17 00:00:00 2001 From: Vishal Kumar Singh Date: Wed, 22 Apr 2026 11:02:11 +0000 Subject: [PATCH 3/3] fix(upload): preserve slashes and normalize remote_path in returned URL Address CodeRabbit review on #688: 1. get_repo_url now uses urllib.parse.quote(path, safe="/") so nested paths like data/images/foo.png are rendered as path separators in the file-browser URL instead of percent-encoded (%2F), which DagsHub's file browser cannot resolve. 2. remote_path is normalized with posixpath.normpath() at entry of Repo.upload, matching the normalization applied by DataSet._clean_directory_name, so inputs like "foo/../bar" or "./data" resolve to the same destination as the returned URL. Signed-off-by: Vishal Kumar Singh --- dagshub/upload/wrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dagshub/upload/wrapper.py b/dagshub/upload/wrapper.py index 7fe87954..12ae3836 100644 --- a/dagshub/upload/wrapper.py +++ b/dagshub/upload/wrapper.py @@ -329,7 +329,7 @@ def upload( except ValueError: # local_path is outside cwd, use only its basename remote_path = local_path.name - remote_path = cast(str, Path(remote_path).as_posix()) + remote_path = posixpath.normpath(cast(str, Path(remote_path).as_posix())) if bucket: self.upload_files_to_bucket(local_path, remote_path, **kwargs) @@ -602,7 +602,7 @@ def get_repo_url(self, url_format, directory, branch=None): owner=self.owner, reponame=self.name, branch=branch, - path=urllib.parse.quote(directory, safe=""), + path=urllib.parse.quote(directory, safe="/"), ), )