diff --git a/.github/workflows/contrib-tests.yml b/.github/workflows/contrib-tests.yml index df663ce975..d294b7b530 100644 --- a/.github/workflows/contrib-tests.yml +++ b/.github/workflows/contrib-tests.yml @@ -26,10 +26,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8 + - name: Set up Python 3.9 uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: 3.9 # Install pip - name: Install pip diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 11bfcc806f..6c9bacf656 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.13"] + python-version: ["3.9", "3.13"] test_name: [ "Repository only", @@ -30,18 +30,18 @@ jobs: "Xet only" ] include: - - python-version: "3.13" # LFS not ran on 3.8 + - python-version: "3.13" # LFS not ran on 3.9 test_name: "lfs" - - python-version: "3.8" + - python-version: "3.9" test_name: "fastai" - python-version: "3.10" # fastai not supported on 3.12 and 3.11 -> test it on 3.10 test_name: "fastai" - - python-version: "3.8" + - python-version: "3.9" test_name: "tensorflow" - python-version: "3.10" # tensorflow not supported on 3.12 -> test it on 3.10 test_name: "tensorflow" - - python-version: "3.8" # test torch~=1.11 on python 3.8 only. - test_name: "Python 3.8, torch_1.11" + - python-version: "3.9" # test torch~=1.11 on python 3.9 only. + test_name: "Python 3.9, torch_1.11" - python-version: "3.12" # test torch latest on python 3.12 only. test_name: "torch_latest" steps: @@ -84,7 +84,7 @@ jobs: uv pip install --upgrade torch ;; - "Python 3.8, torch_1.11") + "Python 3.9, torch_1.11") uv pip install "huggingface_hub[torch] @ ." uv pip install torch~=1.11 ;; @@ -147,7 +147,7 @@ jobs: eval "$PYTEST ../tests/test_serialization.py" ;; - "Python 3.8, torch_1.11" | torch_latest) + "Python 3.9, torch_1.11" | torch_latest) eval "$PYTEST ../tests/test_hub_mixin*" eval "$PYTEST ../tests/test_serialization.py" ;; @@ -178,7 +178,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.11"] + python-version: ["3.9", "3.11"] test_name: ["Everything else", "Xet only"] steps: diff --git a/.github/workflows/release-conda.yml b/.github/workflows/release-conda.yml index 135d988809..b6ead02950 100644 --- a/.github/workflows/release-conda.yml +++ b/.github/workflows/release-conda.yml @@ -26,7 +26,7 @@ jobs: with: auto-update-conda: true auto-activate-base: false - python-version: 3.8 + python-version: 3.9 activate-environment: "build-hub" - name: Setup conda env diff --git a/docs/source/cn/installation.md b/docs/source/cn/installation.md index c800b4b173..ec899a2305 100644 --- a/docs/source/cn/installation.md +++ b/docs/source/cn/installation.md @@ -6,7 +6,7 @@ rendered properly in your Markdown viewer. 在开始之前,您需要通过安装适当的软件包来设置您的环境 -huggingface_hub 在 Python 3.8 或更高版本上进行了测试,可以保证在这些版本上正常运行。如果您使用的是 Python 3.7 或更低版本,可能会出现兼容性问题 +huggingface_hub 在 Python 3.9 或更高版本上进行了测试,可以保证在这些版本上正常运行。如果您使用的是 Python 3.7 或更低版本,可能会出现兼容性问题 ## 使用 pip 安装 diff --git a/docs/source/de/guides/integrations.md b/docs/source/de/guides/integrations.md index 06384c80da..3d792c3b5e 100644 --- a/docs/source/de/guides/integrations.md +++ b/docs/source/de/guides/integrations.md @@ -202,7 +202,7 @@ class PyTorchModelHubMixin(ModelHubMixin): revision: str, cache_dir: str, force_download: bool, - proxies: Optional[Dict], + proxies: Optional[dict], resume_download: bool, local_files_only: bool, token: Union[str, bool, None], diff --git a/docs/source/de/installation.md b/docs/source/de/installation.md index 3ba965bd4b..4c2a907f04 100644 --- a/docs/source/de/installation.md +++ b/docs/source/de/installation.md @@ -6,7 +6,7 @@ rendered properly in your Markdown viewer. Bevor Sie beginnen, müssen Sie Ihre Umgebung vorbereiten, indem Sie die entsprechenden Pakete installieren. -`huggingface_hub` wurde für **Python 3.8+** getestet. +`huggingface_hub` wurde für **Python 3.9+** getestet. ## Installation mit pip diff --git a/docs/source/en/guides/integrations.md b/docs/source/en/guides/integrations.md index e5ac9aaa87..cc4431923d 100644 --- a/docs/source/en/guides/integrations.md +++ b/docs/source/en/guides/integrations.md @@ -244,7 +244,7 @@ class PyTorchModelHubMixin(ModelHubMixin): revision: str, cache_dir: str, force_download: bool, - proxies: Optional[Dict], + proxies: Optional[dict], resume_download: bool, local_files_only: bool, token: Union[str, bool, None], diff --git a/docs/source/en/installation.md b/docs/source/en/installation.md index 9af8a32676..7d86b715d0 100644 --- a/docs/source/en/installation.md +++ b/docs/source/en/installation.md @@ -6,7 +6,7 @@ rendered properly in your Markdown viewer. Before you start, you will need to setup your environment by installing the appropriate packages. -`huggingface_hub` is tested on **Python 3.8+**. +`huggingface_hub` is tested on **Python 3.9+**. ## Install with pip diff --git a/docs/source/fr/guides/integrations.md b/docs/source/fr/guides/integrations.md index 5a9736667f..f2c81a3d17 100644 --- a/docs/source/fr/guides/integrations.md +++ b/docs/source/fr/guides/integrations.md @@ -223,7 +223,7 @@ class PyTorchModelHubMixin(ModelHubMixin): revision: str, cache_dir: str, force_download: bool, - proxies: Optional[Dict], + proxies: Optional[dict], resume_download: bool, local_files_only: bool, token: Union[str, bool, None], @@ -266,9 +266,9 @@ est ici pour vous donner des indications et des idées sur comment gérer l'int n'hésitez pas à nous contacter si vous avez une question ! -| Intégration | Utilisant des helpers | Utilisant [`ModelHubMixin`] | -|:---:|:---:|:---:| -| Expérience utilisateur | `model = load_from_hub(...)`
`push_to_hub(model, ...)` | `model = MyModel.from_pretrained(...)`
`model.push_to_hub(...)` | -| Flexible | Très flexible.
Vous controllez complètement l'implémentation. | Moins flexible.
Votre framework doit avoir une classe de modèle. | -| Maintenance | Plus de maintenance pour ajouter du support pour la configuration, et de nouvelles fonctionnalités. Peut aussi nécessiter de fixx des problèmes signalés par les utilisateurs.| Moins de maintenance vu que la plupart des intégrations avec le Hub sont implémentés dans `huggingface_hub` | -| Documentation / Anotation de type| A écrire à la main | Géré partiellement par `huggingface_hub`. | +| Intégration | Utilisant des helpers | Utilisant [`ModelHubMixin`] | +| :-------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------: | +| Expérience utilisateur | `model = load_from_hub(...)`
`push_to_hub(model, ...)` | `model = MyModel.from_pretrained(...)`
`model.push_to_hub(...)` | +| Flexible | Très flexible.
Vous controllez complètement l'implémentation. | Moins flexible.
Votre framework doit avoir une classe de modèle. | +| Maintenance | Plus de maintenance pour ajouter du support pour la configuration, et de nouvelles fonctionnalités. Peut aussi nécessiter de fixx des problèmes signalés par les utilisateurs. | Moins de maintenance vu que la plupart des intégrations avec le Hub sont implémentés dans `huggingface_hub` | +| Documentation / Anotation de type | A écrire à la main | Géré partiellement par `huggingface_hub`. | diff --git a/docs/source/fr/installation.md b/docs/source/fr/installation.md index eb4b2ee9b4..6e0f41ee6e 100644 --- a/docs/source/fr/installation.md +++ b/docs/source/fr/installation.md @@ -7,7 +7,7 @@ rendered properly in your Markdown viewer. Avant de commencer, vous allez avoir besoin de préparer votre environnement en installant les packages appropriés. -`huggingface_hub` est testée sur **Python 3.8+**. +`huggingface_hub` est testée sur **Python 3.9+**. ## Installation avec pip diff --git a/docs/source/hi/installation.md b/docs/source/hi/installation.md index 1659e85fd7..c5974a32f7 100644 --- a/docs/source/hi/installation.md +++ b/docs/source/hi/installation.md @@ -6,7 +6,7 @@ rendered properly in your Markdown viewer. आरंभ करने से पहले, आपको उपयुक्त पैकेज स्थापित करके अपना परिवेश सेटअप करना होगा। -`huggingface_hub` का परीक्षण **Python 3.8+** पर किया गया है। +`huggingface_hub` का परीक्षण **Python 3.9+** पर किया गया है। ## पिप के साथ स्थापित करें diff --git a/docs/source/ko/guides/integrations.md b/docs/source/ko/guides/integrations.md index f0946bc298..a3ff1750f6 100644 --- a/docs/source/ko/guides/integrations.md +++ b/docs/source/ko/guides/integrations.md @@ -211,7 +211,7 @@ class PyTorchModelHubMixin(ModelHubMixin): revision: str, cache_dir: str, force_download: bool, - proxies: Optional[Dict], + proxies: Optional[dict], resume_download: bool, local_files_only: bool, token: Union[str, bool, None], @@ -393,11 +393,11 @@ class VoiceCraft( 두 가지 접근 방법에 대한 장단점을 간단히 정리해보겠습니다. 아래 표는 단순히 예시일 뿐입니다. 각자 다른 프레임워크에는 고려해야 할 특정 사항이 있을 수 있습니다. 이 가이드는 통합을 다루는 아이디어와 지침을 제공하기 위한 것입니다. 언제든지 궁금한 점이 있으면 문의해 주세요! -| 통합 | helpers 사용 시 | [`ModelHubMixin`] 사용 시 | -|:---:|:---:|:---:| -| 사용자 경험 | `model = load_from_hub(...)`
`push_to_hub(model, ...)` | `model = MyModel.from_pretrained(...)`
`model.push_to_hub(...)` | -| 유연성 | 매우 유연합니다.
구현을 완전히 제어합니다. | 유연성이 떨어집니다.
프레임워크에는 모델 클래스가 있어야 합니다. | -| 유지 관리 | 구성 및 새로운 기능에 대한 지원을 추가하기 위한 유지 관리가 더 필요합니다. 사용자가 보고한 문제를 해결해야할 수도 있습니다. | Hub와의 대부분의 상호 작용이 `huggingface_hub`에서 구현되므로 유지 관리가 줄어듭니다. | -| 문서화 / 타입 주석 | 수동으로 작성해야 합니다. | `huggingface_hub`에서 부분적으로 처리됩니다. | -| 다운로드 횟수 표시기 | 수동으로 처리해야 합니다. | 클래스에 `config` 속성이 있다면 기본적으로 활성화됩니다. | -| 모델 카드 | 수동으로 처리해야 합니다. | library_name, tags 등을 활용하여 기본적으로 생성됩니다. | +| 통합 | helpers 사용 시 | [`ModelHubMixin`] 사용 시 | +| :------------------: | :-------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------: | +| 사용자 경험 | `model = load_from_hub(...)`
`push_to_hub(model, ...)` | `model = MyModel.from_pretrained(...)`
`model.push_to_hub(...)` | +| 유연성 | 매우 유연합니다.
구현을 완전히 제어합니다. | 유연성이 떨어집니다.
프레임워크에는 모델 클래스가 있어야 합니다. | +| 유지 관리 | 구성 및 새로운 기능에 대한 지원을 추가하기 위한 유지 관리가 더 필요합니다. 사용자가 보고한 문제를 해결해야할 수도 있습니다. | Hub와의 대부분의 상호 작용이 `huggingface_hub`에서 구현되므로 유지 관리가 줄어듭니다. | +| 문서화 / 타입 주석 | 수동으로 작성해야 합니다. | `huggingface_hub`에서 부분적으로 처리됩니다. | +| 다운로드 횟수 표시기 | 수동으로 처리해야 합니다. | 클래스에 `config` 속성이 있다면 기본적으로 활성화됩니다. | +| 모델 카드 | 수동으로 처리해야 합니다. | library_name, tags 등을 활용하여 기본적으로 생성됩니다. | diff --git a/docs/source/ko/installation.md b/docs/source/ko/installation.md index 720346b1a1..b222bef630 100644 --- a/docs/source/ko/installation.md +++ b/docs/source/ko/installation.md @@ -6,7 +6,7 @@ rendered properly in your Markdown viewer. 시작하기 전에 적절한 패키지를 설치하여 환경을 설정해야 합니다. -`huggingface_hub`는 **Python 3.8+**에서 테스트되었습니다. +`huggingface_hub`는 **Python 3.9+**에서 테스트되었습니다. ## pip로 설치하기 [[install-with-pip]] diff --git a/docs/source/tm/installation.md b/docs/source/tm/installation.md index f16ac74667..28134ed5b7 100644 --- a/docs/source/tm/installation.md +++ b/docs/source/tm/installation.md @@ -2,7 +2,7 @@ நீங்கள் தொடங்குவதற்கு முன், தகுந்த தொகுப்புகளை நிறுவுவதன் மூலம் உங்கள் சூழலை அமைக்க வேண்டும். -`huggingface_hub` **Python 3.8+** மின்பொருள்களில் சோதிக்கப்பட்டுள்ளது. +`huggingface_hub` **Python 3.9+** மின்பொருள்களில் சோதிக்கப்பட்டுள்ளது. ### பிப் மூலம் நிறுவு diff --git a/setup.py b/setup.py index 3fd35880fa..ec5ebfbb39 100644 --- a/setup.py +++ b/setup.py @@ -89,7 +89,7 @@ def get_version() -> str: "soundfile", "Pillow", "gradio>=4.0.0", # to test webhooks # pin to avoid issue on Python3.12 - "requests", # for gradio + "requests", # for gradio "numpy", # for embeddings "fastapi", # To build the documentation ] @@ -108,8 +108,7 @@ def get_version() -> str: extras["quality"] = [ "ruff>=0.9.0", - "mypy>=1.14.1,<1.15.0; python_version=='3.8'", - "mypy==1.15.0; python_version>='3.9'", + "mypy==1.15.0", "libcst>=1.4.0", "ty", ] @@ -140,7 +139,7 @@ def get_version() -> str: ], "fsspec.specs": "hf=huggingface_hub.HfFileSystem", }, - python_requires=">=3.8.0", + python_requires=">=3.9.0", install_requires=install_requires, classifiers=[ "Intended Audience :: Developers", @@ -150,7 +149,6 @@ def get_version() -> str: "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", diff --git a/src/huggingface_hub/_commit_api.py b/src/huggingface_hub/_commit_api.py index 58e082b307..70fe8f78c3 100644 --- a/src/huggingface_hub/_commit_api.py +++ b/src/huggingface_hub/_commit_api.py @@ -11,7 +11,7 @@ from dataclasses import dataclass, field from itertools import groupby from pathlib import Path, PurePosixPath -from typing import TYPE_CHECKING, Any, BinaryIO, Dict, Iterable, Iterator, List, Literal, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, BinaryIO, Iterable, Iterator, Literal, Optional, Union from tqdm.contrib.concurrent import thread_map @@ -306,7 +306,7 @@ def _validate_path_in_repo(path_in_repo: str) -> str: CommitOperation = Union[CommitOperationAdd, CommitOperationCopy, CommitOperationDelete] -def _warn_on_overwriting_operations(operations: List[CommitOperation]) -> None: +def _warn_on_overwriting_operations(operations: list[CommitOperation]) -> None: """ Warn user when a list of operations is expected to overwrite itself in a single commit. @@ -321,7 +321,7 @@ def _warn_on_overwriting_operations(operations: List[CommitOperation]) -> None: delete before upload) but can happen if a user deletes an entire folder and then add new files to it. """ - nb_additions_per_path: Dict[str, int] = defaultdict(int) + nb_additions_per_path: dict[str, int] = defaultdict(int) for operation in operations: path_in_repo = operation.path_in_repo if isinstance(operation, CommitOperationAdd): @@ -355,10 +355,10 @@ def _warn_on_overwriting_operations(operations: List[CommitOperation]) -> None: @validate_hf_hub_args def _upload_lfs_files( *, - additions: List[CommitOperationAdd], + additions: list[CommitOperationAdd], repo_type: str, repo_id: str, - headers: Dict[str, str], + headers: dict[str, str], endpoint: Optional[str] = None, num_threads: int = 5, revision: Optional[str] = None, @@ -377,7 +377,7 @@ def _upload_lfs_files( repo_id (`str`): A namespace (user or an organization) and a repo name separated by a `/`. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): Headers to use for the request, including authorization headers and user agent. num_threads (`int`, *optional*): The number of concurrent threads to use when uploading. Defaults to 5. @@ -395,7 +395,7 @@ def _upload_lfs_files( # Step 1: retrieve upload instructions from the LFS batch endpoint. # Upload instructions are retrieved by chunk of 256 files to avoid reaching # the payload limit. - batch_actions: List[Dict] = [] + batch_actions: list[dict] = [] for chunk in chunk_iterable(additions, chunk_size=UPLOAD_BATCH_MAX_NUM_FILES): batch_actions_chunk, batch_errors_chunk = post_lfs_batch_info( upload_infos=[op.upload_info for op in chunk], @@ -466,10 +466,10 @@ def _wrapped_lfs_upload(batch_action) -> None: @validate_hf_hub_args def _upload_xet_files( *, - additions: List[CommitOperationAdd], + additions: list[CommitOperationAdd], repo_type: str, repo_id: str, - headers: Dict[str, str], + headers: dict[str, str], endpoint: Optional[str] = None, revision: Optional[str] = None, create_pr: Optional[bool] = None, @@ -486,7 +486,7 @@ def _upload_xet_files( repo_id (`str`): A namespace (user or an organization) and a repo name separated by a `/`. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): Headers to use for the request, including authorization headers and user agent. endpoint: (`str`, *optional*): The endpoint to use for the xetcas service. Defaults to `constants.ENDPOINT`. @@ -555,7 +555,7 @@ def _upload_xet_files( xet_endpoint = xet_connection_info.endpoint access_token_info = (xet_connection_info.access_token, xet_connection_info.expiration_unix_epoch) - def token_refresher() -> Tuple[str, int]: + def token_refresher() -> tuple[str, int]: new_xet_connection = fetch_xet_connection_info_from_repo_info( token_type=XetTokenType.WRITE, repo_id=repo_id, @@ -628,7 +628,7 @@ def _fetch_upload_modes( additions: Iterable[CommitOperationAdd], repo_type: str, repo_id: str, - headers: Dict[str, str], + headers: dict[str, str], revision: str, endpoint: Optional[str] = None, create_pr: bool = False, @@ -647,7 +647,7 @@ def _fetch_upload_modes( repo_id (`str`): A namespace (user or an organization) and a repo name separated by a `/`. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): Headers to use for the request, including authorization headers and user agent. revision (`str`): The git revision to upload the files to. Can be any valid git revision. @@ -665,12 +665,12 @@ def _fetch_upload_modes( endpoint = endpoint if endpoint is not None else constants.ENDPOINT # Fetch upload mode (LFS or regular) chunk by chunk. - upload_modes: Dict[str, UploadMode] = {} - should_ignore_info: Dict[str, bool] = {} - oid_info: Dict[str, Optional[str]] = {} + upload_modes: dict[str, UploadMode] = {} + should_ignore_info: dict[str, bool] = {} + oid_info: dict[str, Optional[str]] = {} for chunk in chunk_iterable(additions, 256): - payload: Dict = { + payload: dict = { "files": [ { "path": op.path_in_repo, @@ -713,10 +713,10 @@ def _fetch_files_to_copy( copies: Iterable[CommitOperationCopy], repo_type: str, repo_id: str, - headers: Dict[str, str], + headers: dict[str, str], revision: str, endpoint: Optional[str] = None, -) -> Dict[Tuple[str, Optional[str]], Union["RepoFile", bytes]]: +) -> dict[tuple[str, Optional[str]], Union["RepoFile", bytes]]: """ Fetch information about the files to copy. @@ -732,12 +732,12 @@ def _fetch_files_to_copy( repo_id (`str`): A namespace (user or an organization) and a repo name separated by a `/`. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): Headers to use for the request, including authorization headers and user agent. revision (`str`): The git revision to upload the files to. Can be any valid git revision. - Returns: `Dict[Tuple[str, Optional[str]], Union[RepoFile, bytes]]]` + Returns: `dict[tuple[str, Optional[str]], Union[RepoFile, bytes]]]` Key is the file path and revision of the file to copy. Value is the raw content as bytes (for regular files) or the file information as a RepoFile (for LFS files). @@ -750,9 +750,9 @@ def _fetch_files_to_copy( from .hf_api import HfApi, RepoFolder hf_api = HfApi(endpoint=endpoint, headers=headers) - files_to_copy: Dict[Tuple[str, Optional[str]], Union["RepoFile", bytes]] = {} + files_to_copy: dict[tuple[str, Optional[str]], Union["RepoFile", bytes]] = {} # Store (path, revision) -> oid mapping - oid_info: Dict[Tuple[str, Optional[str]], Optional[str]] = {} + oid_info: dict[tuple[str, Optional[str]], Optional[str]] = {} # 1. Fetch OIDs for destination paths in batches. dest_paths = [op.path_in_repo for op in copies] for offset in range(0, len(dest_paths), FETCH_LFS_BATCH_SIZE): @@ -812,11 +812,11 @@ def _fetch_files_to_copy( def _prepare_commit_payload( operations: Iterable[CommitOperation], - files_to_copy: Dict[Tuple[str, Optional[str]], Union["RepoFile", bytes]], + files_to_copy: dict[tuple[str, Optional[str]], Union["RepoFile", bytes]], commit_message: str, commit_description: Optional[str] = None, parent_commit: Optional[str] = None, -) -> Iterable[Dict[str, Any]]: +) -> Iterable[dict[str, Any]]: """ Builds the payload to POST to the `/commit` API of the Hub. diff --git a/src/huggingface_hub/_commit_scheduler.py b/src/huggingface_hub/_commit_scheduler.py index f28180fd68..3aee068fd8 100644 --- a/src/huggingface_hub/_commit_scheduler.py +++ b/src/huggingface_hub/_commit_scheduler.py @@ -7,7 +7,7 @@ from io import SEEK_END, SEEK_SET, BytesIO from pathlib import Path from threading import Lock, Thread -from typing import Dict, List, Optional, Union +from typing import Optional, Union from .hf_api import DEFAULT_IGNORE_PATTERNS, CommitInfo, CommitOperationAdd, HfApi from .utils import filter_repo_objects @@ -53,9 +53,9 @@ class CommitScheduler: Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. token (`str`, *optional*): The token to use to commit to the repo. Defaults to the token saved on the machine. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are uploaded. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not uploaded. squash_history (`bool`, *optional*): Whether to squash the history of the repo after each commit. Defaults to `False`. Squashing commits is @@ -108,8 +108,8 @@ def __init__( revision: Optional[str] = None, private: Optional[bool] = None, token: Optional[str] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, squash_history: bool = False, hf_api: Optional["HfApi"] = None, ) -> None: @@ -138,7 +138,7 @@ def __init__( self.token = token # Keep track of already uploaded files - self.last_uploaded: Dict[Path, float] = {} # key is local path, value is timestamp + self.last_uploaded: dict[Path, float] = {} # key is local path, value is timestamp # Scheduler if not every > 0: @@ -232,7 +232,7 @@ def push_to_hub(self) -> Optional[CommitInfo]: prefix = f"{self.path_in_repo.strip('/')}/" if self.path_in_repo else "" # Filter with pattern + filter out unchanged files + retrieve current file size - files_to_upload: List[_FileToUpload] = [] + files_to_upload: list[_FileToUpload] = [] for relpath in filter_repo_objects( relpath_to_abspath.keys(), allow_patterns=self.allow_patterns, ignore_patterns=self.ignore_patterns ): diff --git a/src/huggingface_hub/_inference_endpoints.py b/src/huggingface_hub/_inference_endpoints.py index 37f772bfbe..4422cac7c3 100644 --- a/src/huggingface_hub/_inference_endpoints.py +++ b/src/huggingface_hub/_inference_endpoints.py @@ -2,7 +2,7 @@ from dataclasses import dataclass, field from datetime import datetime from enum import Enum -from typing import TYPE_CHECKING, Dict, Optional, Union +from typing import TYPE_CHECKING, Optional, Union from huggingface_hub.errors import InferenceEndpointError, InferenceEndpointTimeoutError @@ -62,7 +62,7 @@ class InferenceEndpoint: The timestamp of the last update of the Inference Endpoint. type ([`InferenceEndpointType`]): The type of the Inference Endpoint (public, protected, private). - raw (`Dict`): + raw (`dict`): The raw dictionary data returned from the API. token (`str` or `bool`, *optional*): Authentication token for the Inference Endpoint, if set when requesting the API. Will default to the @@ -112,7 +112,7 @@ class InferenceEndpoint: type: InferenceEndpointType = field(repr=False, init=False) # Raw dict from the API - raw: Dict = field(repr=False) + raw: dict = field(repr=False) # Internal fields _token: Union[str, bool, None] = field(repr=False, compare=False) @@ -120,7 +120,7 @@ class InferenceEndpoint: @classmethod def from_raw( - cls, raw: Dict, namespace: str, token: Union[str, bool, None] = None, api: Optional["HfApi"] = None + cls, raw: dict, namespace: str, token: Union[str, bool, None] = None, api: Optional["HfApi"] = None ) -> "InferenceEndpoint": """Initialize object from raw dictionary.""" if api is None: @@ -260,8 +260,8 @@ def update( framework: Optional[str] = None, revision: Optional[str] = None, task: Optional[str] = None, - custom_image: Optional[Dict] = None, - secrets: Optional[Dict[str, str]] = None, + custom_image: Optional[dict] = None, + secrets: Optional[dict[str, str]] = None, ) -> "InferenceEndpoint": """Update the Inference Endpoint. @@ -293,10 +293,10 @@ def update( The specific model revision to deploy on the Inference Endpoint (e.g. `"6c0e6080953db56375760c0471a8c5f2929baf11"`). task (`str`, *optional*): The task on which to deploy the model (e.g. `"text-classification"`). - custom_image (`Dict`, *optional*): + custom_image (`dict`, *optional*): A custom Docker image to use for the Inference Endpoint. This is useful if you want to deploy an Inference Endpoint running on the `text-generation-inference` (TGI) framework (see examples). - secrets (`Dict[str, str]`, *optional*): + secrets (`dict[str, str]`, *optional*): Secret values to inject in the container environment. Returns: [`InferenceEndpoint`]: the same Inference Endpoint, mutated in place with the latest data. diff --git a/src/huggingface_hub/_jobs_api.py b/src/huggingface_hub/_jobs_api.py index 623fd9dc9d..c85324ce1c 100644 --- a/src/huggingface_hub/_jobs_api.py +++ b/src/huggingface_hub/_jobs_api.py @@ -15,7 +15,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union from huggingface_hub import constants from huggingface_hub._space_api import SpaceHardware @@ -71,13 +71,13 @@ class JobInfo: space_id (`str` or `None`): The Docker image from Hugging Face Spaces used for the Job. Can be None if docker_image is present instead. - command (`List[str]` or `None`): + command (`list[str]` or `None`): Command of the Job, e.g. `["python", "-c", "print('hello world')"]` - arguments (`List[str]` or `None`): + arguments (`list[str]` or `None`): Arguments passed to the command - environment (`Dict[str]` or `None`): + environment (`dict[str]` or `None`): Environment variables of the Job as a dictionary. - secrets (`Dict[str]` or `None`): + secrets (`dict[str]` or `None`): Secret environment variables of the Job (encrypted). flavor (`str` or `None`): Flavor for the hardware, as in Hugging Face Spaces. See [`SpaceHardware`] for possible values. @@ -111,10 +111,10 @@ class JobInfo: created_at: Optional[datetime] docker_image: Optional[str] space_id: Optional[str] - command: Optional[List[str]] - arguments: Optional[List[str]] - environment: Optional[Dict[str, Any]] - secrets: Optional[Dict[str, Any]] + command: Optional[list[str]] + arguments: Optional[list[str]] + environment: Optional[dict[str, Any]] + secrets: Optional[dict[str, Any]] flavor: Optional[SpaceHardware] status: JobStatus owner: JobOwner @@ -148,13 +148,13 @@ def __init__(self, **kwargs) -> None: class JobSpec: docker_image: Optional[str] space_id: Optional[str] - command: Optional[List[str]] - arguments: Optional[List[str]] - environment: Optional[Dict[str, Any]] - secrets: Optional[Dict[str, Any]] + command: Optional[list[str]] + arguments: Optional[list[str]] + environment: Optional[dict[str, Any]] + secrets: Optional[dict[str, Any]] flavor: Optional[SpaceHardware] timeout: Optional[int] - tags: Optional[List[str]] + tags: Optional[list[str]] arch: Optional[str] def __init__(self, **kwargs) -> None: @@ -202,7 +202,7 @@ class ScheduledJobInfo: Scheduled Job ID. created_at (`datetime` or `None`): When the scheduled Job was created. - tags (`List[str]` or `None`): + tags (`list[str]` or `None`): The tags of the scheduled Job. schedule (`str` or `None`): One of "@annually", "@yearly", "@monthly", "@weekly", "@daily", "@hourly", or a @@ -263,14 +263,14 @@ def __init__(self, **kwargs) -> None: def _create_job_spec( *, image: str, - command: List[str], - env: Optional[Dict[str, Any]], - secrets: Optional[Dict[str, Any]], + command: list[str], + env: Optional[dict[str, Any]], + secrets: Optional[dict[str, Any]], flavor: Optional[SpaceHardware], timeout: Optional[Union[int, float, str]], -) -> Dict[str, Any]: +) -> dict[str, Any]: # prepare job spec to send to HF Jobs API - job_spec: Dict[str, Any] = { + job_spec: dict[str, Any] = { "command": command, "arguments": [], "environment": env or {}, diff --git a/src/huggingface_hub/_oauth.py b/src/huggingface_hub/_oauth.py index 9f8eb60796..7bdfa6a058 100644 --- a/src/huggingface_hub/_oauth.py +++ b/src/huggingface_hub/_oauth.py @@ -6,7 +6,7 @@ import urllib.parse import warnings from dataclasses import dataclass -from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Tuple, Union +from typing import TYPE_CHECKING, Literal, Optional, Union from . import constants from .hf_api import whoami @@ -39,7 +39,7 @@ class OAuthOrgInfo: Whether the org has a payment method set up. Hugging Face field. role_in_org (`Optional[str]`, *optional*): The user's role in the org. Hugging Face field. - security_restrictions (`Optional[List[Literal["ip", "token-policy", "mfa", "sso"]]]`, *optional*): + security_restrictions (`Optional[list[Literal["ip", "token-policy", "mfa", "sso"]]]`, *optional*): Array of security restrictions that the user hasn't completed for this org. Possible values: "ip", "token-policy", "mfa", "sso". Hugging Face field. """ @@ -50,7 +50,7 @@ class OAuthOrgInfo: is_enterprise: bool can_pay: Optional[bool] = None role_in_org: Optional[str] = None - security_restrictions: Optional[List[Literal["ip", "token-policy", "mfa", "sso"]]] = None + security_restrictions: Optional[list[Literal["ip", "token-policy", "mfa", "sso"]]] = None @dataclass @@ -79,7 +79,7 @@ class OAuthUserInfo: Whether the user is a pro user. Hugging Face field. can_pay (`Optional[bool]`, *optional*): Whether the user has a payment method set up. Hugging Face field. - orgs (`Optional[List[OrgInfo]]`, *optional*): + orgs (`Optional[list[OrgInfo]]`, *optional*): List of organizations the user is part of. Hugging Face field. """ @@ -93,7 +93,7 @@ class OAuthUserInfo: website: Optional[str] is_pro: bool can_pay: Optional[bool] - orgs: Optional[List[OAuthOrgInfo]] + orgs: Optional[list[OAuthOrgInfo]] @dataclass @@ -306,7 +306,7 @@ async def oauth_redirect_callback(request: fastapi.Request) -> RedirectResponse: target_url = request.query_params.get("_target_url") # Build redirect URI with the same query params as before and bump nb_redirects count - query_params: Dict[str, Union[int, str]] = {"_nb_redirects": nb_redirects + 1} + query_params: dict[str, Union[int, str]] = {"_nb_redirects": nb_redirects + 1} if target_url: query_params["_target_url"] = target_url @@ -406,7 +406,7 @@ def _get_redirect_target(request: "fastapi.Request", default_target: str = "/") return request.query_params.get("_target_url", default_target) -def _get_mocked_oauth_info() -> Dict: +def _get_mocked_oauth_info() -> dict: token = get_token() if token is None: raise ValueError( @@ -449,7 +449,7 @@ def _get_mocked_oauth_info() -> Dict: } -def _get_oauth_uris(route_prefix: str = "/") -> Tuple[str, str, str]: +def _get_oauth_uris(route_prefix: str = "/") -> tuple[str, str, str]: route_prefix = route_prefix.strip("/") if route_prefix: route_prefix = f"/{route_prefix}" diff --git a/src/huggingface_hub/_snapshot_download.py b/src/huggingface_hub/_snapshot_download.py index aa65d561da..200ed7cc2e 100644 --- a/src/huggingface_hub/_snapshot_download.py +++ b/src/huggingface_hub/_snapshot_download.py @@ -1,6 +1,6 @@ import os from pathlib import Path -from typing import Dict, Iterable, List, Literal, Optional, Type, Union +from typing import Iterable, Literal, Optional, Union import httpx from tqdm.auto import tqdm as base_tqdm @@ -35,16 +35,16 @@ def snapshot_download( local_dir: Union[str, Path, None] = None, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Optional[Union[Dict, str]] = None, + user_agent: Optional[Union[dict, str]] = None, etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, force_download: bool = False, token: Optional[Union[bool, str]] = None, local_files_only: bool = False, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, max_workers: int = 8, - tqdm_class: Optional[Type[base_tqdm]] = None, - headers: Optional[Dict[str, str]] = None, + tqdm_class: Optional[type[base_tqdm]] = None, + headers: Optional[dict[str, str]] = None, endpoint: Optional[str] = None, # Deprecated args local_dir_use_symlinks: Union[bool, Literal["auto"]] = "auto", @@ -99,9 +99,9 @@ def snapshot_download( local_files_only (`bool`, *optional*, defaults to `False`): If `True`, avoid downloading the file and return the path to the local cached file if it exists. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are downloaded. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not downloaded. max_workers (`int`, *optional*): Number of concurrent threads to download files (1 thread = 1 file download). diff --git a/src/huggingface_hub/_space_api.py b/src/huggingface_hub/_space_api.py index 05fccfbc1e..6dd7976329 100644 --- a/src/huggingface_hub/_space_api.py +++ b/src/huggingface_hub/_space_api.py @@ -15,7 +15,7 @@ from dataclasses import dataclass from datetime import datetime from enum import Enum -from typing import Dict, Optional +from typing import Optional from huggingface_hub.utils import parse_datetime @@ -128,9 +128,9 @@ class SpaceRuntime: requested_hardware: Optional[SpaceHardware] sleep_time: Optional[int] storage: Optional[SpaceStorage] - raw: Dict + raw: dict - def __init__(self, data: Dict) -> None: + def __init__(self, data: dict) -> None: self.stage = data["stage"] self.hardware = data.get("hardware", {}).get("current") self.requested_hardware = data.get("hardware", {}).get("requested") @@ -160,7 +160,7 @@ class SpaceVariable: description: Optional[str] updated_at: Optional[datetime] - def __init__(self, key: str, values: Dict) -> None: + def __init__(self, key: str, values: dict) -> None: self.key = key self.value = values["value"] self.description = values.get("description") diff --git a/src/huggingface_hub/_tensorboard_logger.py b/src/huggingface_hub/_tensorboard_logger.py index fb172acceb..5b15468cfd 100644 --- a/src/huggingface_hub/_tensorboard_logger.py +++ b/src/huggingface_hub/_tensorboard_logger.py @@ -14,7 +14,7 @@ """Contains a logger to push training logs to the Hub, using Tensorboard.""" from pathlib import Path -from typing import List, Optional, Union +from typing import Optional, Union from ._commit_scheduler import CommitScheduler from .errors import EntryNotFoundError @@ -77,10 +77,10 @@ class HFSummaryWriter(_RuntimeSummaryWriter): Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. path_in_repo (`str`, *optional*): The path to the folder in the repo where the logs will be pushed. Defaults to "tensorboard/". - repo_allow_patterns (`List[str]` or `str`, *optional*): + repo_allow_patterns (`list[str]` or `str`, *optional*): A list of patterns to include in the upload. Defaults to `"*.tfevents.*"`. Check out the [upload guide](https://huggingface.co/docs/huggingface_hub/guides/upload#upload-a-folder) for more details. - repo_ignore_patterns (`List[str]` or `str`, *optional*): + repo_ignore_patterns (`list[str]` or `str`, *optional*): A list of patterns to exclude in the upload. Check out the [upload guide](https://huggingface.co/docs/huggingface_hub/guides/upload#upload-a-folder) for more details. token (`str`, *optional*): @@ -137,8 +137,8 @@ def __init__( repo_revision: Optional[str] = None, repo_private: Optional[bool] = None, path_in_repo: Optional[str] = "tensorboard", - repo_allow_patterns: Optional[Union[List[str], str]] = "*.tfevents.*", - repo_ignore_patterns: Optional[Union[List[str], str]] = None, + repo_allow_patterns: Optional[Union[list[str], str]] = "*.tfevents.*", + repo_ignore_patterns: Optional[Union[list[str], str]] = None, token: Optional[str] = None, **kwargs, ): diff --git a/src/huggingface_hub/_upload_large_folder.py b/src/huggingface_hub/_upload_large_folder.py index 1ccbc07d39..a4eaeaf250 100644 --- a/src/huggingface_hub/_upload_large_folder.py +++ b/src/huggingface_hub/_upload_large_folder.py @@ -24,7 +24,7 @@ from datetime import datetime from pathlib import Path from threading import Lock -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Optional, Union from urllib.parse import quote from . import constants @@ -44,7 +44,7 @@ WAITING_TIME_IF_NO_TASKS = 10 # seconds MAX_NB_FILES_FETCH_UPLOAD_MODE = 100 -COMMIT_SIZE_SCALE: List[int] = [20, 50, 75, 100, 125, 200, 250, 400, 600, 1000] +COMMIT_SIZE_SCALE: list[int] = [20, 50, 75, 100, 125, 200, 250, 400, 600, 1000] UPLOAD_BATCH_SIZE_XET = 256 # Max 256 files per upload batch for XET-enabled repos UPLOAD_BATCH_SIZE_LFS = 1 # Otherwise, batches of 1 for regular LFS upload @@ -56,7 +56,7 @@ RECOMMENDED_FILE_SIZE_GB = 20 # Recommended maximum for individual file size -def _validate_upload_limits(paths_list: List[LocalUploadFilePaths]) -> None: +def _validate_upload_limits(paths_list: list[LocalUploadFilePaths]) -> None: """ Validate upload against repository limits and warn about potential issues. @@ -85,7 +85,7 @@ def _validate_upload_limits(paths_list: List[LocalUploadFilePaths]) -> None: # Track immediate children (files and subdirs) for each folder from collections import defaultdict - entries_per_folder: Dict[str, Any] = defaultdict(lambda: {"files": 0, "subdirs": set()}) + entries_per_folder: dict[str, Any] = defaultdict(lambda: {"files": 0, "subdirs": set()}) for paths in paths_list: path = Path(paths.path_in_repo) @@ -160,8 +160,8 @@ def upload_large_folder_internal( repo_type: str, # Repo type is required! revision: Optional[str] = None, private: Optional[bool] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, num_workers: Optional[int] = None, print_report: bool = True, print_report_every: int = 60, @@ -284,13 +284,13 @@ class WorkerJob(enum.Enum): WAIT = enum.auto() # if no tasks are available but we don't want to exit -JOB_ITEM_T = Tuple[LocalUploadFilePaths, LocalUploadFileMetadata] +JOB_ITEM_T = tuple[LocalUploadFilePaths, LocalUploadFileMetadata] class LargeUploadStatus: """Contains information, queues and tasks for a large upload process.""" - def __init__(self, items: List[JOB_ITEM_T], upload_batch_size: int = 1): + def __init__(self, items: list[JOB_ITEM_T], upload_batch_size: int = 1): self.items = items self.queue_sha256: "queue.Queue[JOB_ITEM_T]" = queue.Queue() self.queue_get_upload_mode: "queue.Queue[JOB_ITEM_T]" = queue.Queue() @@ -423,7 +423,7 @@ def _worker_job( Read `upload_large_folder` docstring for more information on how tasks are prioritized. """ while True: - next_job: Optional[Tuple[WorkerJob, List[JOB_ITEM_T]]] = None + next_job: Optional[tuple[WorkerJob, list[JOB_ITEM_T]]] = None # Determine next task next_job = _determine_next_job(status) @@ -516,7 +516,7 @@ def _worker_job( status.nb_workers_waiting -= 1 -def _determine_next_job(status: LargeUploadStatus) -> Optional[Tuple[WorkerJob, List[JOB_ITEM_T]]]: +def _determine_next_job(status: LargeUploadStatus) -> Optional[tuple[WorkerJob, list[JOB_ITEM_T]]]: with status.lock: # 1. Commit if more than 5 minutes since last commit attempt (and at least 1 file) if ( @@ -639,7 +639,7 @@ def _compute_sha256(item: JOB_ITEM_T) -> None: metadata.save(paths) -def _get_upload_mode(items: List[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: +def _get_upload_mode(items: list[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: """Get upload mode for each file and update metadata. Also receive info if the file should be ignored. @@ -661,7 +661,7 @@ def _get_upload_mode(items: List[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_t metadata.save(paths) -def _preupload_lfs(items: List[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: +def _preupload_lfs(items: list[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: """Preupload LFS files and update metadata.""" additions = [_build_hacky_operation(item) for item in items] api.preupload_lfs_files( @@ -676,7 +676,7 @@ def _preupload_lfs(items: List[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_typ metadata.save(paths) -def _commit(items: List[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: +def _commit(items: list[JOB_ITEM_T], api: "HfApi", repo_id: str, repo_type: str, revision: str) -> None: """Commit files to the repo.""" additions = [_build_hacky_operation(item) for item in items] api.create_commit( @@ -721,11 +721,11 @@ def _build_hacky_operation(item: JOB_ITEM_T) -> HackyCommitOperationAdd: #################### -def _get_one(queue: "queue.Queue[JOB_ITEM_T]") -> List[JOB_ITEM_T]: +def _get_one(queue: "queue.Queue[JOB_ITEM_T]") -> list[JOB_ITEM_T]: return [queue.get()] -def _get_n(queue: "queue.Queue[JOB_ITEM_T]", n: int) -> List[JOB_ITEM_T]: +def _get_n(queue: "queue.Queue[JOB_ITEM_T]", n: int) -> list[JOB_ITEM_T]: return [queue.get() for _ in range(min(queue.qsize(), n))] diff --git a/src/huggingface_hub/_webhooks_payload.py b/src/huggingface_hub/_webhooks_payload.py index 288f4b08b9..90f12425cb 100644 --- a/src/huggingface_hub/_webhooks_payload.py +++ b/src/huggingface_hub/_webhooks_payload.py @@ -14,7 +14,7 @@ # limitations under the License. """Contains data structures to parse the webhooks payload.""" -from typing import List, Literal, Optional +from typing import Literal, Optional from .utils import is_pydantic_available @@ -116,7 +116,7 @@ class WebhookPayloadRepo(ObjectId): name: str private: bool subdomain: Optional[str] = None - tags: Optional[List[str]] = None + tags: Optional[list[str]] = None type: Literal["dataset", "model", "space"] url: WebhookPayloadUrl @@ -134,4 +134,4 @@ class WebhookPayload(BaseModel): comment: Optional[WebhookPayloadComment] = None webhook: WebhookPayloadWebhook movedTo: Optional[WebhookPayloadMovedTo] = None - updatedRefs: Optional[List[WebhookPayloadUpdatedRef]] = None + updatedRefs: Optional[list[WebhookPayloadUpdatedRef]] = None diff --git a/src/huggingface_hub/_webhooks_server.py b/src/huggingface_hub/_webhooks_server.py index a7bd6c8626..f8ca539af0 100644 --- a/src/huggingface_hub/_webhooks_server.py +++ b/src/huggingface_hub/_webhooks_server.py @@ -18,7 +18,7 @@ import inspect import os from functools import wraps -from typing import TYPE_CHECKING, Any, Callable, Dict, Optional +from typing import TYPE_CHECKING, Any, Callable, Optional from .utils import experimental, is_fastapi_available, is_gradio_available @@ -115,7 +115,7 @@ def __init__( self._ui = ui self.webhook_secret = webhook_secret or os.getenv("WEBHOOK_SECRET") - self.registered_webhooks: Dict[str, Callable] = {} + self.registered_webhooks: dict[str, Callable] = {} _warn_on_empty_secret(self.webhook_secret) def add_webhook(self, path: Optional[str] = None) -> Callable: diff --git a/src/huggingface_hub/cli/_cli_utils.py b/src/huggingface_hub/cli/_cli_utils.py index bd56ad6896..d0f0b98d8a 100644 --- a/src/huggingface_hub/cli/_cli_utils.py +++ b/src/huggingface_hub/cli/_cli_utils.py @@ -14,7 +14,7 @@ """Contains a utility for good-looking prints.""" import os -from typing import List, Union +from typing import Union class ANSI: @@ -52,7 +52,7 @@ def _format(cls, s: str, code: str) -> str: return f"{code}{s}{cls._reset}" -def tabulate(rows: List[List[Union[str, int]]], headers: List[str]) -> str: +def tabulate(rows: list[list[Union[str, int]]], headers: list[str]) -> str: """ Inspired by: diff --git a/src/huggingface_hub/cli/auth.py b/src/huggingface_hub/cli/auth.py index 91e6b3c18d..8740a86423 100644 --- a/src/huggingface_hub/cli/auth.py +++ b/src/huggingface_hub/cli/auth.py @@ -31,7 +31,7 @@ """ from argparse import _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub.commands import BaseHuggingfaceCLICommand from huggingface_hub.constants import ENDPOINT @@ -172,7 +172,7 @@ def _select_token_name(self) -> Optional[str]: except ValueError: print("Invalid input. Please enter a number or 'q' to quit.") - def _select_token_name_tui(self, token_names: List[str]) -> Optional[str]: + def _select_token_name_tui(self, token_names: list[str]) -> Optional[str]: choices = [Choice(token_name, name=token_name) for token_name in token_names] try: return inquirer.select( diff --git a/src/huggingface_hub/cli/cache.py b/src/huggingface_hub/cli/cache.py index cc36ef5efd..7eb3e82509 100644 --- a/src/huggingface_hub/cli/cache.py +++ b/src/huggingface_hub/cli/cache.py @@ -19,7 +19,7 @@ from argparse import Namespace, _SubParsersAction from functools import wraps from tempfile import mkstemp -from typing import Any, Callable, Iterable, List, Literal, Optional, Union +from typing import Any, Callable, Iterable, Literal, Optional, Union from ..utils import CachedRepoInfo, CachedRevisionInfo, CacheNotFound, HFCacheInfo, scan_cache_dir from . import BaseHuggingfaceCLICommand @@ -243,8 +243,8 @@ def _get_repo_sorting_key(repo: CachedRepoInfo, sort_by: Optional[SortingOption_ @require_inquirer_py def _manual_review_tui( - hf_cache_info: HFCacheInfo, preselected: List[str], sort_by: Optional[SortingOption_T] = None -) -> List[str]: + hf_cache_info: HFCacheInfo, preselected: list[str], sort_by: Optional[SortingOption_T] = None +) -> list[str]: choices = _get_tui_choices_from_scan(repos=hf_cache_info.repos, preselected=preselected, sort_by=sort_by) checkbox = inquirer.checkbox( message="Select revisions to delete:", @@ -277,9 +277,9 @@ def _ask_for_confirmation_tui(message: str, default: bool = True) -> bool: def _get_tui_choices_from_scan( - repos: Iterable[CachedRepoInfo], preselected: List[str], sort_by: Optional[SortingOption_T] = None -) -> List: - choices: List[Union["Choice", "Separator"]] = [] + repos: Iterable[CachedRepoInfo], preselected: list[str], sort_by: Optional[SortingOption_T] = None +) -> list: + choices: list[Union["Choice", "Separator"]] = [] choices.append( Choice( _CANCEL_DELETION_STR, name="None of the following (if selected, nothing will be deleted).", enabled=False @@ -306,8 +306,8 @@ def _get_tui_choices_from_scan( def _manual_review_no_tui( - hf_cache_info: HFCacheInfo, preselected: List[str], sort_by: Optional[SortingOption_T] = None -) -> List[str]: + hf_cache_info: HFCacheInfo, preselected: list[str], sort_by: Optional[SortingOption_T] = None +) -> list[str]: fd, tmp_path = mkstemp(suffix=".txt") os.close(fd) lines = [] @@ -358,14 +358,14 @@ def _ask_for_confirmation_no_tui(message: str, default: bool = True) -> bool: print(f"Invalid input. Must be one of {ALL}") -def _get_expectations_str(hf_cache_info: HFCacheInfo, selected_hashes: List[str]) -> str: +def _get_expectations_str(hf_cache_info: HFCacheInfo, selected_hashes: list[str]) -> str: if _CANCEL_DELETION_STR in selected_hashes: return "Nothing will be deleted." strategy = hf_cache_info.delete_revisions(*selected_hashes) return f"{len(selected_hashes)} revisions selected counting for {strategy.expected_freed_size_str}." -def _read_manual_review_tmp_file(tmp_path: str) -> List[str]: +def _read_manual_review_tmp_file(tmp_path: str) -> list[str]: with open(tmp_path) as f: content = f.read() lines = [line.strip() for line in content.split("\n")] diff --git a/src/huggingface_hub/cli/download.py b/src/huggingface_hub/cli/download.py index 3e59233da1..ea6714d124 100644 --- a/src/huggingface_hub/cli/download.py +++ b/src/huggingface_hub/cli/download.py @@ -38,7 +38,7 @@ import warnings from argparse import Namespace, _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub._snapshot_download import snapshot_download @@ -113,11 +113,11 @@ def register_subcommand(parser: _SubParsersAction): def __init__(self, args: Namespace) -> None: self.token = args.token self.repo_id: str = args.repo_id - self.filenames: List[str] = args.filenames + self.filenames: list[str] = args.filenames self.repo_type: str = args.repo_type self.revision: Optional[str] = args.revision - self.include: Optional[List[str]] = args.include - self.exclude: Optional[List[str]] = args.exclude + self.include: Optional[list[str]] = args.include + self.exclude: Optional[list[str]] = args.exclude self.cache_dir: Optional[str] = args.cache_dir self.local_dir: Optional[str] = args.local_dir self.force_download: bool = args.force_download diff --git a/src/huggingface_hub/cli/jobs.py b/src/huggingface_hub/cli/jobs.py index 5b8d355c6f..b4f8385e1d 100644 --- a/src/huggingface_hub/cli/jobs.py +++ b/src/huggingface_hub/cli/jobs.py @@ -36,7 +36,7 @@ from argparse import Namespace, _SubParsersAction from dataclasses import asdict from pathlib import Path -from typing import Dict, List, Optional, Union +from typing import Optional, Union from huggingface_hub import HfApi, SpaceHardware, get_token from huggingface_hub.errors import HfHubHTTPError @@ -118,7 +118,7 @@ def register_subcommand(parser: _SubParsersAction) -> None: def __init__(self, args: Namespace) -> None: self.image: str = args.image - self.command: List[str] = args.command + self.command: list[str] = args.command self.env: dict[str, Optional[str]] = {} if args.env_file: self.env.update(load_dotenv(Path(args.env_file).read_text(), environ=os.environ.copy())) @@ -185,7 +185,7 @@ def run(self) -> None: print(log) -def _tabulate(rows: List[List[Union[str, int]]], headers: List[str]) -> str: +def _tabulate(rows: list[list[Union[str, int]]], headers: list[str]) -> str: """ Inspired by: @@ -253,7 +253,7 @@ def __init__(self, args: Namespace) -> None: self.namespace: Optional[str] = args.namespace self.token: Optional[str] = args.token self.format: Optional[str] = args.format - self.filters: Dict[str, str] = {} + self.filters: dict[str, str] = {} # Parse filter arguments (key=value pairs) for f in args.filter: @@ -335,7 +335,7 @@ def run(self) -> None: except Exception as e: print(f"Unexpected error - {type(e).__name__}: {e}") - def _matches_filters(self, job_properties: Dict[str, str]) -> bool: + def _matches_filters(self, job_properties: dict[str, str]) -> bool: """Check if job matches all specified filters.""" for key, pattern in self.filters.items(): # Check if property exists @@ -394,7 +394,7 @@ def register_subcommand(parser: _SubParsersAction) -> None: def __init__(self, args: Namespace) -> None: self.namespace: Optional[str] = args.namespace self.token: Optional[str] = args.token - self.job_ids: List[str] = args.job_ids + self.job_ids: list[str] = args.job_ids def run(self) -> None: api = HfApi(token=self.token) @@ -543,7 +543,7 @@ def run(self) -> None: print(log) -def _get_extended_environ() -> Dict[str, str]: +def _get_extended_environ() -> dict[str, str]: extended_environ = os.environ.copy() if (token := get_token()) is not None: extended_environ["HF_TOKEN"] = token @@ -631,7 +631,7 @@ def register_subcommand(parser: _SubParsersAction) -> None: def __init__(self, args: Namespace) -> None: self.schedule: str = args.schedule self.image: str = args.image - self.command: List[str] = args.command + self.command: list[str] = args.command self.suspend: Optional[bool] = args.suspend self.concurrency: Optional[bool] = args.concurrency self.env: dict[str, Optional[str]] = {} @@ -709,7 +709,7 @@ def __init__(self, args: Namespace) -> None: self.namespace: Optional[str] = args.namespace self.token: Optional[str] = args.token self.format: Optional[str] = args.format - self.filters: Dict[str, str] = {} + self.filters: dict[str, str] = {} # Parse filter arguments (key=value pairs) for f in args.filter: @@ -821,7 +821,7 @@ def run(self) -> None: except Exception as e: print(f"Unexpected error - {type(e).__name__}: {e}") - def _matches_filters(self, job_properties: Dict[str, str]) -> bool: + def _matches_filters(self, job_properties: dict[str, str]) -> bool: """Check if scheduled job matches all specified filters.""" for key, pattern in self.filters.items(): # Check if property exists @@ -882,7 +882,7 @@ def register_subcommand(parser: _SubParsersAction) -> None: def __init__(self, args: Namespace) -> None: self.namespace: Optional[str] = args.namespace self.token: Optional[str] = args.token - self.scheduled_job_ids: List[str] = args.scheduled_job_ids + self.scheduled_job_ids: list[str] = args.scheduled_job_ids def run(self) -> None: api = HfApi(token=self.token) diff --git a/src/huggingface_hub/cli/lfs.py b/src/huggingface_hub/cli/lfs.py index e4c5b900c8..ec1b19107e 100644 --- a/src/huggingface_hub/cli/lfs.py +++ b/src/huggingface_hub/cli/lfs.py @@ -21,7 +21,7 @@ import subprocess import sys from argparse import _SubParsersAction -from typing import Dict, List, Optional +from typing import Optional from huggingface_hub.commands import BaseHuggingfaceCLICommand from huggingface_hub.lfs import LFS_MULTIPART_UPLOAD_COMMAND @@ -87,14 +87,14 @@ def run(self): print("Local repo set up for largefiles") -def write_msg(msg: Dict): +def write_msg(msg: dict): """Write out the message in Line delimited JSON.""" msg_str = json.dumps(msg) + "\n" sys.stdout.write(msg_str) sys.stdout.flush() -def read_msg() -> Optional[Dict]: +def read_msg() -> Optional[dict]: """Read Line delimited JSON from stdin.""" msg = json.loads(sys.stdin.readline().strip()) @@ -144,7 +144,7 @@ def run(self) -> None: completion_url = msg["action"]["href"] header = msg["action"]["header"] chunk_size = int(header.pop("chunk_size")) - presigned_urls: List[str] = list(header.values()) + presigned_urls: list[str] = list(header.values()) # Send a "started" progress event to allow other workers to start. # Otherwise they're delayed until first "progress" event is reported, diff --git a/src/huggingface_hub/cli/repo_files.py b/src/huggingface_hub/cli/repo_files.py index 34fbeb09c2..ba3259e576 100644 --- a/src/huggingface_hub/cli/repo_files.py +++ b/src/huggingface_hub/cli/repo_files.py @@ -35,7 +35,7 @@ """ from argparse import _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub.commands import BaseHuggingfaceCLICommand @@ -52,7 +52,7 @@ def __init__(self, args) -> None: self.repo_type: Optional[str] = args.repo_type self.revision: Optional[str] = args.revision self.api: HfApi = HfApi(token=args.token, library_name="hf") - self.patterns: List[str] = args.patterns + self.patterns: list[str] = args.patterns self.commit_message: Optional[str] = args.commit_message self.commit_description: Optional[str] = args.commit_description self.create_pr: bool = args.create_pr diff --git a/src/huggingface_hub/cli/upload.py b/src/huggingface_hub/cli/upload.py index 07ab79bf24..80a0623743 100644 --- a/src/huggingface_hub/cli/upload.py +++ b/src/huggingface_hub/cli/upload.py @@ -50,7 +50,7 @@ import time import warnings from argparse import Namespace, _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub._commit_scheduler import CommitScheduler @@ -144,9 +144,9 @@ def __init__(self, args: Namespace) -> None: self.revision: Optional[str] = args.revision self.private: bool = args.private - self.include: Optional[List[str]] = args.include - self.exclude: Optional[List[str]] = args.exclude - self.delete: Optional[List[str]] = args.delete + self.include: Optional[list[str]] = args.include + self.exclude: Optional[list[str]] = args.exclude + self.delete: Optional[list[str]] = args.delete self.commit_message: Optional[str] = args.commit_message self.commit_description: Optional[str] = args.commit_description diff --git a/src/huggingface_hub/cli/upload_large_folder.py b/src/huggingface_hub/cli/upload_large_folder.py index 618cd21b52..f923abc0a7 100644 --- a/src/huggingface_hub/cli/upload_large_folder.py +++ b/src/huggingface_hub/cli/upload_large_folder.py @@ -16,7 +16,7 @@ import os from argparse import Namespace, _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub.commands import BaseHuggingfaceCLICommand @@ -76,8 +76,8 @@ def __init__(self, args: Namespace) -> None: self.revision: Optional[str] = args.revision self.private: bool = args.private - self.include: Optional[List[str]] = args.include - self.exclude: Optional[List[str]] = args.exclude + self.include: Optional[list[str]] = args.include + self.exclude: Optional[list[str]] = args.exclude self.api: HfApi = HfApi(token=args.token, library_name="hf") diff --git a/src/huggingface_hub/commands/_cli_utils.py b/src/huggingface_hub/commands/_cli_utils.py index bf4a1c0373..3f4819c26c 100644 --- a/src/huggingface_hub/commands/_cli_utils.py +++ b/src/huggingface_hub/commands/_cli_utils.py @@ -14,7 +14,7 @@ """Contains a utility for good-looking prints.""" import os -from typing import List, Union +from typing import Union class ANSI: @@ -52,7 +52,7 @@ def _format(cls, s: str, code: str) -> str: return f"{code}{s}{cls._reset}" -def tabulate(rows: List[List[Union[str, int]]], headers: List[str]) -> str: +def tabulate(rows: list[list[Union[str, int]]], headers: list[str]) -> str: """ Inspired by: diff --git a/src/huggingface_hub/commands/delete_cache.py b/src/huggingface_hub/commands/delete_cache.py index 78ea117967..2983ab80b0 100644 --- a/src/huggingface_hub/commands/delete_cache.py +++ b/src/huggingface_hub/commands/delete_cache.py @@ -60,7 +60,7 @@ from argparse import Namespace, _SubParsersAction from functools import wraps from tempfile import mkstemp -from typing import Any, Callable, Iterable, List, Literal, Optional, Union +from typing import Any, Callable, Iterable, Literal, Optional, Union from ..utils import CachedRepoInfo, CachedRevisionInfo, HFCacheInfo, scan_cache_dir from . import BaseHuggingfaceCLICommand @@ -197,9 +197,9 @@ def _get_repo_sorting_key(repo: CachedRepoInfo, sort_by: Optional[SortingOption_ @require_inquirer_py def _manual_review_tui( hf_cache_info: HFCacheInfo, - preselected: List[str], + preselected: list[str], sort_by: Optional[SortingOption_T] = None, -) -> List[str]: +) -> list[str]: """Ask the user for a manual review of the revisions to delete. Displays a multi-select menu in the terminal (TUI). @@ -254,15 +254,15 @@ def _ask_for_confirmation_tui(message: str, default: bool = True) -> bool: def _get_tui_choices_from_scan( repos: Iterable[CachedRepoInfo], - preselected: List[str], + preselected: list[str], sort_by: Optional[SortingOption_T] = None, -) -> List: +) -> list: """Build a list of choices from the scanned repos. Args: repos (*Iterable[`CachedRepoInfo`]*): List of scanned repos on which we want to delete revisions. - preselected (*List[`str`]*): + preselected (*list[`str`]*): List of revision hashes that will be preselected. sort_by (*Optional[SortingOption_T]*): Sorting direction. Choices: "alphabetical", "lastUpdated", "lastUsed", "size". @@ -270,7 +270,7 @@ def _get_tui_choices_from_scan( Return: The list of choices to pass to `inquirer.checkbox`. """ - choices: List[Union[Choice, Separator]] = [] + choices: list[Union[Choice, Separator]] = [] # First choice is to cancel the deletion choices.append( @@ -312,9 +312,9 @@ def _get_tui_choices_from_scan( def _manual_review_no_tui( hf_cache_info: HFCacheInfo, - preselected: List[str], + preselected: list[str], sort_by: Optional[SortingOption_T] = None, -) -> List[str]: +) -> list[str]: """Ask the user for a manual review of the revisions to delete. Used when TUI is disabled. Manual review happens in a separate tmp file that the @@ -390,7 +390,7 @@ def _ask_for_confirmation_no_tui(message: str, default: bool = True) -> bool: print(f"Invalid input. Must be one of {ALL}") -def _get_expectations_str(hf_cache_info: HFCacheInfo, selected_hashes: List[str]) -> str: +def _get_expectations_str(hf_cache_info: HFCacheInfo, selected_hashes: list[str]) -> str: """Format a string to display to the user how much space would be saved. Example: @@ -405,7 +405,7 @@ def _get_expectations_str(hf_cache_info: HFCacheInfo, selected_hashes: List[str] return f"{len(selected_hashes)} revisions selected counting for {strategy.expected_freed_size_str}." -def _read_manual_review_tmp_file(tmp_path: str) -> List[str]: +def _read_manual_review_tmp_file(tmp_path: str) -> list[str]: """Read the manually reviewed instruction file and return a list of revision hash. Example: diff --git a/src/huggingface_hub/commands/download.py b/src/huggingface_hub/commands/download.py index 0dd2c1070e..103f2a52b5 100644 --- a/src/huggingface_hub/commands/download.py +++ b/src/huggingface_hub/commands/download.py @@ -38,7 +38,7 @@ import warnings from argparse import Namespace, _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub._snapshot_download import snapshot_download @@ -125,11 +125,11 @@ def register_subcommand(parser: _SubParsersAction): def __init__(self, args: Namespace) -> None: self.token = args.token self.repo_id: str = args.repo_id - self.filenames: List[str] = args.filenames + self.filenames: list[str] = args.filenames self.repo_type: str = args.repo_type self.revision: Optional[str] = args.revision - self.include: Optional[List[str]] = args.include - self.exclude: Optional[List[str]] = args.exclude + self.include: Optional[list[str]] = args.include + self.exclude: Optional[list[str]] = args.exclude self.cache_dir: Optional[str] = args.cache_dir self.local_dir: Optional[str] = args.local_dir self.force_download: bool = args.force_download diff --git a/src/huggingface_hub/commands/lfs.py b/src/huggingface_hub/commands/lfs.py index e510e345e6..2133bf1f00 100644 --- a/src/huggingface_hub/commands/lfs.py +++ b/src/huggingface_hub/commands/lfs.py @@ -21,7 +21,7 @@ import subprocess import sys from argparse import _SubParsersAction -from typing import Dict, List, Optional +from typing import Optional from huggingface_hub.commands import BaseHuggingfaceCLICommand from huggingface_hub.lfs import LFS_MULTIPART_UPLOAD_COMMAND @@ -89,14 +89,14 @@ def run(self): print("Local repo set up for largefiles") -def write_msg(msg: Dict): +def write_msg(msg: dict): """Write out the message in Line delimited JSON.""" msg_str = json.dumps(msg) + "\n" sys.stdout.write(msg_str) sys.stdout.flush() -def read_msg() -> Optional[Dict]: +def read_msg() -> Optional[dict]: """Read Line delimited JSON from stdin.""" msg = json.loads(sys.stdin.readline().strip()) @@ -146,7 +146,7 @@ def run(self) -> None: completion_url = msg["action"]["href"] header = msg["action"]["header"] chunk_size = int(header.pop("chunk_size")) - presigned_urls: List[str] = list(header.values()) + presigned_urls: list[str] = list(header.values()) # Send a "started" progress event to allow other workers to start. # Otherwise they're delayed until first "progress" event is reported, diff --git a/src/huggingface_hub/commands/repo_files.py b/src/huggingface_hub/commands/repo_files.py index da9685315e..b914a2dc92 100644 --- a/src/huggingface_hub/commands/repo_files.py +++ b/src/huggingface_hub/commands/repo_files.py @@ -35,7 +35,7 @@ """ from argparse import _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub.commands import BaseHuggingfaceCLICommand @@ -54,7 +54,7 @@ def __init__(self, args) -> None: self.repo_type: Optional[str] = args.repo_type self.revision: Optional[str] = args.revision self.api: HfApi = HfApi(token=args.token, library_name="huggingface-cli") - self.patterns: List[str] = args.patterns + self.patterns: list[str] = args.patterns self.commit_message: Optional[str] = args.commit_message self.commit_description: Optional[str] = args.commit_description self.create_pr: bool = args.create_pr diff --git a/src/huggingface_hub/commands/upload.py b/src/huggingface_hub/commands/upload.py index c778555cda..180f8ef58b 100644 --- a/src/huggingface_hub/commands/upload.py +++ b/src/huggingface_hub/commands/upload.py @@ -50,7 +50,7 @@ import time import warnings from argparse import Namespace, _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub._commit_scheduler import CommitScheduler @@ -144,9 +144,9 @@ def __init__(self, args: Namespace) -> None: self.revision: Optional[str] = args.revision self.private: bool = args.private - self.include: Optional[List[str]] = args.include - self.exclude: Optional[List[str]] = args.exclude - self.delete: Optional[List[str]] = args.delete + self.include: Optional[list[str]] = args.include + self.exclude: Optional[list[str]] = args.exclude + self.delete: Optional[list[str]] = args.delete self.commit_message: Optional[str] = args.commit_message self.commit_description: Optional[str] = args.commit_description diff --git a/src/huggingface_hub/commands/upload_large_folder.py b/src/huggingface_hub/commands/upload_large_folder.py index 3105ba3f57..b0597868ea 100644 --- a/src/huggingface_hub/commands/upload_large_folder.py +++ b/src/huggingface_hub/commands/upload_large_folder.py @@ -16,7 +16,7 @@ import os from argparse import Namespace, _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub import logging from huggingface_hub.commands import BaseHuggingfaceCLICommand @@ -73,8 +73,8 @@ def __init__(self, args: Namespace) -> None: self.revision: Optional[str] = args.revision self.private: bool = args.private - self.include: Optional[List[str]] = args.include - self.exclude: Optional[List[str]] = args.exclude + self.include: Optional[list[str]] = args.include + self.exclude: Optional[list[str]] = args.exclude self.api: HfApi = HfApi(token=args.token, library_name="huggingface-cli") diff --git a/src/huggingface_hub/commands/user.py b/src/huggingface_hub/commands/user.py index 61cbc4c9e1..b187876328 100644 --- a/src/huggingface_hub/commands/user.py +++ b/src/huggingface_hub/commands/user.py @@ -31,7 +31,7 @@ """ from argparse import _SubParsersAction -from typing import List, Optional +from typing import Optional from huggingface_hub.commands import BaseHuggingfaceCLICommand from huggingface_hub.constants import ENDPOINT @@ -163,7 +163,7 @@ def _select_token_name(self) -> Optional[str]: except ValueError: print("Invalid input. Please enter a number or 'q' to quit.") - def _select_token_name_tui(self, token_names: List[str]) -> Optional[str]: + def _select_token_name_tui(self, token_names: list[str]) -> Optional[str]: choices = [Choice(token_name, name=token_name) for token_name in token_names] try: return inquirer.select( diff --git a/src/huggingface_hub/community.py b/src/huggingface_hub/community.py index 16f2f02428..3bb81e8e2e 100644 --- a/src/huggingface_hub/community.py +++ b/src/huggingface_hub/community.py @@ -7,7 +7,7 @@ from dataclasses import dataclass from datetime import datetime -from typing import List, Literal, Optional, Union +from typing import Literal, Optional, Union from . import constants from .utils import parse_datetime @@ -116,7 +116,7 @@ class DiscussionWithDetails(Discussion): The `datetime` of creation of the Discussion / Pull Request. events (`list` of [`DiscussionEvent`]) The list of [`DiscussionEvents`] in this Discussion or Pull Request. - conflicting_files (`Union[List[str], bool, None]`, *optional*): + conflicting_files (`Union[list[str], bool, None]`, *optional*): A list of conflicting files if this is a Pull Request. `None` if `self.is_pull_request` is `False`. `True` if there are conflicting files but the list can't be retrieved. @@ -136,8 +136,8 @@ class DiscussionWithDetails(Discussion): (property) URL of the discussion on the Hub. """ - events: List["DiscussionEvent"] - conflicting_files: Union[List[str], bool, None] + events: list["DiscussionEvent"] + conflicting_files: Union[list[str], bool, None] target_branch: Optional[str] merge_commit_oid: Optional[str] diff: Optional[str] @@ -222,7 +222,7 @@ def last_edited_by(self) -> str: return self._event["data"]["latest"].get("author", {}).get("name", "deleted") @property - def edit_history(self) -> List[dict]: + def edit_history(self) -> list[dict]: """The edit history of the comment""" return self._event["data"]["history"] diff --git a/src/huggingface_hub/constants.py b/src/huggingface_hub/constants.py index b30b2c01d9..c1445ffc9d 100644 --- a/src/huggingface_hub/constants.py +++ b/src/huggingface_hub/constants.py @@ -1,7 +1,7 @@ import os import re import typing -from typing import Literal, Optional, Tuple +from typing import Literal, Optional # Possible values for env variables @@ -118,9 +118,9 @@ def _as_int(value: Optional[str]) -> Optional[int]: } DiscussionTypeFilter = Literal["all", "discussion", "pull_request"] -DISCUSSION_TYPES: Tuple[DiscussionTypeFilter, ...] = typing.get_args(DiscussionTypeFilter) +DISCUSSION_TYPES: tuple[DiscussionTypeFilter, ...] = typing.get_args(DiscussionTypeFilter) DiscussionStatusFilter = Literal["all", "open", "closed"] -DISCUSSION_STATUS: Tuple[DiscussionTypeFilter, ...] = typing.get_args(DiscussionStatusFilter) +DISCUSSION_STATUS: tuple[DiscussionTypeFilter, ...] = typing.get_args(DiscussionStatusFilter) # Webhook subscription types WEBHOOK_DOMAIN_T = Literal["repo", "discussions"] diff --git a/src/huggingface_hub/dataclasses.py b/src/huggingface_hub/dataclasses.py index bf81c522d5..cc78945e3a 100644 --- a/src/huggingface_hub/dataclasses.py +++ b/src/huggingface_hub/dataclasses.py @@ -4,11 +4,8 @@ from typing import ( Any, Callable, - Dict, - List, Literal, Optional, - Tuple, Type, TypeVar, Union, @@ -102,7 +99,7 @@ def wrap(cls: Type[T]) -> Type[T]: ) # List and store validators - field_validators: Dict[str, List[Validator_T]] = {} + field_validators: dict[str, list[Validator_T]] = {} for f in fields(cls): # type: ignore [arg-type] validators = [] validators.append(_create_type_validator(f)) @@ -238,14 +235,14 @@ def init_with_validate(self, *args, **kwargs) -> None: def validated_field( - validator: Union[List[Validator_T], Validator_T], + validator: Union[list[Validator_T], Validator_T], default: Union[Any, _MISSING_TYPE] = MISSING, default_factory: Union[Callable[[], Any], _MISSING_TYPE] = MISSING, init: bool = True, repr: bool = True, hash: Optional[bool] = None, compare: bool = True, - metadata: Optional[Dict] = None, + metadata: Optional[dict] = None, **kwargs: Any, ) -> Any: """ @@ -254,7 +251,7 @@ def validated_field( Useful to apply several checks to a field. If only applying one rule, check out the [`as_validated_field`] decorator. Args: - validator (`Callable` or `List[Callable]`): + validator (`Callable` or `list[Callable]`): A method that takes a value as input and raises ValueError/TypeError if the value is invalid. Can be a list of validators to apply multiple checks. **kwargs: @@ -296,7 +293,7 @@ def _inner( repr: bool = True, hash: Optional[bool] = None, compare: bool = True, - metadata: Optional[Dict] = None, + metadata: Optional[dict] = None, **kwargs: Any, ): return validated_field( @@ -329,7 +326,7 @@ def type_validator(name: str, value: Any, expected_type: Any) -> None: raise TypeError(f"Unsupported type for field '{name}': {expected_type}") -def _validate_union(name: str, value: Any, args: Tuple[Any, ...]) -> None: +def _validate_union(name: str, value: Any, args: tuple[Any, ...]) -> None: """Validate that value matches one of the types in a Union.""" errors = [] for t in args: @@ -344,14 +341,14 @@ def _validate_union(name: str, value: Any, args: Tuple[Any, ...]) -> None: ) -def _validate_literal(name: str, value: Any, args: Tuple[Any, ...]) -> None: +def _validate_literal(name: str, value: Any, args: tuple[Any, ...]) -> None: """Validate Literal type.""" if value not in args: raise TypeError(f"Field '{name}' expected one of {args}, got {value}") -def _validate_list(name: str, value: Any, args: Tuple[Any, ...]) -> None: - """Validate List[T] type.""" +def _validate_list(name: str, value: Any, args: tuple[Any, ...]) -> None: + """Validate list[T] type.""" if not isinstance(value, list): raise TypeError(f"Field '{name}' expected a list, got {type(value).__name__}") @@ -364,8 +361,8 @@ def _validate_list(name: str, value: Any, args: Tuple[Any, ...]) -> None: raise TypeError(f"Invalid item at index {i} in list '{name}'") from e -def _validate_dict(name: str, value: Any, args: Tuple[Any, ...]) -> None: - """Validate Dict[K, V] type.""" +def _validate_dict(name: str, value: Any, args: tuple[Any, ...]) -> None: + """Validate dict[K, V] type.""" if not isinstance(value, dict): raise TypeError(f"Field '{name}' expected a dict, got {type(value).__name__}") @@ -379,19 +376,19 @@ def _validate_dict(name: str, value: Any, args: Tuple[Any, ...]) -> None: raise TypeError(f"Invalid key or value in dict '{name}'") from e -def _validate_tuple(name: str, value: Any, args: Tuple[Any, ...]) -> None: +def _validate_tuple(name: str, value: Any, args: tuple[Any, ...]) -> None: """Validate Tuple type.""" if not isinstance(value, tuple): raise TypeError(f"Field '{name}' expected a tuple, got {type(value).__name__}") - # Handle variable-length tuples: Tuple[T, ...] + # Handle variable-length tuples: tuple[T, ...] if len(args) == 2 and args[1] is Ellipsis: for i, item in enumerate(value): try: type_validator(f"{name}[{i}]", item, args[0]) except TypeError as e: raise TypeError(f"Invalid item at index {i} in tuple '{name}'") from e - # Handle fixed-length tuples: Tuple[T1, T2, ...] + # Handle fixed-length tuples: tuple[T1, T2, ...] elif len(args) != len(value): raise TypeError(f"Field '{name}' expected a tuple of length {len(args)}, got {len(value)}") else: @@ -402,8 +399,8 @@ def _validate_tuple(name: str, value: Any, args: Tuple[Any, ...]) -> None: raise TypeError(f"Invalid item at index {i} in tuple '{name}'") from e -def _validate_set(name: str, value: Any, args: Tuple[Any, ...]) -> None: - """Validate Set[T] type.""" +def _validate_set(name: str, value: Any, args: tuple[Any, ...]) -> None: + """Validate set[T] type.""" if not isinstance(value, set): raise TypeError(f"Field '{name}' expected a set, got {type(value).__name__}") diff --git a/src/huggingface_hub/fastai_utils.py b/src/huggingface_hub/fastai_utils.py index e75eba2a8b..de36ff3b36 100644 --- a/src/huggingface_hub/fastai_utils.py +++ b/src/huggingface_hub/fastai_utils.py @@ -2,7 +2,7 @@ import os from pathlib import Path from pickle import DEFAULT_PROTOCOL, PicklingError -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union from packaging import version @@ -241,7 +241,7 @@ def _create_model_pyproject(repo_dir: Path): def _save_pretrained_fastai( learner, save_directory: Union[str, Path], - config: Optional[Dict[str, Any]] = None, + config: Optional[dict[str, Any]] = None, ): """ Saves a fastai learner to `save_directory` in pickle format using the default pickle protocol for the version of python used. @@ -350,9 +350,9 @@ def push_to_hub_fastai( config: Optional[dict] = None, branch: Optional[str] = None, create_pr: Optional[bool] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, - delete_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, + delete_patterns: Optional[Union[list[str], str]] = None, api_endpoint: Optional[str] = None, ): """ @@ -385,11 +385,11 @@ def push_to_hub_fastai( Defaults to `False`. api_endpoint (`str`, *optional*): The API endpoint to use when pushing the model to the hub. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are pushed. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not pushed. - delete_patterns (`List[str]` or `str`, *optional*): + delete_patterns (`list[str]` or `str`, *optional*): If provided, remote files matching any of the patterns will be deleted from the repo. Returns: diff --git a/src/huggingface_hub/file_download.py b/src/huggingface_hub/file_download.py index 89e2ad74e4..c3f57fbd78 100644 --- a/src/huggingface_hub/file_download.py +++ b/src/huggingface_hub/file_download.py @@ -9,7 +9,7 @@ import warnings from dataclasses import dataclass from pathlib import Path -from typing import Any, BinaryIO, Dict, Literal, NoReturn, Optional, Tuple, Union +from typing import Any, BinaryIO, Literal, NoReturn, Optional, Union from urllib.parse import quote, urlparse import httpx @@ -81,7 +81,7 @@ # Regex to check if the file etag IS a valid sha256 REGEX_SHA256 = re.compile(r"^[0-9a-f]{64}$") -_are_symlinks_supported_in_dir: Dict[str, bool] = {} +_are_symlinks_supported_in_dir: dict[str, bool] = {} def are_symlinks_supported(cache_dir: Union[str, Path, None] = None) -> bool: @@ -341,7 +341,7 @@ def http_get( temp_file: BinaryIO, *, resume_size: int = 0, - headers: Optional[Dict[str, Any]] = None, + headers: Optional[dict[str, Any]] = None, expected_size: Optional[int] = None, displayed_filename: Optional[str] = None, _nb_retries: int = 5, @@ -512,7 +512,7 @@ def xet_get( *, incomplete_path: Path, xet_file_data: XetFileData, - headers: Dict[str, str], + headers: dict[str, str], expected_size: Optional[int] = None, displayed_filename: Optional[str] = None, _tqdm_bar: Optional[tqdm] = None, @@ -525,7 +525,7 @@ def xet_get( The path to the file to download. xet_file_data (`XetFileData`): The file metadata needed to make the request to the xet storage service. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): The headers to send to the xet storage service. expected_size (`int`, *optional*): The expected size of the file to download. If set, the download will raise an error if the size of the @@ -572,7 +572,7 @@ def xet_get( connection_info = refresh_xet_connection_info(file_data=xet_file_data, headers=headers) - def token_refresher() -> Tuple[str, int]: + def token_refresher() -> tuple[str, int]: connection_info = refresh_xet_connection_info(file_data=xet_file_data, headers=headers) if connection_info is None: raise ValueError("Failed to refresh token using xet metadata.") @@ -799,12 +799,12 @@ def hf_hub_download( library_version: Optional[str] = None, cache_dir: Union[str, Path, None] = None, local_dir: Union[str, Path, None] = None, - user_agent: Union[Dict, str, None] = None, + user_agent: Union[dict, str, None] = None, force_download: bool = False, etag_timeout: float = constants.DEFAULT_ETAG_TIMEOUT, token: Union[bool, str, None] = None, local_files_only: bool = False, - headers: Optional[Dict[str, str]] = None, + headers: Optional[dict[str, str]] = None, endpoint: Optional[str] = None, resume_download: Optional[bool] = None, force_filename: Optional[str] = None, @@ -1012,7 +1012,7 @@ def _hf_hub_download_to_cache_dir( # HTTP info endpoint: Optional[str], etag_timeout: float, - headers: Dict[str, str], + headers: dict[str, str], token: Optional[Union[bool, str]], # Additional options local_files_only: bool, @@ -1168,7 +1168,7 @@ def _hf_hub_download_to_local_dir( # HTTP info endpoint: Optional[str], etag_timeout: float, - headers: Dict[str, str], + headers: dict[str, str], token: Union[bool, str, None], # Additional options cache_dir: str, @@ -1381,8 +1381,8 @@ def get_hf_file_metadata( timeout: Optional[float] = constants.DEFAULT_REQUEST_TIMEOUT, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Union[Dict, str, None] = None, - headers: Optional[Dict[str, str]] = None, + user_agent: Union[dict, str, None] = None, + headers: Optional[dict[str, str]] = None, endpoint: Optional[str] = None, ) -> HfFileMetadata: """Fetch metadata of a file versioned on the Hub for a given url. @@ -1451,17 +1451,17 @@ def _get_metadata_or_catch_error( revision: str, endpoint: Optional[str], etag_timeout: Optional[float], - headers: Dict[str, str], # mutated inplace! + headers: dict[str, str], # mutated inplace! token: Union[bool, str, None], local_files_only: bool, relative_filename: Optional[str] = None, # only used to store `.no_exists` in cache storage_folder: Optional[str] = None, # only used to store `.no_exists` in cache ) -> Union[ # Either an exception is caught and returned - Tuple[None, None, None, None, None, Exception], + tuple[None, None, None, None, None, Exception], # Or the metadata is returned as # `(url_to_download, etag, commit_hash, expected_size, xet_file_data, None)` - Tuple[str, str, str, int, Optional[XetFileData], None], + tuple[str, str, str, int, Optional[XetFileData], None], ]: """Get metadata for a file on the Hub, safely handling network issues. @@ -1619,7 +1619,7 @@ def _download_to_tmp_and_move( incomplete_path: Path, destination_path: Path, url_to_download: str, - headers: Dict[str, str], + headers: dict[str, str], expected_size: Optional[int], filename: str, force_download: bool, diff --git a/src/huggingface_hub/hf_api.py b/src/huggingface_hub/hf_api.py index a5aef6bbc5..951a19dcc0 100644 --- a/src/huggingface_hub/hf_api.py +++ b/src/huggingface_hub/hf_api.py @@ -34,14 +34,10 @@ Any, BinaryIO, Callable, - Dict, Iterable, Iterator, - List, Literal, Optional, - Tuple, - Type, TypeVar, Union, overload, @@ -242,7 +238,7 @@ logger = logging.get_logger(__name__) -def repo_type_and_id_from_hf_id(hf_id: str, hub_url: Optional[str] = None) -> Tuple[Optional[str], Optional[str], str]: +def repo_type_and_id_from_hf_id(hf_id: str, hub_url: Optional[str] = None) -> tuple[Optional[str], Optional[str], str]: """ Returns the repo type and ID from a huggingface.co URL linking to a repository @@ -352,8 +348,8 @@ def __post_init__(self): # hack to make BlobLfsInfo backward compatible class BlobSecurityInfo(dict): safe: bool # duplicate information with "status" field, keeping it for backward compatibility status: str - av_scan: Optional[Dict] - pickle_import_scan: Optional[Dict] + av_scan: Optional[dict] + pickle_import_scan: Optional[dict] def __post_init__(self): # hack to make BlogSecurityInfo backward compatible self.update(asdict(self)) @@ -373,7 +369,7 @@ def __post_init__(self): # hack to make TransformersInfo backward compatible @dataclass class SafeTensorsInfo(dict): - parameters: Dict[str, int] + parameters: dict[str, int] total: int def __post_init__(self): # hack to make SafeTensorsInfo backward compatible @@ -476,7 +472,7 @@ class AccessRequest: Timestamp of the request. status (`Literal["pending", "accepted", "rejected"]`): Status of the request. Can be one of `["pending", "accepted", "rejected"]`. - fields (`Dict[str, Any]`, *optional*): + fields (`dict[str, Any]`, *optional*): Additional fields filled by the user in the gate form. """ @@ -487,7 +483,7 @@ class AccessRequest: status: Literal["pending", "accepted", "rejected"] # Additional fields filled by the user in the gate form - fields: Optional[Dict[str, Any]] = None + fields: Optional[dict[str, Any]] = None @dataclass @@ -514,9 +510,9 @@ class WebhookInfo: ID of the webhook. url (`str`): URL of the webhook. - watched (`List[WebhookWatchedItem]`): + watched (`list[WebhookWatchedItem]`): List of items watched by the webhook, see [`WebhookWatchedItem`]. - domains (`List[WEBHOOK_DOMAIN_T]`): + domains (`list[WEBHOOK_DOMAIN_T]`): List of domains the webhook is watching. Can be one of `["repo", "discussions"]`. secret (`str`, *optional*): Secret of the webhook. @@ -526,8 +522,8 @@ class WebhookInfo: id: str url: str - watched: List[WebhookWatchedItem] - domains: List[constants.WEBHOOK_DOMAIN_T] + watched: list[WebhookWatchedItem] + domains: list[constants.WEBHOOK_DOMAIN_T] secret: Optional[str] disabled: bool @@ -778,17 +774,17 @@ class ModelInfo: gated (`Literal["auto", "manual", False]`, *optional*): Is the repo gated. If so, whether there is manual or automatic approval. - gguf (`Dict`, *optional*): + gguf (`dict`, *optional*): GGUF information of the model. inference (`Literal["warm"]`, *optional*): Status of the model on Inference Providers. Warm if the model is served by at least one provider. - inference_provider_mapping (`List[InferenceProviderMapping]`, *optional*): + inference_provider_mapping (`list[InferenceProviderMapping]`, *optional*): A list of [`InferenceProviderMapping`] ordered after the user's provider order. likes (`int`): Number of likes of the model. library_name (`str`, *optional*): Library associated with the model. - tags (`List[str]`): + tags (`list[str]`): List of tags of the model. Compared to `card_data.tags`, contains extra tags computed by the Hub (e.g. supported libraries, model's arXiv). pipeline_tag (`str`, *optional*): @@ -797,9 +793,9 @@ class ModelInfo: Mask token used by the model. widget_data (`Any`, *optional*): Widget data associated with the model. - model_index (`Dict`, *optional*): + model_index (`dict`, *optional*): Model index for evaluation. - config (`Dict`, *optional*): + config (`dict`, *optional*): Model configuration. transformers_info (`TransformersInfo`, *optional*): Transformers-specific info (auto class, processor, etc.) associated with the model. @@ -807,13 +803,13 @@ class ModelInfo: Trending score of the model. card_data (`ModelCardData`, *optional*): Model Card Metadata as a [`huggingface_hub.repocard_data.ModelCardData`] object. - siblings (`List[RepoSibling]`): + siblings (`list[RepoSibling]`): List of [`huggingface_hub.hf_api.RepoSibling`] objects that constitute the model. - spaces (`List[str]`, *optional*): + spaces (`list[str]`, *optional*): List of spaces using the model. safetensors (`SafeTensorsInfo`, *optional*): Model's safetensors information. - security_repo_status (`Dict`, *optional*): + security_repo_status (`dict`, *optional*): Model's security scan status. """ @@ -827,24 +823,24 @@ class ModelInfo: downloads: Optional[int] downloads_all_time: Optional[int] gated: Optional[Literal["auto", "manual", False]] - gguf: Optional[Dict] + gguf: Optional[dict] inference: Optional[Literal["warm"]] - inference_provider_mapping: Optional[List[InferenceProviderMapping]] + inference_provider_mapping: Optional[list[InferenceProviderMapping]] likes: Optional[int] library_name: Optional[str] - tags: Optional[List[str]] + tags: Optional[list[str]] pipeline_tag: Optional[str] mask_token: Optional[str] card_data: Optional[ModelCardData] widget_data: Optional[Any] - model_index: Optional[Dict] - config: Optional[Dict] + model_index: Optional[dict] + config: Optional[dict] transformers_info: Optional[TransformersInfo] trending_score: Optional[int] - siblings: Optional[List[RepoSibling]] - spaces: Optional[List[str]] + siblings: Optional[list[RepoSibling]] + spaces: Optional[list[str]] safetensors: Optional[SafeTensorsInfo] - security_repo_status: Optional[Dict] + security_repo_status: Optional[dict] xet_enabled: Optional[bool] def __init__(self, **kwargs): @@ -979,11 +975,11 @@ class DatasetInfo: Cumulated number of downloads of the model since its creation. likes (`int`): Number of likes of the dataset. - tags (`List[str]`): + tags (`list[str]`): List of tags of the dataset. card_data (`DatasetCardData`, *optional*): Model Card Metadata as a [`huggingface_hub.repocard_data.DatasetCardData`] object. - siblings (`List[RepoSibling]`): + siblings (`list[RepoSibling]`): List of [`huggingface_hub.hf_api.RepoSibling`] objects that constitute the dataset. paperswithcode_id (`str`, *optional*): Papers with code ID of the dataset. @@ -1003,10 +999,10 @@ class DatasetInfo: downloads_all_time: Optional[int] likes: Optional[int] paperswithcode_id: Optional[str] - tags: Optional[List[str]] + tags: Optional[list[str]] trending_score: Optional[int] card_data: Optional[DatasetCardData] - siblings: Optional[List[RepoSibling]] + siblings: Optional[list[RepoSibling]] xet_enabled: Optional[bool] def __init__(self, **kwargs): @@ -1098,9 +1094,9 @@ class SpaceInfo: Subdomain of the Space. likes (`int`): Number of likes of the Space. - tags (`List[str]`): + tags (`list[str]`): List of tags of the Space. - siblings (`List[RepoSibling]`): + siblings (`list[RepoSibling]`): List of [`huggingface_hub.hf_api.RepoSibling`] objects that constitute the Space. card_data (`SpaceCardData`, *optional*): Space Card Metadata as a [`huggingface_hub.repocard_data.SpaceCardData`] object. @@ -1108,9 +1104,9 @@ class SpaceInfo: Space runtime information as a [`huggingface_hub.hf_api.SpaceRuntime`] object. sdk (`str`, *optional*): SDK used by the Space. - models (`List[str]`, *optional*): + models (`list[str]`, *optional*): List of models used by the Space. - datasets (`List[str]`, *optional*): + datasets (`list[str]`, *optional*): List of datasets used by the Space. trending_score (`int`, *optional*): Trending score of the Space. @@ -1128,13 +1124,13 @@ class SpaceInfo: subdomain: Optional[str] likes: Optional[int] sdk: Optional[str] - tags: Optional[List[str]] - siblings: Optional[List[RepoSibling]] + tags: Optional[list[str]] + siblings: Optional[list[RepoSibling]] trending_score: Optional[int] card_data: Optional[SpaceCardData] runtime: Optional[SpaceRuntime] - models: Optional[List[str]] - datasets: Optional[List[str]] + models: Optional[list[str]] + datasets: Optional[list[str]] xet_enabled: Optional[bool] def __init__(self, **kwargs): @@ -1222,7 +1218,7 @@ def __init__( id: str, type: CollectionItemType_T, position: int, - note: Optional[Dict] = None, + note: Optional[dict] = None, **kwargs, ) -> None: self.item_object_id: str = _id # id in database @@ -1248,7 +1244,7 @@ class Collection: Title of the collection. E.g. `"Recent models"`. owner (`str`): Owner of the collection. E.g. `"TheBloke"`. - items (`List[CollectionItem]`): + items (`list[CollectionItem]`): List of items in the collection. last_updated (`datetime`): Date of the last update of the collection. @@ -1269,7 +1265,7 @@ class Collection: slug: str title: str owner: str - items: List[CollectionItem] + items: list[CollectionItem] last_updated: datetime position: int private: bool @@ -1326,22 +1322,22 @@ class GitRefs: Object is returned by [`list_repo_refs`]. Attributes: - branches (`List[GitRefInfo]`): + branches (`list[GitRefInfo]`): A list of [`GitRefInfo`] containing information about branches on the repo. - converts (`List[GitRefInfo]`): + converts (`list[GitRefInfo]`): A list of [`GitRefInfo`] containing information about "convert" refs on the repo. Converts are refs used (internally) to push preprocessed data in Dataset repos. - tags (`List[GitRefInfo]`): + tags (`list[GitRefInfo]`): A list of [`GitRefInfo`] containing information about tags on the repo. - pull_requests (`List[GitRefInfo]`, *optional*): + pull_requests (`list[GitRefInfo]`, *optional*): A list of [`GitRefInfo`] containing information about pull requests on the repo. Only returned if `include_prs=True` is set. """ - branches: List[GitRefInfo] - converts: List[GitRefInfo] - tags: List[GitRefInfo] - pull_requests: Optional[List[GitRefInfo]] = None + branches: list[GitRefInfo] + converts: list[GitRefInfo] + tags: list[GitRefInfo] + pull_requests: Optional[list[GitRefInfo]] = None @dataclass @@ -1352,7 +1348,7 @@ class GitCommitInfo: Attributes: commit_id (`str`): OID of the commit (e.g. `"e7da7f221d5bf496a48136c0cd264e630fe9fcc8"`) - authors (`List[str]`): + authors (`list[str]`): List of authors of the commit. created_at (`datetime`): Datetime when the commit was created. @@ -1368,7 +1364,7 @@ class GitCommitInfo: commit_id: str - authors: List[str] + authors: list[str] created_at: datetime title: str message: str @@ -1387,11 +1383,11 @@ class UserLikes: Name of the user for which we fetched the likes. total (`int`): Total number of likes. - datasets (`List[str]`): + datasets (`list[str]`): List of datasets liked by the user (as repo_ids). - models (`List[str]`): + models (`list[str]`): List of models liked by the user (as repo_ids). - spaces (`List[str]`): + spaces (`list[str]`): List of spaces liked by the user (as repo_ids). """ @@ -1400,9 +1396,9 @@ class UserLikes: total: int # User likes - datasets: List[str] - models: List[str] - spaces: List[str] + datasets: list[str] + models: list[str] + spaces: list[str] @dataclass @@ -1488,7 +1484,7 @@ class User: num_likes: Optional[int] = None num_following: Optional[int] = None num_followers: Optional[int] = None - orgs: List[Organization] = field(default_factory=list) + orgs: list[Organization] = field(default_factory=list) def __init__(self, **kwargs) -> None: self.username = kwargs.pop("user", "") @@ -1521,7 +1517,7 @@ class PaperInfo: Attributes: id (`str`): arXiv paper ID. - authors (`List[str]`, **optional**): + authors (`list[str]`, **optional**): Names of paper authors published_at (`datetime`, **optional**): Date paper published. @@ -1544,7 +1540,7 @@ class PaperInfo: """ id: str - authors: Optional[List[str]] + authors: Optional[list[str]] published_at: Optional[datetime] title: Optional[str] summary: Optional[str] @@ -1708,8 +1704,8 @@ def __init__( token: Union[str, bool, None] = None, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Union[Dict, str, None] = None, - headers: Optional[Dict[str, str]] = None, + user_agent: Union[dict, str, None] = None, + headers: Optional[dict[str, str]] = None, ) -> None: self.endpoint = endpoint if endpoint is not None else constants.ENDPOINT self.token = token @@ -1760,7 +1756,7 @@ def run_as_future(self, fn: Callable[..., R], *args, **kwargs) -> Future[R]: return self._thread_pool.submit(fn, *args, **kwargs) @validate_hf_hub_args - def whoami(self, token: Union[bool, str, None] = None) -> Dict: + def whoami(self, token: Union[bool, str, None] = None) -> dict: """ Call HF API to know "whoami". @@ -1836,7 +1832,7 @@ def get_token_permission( except (LocalTokenNotFoundError, HfHubHTTPError, KeyError): return None - def get_model_tags(self) -> Dict: + def get_model_tags(self) -> dict: """ List all valid model tags as a nested namespace object """ @@ -1845,7 +1841,7 @@ def get_model_tags(self) -> Dict: hf_raise_for_status(r) return r.json() - def get_dataset_tags(self) -> Dict: + def get_dataset_tags(self) -> dict: """ List all valid dataset tags as a nested namespace object. """ @@ -1864,30 +1860,30 @@ def list_models( # Search-query parameter filter: Union[str, Iterable[str], None] = None, author: Optional[str] = None, - apps: Optional[Union[str, List[str]]] = None, + apps: Optional[Union[str, list[str]]] = None, gated: Optional[bool] = None, inference: Optional[Literal["warm"]] = None, - inference_provider: Optional[Union[Literal["all"], "PROVIDER_T", List["PROVIDER_T"]]] = None, + inference_provider: Optional[Union[Literal["all"], "PROVIDER_T", list["PROVIDER_T"]]] = None, model_name: Optional[str] = None, - trained_dataset: Optional[Union[str, List[str]]] = None, + trained_dataset: Optional[Union[str, list[str]]] = None, search: Optional[str] = None, pipeline_tag: Optional[str] = None, - emissions_thresholds: Optional[Tuple[float, float]] = None, + emissions_thresholds: Optional[tuple[float, float]] = None, # Sorting and pagination parameters sort: Union[Literal["last_modified"], str, None] = None, direction: Optional[Literal[-1]] = None, limit: Optional[int] = None, # Additional data to fetch - expand: Optional[List[ExpandModelProperty_T]] = None, + expand: Optional[list[ExpandModelProperty_T]] = None, full: Optional[bool] = None, cardData: bool = False, fetch_config: bool = False, token: Union[bool, str, None] = None, # Deprecated arguments - use `filter` instead - language: Optional[Union[str, List[str]]] = None, - library: Optional[Union[str, List[str]]] = None, - tags: Optional[Union[str, List[str]]] = None, - task: Optional[Union[str, List[str]]] = None, + language: Optional[Union[str, list[str]]] = None, + library: Optional[Union[str, list[str]]] = None, + tags: Optional[Union[str, list[str]]] = None, + task: Optional[Union[str, list[str]]] = None, ) -> Iterable[ModelInfo]: """ List models hosted on the Huggingface Hub, given some filters. @@ -1941,7 +1937,7 @@ def list_models( limit (`int`, *optional*): The limit on the number of models fetched. Leaving this option to `None` fetches all models. - expand (`List[ExpandModelProperty_T]`, *optional*): + expand (`list[ExpandModelProperty_T]`, *optional*): List properties to return in the response. When used, only the properties in the list will be returned. This parameter cannot be used if `full`, `cardData` or `fetch_config` are passed. Possible values are `"author"`, `"cardData"`, `"config"`, `"createdAt"`, `"disabled"`, `"downloads"`, `"downloadsAllTime"`, `"gated"`, `"gguf"`, `"inference"`, `"inferenceProviderMapping"`, `"lastModified"`, `"library_name"`, `"likes"`, `"mask_token"`, `"model-index"`, `"pipeline_tag"`, `"private"`, `"safetensors"`, `"sha"`, `"siblings"`, `"spaces"`, `"tags"`, `"transformersInfo"`, `"trendingScore"`, `"widgetData"`, `"resourceGroup"` and `"xetEnabled"`. @@ -2000,10 +1996,10 @@ def list_models( path = f"{self.endpoint}/api/models" headers = self._build_hf_headers(token=token) - params: Dict[str, Any] = {} + params: dict[str, Any] = {} # Build the filter list - filter_list: List[str] = [] + filter_list: list[str] = [] if filter: filter_list.extend([filter] if isinstance(filter, str) else filter) if library: @@ -2090,26 +2086,26 @@ def list_datasets( # Search-query parameter filter: Union[str, Iterable[str], None] = None, author: Optional[str] = None, - benchmark: Optional[Union[str, List[str]]] = None, + benchmark: Optional[Union[str, list[str]]] = None, dataset_name: Optional[str] = None, gated: Optional[bool] = None, - language_creators: Optional[Union[str, List[str]]] = None, - language: Optional[Union[str, List[str]]] = None, - multilinguality: Optional[Union[str, List[str]]] = None, - size_categories: Optional[Union[str, List[str]]] = None, - task_categories: Optional[Union[str, List[str]]] = None, - task_ids: Optional[Union[str, List[str]]] = None, + language_creators: Optional[Union[str, list[str]]] = None, + language: Optional[Union[str, list[str]]] = None, + multilinguality: Optional[Union[str, list[str]]] = None, + size_categories: Optional[Union[str, list[str]]] = None, + task_categories: Optional[Union[str, list[str]]] = None, + task_ids: Optional[Union[str, list[str]]] = None, search: Optional[str] = None, # Sorting and pagination parameters sort: Optional[Union[Literal["last_modified"], str]] = None, direction: Optional[Literal[-1]] = None, limit: Optional[int] = None, # Additional data to fetch - expand: Optional[List[ExpandDatasetProperty_T]] = None, + expand: Optional[list[ExpandDatasetProperty_T]] = None, full: Optional[bool] = None, token: Union[bool, str, None] = None, # Deprecated arguments - use `filter` instead - tags: Optional[Union[str, List[str]]] = None, + tags: Optional[Union[str, list[str]]] = None, ) -> Iterable[DatasetInfo]: """ List datasets hosted on the Huggingface Hub, given some filters. @@ -2164,7 +2160,7 @@ def list_datasets( limit (`int`, *optional*): The limit on the number of datasets fetched. Leaving this option to `None` fetches all datasets. - expand (`List[ExpandDatasetProperty_T]`, *optional*): + expand (`list[ExpandDatasetProperty_T]`, *optional*): List properties to return in the response. When used, only the properties in the list will be returned. This parameter cannot be used if `full` is passed. Possible values are `"author"`, `"cardData"`, `"citation"`, `"createdAt"`, `"disabled"`, `"description"`, `"downloads"`, `"downloadsAllTime"`, `"gated"`, `"lastModified"`, `"likes"`, `"paperswithcode_id"`, `"private"`, `"siblings"`, `"sha"`, `"tags"`, `"trendingScore"`, `"usedStorage"`, `"resourceGroup"` and `"xetEnabled"`. @@ -2224,7 +2220,7 @@ def list_datasets( path = f"{self.endpoint}/api/datasets" headers = self._build_hf_headers(token=token) - params: Dict[str, Any] = {} + params: dict[str, Any] = {} # Build `filter` list filter_list = [] @@ -2311,7 +2307,7 @@ def list_spaces( direction: Optional[Literal[-1]] = None, limit: Optional[int] = None, # Additional data to fetch - expand: Optional[List[ExpandSpaceProperty_T]] = None, + expand: Optional[list[ExpandSpaceProperty_T]] = None, full: Optional[bool] = None, token: Union[bool, str, None] = None, ) -> Iterable[SpaceInfo]: @@ -2342,7 +2338,7 @@ def list_spaces( limit (`int`, *optional*): The limit on the number of Spaces fetched. Leaving this option to `None` fetches all Spaces. - expand (`List[ExpandSpaceProperty_T]`, *optional*): + expand (`list[ExpandSpaceProperty_T]`, *optional*): List properties to return in the response. When used, only the properties in the list will be returned. This parameter cannot be used if `full` is passed. Possible values are `"author"`, `"cardData"`, `"datasets"`, `"disabled"`, `"lastModified"`, `"createdAt"`, `"likes"`, `"models"`, `"private"`, `"runtime"`, `"sdk"`, `"siblings"`, `"sha"`, `"subdomain"`, `"tags"`, `"trendingScore"`, `"usedStorage"`, `"resourceGroup"` and `"xetEnabled"`. @@ -2363,7 +2359,7 @@ def list_spaces( path = f"{self.endpoint}/api/spaces" headers = self._build_hf_headers(token=token) - params: Dict[str, Any] = {} + params: dict[str, Any] = {} if filter is not None: params["filter"] = filter if author is not None: @@ -2580,7 +2576,7 @@ def model_info( timeout: Optional[float] = None, securityStatus: Optional[bool] = None, files_metadata: bool = False, - expand: Optional[List[ExpandModelProperty_T]] = None, + expand: Optional[list[ExpandModelProperty_T]] = None, token: Union[bool, str, None] = None, ) -> ModelInfo: """ @@ -2603,7 +2599,7 @@ def model_info( files_metadata (`bool`, *optional*): Whether or not to retrieve metadata for files in the repository (size, LFS metadata, etc). Defaults to `False`. - expand (`List[ExpandModelProperty_T]`, *optional*): + expand (`list[ExpandModelProperty_T]`, *optional*): List properties to return in the response. When used, only the properties in the list will be returned. This parameter cannot be used if `securityStatus` or `files_metadata` are passed. Possible values are `"author"`, `"baseModels"`, `"cardData"`, `"childrenModelCount"`, `"config"`, `"createdAt"`, `"disabled"`, `"downloads"`, `"downloadsAllTime"`, `"gated"`, `"gguf"`, `"inference"`, `"inferenceProviderMapping"`, `"lastModified"`, `"library_name"`, `"likes"`, `"mask_token"`, `"model-index"`, `"pipeline_tag"`, `"private"`, `"safetensors"`, `"sha"`, `"siblings"`, `"spaces"`, `"tags"`, `"transformersInfo"`, `"trendingScore"`, `"widgetData"`, `"usedStorage"`, `"resourceGroup"` and `"xetEnabled"`. @@ -2637,7 +2633,7 @@ def model_info( if revision is None else (f"{self.endpoint}/api/models/{repo_id}/revision/{quote(revision, safe='')}") ) - params: Dict = {} + params: dict = {} if securityStatus: params["securityStatus"] = True if files_metadata: @@ -2657,7 +2653,7 @@ def dataset_info( revision: Optional[str] = None, timeout: Optional[float] = None, files_metadata: bool = False, - expand: Optional[List[ExpandDatasetProperty_T]] = None, + expand: Optional[list[ExpandDatasetProperty_T]] = None, token: Union[bool, str, None] = None, ) -> DatasetInfo: """ @@ -2677,7 +2673,7 @@ def dataset_info( files_metadata (`bool`, *optional*): Whether or not to retrieve metadata for files in the repository (size, LFS metadata, etc). Defaults to `False`. - expand (`List[ExpandDatasetProperty_T]`, *optional*): + expand (`list[ExpandDatasetProperty_T]`, *optional*): List properties to return in the response. When used, only the properties in the list will be returned. This parameter cannot be used if `files_metadata` is passed. Possible values are `"author"`, `"cardData"`, `"citation"`, `"createdAt"`, `"disabled"`, `"description"`, `"downloads"`, `"downloadsAllTime"`, `"gated"`, `"lastModified"`, `"likes"`, `"paperswithcode_id"`, `"private"`, `"siblings"`, `"sha"`, `"tags"`, `"trendingScore"`,`"usedStorage"`, `"resourceGroup"` and `"xetEnabled"`. @@ -2711,7 +2707,7 @@ def dataset_info( if revision is None else (f"{self.endpoint}/api/datasets/{repo_id}/revision/{quote(revision, safe='')}") ) - params: Dict = {} + params: dict = {} if files_metadata: params["blobs"] = True if expand: @@ -2730,7 +2726,7 @@ def space_info( revision: Optional[str] = None, timeout: Optional[float] = None, files_metadata: bool = False, - expand: Optional[List[ExpandSpaceProperty_T]] = None, + expand: Optional[list[ExpandSpaceProperty_T]] = None, token: Union[bool, str, None] = None, ) -> SpaceInfo: """ @@ -2750,7 +2746,7 @@ def space_info( files_metadata (`bool`, *optional*): Whether or not to retrieve metadata for files in the repository (size, LFS metadata, etc). Defaults to `False`. - expand (`List[ExpandSpaceProperty_T]`, *optional*): + expand (`list[ExpandSpaceProperty_T]`, *optional*): List properties to return in the response. When used, only the properties in the list will be returned. This parameter cannot be used if `full` is passed. Possible values are `"author"`, `"cardData"`, `"createdAt"`, `"datasets"`, `"disabled"`, `"lastModified"`, `"likes"`, `"models"`, `"private"`, `"runtime"`, `"sdk"`, `"siblings"`, `"sha"`, `"subdomain"`, `"tags"`, `"trendingScore"`, `"usedStorage"`, `"resourceGroup"` and `"xetEnabled"`. @@ -2784,7 +2780,7 @@ def space_info( if revision is None else (f"{self.endpoint}/api/spaces/{repo_id}/revision/{quote(revision, safe='')}") ) - params: Dict = {} + params: dict = {} if files_metadata: params["blobs"] = True if expand: @@ -3026,7 +3022,7 @@ def list_repo_files( revision: Optional[str] = None, repo_type: Optional[str] = None, token: Union[str, bool, None] = None, - ) -> List[str]: + ) -> list[str]: """ Get the list of files in a given repo. @@ -3045,7 +3041,7 @@ def list_repo_files( To disable authentication, pass `False`. Returns: - `List[str]`: the list of files in a given repository. + `list[str]`: the list of files in a given repository. """ return [ f.rfilename @@ -3247,7 +3243,7 @@ def list_repo_refs( hf_raise_for_status(response) data = response.json() - def _format_as_git_ref_info(item: Dict) -> GitRefInfo: + def _format_as_git_ref_info(item: dict) -> GitRefInfo: return GitRefInfo(name=item["name"], ref=item["ref"], target_commit=item["targetCommit"]) return GitRefs( @@ -3268,7 +3264,7 @@ def list_repo_commits( token: Union[bool, str, None] = None, revision: Optional[str] = None, formatted: bool = False, - ) -> List[GitCommitInfo]: + ) -> list[GitCommitInfo]: """ Get the list of commits of a given revision for a repo on the Hub. @@ -3315,7 +3311,7 @@ def list_repo_commits( ``` Returns: - List[[`GitCommitInfo`]]: list of objects containing information about the commits for a repo on the Hub. + list[[`GitCommitInfo`]]: list of objects containing information about the commits for a repo on the Hub. Raises: [`~utils.RepositoryNotFoundError`]: @@ -3349,20 +3345,20 @@ def list_repo_commits( def get_paths_info( self, repo_id: str, - paths: Union[List[str], str], + paths: Union[list[str], str], *, expand: bool = False, revision: Optional[str] = None, repo_type: Optional[str] = None, token: Union[str, bool, None] = None, - ) -> List[Union[RepoFile, RepoFolder]]: + ) -> list[Union[RepoFile, RepoFolder]]: """ Get information about a repo's paths. Args: repo_id (`str`): A namespace (user or an organization) and a repo name separated by a `/`. - paths (`Union[List[str], str]`, *optional*): + paths (`Union[list[str], str]`, *optional*): The paths to get information about. If a path do not exist, it is ignored without raising an exception. expand (`bool`, *optional*, defaults to `False`): @@ -3382,7 +3378,7 @@ def get_paths_info( To disable authentication, pass `False`. Returns: - `List[Union[RepoFile, RepoFolder]]`: + `list[Union[RepoFile, RepoFolder]]`: The information about the paths, as a list of [`RepoFile`] and [`RepoFolder`] objects. Raises: @@ -3647,8 +3643,8 @@ def create_repo( space_hardware: Optional[SpaceHardware] = None, space_storage: Optional[SpaceStorage] = None, space_sleep_time: Optional[int] = None, - space_secrets: Optional[List[Dict[str, str]]] = None, - space_variables: Optional[List[Dict[str, str]]] = None, + space_secrets: Optional[list[dict[str, str]]] = None, + space_variables: Optional[list[dict[str, str]]] = None, ) -> RepoUrl: """Create an empty repo on the HuggingFace Hub. @@ -3685,10 +3681,10 @@ def create_repo( your Space to sleep (default behavior for upgraded hardware). For free hardware, you can't configure the sleep time (value is fixed to 48 hours of inactivity). See https://huggingface.co/docs/hub/spaces-gpus#sleep-time for more details. - space_secrets (`List[Dict[str, str]]`, *optional*): + space_secrets (`list[dict[str, str]]`, *optional*): A list of secret keys to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional. For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets. - space_variables (`List[Dict[str, str]]`, *optional*): + space_variables (`list[dict[str, str]]`, *optional*): A list of public environment variables to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional. For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets-and-environment-variables. @@ -3703,7 +3699,7 @@ def create_repo( if repo_type not in constants.REPO_TYPES: raise ValueError("Invalid repo type") - json: Dict[str, Any] = {"name": name, "organization": organization} + json: dict[str, Any] = {"name": name, "organization": organization} if private is not None: json["private"] = private if repo_type is not None: @@ -3841,7 +3837,7 @@ def update_repo_visibility( *, token: Union[str, bool, None] = None, repo_type: Optional[str] = None, - ) -> Dict[str, bool]: + ) -> dict[str, bool]: """Update the visibility setting of a repository. Deprecated. Use `update_repo_settings` instead. @@ -3942,7 +3938,7 @@ def update_repo_settings( repo_type = constants.REPO_TYPE_MODEL # default repo type # Prepare the JSON payload for the PUT request - payload: Dict = {} + payload: dict = {} if gated is not None: if gated not in ["auto", "manual", False]: @@ -4760,9 +4756,9 @@ def upload_folder( # type: ignore revision: Optional[str] = None, create_pr: Optional[bool] = None, parent_commit: Optional[str] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, - delete_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, + delete_patterns: Optional[Union[list[str], str]] = None, run_as_future: Literal[False] = ..., ) -> CommitInfo: ... @@ -4780,9 +4776,9 @@ def upload_folder( # type: ignore revision: Optional[str] = None, create_pr: Optional[bool] = None, parent_commit: Optional[str] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, - delete_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, + delete_patterns: Optional[Union[list[str], str]] = None, run_as_future: Literal[True] = ..., ) -> Future[CommitInfo]: ... @@ -4801,9 +4797,9 @@ def upload_folder( revision: Optional[str] = None, create_pr: Optional[bool] = None, parent_commit: Optional[str] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, - delete_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, + delete_patterns: Optional[Union[list[str], str]] = None, run_as_future: bool = False, ) -> Union[CommitInfo, Future[CommitInfo]]: """ @@ -4865,11 +4861,11 @@ def upload_folder( If specified and `create_pr` is `True`, the pull request will be created from `parent_commit`. Specifying `parent_commit` ensures the repo has not changed before committing the changes, and can be especially useful if the repo is updated / committed to concurrently. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are uploaded. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not uploaded. - delete_patterns (`List[str]` or `str`, *optional*): + delete_patterns (`list[str]` or `str`, *optional*): If provided, remote files matching any of the patterns will be deleted from the repo while committing new files. This is useful if you don't know which files have already been uploaded. Note: to avoid discrepancies the `.gitattributes` file is not deleted even if it matches the pattern. @@ -5113,7 +5109,7 @@ def delete_file( def delete_files( self, repo_id: str, - delete_patterns: List[str], + delete_patterns: list[str], *, token: Union[bool, str, None] = None, repo_type: Optional[str] = None, @@ -5133,7 +5129,7 @@ def delete_files( repo_id (`str`): The repository from which the folder will be deleted, for example: `"username/custom_transformers"` - delete_patterns (`List[str]`): + delete_patterns (`list[str]`): List of files or folders to delete. Each string can either be a file path, a folder path or a Unix shell-style wildcard. E.g. `["file.txt", "folder/", "data/*.parquet"]` @@ -5261,8 +5257,8 @@ def upload_large_folder( repo_type: str, # Repo type is required! revision: Optional[str] = None, private: Optional[bool] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, num_workers: Optional[int] = None, print_report: bool = True, print_report_every: int = 60, @@ -5290,9 +5286,9 @@ def upload_large_folder( private (`bool`, `optional`): Whether the repository should be private. If `None` (default), the repo will be public unless the organization's default is private. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are uploaded. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not uploaded. num_workers (`int`, *optional*): Number of workers to start. Defaults to `os.cpu_count() - 2` (minimum 2). @@ -5562,10 +5558,10 @@ def snapshot_download( force_download: bool = False, token: Union[bool, str, None] = None, local_files_only: bool = False, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, max_workers: int = 8, - tqdm_class: Optional[Type[base_tqdm]] = None, + tqdm_class: Optional[type[base_tqdm]] = None, # Deprecated args local_dir_use_symlinks: Union[bool, Literal["auto"]] = "auto", resume_download: Optional[bool] = None, @@ -5611,9 +5607,9 @@ def snapshot_download( local_files_only (`bool`, *optional*, defaults to `False`): If `True`, avoid downloading the file and return the path to the local cached file if it exists. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are downloaded. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not downloaded. max_workers (`int`, *optional*): Number of concurrent threads to download files (1 thread = 1 file download). @@ -6276,7 +6272,7 @@ def get_repo_discussions( headers = self._build_hf_headers(token=token) path = f"{self.endpoint}/api/{repo_type}s/{repo_id}/discussions" - params: Dict[str, Union[str, int]] = {} + params: dict[str, Union[str, int]] = {} if discussion_type is not None: params["type"] = discussion_type if discussion_status is not None: @@ -6785,7 +6781,7 @@ def change_discussion_status( """ if new_status not in ["open", "closed"]: raise ValueError("Invalid status, valid statuses are: 'open' and 'closed'") - body: Dict[str, str] = {"status": new_status} + body: dict[str, str] = {"status": new_status} if comment and comment.strip(): body["comment"] = comment.strip() resp = self._post_discussion_changes( @@ -7045,7 +7041,7 @@ def delete_space_secret(self, repo_id: str, key: str, *, token: Union[bool, str, hf_raise_for_status(r) @validate_hf_hub_args - def get_space_variables(self, repo_id: str, *, token: Union[bool, str, None] = None) -> Dict[str, SpaceVariable]: + def get_space_variables(self, repo_id: str, *, token: Union[bool, str, None] = None) -> dict[str, SpaceVariable]: """Gets all variables from a Space. Variables allow to set environment variables to a Space without hardcoding them. @@ -7076,7 +7072,7 @@ def add_space_variable( *, description: Optional[str] = None, token: Union[bool, str, None] = None, - ) -> Dict[str, SpaceVariable]: + ) -> dict[str, SpaceVariable]: """Adds or updates a variable in a Space. Variables allow to set environment variables to a Space without hardcoding them. @@ -7111,7 +7107,7 @@ def add_space_variable( @validate_hf_hub_args def delete_space_variable( self, repo_id: str, key: str, *, token: Union[bool, str, None] = None - ) -> Dict[str, SpaceVariable]: + ) -> dict[str, SpaceVariable]: """Deletes a variable from a Space. Variables allow to set environment variables to a Space without hardcoding them. @@ -7200,7 +7196,7 @@ def request_space_hardware( " you want to set a custom sleep time, you need to upgrade to a paid Hardware.", UserWarning, ) - payload: Dict[str, Any] = {"flavor": hardware} + payload: dict[str, Any] = {"flavor": hardware} if sleep_time is not None: payload["sleepTimeSeconds"] = sleep_time r = get_session().post( @@ -7359,8 +7355,8 @@ def duplicate_space( hardware: Optional[SpaceHardware] = None, storage: Optional[SpaceStorage] = None, sleep_time: Optional[int] = None, - secrets: Optional[List[Dict[str, str]]] = None, - variables: Optional[List[Dict[str, str]]] = None, + secrets: Optional[list[dict[str, str]]] = None, + variables: Optional[list[dict[str, str]]] = None, ) -> RepoUrl: """Duplicate a Space. @@ -7391,10 +7387,10 @@ def duplicate_space( your Space to sleep (default behavior for upgraded hardware). For free hardware, you can't configure the sleep time (value is fixed to 48 hours of inactivity). See https://huggingface.co/docs/hub/spaces-gpus#sleep-time for more details. - secrets (`List[Dict[str, str]]`, *optional*): + secrets (`list[dict[str, str]]`, *optional*): A list of secret keys to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional. For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets. - variables (`List[Dict[str, str]]`, *optional*): + variables (`list[dict[str, str]]`, *optional*): A list of public environment variables to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional. For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets-and-environment-variables. @@ -7434,7 +7430,7 @@ def duplicate_space( to_repo_name = parsed_to_id.repo_name if to_id is not None else RepoUrl(from_id).repo_name # type: ignore # repository must be a valid repo_id (namespace/repo_name). - payload: Dict[str, Any] = {"repository": f"{to_namespace}/{to_repo_name}"} + payload: dict[str, Any] = {"repository": f"{to_namespace}/{to_repo_name}"} keys = ["private", "hardware", "storageTier", "sleepTimeSeconds", "secrets", "variables"] values = [private, hardware, storage, sleep_time, secrets, variables] @@ -7495,7 +7491,7 @@ def request_space_storage( """ - payload: Dict[str, SpaceStorage] = {"tier": storage} + payload: dict[str, SpaceStorage] = {"tier": storage} r = get_session().post( f"{self.endpoint}/api/spaces/{repo_id}/storage", headers=self._build_hf_headers(token=token), @@ -7541,7 +7537,7 @@ def delete_space_storage( def list_inference_endpoints( self, namespace: Optional[str] = None, *, token: Union[bool, str, None] = None - ) -> List[InferenceEndpoint]: + ) -> list[InferenceEndpoint]: """Lists all inference endpoints for the given namespace. Args: @@ -7555,7 +7551,7 @@ def list_inference_endpoints( To disable authentication, pass `False`. Returns: - List[`InferenceEndpoint`]: A list of all inference endpoints for the given namespace. + list[`InferenceEndpoint`]: A list of all inference endpoints for the given namespace. Example: ```python @@ -7570,7 +7566,7 @@ def list_inference_endpoints( user = self.whoami(token=token) # List personal endpoints first - endpoints: List[InferenceEndpoint] = list_inference_endpoints(namespace=self._get_namespace(token=token)) + endpoints: list[InferenceEndpoint] = list_inference_endpoints(namespace=self._get_namespace(token=token)) # Then list endpoints for all orgs the user belongs to and ignore 401 errors (no billing or no access) for org in user.get("orgs", []): @@ -7614,14 +7610,14 @@ def create_inference_endpoint( scale_to_zero_timeout: Optional[int] = None, revision: Optional[str] = None, task: Optional[str] = None, - custom_image: Optional[Dict] = None, - env: Optional[Dict[str, str]] = None, - secrets: Optional[Dict[str, str]] = None, + custom_image: Optional[dict] = None, + env: Optional[dict[str, str]] = None, + secrets: Optional[dict[str, str]] = None, type: InferenceEndpointType = InferenceEndpointType.PROTECTED, domain: Optional[str] = None, path: Optional[str] = None, cache_http_responses: Optional[bool] = None, - tags: Optional[List[str]] = None, + tags: Optional[list[str]] = None, namespace: Optional[str] = None, token: Union[bool, str, None] = None, ) -> InferenceEndpoint: @@ -7658,12 +7654,12 @@ def create_inference_endpoint( The specific model revision to deploy on the Inference Endpoint (e.g. `"6c0e6080953db56375760c0471a8c5f2929baf11"`). task (`str`, *optional*): The task on which to deploy the model (e.g. `"text-classification"`). - custom_image (`Dict`, *optional*): + custom_image (`dict`, *optional*): A custom Docker image to use for the Inference Endpoint. This is useful if you want to deploy an Inference Endpoint running on the `text-generation-inference` (TGI) framework (see examples). - env (`Dict[str, str]`, *optional*): + env (`dict[str, str]`, *optional*): Non-secret environment variables to inject in the container environment. - secrets (`Dict[str, str]`, *optional*): + secrets (`dict[str, str]`, *optional*): Secret values to inject in the container environment. type ([`InferenceEndpointType]`, *optional*): The type of the Inference Endpoint, which can be `"protected"` (default), `"public"` or `"private"`. @@ -7673,7 +7669,7 @@ def create_inference_endpoint( The custom path to the deployed model, should start with a `/` (e.g. `"/models/google-bert/bert-base-uncased"`). cache_http_responses (`bool`, *optional*): Whether to cache HTTP responses from the Inference Endpoint. Defaults to `False`. - tags (`List[str]`, *optional*): + tags (`list[str]`, *optional*): A list of tags to associate with the Inference Endpoint. namespace (`str`, *optional*): The namespace where the Inference Endpoint will be created. Defaults to the current user's namespace. @@ -7776,7 +7772,7 @@ def create_inference_endpoint( else: image = {"huggingface": {}} - payload: Dict = { + payload: dict = { "accountId": account_id, "compute": { "accelerator": accelerator, @@ -7865,7 +7861,7 @@ def create_inference_endpoint_from_catalog( """ token = token or self.token or get_token() - payload: Dict = { + payload: dict = { "namespace": namespace or self._get_namespace(token=token), "repoId": repo_id, } @@ -7883,7 +7879,7 @@ def create_inference_endpoint_from_catalog( @experimental @validate_hf_hub_args - def list_inference_catalog(self, *, token: Union[bool, str, None] = None) -> List[str]: + def list_inference_catalog(self, *, token: Union[bool, str, None] = None) -> list[str]: """List models available in the Hugging Face Inference Catalog. The goal of the Inference Catalog is to provide a curated list of models that are optimized for inference @@ -7899,7 +7895,7 @@ def list_inference_catalog(self, *, token: Union[bool, str, None] = None) -> Lis https://huggingface.co/docs/huggingface_hub/quick-start#authentication). Returns: - List[`str`]: A list of model IDs available in the catalog. + list[`str`]: A list of model IDs available in the catalog. `list_inference_catalog` is experimental. Its API is subject to change in the future. Please provide feedback @@ -7977,15 +7973,15 @@ def update_inference_endpoint( framework: Optional[str] = None, revision: Optional[str] = None, task: Optional[str] = None, - custom_image: Optional[Dict] = None, - env: Optional[Dict[str, str]] = None, - secrets: Optional[Dict[str, str]] = None, + custom_image: Optional[dict] = None, + env: Optional[dict[str, str]] = None, + secrets: Optional[dict[str, str]] = None, # Route update domain: Optional[str] = None, path: Optional[str] = None, # Other cache_http_responses: Optional[bool] = None, - tags: Optional[List[str]] = None, + tags: Optional[list[str]] = None, namespace: Optional[str] = None, token: Union[bool, str, None] = None, ) -> InferenceEndpoint: @@ -8021,12 +8017,12 @@ def update_inference_endpoint( The specific model revision to deploy on the Inference Endpoint (e.g. `"6c0e6080953db56375760c0471a8c5f2929baf11"`). task (`str`, *optional*): The task on which to deploy the model (e.g. `"text-classification"`). - custom_image (`Dict`, *optional*): + custom_image (`dict`, *optional*): A custom Docker image to use for the Inference Endpoint. This is useful if you want to deploy an Inference Endpoint running on the `text-generation-inference` (TGI) framework (see examples). - env (`Dict[str, str]`, *optional*): + env (`dict[str, str]`, *optional*): Non-secret environment variables to inject in the container environment - secrets (`Dict[str, str]`, *optional*): + secrets (`dict[str, str]`, *optional*): Secret values to inject in the container environment. domain (`str`, *optional*): @@ -8036,7 +8032,7 @@ def update_inference_endpoint( cache_http_responses (`bool`, *optional*): Whether to cache HTTP responses from the Inference Endpoint. - tags (`List[str]`, *optional*): + tags (`list[str]`, *optional*): A list of tags to associate with the Inference Endpoint. namespace (`str`, *optional*): @@ -8053,7 +8049,7 @@ def update_inference_endpoint( namespace = namespace or self._get_namespace(token=token) # Populate only the fields that are not None - payload: Dict = defaultdict(lambda: defaultdict(dict)) + payload: dict = defaultdict(lambda: defaultdict(dict)) if accelerator is not None: payload["compute"]["accelerator"] = accelerator if instance_size is not None: @@ -8260,8 +8256,8 @@ def _get_namespace(self, token: Union[bool, str, None] = None) -> str: def list_collections( self, *, - owner: Union[List[str], str, None] = None, - item: Union[List[str], str, None] = None, + owner: Union[list[str], str, None] = None, + item: Union[list[str], str, None] = None, sort: Optional[Literal["lastModified", "trending", "upvotes"]] = None, limit: Optional[int] = None, token: Union[bool, str, None] = None, @@ -8276,9 +8272,9 @@ def list_collections( Args: - owner (`List[str]` or `str`, *optional*): + owner (`list[str]` or `str`, *optional*): Filter by owner's username. - item (`List[str]` or `str`, *optional*): + item (`list[str]` or `str`, *optional*): Filter collections containing a particular items. Example: `"models/teknium/OpenHermes-2.5-Mistral-7B"`, `"datasets/squad"` or `"papers/2311.12983"`. sort (`Literal["lastModified", "trending", "upvotes"]`, *optional*): Sort collections by last modified, trending or upvotes. @@ -8296,7 +8292,7 @@ def list_collections( # Construct the API endpoint path = f"{self.endpoint}/api/collections" headers = self._build_hf_headers(token=token) - params: Dict = {} + params: dict = {} if owner is not None: params.update({"owner": owner}) if item is not None: @@ -8595,7 +8591,7 @@ def add_collection_item( (...) ``` """ - payload: Dict[str, Any] = {"item": {"id": item_id, "type": item_type}} + payload: dict[str, Any] = {"item": {"id": item_id, "type": item_type}} if note is not None: payload["note"] = note r = get_session().post( @@ -8725,7 +8721,7 @@ def delete_collection_item( @validate_hf_hub_args def list_pending_access_requests( self, repo_id: str, *, repo_type: Optional[str] = None, token: Union[bool, str, None] = None - ) -> List[AccessRequest]: + ) -> list[AccessRequest]: """ Get pending access requests for a given gated repo. @@ -8748,7 +8744,7 @@ def list_pending_access_requests( To disable authentication, pass `False`. Returns: - `List[AccessRequest]`: A list of [`AccessRequest`] objects. Each time contains a `username`, `email`, + `list[AccessRequest]`: A list of [`AccessRequest`] objects. Each time contains a `username`, `email`, `status` and `timestamp` attribute. If the gated repo has a custom form, the `fields` attribute will be populated with user's answers. @@ -8789,7 +8785,7 @@ def list_pending_access_requests( @validate_hf_hub_args def list_accepted_access_requests( self, repo_id: str, *, repo_type: Optional[str] = None, token: Union[bool, str, None] = None - ) -> List[AccessRequest]: + ) -> list[AccessRequest]: """ Get accepted access requests for a given gated repo. @@ -8814,7 +8810,7 @@ def list_accepted_access_requests( To disable authentication, pass `False`. Returns: - `List[AccessRequest]`: A list of [`AccessRequest`] objects. Each time contains a `username`, `email`, + `list[AccessRequest]`: A list of [`AccessRequest`] objects. Each time contains a `username`, `email`, `status` and `timestamp` attribute. If the gated repo has a custom form, the `fields` attribute will be populated with user's answers. @@ -8851,7 +8847,7 @@ def list_accepted_access_requests( @validate_hf_hub_args def list_rejected_access_requests( self, repo_id: str, *, repo_type: Optional[str] = None, token: Union[bool, str, None] = None - ) -> List[AccessRequest]: + ) -> list[AccessRequest]: """ Get rejected access requests for a given gated repo. @@ -8876,7 +8872,7 @@ def list_rejected_access_requests( To disable authentication, pass `False`. Returns: - `List[AccessRequest]`: A list of [`AccessRequest`] objects. Each time contains a `username`, `email`, + `list[AccessRequest]`: A list of [`AccessRequest`] objects. Each time contains a `username`, `email`, `status` and `timestamp` attribute. If the gated repo has a custom form, the `fields` attribute will be populated with user's answers. @@ -8916,7 +8912,7 @@ def _list_access_requests( status: Literal["accepted", "rejected", "pending"], repo_type: Optional[str] = None, token: Union[bool, str, None] = None, - ) -> List[AccessRequest]: + ) -> 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 is None: @@ -9209,7 +9205,7 @@ def get_webhook(self, webhook_id: str, *, token: Union[bool, str, None] = None) return webhook @validate_hf_hub_args - def list_webhooks(self, *, token: Union[bool, str, None] = None) -> List[WebhookInfo]: + def list_webhooks(self, *, token: Union[bool, str, None] = None) -> list[WebhookInfo]: """List all configured webhooks. Args: @@ -9219,7 +9215,7 @@ def list_webhooks(self, *, token: Union[bool, str, None] = None) -> List[Webhook To disable authentication, pass `False`. Returns: - `List[WebhookInfo]`: + `list[WebhookInfo]`: List of webhook info objects. Example: @@ -9263,8 +9259,8 @@ def create_webhook( self, *, url: str, - watched: List[Union[Dict, WebhookWatchedItem]], - domains: Optional[List[constants.WEBHOOK_DOMAIN_T]] = None, + watched: list[Union[dict, WebhookWatchedItem]], + domains: Optional[list[constants.WEBHOOK_DOMAIN_T]] = None, secret: Optional[str] = None, token: Union[bool, str, None] = None, ) -> WebhookInfo: @@ -9273,10 +9269,10 @@ def create_webhook( Args: url (`str`): URL to send the payload to. - watched (`List[WebhookWatchedItem]`): + watched (`list[WebhookWatchedItem]`): List of [`WebhookWatchedItem`] to be watched by the webhook. It can be users, orgs, models, datasets or spaces. Watched items can also be provided as plain dictionaries. - domains (`List[Literal["repo", "discussion"]]`, optional): + domains (`list[Literal["repo", "discussion"]]`, optional): List of domains to watch. It can be "repo", "discussion" or both. secret (`str`, optional): A secret to sign the payload with. @@ -9337,8 +9333,8 @@ def update_webhook( webhook_id: str, *, url: Optional[str] = None, - watched: Optional[List[Union[Dict, WebhookWatchedItem]]] = None, - domains: Optional[List[constants.WEBHOOK_DOMAIN_T]] = None, + watched: Optional[list[Union[dict, WebhookWatchedItem]]] = None, + domains: Optional[list[constants.WEBHOOK_DOMAIN_T]] = None, secret: Optional[str] = None, token: Union[bool, str, None] = None, ) -> WebhookInfo: @@ -9349,10 +9345,10 @@ def update_webhook( The unique identifier of the webhook to be updated. url (`str`, optional): The URL to which the payload will be sent. - watched (`List[WebhookWatchedItem]`, optional): + watched (`list[WebhookWatchedItem]`, optional): List of items to watch. It can be users, orgs, models, datasets, or spaces. Refer to [`WebhookWatchedItem`] for more details. Watched items can also be provided as plain dictionaries. - domains (`List[Literal["repo", "discussion"]]`, optional): + domains (`list[Literal["repo", "discussion"]]`, optional): The domains to watch. This can include "repo", "discussion", or both. secret (`str`, optional): A secret to sign the payload with, providing an additional layer of security. @@ -9548,8 +9544,8 @@ def _build_hf_headers( token: Union[bool, str, None] = None, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Union[Dict, str, None] = None, - ) -> Dict[str, str]: + user_agent: Union[dict, str, None] = None, + ) -> dict[str, str]: """ Alias for [`build_hf_headers`] that uses the token from [`HfApi`] client when `token` is not provided. @@ -9571,9 +9567,9 @@ def _prepare_folder_deletions( repo_type: Optional[str], revision: Optional[str], path_in_repo: str, - delete_patterns: Optional[Union[List[str], str]], + delete_patterns: Optional[Union[list[str], str]], token: Union[bool, str, None] = None, - ) -> List[CommitOperationDelete]: + ) -> list[CommitOperationDelete]: """Generate the list of Delete operations for a commit to delete files from a repo. List remote files and match them against the `delete_patterns` constraints. Returns a list of [`CommitOperationDelete`] @@ -9609,11 +9605,11 @@ def _prepare_upload_folder_additions( self, folder_path: Union[str, Path], path_in_repo: str, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, repo_type: Optional[str] = None, token: Union[bool, str, None] = None, - ) -> List[CommitOperationAdd]: + ) -> list[CommitOperationAdd]: """Generate the list of Add operations for a commit to upload a folder. Files not matching the `allow_patterns` (allowlist) and `ignore_patterns` (denylist) @@ -9955,9 +9951,9 @@ def run_job( self, *, image: str, - command: List[str], - env: Optional[Dict[str, Any]] = None, - secrets: Optional[Dict[str, Any]] = None, + command: list[str], + env: Optional[dict[str, Any]] = None, + secrets: Optional[dict[str, Any]] = None, flavor: Optional[SpaceHardware] = None, timeout: Optional[Union[int, float, str]] = None, namespace: Optional[str] = None, @@ -9972,13 +9968,13 @@ def run_job( Examples: `"ubuntu"`, `"python:3.12"`, `"pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel"`. Example with an image from a Space: `"hf.co/spaces/lhoestq/duckdb"`. - command (`List[str]`): + command (`list[str]`): The command to run. Example: `["echo", "hello"]`. - env (`Dict[str, Any]`, *optional*): + env (`dict[str, Any]`, *optional*): Defines the environment variables for the Job. - secrets (`Dict[str, Any]`, *optional*): + secrets (`dict[str, Any]`, *optional*): Defines the secret environment variables for the Job. flavor (`str`, *optional*): @@ -10131,7 +10127,7 @@ def list_jobs( timeout: Optional[int] = None, namespace: Optional[str] = None, token: Union[bool, str, None] = None, - ) -> List[JobInfo]: + ) -> list[JobInfo]: """ List compute Jobs on Hugging Face infrastructure. @@ -10242,12 +10238,12 @@ def run_uv_job( self, script: str, *, - script_args: Optional[List[str]] = None, - dependencies: Optional[List[str]] = None, + script_args: Optional[list[str]] = None, + dependencies: Optional[list[str]] = None, python: Optional[str] = None, image: Optional[str] = None, - env: Optional[Dict[str, Any]] = None, - secrets: Optional[Dict[str, Any]] = None, + env: Optional[dict[str, Any]] = None, + secrets: Optional[dict[str, Any]] = None, flavor: Optional[SpaceHardware] = None, timeout: Optional[Union[int, float, str]] = None, namespace: Optional[str] = None, @@ -10261,10 +10257,10 @@ def run_uv_job( script (`str`): Path or URL of the UV script, or a command. - script_args (`List[str]`, *optional*) + script_args (`list[str]`, *optional*) Arguments to pass to the script or command. - dependencies (`List[str]`, *optional*) + dependencies (`list[str]`, *optional*) Dependencies to use to run the UV script. python (`str`, *optional*) @@ -10273,10 +10269,10 @@ def run_uv_job( image (`str`, *optional*, defaults to "ghcr.io/astral-sh/uv:python3.12-bookworm"): Use a custom Docker image with `uv` installed. - env (`Dict[str, Any]`, *optional*): + env (`dict[str, Any]`, *optional*): Defines the environment variables for the Job. - secrets (`Dict[str, Any]`, *optional*): + secrets (`dict[str, Any]`, *optional*): Defines the secret environment variables for the Job. flavor (`str`, *optional*): @@ -10356,12 +10352,12 @@ def create_scheduled_job( self, *, image: str, - command: List[str], + command: list[str], schedule: str, suspend: Optional[bool] = None, concurrency: Optional[bool] = None, - env: Optional[Dict[str, Any]] = None, - secrets: Optional[Dict[str, Any]] = None, + env: Optional[dict[str, Any]] = None, + secrets: Optional[dict[str, Any]] = None, flavor: Optional[SpaceHardware] = None, timeout: Optional[Union[int, float, str]] = None, namespace: Optional[str] = None, @@ -10376,7 +10372,7 @@ def create_scheduled_job( Examples: `"ubuntu"`, `"python:3.12"`, `"pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel"`. Example with an image from a Space: `"hf.co/spaces/lhoestq/duckdb"`. - command (`List[str]`): + command (`list[str]`): The command to run. Example: `["echo", "hello"]`. schedule (`str`): @@ -10389,10 +10385,10 @@ def create_scheduled_job( concurrency (`bool`, *optional*): If True, multiple instances of this Job can run concurrently. Defaults to False. - env (`Dict[str, Any]`, *optional*): + env (`dict[str, Any]`, *optional*): Defines the environment variables for the Job. - secrets (`Dict[str, Any]`, *optional*): + secrets (`dict[str, Any]`, *optional*): Defines the secret environment variables for the Job. flavor (`str`, *optional*): @@ -10448,7 +10444,7 @@ def create_scheduled_job( flavor=flavor, timeout=timeout, ) - input_json: Dict[str, Any] = { + input_json: dict[str, Any] = { "jobSpec": job_spec, "schedule": schedule, } @@ -10471,7 +10467,7 @@ def list_scheduled_jobs( timeout: Optional[int] = None, namespace: Optional[str] = None, token: Union[bool, str, None] = None, - ) -> List[ScheduledJobInfo]: + ) -> list[ScheduledJobInfo]: """ List scheduled compute Jobs on Hugging Face infrastructure. @@ -10629,15 +10625,15 @@ def create_scheduled_uv_job( self, script: str, *, - script_args: Optional[List[str]] = None, + script_args: Optional[list[str]] = None, schedule: str, suspend: Optional[bool] = None, concurrency: Optional[bool] = None, - dependencies: Optional[List[str]] = None, + dependencies: Optional[list[str]] = None, python: Optional[str] = None, image: Optional[str] = None, - env: Optional[Dict[str, Any]] = None, - secrets: Optional[Dict[str, Any]] = None, + env: Optional[dict[str, Any]] = None, + secrets: Optional[dict[str, Any]] = None, flavor: Optional[SpaceHardware] = None, timeout: Optional[Union[int, float, str]] = None, namespace: Optional[str] = None, @@ -10651,7 +10647,7 @@ def create_scheduled_uv_job( script (`str`): Path or URL of the UV script, or a command. - script_args (`List[str]`, *optional*) + script_args (`list[str]`, *optional*) Arguments to pass to the script, or a command. schedule (`str`): @@ -10664,7 +10660,7 @@ def create_scheduled_uv_job( concurrency (`bool`, *optional*): If True, multiple instances of this Job can run concurrently. Defaults to False. - dependencies (`List[str]`, *optional*) + dependencies (`list[str]`, *optional*) Dependencies to use to run the UV script. python (`str`, *optional*) @@ -10673,10 +10669,10 @@ def create_scheduled_uv_job( image (`str`, *optional*, defaults to "ghcr.io/astral-sh/uv:python3.12-bookworm"): Use a custom Docker image with `uv` installed. - env (`Dict[str, Any]`, *optional*): + env (`dict[str, Any]`, *optional*): Defines the environment variables for the Job. - secrets (`Dict[str, Any]`, *optional*): + secrets (`dict[str, Any]`, *optional*): Defines the secret environment variables for the Job. flavor (`str`, *optional*): @@ -10756,15 +10752,15 @@ def _create_uv_command_env_and_secrets( self, *, script: str, - script_args: Optional[List[str]], - dependencies: Optional[List[str]], + script_args: Optional[list[str]], + dependencies: Optional[list[str]], python: Optional[str], - env: Optional[Dict[str, Any]], - secrets: Optional[Dict[str, Any]], + env: Optional[dict[str, Any]], + secrets: Optional[dict[str, Any]], namespace: Optional[str], token: Union[bool, str, None], _repo: Optional[str], - ) -> Tuple[List[str], Dict[str, Any], Dict[str, Any]]: + ) -> tuple[list[str], dict[str, Any], dict[str, Any]]: env = env or {} secrets = secrets or {} diff --git a/src/huggingface_hub/hf_file_system.py b/src/huggingface_hub/hf_file_system.py index e82365e3ce..ff3bb02661 100644 --- a/src/huggingface_hub/hf_file_system.py +++ b/src/huggingface_hub/hf_file_system.py @@ -7,7 +7,7 @@ from datetime import datetime from itertools import chain from pathlib import Path -from typing import Any, Dict, Iterator, List, NoReturn, Optional, Tuple, Union +from typing import Any, Iterator, NoReturn, Optional, Union from urllib.parse import quote, unquote import fsspec @@ -114,13 +114,13 @@ def __init__( # Maps (repo_type, repo_id, revision) to a 2-tuple with: # * the 1st element indicating whether the repositoy and the revision exist # * the 2nd element being the exception raised if the repository or revision doesn't exist - self._repo_and_revision_exists_cache: Dict[ - Tuple[str, str, Optional[str]], Tuple[bool, Optional[Exception]] + self._repo_and_revision_exists_cache: dict[ + tuple[str, str, Optional[str]], tuple[bool, Optional[Exception]] ] = {} def _repo_and_revision_exist( self, repo_type: str, repo_id: str, revision: Optional[str] - ) -> Tuple[bool, Optional[Exception]]: + ) -> tuple[bool, Optional[Exception]]: if (repo_type, repo_id, revision) not in self._repo_and_revision_exists_cache: try: self._api.repo_info( @@ -339,7 +339,7 @@ def rm( def ls( self, path: str, detail: bool = True, refresh: bool = False, revision: Optional[str] = None, **kwargs - ) -> List[Union[str, Dict[str, Any]]]: + ) -> list[Union[str, dict[str, Any]]]: """ List the contents of a directory. @@ -363,7 +363,7 @@ def ls( The git revision to list from. Returns: - `List[Union[str, Dict[str, Any]]]`: List of file paths (if detail=False) or list of file information + `list[Union[str, dict[str, Any]]]`: List of file paths (if detail=False) or list of file information dictionaries (if detail=True). """ resolved_path = self.resolve_path(path, revision=revision) @@ -484,7 +484,7 @@ def _ls_tree( out.append(cache_path_info) return out - def walk(self, path: str, *args, **kwargs) -> Iterator[Tuple[str, List[str], List[str]]]: + def walk(self, path: str, *args, **kwargs) -> Iterator[tuple[str, list[str], list[str]]]: """ Return all files below the given path. @@ -495,12 +495,12 @@ def walk(self, path: str, *args, **kwargs) -> Iterator[Tuple[str, List[str], Lis Root path to list files from. Returns: - `Iterator[Tuple[str, List[str], List[str]]]`: An iterator of (path, list of directory names, list of file names) tuples. + `Iterator[tuple[str, list[str], list[str]]]`: An iterator of (path, list of directory names, list of file names) tuples. """ path = self.resolve_path(path, revision=kwargs.get("revision")).unresolve() yield from super().walk(path, *args, **kwargs) - def glob(self, path: str, **kwargs) -> List[str]: + def glob(self, path: str, **kwargs) -> list[str]: """ Find files by glob-matching. @@ -511,7 +511,7 @@ def glob(self, path: str, **kwargs) -> List[str]: Path pattern to match. Returns: - `List[str]`: List of paths matching the pattern. + `list[str]`: List of paths matching the pattern. """ path = self.resolve_path(path, revision=kwargs.get("revision")).unresolve() return super().glob(path, **kwargs) @@ -525,7 +525,7 @@ def find( refresh: bool = False, revision: Optional[str] = None, **kwargs, - ) -> Union[List[str], Dict[str, Dict[str, Any]]]: + ) -> Union[list[str], dict[str, dict[str, Any]]]: """ List all files below path. @@ -546,7 +546,7 @@ def find( The git revision to list from. Returns: - `Union[List[str], Dict[str, Dict[str, Any]]]`: List of paths or dict of file information. + `Union[list[str], dict[str, dict[str, Any]]]`: List of paths or dict of file information. """ if maxdepth: return super().find( @@ -651,7 +651,7 @@ def modified(self, path: str, **kwargs) -> datetime: info = self.info(path, **{**kwargs, "expand_info": True}) return info["last_commit"]["date"] - def info(self, path: str, refresh: bool = False, revision: Optional[str] = None, **kwargs) -> Dict[str, Any]: + def info(self, path: str, refresh: bool = False, revision: Optional[str] = None, **kwargs) -> dict[str, Any]: """ Get information about a file or directory. @@ -672,7 +672,7 @@ def info(self, path: str, refresh: bool = False, revision: Optional[str] = None, The git revision to get info from. Returns: - `Dict[str, Any]`: Dictionary containing file information (type, size, commit info, etc.). + `dict[str, Any]`: Dictionary containing file information (type, size, commit info, etc.). """ resolved_path = self.resolve_path(path, revision=revision) diff --git a/src/huggingface_hub/hub_mixin.py b/src/huggingface_hub/hub_mixin.py index d1ddee213f..c297026d35 100644 --- a/src/huggingface_hub/hub_mixin.py +++ b/src/huggingface_hub/hub_mixin.py @@ -3,7 +3,7 @@ import os from dataclasses import Field, asdict, dataclass, is_dataclass from pathlib import Path -from typing import Any, Callable, ClassVar, Dict, List, Optional, Protocol, Tuple, Type, TypeVar, Union +from typing import Any, Callable, ClassVar, Optional, Protocol, Type, TypeVar, Union import packaging.version @@ -38,7 +38,7 @@ # Type alias for dataclass instances, copied from https://github.com/python/typeshed/blob/9f28171658b9ca6c32a7cb93fbb99fc92b17858b/stdlib/_typeshed/__init__.pyi#L349 class DataclassInstance(Protocol): - __dataclass_fields__: ClassVar[Dict[str, Field]] + __dataclass_fields__: ClassVar[dict[str, Field]] # Generic variable that is either ModelHubMixin or a subclass thereof @@ -47,7 +47,7 @@ class DataclassInstance(Protocol): ARGS_T = TypeVar("ARGS_T") ENCODER_T = Callable[[ARGS_T], Any] DECODER_T = Callable[[Any], ARGS_T] -CODER_T = Tuple[ENCODER_T, DECODER_T] +CODER_T = tuple[ENCODER_T, DECODER_T] DEFAULT_MODEL_CARD = """ @@ -96,7 +96,7 @@ class ModelHubMixin: URL of the library documentation. Used to generate model card. model_card_template (`str`, *optional*): Template of the model card. Used to generate model card. Defaults to a generic template. - language (`str` or `List[str]`, *optional*): + language (`str` or `list[str]`, *optional*): Language supported by the library. Used to generate model card. library_name (`str`, *optional*): Name of the library integrating ModelHubMixin. Used to generate model card. @@ -113,9 +113,9 @@ class ModelHubMixin: E.g: "https://coqui.ai/cpml". pipeline_tag (`str`, *optional*): Tag of the pipeline. Used to generate model card. E.g. "text-classification". - tags (`List[str]`, *optional*): + tags (`list[str]`, *optional*): Tags to be added to the model card. Used to generate model card. E.g. ["computer-vision"] - coders (`Dict[Type, Tuple[Callable, Callable]]`, *optional*): + coders (`dict[Type, tuple[Callable, Callable]]`, *optional*): Dictionary of custom types and their encoders/decoders. Used to encode/decode arguments that are not jsonable by default. E.g dataclasses, argparse.Namespace, OmegaConf, etc. @@ -145,7 +145,7 @@ class ModelHubMixin: ... ... @classmethod ... def from_pretrained( - ... cls: Type[T], + ... cls: type[T], ... pretrained_model_name_or_path: Union[str, Path], ... *, ... force_download: bool = False, @@ -187,10 +187,10 @@ class ModelHubMixin: _hub_mixin_info: MixinInfo # ^ information about the library integrating ModelHubMixin (used to generate model card) _hub_mixin_inject_config: bool # whether `_from_pretrained` expects `config` or not - _hub_mixin_init_parameters: Dict[str, inspect.Parameter] # __init__ parameters - _hub_mixin_jsonable_default_values: Dict[str, Any] # default values for __init__ parameters - _hub_mixin_jsonable_custom_types: Tuple[Type, ...] # custom types that can be encoded/decoded - _hub_mixin_coders: Dict[Type, CODER_T] # encoders/decoders for custom types + _hub_mixin_init_parameters: dict[str, inspect.Parameter] # __init__ parameters + _hub_mixin_jsonable_default_values: dict[str, Any] # default values for __init__ parameters + _hub_mixin_jsonable_custom_types: tuple[Type, ...] # custom types that can be encoded/decoded + _hub_mixin_coders: dict[Type, CODER_T] # encoders/decoders for custom types # ^ internal values to handle config def __init_subclass__( @@ -203,16 +203,16 @@ def __init_subclass__( # Model card template model_card_template: str = DEFAULT_MODEL_CARD, # Model card metadata - language: Optional[List[str]] = None, + language: Optional[list[str]] = None, library_name: Optional[str] = None, license: Optional[str] = None, license_name: Optional[str] = None, license_link: Optional[str] = None, pipeline_tag: Optional[str] = None, - tags: Optional[List[str]] = None, + tags: Optional[list[str]] = None, # How to encode/decode arguments with custom type into a JSON config? coders: Optional[ - Dict[Type, CODER_T] + dict[Type, CODER_T] # Key is a type. # Value is a tuple (encoder, decoder). # Example: {MyCustomType: (lambda x: x.value, lambda data: MyCustomType(data))} @@ -287,7 +287,7 @@ def __init_subclass__( } cls._hub_mixin_inject_config = "config" in inspect.signature(cls._from_pretrained).parameters - def __new__(cls: Type[T], *args, **kwargs) -> T: + def __new__(cls: type[T], *args, **kwargs) -> T: """Create a new instance of the class and handle config. 3 cases: @@ -363,7 +363,7 @@ def _encode_arg(cls, arg: Any) -> Any: return arg @classmethod - def _decode_arg(cls, expected_type: Type[ARGS_T], value: Any) -> Optional[ARGS_T]: + def _decode_arg(cls, expected_type: type[ARGS_T], value: Any) -> Optional[ARGS_T]: """Decode a JSON serializable value into an argument.""" if is_simple_optional_type(expected_type): if value is None: @@ -386,7 +386,7 @@ def save_pretrained( config: Optional[Union[dict, DataclassInstance]] = None, repo_id: Optional[str] = None, push_to_hub: bool = False, - model_card_kwargs: Optional[Dict[str, Any]] = None, + model_card_kwargs: Optional[dict[str, Any]] = None, **push_to_hub_kwargs, ) -> Optional[str]: """ @@ -402,7 +402,7 @@ def save_pretrained( repo_id (`str`, *optional*): ID of your repository on the Hub. Used only if `push_to_hub=True`. Will default to the folder name if not provided. - model_card_kwargs (`Dict[str, Any]`, *optional*): + model_card_kwargs (`dict[str, Any]`, *optional*): Additional arguments passed to the model card template to customize the model card. push_to_hub_kwargs: Additional key word arguments passed along to the [`~ModelHubMixin.push_to_hub`] method. @@ -461,7 +461,7 @@ def _save_pretrained(self, save_directory: Path) -> None: @classmethod @validate_hf_hub_args def from_pretrained( - cls: Type[T], + cls: type[T], pretrained_model_name_or_path: Union[str, Path], *, force_download: bool = False, @@ -493,7 +493,7 @@ def from_pretrained( Path to the folder where cached files are stored. local_files_only (`bool`, *optional*, defaults to `False`): If `True`, avoid downloading the file and return the path to the local cached file if it exists. - model_kwargs (`Dict`, *optional*): + model_kwargs (`dict`, *optional*): Additional kwargs to pass to the model during initialization. """ model_id = str(pretrained_model_name_or_path) @@ -551,7 +551,7 @@ def from_pretrained( if key not in model_kwargs and key in config: model_kwargs[key] = config[key] elif any(param.kind == inspect.Parameter.VAR_KEYWORD for param in cls._hub_mixin_init_parameters.values()): - for key, value in config.items(): + for key, value in config.items(): # type: ignore[union-attr] if key not in model_kwargs: model_kwargs[key] = value @@ -579,7 +579,7 @@ def from_pretrained( @classmethod def _from_pretrained( - cls: Type[T], + cls: type[T], *, model_id: str, revision: Optional[str], @@ -631,10 +631,10 @@ def push_to_hub( token: Optional[str] = None, branch: Optional[str] = None, create_pr: Optional[bool] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, - delete_patterns: Optional[Union[List[str], str]] = None, - model_card_kwargs: Optional[Dict[str, Any]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, + delete_patterns: Optional[Union[list[str], str]] = None, + model_card_kwargs: Optional[dict[str, Any]] = None, ) -> str: """ Upload model checkpoint to the Hub. @@ -660,13 +660,13 @@ def push_to_hub( The git branch on which to push the model. This defaults to `"main"`. create_pr (`boolean`, *optional*): Whether or not to create a Pull Request from `branch` with that commit. Defaults to `False`. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are pushed. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not pushed. - delete_patterns (`List[str]` or `str`, *optional*): + delete_patterns (`list[str]` or `str`, *optional*): If provided, remote files matching any of the patterns will be deleted from the repo. - model_card_kwargs (`Dict[str, Any]`, *optional*): + model_card_kwargs (`dict[str, Any]`, *optional*): Additional arguments passed to the model card template to customize the model card. Returns: @@ -749,7 +749,7 @@ class PyTorchModelHubMixin(ModelHubMixin): ``` """ - def __init_subclass__(cls, *args, tags: Optional[List[str]] = None, **kwargs) -> None: + def __init_subclass__(cls, *args, tags: Optional[list[str]] = None, **kwargs) -> None: tags = tags or [] tags.append("pytorch_model_hub_mixin") kwargs["tags"] = tags @@ -831,7 +831,7 @@ def _load_as_safetensor(cls, model: T, model_file: str, map_location: str, stric return model -def _load_dataclass(datacls: Type[DataclassInstance], data: dict) -> DataclassInstance: +def _load_dataclass(datacls: type[DataclassInstance], data: dict) -> DataclassInstance: """Load a dataclass instance from a dictionary. Fields not expected by the dataclass are ignored. diff --git a/src/huggingface_hub/inference/_client.py b/src/huggingface_hub/inference/_client.py index 22a979509c..ef78d93eee 100644 --- a/src/huggingface_hub/inference/_client.py +++ b/src/huggingface_hub/inference/_client.py @@ -38,7 +38,7 @@ import re import warnings from contextlib import ExitStack -from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Literal, Optional, Union, overload +from typing import TYPE_CHECKING, Any, Iterable, Literal, Optional, Union, overload from huggingface_hub import constants from huggingface_hub.errors import BadRequestError, HfHubHTTPError, InferenceTimeoutError @@ -144,13 +144,13 @@ class InferenceClient: arguments are mutually exclusive and have the exact same behavior. timeout (`float`, `optional`): The maximum number of seconds to wait for a response from the server. Defaults to None, meaning it will loop until the server is available. - headers (`Dict[str, str]`, `optional`): + headers (`dict[str, str]`, `optional`): Additional headers to send to the server. By default only the authorization and user-agent headers are sent. Values in this dictionary will override the default values. bill_to (`str`, `optional`): The billing account to use for the requests. By default the requests are billed on the user's account. Requests can only be billed to an organization the user is a member of, and which has subscribed to Enterprise Hub. - cookies (`Dict[str, str]`, `optional`): + cookies (`dict[str, str]`, `optional`): Additional cookies to send to the server. base_url (`str`, `optional`): Base URL to run inference. This is a duplicated argument from `model` to make [`InferenceClient`] @@ -168,8 +168,8 @@ def __init__( provider: Optional[PROVIDER_OR_POLICY_T] = None, token: Optional[str] = None, timeout: Optional[float] = None, - headers: Optional[Dict[str, str]] = None, - cookies: Optional[Dict[str, str]] = None, + headers: Optional[dict[str, str]] = None, + cookies: Optional[dict[str, str]] = None, bill_to: Optional[str] = None, # OpenAI compatibility base_url: Optional[str] = None, @@ -304,7 +304,7 @@ def audio_classification( model: Optional[str] = None, top_k: Optional[int] = None, function_to_apply: Optional["AudioClassificationOutputTransform"] = None, - ) -> List[AudioClassificationOutputElement]: + ) -> list[AudioClassificationOutputElement]: """ Perform audio classification on the provided audio content. @@ -322,7 +322,7 @@ def audio_classification( The function to apply to the model outputs in order to retrieve the scores. Returns: - `List[AudioClassificationOutputElement]`: List of [`AudioClassificationOutputElement`] items containing the predicted labels and their confidence. + `list[AudioClassificationOutputElement]`: List of [`AudioClassificationOutputElement`] items containing the predicted labels and their confidence. Raises: [`InferenceTimeoutError`]: @@ -359,7 +359,7 @@ def audio_to_audio( audio: ContentT, *, model: Optional[str] = None, - ) -> List[AudioToAudioOutputElement]: + ) -> list[AudioToAudioOutputElement]: """ Performs multiple tasks related to audio-to-audio depending on the model (eg: speech enhancement, source separation). @@ -373,7 +373,7 @@ def audio_to_audio( audio_to_audio will be used. Returns: - `List[AudioToAudioOutputElement]`: A list of [`AudioToAudioOutputElement`] items containing audios label, content-type, and audio content in blob. + `list[AudioToAudioOutputElement]`: A list of [`AudioToAudioOutputElement`] items containing audios label, content-type, and audio content in blob. Raises: `InferenceTimeoutError`: @@ -411,7 +411,7 @@ def automatic_speech_recognition( audio: ContentT, *, model: Optional[str] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> AutomaticSpeechRecognitionOutput: """ Perform automatic speech recognition (ASR or audio-to-text) on the given audio content. @@ -422,7 +422,7 @@ def automatic_speech_recognition( model (`str`, *optional*): The model to use for ASR. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. If not provided, the default recommended model for ASR will be used. - extra_body (`Dict`, *optional*): + extra_body (`dict`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. Returns: @@ -457,105 +457,105 @@ def automatic_speech_recognition( @overload def chat_completion( # type: ignore self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: Literal[False] = False, frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> ChatCompletionOutput: ... @overload def chat_completion( # type: ignore self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: Literal[True] = True, frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> Iterable[ChatCompletionStreamOutput]: ... @overload def chat_completion( self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: bool = False, frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> Union[ChatCompletionOutput, Iterable[ChatCompletionStreamOutput]]: ... def chat_completion( self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: bool = False, # Parameters from ChatCompletionInput (handled manually) frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> Union[ChatCompletionOutput, Iterable[ChatCompletionStreamOutput]]: """ A method for completing conversations using a specified language model. @@ -585,7 +585,7 @@ def chat_completion( frequency_penalty (`float`, *optional*): Penalizes new tokens based on their existing frequency in the text so far. Range: [-2.0, 2.0]. Defaults to 0.0. - logit_bias (`List[float]`, *optional*): + logit_bias (`list[float]`, *optional*): Adjusts the likelihood of specific tokens appearing in the generated output. logprobs (`bool`, *optional*): Whether to return log probabilities of the output tokens or not. If true, returns the log @@ -601,7 +601,7 @@ def chat_completion( Grammar constraints. Can be either a JSONSchema or a regex. seed (Optional[`int`], *optional*): Seed for reproducible control flow. Defaults to None. - stop (`List[str]`, *optional*): + stop (`list[str]`, *optional*): Up to four strings which trigger the end of the response. Defaults to None. stream (`bool`, *optional*): @@ -625,7 +625,7 @@ def chat_completion( tools (List of [`ChatCompletionInputTool`], *optional*): A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. - extra_body (`Dict`, *optional*): + extra_body (`dict`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. Returns: @@ -951,8 +951,8 @@ def document_question_answering( max_question_len: Optional[int] = None, max_seq_len: Optional[int] = None, top_k: Optional[int] = None, - word_boxes: Optional[List[Union[List[float], str]]] = None, - ) -> List[DocumentQuestionAnsweringOutputElement]: + word_boxes: Optional[list[Union[list[float], str]]] = None, + ) -> list[DocumentQuestionAnsweringOutputElement]: """ Answer questions on document images. @@ -982,11 +982,11 @@ def document_question_answering( top_k (`int`, *optional*): The number of answers to return (will be chosen by order of likelihood). Can return less than top_k answers if there are not enough options available within the context. - word_boxes (`List[Union[List[float], str`, *optional*): + word_boxes (`list[Union[list[float], str`, *optional*): A list of words and bounding boxes (normalized 0->1000). If provided, the inference will skip the OCR step and use the provided bounding boxes instead. Returns: - `List[DocumentQuestionAnsweringOutputElement]`: a list of [`DocumentQuestionAnsweringOutputElement`] items containing the predicted label, associated probability, word ids, and page number. + `list[DocumentQuestionAnsweringOutputElement]`: a list of [`DocumentQuestionAnsweringOutputElement`] items containing the predicted label, associated probability, word ids, and page number. Raises: [`InferenceTimeoutError`]: @@ -1005,7 +1005,7 @@ def document_question_answering( """ model_id = model or self.model provider_helper = get_provider_helper(self.provider, task="document-question-answering", model=model_id) - inputs: Dict[str, Any] = {"question": question, "image": _b64_encode(image)} + inputs: dict[str, Any] = {"question": question, "image": _b64_encode(image)} request_parameters = provider_helper.prepare_request( inputs=inputs, parameters={ @@ -1103,9 +1103,9 @@ def fill_mask( text: str, *, model: Optional[str] = None, - targets: Optional[List[str]] = None, + targets: Optional[list[str]] = None, top_k: Optional[int] = None, - ) -> List[FillMaskOutputElement]: + ) -> list[FillMaskOutputElement]: """ Fill in a hole with a missing word (token to be precise). @@ -1115,14 +1115,14 @@ def fill_mask( model (`str`, *optional*): The model to use for the fill mask task. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. If not provided, the default recommended fill mask model will be used. - targets (`List[str`, *optional*): + targets (`list[str`, *optional*): When passed, the model will limit the scores to the passed targets instead of looking up in the whole vocabulary. If the provided targets are not in the model vocab, they will be tokenized and the first resulting token will be used (with a warning, and that might be slower). top_k (`int`, *optional*): When passed, overrides the number of predictions to return. Returns: - `List[FillMaskOutputElement]`: a list of [`FillMaskOutputElement`] items containing the predicted label, associated + `list[FillMaskOutputElement]`: a list of [`FillMaskOutputElement`] items containing the predicted label, associated probability, token reference, and completed text. Raises: @@ -1161,7 +1161,7 @@ def image_classification( model: Optional[str] = None, function_to_apply: Optional["ImageClassificationOutputTransform"] = None, top_k: Optional[int] = None, - ) -> List[ImageClassificationOutputElement]: + ) -> list[ImageClassificationOutputElement]: """ Perform image classification on the given image using the specified model. @@ -1176,7 +1176,7 @@ def image_classification( top_k (`int`, *optional*): When specified, limits the output to the top K most probable classes. Returns: - `List[ImageClassificationOutputElement]`: a list of [`ImageClassificationOutputElement`] items containing the predicted label and associated probability. + `list[ImageClassificationOutputElement]`: a list of [`ImageClassificationOutputElement`] items containing the predicted label and associated probability. Raises: [`InferenceTimeoutError`]: @@ -1213,7 +1213,7 @@ def image_segmentation( overlap_mask_area_threshold: Optional[float] = None, subtask: Optional["ImageSegmentationSubtask"] = None, threshold: Optional[float] = None, - ) -> List[ImageSegmentationOutputElement]: + ) -> list[ImageSegmentationOutputElement]: """ Perform image segmentation on the given image using the specified model. @@ -1238,7 +1238,7 @@ def image_segmentation( threshold (`float`, *optional*): Probability threshold to filter out predicted masks. Returns: - `List[ImageSegmentationOutputElement]`: A list of [`ImageSegmentationOutputElement`] items containing the segmented masks and associated attributes. + `list[ImageSegmentationOutputElement]`: A list of [`ImageSegmentationOutputElement`] items containing the segmented masks and associated attributes. Raises: [`InferenceTimeoutError`]: @@ -1473,12 +1473,12 @@ def image_to_text(self, image: ContentT, *, model: Optional[str] = None) -> Imag api_key=self.token, ) response = self._inner_post(request_parameters) - output_list: List[ImageToTextOutput] = ImageToTextOutput.parse_obj_as_list(response) + output_list: list[ImageToTextOutput] = ImageToTextOutput.parse_obj_as_list(response) return output_list[0] def object_detection( self, image: ContentT, *, model: Optional[str] = None, threshold: Optional[float] = None - ) -> List[ObjectDetectionOutputElement]: + ) -> list[ObjectDetectionOutputElement]: """ Perform object detection on the given image using the specified model. @@ -1497,7 +1497,7 @@ def object_detection( threshold (`float`, *optional*): The probability necessary to make a prediction. Returns: - `List[ObjectDetectionOutputElement]`: A list of [`ObjectDetectionOutputElement`] items containing the bounding boxes and associated attributes. + `list[ObjectDetectionOutputElement]`: A list of [`ObjectDetectionOutputElement`] items containing the bounding boxes and associated attributes. Raises: [`InferenceTimeoutError`]: @@ -1540,7 +1540,7 @@ def question_answering( max_question_len: Optional[int] = None, max_seq_len: Optional[int] = None, top_k: Optional[int] = None, - ) -> Union[QuestionAnsweringOutputElement, List[QuestionAnsweringOutputElement]]: + ) -> Union[QuestionAnsweringOutputElement, list[QuestionAnsweringOutputElement]]: """ Retrieve the answer to a question from a given text. @@ -1572,7 +1572,7 @@ def question_answering( topk answers if there are not enough options available within the context. Returns: - Union[`QuestionAnsweringOutputElement`, List[`QuestionAnsweringOutputElement`]]: + Union[`QuestionAnsweringOutputElement`, list[`QuestionAnsweringOutputElement`]]: When top_k is 1 or not provided, it returns a single `QuestionAnsweringOutputElement`. When top_k is greater than 1, it returns a list of `QuestionAnsweringOutputElement`. Raises: @@ -1612,15 +1612,15 @@ def question_answering( return output def sentence_similarity( - self, sentence: str, other_sentences: List[str], *, model: Optional[str] = None - ) -> List[float]: + self, sentence: str, other_sentences: list[str], *, model: Optional[str] = None + ) -> list[float]: """ Compute the semantic similarity between a sentence and a list of other sentences by comparing their embeddings. Args: sentence (`str`): The main sentence to compare to others. - other_sentences (`List[str]`): + other_sentences (`list[str]`): The list of sentences to compare to. model (`str`, *optional*): The model to use for the sentence similarity task. Can be a model ID hosted on the Hugging Face Hub or a URL to @@ -1628,7 +1628,7 @@ def sentence_similarity( Defaults to None. Returns: - `List[float]`: The embedding representing the input text. + `list[float]`: The embedding representing the input text. Raises: [`InferenceTimeoutError`]: @@ -1670,7 +1670,7 @@ def summarization( *, model: Optional[str] = None, clean_up_tokenization_spaces: Optional[bool] = None, - generate_parameters: Optional[Dict[str, Any]] = None, + generate_parameters: Optional[dict[str, Any]] = None, truncation: Optional["SummarizationTruncationStrategy"] = None, ) -> SummarizationOutput: """ @@ -1684,7 +1684,7 @@ def summarization( Inference Endpoint. If not provided, the default recommended model for summarization will be used. clean_up_tokenization_spaces (`bool`, *optional*): Whether to clean up the potential extra spaces in the text output. - generate_parameters (`Dict[str, Any]`, *optional*): + generate_parameters (`dict[str, Any]`, *optional*): Additional parametrization of the text generation algorithm. truncation (`"SummarizationTruncationStrategy"`, *optional*): The truncation strategy to use. @@ -1724,7 +1724,7 @@ def summarization( def table_question_answering( self, - table: Dict[str, Any], + table: dict[str, Any], query: str, *, model: Optional[str] = None, @@ -1784,12 +1784,12 @@ def table_question_answering( response = self._inner_post(request_parameters) return TableQuestionAnsweringOutputElement.parse_obj_as_instance(response) - def tabular_classification(self, table: Dict[str, Any], *, model: Optional[str] = None) -> List[str]: + def tabular_classification(self, table: dict[str, Any], *, model: Optional[str] = None) -> list[str]: """ Classifying a target category (a group) based on a set of attributes. Args: - table (`Dict[str, Any]`): + table (`dict[str, Any]`): Set of attributes to classify. model (`str`, *optional*): The model to use for the tabular classification task. Can be a model ID hosted on the Hugging Face Hub or a URL to @@ -1839,12 +1839,12 @@ def tabular_classification(self, table: Dict[str, Any], *, model: Optional[str] response = self._inner_post(request_parameters) return _bytes_to_list(response) - def tabular_regression(self, table: Dict[str, Any], *, model: Optional[str] = None) -> List[float]: + def tabular_regression(self, table: dict[str, Any], *, model: Optional[str] = None) -> list[float]: """ Predicting a numerical target value given a set of attributes/features in a table. Args: - table (`Dict[str, Any]`): + table (`dict[str, Any]`): Set of attributes stored in a table. The attributes used to predict the target can be both numerical and categorical. model (`str`, *optional*): The model to use for the tabular regression task. Can be a model ID hosted on the Hugging Face Hub or a URL to @@ -1896,7 +1896,7 @@ def text_classification( model: Optional[str] = None, top_k: Optional[int] = None, function_to_apply: Optional["TextClassificationOutputTransform"] = None, - ) -> List[TextClassificationOutputElement]: + ) -> list[TextClassificationOutputElement]: """ Perform text classification (e.g. sentiment-analysis) on the given text. @@ -1913,7 +1913,7 @@ def text_classification( The function to apply to the model outputs in order to retrieve the scores. Returns: - `List[TextClassificationOutputElement]`: a list of [`TextClassificationOutputElement`] items containing the predicted label and associated probability. + `list[TextClassificationOutputElement]`: a list of [`TextClassificationOutputElement`] items containing the predicted label and associated probability. Raises: [`InferenceTimeoutError`]: @@ -1966,8 +1966,8 @@ def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -1996,8 +1996,8 @@ def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2026,8 +2026,8 @@ def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, # Manual default value seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2056,8 +2056,8 @@ def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2086,8 +2086,8 @@ def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2115,8 +2115,8 @@ def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2172,9 +2172,9 @@ def text_generation( Whether to prepend the prompt to the generated text seed (`int`, *optional*): Random sampling seed - stop (`List[str]`, *optional*): + stop (`list[str]`, *optional*): Stop generating tokens if a member of `stop` is generated. - stop_sequences (`List[str]`, *optional*): + stop_sequences (`list[str]`, *optional*): Deprecated argument. Use `stop` instead. temperature (`float`, *optional*): The value used to module the logits distribution. @@ -2451,7 +2451,7 @@ def text_to_image( model: Optional[str] = None, scheduler: Optional[str] = None, seed: Optional[int] = None, - extra_body: Optional[Dict[str, Any]] = None, + extra_body: Optional[dict[str, Any]] = None, ) -> "Image": """ Generate an image based on a given text using a specified model. @@ -2489,7 +2489,7 @@ def text_to_image( Override the scheduler with a compatible one. seed (`int`, *optional*): Seed for the random number generator. - extra_body (`Dict[str, Any]`, *optional*): + extra_body (`dict[str, Any]`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. @@ -2588,11 +2588,11 @@ def text_to_video( *, model: Optional[str] = None, guidance_scale: Optional[float] = None, - negative_prompt: Optional[List[str]] = None, + negative_prompt: Optional[list[str]] = None, num_frames: Optional[float] = None, num_inference_steps: Optional[int] = None, seed: Optional[int] = None, - extra_body: Optional[Dict[str, Any]] = None, + extra_body: Optional[dict[str, Any]] = None, ) -> bytes: """ Generate a video based on a given text. @@ -2611,7 +2611,7 @@ def text_to_video( guidance_scale (`float`, *optional*): A higher guidance scale value encourages the model to generate videos closely linked to the text prompt, but values too high may cause saturation and other artifacts. - negative_prompt (`List[str]`, *optional*): + negative_prompt (`list[str]`, *optional*): One or several prompt to guide what NOT to include in video generation. num_frames (`float`, *optional*): The num_frames parameter determines how many video frames are generated. @@ -2620,7 +2620,7 @@ def text_to_video( expense of slower inference. seed (`int`, *optional*): Seed for the random number generator. - extra_body (`Dict[str, Any]`, *optional*): + extra_body (`dict[str, Any]`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. @@ -2700,7 +2700,7 @@ def text_to_speech( top_p: Optional[float] = None, typical_p: Optional[float] = None, use_cache: Optional[bool] = None, - extra_body: Optional[Dict[str, Any]] = None, + extra_body: Optional[dict[str, Any]] = None, ) -> bytes: """ Synthesize an audio of a voice pronouncing a given text. @@ -2762,7 +2762,7 @@ def text_to_speech( paper](https://hf.co/papers/2202.00666) for more details. use_cache (`bool`, *optional*): Whether the model should use the past last key/values attentions to speed up decoding - extra_body (`Dict[str, Any]`, *optional*): + extra_body (`dict[str, Any]`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. Returns: @@ -2894,9 +2894,9 @@ def token_classification( *, model: Optional[str] = None, aggregation_strategy: Optional["TokenClassificationAggregationStrategy"] = None, - ignore_labels: Optional[List[str]] = None, + ignore_labels: Optional[list[str]] = None, stride: Optional[int] = None, - ) -> List[TokenClassificationOutputElement]: + ) -> list[TokenClassificationOutputElement]: """ Perform token classification on the given text. Usually used for sentence parsing, either grammatical, or Named Entity Recognition (NER) to understand keywords contained within text. @@ -2910,13 +2910,13 @@ def token_classification( Defaults to None. aggregation_strategy (`"TokenClassificationAggregationStrategy"`, *optional*): The strategy used to fuse tokens based on model predictions - ignore_labels (`List[str`, *optional*): + ignore_labels (`list[str`, *optional*): A list of labels to ignore stride (`int`, *optional*): The number of overlapping tokens between chunks when splitting the input text. Returns: - `List[TokenClassificationOutputElement]`: List of [`TokenClassificationOutputElement`] items containing the entity group, confidence score, word, start and end index. + `list[TokenClassificationOutputElement]`: List of [`TokenClassificationOutputElement`] items containing the entity group, confidence score, word, start and end index. Raises: [`InferenceTimeoutError`]: @@ -2972,7 +2972,7 @@ def translation( tgt_lang: Optional[str] = None, clean_up_tokenization_spaces: Optional[bool] = None, truncation: Optional["TranslationTruncationStrategy"] = None, - generate_parameters: Optional[Dict[str, Any]] = None, + generate_parameters: Optional[dict[str, Any]] = None, ) -> TranslationOutput: """ Convert text from one language to another. @@ -2997,7 +2997,7 @@ def translation( Whether to clean up the potential extra spaces in the text output. truncation (`"TranslationTruncationStrategy"`, *optional*): The truncation strategy to use. - generate_parameters (`Dict[str, Any]`, *optional*): + generate_parameters (`dict[str, Any]`, *optional*): Additional parametrization of the text generation algorithm. Returns: @@ -3059,7 +3059,7 @@ def visual_question_answering( *, model: Optional[str] = None, top_k: Optional[int] = None, - ) -> List[VisualQuestionAnsweringOutputElement]: + ) -> list[VisualQuestionAnsweringOutputElement]: """ Answering open-ended questions based on an image. @@ -3076,7 +3076,7 @@ def visual_question_answering( The number of answers to return (will be chosen by order of likelihood). Note that we return less than topk answers if there are not enough options available within the context. Returns: - `List[VisualQuestionAnsweringOutputElement]`: a list of [`VisualQuestionAnsweringOutputElement`] items containing the predicted label and associated probability. + `list[VisualQuestionAnsweringOutputElement]`: a list of [`VisualQuestionAnsweringOutputElement`] items containing the predicted label and associated probability. Raises: `InferenceTimeoutError`: @@ -3114,21 +3114,21 @@ def visual_question_answering( def zero_shot_classification( self, text: str, - candidate_labels: List[str], + candidate_labels: list[str], *, multi_label: Optional[bool] = False, hypothesis_template: Optional[str] = None, model: Optional[str] = None, - ) -> List[ZeroShotClassificationOutputElement]: + ) -> list[ZeroShotClassificationOutputElement]: """ Provide as input a text and a set of candidate labels to classify the input text. Args: text (`str`): The input text to classify. - candidate_labels (`List[str]`): + candidate_labels (`list[str]`): The set of possible class labels to classify the text into. - labels (`List[str]`, *optional*): + labels (`list[str]`, *optional*): (deprecated) List of strings. Each string is the verbalization of a possible label for the input text. multi_label (`bool`, *optional*): Whether multiple candidate labels can be true. If false, the scores are normalized such that the sum of @@ -3143,7 +3143,7 @@ def zero_shot_classification( Returns: - `List[ZeroShotClassificationOutputElement]`: List of [`ZeroShotClassificationOutputElement`] items containing the predicted labels and their confidence. + `list[ZeroShotClassificationOutputElement]`: List of [`ZeroShotClassificationOutputElement`] items containing the predicted labels and their confidence. Raises: [`InferenceTimeoutError`]: @@ -3220,22 +3220,22 @@ def zero_shot_classification( def zero_shot_image_classification( self, image: ContentT, - candidate_labels: List[str], + candidate_labels: list[str], *, model: Optional[str] = None, hypothesis_template: Optional[str] = None, # deprecated argument - labels: List[str] = None, # type: ignore - ) -> List[ZeroShotImageClassificationOutputElement]: + labels: list[str] = None, # type: ignore + ) -> list[ZeroShotImageClassificationOutputElement]: """ Provide input image and text labels to predict text labels for the image. Args: image (`Union[str, Path, bytes, BinaryIO, PIL.Image.Image]`): The input image to caption. It can be raw bytes, an image file, a URL to an online image, or a PIL Image. - candidate_labels (`List[str]`): + candidate_labels (`list[str]`): The candidate labels for this image - labels (`List[str]`, *optional*): + labels (`list[str]`, *optional*): (deprecated) List of string possible labels. There must be at least 2 labels. model (`str`, *optional*): The model to use for inference. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed @@ -3245,7 +3245,7 @@ def zero_shot_image_classification( replacing the placeholder with the candidate labels. Returns: - `List[ZeroShotImageClassificationOutputElement]`: List of [`ZeroShotImageClassificationOutputElement`] items containing the predicted labels and their confidence. + `list[ZeroShotImageClassificationOutputElement]`: List of [`ZeroShotImageClassificationOutputElement`] items containing the predicted labels and their confidence. Raises: [`InferenceTimeoutError`]: @@ -3284,7 +3284,7 @@ def zero_shot_image_classification( response = self._inner_post(request_parameters) return ZeroShotImageClassificationOutputElement.parse_obj_as_list(response) - def get_endpoint_info(self, *, model: Optional[str] = None) -> Dict[str, Any]: + def get_endpoint_info(self, *, model: Optional[str] = None) -> dict[str, Any]: """ Get information about the deployed endpoint. @@ -3297,7 +3297,7 @@ def get_endpoint_info(self, *, model: Optional[str] = None) -> Dict[str, Any]: Inference Endpoint. This parameter overrides the model defined at the instance level. Defaults to None. Returns: - `Dict[str, Any]`: Information about the endpoint. + `dict[str, Any]`: Information about the endpoint. Example: ```py diff --git a/src/huggingface_hub/inference/_common.py b/src/huggingface_hub/inference/_common.py index aca297df34..b79713a934 100644 --- a/src/huggingface_hub/inference/_common.py +++ b/src/huggingface_hub/inference/_common.py @@ -21,20 +21,7 @@ import mimetypes from dataclasses import dataclass from pathlib import Path -from typing import ( - TYPE_CHECKING, - Any, - AsyncIterable, - BinaryIO, - Dict, - Iterable, - List, - Literal, - NoReturn, - Optional, - Union, - overload, -) +from typing import TYPE_CHECKING, Any, AsyncIterable, BinaryIO, Iterable, Literal, NoReturn, Optional, Union, overload import httpx @@ -71,9 +58,9 @@ class RequestParameters: url: str task: str model: Optional[str] - json: Optional[Union[str, Dict, List]] + json: Optional[Union[str, dict, list]] data: Optional[bytes] - headers: Dict[str, Any] + headers: dict[str, Any] class MimeBytes(bytes): @@ -240,7 +227,7 @@ def _b64_to_image(encoded_image: str) -> "Image": return Image.open(io.BytesIO(base64.b64decode(encoded_image))) -def _bytes_to_list(content: bytes) -> List: +def _bytes_to_list(content: bytes) -> list: """Parse bytes from a Response object into a Python list. Expects the response body to be JSON-encoded data. @@ -251,7 +238,7 @@ def _bytes_to_list(content: bytes) -> List: return json.loads(content.decode()) -def _bytes_to_dict(content: bytes) -> Dict: +def _bytes_to_dict(content: bytes) -> dict: """Parse bytes from a Response object into a Python dictionary. Expects the response body to be JSON-encoded data. @@ -271,7 +258,7 @@ def _bytes_to_image(content: bytes) -> "Image": return Image.open(io.BytesIO(content)) -def _as_dict(response: Union[bytes, Dict]) -> Dict: +def _as_dict(response: Union[bytes, dict]) -> dict: return json.loads(response) if isinstance(response, bytes) else response @@ -397,14 +384,14 @@ async def _async_yield_from(client: httpx.AsyncClient, response: httpx.Response) # For more details, see https://github.com/huggingface/text-generation-inference and # https://huggingface.co/docs/api-inference/detailed_parameters#text-generation-task. -_UNSUPPORTED_TEXT_GENERATION_KWARGS: Dict[Optional[str], List[str]] = {} +_UNSUPPORTED_TEXT_GENERATION_KWARGS: dict[Optional[str], list[str]] = {} -def _set_unsupported_text_generation_kwargs(model: Optional[str], unsupported_kwargs: List[str]) -> None: +def _set_unsupported_text_generation_kwargs(model: Optional[str], unsupported_kwargs: list[str]) -> None: _UNSUPPORTED_TEXT_GENERATION_KWARGS.setdefault(model, []).extend(unsupported_kwargs) -def _get_unsupported_text_generation_kwargs(model: Optional[str]) -> List[str]: +def _get_unsupported_text_generation_kwargs(model: Optional[str]) -> list[str]: return _UNSUPPORTED_TEXT_GENERATION_KWARGS.get(model, []) diff --git a/src/huggingface_hub/inference/_generated/_async_client.py b/src/huggingface_hub/inference/_generated/_async_client.py index b25a231052..6d1acab8fb 100644 --- a/src/huggingface_hub/inference/_generated/_async_client.py +++ b/src/huggingface_hub/inference/_generated/_async_client.py @@ -25,7 +25,7 @@ import re import warnings from contextlib import AsyncExitStack -from typing import TYPE_CHECKING, Any, AsyncIterable, Dict, List, Literal, Optional, Union, overload +from typing import TYPE_CHECKING, Any, AsyncIterable, Literal, Optional, Union, overload import httpx @@ -135,13 +135,13 @@ class AsyncInferenceClient: arguments are mutually exclusive and have the exact same behavior. timeout (`float`, `optional`): The maximum number of seconds to wait for a response from the server. Defaults to None, meaning it will loop until the server is available. - headers (`Dict[str, str]`, `optional`): + headers (`dict[str, str]`, `optional`): Additional headers to send to the server. By default only the authorization and user-agent headers are sent. Values in this dictionary will override the default values. bill_to (`str`, `optional`): The billing account to use for the requests. By default the requests are billed on the user's account. Requests can only be billed to an organization the user is a member of, and which has subscribed to Enterprise Hub. - cookies (`Dict[str, str]`, `optional`): + cookies (`dict[str, str]`, `optional`): Additional cookies to send to the server. base_url (`str`, `optional`): Base URL to run inference. This is a duplicated argument from `model` to make [`InferenceClient`] @@ -159,8 +159,8 @@ def __init__( provider: Optional[PROVIDER_OR_POLICY_T] = None, token: Optional[str] = None, timeout: Optional[float] = None, - headers: Optional[Dict[str, str]] = None, - cookies: Optional[Dict[str, str]] = None, + headers: Optional[dict[str, str]] = None, + cookies: Optional[dict[str, str]] = None, bill_to: Optional[str] = None, # OpenAI compatibility base_url: Optional[str] = None, @@ -321,7 +321,7 @@ async def audio_classification( model: Optional[str] = None, top_k: Optional[int] = None, function_to_apply: Optional["AudioClassificationOutputTransform"] = None, - ) -> List[AudioClassificationOutputElement]: + ) -> list[AudioClassificationOutputElement]: """ Perform audio classification on the provided audio content. @@ -339,7 +339,7 @@ async def audio_classification( The function to apply to the model outputs in order to retrieve the scores. Returns: - `List[AudioClassificationOutputElement]`: List of [`AudioClassificationOutputElement`] items containing the predicted labels and their confidence. + `list[AudioClassificationOutputElement]`: List of [`AudioClassificationOutputElement`] items containing the predicted labels and their confidence. Raises: [`InferenceTimeoutError`]: @@ -377,7 +377,7 @@ async def audio_to_audio( audio: ContentT, *, model: Optional[str] = None, - ) -> List[AudioToAudioOutputElement]: + ) -> list[AudioToAudioOutputElement]: """ Performs multiple tasks related to audio-to-audio depending on the model (eg: speech enhancement, source separation). @@ -391,7 +391,7 @@ async def audio_to_audio( audio_to_audio will be used. Returns: - `List[AudioToAudioOutputElement]`: A list of [`AudioToAudioOutputElement`] items containing audios label, content-type, and audio content in blob. + `list[AudioToAudioOutputElement]`: A list of [`AudioToAudioOutputElement`] items containing audios label, content-type, and audio content in blob. Raises: `InferenceTimeoutError`: @@ -430,7 +430,7 @@ async def automatic_speech_recognition( audio: ContentT, *, model: Optional[str] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> AutomaticSpeechRecognitionOutput: """ Perform automatic speech recognition (ASR or audio-to-text) on the given audio content. @@ -441,7 +441,7 @@ async def automatic_speech_recognition( model (`str`, *optional*): The model to use for ASR. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. If not provided, the default recommended model for ASR will be used. - extra_body (`Dict`, *optional*): + extra_body (`dict`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. Returns: @@ -477,105 +477,105 @@ async def automatic_speech_recognition( @overload async def chat_completion( # type: ignore self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: Literal[False] = False, frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> ChatCompletionOutput: ... @overload async def chat_completion( # type: ignore self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: Literal[True] = True, frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> AsyncIterable[ChatCompletionStreamOutput]: ... @overload async def chat_completion( self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: bool = False, frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> Union[ChatCompletionOutput, AsyncIterable[ChatCompletionStreamOutput]]: ... async def chat_completion( self, - messages: List[Union[Dict, ChatCompletionInputMessage]], + messages: list[Union[dict, ChatCompletionInputMessage]], *, model: Optional[str] = None, stream: bool = False, # Parameters from ChatCompletionInput (handled manually) frequency_penalty: Optional[float] = None, - logit_bias: Optional[List[float]] = None, + logit_bias: Optional[list[float]] = None, logprobs: Optional[bool] = None, max_tokens: Optional[int] = None, n: Optional[int] = None, presence_penalty: Optional[float] = None, response_format: Optional[ChatCompletionInputGrammarType] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, + stop: Optional[list[str]] = None, stream_options: Optional[ChatCompletionInputStreamOptions] = None, temperature: Optional[float] = None, tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None, tool_prompt: Optional[str] = None, - tools: Optional[List[ChatCompletionInputTool]] = None, + tools: Optional[list[ChatCompletionInputTool]] = None, top_logprobs: Optional[int] = None, top_p: Optional[float] = None, - extra_body: Optional[Dict] = None, + extra_body: Optional[dict] = None, ) -> Union[ChatCompletionOutput, AsyncIterable[ChatCompletionStreamOutput]]: """ A method for completing conversations using a specified language model. @@ -605,7 +605,7 @@ async def chat_completion( frequency_penalty (`float`, *optional*): Penalizes new tokens based on their existing frequency in the text so far. Range: [-2.0, 2.0]. Defaults to 0.0. - logit_bias (`List[float]`, *optional*): + logit_bias (`list[float]`, *optional*): Adjusts the likelihood of specific tokens appearing in the generated output. logprobs (`bool`, *optional*): Whether to return log probabilities of the output tokens or not. If true, returns the log @@ -621,7 +621,7 @@ async def chat_completion( Grammar constraints. Can be either a JSONSchema or a regex. seed (Optional[`int`], *optional*): Seed for reproducible control flow. Defaults to None. - stop (`List[str]`, *optional*): + stop (`list[str]`, *optional*): Up to four strings which trigger the end of the response. Defaults to None. stream (`bool`, *optional*): @@ -645,7 +645,7 @@ async def chat_completion( tools (List of [`ChatCompletionInputTool`], *optional*): A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. - extra_body (`Dict`, *optional*): + extra_body (`dict`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. Returns: @@ -977,8 +977,8 @@ async def document_question_answering( max_question_len: Optional[int] = None, max_seq_len: Optional[int] = None, top_k: Optional[int] = None, - word_boxes: Optional[List[Union[List[float], str]]] = None, - ) -> List[DocumentQuestionAnsweringOutputElement]: + word_boxes: Optional[list[Union[list[float], str]]] = None, + ) -> list[DocumentQuestionAnsweringOutputElement]: """ Answer questions on document images. @@ -1008,11 +1008,11 @@ async def document_question_answering( top_k (`int`, *optional*): The number of answers to return (will be chosen by order of likelihood). Can return less than top_k answers if there are not enough options available within the context. - word_boxes (`List[Union[List[float], str`, *optional*): + word_boxes (`list[Union[list[float], str`, *optional*): A list of words and bounding boxes (normalized 0->1000). If provided, the inference will skip the OCR step and use the provided bounding boxes instead. Returns: - `List[DocumentQuestionAnsweringOutputElement]`: a list of [`DocumentQuestionAnsweringOutputElement`] items containing the predicted label, associated probability, word ids, and page number. + `list[DocumentQuestionAnsweringOutputElement]`: a list of [`DocumentQuestionAnsweringOutputElement`] items containing the predicted label, associated probability, word ids, and page number. Raises: [`InferenceTimeoutError`]: @@ -1032,7 +1032,7 @@ async def document_question_answering( """ model_id = model or self.model provider_helper = get_provider_helper(self.provider, task="document-question-answering", model=model_id) - inputs: Dict[str, Any] = {"question": question, "image": _b64_encode(image)} + inputs: dict[str, Any] = {"question": question, "image": _b64_encode(image)} request_parameters = provider_helper.prepare_request( inputs=inputs, parameters={ @@ -1131,9 +1131,9 @@ async def fill_mask( text: str, *, model: Optional[str] = None, - targets: Optional[List[str]] = None, + targets: Optional[list[str]] = None, top_k: Optional[int] = None, - ) -> List[FillMaskOutputElement]: + ) -> list[FillMaskOutputElement]: """ Fill in a hole with a missing word (token to be precise). @@ -1143,14 +1143,14 @@ async def fill_mask( model (`str`, *optional*): The model to use for the fill mask task. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed Inference Endpoint. If not provided, the default recommended fill mask model will be used. - targets (`List[str`, *optional*): + targets (`list[str`, *optional*): When passed, the model will limit the scores to the passed targets instead of looking up in the whole vocabulary. If the provided targets are not in the model vocab, they will be tokenized and the first resulting token will be used (with a warning, and that might be slower). top_k (`int`, *optional*): When passed, overrides the number of predictions to return. Returns: - `List[FillMaskOutputElement]`: a list of [`FillMaskOutputElement`] items containing the predicted label, associated + `list[FillMaskOutputElement]`: a list of [`FillMaskOutputElement`] items containing the predicted label, associated probability, token reference, and completed text. Raises: @@ -1190,7 +1190,7 @@ async def image_classification( model: Optional[str] = None, function_to_apply: Optional["ImageClassificationOutputTransform"] = None, top_k: Optional[int] = None, - ) -> List[ImageClassificationOutputElement]: + ) -> list[ImageClassificationOutputElement]: """ Perform image classification on the given image using the specified model. @@ -1205,7 +1205,7 @@ async def image_classification( top_k (`int`, *optional*): When specified, limits the output to the top K most probable classes. Returns: - `List[ImageClassificationOutputElement]`: a list of [`ImageClassificationOutputElement`] items containing the predicted label and associated probability. + `list[ImageClassificationOutputElement]`: a list of [`ImageClassificationOutputElement`] items containing the predicted label and associated probability. Raises: [`InferenceTimeoutError`]: @@ -1243,7 +1243,7 @@ async def image_segmentation( overlap_mask_area_threshold: Optional[float] = None, subtask: Optional["ImageSegmentationSubtask"] = None, threshold: Optional[float] = None, - ) -> List[ImageSegmentationOutputElement]: + ) -> list[ImageSegmentationOutputElement]: """ Perform image segmentation on the given image using the specified model. @@ -1268,7 +1268,7 @@ async def image_segmentation( threshold (`float`, *optional*): Probability threshold to filter out predicted masks. Returns: - `List[ImageSegmentationOutputElement]`: A list of [`ImageSegmentationOutputElement`] items containing the segmented masks and associated attributes. + `list[ImageSegmentationOutputElement]`: A list of [`ImageSegmentationOutputElement`] items containing the segmented masks and associated attributes. Raises: [`InferenceTimeoutError`]: @@ -1507,12 +1507,12 @@ async def image_to_text(self, image: ContentT, *, model: Optional[str] = None) - api_key=self.token, ) response = await self._inner_post(request_parameters) - output_list: List[ImageToTextOutput] = ImageToTextOutput.parse_obj_as_list(response) + output_list: list[ImageToTextOutput] = ImageToTextOutput.parse_obj_as_list(response) return output_list[0] async def object_detection( self, image: ContentT, *, model: Optional[str] = None, threshold: Optional[float] = None - ) -> List[ObjectDetectionOutputElement]: + ) -> list[ObjectDetectionOutputElement]: """ Perform object detection on the given image using the specified model. @@ -1531,7 +1531,7 @@ async def object_detection( threshold (`float`, *optional*): The probability necessary to make a prediction. Returns: - `List[ObjectDetectionOutputElement]`: A list of [`ObjectDetectionOutputElement`] items containing the bounding boxes and associated attributes. + `list[ObjectDetectionOutputElement]`: A list of [`ObjectDetectionOutputElement`] items containing the bounding boxes and associated attributes. Raises: [`InferenceTimeoutError`]: @@ -1575,7 +1575,7 @@ async def question_answering( max_question_len: Optional[int] = None, max_seq_len: Optional[int] = None, top_k: Optional[int] = None, - ) -> Union[QuestionAnsweringOutputElement, List[QuestionAnsweringOutputElement]]: + ) -> Union[QuestionAnsweringOutputElement, list[QuestionAnsweringOutputElement]]: """ Retrieve the answer to a question from a given text. @@ -1607,7 +1607,7 @@ async def question_answering( topk answers if there are not enough options available within the context. Returns: - Union[`QuestionAnsweringOutputElement`, List[`QuestionAnsweringOutputElement`]]: + Union[`QuestionAnsweringOutputElement`, list[`QuestionAnsweringOutputElement`]]: When top_k is 1 or not provided, it returns a single `QuestionAnsweringOutputElement`. When top_k is greater than 1, it returns a list of `QuestionAnsweringOutputElement`. Raises: @@ -1648,15 +1648,15 @@ async def question_answering( return output async def sentence_similarity( - self, sentence: str, other_sentences: List[str], *, model: Optional[str] = None - ) -> List[float]: + self, sentence: str, other_sentences: list[str], *, model: Optional[str] = None + ) -> list[float]: """ Compute the semantic similarity between a sentence and a list of other sentences by comparing their embeddings. Args: sentence (`str`): The main sentence to compare to others. - other_sentences (`List[str]`): + other_sentences (`list[str]`): The list of sentences to compare to. model (`str`, *optional*): The model to use for the sentence similarity task. Can be a model ID hosted on the Hugging Face Hub or a URL to @@ -1664,7 +1664,7 @@ async def sentence_similarity( Defaults to None. Returns: - `List[float]`: The embedding representing the input text. + `list[float]`: The embedding representing the input text. Raises: [`InferenceTimeoutError`]: @@ -1707,7 +1707,7 @@ async def summarization( *, model: Optional[str] = None, clean_up_tokenization_spaces: Optional[bool] = None, - generate_parameters: Optional[Dict[str, Any]] = None, + generate_parameters: Optional[dict[str, Any]] = None, truncation: Optional["SummarizationTruncationStrategy"] = None, ) -> SummarizationOutput: """ @@ -1721,7 +1721,7 @@ async def summarization( Inference Endpoint. If not provided, the default recommended model for summarization will be used. clean_up_tokenization_spaces (`bool`, *optional*): Whether to clean up the potential extra spaces in the text output. - generate_parameters (`Dict[str, Any]`, *optional*): + generate_parameters (`dict[str, Any]`, *optional*): Additional parametrization of the text generation algorithm. truncation (`"SummarizationTruncationStrategy"`, *optional*): The truncation strategy to use. @@ -1762,7 +1762,7 @@ async def summarization( async def table_question_answering( self, - table: Dict[str, Any], + table: dict[str, Any], query: str, *, model: Optional[str] = None, @@ -1823,12 +1823,12 @@ async def table_question_answering( response = await self._inner_post(request_parameters) return TableQuestionAnsweringOutputElement.parse_obj_as_instance(response) - async def tabular_classification(self, table: Dict[str, Any], *, model: Optional[str] = None) -> List[str]: + async def tabular_classification(self, table: dict[str, Any], *, model: Optional[str] = None) -> list[str]: """ Classifying a target category (a group) based on a set of attributes. Args: - table (`Dict[str, Any]`): + table (`dict[str, Any]`): Set of attributes to classify. model (`str`, *optional*): The model to use for the tabular classification task. Can be a model ID hosted on the Hugging Face Hub or a URL to @@ -1879,12 +1879,12 @@ async def tabular_classification(self, table: Dict[str, Any], *, model: Optional response = await self._inner_post(request_parameters) return _bytes_to_list(response) - async def tabular_regression(self, table: Dict[str, Any], *, model: Optional[str] = None) -> List[float]: + async def tabular_regression(self, table: dict[str, Any], *, model: Optional[str] = None) -> list[float]: """ Predicting a numerical target value given a set of attributes/features in a table. Args: - table (`Dict[str, Any]`): + table (`dict[str, Any]`): Set of attributes stored in a table. The attributes used to predict the target can be both numerical and categorical. model (`str`, *optional*): The model to use for the tabular regression task. Can be a model ID hosted on the Hugging Face Hub or a URL to @@ -1937,7 +1937,7 @@ async def text_classification( model: Optional[str] = None, top_k: Optional[int] = None, function_to_apply: Optional["TextClassificationOutputTransform"] = None, - ) -> List[TextClassificationOutputElement]: + ) -> list[TextClassificationOutputElement]: """ Perform text classification (e.g. sentiment-analysis) on the given text. @@ -1954,7 +1954,7 @@ async def text_classification( The function to apply to the model outputs in order to retrieve the scores. Returns: - `List[TextClassificationOutputElement]`: a list of [`TextClassificationOutputElement`] items containing the predicted label and associated probability. + `list[TextClassificationOutputElement]`: a list of [`TextClassificationOutputElement`] items containing the predicted label and associated probability. Raises: [`InferenceTimeoutError`]: @@ -2008,8 +2008,8 @@ async def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2038,8 +2038,8 @@ async def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2068,8 +2068,8 @@ async def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, # Manual default value seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2098,8 +2098,8 @@ async def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2128,8 +2128,8 @@ async def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2157,8 +2157,8 @@ async def text_generation( repetition_penalty: Optional[float] = None, return_full_text: Optional[bool] = None, seed: Optional[int] = None, - stop: Optional[List[str]] = None, - stop_sequences: Optional[List[str]] = None, # Deprecated, use `stop` instead + stop: Optional[list[str]] = None, + stop_sequences: Optional[list[str]] = None, # Deprecated, use `stop` instead temperature: Optional[float] = None, top_k: Optional[int] = None, top_n_tokens: Optional[int] = None, @@ -2214,9 +2214,9 @@ async def text_generation( Whether to prepend the prompt to the generated text seed (`int`, *optional*): Random sampling seed - stop (`List[str]`, *optional*): + stop (`list[str]`, *optional*): Stop generating tokens if a member of `stop` is generated. - stop_sequences (`List[str]`, *optional*): + stop_sequences (`list[str]`, *optional*): Deprecated argument. Use `stop` instead. temperature (`float`, *optional*): The value used to module the logits distribution. @@ -2494,7 +2494,7 @@ async def text_to_image( model: Optional[str] = None, scheduler: Optional[str] = None, seed: Optional[int] = None, - extra_body: Optional[Dict[str, Any]] = None, + extra_body: Optional[dict[str, Any]] = None, ) -> "Image": """ Generate an image based on a given text using a specified model. @@ -2532,7 +2532,7 @@ async def text_to_image( Override the scheduler with a compatible one. seed (`int`, *optional*): Seed for the random number generator. - extra_body (`Dict[str, Any]`, *optional*): + extra_body (`dict[str, Any]`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. @@ -2632,11 +2632,11 @@ async def text_to_video( *, model: Optional[str] = None, guidance_scale: Optional[float] = None, - negative_prompt: Optional[List[str]] = None, + negative_prompt: Optional[list[str]] = None, num_frames: Optional[float] = None, num_inference_steps: Optional[int] = None, seed: Optional[int] = None, - extra_body: Optional[Dict[str, Any]] = None, + extra_body: Optional[dict[str, Any]] = None, ) -> bytes: """ Generate a video based on a given text. @@ -2655,7 +2655,7 @@ async def text_to_video( guidance_scale (`float`, *optional*): A higher guidance scale value encourages the model to generate videos closely linked to the text prompt, but values too high may cause saturation and other artifacts. - negative_prompt (`List[str]`, *optional*): + negative_prompt (`list[str]`, *optional*): One or several prompt to guide what NOT to include in video generation. num_frames (`float`, *optional*): The num_frames parameter determines how many video frames are generated. @@ -2664,7 +2664,7 @@ async def text_to_video( expense of slower inference. seed (`int`, *optional*): Seed for the random number generator. - extra_body (`Dict[str, Any]`, *optional*): + extra_body (`dict[str, Any]`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. @@ -2744,7 +2744,7 @@ async def text_to_speech( top_p: Optional[float] = None, typical_p: Optional[float] = None, use_cache: Optional[bool] = None, - extra_body: Optional[Dict[str, Any]] = None, + extra_body: Optional[dict[str, Any]] = None, ) -> bytes: """ Synthesize an audio of a voice pronouncing a given text. @@ -2806,7 +2806,7 @@ async def text_to_speech( paper](https://hf.co/papers/2202.00666) for more details. use_cache (`bool`, *optional*): Whether the model should use the past last key/values attentions to speed up decoding - extra_body (`Dict[str, Any]`, *optional*): + extra_body (`dict[str, Any]`, *optional*): Additional provider-specific parameters to pass to the model. Refer to the provider's documentation for supported parameters. Returns: @@ -2939,9 +2939,9 @@ async def token_classification( *, model: Optional[str] = None, aggregation_strategy: Optional["TokenClassificationAggregationStrategy"] = None, - ignore_labels: Optional[List[str]] = None, + ignore_labels: Optional[list[str]] = None, stride: Optional[int] = None, - ) -> List[TokenClassificationOutputElement]: + ) -> list[TokenClassificationOutputElement]: """ Perform token classification on the given text. Usually used for sentence parsing, either grammatical, or Named Entity Recognition (NER) to understand keywords contained within text. @@ -2955,13 +2955,13 @@ async def token_classification( Defaults to None. aggregation_strategy (`"TokenClassificationAggregationStrategy"`, *optional*): The strategy used to fuse tokens based on model predictions - ignore_labels (`List[str`, *optional*): + ignore_labels (`list[str`, *optional*): A list of labels to ignore stride (`int`, *optional*): The number of overlapping tokens between chunks when splitting the input text. Returns: - `List[TokenClassificationOutputElement]`: List of [`TokenClassificationOutputElement`] items containing the entity group, confidence score, word, start and end index. + `list[TokenClassificationOutputElement]`: List of [`TokenClassificationOutputElement`] items containing the entity group, confidence score, word, start and end index. Raises: [`InferenceTimeoutError`]: @@ -3018,7 +3018,7 @@ async def translation( tgt_lang: Optional[str] = None, clean_up_tokenization_spaces: Optional[bool] = None, truncation: Optional["TranslationTruncationStrategy"] = None, - generate_parameters: Optional[Dict[str, Any]] = None, + generate_parameters: Optional[dict[str, Any]] = None, ) -> TranslationOutput: """ Convert text from one language to another. @@ -3043,7 +3043,7 @@ async def translation( Whether to clean up the potential extra spaces in the text output. truncation (`"TranslationTruncationStrategy"`, *optional*): The truncation strategy to use. - generate_parameters (`Dict[str, Any]`, *optional*): + generate_parameters (`dict[str, Any]`, *optional*): Additional parametrization of the text generation algorithm. Returns: @@ -3106,7 +3106,7 @@ async def visual_question_answering( *, model: Optional[str] = None, top_k: Optional[int] = None, - ) -> List[VisualQuestionAnsweringOutputElement]: + ) -> list[VisualQuestionAnsweringOutputElement]: """ Answering open-ended questions based on an image. @@ -3123,7 +3123,7 @@ async def visual_question_answering( The number of answers to return (will be chosen by order of likelihood). Note that we return less than topk answers if there are not enough options available within the context. Returns: - `List[VisualQuestionAnsweringOutputElement]`: a list of [`VisualQuestionAnsweringOutputElement`] items containing the predicted label and associated probability. + `list[VisualQuestionAnsweringOutputElement]`: a list of [`VisualQuestionAnsweringOutputElement`] items containing the predicted label and associated probability. Raises: `InferenceTimeoutError`: @@ -3162,21 +3162,21 @@ async def visual_question_answering( async def zero_shot_classification( self, text: str, - candidate_labels: List[str], + candidate_labels: list[str], *, multi_label: Optional[bool] = False, hypothesis_template: Optional[str] = None, model: Optional[str] = None, - ) -> List[ZeroShotClassificationOutputElement]: + ) -> list[ZeroShotClassificationOutputElement]: """ Provide as input a text and a set of candidate labels to classify the input text. Args: text (`str`): The input text to classify. - candidate_labels (`List[str]`): + candidate_labels (`list[str]`): The set of possible class labels to classify the text into. - labels (`List[str]`, *optional*): + labels (`list[str]`, *optional*): (deprecated) List of strings. Each string is the verbalization of a possible label for the input text. multi_label (`bool`, *optional*): Whether multiple candidate labels can be true. If false, the scores are normalized such that the sum of @@ -3191,7 +3191,7 @@ async def zero_shot_classification( Returns: - `List[ZeroShotClassificationOutputElement]`: List of [`ZeroShotClassificationOutputElement`] items containing the predicted labels and their confidence. + `list[ZeroShotClassificationOutputElement]`: List of [`ZeroShotClassificationOutputElement`] items containing the predicted labels and their confidence. Raises: [`InferenceTimeoutError`]: @@ -3270,22 +3270,22 @@ async def zero_shot_classification( async def zero_shot_image_classification( self, image: ContentT, - candidate_labels: List[str], + candidate_labels: list[str], *, model: Optional[str] = None, hypothesis_template: Optional[str] = None, # deprecated argument - labels: List[str] = None, # type: ignore - ) -> List[ZeroShotImageClassificationOutputElement]: + labels: list[str] = None, # type: ignore + ) -> list[ZeroShotImageClassificationOutputElement]: """ Provide input image and text labels to predict text labels for the image. Args: image (`Union[str, Path, bytes, BinaryIO, PIL.Image.Image]`): The input image to caption. It can be raw bytes, an image file, a URL to an online image, or a PIL Image. - candidate_labels (`List[str]`): + candidate_labels (`list[str]`): The candidate labels for this image - labels (`List[str]`, *optional*): + labels (`list[str]`, *optional*): (deprecated) List of string possible labels. There must be at least 2 labels. model (`str`, *optional*): The model to use for inference. Can be a model ID hosted on the Hugging Face Hub or a URL to a deployed @@ -3295,7 +3295,7 @@ async def zero_shot_image_classification( replacing the placeholder with the candidate labels. Returns: - `List[ZeroShotImageClassificationOutputElement]`: List of [`ZeroShotImageClassificationOutputElement`] items containing the predicted labels and their confidence. + `list[ZeroShotImageClassificationOutputElement]`: List of [`ZeroShotImageClassificationOutputElement`] items containing the predicted labels and their confidence. Raises: [`InferenceTimeoutError`]: @@ -3335,7 +3335,7 @@ async def zero_shot_image_classification( response = await self._inner_post(request_parameters) return ZeroShotImageClassificationOutputElement.parse_obj_as_list(response) - async def get_endpoint_info(self, *, model: Optional[str] = None) -> Dict[str, Any]: + async def get_endpoint_info(self, *, model: Optional[str] = None) -> dict[str, Any]: """ Get information about the deployed endpoint. @@ -3348,7 +3348,7 @@ async def get_endpoint_info(self, *, model: Optional[str] = None) -> Dict[str, A Inference Endpoint. This parameter overrides the model defined at the instance level. Defaults to None. Returns: - `Dict[str, Any]`: Information about the endpoint. + `dict[str, Any]`: Information about the endpoint. Example: ```py diff --git a/src/huggingface_hub/inference/_generated/types/automatic_speech_recognition.py b/src/huggingface_hub/inference/_generated/types/automatic_speech_recognition.py index f6bfd28256..2e6afc4411 100644 --- a/src/huggingface_hub/inference/_generated/types/automatic_speech_recognition.py +++ b/src/huggingface_hub/inference/_generated/types/automatic_speech_recognition.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import List, Literal, Optional, Union +from typing import Literal, Optional, Union from .base import BaseInferenceType, dataclass_with_extra @@ -97,7 +97,7 @@ class AutomaticSpeechRecognitionInput(BaseInferenceType): class AutomaticSpeechRecognitionOutputChunk(BaseInferenceType): text: str """A chunk of text identified by the model""" - timestamp: List[float] + timestamp: list[float] """The start and end timestamps corresponding with the text""" @@ -107,7 +107,7 @@ class AutomaticSpeechRecognitionOutput(BaseInferenceType): text: str """The recognized text.""" - chunks: Optional[List[AutomaticSpeechRecognitionOutputChunk]] = None + chunks: Optional[list[AutomaticSpeechRecognitionOutputChunk]] = None """When returnTimestamps is enabled, chunks contains a list of audio chunks identified by the model. """ diff --git a/src/huggingface_hub/inference/_generated/types/base.py b/src/huggingface_hub/inference/_generated/types/base.py index 1f0c4687ce..2c6df61c0e 100644 --- a/src/huggingface_hub/inference/_generated/types/base.py +++ b/src/huggingface_hub/inference/_generated/types/base.py @@ -15,8 +15,9 @@ import inspect import json +import types from dataclasses import asdict, dataclass -from typing import Any, Dict, List, Type, TypeVar, Union, get_args +from typing import Any, TypeVar, Union, get_args T = TypeVar("T", bound="BaseInferenceType") @@ -28,7 +29,7 @@ def _repr_with_extra(self): return f"{self.__class__.__name__}({', '.join(f'{k}={self.__dict__[k]!r}' for k in fields + other_fields)})" -def dataclass_with_extra(cls: Type[T]) -> Type[T]: +def dataclass_with_extra(cls: type[T]) -> type[T]: """Decorator to add a custom __repr__ method to a dataclass, showing all fields, including extra ones. This decorator only works with dataclasses that inherit from `BaseInferenceType`. @@ -49,7 +50,7 @@ class BaseInferenceType(dict): """ @classmethod - def parse_obj_as_list(cls: Type[T], data: Union[bytes, str, List, Dict]) -> List[T]: + def parse_obj_as_list(cls: type[T], data: Union[bytes, str, list, dict]) -> list[T]: """Alias to parse server response and return a single instance. See `parse_obj` for more details. @@ -60,7 +61,7 @@ def parse_obj_as_list(cls: Type[T], data: Union[bytes, str, List, Dict]) -> List return output @classmethod - def parse_obj_as_instance(cls: Type[T], data: Union[bytes, str, List, Dict]) -> T: + def parse_obj_as_instance(cls: type[T], data: Union[bytes, str, list, dict]) -> T: """Alias to parse server response and return a single instance. See `parse_obj` for more details. @@ -71,7 +72,7 @@ def parse_obj_as_instance(cls: Type[T], data: Union[bytes, str, List, Dict]) -> return output @classmethod - def parse_obj(cls: Type[T], data: Union[bytes, str, List, Dict]) -> Union[List[T], T]: + def parse_obj(cls: type[T], data: Union[bytes, str, list, dict]) -> Union[list[T], T]: """Parse server response as a dataclass or list of dataclasses. To enable future-compatibility, we want to handle cases where the server return more fields than expected. @@ -85,7 +86,7 @@ def parse_obj(cls: Type[T], data: Union[bytes, str, List, Dict]) -> Union[List[T data = json.loads(data) # If a list, parse each item individually - if isinstance(data, List): + if isinstance(data, list): return [cls.parse_obj(d) for d in data] # type: ignore [misc] # At this point, we expect a dict @@ -109,7 +110,9 @@ def parse_obj(cls: Type[T], data: Union[bytes, str, List, Dict]) -> Union[List[T else: expected_types = get_args(field_type) for expected_type in expected_types: - if getattr(expected_type, "_name", None) == "List": + if ( + isinstance(expected_type, types.GenericAlias) and expected_type.__origin__ is list + ) or getattr(expected_type, "_name", None) == "List": expected_type = get_args(expected_type)[ 0 ] # assume same type for all items in the list diff --git a/src/huggingface_hub/inference/_generated/types/chat_completion.py b/src/huggingface_hub/inference/_generated/types/chat_completion.py index ba708a7009..db814b01ae 100644 --- a/src/huggingface_hub/inference/_generated/types/chat_completion.py +++ b/src/huggingface_hub/inference/_generated/types/chat_completion.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, Dict, List, Literal, Optional, Union +from typing import Any, Literal, Optional, Union from .base import BaseInferenceType, dataclass_with_extra @@ -40,9 +40,9 @@ class ChatCompletionInputToolCall(BaseInferenceType): @dataclass_with_extra class ChatCompletionInputMessage(BaseInferenceType): role: str - content: Optional[Union[List[ChatCompletionInputMessageChunk], str]] = None + content: Optional[Union[list[ChatCompletionInputMessageChunk], str]] = None name: Optional[str] = None - tool_calls: Optional[List[ChatCompletionInputToolCall]] = None + tool_calls: Optional[list[ChatCompletionInputToolCall]] = None @dataclass_with_extra @@ -56,7 +56,7 @@ class ChatCompletionInputJSONSchema(BaseInferenceType): A description of what the response format is for, used by the model to determine how to respond in the format. """ - schema: Optional[Dict[str, object]] = None + schema: Optional[dict[str, object]] = None """ The schema for the response format, described as a JSON Schema object. Learn how to build JSON schemas [here](https://json-schema.org/). @@ -129,14 +129,14 @@ class ChatCompletionInput(BaseInferenceType): https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-tgi-import.ts. """ - messages: List[ChatCompletionInputMessage] + messages: list[ChatCompletionInputMessage] """A list of messages comprising the conversation so far.""" frequency_penalty: Optional[float] = None """Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. """ - logit_bias: Optional[List[float]] = None + logit_bias: Optional[list[float]] = None """UNUSED Modify the likelihood of specified tokens appearing in the completion. Accepts a JSON object that maps tokens @@ -172,7 +172,7 @@ class ChatCompletionInput(BaseInferenceType): """ response_format: Optional[ChatCompletionInputGrammarType] = None seed: Optional[int] = None - stop: Optional[List[str]] = None + stop: Optional[list[str]] = None """Up to 4 sequences where the API will stop generating further tokens.""" stream: Optional[bool] = None stream_options: Optional[ChatCompletionInputStreamOptions] = None @@ -185,7 +185,7 @@ class ChatCompletionInput(BaseInferenceType): tool_choice: Optional[Union[ChatCompletionInputToolChoiceClass, "ChatCompletionInputToolChoiceEnum"]] = None tool_prompt: Optional[str] = None """A prompt to be appended before the tools""" - tools: Optional[List[ChatCompletionInputTool]] = None + tools: Optional[list[ChatCompletionInputTool]] = None """A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. @@ -213,12 +213,12 @@ class ChatCompletionOutputTopLogprob(BaseInferenceType): class ChatCompletionOutputLogprob(BaseInferenceType): logprob: float token: str - top_logprobs: List[ChatCompletionOutputTopLogprob] + top_logprobs: list[ChatCompletionOutputTopLogprob] @dataclass_with_extra class ChatCompletionOutputLogprobs(BaseInferenceType): - content: List[ChatCompletionOutputLogprob] + content: list[ChatCompletionOutputLogprob] @dataclass_with_extra @@ -241,7 +241,7 @@ class ChatCompletionOutputMessage(BaseInferenceType): content: Optional[str] = None reasoning: Optional[str] = None tool_call_id: Optional[str] = None - tool_calls: Optional[List[ChatCompletionOutputToolCall]] = None + tool_calls: Optional[list[ChatCompletionOutputToolCall]] = None @dataclass_with_extra @@ -267,7 +267,7 @@ class ChatCompletionOutput(BaseInferenceType): https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-tgi-import.ts. """ - choices: List[ChatCompletionOutputComplete] + choices: list[ChatCompletionOutputComplete] created: int id: str model: str @@ -295,7 +295,7 @@ class ChatCompletionStreamOutputDelta(BaseInferenceType): content: Optional[str] = None reasoning: Optional[str] = None tool_call_id: Optional[str] = None - tool_calls: Optional[List[ChatCompletionStreamOutputDeltaToolCall]] = None + tool_calls: Optional[list[ChatCompletionStreamOutputDeltaToolCall]] = None @dataclass_with_extra @@ -308,12 +308,12 @@ class ChatCompletionStreamOutputTopLogprob(BaseInferenceType): class ChatCompletionStreamOutputLogprob(BaseInferenceType): logprob: float token: str - top_logprobs: List[ChatCompletionStreamOutputTopLogprob] + top_logprobs: list[ChatCompletionStreamOutputTopLogprob] @dataclass_with_extra class ChatCompletionStreamOutputLogprobs(BaseInferenceType): - content: List[ChatCompletionStreamOutputLogprob] + content: list[ChatCompletionStreamOutputLogprob] @dataclass_with_extra @@ -339,7 +339,7 @@ class ChatCompletionStreamOutput(BaseInferenceType): https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-tgi-import.ts. """ - choices: List[ChatCompletionStreamOutputChoice] + choices: list[ChatCompletionStreamOutputChoice] created: int id: str model: str diff --git a/src/huggingface_hub/inference/_generated/types/depth_estimation.py b/src/huggingface_hub/inference/_generated/types/depth_estimation.py index 1e09bdffa1..765c3635f9 100644 --- a/src/huggingface_hub/inference/_generated/types/depth_estimation.py +++ b/src/huggingface_hub/inference/_generated/types/depth_estimation.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, Dict, Optional +from typing import Any, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -14,7 +14,7 @@ class DepthEstimationInput(BaseInferenceType): inputs: Any """The input image data""" - parameters: Optional[Dict[str, Any]] = None + parameters: Optional[dict[str, Any]] = None """Additional inference parameters for Depth Estimation""" diff --git a/src/huggingface_hub/inference/_generated/types/document_question_answering.py b/src/huggingface_hub/inference/_generated/types/document_question_answering.py index 2457d2c8c2..e3886041d6 100644 --- a/src/huggingface_hub/inference/_generated/types/document_question_answering.py +++ b/src/huggingface_hub/inference/_generated/types/document_question_answering.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, List, Optional, Union +from typing import Any, Optional, Union from .base import BaseInferenceType, dataclass_with_extra @@ -46,7 +46,7 @@ class DocumentQuestionAnsweringParameters(BaseInferenceType): """The number of answers to return (will be chosen by order of likelihood). Can return less than top_k answers if there are not enough options available within the context. """ - word_boxes: Optional[List[Union[List[float], str]]] = None + word_boxes: Optional[list[Union[list[float], str]]] = None """A list of words and bounding boxes (normalized 0->1000). If provided, the inference will skip the OCR step and use the provided bounding boxes instead. """ diff --git a/src/huggingface_hub/inference/_generated/types/feature_extraction.py b/src/huggingface_hub/inference/_generated/types/feature_extraction.py index e965ddbac2..a6b9aa1937 100644 --- a/src/huggingface_hub/inference/_generated/types/feature_extraction.py +++ b/src/huggingface_hub/inference/_generated/types/feature_extraction.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import List, Literal, Optional, Union +from typing import Literal, Optional, Union from .base import BaseInferenceType, dataclass_with_extra @@ -19,7 +19,7 @@ class FeatureExtractionInput(BaseInferenceType): https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-tei-import.ts. """ - inputs: Union[List[str], str] + inputs: Union[list[str], str] """The text or list of texts to embed.""" normalize: Optional[bool] = None prompt_name: Optional[str] = None diff --git a/src/huggingface_hub/inference/_generated/types/fill_mask.py b/src/huggingface_hub/inference/_generated/types/fill_mask.py index dfcdc56bc5..848421dc13 100644 --- a/src/huggingface_hub/inference/_generated/types/fill_mask.py +++ b/src/huggingface_hub/inference/_generated/types/fill_mask.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, List, Optional +from typing import Any, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -12,7 +12,7 @@ class FillMaskParameters(BaseInferenceType): """Additional inference parameters for Fill Mask""" - targets: Optional[List[str]] = None + targets: Optional[list[str]] = None """When passed, the model will limit the scores to the passed targets instead of looking up in the whole vocabulary. If the provided targets are not in the model vocab, they will be tokenized and the first resulting token will be used (with a warning, and that might be diff --git a/src/huggingface_hub/inference/_generated/types/sentence_similarity.py b/src/huggingface_hub/inference/_generated/types/sentence_similarity.py index 66e8bb4d93..4dd42c0bd8 100644 --- a/src/huggingface_hub/inference/_generated/types/sentence_similarity.py +++ b/src/huggingface_hub/inference/_generated/types/sentence_similarity.py @@ -3,14 +3,14 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, Dict, List, Optional +from typing import Any, Optional from .base import BaseInferenceType, dataclass_with_extra @dataclass_with_extra class SentenceSimilarityInputData(BaseInferenceType): - sentences: List[str] + sentences: list[str] """A list of strings which will be compared against the source_sentence.""" source_sentence: str """The string that you wish to compare the other strings with. This can be a phrase, @@ -23,5 +23,5 @@ class SentenceSimilarityInput(BaseInferenceType): """Inputs for Sentence similarity inference""" inputs: SentenceSimilarityInputData - parameters: Optional[Dict[str, Any]] = None + parameters: Optional[dict[str, Any]] = None """Additional inference parameters for Sentence Similarity""" diff --git a/src/huggingface_hub/inference/_generated/types/summarization.py b/src/huggingface_hub/inference/_generated/types/summarization.py index 33eae6fcba..0103853aa6 100644 --- a/src/huggingface_hub/inference/_generated/types/summarization.py +++ b/src/huggingface_hub/inference/_generated/types/summarization.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, Dict, Literal, Optional +from typing import Any, Literal, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -17,7 +17,7 @@ class SummarizationParameters(BaseInferenceType): clean_up_tokenization_spaces: Optional[bool] = None """Whether to clean up the potential extra spaces in the text output.""" - generate_parameters: Optional[Dict[str, Any]] = None + generate_parameters: Optional[dict[str, Any]] = None """Additional parametrization of the text generation algorithm.""" truncation: Optional["SummarizationTruncationStrategy"] = None """The truncation strategy to use.""" diff --git a/src/huggingface_hub/inference/_generated/types/table_question_answering.py b/src/huggingface_hub/inference/_generated/types/table_question_answering.py index 10e208eeeb..cceb59fde9 100644 --- a/src/huggingface_hub/inference/_generated/types/table_question_answering.py +++ b/src/huggingface_hub/inference/_generated/types/table_question_answering.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Dict, List, Literal, Optional +from typing import Literal, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -14,7 +14,7 @@ class TableQuestionAnsweringInputData(BaseInferenceType): question: str """The question to be answered about the table""" - table: Dict[str, List[str]] + table: dict[str, list[str]] """The table to serve as context for the questions""" @@ -54,9 +54,9 @@ class TableQuestionAnsweringOutputElement(BaseInferenceType): """The answer of the question given the table. If there is an aggregator, the answer will be preceded by `AGGREGATOR >`. """ - cells: List[str] + cells: list[str] """List of strings made up of the answer cell values.""" - coordinates: List[List[int]] + coordinates: list[list[int]] """Coordinates of the cells of the answers.""" aggregator: Optional[str] = None """If the model has an aggregator, this returns the aggregator.""" diff --git a/src/huggingface_hub/inference/_generated/types/text2text_generation.py b/src/huggingface_hub/inference/_generated/types/text2text_generation.py index 34ac74e21e..bda2211902 100644 --- a/src/huggingface_hub/inference/_generated/types/text2text_generation.py +++ b/src/huggingface_hub/inference/_generated/types/text2text_generation.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, Dict, Literal, Optional +from typing import Any, Literal, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -17,7 +17,7 @@ class Text2TextGenerationParameters(BaseInferenceType): clean_up_tokenization_spaces: Optional[bool] = None """Whether to clean up the potential extra spaces in the text output.""" - generate_parameters: Optional[Dict[str, Any]] = None + generate_parameters: Optional[dict[str, Any]] = None """Additional parametrization of the text generation algorithm""" truncation: Optional["Text2TextGenerationTruncationStrategy"] = None """The truncation strategy to use""" diff --git a/src/huggingface_hub/inference/_generated/types/text_generation.py b/src/huggingface_hub/inference/_generated/types/text_generation.py index 9b79cc691d..b470198b40 100644 --- a/src/huggingface_hub/inference/_generated/types/text_generation.py +++ b/src/huggingface_hub/inference/_generated/types/text_generation.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, List, Literal, Optional +from typing import Any, Literal, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -49,7 +49,7 @@ class TextGenerationInputGenerateParameters(BaseInferenceType): """Whether to prepend the prompt to the generated text""" seed: Optional[int] = None """Random sampling seed.""" - stop: Optional[List[str]] = None + stop: Optional[list[str]] = None """Stop generating tokens if a member of `stop` is generated.""" temperature: Optional[float] = None """The value used to module the logits distribution.""" @@ -108,21 +108,21 @@ class TextGenerationOutputBestOfSequence(BaseInferenceType): finish_reason: "TextGenerationOutputFinishReason" generated_text: str generated_tokens: int - prefill: List[TextGenerationOutputPrefillToken] - tokens: List[TextGenerationOutputToken] + prefill: list[TextGenerationOutputPrefillToken] + tokens: list[TextGenerationOutputToken] seed: Optional[int] = None - top_tokens: Optional[List[List[TextGenerationOutputToken]]] = None + top_tokens: Optional[list[list[TextGenerationOutputToken]]] = None @dataclass_with_extra class TextGenerationOutputDetails(BaseInferenceType): finish_reason: "TextGenerationOutputFinishReason" generated_tokens: int - prefill: List[TextGenerationOutputPrefillToken] - tokens: List[TextGenerationOutputToken] - best_of_sequences: Optional[List[TextGenerationOutputBestOfSequence]] = None + prefill: list[TextGenerationOutputPrefillToken] + tokens: list[TextGenerationOutputToken] + best_of_sequences: Optional[list[TextGenerationOutputBestOfSequence]] = None seed: Optional[int] = None - top_tokens: Optional[List[List[TextGenerationOutputToken]]] = None + top_tokens: Optional[list[list[TextGenerationOutputToken]]] = None @dataclass_with_extra @@ -165,4 +165,4 @@ class TextGenerationStreamOutput(BaseInferenceType): token: TextGenerationStreamOutputToken details: Optional[TextGenerationStreamOutputStreamDetails] = None generated_text: Optional[str] = None - top_tokens: Optional[List[TextGenerationStreamOutputToken]] = None + top_tokens: Optional[list[TextGenerationStreamOutputToken]] = None diff --git a/src/huggingface_hub/inference/_generated/types/text_to_video.py b/src/huggingface_hub/inference/_generated/types/text_to_video.py index e54a1bc094..a7e9637821 100644 --- a/src/huggingface_hub/inference/_generated/types/text_to_video.py +++ b/src/huggingface_hub/inference/_generated/types/text_to_video.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, List, Optional +from typing import Any, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -16,7 +16,7 @@ class TextToVideoParameters(BaseInferenceType): """A higher guidance scale value encourages the model to generate videos closely linked to the text prompt, but values too high may cause saturation and other artifacts. """ - negative_prompt: Optional[List[str]] = None + negative_prompt: Optional[list[str]] = None """One or several prompt to guide what NOT to include in video generation.""" num_frames: Optional[float] = None """The num_frames parameter determines how many video frames are generated.""" diff --git a/src/huggingface_hub/inference/_generated/types/token_classification.py b/src/huggingface_hub/inference/_generated/types/token_classification.py index e039b6a1db..b40f4b5f6f 100644 --- a/src/huggingface_hub/inference/_generated/types/token_classification.py +++ b/src/huggingface_hub/inference/_generated/types/token_classification.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import List, Literal, Optional +from typing import Literal, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -17,7 +17,7 @@ class TokenClassificationParameters(BaseInferenceType): aggregation_strategy: Optional["TokenClassificationAggregationStrategy"] = None """The strategy used to fuse tokens based on model predictions""" - ignore_labels: Optional[List[str]] = None + ignore_labels: Optional[list[str]] = None """A list of labels to ignore""" stride: Optional[int] = None """The number of overlapping tokens between chunks when splitting the input text.""" diff --git a/src/huggingface_hub/inference/_generated/types/translation.py b/src/huggingface_hub/inference/_generated/types/translation.py index df95b7dbb1..59619e9a90 100644 --- a/src/huggingface_hub/inference/_generated/types/translation.py +++ b/src/huggingface_hub/inference/_generated/types/translation.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import Any, Dict, Literal, Optional +from typing import Any, Literal, Optional from .base import BaseInferenceType, dataclass_with_extra @@ -17,7 +17,7 @@ class TranslationParameters(BaseInferenceType): clean_up_tokenization_spaces: Optional[bool] = None """Whether to clean up the potential extra spaces in the text output.""" - generate_parameters: Optional[Dict[str, Any]] = None + generate_parameters: Optional[dict[str, Any]] = None """Additional parametrization of the text generation algorithm.""" src_lang: Optional[str] = None """The source language of the text. Required for models that can translate from multiple diff --git a/src/huggingface_hub/inference/_generated/types/zero_shot_classification.py b/src/huggingface_hub/inference/_generated/types/zero_shot_classification.py index 47b32492e3..7b0dd13237 100644 --- a/src/huggingface_hub/inference/_generated/types/zero_shot_classification.py +++ b/src/huggingface_hub/inference/_generated/types/zero_shot_classification.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import List, Optional +from typing import Optional from .base import BaseInferenceType, dataclass_with_extra @@ -12,7 +12,7 @@ class ZeroShotClassificationParameters(BaseInferenceType): """Additional inference parameters for Zero Shot Classification""" - candidate_labels: List[str] + candidate_labels: list[str] """The set of possible class labels to classify the text into.""" hypothesis_template: Optional[str] = None """The sentence used in conjunction with `candidate_labels` to attempt the text diff --git a/src/huggingface_hub/inference/_generated/types/zero_shot_image_classification.py b/src/huggingface_hub/inference/_generated/types/zero_shot_image_classification.py index 998d66b6b4..ed138eada5 100644 --- a/src/huggingface_hub/inference/_generated/types/zero_shot_image_classification.py +++ b/src/huggingface_hub/inference/_generated/types/zero_shot_image_classification.py @@ -3,7 +3,7 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import List, Optional +from typing import Optional from .base import BaseInferenceType, dataclass_with_extra @@ -12,7 +12,7 @@ class ZeroShotImageClassificationParameters(BaseInferenceType): """Additional inference parameters for Zero Shot Image Classification""" - candidate_labels: List[str] + candidate_labels: list[str] """The candidate labels for this image""" hypothesis_template: Optional[str] = None """The sentence used in conjunction with `candidate_labels` to attempt the image diff --git a/src/huggingface_hub/inference/_generated/types/zero_shot_object_detection.py b/src/huggingface_hub/inference/_generated/types/zero_shot_object_detection.py index 8ef76b5fcb..e981463b25 100644 --- a/src/huggingface_hub/inference/_generated/types/zero_shot_object_detection.py +++ b/src/huggingface_hub/inference/_generated/types/zero_shot_object_detection.py @@ -3,8 +3,6 @@ # See: # - script: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/scripts/inference-codegen.ts # - specs: https://github.com/huggingface/huggingface.js/tree/main/packages/tasks/src/tasks. -from typing import List - from .base import BaseInferenceType, dataclass_with_extra @@ -12,7 +10,7 @@ class ZeroShotObjectDetectionParameters(BaseInferenceType): """Additional inference parameters for Zero Shot Object Detection""" - candidate_labels: List[str] + candidate_labels: list[str] """The candidate labels for this image""" diff --git a/src/huggingface_hub/inference/_mcp/agent.py b/src/huggingface_hub/inference/_mcp/agent.py index 4f88016ba7..0a372608d0 100644 --- a/src/huggingface_hub/inference/_mcp/agent.py +++ b/src/huggingface_hub/inference/_mcp/agent.py @@ -1,7 +1,7 @@ from __future__ import annotations import asyncio -from typing import AsyncGenerator, Dict, Iterable, List, Optional, Union +from typing import AsyncGenerator, Iterable, Optional, Union from huggingface_hub import ChatCompletionInputMessage, ChatCompletionStreamOutput, MCPClient @@ -24,7 +24,7 @@ class Agent(MCPClient): model (`str`, *optional*): The model to run inference with. Can be a model id hosted on the Hugging Face Hub, e.g. `meta-llama/Meta-Llama-3-8B-Instruct` or a URL to a deployed Inference Endpoint or other local or remote endpoint. - servers (`Iterable[Dict]`): + servers (`Iterable[dict]`): MCP servers to connect to. Each server is a dictionary containing a `type` key and a `config` key. The `type` key can be `"stdio"` or `"sse"`, and the `config` key is a dictionary of arguments for the server. provider (`str`, *optional*): Name of the provider to use for inference. Defaults to "auto" i.e. the first of the providers available for the model, sorted by the user's order in https://hf.co/settings/inference-providers. @@ -49,7 +49,7 @@ def __init__( ): super().__init__(model=model, provider=provider, base_url=base_url, api_key=api_key) self._servers_cfg = list(servers) - self.messages: List[Union[Dict, ChatCompletionInputMessage]] = [ + self.messages: list[Union[dict, ChatCompletionInputMessage]] = [ {"role": "system", "content": prompt or DEFAULT_SYSTEM_PROMPT} ] diff --git a/src/huggingface_hub/inference/_mcp/constants.py b/src/huggingface_hub/inference/_mcp/constants.py index 1ccade43b1..737a9ae549 100644 --- a/src/huggingface_hub/inference/_mcp/constants.py +++ b/src/huggingface_hub/inference/_mcp/constants.py @@ -2,7 +2,6 @@ import sys from pathlib import Path -from typing import List from huggingface_hub import ChatCompletionInputTool @@ -76,7 +75,7 @@ } ) -EXIT_LOOP_TOOLS: List[ChatCompletionInputTool] = [TASK_COMPLETE_TOOL, ASK_QUESTION_TOOL] +EXIT_LOOP_TOOLS: list[ChatCompletionInputTool] = [TASK_COMPLETE_TOOL, ASK_QUESTION_TOOL] DEFAULT_REPO_ID = "tiny-agents/tiny-agents" diff --git a/src/huggingface_hub/inference/_mcp/mcp_client.py b/src/huggingface_hub/inference/_mcp/mcp_client.py index 2383303450..51368bce1f 100644 --- a/src/huggingface_hub/inference/_mcp/mcp_client.py +++ b/src/huggingface_hub/inference/_mcp/mcp_client.py @@ -3,9 +3,9 @@ from contextlib import AsyncExitStack from datetime import timedelta from pathlib import Path -from typing import TYPE_CHECKING, Any, AsyncIterable, Dict, List, Literal, Optional, Union, overload +from typing import TYPE_CHECKING, Any, AsyncIterable, Literal, Optional, TypedDict, Union, overload -from typing_extensions import NotRequired, TypeAlias, TypedDict, Unpack +from typing_extensions import NotRequired, TypeAlias, Unpack from ...utils._runtime import get_hf_hub_version from .._generated._async_client import AsyncInferenceClient @@ -32,14 +32,14 @@ class StdioServerParameters_T(TypedDict): command: str - args: NotRequired[List[str]] - env: NotRequired[Dict[str, str]] + args: NotRequired[list[str]] + env: NotRequired[dict[str, str]] cwd: NotRequired[Union[str, Path, None]] class SSEServerParameters_T(TypedDict): url: str - headers: NotRequired[Dict[str, Any]] + headers: NotRequired[dict[str, Any]] timeout: NotRequired[float] sse_read_timeout: NotRequired[float] @@ -84,9 +84,9 @@ def __init__( api_key: Optional[str] = None, ): # Initialize MCP sessions as a dictionary of ClientSession objects - self.sessions: Dict[ToolName, "ClientSession"] = {} + self.sessions: dict[ToolName, "ClientSession"] = {} self.exit_stack = AsyncExitStack() - self.available_tools: List[ChatCompletionInputTool] = [] + self.available_tools: list[ChatCompletionInputTool] = [] # To be able to send the model in the payload if `base_url` is provided if model is None and base_url is None: raise ValueError("At least one of `model` or `base_url` should be set in `MCPClient`.") @@ -132,27 +132,27 @@ async def add_mcp_server(self, type: ServerType, **params: Any): - "stdio": Standard input/output server (local) - "sse": Server-sent events (SSE) server - "http": StreamableHTTP server - **params (`Dict[str, Any]`): + **params (`dict[str, Any]`): Server parameters that can be either: - For stdio servers: - command (str): The command to run the MCP server - - args (List[str], optional): Arguments for the command - - env (Dict[str, str], optional): Environment variables for the command + - args (list[str], optional): Arguments for the command + - env (dict[str, str], optional): Environment variables for the command - cwd (Union[str, Path, None], optional): Working directory for the command - - allowed_tools (List[str], optional): List of tool names to allow from this server + - allowed_tools (list[str], optional): List of tool names to allow from this server - For SSE servers: - url (str): The URL of the SSE server - - headers (Dict[str, Any], optional): Headers for the SSE connection + - headers (dict[str, Any], optional): Headers for the SSE connection - timeout (float, optional): Connection timeout - sse_read_timeout (float, optional): SSE read timeout - - allowed_tools (List[str], optional): List of tool names to allow from this server + - allowed_tools (list[str], optional): List of tool names to allow from this server - For StreamableHTTP servers: - url (str): The URL of the StreamableHTTP server - - headers (Dict[str, Any], optional): Headers for the StreamableHTTP connection + - headers (dict[str, Any], optional): Headers for the StreamableHTTP connection - timeout (timedelta, optional): Connection timeout - sse_read_timeout (timedelta, optional): SSE read timeout - terminate_on_close (bool, optional): Whether to terminate on close - - allowed_tools (List[str], optional): List of tool names to allow from this server + - allowed_tools (list[str], optional): List of tool names to allow from this server """ from mcp import ClientSession, StdioServerParameters from mcp import types as mcp_types @@ -249,16 +249,16 @@ async def add_mcp_server(self, type: ServerType, **params: Any): async def process_single_turn_with_tools( self, - messages: List[Union[Dict, ChatCompletionInputMessage]], - exit_loop_tools: Optional[List[ChatCompletionInputTool]] = None, + messages: list[Union[dict, ChatCompletionInputMessage]], + exit_loop_tools: Optional[list[ChatCompletionInputTool]] = None, exit_if_first_chunk_no_tool: bool = False, ) -> AsyncIterable[Union[ChatCompletionStreamOutput, ChatCompletionInputMessage]]: """Process a query using `self.model` and available tools, yielding chunks and tool outputs. Args: - messages (`List[Dict]`): + messages (`list[dict]`): List of message objects representing the conversation history - exit_loop_tools (`List[ChatCompletionInputTool]`, *optional*): + exit_loop_tools (`list[ChatCompletionInputTool]`, *optional*): List of tools that should exit the generator when called exit_if_first_chunk_no_tool (`bool`, *optional*): Exit if no tool is present in the first chunks. Default to False. @@ -280,8 +280,8 @@ async def process_single_turn_with_tools( stream=True, ) - message: Dict[str, Any] = {"role": "unknown", "content": ""} - final_tool_calls: Dict[int, ChatCompletionStreamOutputDeltaToolCall] = {} + message: dict[str, Any] = {"role": "unknown", "content": ""} + final_tool_calls: dict[int, ChatCompletionStreamOutputDeltaToolCall] = {} num_of_chunks = 0 # Read from stream @@ -328,7 +328,7 @@ async def process_single_turn_with_tools( message["role"] = "assistant" # Convert final_tool_calls to the format expected by OpenAI if final_tool_calls: - tool_calls_list: List[Dict[str, Any]] = [] + tool_calls_list: list[dict[str, Any]] = [] for tc in final_tool_calls.values(): tool_calls_list.append( { @@ -346,6 +346,17 @@ async def process_single_turn_with_tools( # Process tool calls one by one for tool_call in final_tool_calls.values(): function_name = tool_call.function.name + if function_name is None: + message = ChatCompletionInputMessage.parse_obj_as_instance( + { + "role": "tool", + "tool_call_id": tool_call.id, + "content": "Invalid tool call with no function name.", + } + ) + messages.append(message) + yield message + continue # move to next tool call try: function_args = json.loads(tool_call.function.arguments or "{}") except json.JSONDecodeError as err: diff --git a/src/huggingface_hub/inference/_mcp/types.py b/src/huggingface_hub/inference/_mcp/types.py index 100f67832e..a531929a8e 100644 --- a/src/huggingface_hub/inference/_mcp/types.py +++ b/src/huggingface_hub/inference/_mcp/types.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Literal, TypedDict, Union +from typing import Literal, TypedDict, Union from typing_extensions import NotRequired @@ -13,24 +13,24 @@ class InputConfig(TypedDict, total=False): class StdioServerConfig(TypedDict): type: Literal["stdio"] command: str - args: List[str] - env: Dict[str, str] + args: list[str] + env: dict[str, str] cwd: str - allowed_tools: NotRequired[List[str]] + allowed_tools: NotRequired[list[str]] class HTTPServerConfig(TypedDict): type: Literal["http"] url: str - headers: Dict[str, str] - allowed_tools: NotRequired[List[str]] + headers: dict[str, str] + allowed_tools: NotRequired[list[str]] class SSEServerConfig(TypedDict): type: Literal["sse"] url: str - headers: Dict[str, str] - allowed_tools: NotRequired[List[str]] + headers: dict[str, str] + allowed_tools: NotRequired[list[str]] ServerConfig = Union[StdioServerConfig, HTTPServerConfig, SSEServerConfig] @@ -41,5 +41,5 @@ class AgentConfig(TypedDict): model: str provider: str apiKey: NotRequired[str] - inputs: List[InputConfig] - servers: List[ServerConfig] + inputs: list[InputConfig] + servers: list[ServerConfig] diff --git a/src/huggingface_hub/inference/_mcp/utils.py b/src/huggingface_hub/inference/_mcp/utils.py index ddab10d677..09c902815b 100644 --- a/src/huggingface_hub/inference/_mcp/utils.py +++ b/src/huggingface_hub/inference/_mcp/utils.py @@ -6,7 +6,7 @@ import json from pathlib import Path -from typing import TYPE_CHECKING, List, Optional, Tuple +from typing import TYPE_CHECKING, Optional from huggingface_hub import snapshot_download from huggingface_hub.errors import EntryNotFoundError @@ -36,7 +36,7 @@ def format_result(result: "mcp_types.CallToolResult") -> str: if len(content) == 0: return "[No content]" - formatted_parts: List[str] = [] + formatted_parts: list[str] = [] for item in content: if item.type == "text": @@ -84,10 +84,10 @@ def _get_base64_size(base64_str: str) -> int: return (len(base64_str) * 3) // 4 - padding -def _load_agent_config(agent_path: Optional[str]) -> Tuple[AgentConfig, Optional[str]]: +def _load_agent_config(agent_path: Optional[str]) -> tuple[AgentConfig, Optional[str]]: """Load server config and prompt.""" - def _read_dir(directory: Path) -> Tuple[AgentConfig, Optional[str]]: + def _read_dir(directory: Path) -> tuple[AgentConfig, Optional[str]]: cfg_file = directory / FILENAME_CONFIG if not cfg_file.exists(): raise FileNotFoundError(f" Config file not found in {directory}! Please make sure it exists locally") diff --git a/src/huggingface_hub/inference/_providers/__init__.py b/src/huggingface_hub/inference/_providers/__init__.py index ec4866c30d..2e40f32d19 100644 --- a/src/huggingface_hub/inference/_providers/__init__.py +++ b/src/huggingface_hub/inference/_providers/__init__.py @@ -1,4 +1,4 @@ -from typing import Dict, Literal, Optional, Union +from typing import Literal, Optional, Union from huggingface_hub.inference._providers.featherless_ai import ( FeatherlessConversationalTask, @@ -65,7 +65,7 @@ PROVIDER_OR_POLICY_T = Union[PROVIDER_T, Literal["auto"]] -PROVIDERS: Dict[PROVIDER_T, Dict[str, TaskProviderHelper]] = { +PROVIDERS: dict[PROVIDER_T, dict[str, TaskProviderHelper]] = { "black-forest-labs": { "text-to-image": BlackForestLabsTextToImageTask(), }, diff --git a/src/huggingface_hub/inference/_providers/_common.py b/src/huggingface_hub/inference/_providers/_common.py index 687464a934..e7f3eb1d96 100644 --- a/src/huggingface_hub/inference/_providers/_common.py +++ b/src/huggingface_hub/inference/_providers/_common.py @@ -1,5 +1,5 @@ from functools import lru_cache -from typing import Any, Dict, List, Optional, Union, overload +from typing import Any, Optional, Union, overload from huggingface_hub import constants from huggingface_hub.hf_api import InferenceProviderMapping @@ -14,7 +14,7 @@ # Dev purposes only. # If you want to try to run inference for a new model locally before it's registered on huggingface.co # for a given Inference Provider, you can add it to the following dictionary. -HARDCODED_MODEL_INFERENCE_MAPPING: Dict[str, Dict[str, InferenceProviderMapping]] = { +HARDCODED_MODEL_INFERENCE_MAPPING: dict[str, dict[str, InferenceProviderMapping]] = { # "HF model ID" => InferenceProviderMapping object initialized with "Model ID on Inference Provider's side" # # Example: @@ -38,14 +38,14 @@ @overload -def filter_none(obj: Dict[str, Any]) -> Dict[str, Any]: ... +def filter_none(obj: dict[str, Any]) -> dict[str, Any]: ... @overload -def filter_none(obj: List[Any]) -> List[Any]: ... +def filter_none(obj: list[Any]) -> list[Any]: ... -def filter_none(obj: Union[Dict[str, Any], List[Any]]) -> Union[Dict[str, Any], List[Any]]: +def filter_none(obj: Union[dict[str, Any], list[Any]]) -> Union[dict[str, Any], list[Any]]: if isinstance(obj, dict): - cleaned: Dict[str, Any] = {} + cleaned: dict[str, Any] = {} for k, v in obj.items(): if v is None: continue @@ -72,11 +72,11 @@ def prepare_request( self, *, inputs: Any, - parameters: Dict[str, Any], - headers: Dict, + parameters: dict[str, Any], + headers: dict, model: Optional[str], api_key: Optional[str], - extra_payload: Optional[Dict[str, Any]] = None, + extra_payload: Optional[dict[str, Any]] = None, ) -> RequestParameters: """ Prepare the request to be sent to the provider. @@ -123,7 +123,7 @@ def prepare_request( def get_response( self, - response: Union[bytes, Dict], + response: Union[bytes, dict], request_params: Optional[RequestParameters] = None, ) -> Any: """ @@ -182,8 +182,8 @@ def _prepare_mapping_info(self, model: Optional[str]) -> InferenceProviderMappin return provider_mapping def _normalize_headers( - self, headers: Dict[str, Any], payload: Optional[Dict[str, Any]], data: Optional[MimeBytes] - ) -> Dict[str, Any]: + self, headers: dict[str, Any], payload: Optional[dict[str, Any]], data: Optional[MimeBytes] + ) -> dict[str, Any]: """Normalize the headers to use for the request. Override this method in subclasses for customized headers. @@ -196,7 +196,7 @@ def _normalize_headers( normalized_headers["content-type"] = "application/json" return normalized_headers - def _prepare_headers(self, headers: Dict, api_key: str) -> Dict[str, Any]: + def _prepare_headers(self, headers: dict, api_key: str) -> dict[str, Any]: """Return the headers to use for the request. Override this method in subclasses for customized headers. @@ -231,8 +231,8 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: """Return the payload to use for the request, as a dict. Override this method in subclasses for customized payloads. @@ -243,9 +243,9 @@ def _prepare_payload_as_dict( def _prepare_payload_as_bytes( self, inputs: Any, - parameters: Dict, + parameters: dict, provider_mapping_info: InferenceProviderMapping, - extra_payload: Optional[Dict], + extra_payload: Optional[dict], ) -> Optional[MimeBytes]: """Return the body to use for the request, as bytes. @@ -269,10 +269,10 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: def _prepare_payload_as_dict( self, - inputs: List[Union[Dict, ChatCompletionInputMessage]], - parameters: Dict, + inputs: list[Union[dict, ChatCompletionInputMessage]], + parameters: dict, provider_mapping_info: InferenceProviderMapping, - ) -> Optional[Dict]: + ) -> Optional[dict]: return filter_none({"messages": inputs, **parameters, "model": provider_mapping_info.provider_id}) @@ -289,13 +289,13 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/v1/completions" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: return filter_none({"prompt": inputs, **parameters, "model": provider_mapping_info.provider_id}) @lru_cache(maxsize=None) -def _fetch_inference_provider_mapping(model: str) -> List["InferenceProviderMapping"]: +def _fetch_inference_provider_mapping(model: str) -> list["InferenceProviderMapping"]: """ Fetch provider mappings for a model from the Hub. """ @@ -308,7 +308,7 @@ def _fetch_inference_provider_mapping(model: str) -> List["InferenceProviderMapp return provider_mapping -def recursive_merge(dict1: Dict, dict2: Dict) -> Dict: +def recursive_merge(dict1: dict, dict2: dict) -> dict: return { **dict1, **{ diff --git a/src/huggingface_hub/inference/_providers/black_forest_labs.py b/src/huggingface_hub/inference/_providers/black_forest_labs.py index a5d9683225..1d91b0b842 100644 --- a/src/huggingface_hub/inference/_providers/black_forest_labs.py +++ b/src/huggingface_hub/inference/_providers/black_forest_labs.py @@ -1,5 +1,5 @@ import time -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -18,7 +18,7 @@ class BlackForestLabsTextToImageTask(TaskProviderHelper): def __init__(self): super().__init__(provider="black-forest-labs", base_url="https://api.us1.bfl.ai", task="text-to-image") - def _prepare_headers(self, headers: Dict, api_key: str) -> Dict[str, Any]: + def _prepare_headers(self, headers: dict, api_key: str) -> dict[str, Any]: headers = super()._prepare_headers(headers, api_key) if not api_key.startswith("hf_"): _ = headers.pop("authorization") @@ -29,8 +29,8 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return f"/v1/{mapped_model}" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: parameters = filter_none(parameters) if "num_inference_steps" in parameters: parameters["steps"] = parameters.pop("num_inference_steps") @@ -39,7 +39,7 @@ def _prepare_payload_as_dict( return {"prompt": inputs, **parameters} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: """ Polling mechanism for Black Forest Labs since the API is asynchronous. """ @@ -50,7 +50,7 @@ def get_response(self, response: Union[bytes, Dict], request_params: Optional[Re response = session.get(url, headers={"Content-Type": "application/json"}) # type: ignore response.raise_for_status() # type: ignore - response_json: Dict = response.json() # type: ignore + response_json: dict = response.json() # type: ignore status = response_json.get("status") logger.info( f"Polling generation result from {url}. Current status: {status}. " diff --git a/src/huggingface_hub/inference/_providers/cohere.py b/src/huggingface_hub/inference/_providers/cohere.py index a5e9191cae..0190d5449b 100644 --- a/src/huggingface_hub/inference/_providers/cohere.py +++ b/src/huggingface_hub/inference/_providers/cohere.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Optional from huggingface_hub.hf_api import InferenceProviderMapping @@ -17,8 +17,8 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/compatibility/v1/chat/completions" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: payload = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) response_format = parameters.get("response_format") if isinstance(response_format, dict) and response_format.get("type") == "json_schema": diff --git a/src/huggingface_hub/inference/_providers/fal_ai.py b/src/huggingface_hub/inference/_providers/fal_ai.py index b39b33f616..17cb0168b7 100644 --- a/src/huggingface_hub/inference/_providers/fal_ai.py +++ b/src/huggingface_hub/inference/_providers/fal_ai.py @@ -1,7 +1,7 @@ import base64 import time from abc import ABC -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from urllib.parse import urlparse from huggingface_hub import constants @@ -22,7 +22,7 @@ class FalAITask(TaskProviderHelper, ABC): def __init__(self, task: str): super().__init__(provider="fal-ai", base_url="https://fal.run", task=task) - def _prepare_headers(self, headers: Dict, api_key: str) -> Dict[str, Any]: + def _prepare_headers(self, headers: dict, api_key: str) -> dict[str, Any]: headers = super()._prepare_headers(headers, api_key) if not api_key.startswith("hf_"): headers["authorization"] = f"Key {api_key}" @@ -36,7 +36,7 @@ class FalAIQueueTask(TaskProviderHelper, ABC): def __init__(self, task: str): super().__init__(provider="fal-ai", base_url="https://queue.fal.run", task=task) - def _prepare_headers(self, headers: Dict, api_key: str) -> Dict[str, Any]: + def _prepare_headers(self, headers: dict, api_key: str) -> dict[str, Any]: headers = super()._prepare_headers(headers, api_key) if not api_key.startswith("hf_"): headers["authorization"] = f"Key {api_key}" @@ -50,7 +50,7 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: def get_response( self, - response: Union[bytes, Dict], + response: Union[bytes, dict], request_params: Optional[RequestParameters] = None, ) -> Any: response_dict = _as_dict(response) @@ -91,8 +91,8 @@ def __init__(self): super().__init__("automatic-speech-recognition") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: if isinstance(inputs, str) and inputs.startswith(("http://", "https://")): # If input is a URL, pass it directly audio_url = inputs @@ -108,7 +108,7 @@ def _prepare_payload_as_dict( return {"audio_url": audio_url, **filter_none(parameters)} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: text = _as_dict(response)["text"] if not isinstance(text, str): raise ValueError(f"Unexpected output format from FalAI API. Expected string, got {type(text)}.") @@ -120,9 +120,9 @@ def __init__(self): super().__init__("text-to-image") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: - payload: Dict[str, Any] = { + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: + payload: dict[str, Any] = { "prompt": inputs, **filter_none(parameters), } @@ -145,7 +145,7 @@ def _prepare_payload_as_dict( return payload - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: url = _as_dict(response)["images"][0]["url"] return get_session().get(url).content @@ -155,11 +155,11 @@ def __init__(self): super().__init__("text-to-speech") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: return {"text": inputs, **filter_none(parameters)} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: url = _as_dict(response)["audio"]["url"] return get_session().get(url).content @@ -169,13 +169,13 @@ def __init__(self): super().__init__("text-to-video") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: return {"prompt": inputs, **filter_none(parameters)} def get_response( self, - response: Union[bytes, Dict], + response: Union[bytes, dict], request_params: Optional[RequestParameters] = None, ) -> Any: output = super().get_response(response, request_params) @@ -188,10 +188,10 @@ def __init__(self): super().__init__("image-to-image") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: image_url = _as_url(inputs, default_mime_type="image/jpeg") - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "image_url": image_url, **filter_none(parameters), } @@ -207,7 +207,7 @@ def _prepare_payload_as_dict( def get_response( self, - response: Union[bytes, Dict], + response: Union[bytes, dict], request_params: Optional[RequestParameters] = None, ) -> Any: output = super().get_response(response, request_params) @@ -220,10 +220,10 @@ def __init__(self): super().__init__("image-to-video") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: image_url = _as_url(inputs, default_mime_type="image/jpeg") - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "image_url": image_url, **filter_none(parameters), } @@ -238,7 +238,7 @@ def _prepare_payload_as_dict( def get_response( self, - response: Union[bytes, Dict], + response: Union[bytes, dict], request_params: Optional[RequestParameters] = None, ) -> Any: output = super().get_response(response, request_params) diff --git a/src/huggingface_hub/inference/_providers/featherless_ai.py b/src/huggingface_hub/inference/_providers/featherless_ai.py index 6ad1c48134..ab119636c0 100644 --- a/src/huggingface_hub/inference/_providers/featherless_ai.py +++ b/src/huggingface_hub/inference/_providers/featherless_ai.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -15,14 +15,14 @@ def __init__(self): super().__init__(provider=_PROVIDER, base_url=_BASE_URL) def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: params = filter_none(parameters.copy()) params["max_tokens"] = params.pop("max_new_tokens", None) return {"prompt": inputs, **params, "model": provider_mapping_info.provider_id} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: output = _as_dict(response)["choices"][0] return { "generated_text": output["text"], diff --git a/src/huggingface_hub/inference/_providers/fireworks_ai.py b/src/huggingface_hub/inference/_providers/fireworks_ai.py index b4cc19a570..d76c58478b 100644 --- a/src/huggingface_hub/inference/_providers/fireworks_ai.py +++ b/src/huggingface_hub/inference/_providers/fireworks_ai.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional +from typing import Any, Optional from huggingface_hub.hf_api import InferenceProviderMapping @@ -13,8 +13,8 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/inference/v1/chat/completions" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: payload = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) response_format = parameters.get("response_format") if isinstance(response_format, dict) and response_format.get("type") == "json_schema": diff --git a/src/huggingface_hub/inference/_providers/hf_inference.py b/src/huggingface_hub/inference/_providers/hf_inference.py index d90d00c4f3..dddfaaea85 100644 --- a/src/huggingface_hub/inference/_providers/hf_inference.py +++ b/src/huggingface_hub/inference/_providers/hf_inference.py @@ -1,7 +1,7 @@ import json from functools import lru_cache from pathlib import Path -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from urllib.parse import urlparse, urlunparse from huggingface_hub import constants @@ -60,8 +60,8 @@ def _prepare_url(self, api_key: str, mapped_model: str) -> str: ) def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: if isinstance(inputs, bytes): raise ValueError(f"Unexpected binary input for task {self.task}.") if isinstance(inputs, Path): @@ -71,16 +71,16 @@ def _prepare_payload_as_dict( class HFInferenceBinaryInputTask(HFInferenceTask): def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: return None def _prepare_payload_as_bytes( self, inputs: Any, - parameters: Dict, + parameters: dict, provider_mapping_info: InferenceProviderMapping, - extra_payload: Optional[Dict], + extra_payload: Optional[dict], ) -> Optional[MimeBytes]: parameters = filter_none(parameters) extra_payload = extra_payload or {} @@ -106,8 +106,8 @@ def __init__(self): super().__init__("conversational") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: payload = filter_none(parameters) mapped_model = provider_mapping_info.provider_id payload_model = parameters.get("model") or mapped_model @@ -156,7 +156,7 @@ def _build_chat_completion_url(model_url: str) -> str: @lru_cache(maxsize=1) -def _fetch_recommended_models() -> Dict[str, Optional[str]]: +def _fetch_recommended_models() -> dict[str, Optional[str]]: response = get_session().get(f"{constants.ENDPOINT}/api/tasks", headers=build_hf_headers()) hf_raise_for_status(response) return {task: next(iter(details["widgetModels"]), None) for task, details in response.json().items()} @@ -211,8 +211,8 @@ def __init__(self): super().__init__("feature-extraction") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: if isinstance(inputs, bytes): raise ValueError(f"Unexpected binary input for task {self.task}.") if isinstance(inputs, Path): @@ -222,7 +222,7 @@ def _prepare_payload_as_dict( # See specs: https://github.com/huggingface/huggingface.js/blob/main/packages/tasks/src/tasks/feature-extraction/spec/input.json return {"inputs": inputs, **filter_none(parameters)} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: if isinstance(response, bytes): return _bytes_to_dict(response) return response diff --git a/src/huggingface_hub/inference/_providers/hyperbolic.py b/src/huggingface_hub/inference/_providers/hyperbolic.py index 6dcb14cc27..af512b1624 100644 --- a/src/huggingface_hub/inference/_providers/hyperbolic.py +++ b/src/huggingface_hub/inference/_providers/hyperbolic.py @@ -1,5 +1,5 @@ import base64 -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -14,8 +14,8 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/v1/images/generations" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: mapped_model = provider_mapping_info.provider_id parameters = filter_none(parameters) if "num_inference_steps" in parameters: @@ -29,7 +29,7 @@ def _prepare_payload_as_dict( parameters["height"] = 512 return {"prompt": inputs, "model_name": mapped_model, **parameters} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: response_dict = _as_dict(response) return base64.b64decode(response_dict["images"][0]["image"]) diff --git a/src/huggingface_hub/inference/_providers/nebius.py b/src/huggingface_hub/inference/_providers/nebius.py index 85ad67c4c8..6731855049 100644 --- a/src/huggingface_hub/inference/_providers/nebius.py +++ b/src/huggingface_hub/inference/_providers/nebius.py @@ -1,5 +1,5 @@ import base64 -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -15,7 +15,7 @@ class NebiusTextGenerationTask(BaseTextGenerationTask): def __init__(self): super().__init__(provider="nebius", base_url="https://api.studio.nebius.ai") - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: output = _as_dict(response)["choices"][0] return { "generated_text": output["text"], @@ -31,8 +31,8 @@ def __init__(self): super().__init__(provider="nebius", base_url="https://api.studio.nebius.ai") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: payload = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) response_format = parameters.get("response_format") if isinstance(response_format, dict) and response_format.get("type") == "json_schema": @@ -50,8 +50,8 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/v1/images/generations" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: mapped_model = provider_mapping_info.provider_id parameters = filter_none(parameters) if "guidance_scale" in parameters: @@ -61,7 +61,7 @@ def _prepare_payload_as_dict( return {"prompt": inputs, **parameters, "model": mapped_model} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: response_dict = _as_dict(response) return base64.b64decode(response_dict["data"][0]["b64_json"]) @@ -74,10 +74,10 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/v1/embeddings" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: return {"input": inputs, "model": provider_mapping_info.provider_id} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: embeddings = _as_dict(response)["data"] return [embedding["embedding"] for embedding in embeddings] diff --git a/src/huggingface_hub/inference/_providers/new_provider.md b/src/huggingface_hub/inference/_providers/new_provider.md index 923463284a..4a488df6bb 100644 --- a/src/huggingface_hub/inference/_providers/new_provider.md +++ b/src/huggingface_hub/inference/_providers/new_provider.md @@ -13,7 +13,7 @@ If the provider supports multiple tasks that require different implementations, For `text-generation` and `conversational` tasks, one can just inherit from `BaseTextGenerationTask` and `BaseConversationalTask` respectively (defined in `_common.py`) and override the methods if needed. Examples can be found in `fireworks_ai.py` and `together.py`. ```py -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from ._common import TaskProviderHelper, MimeBytes @@ -25,7 +25,7 @@ class MyNewProviderTaskProviderHelper(TaskProviderHelper): def get_response( self, - response: Union[bytes, Dict], + response: Union[bytes, dict], request_params: Optional[RequestParameters] = None, ) -> Any: """ @@ -34,7 +34,7 @@ class MyNewProviderTaskProviderHelper(TaskProviderHelper): Override this method in subclasses for customized response handling.""" return super().get_response(response) - def _prepare_headers(self, headers: Dict, api_key: str) -> Dict[str, Any]: + def _prepare_headers(self, headers: dict, api_key: str) -> dict[str, Any]: """Return the headers to use for the request. Override this method in subclasses for customized headers. @@ -48,7 +48,7 @@ class MyNewProviderTaskProviderHelper(TaskProviderHelper): """ return super()._prepare_route(mapped_model) - def _prepare_payload_as_dict(self, inputs: Any, parameters: Dict, mapped_model: str) -> Optional[Dict]: + def _prepare_payload_as_dict(self, inputs: Any, parameters: dict, mapped_model: str) -> Optional[dict]: """Return the payload to use for the request, as a dict. Override this method in subclasses for customized payloads. @@ -57,7 +57,7 @@ class MyNewProviderTaskProviderHelper(TaskProviderHelper): return super()._prepare_payload_as_dict(inputs, parameters, mapped_model) def _prepare_payload_as_bytes( - self, inputs: Any, parameters: Dict, mapped_model: str, extra_payload: Optional[Dict] + self, inputs: Any, parameters: dict, mapped_model: str, extra_payload: Optional[dict] ) -> Optional[MimeBytes]: """Return the body to use for the request, as bytes. diff --git a/src/huggingface_hub/inference/_providers/novita.py b/src/huggingface_hub/inference/_providers/novita.py index 44adc9017b..301d7a589d 100644 --- a/src/huggingface_hub/inference/_providers/novita.py +++ b/src/huggingface_hub/inference/_providers/novita.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -23,7 +23,7 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: # there is no v1/ route for novita return "/v3/openai/completions" - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: output = _as_dict(response)["choices"][0] return { "generated_text": output["text"], @@ -51,11 +51,11 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return f"/v3/hf/{mapped_model}" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: return {"prompt": inputs, **filter_none(parameters)} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: response_dict = _as_dict(response) if not ( isinstance(response_dict, dict) diff --git a/src/huggingface_hub/inference/_providers/nscale.py b/src/huggingface_hub/inference/_providers/nscale.py index ce5b20e354..65b15147a2 100644 --- a/src/huggingface_hub/inference/_providers/nscale.py +++ b/src/huggingface_hub/inference/_providers/nscale.py @@ -1,5 +1,5 @@ import base64 -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -20,8 +20,8 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/v1/images/generations" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: mapped_model = provider_mapping_info.provider_id # Combine all parameters except inputs and parameters parameters = filter_none(parameters) @@ -39,6 +39,6 @@ def _prepare_payload_as_dict( } return payload - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: response_dict = _as_dict(response) return base64.b64decode(response_dict["data"][0]["b64_json"]) diff --git a/src/huggingface_hub/inference/_providers/replicate.py b/src/huggingface_hub/inference/_providers/replicate.py index 139582cc80..5a1d1b71f0 100644 --- a/src/huggingface_hub/inference/_providers/replicate.py +++ b/src/huggingface_hub/inference/_providers/replicate.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict, _as_url @@ -14,7 +14,7 @@ class ReplicateTask(TaskProviderHelper): def __init__(self, task: str): super().__init__(provider=_PROVIDER, base_url=_BASE_URL, task=task) - def _prepare_headers(self, headers: Dict, api_key: str) -> Dict[str, Any]: + def _prepare_headers(self, headers: dict, api_key: str) -> dict[str, Any]: headers = super()._prepare_headers(headers, api_key) headers["Prefer"] = "wait" return headers @@ -25,16 +25,16 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return f"/v1/models/{mapped_model}/predictions" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: mapped_model = provider_mapping_info.provider_id - payload: Dict[str, Any] = {"input": {"prompt": inputs, **filter_none(parameters)}} + payload: dict[str, Any] = {"input": {"prompt": inputs, **filter_none(parameters)}} if ":" in mapped_model: version = mapped_model.split(":", 1)[1] payload["version"] = version return payload - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: response_dict = _as_dict(response) if response_dict.get("output") is None: raise TimeoutError( @@ -52,9 +52,9 @@ def __init__(self): super().__init__("text-to-image") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: - payload: Dict = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) # type: ignore[assignment] + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: + payload: dict = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) # type: ignore[assignment] if provider_mapping_info.adapter_weights_path is not None: payload["input"]["lora_weights"] = f"https://huggingface.co/{provider_mapping_info.hf_model_id}" return payload @@ -65,9 +65,9 @@ def __init__(self): super().__init__("text-to-speech") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: - payload: Dict = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) # type: ignore[assignment] + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: + payload: dict = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) # type: ignore[assignment] payload["input"]["text"] = payload["input"].pop("prompt") # rename "prompt" to "text" for TTS return payload @@ -77,11 +77,11 @@ def __init__(self): super().__init__("image-to-image") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: image_url = _as_url(inputs, default_mime_type="image/jpeg") - payload: Dict[str, Any] = {"input": {"input_image": image_url, **filter_none(parameters)}} + payload: dict[str, Any] = {"input": {"input_image": image_url, **filter_none(parameters)}} mapped_model = provider_mapping_info.provider_id if ":" in mapped_model: diff --git a/src/huggingface_hub/inference/_providers/sambanova.py b/src/huggingface_hub/inference/_providers/sambanova.py index ed96fb766c..4b7b1ee57b 100644 --- a/src/huggingface_hub/inference/_providers/sambanova.py +++ b/src/huggingface_hub/inference/_providers/sambanova.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -10,8 +10,8 @@ def __init__(self): super().__init__(provider="sambanova", base_url="https://api.sambanova.ai") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: response_format_config = parameters.get("response_format") if isinstance(response_format_config, dict): if response_format_config.get("type") == "json_schema": @@ -32,11 +32,11 @@ def _prepare_route(self, mapped_model: str, api_key: str) -> str: return "/v1/embeddings" def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: parameters = filter_none(parameters) return {"input": inputs, "model": provider_mapping_info.provider_id, **parameters} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: embeddings = _as_dict(response)["data"] return [embedding["embedding"] for embedding in embeddings] diff --git a/src/huggingface_hub/inference/_providers/together.py b/src/huggingface_hub/inference/_providers/together.py index de166b7baf..338057d438 100644 --- a/src/huggingface_hub/inference/_providers/together.py +++ b/src/huggingface_hub/inference/_providers/together.py @@ -1,6 +1,6 @@ import base64 from abc import ABC -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union from huggingface_hub.hf_api import InferenceProviderMapping from huggingface_hub.inference._common import RequestParameters, _as_dict @@ -36,7 +36,7 @@ class TogetherTextGenerationTask(BaseTextGenerationTask): def __init__(self): super().__init__(provider=_PROVIDER, base_url=_BASE_URL) - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: output = _as_dict(response)["choices"][0] return { "generated_text": output["text"], @@ -52,8 +52,8 @@ def __init__(self): super().__init__(provider=_PROVIDER, base_url=_BASE_URL) def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: payload = super()._prepare_payload_as_dict(inputs, parameters, provider_mapping_info) response_format = parameters.get("response_format") if isinstance(response_format, dict) and response_format.get("type") == "json_schema": @@ -72,8 +72,8 @@ def __init__(self): super().__init__("text-to-image") def _prepare_payload_as_dict( - self, inputs: Any, parameters: Dict, provider_mapping_info: InferenceProviderMapping - ) -> Optional[Dict]: + self, inputs: Any, parameters: dict, provider_mapping_info: InferenceProviderMapping + ) -> Optional[dict]: mapped_model = provider_mapping_info.provider_id parameters = filter_none(parameters) if "num_inference_steps" in parameters: @@ -83,6 +83,6 @@ def _prepare_payload_as_dict( return {"prompt": inputs, "response_format": "base64", **parameters, "model": mapped_model} - def get_response(self, response: Union[bytes, Dict], request_params: Optional[RequestParameters] = None) -> Any: + def get_response(self, response: Union[bytes, dict], request_params: Optional[RequestParameters] = None) -> Any: response_dict = _as_dict(response) return base64.b64decode(response_dict["data"][0]["b64_json"]) diff --git a/src/huggingface_hub/inference_api.py b/src/huggingface_hub/inference_api.py index 333fa0e5de..16c2812864 100644 --- a/src/huggingface_hub/inference_api.py +++ b/src/huggingface_hub/inference_api.py @@ -1,5 +1,5 @@ import io -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union from . import constants from .hf_api import HfApi @@ -157,17 +157,17 @@ def __repr__(self): def __call__( self, - inputs: Optional[Union[str, Dict, List[str], List[List[str]]]] = None, - params: Optional[Dict] = None, + inputs: Optional[Union[str, dict, list[str], list[list[str]]]] = None, + params: Optional[dict] = None, data: Optional[bytes] = None, raw_response: bool = False, ) -> Any: """Make a call to the Inference API. Args: - inputs (`str` or `Dict` or `List[str]` or `List[List[str]]`, *optional*): + inputs (`str` or `dict` or `list[str]` or `list[list[str]]`, *optional*): Inputs for the prediction. - params (`Dict`, *optional*): + params (`dict`, *optional*): Additional parameters for the models. Will be sent as `parameters` in the payload. data (`bytes`, *optional*): @@ -178,7 +178,7 @@ def __call__( (json dictionary or PIL Image for example). """ # Build payload - payload: Dict[str, Any] = { + payload: dict[str, Any] = { "options": self.options, } if inputs: diff --git a/src/huggingface_hub/keras_mixin.py b/src/huggingface_hub/keras_mixin.py index 53290dc858..fa38b5dfba 100644 --- a/src/huggingface_hub/keras_mixin.py +++ b/src/huggingface_hub/keras_mixin.py @@ -5,7 +5,7 @@ from functools import wraps from pathlib import Path from shutil import copytree -from typing import Any, Dict, List, Optional, Union +from typing import Any, Optional, Union from huggingface_hub import ModelHubMixin, snapshot_download from huggingface_hub.utils import ( @@ -157,7 +157,7 @@ def _create_model_card( def save_pretrained_keras( model, save_directory: Union[str, Path], - config: Optional[Dict[str, Any]] = None, + config: Optional[dict[str, Any]] = None, include_optimizer: bool = False, plot_model: bool = True, tags: Optional[Union[list, str]] = None, @@ -276,7 +276,7 @@ def from_pretrained_keras(*args, **kwargs) -> "KerasModelHubMixin": local_files_only(`bool`, *optional*, defaults to `False`): Whether to only look at local files (i.e., do not try to download the model). - model_kwargs (`Dict`, *optional*): + model_kwargs (`dict`, *optional*): model_kwargs will be passed to the model during initialization @@ -302,9 +302,9 @@ def push_to_hub_keras( token: Optional[str] = None, branch: Optional[str] = None, create_pr: Optional[bool] = None, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, - delete_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, + delete_patterns: Optional[Union[list[str], str]] = None, log_dir: Optional[str] = None, include_optimizer: bool = False, tags: Optional[Union[list, str]] = None, @@ -344,11 +344,11 @@ def push_to_hub_keras( Defaults to `False`. config (`dict`, *optional*): Configuration object to be saved alongside the model weights. - allow_patterns (`List[str]` or `str`, *optional*): + allow_patterns (`list[str]` or `str`, *optional*): If provided, only files matching at least one pattern are pushed. - ignore_patterns (`List[str]` or `str`, *optional*): + ignore_patterns (`list[str]` or `str`, *optional*): If provided, files matching any of the patterns are not pushed. - delete_patterns (`List[str]` or `str`, *optional*): + delete_patterns (`list[str]` or `str`, *optional*): If provided, remote files matching any of the patterns will be deleted from the repo. log_dir (`str`, *optional*): TensorBoard logging directory to be pushed. The Hub automatically @@ -462,7 +462,7 @@ def _from_pretrained( resume_download, local_files_only, token, - config: Optional[Dict[str, Any]] = None, + config: Optional[dict[str, Any]] = None, **model_kwargs, ): """Here we just call [`from_pretrained_keras`] function so both the mixin and diff --git a/src/huggingface_hub/lfs.py b/src/huggingface_hub/lfs.py index 3ff465f9c0..a626ef28d6 100644 --- a/src/huggingface_hub/lfs.py +++ b/src/huggingface_hub/lfs.py @@ -21,7 +21,7 @@ from math import ceil from os.path import getsize from pathlib import Path -from typing import TYPE_CHECKING, BinaryIO, Dict, Iterable, List, Optional, Tuple, TypedDict +from typing import TYPE_CHECKING, BinaryIO, Iterable, Optional, TypedDict from urllib.parse import unquote from huggingface_hub import constants @@ -106,8 +106,8 @@ def post_lfs_batch_info( repo_id: str, revision: Optional[str] = None, endpoint: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, -) -> Tuple[List[dict], List[dict]]: + headers: Optional[dict[str, str]] = None, +) -> tuple[list[dict], list[dict]]: """ Requests the LFS batch endpoint to retrieve upload instructions @@ -143,7 +143,7 @@ def post_lfs_batch_info( if repo_type in constants.REPO_TYPES_URL_PREFIXES: url_prefix = constants.REPO_TYPES_URL_PREFIXES[repo_type] batch_url = f"{endpoint}/{url_prefix}{repo_id}.git/info/lfs/objects/batch" - payload: Dict = { + payload: dict = { "operation": "upload", "transfers": ["basic", "multipart"], "objects": [ @@ -186,14 +186,14 @@ class CompletionPayloadT(TypedDict): """Payload that will be sent to the Hub when uploading multi-part.""" oid: str - parts: List[PayloadPartT] + parts: list[PayloadPartT] def lfs_upload( operation: "CommitOperationAdd", - lfs_batch_action: Dict, + lfs_batch_action: dict, token: Optional[str] = None, - headers: Optional[Dict[str, str]] = None, + headers: Optional[dict[str, str]] = None, endpoint: Optional[str] = None, ) -> None: """ @@ -317,7 +317,7 @@ def _upload_single_part(operation: "CommitOperationAdd", upload_url: str) -> Non hf_raise_for_status(response) -def _upload_multi_part(operation: "CommitOperationAdd", header: Dict, chunk_size: int, upload_url: str) -> None: +def _upload_multi_part(operation: "CommitOperationAdd", header: dict, chunk_size: int, upload_url: str) -> None: """ Uploads file using HF multipart LFS transfer protocol. """ @@ -352,7 +352,7 @@ def _upload_multi_part(operation: "CommitOperationAdd", header: Dict, chunk_size hf_raise_for_status(completion_res) -def _get_sorted_parts_urls(header: Dict, upload_info: UploadInfo, chunk_size: int) -> List[str]: +def _get_sorted_parts_urls(header: dict, upload_info: UploadInfo, chunk_size: int) -> list[str]: sorted_part_upload_urls = [ upload_url for _, upload_url in sorted( @@ -370,8 +370,8 @@ def _get_sorted_parts_urls(header: Dict, upload_info: UploadInfo, chunk_size: in return sorted_part_upload_urls -def _get_completion_payload(response_headers: List[Dict], oid: str) -> CompletionPayloadT: - parts: List[PayloadPartT] = [] +def _get_completion_payload(response_headers: list[dict], oid: str) -> CompletionPayloadT: + parts: list[PayloadPartT] = [] for part_number, header in enumerate(response_headers): etag = header.get("etag") if etag is None or etag == "": @@ -386,8 +386,8 @@ def _get_completion_payload(response_headers: List[Dict], oid: str) -> Completio def _upload_parts_iteratively( - operation: "CommitOperationAdd", sorted_parts_urls: List[str], chunk_size: int -) -> List[Dict]: + operation: "CommitOperationAdd", sorted_parts_urls: list[str], chunk_size: int +) -> list[dict]: headers = [] with operation.as_file(with_tqdm=True) as fileobj: for part_idx, part_upload_url in enumerate(sorted_parts_urls): @@ -406,8 +406,8 @@ def _upload_parts_iteratively( def _upload_parts_hf_transfer( - operation: "CommitOperationAdd", sorted_parts_urls: List[str], chunk_size: int -) -> List[Dict]: + operation: "CommitOperationAdd", sorted_parts_urls: list[str], chunk_size: int +) -> list[dict]: # Upload file using an external Rust-based package. Upload is faster but support less features (no progress bars). try: from hf_transfer import multipart_upload diff --git a/src/huggingface_hub/repocard.py b/src/huggingface_hub/repocard.py index c8c9a28a17..4e0f775ddd 100644 --- a/src/huggingface_hub/repocard.py +++ b/src/huggingface_hub/repocard.py @@ -1,7 +1,7 @@ import os import re from pathlib import Path -from typing import Any, Dict, Literal, Optional, Type, Union +from typing import Any, Literal, Optional, Union import yaml @@ -335,7 +335,7 @@ def from_template( class ModelCard(RepoCard): - card_data_class = ModelCardData + card_data_class = ModelCardData # type: ignore[assignment] default_template_path = TEMPLATE_MODELCARD_PATH repo_type = "model" @@ -416,7 +416,7 @@ def from_template( # type: ignore # violates Liskov property but easier to use class DatasetCard(RepoCard): - card_data_class = DatasetCardData + card_data_class = DatasetCardData # type: ignore[assignment] default_template_path = TEMPLATE_DATASETCARD_PATH repo_type = "dataset" @@ -481,7 +481,7 @@ def from_template( # type: ignore # violates Liskov property but easier to use class SpaceCard(RepoCard): - card_data_class = SpaceCardData + card_data_class = SpaceCardData # type: ignore[assignment] default_template_path = TEMPLATE_MODELCARD_PATH repo_type = "space" @@ -507,7 +507,7 @@ def _detect_line_ending(content: str) -> Literal["\r", "\n", "\r\n", None]: # n return "\n" -def metadata_load(local_path: Union[str, Path]) -> Optional[Dict]: +def metadata_load(local_path: Union[str, Path]) -> Optional[dict]: content = Path(local_path).read_text() match = REGEX_YAML_BLOCK.search(content) if match: @@ -520,7 +520,7 @@ def metadata_load(local_path: Union[str, Path]) -> Optional[Dict]: return None -def metadata_save(local_path: Union[str, Path], data: Dict) -> None: +def metadata_save(local_path: Union[str, Path], data: dict) -> None: """ Save the metadata dict in the upper YAML part Trying to preserve newlines as in the existing file. Docs about open() with newline="" parameter: @@ -568,7 +568,7 @@ def metadata_eval_result( dataset_split: Optional[str] = None, dataset_revision: Optional[str] = None, metrics_verification_token: Optional[str] = None, -) -> Dict: +) -> dict: """ Creates a metadata dict with the result from a model evaluated on a dataset. @@ -683,7 +683,7 @@ def metadata_eval_result( @validate_hf_hub_args def metadata_update( repo_id: str, - metadata: Dict, + metadata: dict, *, repo_type: Optional[str] = None, overwrite: bool = False, @@ -751,7 +751,7 @@ def metadata_update( commit_message = commit_message if commit_message is not None else "Update metadata with huggingface_hub" # Card class given repo_type - card_class: Type[RepoCard] + card_class: type[RepoCard] if repo_type is None or repo_type == "model": card_class = ModelCard elif repo_type == "dataset": diff --git a/src/huggingface_hub/repocard_data.py b/src/huggingface_hub/repocard_data.py index 62215f2274..1d283f5baa 100644 --- a/src/huggingface_hub/repocard_data.py +++ b/src/huggingface_hub/repocard_data.py @@ -1,7 +1,7 @@ import copy from collections import defaultdict from dataclasses import dataclass -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any, Optional, Union from huggingface_hub.utils import logging, yaml_dump @@ -38,7 +38,7 @@ class EvalResult: dataset_revision (`str`, *optional*): The revision (AKA Git Sha) of the dataset used in `load_dataset()`. Example: 5503434ddd753f426f4b38109466949a1217c2bb - dataset_args (`Dict[str, Any]`, *optional*): + dataset_args (`dict[str, Any]`, *optional*): The arguments passed during `Metric.compute()`. Example for `bleu`: `{"max_order": 4}` metric_name (`str`, *optional*): A pretty name for the metric. Example: "Test WER". @@ -46,7 +46,7 @@ class EvalResult: The name of the metric configuration used in `load_metric()`. Example: bleurt-large-512 in `load_metric("bleurt", "bleurt-large-512")`. See the `datasets` docs for more info: https://huggingface.co/docs/datasets/v2.1.0/en/loading#load-configurations - metric_args (`Dict[str, Any]`, *optional*): + metric_args (`dict[str, Any]`, *optional*): The arguments passed during `Metric.compute()`. Example for `bleu`: max_order: 4 verified (`bool`, *optional*): Indicates whether the metrics originate from Hugging Face's [evaluation service](https://huggingface.co/spaces/autoevaluate/model-evaluator) or not. Automatically computed by Hugging Face, do not set. @@ -102,7 +102,7 @@ class EvalResult: # The arguments passed during `Metric.compute()`. # Example for `bleu`: max_order: 4 - dataset_args: Optional[Dict[str, Any]] = None + dataset_args: Optional[dict[str, Any]] = None # A pretty name for the metric. # Example: Test WER @@ -115,7 +115,7 @@ class EvalResult: # The arguments passed during `Metric.compute()`. # Example for `bleu`: max_order: 4 - metric_args: Optional[Dict[str, Any]] = None + metric_args: Optional[dict[str, Any]] = None # Indicates whether the metrics originate from Hugging Face's [evaluation service](https://huggingface.co/spaces/autoevaluate/model-evaluator) or not. Automatically computed by Hugging Face, do not set. verified: Optional[bool] = None @@ -195,7 +195,7 @@ def _to_dict(self, data_dict): """ pass - def to_yaml(self, line_break=None, original_order: Optional[List[str]] = None) -> str: + def to_yaml(self, line_break=None, original_order: Optional[list[str]] = None) -> str: """Dumps CardData to a YAML block for inclusion in a README.md file. Args: @@ -246,9 +246,9 @@ def __len__(self) -> int: def _validate_eval_results( - eval_results: Optional[Union[EvalResult, List[EvalResult]]], + eval_results: Optional[Union[EvalResult, list[EvalResult]]], model_name: Optional[str], -) -> List[EvalResult]: +) -> list[EvalResult]: if eval_results is None: return [] if isinstance(eval_results, EvalResult): @@ -266,17 +266,17 @@ class ModelCardData(CardData): """Model Card Metadata that is used by Hugging Face Hub when included at the top of your README.md Args: - base_model (`str` or `List[str]`, *optional*): + base_model (`str` or `list[str]`, *optional*): The identifier of the base model from which the model derives. This is applicable for example if your model is a fine-tune or adapter of an existing model. The value must be the ID of a model on the Hub (or a list of IDs if your model derives from multiple models). Defaults to None. - datasets (`Union[str, List[str]]`, *optional*): + datasets (`Union[str, list[str]]`, *optional*): Dataset or list of datasets that were used to train this model. Should be a dataset ID found on https://hf.co/datasets. Defaults to None. - eval_results (`Union[List[EvalResult], EvalResult]`, *optional*): + eval_results (`Union[list[EvalResult], EvalResult]`, *optional*): List of `huggingface_hub.EvalResult` that define evaluation results of the model. If provided, `model_name` is used to as a name on PapersWithCode's leaderboards. Defaults to `None`. - language (`Union[str, List[str]]`, *optional*): + language (`Union[str, list[str]]`, *optional*): Language of model's training data or metadata. It must be an ISO 639-1, 639-2 or 639-3 code (two/three letters), or a special value like "code", "multilingual". Defaults to `None`. library_name (`str`, *optional*): @@ -292,7 +292,7 @@ class ModelCardData(CardData): license_link (`str`, *optional*): Link to the license of this model. Defaults to None. To be used in conjunction with `license_name`. Common licenses (Apache-2.0, MIT, CC-BY-SA-4.0) do not need a link. In that case, use `license` instead. - metrics (`List[str]`, *optional*): + metrics (`list[str]`, *optional*): List of metrics used to evaluate this model. Should be a metric name that can be found at https://hf.co/metrics. Example: 'accuracy'. Defaults to None. model_name (`str`, *optional*): @@ -302,7 +302,7 @@ class ModelCardData(CardData): then the repo name is used as a default. Defaults to None. pipeline_tag (`str`, *optional*): The pipeline tag associated with the model. Example: "text-classification". - tags (`List[str]`, *optional*): + tags (`list[str]`, *optional*): List of tags to add to your model that can be used when filtering on the Hugging Face Hub. Defaults to None. ignore_metadata_errors (`str`): @@ -329,18 +329,18 @@ class ModelCardData(CardData): def __init__( self, *, - base_model: Optional[Union[str, List[str]]] = None, - datasets: Optional[Union[str, List[str]]] = None, - eval_results: Optional[List[EvalResult]] = None, - language: Optional[Union[str, List[str]]] = None, + base_model: Optional[Union[str, list[str]]] = None, + datasets: Optional[Union[str, list[str]]] = None, + eval_results: Optional[list[EvalResult]] = None, + language: Optional[Union[str, list[str]]] = None, library_name: Optional[str] = None, license: Optional[str] = None, license_name: Optional[str] = None, license_link: Optional[str] = None, - metrics: Optional[List[str]] = None, + metrics: Optional[list[str]] = None, model_name: Optional[str] = None, pipeline_tag: Optional[str] = None, - tags: Optional[List[str]] = None, + tags: Optional[list[str]] = None, ignore_metadata_errors: bool = False, **kwargs, ): @@ -395,58 +395,58 @@ class DatasetCardData(CardData): """Dataset Card Metadata that is used by Hugging Face Hub when included at the top of your README.md Args: - language (`List[str]`, *optional*): + language (`list[str]`, *optional*): Language of dataset's data or metadata. It must be an ISO 639-1, 639-2 or 639-3 code (two/three letters), or a special value like "code", "multilingual". - license (`Union[str, List[str]]`, *optional*): + license (`Union[str, list[str]]`, *optional*): License(s) of this dataset. Example: apache-2.0 or any license from https://huggingface.co/docs/hub/repositories-licenses. - annotations_creators (`Union[str, List[str]]`, *optional*): + annotations_creators (`Union[str, list[str]]`, *optional*): How the annotations for the dataset were created. Options are: 'found', 'crowdsourced', 'expert-generated', 'machine-generated', 'no-annotation', 'other'. - language_creators (`Union[str, List[str]]`, *optional*): + language_creators (`Union[str, list[str]]`, *optional*): How the text-based data in the dataset was created. Options are: 'found', 'crowdsourced', 'expert-generated', 'machine-generated', 'other' - multilinguality (`Union[str, List[str]]`, *optional*): + multilinguality (`Union[str, list[str]]`, *optional*): Whether the dataset is multilingual. Options are: 'monolingual', 'multilingual', 'translation', 'other'. - size_categories (`Union[str, List[str]]`, *optional*): + size_categories (`Union[str, list[str]]`, *optional*): The number of examples in the dataset. Options are: 'n<1K', '1K1T', and 'other'. - source_datasets (`List[str]]`, *optional*): + source_datasets (`list[str]]`, *optional*): Indicates whether the dataset is an original dataset or extended from another existing dataset. Options are: 'original' and 'extended'. - task_categories (`Union[str, List[str]]`, *optional*): + task_categories (`Union[str, list[str]]`, *optional*): What categories of task does the dataset support? - task_ids (`Union[str, List[str]]`, *optional*): + task_ids (`Union[str, list[str]]`, *optional*): What specific tasks does the dataset support? paperswithcode_id (`str`, *optional*): ID of the dataset on PapersWithCode. pretty_name (`str`, *optional*): A more human-readable name for the dataset. (ex. "Cats vs. Dogs") - train_eval_index (`Dict`, *optional*): + train_eval_index (`dict`, *optional*): A dictionary that describes the necessary spec for doing evaluation on the Hub. If not provided, it will be gathered from the 'train-eval-index' key of the kwargs. - config_names (`Union[str, List[str]]`, *optional*): + config_names (`Union[str, list[str]]`, *optional*): A list of the available dataset configs for the dataset. """ def __init__( self, *, - language: Optional[Union[str, List[str]]] = None, - license: Optional[Union[str, List[str]]] = None, - annotations_creators: Optional[Union[str, List[str]]] = None, - language_creators: Optional[Union[str, List[str]]] = None, - multilinguality: Optional[Union[str, List[str]]] = None, - size_categories: Optional[Union[str, List[str]]] = None, - source_datasets: Optional[List[str]] = None, - task_categories: Optional[Union[str, List[str]]] = None, - task_ids: Optional[Union[str, List[str]]] = None, + language: Optional[Union[str, list[str]]] = None, + license: Optional[Union[str, list[str]]] = None, + annotations_creators: Optional[Union[str, list[str]]] = None, + language_creators: Optional[Union[str, list[str]]] = None, + multilinguality: Optional[Union[str, list[str]]] = None, + size_categories: Optional[Union[str, list[str]]] = None, + source_datasets: Optional[list[str]] = None, + task_categories: Optional[Union[str, list[str]]] = None, + task_ids: Optional[Union[str, list[str]]] = None, paperswithcode_id: Optional[str] = None, pretty_name: Optional[str] = None, - train_eval_index: Optional[Dict] = None, - config_names: Optional[Union[str, List[str]]] = None, + train_eval_index: Optional[dict] = None, + config_names: Optional[Union[str, list[str]]] = None, ignore_metadata_errors: bool = False, **kwargs, ): @@ -495,11 +495,11 @@ class SpaceCardData(CardData): https://huggingface.co/docs/hub/repositories-licenses. duplicated_from (`str`, *optional*) ID of the original Space if this is a duplicated Space. - models (List[`str`], *optional*) + models (list[`str`], *optional*) List of models related to this Space. Should be a dataset ID found on https://hf.co/models. - datasets (`List[str]`, *optional*) + datasets (`list[str]`, *optional*) List of datasets related to this Space. Should be a dataset ID found on https://hf.co/datasets. - tags (`List[str]`, *optional*) + tags (`list[str]`, *optional*) List of tags to add to your Space that can be used when filtering on the Hub. ignore_metadata_errors (`str`): If True, errors while parsing the metadata section will be ignored. Some information might be lost during @@ -532,9 +532,9 @@ def __init__( app_port: Optional[int] = None, license: Optional[str] = None, duplicated_from: Optional[str] = None, - models: Optional[List[str]] = None, - datasets: Optional[List[str]] = None, - tags: Optional[List[str]] = None, + models: Optional[list[str]] = None, + datasets: Optional[list[str]] = None, + tags: Optional[list[str]] = None, ignore_metadata_errors: bool = False, **kwargs, ): @@ -552,14 +552,14 @@ def __init__( super().__init__(**kwargs) -def model_index_to_eval_results(model_index: List[Dict[str, Any]]) -> Tuple[str, List[EvalResult]]: +def model_index_to_eval_results(model_index: list[dict[str, Any]]) -> tuple[str, list[EvalResult]]: """Takes in a model index and returns the model name and a list of `huggingface_hub.EvalResult` objects. A detailed spec of the model index can be found here: https://github.com/huggingface/hub-docs/blob/main/modelcard.md?plain=1 Args: - model_index (`List[Dict[str, Any]]`): + model_index (`list[dict[str, Any]]`): A model index data structure, likely coming from a README.md file on the Hugging Face Hub. @@ -567,7 +567,7 @@ def model_index_to_eval_results(model_index: List[Dict[str, Any]]) -> Tuple[str, model_name (`str`): The name of the model as found in the model index. This is used as the identifier for the model on leaderboards like PapersWithCode. - eval_results (`List[EvalResult]`): + eval_results (`list[EvalResult]`): A list of `huggingface_hub.EvalResult` objects containing the metrics reported in the provided model_index. @@ -668,7 +668,7 @@ def _remove_none(obj): return obj -def eval_results_to_model_index(model_name: str, eval_results: List[EvalResult]) -> List[Dict[str, Any]]: +def eval_results_to_model_index(model_name: str, eval_results: list[EvalResult]) -> list[dict[str, Any]]: """Takes in given model name and list of `huggingface_hub.EvalResult` and returns a valid model-index that will be compatible with the format expected by the Hugging Face Hub. @@ -677,12 +677,12 @@ def eval_results_to_model_index(model_name: str, eval_results: List[EvalResult]) model_name (`str`): Name of the model (ex. "my-cool-model"). This is used as the identifier for the model on leaderboards like PapersWithCode. - eval_results (`List[EvalResult]`): + eval_results (`list[EvalResult]`): List of `huggingface_hub.EvalResult` objects containing the metrics to be reported in the model-index. Returns: - model_index (`List[Dict[str, Any]]`): The eval_results converted to a model-index. + model_index (`list[dict[str, Any]]`): The eval_results converted to a model-index. Example: ```python @@ -705,7 +705,7 @@ def eval_results_to_model_index(model_name: str, eval_results: List[EvalResult]) # Metrics are reported on a unique task-and-dataset basis. # Here, we make a map of those pairs and the associated EvalResults. - task_and_ds_types_map: Dict[Any, List[EvalResult]] = defaultdict(list) + task_and_ds_types_map: dict[Any, list[EvalResult]] = defaultdict(list) for eval_result in eval_results: task_and_ds_types_map[eval_result.unique_identifier].append(eval_result) @@ -760,7 +760,7 @@ def eval_results_to_model_index(model_name: str, eval_results: List[EvalResult]) return _remove_none(model_index) -def _to_unique_list(tags: Optional[List[str]]) -> Optional[List[str]]: +def _to_unique_list(tags: Optional[list[str]]) -> Optional[list[str]]: if tags is None: return tags unique_tags = [] # make tags unique + keep order explicitly diff --git a/src/huggingface_hub/repository.py b/src/huggingface_hub/repository.py index d4a904f458..387761cedc 100644 --- a/src/huggingface_hub/repository.py +++ b/src/huggingface_hub/repository.py @@ -6,7 +6,7 @@ import time from contextlib import contextmanager from pathlib import Path -from typing import Callable, Dict, Iterator, List, Optional, Tuple, TypedDict, Union +from typing import Callable, Iterator, Optional, TypedDict, Union from urllib.parse import urlparse from huggingface_hub import constants @@ -238,7 +238,7 @@ def is_binary_file(filename: Union[str, Path]) -> bool: return True -def files_to_be_staged(pattern: str = ".", folder: Union[str, Path, None] = None) -> List[str]: +def files_to_be_staged(pattern: str = ".", folder: Union[str, Path, None] = None) -> list[str]: """ Returns a list of filenames that are to be staged. @@ -249,7 +249,7 @@ def files_to_be_staged(pattern: str = ".", folder: Union[str, Path, None] = None The folder in which to run the command. Returns: - `List[str]`: List of files that are to be staged. + `list[str]`: List of files that are to be staged. """ try: p = run_subprocess("git ls-files --exclude-standard -mo".split() + [pattern], folder) @@ -333,7 +333,7 @@ def output_progress(stopping_event: threading.Event): the tail. """ # Key is tuple(state, filename), value is a dict(tqdm bar and a previous value) - pbars: Dict[Tuple[str, str], PbarT] = {} + pbars: dict[tuple[str, str], PbarT] = {} def close_pbars(): for pbar in pbars.values(): @@ -441,7 +441,7 @@ class Repository: """ - command_queue: List[CommandInProgress] + command_queue: list[CommandInProgress] @validate_hf_hub_args @_deprecate_method( @@ -796,13 +796,13 @@ def git_head_commit_url(self) -> str: url = url[:-1] return f"{url}/commit/{sha}" - def list_deleted_files(self) -> List[str]: + def list_deleted_files(self) -> list[str]: """ Returns a list of the files that are deleted in the working directory or index. Returns: - `List[str]`: A list of files that have been deleted in the working + `list[str]`: A list of files that have been deleted in the working directory or index. """ try: @@ -831,7 +831,7 @@ def list_deleted_files(self) -> List[str]: return deleted_files - def lfs_track(self, patterns: Union[str, List[str]], filename: bool = False): + def lfs_track(self, patterns: Union[str, list[str]], filename: bool = False): """ Tell git-lfs to track files according to a pattern. @@ -840,7 +840,7 @@ def lfs_track(self, patterns: Union[str, List[str]], filename: bool = False): filename will be escaped when writing to the `.gitattributes` file. Args: - patterns (`Union[str, List[str]]`): + patterns (`Union[str, list[str]]`): The pattern, or list of patterns, to track with git-lfs. filename (`bool`, *optional*, defaults to `False`): Whether to use the patterns as literal filenames. @@ -856,12 +856,12 @@ def lfs_track(self, patterns: Union[str, List[str]], filename: bool = False): except subprocess.CalledProcessError as exc: raise EnvironmentError(exc.stderr) - def lfs_untrack(self, patterns: Union[str, List[str]]): + def lfs_untrack(self, patterns: Union[str, list[str]]): """ Tell git-lfs to untrack those files. Args: - patterns (`Union[str, List[str]]`): + patterns (`Union[str, list[str]]`): The pattern, or list of patterns, to untrack with git-lfs. """ if isinstance(patterns, str): @@ -886,7 +886,7 @@ def lfs_enable_largefiles(self): except subprocess.CalledProcessError as exc: raise EnvironmentError(exc.stderr) - def auto_track_binary_files(self, pattern: str = ".") -> List[str]: + def auto_track_binary_files(self, pattern: str = ".") -> list[str]: """ Automatically track binary files with git-lfs. @@ -895,7 +895,7 @@ def auto_track_binary_files(self, pattern: str = ".") -> List[str]: The pattern with which to track files that are binary. Returns: - `List[str]`: List of filenames that are now tracked due to being + `list[str]`: List of filenames that are now tracked due to being binary files """ files_to_be_tracked_with_lfs = [] @@ -929,7 +929,7 @@ def auto_track_binary_files(self, pattern: str = ".") -> List[str]: return files_to_be_tracked_with_lfs - def auto_track_large_files(self, pattern: str = ".") -> List[str]: + def auto_track_large_files(self, pattern: str = ".") -> list[str]: """ Automatically track large files (files that weigh more than 10MBs) with git-lfs. @@ -939,7 +939,7 @@ def auto_track_large_files(self, pattern: str = ".") -> List[str]: The pattern with which to track files that are above 10MBs. Returns: - `List[str]`: List of filenames that are now tracked due to their + `list[str]`: List of filenames that are now tracked due to their size. """ files_to_be_tracked_with_lfs = [] @@ -1060,7 +1060,7 @@ def git_push( upstream: Optional[str] = None, blocking: bool = True, auto_lfs_prune: bool = False, - ) -> Union[str, Tuple[str, CommandInProgress]]: + ) -> Union[str, tuple[str, CommandInProgress]]: """ git push @@ -1298,7 +1298,7 @@ def push_to_hub( blocking: bool = True, clean_ok: bool = True, auto_lfs_prune: bool = False, - ) -> Union[None, str, Tuple[str, CommandInProgress]]: + ) -> Union[None, str, tuple[str, CommandInProgress]]: """ Helper to add, commit, and push files to remote repository on the HuggingFace Hub. Will automatically track large files (>10MB). @@ -1433,13 +1433,13 @@ def commit( os.chdir(current_working_directory) - def repocard_metadata_load(self) -> Optional[Dict]: + def repocard_metadata_load(self) -> Optional[dict]: filepath = os.path.join(self.local_dir, constants.REPOCARD_NAME) if os.path.isfile(filepath): return metadata_load(filepath) return None - def repocard_metadata_save(self, data: Dict) -> None: + def repocard_metadata_save(self, data: dict) -> None: return metadata_save(os.path.join(self.local_dir, constants.REPOCARD_NAME), data) @property diff --git a/src/huggingface_hub/serialization/_base.py b/src/huggingface_hub/serialization/_base.py index b7b6454a90..53b72f6c4a 100644 --- a/src/huggingface_hub/serialization/_base.py +++ b/src/huggingface_hub/serialization/_base.py @@ -14,7 +14,7 @@ """Contains helpers to split tensors into shards.""" from dataclasses import dataclass, field -from typing import Any, Callable, Dict, List, Optional, TypeVar, Union +from typing import Any, Callable, Optional, TypeVar, Union from .. import logging @@ -38,16 +38,16 @@ @dataclass class StateDictSplit: is_sharded: bool = field(init=False) - metadata: Dict[str, Any] - filename_to_tensors: Dict[str, List[str]] - tensor_to_filename: Dict[str, str] + metadata: dict[str, Any] + filename_to_tensors: dict[str, list[str]] + tensor_to_filename: dict[str, str] def __post_init__(self): self.is_sharded = len(self.filename_to_tensors) > 1 def split_state_dict_into_shards_factory( - state_dict: Dict[str, TensorT], + state_dict: dict[str, TensorT], *, get_storage_size: TensorSizeFn_T, filename_pattern: str, @@ -70,7 +70,7 @@ def split_state_dict_into_shards_factory( Args: - state_dict (`Dict[str, Tensor]`): + state_dict (`dict[str, Tensor]`): The state dictionary to save. get_storage_size (`Callable[[Tensor], int]`): A function that returns the size of a tensor when saved on disk in bytes. @@ -87,10 +87,10 @@ def split_state_dict_into_shards_factory( Returns: [`StateDictSplit`]: A `StateDictSplit` object containing the shards and the index to retrieve them. """ - storage_id_to_tensors: Dict[Any, List[str]] = {} + storage_id_to_tensors: dict[Any, list[str]] = {} - shard_list: List[Dict[str, TensorT]] = [] - current_shard: Dict[str, TensorT] = {} + shard_list: list[dict[str, TensorT]] = [] + current_shard: dict[str, TensorT] = {} current_shard_size = 0 total_size = 0 diff --git a/src/huggingface_hub/serialization/_dduf.py b/src/huggingface_hub/serialization/_dduf.py index a1debadb3a..c184509c63 100644 --- a/src/huggingface_hub/serialization/_dduf.py +++ b/src/huggingface_hub/serialization/_dduf.py @@ -7,7 +7,7 @@ from contextlib import contextmanager from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Dict, Generator, Iterable, Tuple, Union +from typing import Any, Generator, Iterable, Union from ..errors import DDUFCorruptedFileError, DDUFExportError, DDUFInvalidEntryNameError @@ -87,7 +87,7 @@ def read_text(self, encoding: str = "utf-8") -> str: return f.read(self.length).decode(encoding=encoding) -def read_dduf_file(dduf_path: Union[os.PathLike, str]) -> Dict[str, DDUFEntry]: +def read_dduf_file(dduf_path: Union[os.PathLike, str]) -> dict[str, DDUFEntry]: """ Read a DDUF file and return a dictionary of entries. @@ -98,7 +98,7 @@ def read_dduf_file(dduf_path: Union[os.PathLike, str]) -> Dict[str, DDUFEntry]: The path to the DDUF file to read. Returns: - `Dict[str, DDUFEntry]`: + `dict[str, DDUFEntry]`: A dictionary of [`DDUFEntry`] indexed by filename. Raises: @@ -157,7 +157,7 @@ def read_dduf_file(dduf_path: Union[os.PathLike, str]) -> Dict[str, DDUFEntry]: def export_entries_as_dduf( - dduf_path: Union[str, os.PathLike], entries: Iterable[Tuple[str, Union[str, Path, bytes]]] + dduf_path: Union[str, os.PathLike], entries: Iterable[tuple[str, Union[str, Path, bytes]]] ) -> None: """Write a DDUF file from an iterable of entries. @@ -167,7 +167,7 @@ def export_entries_as_dduf( Args: dduf_path (`str` or `os.PathLike`): The path to the DDUF file to write. - entries (`Iterable[Tuple[str, Union[str, Path, bytes]]]`): + entries (`Iterable[tuple[str, Union[str, Path, bytes]]]`): An iterable of entries to write in the DDUF file. Each entry is a tuple with the filename and the content. The filename should be the path to the file in the DDUF archive. The content can be a string or a pathlib.Path representing a path to a file on the local disk or directly the content as bytes. @@ -201,7 +201,7 @@ def export_entries_as_dduf( >>> pipe = DiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4") ... # ... do some work with the pipeline - >>> def as_entries(pipe: DiffusionPipeline) -> Generator[Tuple[str, bytes], None, None]: + >>> def as_entries(pipe: DiffusionPipeline) -> Generator[tuple[str, bytes], None, None]: ... # Build an generator that yields the entries to add to the DDUF file. ... # The first element of the tuple is the filename in the DDUF archive (must use UNIX separator!). The second element is the content of the file. ... # Entries will be evaluated lazily when the DDUF file is created (only 1 entry is loaded in memory at a time) @@ -267,7 +267,7 @@ def export_folder_as_dduf(dduf_path: Union[str, os.PathLike], folder_path: Union """ folder_path = Path(folder_path) - def _iterate_over_folder() -> Iterable[Tuple[str, Path]]: + def _iterate_over_folder() -> Iterable[tuple[str, Path]]: for path in Path(folder_path).glob("**/*"): if not path.is_file(): continue diff --git a/src/huggingface_hub/serialization/_tensorflow.py b/src/huggingface_hub/serialization/_tensorflow.py index 59ed8110b2..affcaf4834 100644 --- a/src/huggingface_hub/serialization/_tensorflow.py +++ b/src/huggingface_hub/serialization/_tensorflow.py @@ -15,7 +15,7 @@ import math import re -from typing import TYPE_CHECKING, Dict, Union +from typing import TYPE_CHECKING, Union from .. import constants from ._base import MAX_SHARD_SIZE, StateDictSplit, split_state_dict_into_shards_factory @@ -26,7 +26,7 @@ def split_tf_state_dict_into_shards( - state_dict: Dict[str, "tf.Tensor"], + state_dict: dict[str, "tf.Tensor"], *, filename_pattern: str = constants.TF2_WEIGHTS_FILE_PATTERN, max_shard_size: Union[int, str] = MAX_SHARD_SIZE, @@ -47,7 +47,7 @@ def split_tf_state_dict_into_shards( Args: - state_dict (`Dict[str, Tensor]`): + state_dict (`dict[str, Tensor]`): The state dictionary to save. filename_pattern (`str`, *optional*): The pattern to generate the files names in which the model will be saved. Pattern must be a string that diff --git a/src/huggingface_hub/serialization/_torch.py b/src/huggingface_hub/serialization/_torch.py index c5c70fc89b..00c591134b 100644 --- a/src/huggingface_hub/serialization/_torch.py +++ b/src/huggingface_hub/serialization/_torch.py @@ -20,7 +20,7 @@ from collections import defaultdict, namedtuple from functools import lru_cache from pathlib import Path -from typing import TYPE_CHECKING, Any, Dict, Iterable, List, NamedTuple, Optional, Set, Tuple, Union +from typing import TYPE_CHECKING, Any, Iterable, NamedTuple, Optional, Union from packaging import version @@ -43,10 +43,10 @@ def save_torch_model( filename_pattern: Optional[str] = None, force_contiguous: bool = True, max_shard_size: Union[int, str] = MAX_SHARD_SIZE, - metadata: Optional[Dict[str, str]] = None, + metadata: Optional[dict[str, str]] = None, safe_serialization: bool = True, is_main_process: bool = True, - shared_tensors_to_discard: Optional[List[str]] = None, + shared_tensors_to_discard: Optional[list[str]] = None, ): """ Saves a given torch model to disk, handling sharding and shared tensors issues. @@ -92,7 +92,7 @@ def save_torch_model( that reason. Defaults to `True`. max_shard_size (`int` or `str`, *optional*): The maximum size of each shard, in bytes. Defaults to 5GB. - metadata (`Dict[str, str]`, *optional*): + metadata (`dict[str, str]`, *optional*): Extra information to save along with the model. Some metadata will be added for each dropped tensors. This information will not be enough to recover the entire shared structure but might help understanding things. @@ -104,7 +104,7 @@ def save_torch_model( Whether the process calling this is the main process or not. Useful when in distributed training like TPUs and need to call this function from all processes. In this case, set `is_main_process=True` only on the main process to avoid race conditions. Defaults to True. - shared_tensors_to_discard (`List[str]`, *optional*): + shared_tensors_to_discard (`list[str]`, *optional*): List of tensor names to drop when saving shared tensors. If not provided and shared tensors are detected, it will drop the first name alphabetically. @@ -137,16 +137,16 @@ def save_torch_model( def save_torch_state_dict( - state_dict: Dict[str, "torch.Tensor"], + state_dict: dict[str, "torch.Tensor"], save_directory: Union[str, Path], *, filename_pattern: Optional[str] = None, force_contiguous: bool = True, max_shard_size: Union[int, str] = MAX_SHARD_SIZE, - metadata: Optional[Dict[str, str]] = None, + metadata: Optional[dict[str, str]] = None, safe_serialization: bool = True, is_main_process: bool = True, - shared_tensors_to_discard: Optional[List[str]] = None, + shared_tensors_to_discard: Optional[list[str]] = None, ) -> None: """ Save a model state dictionary to the disk, handling sharding and shared tensors issues. @@ -177,7 +177,7 @@ def save_torch_state_dict( Args: - state_dict (`Dict[str, torch.Tensor]`): + state_dict (`dict[str, torch.Tensor]`): The state dictionary to save. save_directory (`str` or `Path`): The directory in which the model will be saved. @@ -192,7 +192,7 @@ def save_torch_state_dict( that reason. Defaults to `True`. max_shard_size (`int` or `str`, *optional*): The maximum size of each shard, in bytes. Defaults to 5GB. - metadata (`Dict[str, str]`, *optional*): + metadata (`dict[str, str]`, *optional*): Extra information to save along with the model. Some metadata will be added for each dropped tensors. This information will not be enough to recover the entire shared structure but might help understanding things. @@ -204,7 +204,7 @@ def save_torch_state_dict( Whether the process calling this is the main process or not. Useful when in distributed training like TPUs and need to call this function from all processes. In this case, set `is_main_process=True` only on the main process to avoid race conditions. Defaults to True. - shared_tensors_to_discard (`List[str]`, *optional*): + shared_tensors_to_discard (`list[str]`, *optional*): List of tensor names to drop when saving shared tensors. If not provided and shared tensors are detected, it will drop the first name alphabetically. @@ -300,7 +300,7 @@ def save_torch_state_dict( def split_torch_state_dict_into_shards( - state_dict: Dict[str, "torch.Tensor"], + state_dict: dict[str, "torch.Tensor"], *, filename_pattern: str = constants.SAFETENSORS_WEIGHTS_FILE_PATTERN, max_shard_size: Union[int, str] = MAX_SHARD_SIZE, @@ -329,7 +329,7 @@ def split_torch_state_dict_into_shards( Args: - state_dict (`Dict[str, torch.Tensor]`): + state_dict (`dict[str, torch.Tensor]`): The state dictionary to save. filename_pattern (`str`, *optional*): The pattern to generate the files names in which the model will be saved. Pattern must be a string that @@ -348,7 +348,7 @@ def split_torch_state_dict_into_shards( >>> from safetensors.torch import save_file as safe_save_file >>> from huggingface_hub import split_torch_state_dict_into_shards - >>> def save_state_dict(state_dict: Dict[str, torch.Tensor], save_directory: str): + >>> def save_state_dict(state_dict: dict[str, torch.Tensor], save_directory: str): ... state_dict_split = split_torch_state_dict_into_shards(state_dict) ... for filename, tensors in state_dict_split.filename_to_tensors.items(): ... shard = {tensor: state_dict[tensor] for tensor in tensors} @@ -560,7 +560,7 @@ def load_state_dict_from_file( map_location: Optional[Union[str, "torch.device"]] = None, weights_only: bool = False, mmap: bool = False, -) -> Union[Dict[str, "torch.Tensor"], Any]: +) -> Union[dict[str, "torch.Tensor"], Any]: """ Loads a checkpoint file, handling both safetensors and pickle checkpoint formats. @@ -580,7 +580,7 @@ def load_state_dict_from_file( loading safetensors files, as the `safetensors` library uses memory mapping by default. Returns: - `Union[Dict[str, "torch.Tensor"], Any]`: The loaded checkpoint. + `Union[dict[str, "torch.Tensor"], Any]`: The loaded checkpoint. - For safetensors files: always returns a dictionary mapping parameter names to tensors. - For pickle files: returns any Python object that was pickled (commonly a state dict, but could be an entire model, optimizer state, or any other Python object). @@ -700,7 +700,7 @@ def _validate_keys_for_strict_loading( raise RuntimeError(error_message) -def _get_unique_id(tensor: "torch.Tensor") -> Union[int, Tuple[Any, ...]]: +def _get_unique_id(tensor: "torch.Tensor") -> Union[int, tuple[Any, ...]]: """Returns a unique id for plain tensor or a (potentially nested) Tuple of unique id for the flattened Tensor if the input is a wrapper tensor subclass Tensor @@ -741,7 +741,7 @@ def _get_unique_id(tensor: "torch.Tensor") -> Union[int, Tuple[Any, ...]]: return unique_id -def get_torch_storage_id(tensor: "torch.Tensor") -> Optional[Tuple["torch.device", Union[int, Tuple[Any, ...]], int]]: +def get_torch_storage_id(tensor: "torch.Tensor") -> Optional[tuple["torch.device", Union[int, tuple[Any, ...]], int]]: """ Return unique identifier to a tensor storage. @@ -815,7 +815,7 @@ def is_torch_tpu_available(check_device=True): return False -def storage_ptr(tensor: "torch.Tensor") -> Union[int, Tuple[Any, ...]]: +def storage_ptr(tensor: "torch.Tensor") -> Union[int, tuple[Any, ...]]: """ Taken from https://github.com/huggingface/safetensors/blob/079781fd0dc455ba0fe851e2b4507c33d0c0d407/bindings/python/py_src/safetensors/torch.py#L11. """ @@ -841,10 +841,10 @@ def storage_ptr(tensor: "torch.Tensor") -> Union[int, Tuple[Any, ...]]: def _clean_state_dict_for_safetensors( - state_dict: Dict[str, "torch.Tensor"], - metadata: Dict[str, str], + state_dict: dict[str, "torch.Tensor"], + metadata: dict[str, str], force_contiguous: bool = True, - shared_tensors_to_discard: Optional[List[str]] = None, + shared_tensors_to_discard: Optional[list[str]] = None, ): """Remove shared tensors from state_dict and update metadata accordingly (for reloading). @@ -878,7 +878,7 @@ def _end_ptr(tensor: "torch.Tensor") -> int: return stop -def _filter_shared_not_shared(tensors: List[Set[str]], state_dict: Dict[str, "torch.Tensor"]) -> List[Set[str]]: +def _filter_shared_not_shared(tensors: list[set[str]], state_dict: dict[str, "torch.Tensor"]) -> list[set[str]]: """ Taken from https://github.com/huggingface/safetensors/blob/079781fd0dc455ba0fe851e2b4507c33d0c0d407/bindings/python/py_src/safetensors/torch.py#L44 """ @@ -906,7 +906,7 @@ def _filter_shared_not_shared(tensors: List[Set[str]], state_dict: Dict[str, "to return filtered_tensors -def _find_shared_tensors(state_dict: Dict[str, "torch.Tensor"]) -> List[Set[str]]: +def _find_shared_tensors(state_dict: dict[str, "torch.Tensor"]) -> list[set[str]]: """ Taken from https://github.com/huggingface/safetensors/blob/079781fd0dc455ba0fe851e2b4507c33d0c0d407/bindings/python/py_src/safetensors/torch.py#L69. """ @@ -943,11 +943,11 @@ def _is_complete(tensor: "torch.Tensor") -> bool: def _remove_duplicate_names( - state_dict: Dict[str, "torch.Tensor"], + state_dict: dict[str, "torch.Tensor"], *, - preferred_names: Optional[List[str]] = None, - discard_names: Optional[List[str]] = None, -) -> Dict[str, List[str]]: + preferred_names: Optional[list[str]] = None, + discard_names: Optional[list[str]] = None, +) -> dict[str, list[str]]: """ Taken from https://github.com/huggingface/safetensors/blob/079781fd0dc455ba0fe851e2b4507c33d0c0d407/bindings/python/py_src/safetensors/torch.py#L80 """ diff --git a/src/huggingface_hub/utils/_auth.py b/src/huggingface_hub/utils/_auth.py index 72be4dedbd..f19ac3e5f6 100644 --- a/src/huggingface_hub/utils/_auth.py +++ b/src/huggingface_hub/utils/_auth.py @@ -19,7 +19,7 @@ import warnings from pathlib import Path from threading import Lock -from typing import Dict, Optional +from typing import Optional from .. import constants from ._runtime import is_colab_enterprise, is_google_colab @@ -125,13 +125,13 @@ def _get_token_from_file() -> Optional[str]: return None -def get_stored_tokens() -> Dict[str, str]: +def get_stored_tokens() -> dict[str, str]: """ Returns the parsed INI file containing the access tokens. The file is located at `HF_STORED_TOKENS_PATH`, defaulting to `~/.cache/huggingface/stored_tokens`. If the file does not exist, an empty dictionary is returned. - Returns: `Dict[str, str]` + Returns: `dict[str, str]` Key is the token name and value is the token. """ tokens_path = Path(constants.HF_STORED_TOKENS_PATH) @@ -147,12 +147,12 @@ def get_stored_tokens() -> Dict[str, str]: return stored_tokens -def _save_stored_tokens(stored_tokens: Dict[str, str]) -> None: +def _save_stored_tokens(stored_tokens: dict[str, str]) -> None: """ Saves the given configuration to the stored tokens file. Args: - stored_tokens (`Dict[str, str]`): + stored_tokens (`dict[str, str]`): The stored tokens to save. Key is the token name and value is the token. """ stored_tokens_path = Path(constants.HF_STORED_TOKENS_PATH) diff --git a/src/huggingface_hub/utils/_cache_manager.py b/src/huggingface_hub/utils/_cache_manager.py index 311e164a4f..656e548585 100644 --- a/src/huggingface_hub/utils/_cache_manager.py +++ b/src/huggingface_hub/utils/_cache_manager.py @@ -20,7 +20,7 @@ from collections import defaultdict from dataclasses import dataclass from pathlib import Path -from typing import Dict, FrozenSet, List, Literal, Optional, Set, Union +from typing import Literal, Optional, Union from huggingface_hub.errors import CacheNotFound, CorruptedCacheException @@ -119,9 +119,9 @@ class CachedRevisionInfo: snapshot_path (`Path`): Path to the revision directory in the `snapshots` folder. It contains the exact tree structure as the repo on the Hub. - files: (`FrozenSet[CachedFileInfo]`): + files: (`frozenset[CachedFileInfo]`): Set of [`~CachedFileInfo`] describing all files contained in the snapshot. - refs (`FrozenSet[str]`): + refs (`frozenset[str]`): Set of `refs` pointing to this revision. If the revision has no `refs`, it is considered detached. Example: `{"main", "2.4.0"}` or `{"refs/pr/1"}`. @@ -149,8 +149,8 @@ class CachedRevisionInfo: commit_hash: str snapshot_path: Path size_on_disk: int - files: FrozenSet[CachedFileInfo] - refs: FrozenSet[str] + files: frozenset[CachedFileInfo] + refs: frozenset[str] last_modified: float @@ -196,7 +196,7 @@ class CachedRepoInfo: Sum of the blob file sizes in the cached repo. nb_files (`int`): Total number of blob files in the cached repo. - revisions (`FrozenSet[CachedRevisionInfo]`): + revisions (`frozenset[CachedRevisionInfo]`): Set of [`~CachedRevisionInfo`] describing all revisions cached in the repo. last_accessed (`float`): Timestamp of the last time a blob file of the repo has been accessed. @@ -225,7 +225,7 @@ class CachedRepoInfo: repo_path: Path size_on_disk: int nb_files: int - revisions: FrozenSet[CachedRevisionInfo] + revisions: frozenset[CachedRevisionInfo] last_accessed: float last_modified: float @@ -260,7 +260,7 @@ def size_on_disk_str(self) -> str: return _format_size(self.size_on_disk) @property - def refs(self) -> Dict[str, CachedRevisionInfo]: + def refs(self) -> dict[str, CachedRevisionInfo]: """ (property) Mapping between `refs` and revision data structures. """ @@ -277,21 +277,21 @@ class DeleteCacheStrategy: Args: expected_freed_size (`float`): Expected freed size once strategy is executed. - blobs (`FrozenSet[Path]`): + blobs (`frozenset[Path]`): Set of blob file paths to be deleted. - refs (`FrozenSet[Path]`): + refs (`frozenset[Path]`): Set of reference file paths to be deleted. - repos (`FrozenSet[Path]`): + repos (`frozenset[Path]`): Set of entire repo paths to be deleted. - snapshots (`FrozenSet[Path]`): + snapshots (`frozenset[Path]`): Set of snapshots to be deleted (directory of symlinks). """ expected_freed_size: int - blobs: FrozenSet[Path] - refs: FrozenSet[Path] - repos: FrozenSet[Path] - snapshots: FrozenSet[Path] + blobs: frozenset[Path] + refs: frozenset[Path] + repos: frozenset[Path] + snapshots: frozenset[Path] @property def expected_freed_size_str(self) -> str: @@ -352,10 +352,10 @@ class HFCacheInfo: Args: size_on_disk (`int`): Sum of all valid repo sizes in the cache-system. - repos (`FrozenSet[CachedRepoInfo]`): + repos (`frozenset[CachedRepoInfo]`): Set of [`~CachedRepoInfo`] describing all valid cached repos found on the cache-system while scanning. - warnings (`List[CorruptedCacheException]`): + warnings (`list[CorruptedCacheException]`): List of [`~CorruptedCacheException`] that occurred while scanning the cache. Those exceptions are captured so that the scan can continue. Corrupted repos are skipped from the scan. @@ -369,8 +369,8 @@ class HFCacheInfo: """ size_on_disk: int - repos: FrozenSet[CachedRepoInfo] - warnings: List[CorruptedCacheException] + repos: frozenset[CachedRepoInfo] + warnings: list[CorruptedCacheException] @property def size_on_disk_str(self) -> str: @@ -420,9 +420,9 @@ def delete_revisions(self, *revisions: str) -> DeleteCacheStrategy: """ - hashes_to_delete: Set[str] = set(revisions) + hashes_to_delete: set[str] = set(revisions) - repos_with_revisions: Dict[CachedRepoInfo, Set[CachedRevisionInfo]] = defaultdict(set) + repos_with_revisions: dict[CachedRepoInfo, set[CachedRevisionInfo]] = defaultdict(set) for repo in self.repos: for revision in repo.revisions: @@ -433,10 +433,10 @@ def delete_revisions(self, *revisions: str) -> DeleteCacheStrategy: if len(hashes_to_delete) > 0: logger.warning(f"Revision(s) not found - cannot delete them: {', '.join(hashes_to_delete)}") - delete_strategy_blobs: Set[Path] = set() - delete_strategy_refs: Set[Path] = set() - delete_strategy_repos: Set[Path] = set() - delete_strategy_snapshots: Set[Path] = set() + delete_strategy_blobs: set[Path] = set() + delete_strategy_refs: set[Path] = set() + delete_strategy_repos: set[Path] = set() + delete_strategy_snapshots: set[Path] = set() delete_strategy_expected_freed_size = 0 for affected_repo, revisions_to_delete in repos_with_revisions.items(): @@ -681,8 +681,8 @@ def scan_cache_dir(cache_dir: Optional[Union[str, Path]] = None) -> HFCacheInfo: f"Scan cache expects a directory but found a file: {cache_dir}. Please use `cache_dir` argument or set `HF_HUB_CACHE` environment variable." ) - repos: Set[CachedRepoInfo] = set() - warnings: List[CorruptedCacheException] = [] + repos: set[CachedRepoInfo] = set() + warnings: list[CorruptedCacheException] = [] for repo_path in cache_dir.iterdir(): if repo_path.name == ".locks": # skip './.locks/' folder continue @@ -718,7 +718,7 @@ def _scan_cached_repo(repo_path: Path) -> CachedRepoInfo: f"Repo type must be `dataset`, `model` or `space`, found `{repo_type}` ({repo_path})." ) - blob_stats: Dict[Path, os.stat_result] = {} # Key is blob_path, value is blob stats + blob_stats: dict[Path, os.stat_result] = {} # Key is blob_path, value is blob stats snapshots_path = repo_path / "snapshots" refs_path = repo_path / "refs" @@ -729,7 +729,7 @@ def _scan_cached_repo(repo_path: Path) -> CachedRepoInfo: # Scan over `refs` directory # key is revision hash, value is set of refs - refs_by_hash: Dict[str, Set[str]] = defaultdict(set) + refs_by_hash: dict[str, set[str]] = defaultdict(set) if refs_path.exists(): # Example of `refs` directory # ── refs @@ -752,7 +752,7 @@ def _scan_cached_repo(repo_path: Path) -> CachedRepoInfo: refs_by_hash[commit_hash].add(ref_name) # Scan snapshots directory - cached_revisions: Set[CachedRevisionInfo] = set() + cached_revisions: set[CachedRevisionInfo] = set() for revision_path in snapshots_path.iterdir(): # Ignore OS-created helper files if revision_path.name in FILES_TO_IGNORE: diff --git a/src/huggingface_hub/utils/_deprecation.py b/src/huggingface_hub/utils/_deprecation.py index 4cb8d6e418..51063879db 100644 --- a/src/huggingface_hub/utils/_deprecation.py +++ b/src/huggingface_hub/utils/_deprecation.py @@ -62,7 +62,7 @@ def _deprecate_arguments( Args: version (`str`): The version when deprecated arguments will result in error. - deprecated_args (`List[str]`): + deprecated_args (`list[str]`): List of the arguments to be deprecated. custom_message (`str`, *optional*): Warning message that is raised. If not passed, a default warning message diff --git a/src/huggingface_hub/utils/_dotenv.py b/src/huggingface_hub/utils/_dotenv.py index 23b8a1b70a..97e3b885be 100644 --- a/src/huggingface_hub/utils/_dotenv.py +++ b/src/huggingface_hub/utils/_dotenv.py @@ -1,14 +1,14 @@ # AI-generated module (ChatGPT) import re -from typing import Dict, Optional +from typing import Optional -def load_dotenv(dotenv_str: str, environ: Optional[Dict[str, str]] = None) -> Dict[str, str]: +def load_dotenv(dotenv_str: str, environ: Optional[dict[str, str]] = None) -> dict[str, str]: """ Parse a DOTENV-format string and return a dictionary of key-value pairs. Handles quoted values, comments, export keyword, and blank lines. """ - env: Dict[str, str] = {} + env: dict[str, str] = {} line_pattern = re.compile( r""" ^\s* diff --git a/src/huggingface_hub/utils/_git_credential.py b/src/huggingface_hub/utils/_git_credential.py index 5ad84648a0..7aa03727d4 100644 --- a/src/huggingface_hub/utils/_git_credential.py +++ b/src/huggingface_hub/utils/_git_credential.py @@ -16,7 +16,7 @@ import re import subprocess -from typing import List, Optional +from typing import Optional from ..constants import ENDPOINT from ._subprocess import run_interactive_subprocess, run_subprocess @@ -34,7 +34,7 @@ ) -def list_credential_helpers(folder: Optional[str] = None) -> List[str]: +def list_credential_helpers(folder: Optional[str] = None) -> list[str]: """Return the list of git credential helpers configured. See https://git-scm.com/docs/gitcredentials. @@ -104,7 +104,7 @@ def unset_git_credential(username: str = "hf_user", folder: Optional[str] = None stdin.flush() -def _parse_credential_output(output: str) -> List[str]: +def _parse_credential_output(output: str) -> list[str]: """Parse the output of `git credential fill` to extract the password. Args: diff --git a/src/huggingface_hub/utils/_headers.py b/src/huggingface_hub/utils/_headers.py index 053a92a398..23726b56cc 100644 --- a/src/huggingface_hub/utils/_headers.py +++ b/src/huggingface_hub/utils/_headers.py @@ -14,7 +14,7 @@ # limitations under the License. """Contains utilities to handle headers to send in calls to Huggingface Hub.""" -from typing import Dict, Optional, Union +from typing import Optional, Union from huggingface_hub.errors import LocalTokenNotFoundError @@ -47,10 +47,10 @@ def build_hf_headers( token: Optional[Union[bool, str]] = None, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Union[Dict, str, None] = None, - headers: Optional[Dict[str, str]] = None, + user_agent: Union[dict, str, None] = None, + headers: Optional[dict[str, str]] = None, is_write_action: bool = False, -) -> Dict[str, str]: +) -> dict[str, str]: """ Build headers dictionary to send in a HF Hub call. @@ -90,7 +90,7 @@ def build_hf_headers( Ignored and deprecated argument. Returns: - A `Dict` of headers to pass in your API call. + A `dict` of headers to pass in your API call. Example: ```py @@ -176,7 +176,7 @@ def _http_user_agent( *, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Union[Dict, str, None] = None, + user_agent: Union[dict, str, None] = None, ) -> str: """Format a user-agent string containing information about the installed packages. diff --git a/src/huggingface_hub/utils/_http.py b/src/huggingface_hub/utils/_http.py index b3a545c722..15484ec10d 100644 --- a/src/huggingface_hub/utils/_http.py +++ b/src/huggingface_hub/utils/_http.py @@ -24,7 +24,7 @@ from contextlib import contextmanager from http import HTTPStatus from shlex import quote -from typing import Any, Callable, Generator, List, Optional, Tuple, Type, Union +from typing import Any, Callable, Generator, Optional, Union import httpx @@ -260,11 +260,11 @@ def _http_backoff_base( max_retries: int = 5, base_wait_time: float = 1, max_wait_time: float = 8, - retry_on_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ( + retry_on_exceptions: Union[type[Exception], tuple[type[Exception], ...]] = ( httpx.TimeoutException, httpx.NetworkError, ), - retry_on_status_codes: Union[int, Tuple[int, ...]] = HTTPStatus.SERVICE_UNAVAILABLE, + retry_on_status_codes: Union[int, tuple[int, ...]] = HTTPStatus.SERVICE_UNAVAILABLE, stream: bool = False, **kwargs, ) -> Generator[httpx.Response, None, None]: @@ -345,11 +345,11 @@ def http_backoff( max_retries: int = 5, base_wait_time: float = 1, max_wait_time: float = 8, - retry_on_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ( + retry_on_exceptions: Union[type[Exception], tuple[type[Exception], ...]] = ( httpx.TimeoutException, httpx.NetworkError, ), - retry_on_status_codes: Union[int, Tuple[int, ...]] = HTTPStatus.SERVICE_UNAVAILABLE, + retry_on_status_codes: Union[int, tuple[int, ...]] = HTTPStatus.SERVICE_UNAVAILABLE, **kwargs, ) -> httpx.Response: """Wrapper around httpx to retry calls on an endpoint, with exponential backoff. @@ -375,10 +375,10 @@ def http_backoff( `max_wait_time`. max_wait_time (`float`, *optional*, defaults to `8`): Maximum duration (in seconds) to wait before retrying. - retry_on_exceptions (`Type[Exception]` or `Tuple[Type[Exception]]`, *optional*): + retry_on_exceptions (`type[Exception]` or `tuple[type[Exception]]`, *optional*): Define which exceptions must be caught to retry the request. Can be a single type or a tuple of types. By default, retry on `httpx.TimeoutException` and `httpx.NetworkError`. - retry_on_status_codes (`int` or `Tuple[int]`, *optional*, defaults to `503`): + retry_on_status_codes (`int` or `tuple[int]`, *optional*, defaults to `503`): Define on which status codes the request must be retried. By default, only HTTP 503 Service Unavailable is retried. **kwargs (`dict`, *optional*): @@ -432,11 +432,11 @@ def http_stream_backoff( max_retries: int = 5, base_wait_time: float = 1, max_wait_time: float = 8, - retry_on_exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]] = ( + retry_on_exceptions: Union[type[Exception], tuple[type[Exception], ...]] = ( httpx.TimeoutException, httpx.NetworkError, ), - retry_on_status_codes: Union[int, Tuple[int, ...]] = HTTPStatus.SERVICE_UNAVAILABLE, + retry_on_status_codes: Union[int, tuple[int, ...]] = HTTPStatus.SERVICE_UNAVAILABLE, **kwargs, ) -> Generator[httpx.Response, None, None]: """Wrapper around httpx to retry calls on an endpoint, with exponential backoff. @@ -462,10 +462,10 @@ def http_stream_backoff( `max_wait_time`. max_wait_time (`float`, *optional*, defaults to `8`): Maximum duration (in seconds) to wait before retrying. - retry_on_exceptions (`Type[Exception]` or `Tuple[Type[Exception]]`, *optional*): + retry_on_exceptions (`type[Exception]` or `tuple[type[Exception]]`, *optional*): Define which exceptions must be caught to retry the request. Can be a single type or a tuple of types. By default, retry on `httpx.Timeout` and `httpx.NetworkError`. - retry_on_status_codes (`int` or `Tuple[int]`, *optional*, defaults to `503`): + retry_on_status_codes (`int` or `tuple[int]`, *optional*, defaults to `503`): Define on which status codes the request must be retried. By default, only HTTP 503 Service Unavailable is retried. **kwargs (`dict`, *optional*): @@ -636,7 +636,7 @@ def hf_raise_for_status(response: httpx.Response, endpoint_name: Optional[str] = raise _format(HfHubHTTPError, str(e), response) from e -def _format(error_type: Type[HfHubHTTPError], custom_message: str, response: httpx.Response) -> HfHubHTTPError: +def _format(error_type: type[HfHubHTTPError], custom_message: str, response: httpx.Response) -> HfHubHTTPError: server_errors = [] # Retrieve server error from header @@ -722,7 +722,7 @@ def _curlify(request: httpx.Request) -> str: Implementation vendored from https://github.com/ofw/curlify/blob/master/curlify.py. MIT License Copyright (c) 2016 Egor. """ - parts: List[Tuple[Any, Any]] = [ + parts: list[tuple[Any, Any]] = [ ("curl", None), ("-X", request.method), ] diff --git a/src/huggingface_hub/utils/_pagination.py b/src/huggingface_hub/utils/_pagination.py index 1d63ad4b49..275d5d5f5a 100644 --- a/src/huggingface_hub/utils/_pagination.py +++ b/src/huggingface_hub/utils/_pagination.py @@ -14,7 +14,7 @@ # limitations under the License. """Contains utilities to handle pagination on Huggingface Hub.""" -from typing import Dict, Iterable, Optional +from typing import Iterable, Optional import httpx @@ -24,7 +24,7 @@ logger = logging.get_logger(__name__) -def paginate(path: str, params: Dict, headers: Dict) -> Iterable: +def paginate(path: str, params: dict, headers: dict) -> Iterable: """Fetch a list of models/datasets/spaces and paginate through results. This is using the same "Link" header format as GitHub. diff --git a/src/huggingface_hub/utils/_paths.py b/src/huggingface_hub/utils/_paths.py index 4f2c0ebce0..f4d48c2cfe 100644 --- a/src/huggingface_hub/utils/_paths.py +++ b/src/huggingface_hub/utils/_paths.py @@ -16,7 +16,7 @@ from fnmatch import fnmatch from pathlib import Path -from typing import Callable, Generator, Iterable, List, Optional, TypeVar, Union +from typing import Callable, Generator, Iterable, Optional, TypeVar, Union T = TypeVar("T") @@ -39,8 +39,8 @@ def filter_repo_objects( items: Iterable[T], *, - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, key: Optional[Callable[[T], str]] = None, ) -> Generator[T, None, None]: """Filter repo objects based on an allowlist and a denylist. @@ -55,10 +55,10 @@ def filter_repo_objects( Args: items (`Iterable`): List of items to filter. - allow_patterns (`str` or `List[str]`, *optional*): + allow_patterns (`str` or `list[str]`, *optional*): Patterns constituting the allowlist. If provided, item paths must match at least one pattern from the allowlist. - ignore_patterns (`str` or `List[str]`, *optional*): + ignore_patterns (`str` or `list[str]`, *optional*): Patterns constituting the denylist. If provided, item paths must not match any patterns from the denylist. key (`Callable[[T], str]`, *optional*): diff --git a/src/huggingface_hub/utils/_runtime.py b/src/huggingface_hub/utils/_runtime.py index 9e38e6da74..9d52091fc9 100644 --- a/src/huggingface_hub/utils/_runtime.py +++ b/src/huggingface_hub/utils/_runtime.py @@ -19,7 +19,7 @@ import platform import sys import warnings -from typing import Any, Dict +from typing import Any from .. import __version__, constants @@ -312,7 +312,7 @@ def is_colab_enterprise() -> bool: return os.environ.get("VERTEX_PRODUCT") == "COLAB_ENTERPRISE" -def dump_environment_info() -> Dict[str, Any]: +def dump_environment_info() -> dict[str, Any]: """Dump information about the machine to help debugging issues. Similar helper exist in: @@ -326,7 +326,7 @@ def dump_environment_info() -> Dict[str, Any]: token = get_token() # Generic machine info - info: Dict[str, Any] = { + info: dict[str, Any] = { "huggingface_hub version": get_hf_hub_version(), "Platform": platform.platform(), "Python version": get_python_version(), diff --git a/src/huggingface_hub/utils/_safetensors.py b/src/huggingface_hub/utils/_safetensors.py index 38546c6d34..8b9c257055 100644 --- a/src/huggingface_hub/utils/_safetensors.py +++ b/src/huggingface_hub/utils/_safetensors.py @@ -2,7 +2,7 @@ import operator from collections import defaultdict from dataclasses import dataclass, field -from typing import Dict, List, Literal, Optional, Tuple +from typing import Literal, Optional FILENAME_T = str @@ -19,17 +19,17 @@ class TensorInfo: Attributes: dtype (`str`): The data type of the tensor ("F64", "F32", "F16", "BF16", "I64", "I32", "I16", "I8", "U8", "BOOL"). - shape (`List[int]`): + shape (`list[int]`): The shape of the tensor. - data_offsets (`Tuple[int, int]`): + data_offsets (`tuple[int, int]`): The offsets of the data in the file as a tuple `[BEGIN, END]`. parameter_count (`int`): The number of parameters in the tensor. """ dtype: DTYPE_T - shape: List[int] - data_offsets: Tuple[int, int] + shape: list[int] + data_offsets: tuple[int, int] parameter_count: int = field(init=False) def __post_init__(self) -> None: @@ -49,22 +49,22 @@ class SafetensorsFileMetadata: For more details regarding the safetensors format, check out https://huggingface.co/docs/safetensors/index#format. Attributes: - metadata (`Dict`): + metadata (`dict`): The metadata contained in the file. - tensors (`Dict[str, TensorInfo]`): + tensors (`dict[str, TensorInfo]`): A map of all tensors. Keys are tensor names and values are information about the corresponding tensor, as a [`TensorInfo`] object. - parameter_count (`Dict[str, int]`): + parameter_count (`dict[str, int]`): A map of the number of parameters per data type. Keys are data types and values are the number of parameters of that data type. """ - metadata: Dict[str, str] - tensors: Dict[TENSOR_NAME_T, TensorInfo] - parameter_count: Dict[DTYPE_T, int] = field(init=False) + metadata: dict[str, str] + tensors: dict[TENSOR_NAME_T, TensorInfo] + parameter_count: dict[DTYPE_T, int] = field(init=False) def __post_init__(self) -> None: - parameter_count: Dict[DTYPE_T, int] = defaultdict(int) + parameter_count: dict[DTYPE_T, int] = defaultdict(int) for tensor in self.tensors.values(): parameter_count[tensor.dtype] += tensor.parameter_count self.parameter_count = dict(parameter_count) @@ -82,29 +82,29 @@ class SafetensorsRepoMetadata: For more details regarding the safetensors format, check out https://huggingface.co/docs/safetensors/index#format. Attributes: - metadata (`Dict`, *optional*): + metadata (`dict`, *optional*): The metadata contained in the 'model.safetensors.index.json' file, if it exists. Only populated for sharded models. sharded (`bool`): Whether the repo contains a sharded model or not. - weight_map (`Dict[str, str]`): + weight_map (`dict[str, str]`): A map of all weights. Keys are tensor names and values are filenames of the files containing the tensors. - files_metadata (`Dict[str, SafetensorsFileMetadata]`): + files_metadata (`dict[str, SafetensorsFileMetadata]`): A map of all files metadata. Keys are filenames and values are the metadata of the corresponding file, as a [`SafetensorsFileMetadata`] object. - parameter_count (`Dict[str, int]`): + parameter_count (`dict[str, int]`): A map of the number of parameters per data type. Keys are data types and values are the number of parameters of that data type. """ - metadata: Optional[Dict] + metadata: Optional[dict] sharded: bool - weight_map: Dict[TENSOR_NAME_T, FILENAME_T] # tensor name -> filename - files_metadata: Dict[FILENAME_T, SafetensorsFileMetadata] # filename -> metadata - parameter_count: Dict[DTYPE_T, int] = field(init=False) + weight_map: dict[TENSOR_NAME_T, FILENAME_T] # tensor name -> filename + files_metadata: dict[FILENAME_T, SafetensorsFileMetadata] # filename -> metadata + parameter_count: dict[DTYPE_T, int] = field(init=False) def __post_init__(self) -> None: - parameter_count: Dict[DTYPE_T, int] = defaultdict(int) + parameter_count: dict[DTYPE_T, int] = defaultdict(int) for file_metadata in self.files_metadata.values(): for dtype, nb_parameters_ in file_metadata.parameter_count.items(): parameter_count[dtype] += nb_parameters_ diff --git a/src/huggingface_hub/utils/_subprocess.py b/src/huggingface_hub/utils/_subprocess.py index fdabf1c4df..e2b9a4f2f1 100644 --- a/src/huggingface_hub/utils/_subprocess.py +++ b/src/huggingface_hub/utils/_subprocess.py @@ -20,7 +20,7 @@ from contextlib import contextmanager from io import StringIO from pathlib import Path -from typing import IO, Generator, List, Optional, Tuple, Union +from typing import IO, Generator, Optional, Union from .logging import get_logger @@ -51,7 +51,7 @@ def capture_output() -> Generator[StringIO, None, None]: def run_subprocess( - command: Union[str, List[str]], + command: Union[str, list[str]], folder: Optional[Union[str, Path]] = None, check=True, **kwargs, @@ -62,7 +62,7 @@ def run_subprocess( be captured. Args: - command (`str` or `List[str]`): + command (`str` or `list[str]`): The command to execute as a string or list of strings. folder (`str`, *optional*): The folder in which to run the command. Defaults to current working @@ -70,7 +70,7 @@ def run_subprocess( check (`bool`, *optional*, defaults to `True`): Setting `check` to `True` will raise a `subprocess.CalledProcessError` when the subprocess has a non-zero exit code. - kwargs (`Dict[str]`): + kwargs (`dict[str]`): Keyword arguments to be passed to the `subprocess.run` underlying command. Returns: @@ -96,23 +96,23 @@ def run_subprocess( @contextmanager def run_interactive_subprocess( - command: Union[str, List[str]], + command: Union[str, list[str]], folder: Optional[Union[str, Path]] = None, **kwargs, -) -> Generator[Tuple[IO[str], IO[str]], None, None]: +) -> Generator[tuple[IO[str], IO[str]], None, None]: """Run a subprocess in an interactive mode in a context manager. Args: - command (`str` or `List[str]`): + command (`str` or `list[str]`): The command to execute as a string or list of strings. folder (`str`, *optional*): The folder in which to run the command. Defaults to current working directory (from `os.getcwd()`). - kwargs (`Dict[str]`): + kwargs (`dict[str]`): Keyword arguments to be passed to the `subprocess.run` underlying command. Returns: - `Tuple[IO[str], IO[str]]`: A tuple with `stdin` and `stdout` to interact + `tuple[IO[str], IO[str]]`: A tuple with `stdin` and `stdout` to interact with the process (input and output are utf-8 encoded). Example: diff --git a/src/huggingface_hub/utils/_telemetry.py b/src/huggingface_hub/utils/_telemetry.py index 2ba4a6349a..e8f0bd0345 100644 --- a/src/huggingface_hub/utils/_telemetry.py +++ b/src/huggingface_hub/utils/_telemetry.py @@ -1,6 +1,6 @@ from queue import Queue from threading import Lock, Thread -from typing import Dict, Optional, Union +from typing import Optional, Union from urllib.parse import quote from .. import constants, logging @@ -22,7 +22,7 @@ def send_telemetry( *, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Union[Dict, str, None] = None, + user_agent: Union[dict, str, None] = None, ) -> None: """ Sends telemetry that helps tracking usage of different HF libraries. @@ -98,7 +98,7 @@ def _send_telemetry_in_thread( *, library_name: Optional[str] = None, library_version: Optional[str] = None, - user_agent: Union[Dict, str, None] = None, + user_agent: Union[dict, str, None] = None, ) -> None: """Contains the actual data sending data to the Hub. diff --git a/src/huggingface_hub/utils/_typing.py b/src/huggingface_hub/utils/_typing.py index b8388ca0c0..6fcbe4a530 100644 --- a/src/huggingface_hub/utils/_typing.py +++ b/src/huggingface_hub/utils/_typing.py @@ -15,10 +15,10 @@ """Handle typing imports based on system compatibility.""" import sys -from typing import Any, Callable, List, Literal, Type, TypeVar, Union, get_args, get_origin +from typing import Any, Callable, Literal, Type, TypeVar, Union, get_args, get_origin -UNION_TYPES: List[Any] = [Union] +UNION_TYPES: list[Any] = [Union] if sys.version_info >= (3, 10): from types import UnionType diff --git a/src/huggingface_hub/utils/_validators.py b/src/huggingface_hub/utils/_validators.py index 2a1b473446..8bbb16d87e 100644 --- a/src/huggingface_hub/utils/_validators.py +++ b/src/huggingface_hub/utils/_validators.py @@ -19,7 +19,7 @@ import warnings from functools import wraps from itertools import chain -from typing import Any, Dict +from typing import Any from huggingface_hub.errors import HFValidationError @@ -172,7 +172,7 @@ def validate_repo_id(repo_id: str) -> None: raise HFValidationError(f"Repo_id cannot end by '.git': '{repo_id}'.") -def smoothly_deprecate_proxies(fn_name: str, kwargs: Dict[str, Any]) -> Dict[str, Any]: +def smoothly_deprecate_proxies(fn_name: str, kwargs: dict[str, Any]) -> dict[str, Any]: """Smoothly deprecate `proxies` in the `huggingface_hub` codebase. This function removes the `proxies` key from the kwargs and warns the user that the `proxies` argument is ignored. @@ -203,7 +203,7 @@ def smoothly_deprecate_proxies(fn_name: str, kwargs: Dict[str, Any]) -> Dict[str return new_kwargs -def smoothly_deprecate_use_auth_token(fn_name: str, has_token: bool, kwargs: Dict[str, Any]) -> Dict[str, Any]: +def smoothly_deprecate_use_auth_token(fn_name: str, has_token: bool, kwargs: dict[str, Any]) -> dict[str, Any]: """Smoothly deprecate `use_auth_token` in the `huggingface_hub` codebase. The long-term goal is to remove any mention of `use_auth_token` in the codebase in diff --git a/src/huggingface_hub/utils/_xet.py b/src/huggingface_hub/utils/_xet.py index c49c8f88f0..473c451251 100644 --- a/src/huggingface_hub/utils/_xet.py +++ b/src/huggingface_hub/utils/_xet.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from enum import Enum -from typing import Dict, Optional +from typing import Optional import httpx @@ -63,11 +63,11 @@ def parse_xet_file_data_from_response( ) -def parse_xet_connection_info_from_headers(headers: Dict[str, str]) -> Optional[XetConnectionInfo]: +def parse_xet_connection_info_from_headers(headers: dict[str, str]) -> Optional[XetConnectionInfo]: """ Parse XET connection info from the HTTP headers or return None if not found. Args: - headers (`Dict`): + headers (`dict`): HTTP headers to extract the XET metadata from. Returns: `XetConnectionInfo` or `None`: @@ -92,7 +92,7 @@ def parse_xet_connection_info_from_headers(headers: Dict[str, str]) -> Optional[ def refresh_xet_connection_info( *, file_data: XetFileData, - headers: Dict[str, str], + headers: dict[str, str], ) -> XetConnectionInfo: """ Utilizes the information in the parsed metadata to request the Hub xet connection information. @@ -100,7 +100,7 @@ def refresh_xet_connection_info( Args: file_data: (`XetFileData`): The file data needed to refresh the xet connection information. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): Headers to use for the request, including authorization headers and user agent. Returns: `XetConnectionInfo`: @@ -123,9 +123,9 @@ def fetch_xet_connection_info_from_repo_info( repo_id: str, repo_type: str, revision: Optional[str] = None, - headers: Dict[str, str], + headers: dict[str, str], endpoint: Optional[str] = None, - params: Optional[Dict[str, str]] = None, + params: Optional[dict[str, str]] = None, ) -> XetConnectionInfo: """ Uses the repo info to request a xet access token from Hub. @@ -138,11 +138,11 @@ def fetch_xet_connection_info_from_repo_info( Type of the repo to upload to: `"model"`, `"dataset"` or `"space"`. revision (`str`, `optional`): The revision of the repo to get the token for. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): Headers to use for the request, including authorization headers and user agent. endpoint (`str`, `optional`): The endpoint to use for the request. Defaults to the Hub endpoint. - params (`Dict[str, str]`, `optional`): + params (`dict[str, str]`, `optional`): Additional parameters to pass with the request. Returns: `XetConnectionInfo`: @@ -161,8 +161,8 @@ def fetch_xet_connection_info_from_repo_info( @validate_hf_hub_args def _fetch_xet_connection_info_with_url( url: str, - headers: Dict[str, str], - params: Optional[Dict[str, str]] = None, + headers: dict[str, str], + params: Optional[dict[str, str]] = None, ) -> XetConnectionInfo: """ Requests the xet connection info from the supplied URL. This includes the @@ -170,9 +170,9 @@ def _fetch_xet_connection_info_with_url( Args: url: (`str`): The access token endpoint URL. - headers (`Dict[str, str]`): + headers (`dict[str, str]`): Headers to use for the request, including authorization headers and user agent. - params (`Dict[str, str]`, `optional`): + params (`dict[str, str]`, `optional`): Additional parameters to pass with the request. Returns: `XetConnectionInfo`: diff --git a/src/huggingface_hub/utils/_xet_progress_reporting.py b/src/huggingface_hub/utils/_xet_progress_reporting.py index e47740d5c5..05c87b835a 100644 --- a/src/huggingface_hub/utils/_xet_progress_reporting.py +++ b/src/huggingface_hub/utils/_xet_progress_reporting.py @@ -64,7 +64,7 @@ def format_desc(self, name: str, indent: bool) -> str: return f"{padding}{name.ljust(width)}" - def update_progress(self, total_update: PyTotalProgressUpdate, item_updates: List[PyItemProgressUpdate]): + def update_progress(self, total_update: PyTotalProgressUpdate, item_updates: list[PyItemProgressUpdate]): # Update all the per-item values. for item in item_updates: item_name = item.item_name diff --git a/src/huggingface_hub/utils/insecure_hashlib.py b/src/huggingface_hub/utils/insecure_hashlib.py index 6901b6d647..639e04460b 100644 --- a/src/huggingface_hub/utils/insecure_hashlib.py +++ b/src/huggingface_hub/utils/insecure_hashlib.py @@ -25,14 +25,8 @@ # ``` import functools import hashlib -import sys -if sys.version_info >= (3, 9): - md5 = functools.partial(hashlib.md5, usedforsecurity=False) - sha1 = functools.partial(hashlib.sha1, usedforsecurity=False) - sha256 = functools.partial(hashlib.sha256, usedforsecurity=False) -else: - md5 = hashlib.md5 - sha1 = hashlib.sha1 - sha256 = hashlib.sha256 +md5 = functools.partial(hashlib.md5, usedforsecurity=False) +sha1 = functools.partial(hashlib.sha1, usedforsecurity=False) +sha256 = functools.partial(hashlib.sha256, usedforsecurity=False) diff --git a/src/huggingface_hub/utils/tqdm.py b/src/huggingface_hub/utils/tqdm.py index 46bd0ace67..4d47cafc8f 100644 --- a/src/huggingface_hub/utils/tqdm.py +++ b/src/huggingface_hub/utils/tqdm.py @@ -86,7 +86,7 @@ import warnings from contextlib import contextmanager, nullcontext from pathlib import Path -from typing import ContextManager, Dict, Iterator, Optional, Union +from typing import ContextManager, Iterator, Optional, Union from tqdm.auto import tqdm as old_tqdm @@ -102,7 +102,7 @@ # progress bar visibility through code. By default, progress bars are turned on. -progress_bar_states: Dict[str, bool] = {} +progress_bar_states: dict[str, bool] = {} def disable_progress_bars(name: Optional[str] = None) -> None: diff --git a/tests/test_dduf.py b/tests/test_dduf.py index 7c4b5afc9f..c4d509ec85 100644 --- a/tests/test_dduf.py +++ b/tests/test_dduf.py @@ -1,7 +1,7 @@ import json import zipfile from pathlib import Path -from typing import Iterable, Tuple, Union +from typing import Iterable, Union import pytest from pytest_mock import MockerFixture @@ -146,7 +146,7 @@ def test_export_folder(self, dummy_folder: Path, mocker: MockerFixture): class TestExportEntries: @pytest.fixture - def dummy_entries(self, tmp_path: Path) -> Iterable[Tuple[str, Union[str, Path, bytes]]]: + def dummy_entries(self, tmp_path: Path) -> Iterable[tuple[str, Union[str, Path, bytes]]]: (tmp_path / "model_index.json").write_text(json.dumps({"foo": "bar"})) (tmp_path / "doesnt_have_to_be_same_name.safetensors").write_bytes(b"this is safetensors content") @@ -157,7 +157,7 @@ def dummy_entries(self, tmp_path: Path) -> Iterable[Tuple[str, Union[str, Path, ] def test_export_entries( - self, tmp_path: Path, dummy_entries: Iterable[Tuple[str, Union[str, Path, bytes]]], mocker: MockerFixture + self, tmp_path: Path, dummy_entries: Iterable[tuple[str, Union[str, Path, bytes]]], mocker: MockerFixture ): mock = mocker.patch("huggingface_hub.serialization._dduf._validate_dduf_structure") export_entries_as_dduf(tmp_path / "dummy.dduf", dummy_entries) diff --git a/tests/test_file_download.py b/tests/test_file_download.py index bb76af9c47..87a2a645b9 100644 --- a/tests/test_file_download.py +++ b/tests/test_file_download.py @@ -19,7 +19,7 @@ import warnings from contextlib import contextmanager from pathlib import Path -from typing import Iterable, List +from typing import Iterable from unittest.mock import Mock, patch import httpx @@ -1008,7 +1008,7 @@ def _iter_content_4() -> Iterable[bytes]: ), ], ) - def test_http_get_with_range_headers(self, caplog, initial_range: str, expected_ranges: List[str]): + def test_http_get_with_range_headers(self, caplog, initial_range: str, expected_ranges: list[str]): def _iter_content_1() -> Iterable[bytes]: yield b"0" * 10 yield b"0" * 10 diff --git a/tests/test_hf_api.py b/tests/test_hf_api.py index ce5c08d2e2..ff7a829baf 100644 --- a/tests/test_hf_api.py +++ b/tests/test_hf_api.py @@ -25,7 +25,7 @@ from dataclasses import fields from io import BytesIO from pathlib import Path -from typing import List, Optional, Set, Union, get_args +from typing import Optional, Union, get_args from unittest.mock import Mock, patch from urllib.parse import quote, urlparse @@ -1758,7 +1758,7 @@ def tearDown(self) -> None: self._api.delete_repo(repo_id=self.repo_id) super().tearDown() - def remote_files(self) -> Set[set]: + def remote_files(self) -> set[set]: return set(self._api.list_repo_files(repo_id=self.repo_id)) def test_delete_single_file(self): @@ -2196,7 +2196,7 @@ def test_dataset_info_with_file_metadata(self): assert files is not None self._check_siblings_metadata(files) - def _check_siblings_metadata(self, files: List[RepoSibling]): + def _check_siblings_metadata(self, files: list[RepoSibling]): """Check requested metadata has been received from the server.""" at_least_one_lfs = False for file in files: @@ -2657,7 +2657,7 @@ def setUp(self) -> None: self.create_commit_mock.return_value.pr_url = None self.api.create_commit = self.create_commit_mock - def _upload_folder_alias(self, **kwargs) -> List[Union[CommitOperationAdd, CommitOperationDelete]]: + def _upload_folder_alias(self, **kwargs) -> list[Union[CommitOperationAdd, CommitOperationDelete]]: """Alias to call `upload_folder` + retrieve the CommitOperation list passed to `create_commit`.""" if "folder_path" not in kwargs: kwargs["folder_path"] = self.cache_dir @@ -4488,7 +4488,7 @@ class HfApiInferenceCatalogTest(HfApiCommonTest): def test_list_inference_catalog(self) -> None: models = self._api.list_inference_catalog() # note: @experimental api # Check that server returns a list[str] => at least if it changes in the future, we'll notice - assert isinstance(models, List) + assert isinstance(models, list) assert len(models) > 0 assert all(isinstance(model, str) for model in models) diff --git a/tests/test_hub_mixin.py b/tests/test_hub_mixin.py index 90582e846d..5b1ccdd574 100644 --- a/tests/test_hub_mixin.py +++ b/tests/test_hub_mixin.py @@ -4,7 +4,7 @@ import unittest from dataclasses import dataclass from pathlib import Path -from typing import Dict, Optional, Union, get_type_hints +from typing import Optional, Union, get_type_hints from unittest.mock import Mock, patch import jedi @@ -58,7 +58,7 @@ def __init__(self, config: ConfigAsDataclass): class DummyModelConfigAsDict(BaseModel, ModelHubMixin): - def __init__(self, config: Dict): + def __init__(self, config: dict): pass @@ -68,7 +68,7 @@ def __init__(self, config: Optional[ConfigAsDataclass] = None): class DummyModelConfigAsOptionalDict(BaseModel, ModelHubMixin): - def __init__(self, config: Optional[Dict] = None): + def __init__(self, config: Optional[dict] = None): pass @@ -85,7 +85,7 @@ def _save_pretrained(self, save_directory: Path) -> None: def _from_pretrained( cls, model_id: Union[str, Path], - config: Optional[Dict] = None, + config: Optional[dict] = None, **kwargs, ) -> "BaseModel": return cls(**kwargs) diff --git a/tests/test_hub_mixin_pytorch.py b/tests/test_hub_mixin_pytorch.py index dd965189fe..1ebde60d42 100644 --- a/tests/test_hub_mixin_pytorch.py +++ b/tests/test_hub_mixin_pytorch.py @@ -4,7 +4,7 @@ import unittest from argparse import Namespace from pathlib import Path -from typing import Any, Dict, Optional, TypeVar +from typing import Any, Optional, TypeVar from unittest.mock import Mock, patch import pytest @@ -89,7 +89,7 @@ def __init__( self.not_jsonable = not_jsonable class DummyModelWithConfigAndKwargs(nn.Module, PyTorchModelHubMixin): - def __init__(self, num_classes: int = 42, state: str = "layernorm", config: Optional[Dict] = None, **kwargs): + def __init__(self, num_classes: int = 42, state: str = "layernorm", config: Optional[dict] = None, **kwargs): super().__init__() class DummyModelWithModelCardAndCustomKwargs( diff --git a/tests/test_inference_client.py b/tests/test_inference_client.py index e2370aa708..cedf6b4b89 100644 --- a/tests/test_inference_client.py +++ b/tests/test_inference_client.py @@ -18,7 +18,6 @@ import string import time from pathlib import Path -from typing import List from unittest.mock import MagicMock, patch import numpy as np @@ -215,7 +214,7 @@ } -def list_clients(task: str) -> List[pytest.param]: +def list_clients(task: str) -> list[pytest.param]: """Get list of clients for a specific task, with proper skip handling.""" clients = [] for provider, tasks in _RECOMMENDED_MODELS_FOR_VCR.items(): diff --git a/tests/test_inference_providers.py b/tests/test_inference_providers.py index 333eb57d33..73346177ae 100644 --- a/tests/test_inference_providers.py +++ b/tests/test_inference_providers.py @@ -1,6 +1,5 @@ import base64 import logging -from typing import Dict from unittest.mock import MagicMock, patch import pytest @@ -1529,7 +1528,7 @@ def test_prepare_payload(self): ), ], ) -def test_recursive_merge(dict1: Dict, dict2: Dict, expected: Dict): +def test_recursive_merge(dict1: dict, dict2: dict, expected: dict): initial_dict1 = dict1.copy() initial_dict2 = dict2.copy() assert recursive_merge(dict1, dict2) == expected @@ -1563,7 +1562,7 @@ def test_recursive_merge(dict1: Dict, dict2: Dict, expected: Dict): ({"a": [None, {"x": None}]}, {"a": [None, {}]}), ], ) -def test_filter_none(data: Dict, expected: Dict): +def test_filter_none(data: dict, expected: dict): """Test that filter_none removes None values from nested dictionaries.""" assert filter_none(data) == expected diff --git a/tests/test_inference_text_generation.py b/tests/test_inference_text_generation.py index 3135172e9d..4bb30e5665 100644 --- a/tests/test_inference_text_generation.py +++ b/tests/test_inference_text_generation.py @@ -4,7 +4,6 @@ # See './src/huggingface_hub/inference/_text_generation.py' for details. import json import unittest -from typing import Dict from unittest.mock import MagicMock, patch import pytest @@ -45,7 +44,7 @@ def test_validation_error(self): raise_text_generation_error(error) -def _mocked_error(payload: Dict) -> MagicMock: +def _mocked_error(payload: dict) -> MagicMock: error = HfHubHTTPError("message", response=MagicMock()) error.response.json.return_value = payload return error diff --git a/tests/test_inference_types.py b/tests/test_inference_types.py index 5f7a5b2a6e..c164877fd7 100644 --- a/tests/test_inference_types.py +++ b/tests/test_inference_types.py @@ -18,8 +18,8 @@ class DummyType(BaseInferenceType): @dataclass_with_extra class DummyNestedType(BaseInferenceType): item: DummyType - items: List[DummyType] - maybe_items: Optional[List[DummyType]] = None + items: List[DummyType] # works both with List and list + maybe_items: Optional[list[DummyType]] = None DUMMY_AS_DICT = {"foo": 42, "bar": "baz"} @@ -97,6 +97,7 @@ def test_parse_nested_class(): def test_all_fields_are_optional(): # all fields are optional => silently accept None if server returns less data than expected instance = DummyNestedType.parse_obj({"maybe_items": [{}, DUMMY_AS_BYTES]}) + assert isinstance(instance, DummyNestedType) assert instance.item is None assert instance.items is None assert len(instance.maybe_items) == 2 diff --git a/tests/test_serialization.py b/tests/test_serialization.py index dad7065de6..6bc74b9962 100644 --- a/tests/test_serialization.py +++ b/tests/test_serialization.py @@ -1,7 +1,7 @@ import json import struct from pathlib import Path -from typing import TYPE_CHECKING, Dict, List +from typing import TYPE_CHECKING from unittest.mock import Mock import pytest @@ -57,7 +57,7 @@ def is_dtensor_available(): @pytest.fixture -def dummy_state_dict() -> Dict[str, List[int]]: +def dummy_state_dict() -> dict[str, list[int]]: return { "layer_1": [6], "layer_2": [10], @@ -68,7 +68,7 @@ def dummy_state_dict() -> Dict[str, List[int]]: @pytest.fixture -def torch_state_dict() -> Dict[str, "torch.Tensor"]: +def torch_state_dict() -> dict[str, "torch.Tensor"]: try: import torch @@ -105,7 +105,7 @@ def __init__(self): @pytest.fixture -def torch_state_dict_tensor_subclass() -> Dict[str, "torch.Tensor"]: +def torch_state_dict_tensor_subclass() -> dict[str, "torch.Tensor"]: try: import torch # type: ignore[import] from torch.testing._internal.two_tensor import TwoTensor # type: ignore[import] @@ -124,7 +124,7 @@ def torch_state_dict_tensor_subclass() -> Dict[str, "torch.Tensor"]: @pytest.fixture -def torch_state_dict_shared_layers() -> Dict[str, "torch.Tensor"]: +def torch_state_dict_shared_layers() -> dict[str, "torch.Tensor"]: try: import torch # type: ignore[import] @@ -141,7 +141,7 @@ def torch_state_dict_shared_layers() -> Dict[str, "torch.Tensor"]: @pytest.fixture -def torch_state_dict_shared_layers_tensor_subclass() -> Dict[str, "torch.Tensor"]: +def torch_state_dict_shared_layers_tensor_subclass() -> dict[str, "torch.Tensor"]: try: import torch # type: ignore[import] from torch.testing._internal.two_tensor import TwoTensor # type: ignore[import] @@ -341,14 +341,14 @@ def test_save_torch_model(mocker: MockerFixture, tmp_path: Path) -> None: ) -def test_save_torch_state_dict_not_sharded(tmp_path: Path, torch_state_dict: Dict[str, "torch.Tensor"]) -> None: +def test_save_torch_state_dict_not_sharded(tmp_path: Path, torch_state_dict: dict[str, "torch.Tensor"]) -> None: """Save as safetensors without sharding.""" save_torch_state_dict(torch_state_dict, tmp_path, max_shard_size="1GB") assert (tmp_path / "model.safetensors").is_file() assert not (tmp_path / "model.safetensors.index.json").is_file() -def test_save_torch_state_dict_sharded(tmp_path: Path, torch_state_dict: Dict[str, "torch.Tensor"]) -> None: +def test_save_torch_state_dict_sharded(tmp_path: Path, torch_state_dict: dict[str, "torch.Tensor"]) -> None: """Save as safetensors with sharding.""" save_torch_state_dict(torch_state_dict, tmp_path, max_shard_size=30) assert not (tmp_path / "model.safetensors").is_file() @@ -369,7 +369,7 @@ def test_save_torch_state_dict_sharded(tmp_path: Path, torch_state_dict: Dict[st def test_save_torch_state_dict_unsafe_not_sharded( - tmp_path: Path, caplog: pytest.LogCaptureFixture, torch_state_dict: Dict[str, "torch.Tensor"] + tmp_path: Path, caplog: pytest.LogCaptureFixture, torch_state_dict: dict[str, "torch.Tensor"] ) -> None: """Save as pickle without sharding.""" with caplog.at_level("WARNING"): @@ -382,7 +382,7 @@ def test_save_torch_state_dict_unsafe_not_sharded( @pytest.mark.skipif(not is_wrapper_tensor_subclass_available(), reason="requires torch 2.1 or higher") def test_save_torch_state_dict_tensor_subclass_unsafe_not_sharded( - tmp_path: Path, caplog: pytest.LogCaptureFixture, torch_state_dict_tensor_subclass: Dict[str, "torch.Tensor"] + tmp_path: Path, caplog: pytest.LogCaptureFixture, torch_state_dict_tensor_subclass: dict[str, "torch.Tensor"] ) -> None: """Save as pickle without sharding.""" with caplog.at_level("WARNING"): @@ -399,7 +399,7 @@ def test_save_torch_state_dict_tensor_subclass_unsafe_not_sharded( def test_save_torch_state_dict_shared_layers_tensor_subclass_unsafe_not_sharded( tmp_path: Path, caplog: pytest.LogCaptureFixture, - torch_state_dict_shared_layers_tensor_subclass: Dict[str, "torch.Tensor"], + torch_state_dict_shared_layers_tensor_subclass: dict[str, "torch.Tensor"], ) -> None: """Save as pickle without sharding.""" with caplog.at_level("WARNING"): @@ -413,7 +413,7 @@ def test_save_torch_state_dict_shared_layers_tensor_subclass_unsafe_not_sharded( def test_save_torch_state_dict_unsafe_sharded( - tmp_path: Path, caplog: pytest.LogCaptureFixture, torch_state_dict: Dict[str, "torch.Tensor"] + tmp_path: Path, caplog: pytest.LogCaptureFixture, torch_state_dict: dict[str, "torch.Tensor"] ) -> None: """Save as pickle with sharding.""" # Check logs @@ -439,7 +439,7 @@ def test_save_torch_state_dict_unsafe_sharded( def test_save_torch_state_dict_shared_layers_not_sharded( - tmp_path: Path, torch_state_dict_shared_layers: Dict[str, "torch.Tensor"] + tmp_path: Path, torch_state_dict_shared_layers: dict[str, "torch.Tensor"] ) -> None: from safetensors.torch import load_file @@ -461,7 +461,7 @@ def test_save_torch_state_dict_shared_layers_not_sharded( def test_save_torch_state_dict_shared_layers_sharded( - tmp_path: Path, torch_state_dict_shared_layers: Dict[str, "torch.Tensor"] + tmp_path: Path, torch_state_dict_shared_layers: dict[str, "torch.Tensor"] ) -> None: from safetensors.torch import load_file @@ -480,7 +480,7 @@ def test_save_torch_state_dict_shared_layers_sharded( def test_save_torch_state_dict_discard_selected_sharded( - tmp_path: Path, torch_state_dict_shared_layers: Dict[str, "torch.Tensor"] + tmp_path: Path, torch_state_dict_shared_layers: dict[str, "torch.Tensor"] ) -> None: from safetensors.torch import load_file @@ -502,7 +502,7 @@ def test_save_torch_state_dict_discard_selected_sharded( def test_save_torch_state_dict_discard_selected_not_sharded( - tmp_path: Path, torch_state_dict_shared_layers: Dict[str, "torch.Tensor"] + tmp_path: Path, torch_state_dict_shared_layers: dict[str, "torch.Tensor"] ) -> None: from safetensors.torch import load_file @@ -529,7 +529,7 @@ def test_save_torch_state_dict_discard_selected_not_sharded( def test_split_torch_state_dict_into_shards( - tmp_path: Path, torch_state_dict_shared_layers_tensor_subclass: Dict[str, "torch.Tensor"] + tmp_path: Path, torch_state_dict_shared_layers_tensor_subclass: dict[str, "torch.Tensor"] ): # the model size is 72, setting max_shard_size to 32 means we'll shard the file state_dict_split = split_torch_state_dict_into_shards( @@ -540,7 +540,7 @@ def test_split_torch_state_dict_into_shards( assert state_dict_split.is_sharded -def test_save_torch_state_dict_custom_filename(tmp_path: Path, torch_state_dict: Dict[str, "torch.Tensor"]) -> None: +def test_save_torch_state_dict_custom_filename(tmp_path: Path, torch_state_dict: dict[str, "torch.Tensor"]) -> None: """Custom filename pattern is respected.""" # Not sharded save_torch_state_dict(torch_state_dict, tmp_path, filename_pattern="model.variant{suffix}.safetensors") @@ -556,7 +556,7 @@ def test_save_torch_state_dict_custom_filename(tmp_path: Path, torch_state_dict: def test_save_torch_state_dict_delete_existing_files( - tmp_path: Path, torch_state_dict: Dict[str, "torch.Tensor"] + tmp_path: Path, torch_state_dict: dict[str, "torch.Tensor"] ) -> None: """Directory is cleaned before saving new files.""" (tmp_path / "model.safetensors").touch() @@ -590,7 +590,7 @@ def test_save_torch_state_dict_delete_existing_files( def test_save_torch_state_dict_not_main_process( tmp_path: Path, - torch_state_dict: Dict[str, "torch.Tensor"], + torch_state_dict: dict[str, "torch.Tensor"], ) -> None: """ Test that previous files in the directory are not deleted when is_main_process=False. @@ -613,7 +613,7 @@ def test_save_torch_state_dict_not_main_process( @requires("torch") -def test_load_state_dict_from_file(tmp_path: Path, torch_state_dict: Dict[str, "torch.Tensor"]): +def test_load_state_dict_from_file(tmp_path: Path, torch_state_dict: dict[str, "torch.Tensor"]): """Test saving and loading a state dict with both safetensors and pickle formats.""" import torch # type: ignore[import] @@ -637,7 +637,7 @@ def test_load_state_dict_from_file(tmp_path: Path, torch_state_dict: Dict[str, " @requires("torch") def test_load_sharded_state_dict( tmp_path: Path, - torch_state_dict: Dict[str, "torch.Tensor"], + torch_state_dict: dict[str, "torch.Tensor"], dummy_model: "torch.nn.Module", ): """Test saving and loading a sharded state dict.""" @@ -666,7 +666,7 @@ def test_load_sharded_state_dict( @requires("torch") def test_load_from_directory_not_sharded( - tmp_path: Path, torch_state_dict: Dict[str, "torch.Tensor"], dummy_model: "torch.nn.Module" + tmp_path: Path, torch_state_dict: dict[str, "torch.Tensor"], dummy_model: "torch.nn.Module" ): import torch diff --git a/tests/test_utils_cache.py b/tests/test_utils_cache.py index efd8a961f3..a08ad14391 100644 --- a/tests/test_utils_cache.py +++ b/tests/test_utils_cache.py @@ -3,7 +3,7 @@ import time import unittest from pathlib import Path -from typing import Any, List +from typing import Any from unittest.mock import Mock import pytest @@ -854,6 +854,6 @@ def test_format_timesince(self) -> None: ) -def is_sublist(sub: List[Any], full: List[Any]) -> bool: +def is_sublist(sub: list[Any], full: list[Any]) -> bool: it = iter(full) return all(item in it for item in sub) diff --git a/tests/test_utils_paths.py b/tests/test_utils_paths.py index 82ffa174bd..39f311dd5f 100644 --- a/tests/test_utils_paths.py +++ b/tests/test_utils_paths.py @@ -1,7 +1,7 @@ import unittest from dataclasses import dataclass from pathlib import Path -from typing import Any, Callable, List, Optional, Union +from typing import Any, Callable, Optional, Union from huggingface_hub.utils import DEFAULT_IGNORE_PATTERNS, filter_repo_objects @@ -97,10 +97,10 @@ def test_filter_object_with_folder(self) -> None: def _check( self, - items: List[Any], - expected_items: List[Any], - allow_patterns: Optional[Union[List[str], str]] = None, - ignore_patterns: Optional[Union[List[str], str]] = None, + items: list[Any], + expected_items: list[Any], + allow_patterns: Optional[Union[list[str], str]] = None, + ignore_patterns: Optional[Union[list[str], str]] = None, key: Optional[Callable[[Any], str]] = None, ) -> None: """Run `filter_repo_objects` and check output against expected result.""" diff --git a/tests/test_utils_strict_dataclass.py b/tests/test_utils_strict_dataclass.py index 4a4cd6d56c..5eb68161b6 100644 --- a/tests/test_utils_strict_dataclass.py +++ b/tests/test_utils_strict_dataclass.py @@ -1,6 +1,6 @@ import inspect from dataclasses import asdict, astuple, dataclass, is_dataclass -from typing import Any, Dict, List, Literal, Optional, Set, Tuple, Union, get_type_hints +from typing import Any, Literal, Optional, Union, get_type_hints import jedi import pytest @@ -136,18 +136,18 @@ class Config: ("John", Literal["John", "Doe"]), (5, Literal[4, 5, 6]), # List - ([1, 2, 3], List[int]), - ([1, 2, "3"], List[Union[int, str]]), + ([1, 2, 3], list[int]), + ([1, 2, "3"], list[Union[int, str]]), # Tuple - ((1, 2, 3), Tuple[int, int, int]), - ((1, 2, "3"), Tuple[int, int, str]), - ((1, 2, 3, 4), Tuple[int, ...]), + ((1, 2, 3), tuple[int, int, int]), + ((1, 2, "3"), tuple[int, int, str]), + ((1, 2, 3, 4), tuple[int, ...]), # Dict - ({"a": 1, "b": 2}, Dict[str, int]), - ({"a": 1, "b": "2"}, Dict[str, Union[int, str]]), + ({"a": 1, "b": 2}, dict[str, int]), + ({"a": 1, "b": "2"}, dict[str, Union[int, str]]), # Set - ({1, 2, 3}, Set[int]), - ({1, 2, "3"}, Set[Union[int, str]]), + ({1, 2, 3}, set[int]), + ({1, 2, "3"}, set[Union[int, str]]), # Custom classes (DummyClass(), DummyClass), # Any @@ -162,13 +162,13 @@ class Config: (2, DummyClass(), None), ], }, - Dict[ + dict[ str, - List[ - Tuple[ + list[ + tuple[ int, DummyClass, - Optional[Set[Union[int, str],]], + Optional[set[Union[int, str],]], ] ], ], @@ -197,19 +197,19 @@ def test_type_validator_valid(value, type_annotation): ("Ada", Literal["John", "Doe"]), (3, Literal[4, 5, 6]), # List - (5, List[int]), - ([1, 2, "3"], List[int]), + (5, list[int]), + ([1, 2, "3"], list[int]), # Tuple - (5, Tuple[int, int, int]), - ((1, 2, "3"), Tuple[int, int, int]), - ((1, 2, 3, 4), Tuple[int, int, int]), - ((1, 2, "3", 4), Tuple[int, ...]), + (5, tuple[int, int, int]), + ((1, 2, "3"), tuple[int, int, int]), + ((1, 2, 3, 4), tuple[int, int, int]), + ((1, 2, "3", 4), tuple[int, ...]), # Dict - (5, Dict[str, int]), - ({"a": 1, "b": "2"}, Dict[str, int]), + (5, dict[str, int]), + ({"a": 1, "b": "2"}, dict[str, int]), # Set - (5, Set[int]), - ({1, 2, "3"}, Set[int]), + (5, set[int]), + ({1, 2, "3"}, set[int]), # Custom classes (5, DummyClass), ("John", DummyClass), diff --git a/tests/test_xet_download.py b/tests/test_xet_download.py index be59bf125e..24e6877738 100644 --- a/tests/test_xet_download.py +++ b/tests/test_xet_download.py @@ -1,7 +1,6 @@ import os from contextlib import contextmanager from pathlib import Path -from typing import Tuple from unittest.mock import DEFAULT, Mock, patch from huggingface_hub import snapshot_download @@ -318,7 +317,7 @@ def test_download_backward_compatibility(self, tmp_path): connection_info = refresh_xet_connection_info(file_data=xet_file_data, headers={}) - def token_refresher() -> Tuple[str, int]: + def token_refresher() -> tuple[str, int]: connection_info = refresh_xet_connection_info(file_data=xet_file_data, headers={}) return connection_info.access_token, connection_info.expiration_unix_epoch diff --git a/tests/test_xet_upload.py b/tests/test_xet_upload.py index d2f4a8b55f..2db0279c97 100644 --- a/tests/test_xet_upload.py +++ b/tests/test_xet_upload.py @@ -15,7 +15,6 @@ from contextlib import contextmanager from io import BytesIO from pathlib import Path -from typing import Tuple from unittest.mock import MagicMock, patch import pytest @@ -366,7 +365,7 @@ def test_hf_xet_with_token_refresher(self, api, tmp_path, repo_url): # manually construct parameters to hf_xet.download_files and use a locally defined token_refresher function # to verify that token refresh works as expected. - def token_refresher() -> Tuple[str, int]: + def token_refresher() -> tuple[str, int]: # Issue a token refresh by returning a new access token and expiration time new_connection = refresh_xet_connection_info(file_data=xet_filedata, headers=headers) return new_connection.access_token, new_connection.expiration_unix_epoch diff --git a/tests/testing_utils.py b/tests/testing_utils.py index 792f08ad17..bc88840aee 100644 --- a/tests/testing_utils.py +++ b/tests/testing_utils.py @@ -9,7 +9,7 @@ from enum import Enum from functools import wraps from pathlib import Path -from typing import Callable, Optional, Type, TypeVar, Union +from typing import Callable, Optional, TypeVar, Union from unittest.mock import Mock, patch import httpx @@ -302,7 +302,7 @@ def _inner_test_function(*args, **kwargs): return _inner_decorator -def xfail_on_windows(reason: str, raises: Optional[Type[Exception]] = None): +def xfail_on_windows(reason: str, raises: Optional[type[Exception]] = None): """ Decorator to flag tests that we expect to fail on Windows. @@ -312,7 +312,7 @@ def xfail_on_windows(reason: str, raises: Optional[Type[Exception]] = None): Args: reason (`str`): Reason why it should fail. - raises (`Type[Exception]`): + raises (`type[Exception]`): The error type we except to happen. """ diff --git a/utils/check_all_variable.py b/utils/check_all_variable.py index 0754fae7e9..6b093740a9 100644 --- a/utils/check_all_variable.py +++ b/utils/check_all_variable.py @@ -18,7 +18,7 @@ import argparse import re from pathlib import Path -from typing import Dict, List, NoReturn +from typing import NoReturn from huggingface_hub import _SUBMOD_ATTRS @@ -26,7 +26,7 @@ INIT_FILE_PATH = Path(__file__).parents[1] / "src" / "huggingface_hub" / "__init__.py" -def format_all_definition(submod_attrs: Dict[str, List[str]]) -> str: +def format_all_definition(submod_attrs: dict[str, list[str]]) -> str: """ Generate a formatted static __all__ definition with grouped comments. """ @@ -39,7 +39,7 @@ def format_all_definition(submod_attrs: Dict[str, List[str]]) -> str: return "\n".join(lines) -def parse_all_definition(content: str) -> List[str]: +def parse_all_definition(content: str) -> list[str]: """ Extract the current __all__ contents from file content. diff --git a/utils/check_task_parameters.py b/utils/check_task_parameters.py index eec18aeaa9..d8948ef278 100644 --- a/utils/check_task_parameters.py +++ b/utils/check_task_parameters.py @@ -42,7 +42,7 @@ import textwrap from collections import defaultdict from pathlib import Path -from typing import Any, Dict, List, NoReturn, Optional, Set, Tuple +from typing import Any, NoReturn, Optional import libcst as cst from helpers import format_source_code @@ -101,7 +101,7 @@ class DataclassFieldCollector(cst.CSTVisitor): def __init__(self, dataclass_name: str): self.dataclass_name = dataclass_name - self.parameters: Dict[str, Dict[str, str]] = {} + self.parameters: dict[str, dict[str, str]] = {} def visit_ClassDef(self, node: cst.ClassDef) -> None: """Visit class definitions to find the target dataclass.""" @@ -130,7 +130,7 @@ def visit_ClassDef(self, node: cst.ClassDef) -> None: @staticmethod def _extract_docstring( - body_statements: List[cst.CSTNode], + body_statements: list[cst.CSTNode], field_index: int, ) -> str: """Extract the docstring following a field definition.""" @@ -169,7 +169,7 @@ class MethodArgumentsCollector(cst.CSTVisitor): def __init__(self, method_name: str): self.method_name = method_name - self.parameters: Dict[str, Dict[str, str]] = {} + self.parameters: dict[str, dict[str, str]] = {} def visit_FunctionDef(self, node: cst.FunctionDef) -> None: if node.name.value != self.method_name: @@ -194,7 +194,7 @@ def _extract_docstring(self, node: cst.FunctionDef) -> str: return node.body.body[0].body[0].value.evaluated_value return "" - def _parse_docstring_params(self, docstring: str) -> Dict[str, str]: + def _parse_docstring_params(self, docstring: str) -> dict[str, str]: """Parse parameter descriptions from docstring.""" param_docs = {} lines = docstring.split("\n") @@ -230,7 +230,7 @@ def _parse_docstring_params(self, docstring: str) -> Dict[str, str]: class AddImports(cst.CSTTransformer): """Transformer that adds import statements to the module.""" - def __init__(self, imports_to_add: List[cst.BaseStatement]): + def __init__(self, imports_to_add: list[cst.BaseStatement]): self.imports_to_add = imports_to_add self.added = False @@ -265,7 +265,7 @@ def leave_Module( class UpdateParameters(cst.CSTTransformer): """Updates a method's parameters, types, and docstrings.""" - def __init__(self, method_name: str, param_updates: Dict[str, Dict[str, str]]): + def __init__(self, method_name: str, param_updates: dict[str, dict[str, str]]): self.method_name = method_name self.param_updates = param_updates self.found_method = False # Flag to check if the method is found @@ -383,10 +383,10 @@ def _update_docstring_content(self, docstring: str) -> str: def _format_param_docstring( self, param_name: str, - param_info: Dict[str, str], + param_info: dict[str, str], param_indent: str, desc_indent: str, - ) -> List[str]: + ) -> list[str]: """Format the docstring lines for a single parameter.""" # Extract and format the parameter type param_type = param_info["type"] @@ -417,12 +417,12 @@ def _format_param_docstring( def _process_existing_params( self, - docstring_lines: List[str], - params_to_update: Dict[str, Dict[str, str]], + docstring_lines: list[str], + params_to_update: dict[str, dict[str, str]], args_index: int, param_indent: str, desc_indent: str, - ) -> Tuple[List[str], Dict[str, Dict[str, str]]]: + ) -> tuple[list[str], dict[str, dict[str, str]]]: """Update existing parameters in the docstring.""" # track the params that are updated params_updated = params_to_update.copy() @@ -473,12 +473,12 @@ def _process_existing_params( def _add_new_params( self, - docstring_lines: List[str], - new_params: Dict[str, Dict[str, str]], + docstring_lines: list[str], + new_params: dict[str, dict[str, str]], args_index: int, param_indent: str, desc_indent: str, - ) -> List[str]: + ) -> list[str]: """Add new parameters to the docstring.""" # Find the insertion point after existing parameters insertion_index = args_index + 1 @@ -521,7 +521,7 @@ def _check_parameters( parameters_module: cst.Module, method_name: str, parameter_type_name: str, -) -> Dict[str, Dict[str, Any]]: +) -> dict[str, dict[str, Any]]: """ Check for missing parameters and outdated types/docstrings. @@ -571,7 +571,7 @@ def _check_parameters( def _update_parameters( module: cst.Module, method_name: str, - param_updates: Dict[str, Dict[str, str]], + param_updates: dict[str, dict[str, str]], ) -> cst.Module: """ Update method parameters, types and docstrings. @@ -590,21 +590,21 @@ def _update_parameters( def _get_imports_to_add( - parameters: Dict[str, Dict[str, str]], + parameters: dict[str, dict[str, str]], parameters_module: cst.Module, inference_client_module: cst.Module, -) -> Dict[str, List[str]]: +) -> dict[str, list[str]]: """ Get the needed imports for missing parameters. Args: - parameters (Dict[str, Dict[str, str]]): Dictionary of parameters with their type and docstring. + parameters (dict[str, dict[str, str]]): Dictionary of parameters with their type and docstring. eg: {"function_to_apply": {"type": "ClassificationOutputTransform", "docstring": "Function to apply to the input."}} parameters_module (cst.Module): The module where the parameters are defined. inference_client_module (cst.Module): The module of the inference client. Returns: - Dict[str, List[str]]: A dictionary mapping modules to list of types to import. + dict[str, list[str]]: A dictionary mapping modules to list of types to import. eg: {"huggingface_hub.inference._generated.types": ["ClassificationOutputTransform"]} """ # Collect all type names from parameter annotations @@ -630,12 +630,12 @@ def _get_imports_to_add( return needed_imports -def _generate_import_statements(import_dict: Dict[str, List[str]]) -> str: +def _generate_import_statements(import_dict: dict[str, list[str]]) -> str: """ Generate import statements from a dictionary of needed imports. Args: - import_dict (Dict[str, List[str]]): Dictionary mapping modules to list of types to import. + import_dict (dict[str, list[str]]): Dictionary mapping modules to list of types to import. eg: {"typing": ["List", "Dict"], "huggingface_hub.inference._generated.types": ["ClassificationOutputTransform"]} Returns: @@ -658,7 +658,7 @@ def _normalize_docstring(docstring: str) -> str: # TODO: Needs to be improved, maybe using `typing.get_type_hints` instead (we gonna need to access the method though)? -def _collect_type_hints_from_annotation(annotation_str: str) -> Set[str]: +def _collect_type_hints_from_annotation(annotation_str: str) -> set[str]: """ Collect type hints from an annotation string. @@ -666,7 +666,7 @@ def _collect_type_hints_from_annotation(annotation_str: str) -> Set[str]: annotation_str (str): The annotation string. Returns: - Set[str]: A set of type hints. + set[str]: A set of type hints. """ type_string = annotation_str.replace(" ", "") builtin_types = {d for d in dir(builtins) if isinstance(getattr(builtins, d), type)} @@ -699,7 +699,7 @@ def _parse_module_from_file(filepath: Path) -> Optional[cst.Module]: def _check_and_update_parameters( - method_params: Dict[str, str], + method_params: dict[str, str], update: bool, ) -> NoReturn: """ diff --git a/utils/generate_inference_types.py b/utils/generate_inference_types.py index 823e814323..aaa071b8f3 100644 --- a/utils/generate_inference_types.py +++ b/utils/generate_inference_types.py @@ -17,7 +17,7 @@ import argparse import re from pathlib import Path -from typing import Dict, List, Literal, NoReturn, Optional +from typing import Literal, NoReturn, Optional import libcst as cst from helpers import check_and_update_file_content, format_source_code @@ -219,12 +219,12 @@ def _make_optional_fields_default_to_none(content: str): return "\n".join(lines) -def _list_dataclasses(content: str) -> List[str]: +def _list_dataclasses(content: str) -> list[str]: """List all dataclasses defined in the module.""" return INHERITED_DATACLASS_REGEX.findall(content) -def _list_type_aliases(content: str) -> List[str]: +def _list_type_aliases(content: str) -> list[str]: """List all type aliases defined in the module.""" return [alias_class for alias_class, _ in TYPE_ALIAS_REGEX.findall(content)] @@ -234,7 +234,7 @@ def is_deprecated(self, docstring: Optional[str]) -> bool: """Check if a docstring contains @deprecated.""" return docstring is not None and "@deprecated" in docstring.lower() - def get_docstring(self, body: List[cst.BaseStatement]) -> Optional[str]: + def get_docstring(self, body: list[cst.BaseStatement]) -> Optional[str]: """Extract docstring from a body of statements.""" if not body: return None @@ -294,7 +294,7 @@ def fix_inference_classes(content: str, module_name: str) -> str: return content -def create_init_py(dataclasses: Dict[str, List[str]]): +def create_init_py(dataclasses: dict[str, list[str]]): """Create __init__.py file with all dataclasses.""" content = INIT_PY_HEADER content += "\n" @@ -304,14 +304,14 @@ def create_init_py(dataclasses: Dict[str, List[str]]): return content -def add_dataclasses_to_main_init(content: str, dataclasses: Dict[str, List[str]]): +def add_dataclasses_to_main_init(content: str, dataclasses: dict[str, list[str]]): dataclasses_list = sorted({cls for classes in dataclasses.values() for cls in classes}) dataclasses_str = ", ".join(f"'{cls}'" for cls in dataclasses_list) return MAIN_INIT_PY_REGEX.sub(f'"inference._generated.types": [{dataclasses_str}]', content) -def generate_reference_package(dataclasses: Dict[str, List[str]], language: Literal["en", "ko"]) -> str: +def generate_reference_package(dataclasses: dict[str, list[str]], language: Literal["en", "ko"]) -> str: """Generate the reference package content.""" per_task_docs = []