diff --git a/Makefile b/Makefile index 32e32a240a..341f8f9e12 100644 --- a/Makefile +++ b/Makefile @@ -7,19 +7,18 @@ check_dirs := contrib src tests utils setup.py quality: ruff check $(check_dirs) # linter ruff format --check $(check_dirs) # formatter - python3 utils/check_inference_input_params.py - python3 utils/check_contrib_list.py - python3 utils/check_static_imports.py - python3 utils/generate_async_inference_client.py + python utils/check_inference_input_params.py + python utils/check_contrib_list.py + python utils/check_static_imports.py + python utils/generate_async_inference_client.py mypy src style: ruff format $(check_dirs) # formatter ruff check --fix $(check_dirs) # linter - python3 utils/check_contrib_list.py --update - python3 utils/check_static_imports.py --update - python3 utils/generate_async_inference_client.py --update - ruff format src/huggingface_hub/hf_api.py + python utils/check_contrib_list.py --update + python utils/check_static_imports.py --update + python utils/generate_async_inference_client.py --update inference_types_check: python utils/generate_inference_types.py diff --git a/src/huggingface_hub/__init__.py b/src/huggingface_hub/__init__.py index 38e1a65c00..47129d1ec9 100644 --- a/src/huggingface_hub/__init__.py +++ b/src/huggingface_hub/__init__.py @@ -143,11 +143,14 @@ "CommitOperationAdd", "CommitOperationCopy", "CommitOperationDelete", + "DatasetInfo", "GitCommitInfo", "GitRefInfo", "GitRefs", "HfApi", + "ModelInfo", "RepoUrl", + "SpaceInfo", "User", "UserLikes", "WebhookInfo", @@ -199,6 +202,7 @@ "get_space_runtime", "get_space_variables", "get_token_permission", + "get_user_overview", "get_webhook", "grant_access", "like", @@ -643,11 +647,14 @@ def __dir__(): CommitOperationAdd, # noqa: F401 CommitOperationCopy, # noqa: F401 CommitOperationDelete, # noqa: F401 + DatasetInfo, # noqa: F401 GitCommitInfo, # noqa: F401 GitRefInfo, # noqa: F401 GitRefs, # noqa: F401 HfApi, # noqa: F401 + ModelInfo, # noqa: F401 RepoUrl, # noqa: F401 + SpaceInfo, # noqa: F401 User, # noqa: F401 UserLikes, # noqa: F401 WebhookInfo, # noqa: F401 @@ -699,6 +706,7 @@ def __dir__(): get_space_runtime, # noqa: F401 get_space_variables, # noqa: F401 get_token_permission, # noqa: F401 + get_user_overview, # noqa: F401 get_webhook, # noqa: F401 grant_access, # noqa: F401 like, # noqa: F401 diff --git a/src/huggingface_hub/fastai_utils.py b/src/huggingface_hub/fastai_utils.py index e586e8663c..640ac0b6cd 100644 --- a/src/huggingface_hub/fastai_utils.py +++ b/src/huggingface_hub/fastai_utils.py @@ -7,7 +7,7 @@ from packaging import version from huggingface_hub import snapshot_download -from huggingface_hub.constants import CONFIG_NAME +from huggingface_hub import constants from huggingface_hub.hf_api import HfApi from huggingface_hub.utils import ( SoftTemporaryDirectory, @@ -272,7 +272,7 @@ def _save_pretrained_fastai( if config is not None: if not isinstance(config, dict): raise RuntimeError(f"Provided config should be a dict. Got: '{type(config)}'") - path = os.path.join(save_directory, CONFIG_NAME) + path = os.path.join(save_directory, constants.CONFIG_NAME) with open(path, "w") as f: json.dump(config, f) diff --git a/src/huggingface_hub/hf_api.py b/src/huggingface_hub/hf_api.py index e17c0fd56f..b696165acb 100644 --- a/src/huggingface_hub/hf_api.py +++ b/src/huggingface_hub/hf_api.py @@ -48,9 +48,6 @@ from tqdm.auto import tqdm as base_tqdm from tqdm.contrib.concurrent import thread_map -from huggingface_hub import constants -from huggingface_hub.constants import ENDPOINT - from ._commit_api import ( CommitOperation, CommitOperationAdd, @@ -85,6 +82,27 @@ DiscussionWithDetails, deserialize_event, ) +from .constants import ( + DEFAULT_ETAG_TIMEOUT, # noqa: F401 # kept for backward compatibility + DEFAULT_REQUEST_TIMEOUT, # noqa: F401 # kept for backward compatibility + DEFAULT_REVISION, # noqa: F401 # kept for backward compatibility + DISCUSSION_STATUS, # noqa: F401 # kept for backward compatibility + DISCUSSION_TYPES, # noqa: F401 # kept for backward compatibility + ENDPOINT, # noqa: F401 # kept for backward compatibility + INFERENCE_ENDPOINTS_ENDPOINT, # noqa: F401 # kept for backward compatibility + REGEX_COMMIT_OID, # noqa: F401 # kept for backward compatibility + REPO_TYPE_MODEL, # noqa: F401 # kept for backward compatibility + REPO_TYPES, # noqa: F401 # kept for backward compatibility + REPO_TYPES_MAPPING, # noqa: F401 # kept for backward compatibility + REPO_TYPES_URL_PREFIXES, # noqa: F401 # kept for backward compatibility + SAFETENSORS_INDEX_FILE, # noqa: F401 # kept for backward compatibility + SAFETENSORS_MAX_HEADER_LENGTH, # noqa: F401 # kept for backward compatibility + SAFETENSORS_SINGLE_FILE, # noqa: F401 # kept for backward compatibility + SPACES_SDK_TYPES, # noqa: F401 # kept for backward compatibility + WEBHOOK_DOMAIN_T, # noqa: F401 # kept for backward compatibility + DiscussionStatusFilter, # noqa: F401 # kept for backward compatibility + DiscussionTypeFilter, # noqa: F401 # kept for backward compatibility +) from .file_download import HfFileMetadata, get_hf_file_metadata, hf_hub_url from .repocard_data import DatasetCardData, ModelCardData, SpaceCardData from .utils import ( @@ -245,9 +263,9 @@ def repo_type_and_id_from_hf_id(hf_id: str, hub_url: Optional[str] = None) -> Tu namespace = None if len(url_segments) > 2 and hub_url not in url_segments[-3]: repo_type = url_segments[-3] - elif namespace in constants.REPO_TYPES_MAPPING: + elif namespace in REPO_TYPES_MAPPING: # Mean canonical dataset or model - repo_type = constants.REPO_TYPES_MAPPING[namespace] + repo_type = REPO_TYPES_MAPPING[namespace] namespace = None else: repo_type = None @@ -256,9 +274,9 @@ def repo_type_and_id_from_hf_id(hf_id: str, hub_url: Optional[str] = None) -> Tu # Passed // or // repo_type, namespace, repo_id = url_segments[-3:] elif len(url_segments) == 2: - if url_segments[0] in constants.REPO_TYPES_MAPPING: + if url_segments[0] in REPO_TYPES_MAPPING: # Passed '' or 'datasets/' for a canonical model or dataset - repo_type = constants.REPO_TYPES_MAPPING[url_segments[0]] + repo_type = REPO_TYPES_MAPPING[url_segments[0]] namespace = None repo_id = hf_id.split("/")[-1] else: @@ -273,11 +291,11 @@ def repo_type_and_id_from_hf_id(hf_id: str, hub_url: Optional[str] = None) -> Tu raise ValueError(f"Unable to retrieve user and repo ID from the passed HF ID: {hf_id}") # Check if repo type is known (mapping "spaces" => "space" + empty value => `None`) - if repo_type in constants.REPO_TYPES_MAPPING: - repo_type = constants.REPO_TYPES_MAPPING[repo_type] + if repo_type in REPO_TYPES_MAPPING: + repo_type = REPO_TYPES_MAPPING[repo_type] if repo_type == "": repo_type = None - if repo_type not in constants.REPO_TYPES: + if repo_type not in REPO_TYPES: raise ValueError(f"Unknown `repo_type`: '{repo_type}' ('{input_hf_id}')") return repo_type, namespace, repo_id @@ -471,7 +489,7 @@ class WebhookInfo: id: str url: str watched: List[WebhookWatchedItem] - domains: List[constants.WEBHOOK_DOMAIN_T] + domains: List[WEBHOOK_DOMAIN_T] secret: Optional[str] disabled: bool @@ -530,7 +548,7 @@ def __init__(self, url: Any, endpoint: Optional[str] = None) -> None: self.namespace = namespace self.repo_name = repo_name self.repo_id = repo_name if namespace is None else f"{namespace}/{repo_name}" - self.repo_type = repo_type or constants.REPO_TYPE_MODEL + self.repo_type = repo_type or REPO_TYPE_MODEL self.url = str(self) # just in case it's needed def __repr__(self) -> str: @@ -2138,7 +2156,7 @@ def like( ``` """ if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL response = get_session().post( url=f"{self.endpoint}/api/{repo_type}s/{repo_id}/like", headers=self._build_hf_headers(token=token), @@ -2189,7 +2207,7 @@ def unlike( ``` """ if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL response = get_session().delete( url=f"{self.endpoint}/api/{repo_type}s/{repo_id}/like", headers=self._build_hf_headers(token=token) ) @@ -2305,7 +2323,7 @@ def list_repo_likers( # Construct the API endpoint if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL path = f"{self.endpoint}/api/{repo_type}s/{repo_id}/likers" headers = self._build_hf_headers(token=token) @@ -2931,8 +2949,8 @@ def list_repo_tree( ] ``` """ - repo_type = repo_type or constants.REPO_TYPE_MODEL - revision = quote(revision, safe="") if revision is not None else constants.DEFAULT_REVISION + repo_type = repo_type or REPO_TYPE_MODEL + revision = quote(revision, safe="") if revision is not None else DEFAULT_REVISION headers = self._build_hf_headers(token=token) encoded_path_in_repo = "/" + quote(path_in_repo, safe="") if path_in_repo else "" @@ -2991,7 +3009,7 @@ def list_repo_refs( [`GitRefs`]: object containing all information about branches and tags for a repo on the Hub. """ - repo_type = repo_type or constants.REPO_TYPE_MODEL + repo_type = repo_type or REPO_TYPE_MODEL response = get_session().get( f"{self.endpoint}/api/{repo_type}s/{repo_id}/refs", headers=self._build_hf_headers(token=token), @@ -3077,8 +3095,8 @@ def list_repo_commits( [`~utils.RevisionNotFoundError`]: If revision is not found (error 404) on the repo. """ - repo_type = repo_type or constants.REPO_TYPE_MODEL - revision = quote(revision, safe="") if revision is not None else constants.DEFAULT_REVISION + repo_type = repo_type or REPO_TYPE_MODEL + revision = quote(revision, safe="") if revision is not None else DEFAULT_REVISION # Paginate over results and return the list of commits. return [ @@ -3156,8 +3174,8 @@ def get_paths_info( ] ``` """ - repo_type = repo_type or constants.REPO_TYPE_MODEL - revision = quote(revision, safe="") if revision is not None else constants.DEFAULT_REVISION + repo_type = repo_type or REPO_TYPE_MODEL + revision = quote(revision, safe="") if revision is not None else DEFAULT_REVISION headers = self._build_hf_headers(token=token) response = get_session().post( @@ -3246,11 +3264,11 @@ def super_squash_history( ``` """ if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL - if repo_type not in constants.REPO_TYPES: + repo_type = REPO_TYPE_MODEL + if repo_type not in REPO_TYPES: raise ValueError("Invalid repo type") if branch is None: - branch = constants.DEFAULT_REVISION + branch = DEFAULT_REVISION # Prepare request url = f"{self.endpoint}/api/{repo_type}s/{repo_id}/super-squash/{branch}" @@ -3328,7 +3346,7 @@ def create_repo( path = f"{self.endpoint}/api/repos/create" - if repo_type not in constants.REPO_TYPES: + if repo_type not in REPO_TYPES: raise ValueError("Invalid repo type") json: Dict[str, Any] = {"name": name, "organization": organization, "private": private} @@ -3338,10 +3356,10 @@ def create_repo( if space_sdk is None: raise ValueError( "No space_sdk provided. `create_repo` expects space_sdk to be one" - f" of {constants.SPACES_SDK_TYPES} when repo_type is 'space'`" + f" of {SPACES_SDK_TYPES} when repo_type is 'space'`" ) - if space_sdk not in constants.SPACES_SDK_TYPES: - raise ValueError(f"Invalid space_sdk. Please choose one of {constants.SPACES_SDK_TYPES}.") + if space_sdk not in SPACES_SDK_TYPES: + raise ValueError(f"Invalid space_sdk. Please choose one of {SPACES_SDK_TYPES}.") json["sdk"] = space_sdk if space_sdk is not None and repo_type != "space": @@ -3397,7 +3415,7 @@ def create_repo( # No write permission on the namespace but repo might already exist try: self.repo_info(repo_id=repo_id, repo_type=repo_type, token=token) - if repo_type is None or repo_type == constants.REPO_TYPE_MODEL: + if repo_type is None or repo_type == REPO_TYPE_MODEL: return RepoUrl(f"{self.endpoint}/{repo_id}") return RepoUrl(f"{self.endpoint}/{repo_type}/{repo_id}") except HfHubHTTPError: @@ -3443,7 +3461,7 @@ def delete_repo( path = f"{self.endpoint}/api/repos/delete" - if repo_type not in constants.REPO_TYPES: + if repo_type not in REPO_TYPES: raise ValueError("Invalid repo type") json = {"name": name, "organization": organization} @@ -3497,10 +3515,10 @@ def update_repo_visibility( """ - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL # default repo type + repo_type = REPO_TYPE_MODEL # default repo type r = get_session().put( url=f"{self.endpoint}/api/{repo_type}s/{repo_id}/settings", @@ -3559,7 +3577,7 @@ def move_repo( raise ValueError(f"Invalid repo_id: {to_id}. It should have a namespace (:namespace:/:repo_name:)") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL # Hub won't accept `None`. + repo_type = REPO_TYPE_MODEL # Hub won't accept `None`. json = {"fromRepo": from_id, "toRepo": to_id, "type": repo_type} @@ -3729,19 +3747,19 @@ def create_commit( If repository is not found (error 404): wrong repo_id/repo_type, private but not authenticated or repo does not exist. """ - if parent_commit is not None and not constants.REGEX_COMMIT_OID.fullmatch(parent_commit): + if parent_commit is not None and not REGEX_COMMIT_OID.fullmatch(parent_commit): raise ValueError( - f"`parent_commit` is not a valid commit OID. It must match the following regex: {constants.REGEX_COMMIT_OID}" + f"`parent_commit` is not a valid commit OID. It must match the following regex: {REGEX_COMMIT_OID}" ) if commit_message is None or len(commit_message) == 0: raise ValueError("`commit_message` can't be empty, please pass a value.") commit_description = commit_description if commit_description is not None else "" - repo_type = repo_type if repo_type is not None else constants.REPO_TYPE_MODEL - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") - unquoted_revision = revision or constants.DEFAULT_REVISION + repo_type = repo_type if repo_type is not None else REPO_TYPE_MODEL + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") + unquoted_revision = revision or DEFAULT_REVISION revision = quote(unquoted_revision, safe="") create_pr = create_pr if create_pr is not None else False @@ -3845,7 +3863,7 @@ def create_commit( # Return commit info based on latest commit url_prefix = self.endpoint - if repo_type is not None and repo_type != constants.REPO_TYPE_MODEL: + if repo_type is not None and repo_type != REPO_TYPE_MODEL: url_prefix = f"{url_prefix}/{repo_type}s" return CommitInfo( commit_url=f"{url_prefix}/{repo_id}/commit/{info.sha}", @@ -4086,7 +4104,7 @@ def create_commits_on_pr( commits_on_main_branch = { commit.commit_id for commit in self.list_repo_commits( - repo_id=repo_id, repo_type=repo_type, token=token, revision=constants.DEFAULT_REVISION + repo_id=repo_id, repo_type=repo_type, token=token, revision=DEFAULT_REVISION ) } pr_commits = [ @@ -4305,10 +4323,10 @@ def preupload_lfs_files( >>> create_commit(repo_id, operations=operations, commit_message="Commit all shards") ``` """ - repo_type = repo_type if repo_type is not None else constants.REPO_TYPE_MODEL - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") - revision = quote(revision, safe="") if revision is not None else constants.DEFAULT_REVISION + repo_type = repo_type if repo_type is not None else REPO_TYPE_MODEL + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") + revision = quote(revision, safe="") if revision is not None else DEFAULT_REVISION create_pr = create_pr if create_pr is not None else False headers = self._build_hf_headers(token=token) @@ -4536,8 +4554,8 @@ def upload_file( "https://huggingface.co/username/my-model/blob/refs%2Fpr%2F1/remote/file/path.h5" ``` """ - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") commit_message = ( commit_message if commit_message is not None else f"Upload {path_in_repo} with huggingface_hub" @@ -4561,9 +4579,9 @@ def upload_file( if commit_info.pr_url is not None: revision = quote(_parse_revision_from_pr_url(commit_info.pr_url), safe="") - if repo_type in constants.REPO_TYPES_URL_PREFIXES: - repo_id = constants.REPO_TYPES_URL_PREFIXES[repo_type] + repo_id - revision = revision if revision is not None else constants.DEFAULT_REVISION + if repo_type in REPO_TYPES_URL_PREFIXES: + repo_id = REPO_TYPES_URL_PREFIXES[repo_type] + repo_id + revision = revision if revision is not None else DEFAULT_REVISION return CommitInfo( commit_url=commit_info.commit_url, @@ -4838,11 +4856,11 @@ def upload_folder( ``` """ - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if multi_commits: - if revision is not None and revision != constants.DEFAULT_REVISION: + if revision is not None and revision != DEFAULT_REVISION: raise ValueError("Cannot use `multi_commit` to commit changes other than the main branch.") # By default, upload folder to the root directory in repo. @@ -4859,7 +4877,7 @@ def upload_folder( delete_operations = self._prepare_folder_deletions( repo_id=repo_id, repo_type=repo_type, - revision=constants.DEFAULT_REVISION if create_pr else revision, + revision=DEFAULT_REVISION if create_pr else revision, token=token, path_in_repo=path_in_repo, delete_patterns=delete_patterns, @@ -4916,9 +4934,9 @@ def upload_folder( # Create url to uploaded folder (for legacy return value) if create_pr and commit_info.pr_url is not None: revision = quote(_parse_revision_from_pr_url(commit_info.pr_url), safe="") - if repo_type in constants.REPO_TYPES_URL_PREFIXES: - repo_id = constants.REPO_TYPES_URL_PREFIXES[repo_type] + repo_id - revision = revision if revision is not None else constants.DEFAULT_REVISION + if repo_type in REPO_TYPES_URL_PREFIXES: + repo_id = REPO_TYPES_URL_PREFIXES[repo_type] + repo_id + revision = revision if revision is not None else DEFAULT_REVISION return CommitInfo( commit_url=commit_info.commit_url, @@ -5172,7 +5190,7 @@ def get_hf_file_metadata( url: str, token: Union[bool, str, None] = None, proxies: Optional[Dict] = None, - timeout: Optional[float] = constants.DEFAULT_REQUEST_TIMEOUT, + timeout: Optional[float] = DEFAULT_REQUEST_TIMEOUT, ) -> HfFileMetadata: """Fetch metadata of a file versioned on the Hub for a given url. @@ -5219,7 +5237,7 @@ def hf_hub_download( local_dir: Union[str, Path, None] = None, force_download: bool = False, proxies: Optional[Dict] = None, - etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, + etag_timeout: float = DEFAULT_ETAG_TIMEOUT, token: Union[bool, str, None] = None, local_files_only: bool = False, # Deprecated args @@ -5358,7 +5376,7 @@ def snapshot_download( cache_dir: Union[str, Path, None] = None, local_dir: Union[str, Path, None] = None, proxies: Optional[Dict] = None, - etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, + etag_timeout: float = DEFAULT_ETAG_TIMEOUT, force_download: bool = False, token: Union[bool, str, None] = None, local_files_only: bool = False, @@ -5548,14 +5566,14 @@ def get_safetensors_metadata( """ if self.file_exists( # Single safetensors file => non-sharded model repo_id=repo_id, - filename=constants.SAFETENSORS_SINGLE_FILE, + filename=SAFETENSORS_SINGLE_FILE, repo_type=repo_type, revision=revision, token=token, ): file_metadata = self.parse_safetensors_file_metadata( repo_id=repo_id, - filename=constants.SAFETENSORS_SINGLE_FILE, + filename=SAFETENSORS_SINGLE_FILE, repo_type=repo_type, revision=revision, token=token, @@ -5564,13 +5582,13 @@ def get_safetensors_metadata( metadata=None, sharded=False, weight_map={ - tensor_name: constants.SAFETENSORS_SINGLE_FILE for tensor_name in file_metadata.tensors.keys() + tensor_name: SAFETENSORS_SINGLE_FILE for tensor_name in file_metadata.tensors.keys() }, - files_metadata={constants.SAFETENSORS_SINGLE_FILE: file_metadata}, + files_metadata={SAFETENSORS_SINGLE_FILE: file_metadata}, ) elif self.file_exists( # Multiple safetensors files => sharded with index repo_id=repo_id, - filename=constants.SAFETENSORS_INDEX_FILE, + filename=SAFETENSORS_INDEX_FILE, repo_type=repo_type, revision=revision, token=token, @@ -5578,7 +5596,7 @@ def get_safetensors_metadata( # Fetch index index_file = self.hf_hub_download( repo_id=repo_id, - filename=constants.SAFETENSORS_INDEX_FILE, + filename=SAFETENSORS_INDEX_FILE, repo_type=repo_type, revision=revision, token=token, @@ -5612,7 +5630,7 @@ def _parse(filename: str) -> None: else: # Not a safetensors repo raise NotASafetensorsRepoError( - f"'{repo_id}' is not a safetensors repo. Couldn't find '{constants.SAFETENSORS_INDEX_FILE}' or '{constants.SAFETENSORS_SINGLE_FILE}' files." + f"'{repo_id}' is not a safetensors repo. Couldn't find '{SAFETENSORS_INDEX_FILE}' or '{SAFETENSORS_SINGLE_FILE}' files." ) def parse_safetensors_file_metadata( @@ -5673,11 +5691,11 @@ def parse_safetensors_file_metadata( # 2. Parse metadata size metadata_size = struct.unpack(" constants.SAFETENSORS_MAX_HEADER_LENGTH: + if metadata_size > SAFETENSORS_MAX_HEADER_LENGTH: raise SafetensorsParsingError( f"Failed to parse safetensors header for '{filename}' (repo '{repo_id}', revision " - f"'{revision or constants.DEFAULT_REVISION}'): safetensors header is too big. Maximum supported size is " - f"{constants.SAFETENSORS_MAX_HEADER_LENGTH} bytes (got {metadata_size})." + f"'{revision or DEFAULT_REVISION}'): safetensors header is too big. Maximum supported size is " + f"{SAFETENSORS_MAX_HEADER_LENGTH} bytes (got {metadata_size})." ) # 3.a. Get metadata from payload @@ -5694,7 +5712,7 @@ def parse_safetensors_file_metadata( except json.JSONDecodeError as e: raise SafetensorsParsingError( f"Failed to parse safetensors header for '{filename}' (repo '{repo_id}', revision " - f"'{revision or constants.DEFAULT_REVISION}'): header is not json-encoded string. Please make sure this is a " + f"'{revision or DEFAULT_REVISION}'): header is not json-encoded string. Please make sure this is a " "correctly formatted safetensors file." ) from e @@ -5714,7 +5732,7 @@ def parse_safetensors_file_metadata( except (KeyError, IndexError) as e: raise SafetensorsParsingError( f"Failed to parse safetensors header for '{filename}' (repo '{repo_id}', revision " - f"'{revision or constants.DEFAULT_REVISION}'): header format not recognized. Please make sure this is a correctly" + f"'{revision or DEFAULT_REVISION}'): header format not recognized. Please make sure this is a correctly" " formatted safetensors file." ) from e @@ -5770,7 +5788,7 @@ def create_branch( set to `False`. """ if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL branch = quote(branch, safe="") # Prepare request @@ -5839,7 +5857,7 @@ def delete_branch( """ if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL branch = quote(branch, safe="") # Prepare request @@ -5906,8 +5924,8 @@ def create_tag( set to `False`. """ if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL - revision = quote(revision, safe="") if revision is not None else constants.DEFAULT_REVISION + repo_type = REPO_TYPE_MODEL + revision = quote(revision, safe="") if revision is not None else DEFAULT_REVISION # Prepare request tag_url = f"{self.endpoint}/api/{repo_type}s/{repo_id}/tag/{revision}" @@ -5962,7 +5980,7 @@ def delete_tag( If tag is not found. """ if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL tag = quote(tag, safe="") # Prepare request @@ -6017,8 +6035,8 @@ def get_repo_discussions( repo_id: str, *, author: Optional[str] = None, - discussion_type: Optional[constants.DiscussionTypeFilter] = None, - discussion_status: Optional[constants.DiscussionStatusFilter] = None, + discussion_type: Optional[DiscussionTypeFilter] = None, + discussion_status: Optional[DiscussionStatusFilter] = None, repo_type: Optional[str] = None, token: Union[bool, str, None] = None, ) -> Iterator[Discussion]: @@ -6070,14 +6088,14 @@ def get_repo_discussions( ... print(discussion.num, discussion.title) ``` """ - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL - if discussion_type is not None and discussion_type not in constants.DISCUSSION_TYPES: - raise ValueError(f"Invalid discussion_type, must be one of {constants.DISCUSSION_TYPES}") - if discussion_status is not None and discussion_status not in constants.DISCUSSION_STATUS: - raise ValueError(f"Invalid discussion_status, must be one of {constants.DISCUSSION_STATUS}") + repo_type = REPO_TYPE_MODEL + if discussion_type is not None and discussion_type not in DISCUSSION_TYPES: + raise ValueError(f"Invalid discussion_type, must be one of {DISCUSSION_TYPES}") + if discussion_status is not None and discussion_status not in DISCUSSION_STATUS: + raise ValueError(f"Invalid discussion_status, must be one of {DISCUSSION_STATUS}") headers = self._build_hf_headers(token=token) path = f"{self.endpoint}/api/{repo_type}s/{repo_id}/discussions" @@ -6164,10 +6182,10 @@ def get_discussion_details( """ if not isinstance(discussion_num, int) or discussion_num <= 0: raise ValueError("Invalid discussion_num, must be a positive integer") - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL path = f"{self.endpoint}/api/{repo_type}s/{repo_id}/discussions/{discussion_num}" headers = self._build_hf_headers(token=token) @@ -6254,10 +6272,10 @@ def create_discussion( or because it is set to `private` and you do not have access. """ - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL if description is not None: description = description.strip() @@ -6364,10 +6382,10 @@ def _post_discussion_changes( """Internal utility to POST changes to a Discussion or Pull Request""" if not isinstance(discussion_num, int) or discussion_num <= 0: raise ValueError("Invalid discussion_num, must be a positive integer") - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL repo_id = f"{repo_type}s/{repo_id}" path = f"{self.endpoint}/api/{repo_id}/discussions/{discussion_num}/{resource}" @@ -7391,7 +7409,7 @@ def list_inference_endpoints( namespace = namespace or self._get_namespace(token=token) response = get_session().get( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}", headers=self._build_hf_headers(token=token), ) hf_raise_for_status(response) @@ -7550,7 +7568,7 @@ def create_inference_endpoint( } response = get_session().post( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}", headers=self._build_hf_headers(token=token), json=payload, ) @@ -7598,7 +7616,7 @@ def get_inference_endpoint( namespace = namespace or self._get_namespace(token=token) response = get_session().get( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}", headers=self._build_hf_headers(token=token), ) hf_raise_for_status(response) @@ -7694,7 +7712,7 @@ def update_inference_endpoint( } response = get_session().put( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}", headers=self._build_hf_headers(token=token), json=payload, ) @@ -7725,7 +7743,7 @@ def delete_inference_endpoint( """ namespace = namespace or self._get_namespace(token=token) response = get_session().delete( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}", headers=self._build_hf_headers(token=token), ) hf_raise_for_status(response) @@ -7758,7 +7776,7 @@ def pause_inference_endpoint( namespace = namespace or self._get_namespace(token=token) response = get_session().post( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}/pause", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}/pause", headers=self._build_hf_headers(token=token), ) hf_raise_for_status(response) @@ -7797,7 +7815,7 @@ def resume_inference_endpoint( namespace = namespace or self._get_namespace(token=token) response = get_session().post( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}/resume", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}/resume", headers=self._build_hf_headers(token=token), ) try: @@ -7839,7 +7857,7 @@ def scale_to_zero_inference_endpoint( namespace = namespace or self._get_namespace(token=token) response = get_session().post( - f"{constants.INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}/scale-to-zero", + f"{INFERENCE_ENDPOINTS_ENDPOINT}/endpoint/{namespace}/{name}/scale-to-zero", headers=self._build_hf_headers(token=token), ) hf_raise_for_status(response) @@ -8521,10 +8539,10 @@ def _list_access_requests( repo_type: Optional[str] = None, token: Union[bool, str, None] = None, ) -> List[AccessRequest]: - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL response = get_session().get( f"{ENDPOINT}/api/{repo_type}s/{repo_id}/user-access-request/{status}", @@ -8676,10 +8694,10 @@ def _handle_access_request( repo_type: Optional[str] = None, token: Union[bool, str, None] = None, ) -> None: - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL response = get_session().post( f"{ENDPOINT}/api/{repo_type}s/{repo_id}/user-access-request/handle", @@ -8726,10 +8744,10 @@ def grant_access( [`HTTPError`](https://requests.readthedocs.io/en/latest/api/#requests.HTTPError): HTTP 404 if the user does not exist on the Hub. """ - if repo_type not in constants.REPO_TYPES: - raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}") + if repo_type not in REPO_TYPES: + raise ValueError(f"Invalid repo type, must be one of {REPO_TYPES}") if repo_type is None: - repo_type = constants.REPO_TYPE_MODEL + repo_type = REPO_TYPE_MODEL response = get_session().post( f"{ENDPOINT}/api/models/{repo_id}/user-access-request/grant", @@ -8850,7 +8868,7 @@ def create_webhook( *, url: str, watched: List[Union[Dict, WebhookWatchedItem]], - domains: Optional[List[constants.WEBHOOK_DOMAIN_T]] = None, + domains: Optional[List[WEBHOOK_DOMAIN_T]] = None, secret: Optional[str] = None, token: Union[bool, str, None] = None, ) -> WebhookInfo: @@ -8924,7 +8942,7 @@ def update_webhook( *, url: Optional[str] = None, watched: Optional[List[Union[Dict, WebhookWatchedItem]]] = None, - domains: Optional[List[constants.WEBHOOK_DOMAIN_T]] = None, + domains: Optional[List[WEBHOOK_DOMAIN_T]] = None, secret: Optional[str] = None, token: Union[bool, str, None] = None, ) -> WebhookInfo: diff --git a/tests/test_hf_api.py b/tests/test_hf_api.py index 84a552d561..07a6dd68b5 100644 --- a/tests/test_hf_api.py +++ b/tests/test_hf_api.py @@ -35,7 +35,7 @@ from requests.exceptions import HTTPError import huggingface_hub.lfs -from huggingface_hub import HfApi, SpaceHardware, SpaceStage, SpaceStorage, constants +from huggingface_hub import HfApi, SpaceHardware, SpaceStage, SpaceStorage from huggingface_hub._commit_api import ( CommitOperationAdd, CommitOperationCopy, @@ -43,6 +43,12 @@ _fetch_upload_modes, ) from huggingface_hub.community import DiscussionComment, DiscussionWithDetails +from huggingface_hub.constants import ( + REPO_TYPE_DATASET, + REPO_TYPE_MODEL, + REPO_TYPE_SPACE, + SPACES_SDK_TYPES, +) from huggingface_hub.file_download import hf_hub_download from huggingface_hub.hf_api import ( AccessRequest, @@ -223,43 +229,41 @@ def test_create_update_and_delete_repo(self): self._api.delete_repo(repo_id=repo_id) def test_create_update_and_delete_model_repo(self): - repo_id = self._api.create_repo(repo_id=repo_name(), repo_type=constants.REPO_TYPE_MODEL).repo_id - res = self._api.update_repo_visibility(repo_id=repo_id, private=True, repo_type=constants.REPO_TYPE_MODEL) + repo_id = self._api.create_repo(repo_id=repo_name(), repo_type=REPO_TYPE_MODEL).repo_id + res = self._api.update_repo_visibility(repo_id=repo_id, private=True, repo_type=REPO_TYPE_MODEL) assert res["private"] - res = self._api.update_repo_visibility(repo_id=repo_id, private=False, repo_type=constants.REPO_TYPE_MODEL) + res = self._api.update_repo_visibility(repo_id=repo_id, private=False, repo_type=REPO_TYPE_MODEL) assert not res["private"] - self._api.delete_repo(repo_id=repo_id, repo_type=constants.REPO_TYPE_MODEL) + self._api.delete_repo(repo_id=repo_id, repo_type=REPO_TYPE_MODEL) def test_create_update_and_delete_dataset_repo(self): - repo_id = self._api.create_repo(repo_id=repo_name(), repo_type=constants.REPO_TYPE_DATASET).repo_id - res = self._api.update_repo_visibility(repo_id=repo_id, private=True, repo_type=constants.REPO_TYPE_DATASET) + repo_id = self._api.create_repo(repo_id=repo_name(), repo_type=REPO_TYPE_DATASET).repo_id + res = self._api.update_repo_visibility(repo_id=repo_id, private=True, repo_type=REPO_TYPE_DATASET) assert res["private"] - res = self._api.update_repo_visibility(repo_id=repo_id, private=False, repo_type=constants.REPO_TYPE_DATASET) + res = self._api.update_repo_visibility(repo_id=repo_id, private=False, repo_type=REPO_TYPE_DATASET) assert not res["private"] - self._api.delete_repo(repo_id=repo_id, repo_type=constants.REPO_TYPE_DATASET) + self._api.delete_repo(repo_id=repo_id, repo_type=REPO_TYPE_DATASET) def test_create_update_and_delete_space_repo(self): with pytest.raises(ValueError, match=r"No space_sdk provided.*"): - self._api.create_repo(repo_id=repo_name(), repo_type=constants.REPO_TYPE_SPACE, space_sdk=None) + self._api.create_repo(repo_id=repo_name(), repo_type=REPO_TYPE_SPACE, space_sdk=None) with pytest.raises(ValueError, match=r"Invalid space_sdk.*"): - self._api.create_repo(repo_id=repo_name(), repo_type=constants.REPO_TYPE_SPACE, space_sdk="something") + self._api.create_repo(repo_id=repo_name(), repo_type=REPO_TYPE_SPACE, space_sdk="something") - for sdk in constants.SPACES_SDK_TYPES: - repo_id = self._api.create_repo( - repo_id=repo_name(), repo_type=constants.REPO_TYPE_SPACE, space_sdk=sdk - ).repo_id - res = self._api.update_repo_visibility(repo_id=repo_id, private=True, repo_type=constants.REPO_TYPE_SPACE) + for sdk in SPACES_SDK_TYPES: + repo_id = self._api.create_repo(repo_id=repo_name(), repo_type=REPO_TYPE_SPACE, space_sdk=sdk).repo_id + res = self._api.update_repo_visibility(repo_id=repo_id, private=True, repo_type=REPO_TYPE_SPACE) assert res["private"] - res = self._api.update_repo_visibility(repo_id=repo_id, private=False, repo_type=constants.REPO_TYPE_SPACE) + res = self._api.update_repo_visibility(repo_id=repo_id, private=False, repo_type=REPO_TYPE_SPACE) assert not res["private"] - self._api.delete_repo(repo_id=repo_id, repo_type=constants.REPO_TYPE_SPACE) + self._api.delete_repo(repo_id=repo_id, repo_type=REPO_TYPE_SPACE) def test_move_repo_normal_usage(self): repo_id = f"{USER}/{repo_name()}" new_repo_id = f"{USER}/{repo_name()}" # Spaces not tested on staging (error 500) - for repo_type in [None, constants.REPO_TYPE_MODEL, constants.REPO_TYPE_DATASET]: + for repo_type in [None, REPO_TYPE_MODEL, REPO_TYPE_DATASET]: self._api.create_repo(repo_id=repo_id, repo_type=repo_type) self._api.move_repo(from_id=repo_id, to_id=new_repo_id, repo_type=repo_type) self._api.delete_repo(repo_id=new_repo_id, repo_type=repo_type) @@ -272,7 +276,7 @@ def test_move_repo_target_already_exists(self) -> None: self._api.create_repo(repo_id=repo_id_2) with pytest.raises(HfHubHTTPError, match=r"A model repository called .* already exists"): - self._api.move_repo(from_id=repo_id_1, to_id=repo_id_2, repo_type=constants.REPO_TYPE_MODEL) + self._api.move_repo(from_id=repo_id_1, to_id=repo_id_2, repo_type=REPO_TYPE_MODEL) self._api.delete_repo(repo_id=repo_id_1) self._api.delete_repo(repo_id=repo_id_2)