| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| """CLI error handling utilities.""" |
|
|
| import traceback |
| from typing import Callable, Optional |
|
|
| from huggingface_hub.errors import ( |
| BucketNotFoundError, |
| CLIError, |
| CLIExtensionInstallError, |
| GatedRepoError, |
| HfHubHTTPError, |
| LocalTokenNotFoundError, |
| RemoteEntryNotFoundError, |
| RepositoryNotFoundError, |
| RevisionNotFoundError, |
| ) |
|
|
|
|
| def _format_repo_not_found(error: RepositoryNotFoundError) -> str: |
| label = error.repo_type.capitalize() if error.repo_type else "Repository" |
| if error.repo_id: |
| msg = f"{label} '{error.repo_id}' not found." |
| else: |
| msg = f"{label} not found." |
| msg += " If the repo is private, make sure you are authenticated." |
| return msg |
|
|
|
|
| def _format_gated_repo(error: GatedRepoError) -> str: |
| label = error.repo_type if error.repo_type else "repository" |
| if error.repo_id: |
| return f"Access denied. {label.capitalize()} '{error.repo_id}' requires approval." |
| return f"Access denied. This {label} requires approval." |
|
|
|
|
| def _format_bucket_not_found(error: BucketNotFoundError) -> str: |
| if error.bucket_id: |
| return f"Bucket '{error.bucket_id}' not found. If the bucket is private, make sure you are authenticated." |
| return "Bucket not found. Check the bucket id (namespace/name). If the bucket is private, make sure you are authenticated." |
|
|
|
|
| def _format_entry_not_found(error: RemoteEntryNotFoundError) -> str: |
| label = error.repo_type if error.repo_type else "repository" |
| url = str(error.response.url) if error.response else None |
| if error.repo_id: |
| msg = f"File not found in {label} '{error.repo_id}'." |
| else: |
| msg = f"File not found in {label}." |
| if url: |
| msg += f"\nURL: {url}" |
| return msg |
|
|
|
|
| def _format_revision_not_found(error: RevisionNotFoundError) -> str: |
| label = error.repo_type if error.repo_type else "repository" |
| if error.repo_id: |
| return f"Revision not found in {label} '{error.repo_id}'." |
| return f"Revision not found in {label}. Check the revision parameter." |
|
|
|
|
| def _format_cli_error(error: CLIError) -> str: |
| """No traceback, just the error message.""" |
| return str(error) |
|
|
|
|
| def _format_cli_extension_install_error(error: CLIExtensionInstallError) -> str: |
| """Format a CLI extension installation error. |
| |
| The error is likely to be a tricky subprocess error to investigate. In this specific case we want to format the |
| traceback of the root cause while keeping the "nicely formatted" error message of the CLIExtensionInstallError |
| as a 1-line message. |
| """ |
| cause_tb = ( |
| "".join(traceback.format_exception(type(error.__cause__), error.__cause__, error.__cause__.__traceback__)) |
| if error.__cause__ is not None |
| else "" |
| ) |
| return f"{cause_tb}\n{error}" |
|
|
|
|
| CLI_ERROR_MAPPINGS: dict[type[Exception], Callable[..., str]] = { |
| |
| GatedRepoError: _format_gated_repo, |
| BucketNotFoundError: _format_bucket_not_found, |
| RepositoryNotFoundError: _format_repo_not_found, |
| RevisionNotFoundError: _format_revision_not_found, |
| LocalTokenNotFoundError: lambda _: "Not logged in. Run 'hf auth login' first.", |
| RemoteEntryNotFoundError: _format_entry_not_found, |
| HfHubHTTPError: lambda error: str(error), |
| ValueError: lambda error: f"Invalid value. {error}", |
| CLIExtensionInstallError: _format_cli_extension_install_error, |
| CLIError: _format_cli_error, |
| } |
|
|
|
|
| def format_known_exception(error: Exception) -> Optional[str]: |
| for exc_type, formatter in CLI_ERROR_MAPPINGS.items(): |
| if isinstance(error, exc_type): |
| return formatter(error) |
| return None |
|
|