huggingface-hub 0.33.5__py3-none-any.whl → 0.35.0rc0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of huggingface-hub might be problematic. Click here for more details.
- huggingface_hub/__init__.py +487 -525
- huggingface_hub/_commit_api.py +21 -28
- huggingface_hub/_jobs_api.py +145 -0
- huggingface_hub/_local_folder.py +7 -1
- huggingface_hub/_login.py +5 -5
- huggingface_hub/_oauth.py +1 -1
- huggingface_hub/_snapshot_download.py +11 -6
- huggingface_hub/_upload_large_folder.py +46 -23
- huggingface_hub/cli/__init__.py +27 -0
- huggingface_hub/cli/_cli_utils.py +69 -0
- huggingface_hub/cli/auth.py +210 -0
- huggingface_hub/cli/cache.py +405 -0
- huggingface_hub/cli/download.py +181 -0
- huggingface_hub/cli/hf.py +66 -0
- huggingface_hub/cli/jobs.py +522 -0
- huggingface_hub/cli/lfs.py +198 -0
- huggingface_hub/cli/repo.py +243 -0
- huggingface_hub/cli/repo_files.py +128 -0
- huggingface_hub/cli/system.py +52 -0
- huggingface_hub/cli/upload.py +316 -0
- huggingface_hub/cli/upload_large_folder.py +132 -0
- huggingface_hub/commands/_cli_utils.py +5 -0
- huggingface_hub/commands/delete_cache.py +3 -1
- huggingface_hub/commands/download.py +4 -0
- huggingface_hub/commands/env.py +3 -0
- huggingface_hub/commands/huggingface_cli.py +2 -0
- huggingface_hub/commands/repo.py +4 -0
- huggingface_hub/commands/repo_files.py +4 -0
- huggingface_hub/commands/scan_cache.py +3 -1
- huggingface_hub/commands/tag.py +3 -1
- huggingface_hub/commands/upload.py +4 -0
- huggingface_hub/commands/upload_large_folder.py +3 -1
- huggingface_hub/commands/user.py +11 -1
- huggingface_hub/commands/version.py +3 -0
- huggingface_hub/constants.py +1 -0
- huggingface_hub/file_download.py +16 -5
- huggingface_hub/hf_api.py +519 -7
- huggingface_hub/hf_file_system.py +8 -16
- huggingface_hub/hub_mixin.py +3 -3
- huggingface_hub/inference/_client.py +38 -39
- huggingface_hub/inference/_common.py +38 -11
- huggingface_hub/inference/_generated/_async_client.py +50 -51
- huggingface_hub/inference/_generated/types/__init__.py +1 -0
- huggingface_hub/inference/_generated/types/image_to_video.py +60 -0
- huggingface_hub/inference/_mcp/cli.py +36 -18
- huggingface_hub/inference/_mcp/constants.py +8 -0
- huggingface_hub/inference/_mcp/types.py +3 -0
- huggingface_hub/inference/_providers/__init__.py +4 -1
- huggingface_hub/inference/_providers/_common.py +3 -6
- huggingface_hub/inference/_providers/fal_ai.py +85 -42
- huggingface_hub/inference/_providers/hf_inference.py +17 -9
- huggingface_hub/inference/_providers/replicate.py +19 -1
- huggingface_hub/keras_mixin.py +2 -2
- huggingface_hub/repocard.py +1 -1
- huggingface_hub/repository.py +2 -2
- huggingface_hub/utils/_auth.py +1 -1
- huggingface_hub/utils/_cache_manager.py +2 -2
- huggingface_hub/utils/_dotenv.py +51 -0
- huggingface_hub/utils/_headers.py +1 -1
- huggingface_hub/utils/_runtime.py +1 -1
- huggingface_hub/utils/_xet.py +6 -2
- huggingface_hub/utils/_xet_progress_reporting.py +141 -0
- {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/METADATA +7 -8
- {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/RECORD +68 -51
- {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/entry_points.txt +1 -0
- {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/LICENSE +0 -0
- {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/WHEEL +0 -0
- {huggingface_hub-0.33.5.dist-info → huggingface_hub-0.35.0rc0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Implementation of a custom transfer agent for the transfer type "multipart" for
|
|
3
|
+
git-lfs.
|
|
4
|
+
|
|
5
|
+
Inspired by:
|
|
6
|
+
github.com/cbartz/git-lfs-swift-transfer-agent/blob/master/git_lfs_swift_transfer.py
|
|
7
|
+
|
|
8
|
+
Spec is: github.com/git-lfs/git-lfs/blob/master/docs/custom-transfers.md
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
To launch debugger while developing:
|
|
12
|
+
|
|
13
|
+
``` [lfs "customtransfer.multipart"]
|
|
14
|
+
path = /path/to/huggingface_hub/.env/bin/python args = -m debugpy --listen 5678
|
|
15
|
+
--wait-for-client
|
|
16
|
+
/path/to/huggingface_hub/src/huggingface_hub/commands/huggingface_cli.py
|
|
17
|
+
lfs-multipart-upload ```"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import subprocess
|
|
22
|
+
import sys
|
|
23
|
+
from argparse import _SubParsersAction
|
|
24
|
+
from typing import Dict, List, Optional
|
|
25
|
+
|
|
26
|
+
from huggingface_hub.commands import BaseHuggingfaceCLICommand
|
|
27
|
+
from huggingface_hub.lfs import LFS_MULTIPART_UPLOAD_COMMAND
|
|
28
|
+
|
|
29
|
+
from ..utils import get_session, hf_raise_for_status, logging
|
|
30
|
+
from ..utils._lfs import SliceFileObj
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
logger = logging.get_logger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class LfsCommands(BaseHuggingfaceCLICommand):
|
|
37
|
+
"""
|
|
38
|
+
Implementation of a custom transfer agent for the transfer type "multipart"
|
|
39
|
+
for git-lfs. This lets users upload large files >5GB 🔥. Spec for LFS custom
|
|
40
|
+
transfer agent is:
|
|
41
|
+
https://github.com/git-lfs/git-lfs/blob/master/docs/custom-transfers.md
|
|
42
|
+
|
|
43
|
+
This introduces two commands to the CLI:
|
|
44
|
+
|
|
45
|
+
1. $ hf lfs-enable-largefiles
|
|
46
|
+
|
|
47
|
+
This should be executed once for each model repo that contains a model file
|
|
48
|
+
>5GB. It's documented in the error message you get if you just try to git
|
|
49
|
+
push a 5GB file without having enabled it before.
|
|
50
|
+
|
|
51
|
+
2. $ hf lfs-multipart-upload
|
|
52
|
+
|
|
53
|
+
This command is called by lfs directly and is not meant to be called by the
|
|
54
|
+
user.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def register_subcommand(parser: _SubParsersAction):
|
|
59
|
+
enable_parser = parser.add_parser("lfs-enable-largefiles", add_help=False)
|
|
60
|
+
enable_parser.add_argument("path", type=str, help="Local path to repository you want to configure.")
|
|
61
|
+
enable_parser.set_defaults(func=lambda args: LfsEnableCommand(args))
|
|
62
|
+
|
|
63
|
+
# Command will get called by git-lfs, do not call it directly.
|
|
64
|
+
upload_parser = parser.add_parser(LFS_MULTIPART_UPLOAD_COMMAND, add_help=False)
|
|
65
|
+
upload_parser.set_defaults(func=lambda args: LfsUploadCommand(args))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class LfsEnableCommand:
|
|
69
|
+
def __init__(self, args):
|
|
70
|
+
self.args = args
|
|
71
|
+
|
|
72
|
+
def run(self):
|
|
73
|
+
local_path = os.path.abspath(self.args.path)
|
|
74
|
+
if not os.path.isdir(local_path):
|
|
75
|
+
print("This does not look like a valid git repo.")
|
|
76
|
+
exit(1)
|
|
77
|
+
subprocess.run(
|
|
78
|
+
"git config lfs.customtransfer.multipart.path hf".split(),
|
|
79
|
+
check=True,
|
|
80
|
+
cwd=local_path,
|
|
81
|
+
)
|
|
82
|
+
subprocess.run(
|
|
83
|
+
f"git config lfs.customtransfer.multipart.args {LFS_MULTIPART_UPLOAD_COMMAND}".split(),
|
|
84
|
+
check=True,
|
|
85
|
+
cwd=local_path,
|
|
86
|
+
)
|
|
87
|
+
print("Local repo set up for largefiles")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def write_msg(msg: Dict):
|
|
91
|
+
"""Write out the message in Line delimited JSON."""
|
|
92
|
+
msg_str = json.dumps(msg) + "\n"
|
|
93
|
+
sys.stdout.write(msg_str)
|
|
94
|
+
sys.stdout.flush()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def read_msg() -> Optional[Dict]:
|
|
98
|
+
"""Read Line delimited JSON from stdin."""
|
|
99
|
+
msg = json.loads(sys.stdin.readline().strip())
|
|
100
|
+
|
|
101
|
+
if "terminate" in (msg.get("type"), msg.get("event")):
|
|
102
|
+
# terminate message received
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
if msg.get("event") not in ("download", "upload"):
|
|
106
|
+
logger.critical("Received unexpected message")
|
|
107
|
+
sys.exit(1)
|
|
108
|
+
|
|
109
|
+
return msg
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class LfsUploadCommand:
|
|
113
|
+
def __init__(self, args) -> None:
|
|
114
|
+
self.args = args
|
|
115
|
+
|
|
116
|
+
def run(self) -> None:
|
|
117
|
+
# Immediately after invoking a custom transfer process, git-lfs
|
|
118
|
+
# sends initiation data to the process over stdin.
|
|
119
|
+
# This tells the process useful information about the configuration.
|
|
120
|
+
init_msg = json.loads(sys.stdin.readline().strip())
|
|
121
|
+
if not (init_msg.get("event") == "init" and init_msg.get("operation") == "upload"):
|
|
122
|
+
write_msg({"error": {"code": 32, "message": "Wrong lfs init operation"}})
|
|
123
|
+
sys.exit(1)
|
|
124
|
+
|
|
125
|
+
# The transfer process should use the information it needs from the
|
|
126
|
+
# initiation structure, and also perform any one-off setup tasks it
|
|
127
|
+
# needs to do. It should then respond on stdout with a simple empty
|
|
128
|
+
# confirmation structure, as follows:
|
|
129
|
+
write_msg({})
|
|
130
|
+
|
|
131
|
+
# After the initiation exchange, git-lfs will send any number of
|
|
132
|
+
# transfer requests to the stdin of the transfer process, in a serial sequence.
|
|
133
|
+
while True:
|
|
134
|
+
msg = read_msg()
|
|
135
|
+
if msg is None:
|
|
136
|
+
# When all transfers have been processed, git-lfs will send
|
|
137
|
+
# a terminate event to the stdin of the transfer process.
|
|
138
|
+
# On receiving this message the transfer process should
|
|
139
|
+
# clean up and terminate. No response is expected.
|
|
140
|
+
sys.exit(0)
|
|
141
|
+
|
|
142
|
+
oid = msg["oid"]
|
|
143
|
+
filepath = msg["path"]
|
|
144
|
+
completion_url = msg["action"]["href"]
|
|
145
|
+
header = msg["action"]["header"]
|
|
146
|
+
chunk_size = int(header.pop("chunk_size"))
|
|
147
|
+
presigned_urls: List[str] = list(header.values())
|
|
148
|
+
|
|
149
|
+
# Send a "started" progress event to allow other workers to start.
|
|
150
|
+
# Otherwise they're delayed until first "progress" event is reported,
|
|
151
|
+
# i.e. after the first 5GB by default (!)
|
|
152
|
+
write_msg(
|
|
153
|
+
{
|
|
154
|
+
"event": "progress",
|
|
155
|
+
"oid": oid,
|
|
156
|
+
"bytesSoFar": 1,
|
|
157
|
+
"bytesSinceLast": 0,
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
parts = []
|
|
162
|
+
with open(filepath, "rb") as file:
|
|
163
|
+
for i, presigned_url in enumerate(presigned_urls):
|
|
164
|
+
with SliceFileObj(
|
|
165
|
+
file,
|
|
166
|
+
seek_from=i * chunk_size,
|
|
167
|
+
read_limit=chunk_size,
|
|
168
|
+
) as data:
|
|
169
|
+
r = get_session().put(presigned_url, data=data)
|
|
170
|
+
hf_raise_for_status(r)
|
|
171
|
+
parts.append(
|
|
172
|
+
{
|
|
173
|
+
"etag": r.headers.get("etag"),
|
|
174
|
+
"partNumber": i + 1,
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
# In order to support progress reporting while data is uploading / downloading,
|
|
178
|
+
# the transfer process should post messages to stdout
|
|
179
|
+
write_msg(
|
|
180
|
+
{
|
|
181
|
+
"event": "progress",
|
|
182
|
+
"oid": oid,
|
|
183
|
+
"bytesSoFar": (i + 1) * chunk_size,
|
|
184
|
+
"bytesSinceLast": chunk_size,
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
# Not precise but that's ok.
|
|
188
|
+
|
|
189
|
+
r = get_session().post(
|
|
190
|
+
completion_url,
|
|
191
|
+
json={
|
|
192
|
+
"oid": oid,
|
|
193
|
+
"parts": parts,
|
|
194
|
+
},
|
|
195
|
+
)
|
|
196
|
+
hf_raise_for_status(r)
|
|
197
|
+
|
|
198
|
+
write_msg({"event": "complete", "oid": oid})
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Copyright 2025 The HuggingFace Team. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Contains commands to interact with repositories on the Hugging Face Hub.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
# create a new dataset repo on the Hub
|
|
18
|
+
hf repo create my-cool-dataset --repo-type=dataset
|
|
19
|
+
|
|
20
|
+
# create a private model repo on the Hub
|
|
21
|
+
hf repo create my-cool-model --private
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
from argparse import _SubParsersAction
|
|
26
|
+
from typing import Optional
|
|
27
|
+
|
|
28
|
+
from requests.exceptions import HTTPError
|
|
29
|
+
|
|
30
|
+
from huggingface_hub.commands import BaseHuggingfaceCLICommand
|
|
31
|
+
from huggingface_hub.commands._cli_utils import ANSI
|
|
32
|
+
from huggingface_hub.constants import REPO_TYPES, SPACES_SDK_TYPES
|
|
33
|
+
from huggingface_hub.errors import HfHubHTTPError, RepositoryNotFoundError, RevisionNotFoundError
|
|
34
|
+
from huggingface_hub.hf_api import HfApi
|
|
35
|
+
from huggingface_hub.utils import logging
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
logger = logging.get_logger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class RepoCommands(BaseHuggingfaceCLICommand):
|
|
42
|
+
@staticmethod
|
|
43
|
+
def register_subcommand(parser: _SubParsersAction):
|
|
44
|
+
repo_parser = parser.add_parser("repo", help="Manage repos on the Hub.")
|
|
45
|
+
repo_subparsers = repo_parser.add_subparsers(help="huggingface.co repos related commands")
|
|
46
|
+
# CREATE
|
|
47
|
+
repo_create_parser = repo_subparsers.add_parser("create", help="Create a new repo on huggingface.co")
|
|
48
|
+
repo_create_parser.add_argument(
|
|
49
|
+
"repo_id",
|
|
50
|
+
type=str,
|
|
51
|
+
help="The ID of the repo to create to (e.g. `username/repo-name`). The username is optional and will be set to your username if not provided.",
|
|
52
|
+
)
|
|
53
|
+
repo_create_parser.add_argument(
|
|
54
|
+
"--repo-type",
|
|
55
|
+
type=str,
|
|
56
|
+
help='Optional: set to "dataset" or "space" if creating a dataset or space, default is model.',
|
|
57
|
+
)
|
|
58
|
+
repo_create_parser.add_argument(
|
|
59
|
+
"--space_sdk",
|
|
60
|
+
type=str,
|
|
61
|
+
help='Optional: Hugging Face Spaces SDK type. Required when --type is set to "space".',
|
|
62
|
+
choices=SPACES_SDK_TYPES,
|
|
63
|
+
)
|
|
64
|
+
repo_create_parser.add_argument(
|
|
65
|
+
"--private",
|
|
66
|
+
action="store_true",
|
|
67
|
+
help="Whether to create a private repository. Defaults to public unless the organization's default is private.",
|
|
68
|
+
)
|
|
69
|
+
repo_create_parser.add_argument(
|
|
70
|
+
"--token",
|
|
71
|
+
type=str,
|
|
72
|
+
help="Hugging Face token. Will default to the locally saved token if not provided.",
|
|
73
|
+
)
|
|
74
|
+
repo_create_parser.add_argument(
|
|
75
|
+
"--exist-ok",
|
|
76
|
+
action="store_true",
|
|
77
|
+
help="Do not raise an error if repo already exists.",
|
|
78
|
+
)
|
|
79
|
+
repo_create_parser.add_argument(
|
|
80
|
+
"--resource-group-id",
|
|
81
|
+
type=str,
|
|
82
|
+
help="Resource group in which to create the repo. Resource groups is only available for Enterprise Hub organizations.",
|
|
83
|
+
)
|
|
84
|
+
repo_create_parser.set_defaults(func=lambda args: RepoCreateCommand(args))
|
|
85
|
+
|
|
86
|
+
# TAG SUBCOMMANDS
|
|
87
|
+
repo_tag_parser = repo_subparsers.add_parser("tag", help="Manage tags for a repo on the Hub.")
|
|
88
|
+
tag_subparsers = repo_tag_parser.add_subparsers(help="Tag actions", dest="tag_action", required=True)
|
|
89
|
+
|
|
90
|
+
# tag create
|
|
91
|
+
tag_create_parser = tag_subparsers.add_parser("create", help="Create a tag for a repo.")
|
|
92
|
+
tag_create_parser.add_argument(
|
|
93
|
+
"repo_id", type=str, help="The ID of the repo to tag (e.g. `username/repo-name`)."
|
|
94
|
+
)
|
|
95
|
+
tag_create_parser.add_argument("tag", type=str, help="The name of the tag to create.")
|
|
96
|
+
tag_create_parser.add_argument("-m", "--message", type=str, help="The description of the tag to create.")
|
|
97
|
+
tag_create_parser.add_argument("--revision", type=str, help="The git revision to tag.")
|
|
98
|
+
tag_create_parser.add_argument(
|
|
99
|
+
"--token", type=str, help="A User Access Token generated from https://huggingface.co/settings/tokens."
|
|
100
|
+
)
|
|
101
|
+
tag_create_parser.add_argument(
|
|
102
|
+
"--repo-type",
|
|
103
|
+
choices=["model", "dataset", "space"],
|
|
104
|
+
default="model",
|
|
105
|
+
help="Set the type of repository (model, dataset, or space).",
|
|
106
|
+
)
|
|
107
|
+
tag_create_parser.set_defaults(func=lambda args: RepoTagCreateCommand(args))
|
|
108
|
+
|
|
109
|
+
# tag list
|
|
110
|
+
tag_list_parser = tag_subparsers.add_parser("list", help="List tags for a repo.")
|
|
111
|
+
tag_list_parser.add_argument(
|
|
112
|
+
"repo_id", type=str, help="The ID of the repo to list tags for (e.g. `username/repo-name`)."
|
|
113
|
+
)
|
|
114
|
+
tag_list_parser.add_argument(
|
|
115
|
+
"--token", type=str, help="A User Access Token generated from https://huggingface.co/settings/tokens."
|
|
116
|
+
)
|
|
117
|
+
tag_list_parser.add_argument(
|
|
118
|
+
"--repo-type",
|
|
119
|
+
choices=["model", "dataset", "space"],
|
|
120
|
+
default="model",
|
|
121
|
+
help="Set the type of repository (model, dataset, or space).",
|
|
122
|
+
)
|
|
123
|
+
tag_list_parser.set_defaults(func=lambda args: RepoTagListCommand(args))
|
|
124
|
+
|
|
125
|
+
# tag delete
|
|
126
|
+
tag_delete_parser = tag_subparsers.add_parser("delete", help="Delete a tag from a repo.")
|
|
127
|
+
tag_delete_parser.add_argument(
|
|
128
|
+
"repo_id", type=str, help="The ID of the repo to delete the tag from (e.g. `username/repo-name`)."
|
|
129
|
+
)
|
|
130
|
+
tag_delete_parser.add_argument("tag", type=str, help="The name of the tag to delete.")
|
|
131
|
+
tag_delete_parser.add_argument("-y", "--yes", action="store_true", help="Answer Yes to prompts automatically.")
|
|
132
|
+
tag_delete_parser.add_argument(
|
|
133
|
+
"--token", type=str, help="A User Access Token generated from https://huggingface.co/settings/tokens."
|
|
134
|
+
)
|
|
135
|
+
tag_delete_parser.add_argument(
|
|
136
|
+
"--repo-type",
|
|
137
|
+
choices=["model", "dataset", "space"],
|
|
138
|
+
default="model",
|
|
139
|
+
help="Set the type of repository (model, dataset, or space).",
|
|
140
|
+
)
|
|
141
|
+
tag_delete_parser.set_defaults(func=lambda args: RepoTagDeleteCommand(args))
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class RepoCreateCommand:
|
|
145
|
+
def __init__(self, args: argparse.Namespace):
|
|
146
|
+
self.repo_id: str = args.repo_id
|
|
147
|
+
self.repo_type: Optional[str] = args.repo_type
|
|
148
|
+
self.space_sdk: Optional[str] = args.space_sdk
|
|
149
|
+
self.private: bool = args.private
|
|
150
|
+
self.token: Optional[str] = args.token
|
|
151
|
+
self.exist_ok: bool = args.exist_ok
|
|
152
|
+
self.resource_group_id: Optional[str] = args.resource_group_id
|
|
153
|
+
self._api = HfApi()
|
|
154
|
+
|
|
155
|
+
def run(self):
|
|
156
|
+
repo_url = self._api.create_repo(
|
|
157
|
+
repo_id=self.repo_id,
|
|
158
|
+
repo_type=self.repo_type,
|
|
159
|
+
private=self.private,
|
|
160
|
+
token=self.token,
|
|
161
|
+
exist_ok=self.exist_ok,
|
|
162
|
+
resource_group_id=self.resource_group_id,
|
|
163
|
+
space_sdk=self.space_sdk,
|
|
164
|
+
)
|
|
165
|
+
print(f"Successfully created {ANSI.bold(repo_url.repo_id)} on the Hub.")
|
|
166
|
+
print(f"Your repo is now available at {ANSI.bold(repo_url)}")
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class RepoTagCommand:
|
|
170
|
+
def __init__(self, args):
|
|
171
|
+
self.args = args
|
|
172
|
+
self.api = HfApi(token=getattr(args, "token", None))
|
|
173
|
+
self.repo_id = args.repo_id
|
|
174
|
+
self.repo_type = getattr(args, "repo_type", "model")
|
|
175
|
+
if self.repo_type not in REPO_TYPES:
|
|
176
|
+
print("Invalid repo --repo-type")
|
|
177
|
+
exit(1)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class RepoTagCreateCommand(RepoTagCommand):
|
|
181
|
+
def run(self):
|
|
182
|
+
print(f"You are about to create tag {ANSI.bold(self.args.tag)} on {self.repo_type} {ANSI.bold(self.repo_id)}")
|
|
183
|
+
try:
|
|
184
|
+
self.api.create_tag(
|
|
185
|
+
repo_id=self.repo_id,
|
|
186
|
+
tag=self.args.tag,
|
|
187
|
+
tag_message=getattr(self.args, "message", None),
|
|
188
|
+
revision=getattr(self.args, "revision", None),
|
|
189
|
+
repo_type=self.repo_type,
|
|
190
|
+
)
|
|
191
|
+
except RepositoryNotFoundError:
|
|
192
|
+
print(f"{self.repo_type.capitalize()} {ANSI.bold(self.repo_id)} not found.")
|
|
193
|
+
exit(1)
|
|
194
|
+
except RevisionNotFoundError:
|
|
195
|
+
print(f"Revision {ANSI.bold(getattr(self.args, 'revision', None))} not found.")
|
|
196
|
+
exit(1)
|
|
197
|
+
except HfHubHTTPError as e:
|
|
198
|
+
if e.response.status_code == 409:
|
|
199
|
+
print(f"Tag {ANSI.bold(self.args.tag)} already exists on {ANSI.bold(self.repo_id)}")
|
|
200
|
+
exit(1)
|
|
201
|
+
raise e
|
|
202
|
+
print(f"Tag {ANSI.bold(self.args.tag)} created on {ANSI.bold(self.repo_id)}")
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class RepoTagListCommand(RepoTagCommand):
|
|
206
|
+
def run(self):
|
|
207
|
+
try:
|
|
208
|
+
refs = self.api.list_repo_refs(
|
|
209
|
+
repo_id=self.repo_id,
|
|
210
|
+
repo_type=self.repo_type,
|
|
211
|
+
)
|
|
212
|
+
except RepositoryNotFoundError:
|
|
213
|
+
print(f"{self.repo_type.capitalize()} {ANSI.bold(self.repo_id)} not found.")
|
|
214
|
+
exit(1)
|
|
215
|
+
except HTTPError as e:
|
|
216
|
+
print(e)
|
|
217
|
+
print(ANSI.red(e.response.text))
|
|
218
|
+
exit(1)
|
|
219
|
+
if len(refs.tags) == 0:
|
|
220
|
+
print("No tags found")
|
|
221
|
+
exit(0)
|
|
222
|
+
print(f"Tags for {self.repo_type} {ANSI.bold(self.repo_id)}:")
|
|
223
|
+
for tag in refs.tags:
|
|
224
|
+
print(tag.name)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class RepoTagDeleteCommand(RepoTagCommand):
|
|
228
|
+
def run(self):
|
|
229
|
+
print(f"You are about to delete tag {ANSI.bold(self.args.tag)} on {self.repo_type} {ANSI.bold(self.repo_id)}")
|
|
230
|
+
if not getattr(self.args, "yes", False):
|
|
231
|
+
choice = input("Proceed? [Y/n] ").lower()
|
|
232
|
+
if choice not in ("", "y", "yes"):
|
|
233
|
+
print("Abort")
|
|
234
|
+
exit()
|
|
235
|
+
try:
|
|
236
|
+
self.api.delete_tag(repo_id=self.repo_id, tag=self.args.tag, repo_type=self.repo_type)
|
|
237
|
+
except RepositoryNotFoundError:
|
|
238
|
+
print(f"{self.repo_type.capitalize()} {ANSI.bold(self.repo_id)} not found.")
|
|
239
|
+
exit(1)
|
|
240
|
+
except RevisionNotFoundError:
|
|
241
|
+
print(f"Tag {ANSI.bold(self.args.tag)} not found on {ANSI.bold(self.repo_id)}")
|
|
242
|
+
exit(1)
|
|
243
|
+
print(f"Tag {ANSI.bold(self.args.tag)} deleted on {ANSI.bold(self.repo_id)}")
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
# Copyright 2023-present, the HuggingFace Inc. team.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Contains command to update or delete files in a repository using the CLI.
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
# delete all
|
|
19
|
+
hf repo-files delete <repo_id> "*"
|
|
20
|
+
|
|
21
|
+
# delete single file
|
|
22
|
+
hf repo-files delete <repo_id> file.txt
|
|
23
|
+
|
|
24
|
+
# delete single folder
|
|
25
|
+
hf repo-files delete <repo_id> folder/
|
|
26
|
+
|
|
27
|
+
# delete multiple
|
|
28
|
+
hf repo-files delete <repo_id> file.txt folder/ file2.txt
|
|
29
|
+
|
|
30
|
+
# delete multiple patterns
|
|
31
|
+
hf repo-files delete <repo_id> file.txt "*.json" "folder/*.parquet"
|
|
32
|
+
|
|
33
|
+
# delete from different revision / repo-type
|
|
34
|
+
hf repo-files delete <repo_id> file.txt --revision=refs/pr/1 --repo-type=dataset
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from argparse import _SubParsersAction
|
|
38
|
+
from typing import List, Optional
|
|
39
|
+
|
|
40
|
+
from huggingface_hub import logging
|
|
41
|
+
from huggingface_hub.commands import BaseHuggingfaceCLICommand
|
|
42
|
+
from huggingface_hub.hf_api import HfApi
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
logger = logging.get_logger(__name__)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class DeleteFilesSubCommand:
|
|
49
|
+
def __init__(self, args) -> None:
|
|
50
|
+
self.args = args
|
|
51
|
+
self.repo_id: str = args.repo_id
|
|
52
|
+
self.repo_type: Optional[str] = args.repo_type
|
|
53
|
+
self.revision: Optional[str] = args.revision
|
|
54
|
+
self.api: HfApi = HfApi(token=args.token, library_name="hf")
|
|
55
|
+
self.patterns: List[str] = args.patterns
|
|
56
|
+
self.commit_message: Optional[str] = args.commit_message
|
|
57
|
+
self.commit_description: Optional[str] = args.commit_description
|
|
58
|
+
self.create_pr: bool = args.create_pr
|
|
59
|
+
self.token: Optional[str] = args.token
|
|
60
|
+
|
|
61
|
+
def run(self) -> None:
|
|
62
|
+
logging.set_verbosity_info()
|
|
63
|
+
url = self.api.delete_files(
|
|
64
|
+
delete_patterns=self.patterns,
|
|
65
|
+
repo_id=self.repo_id,
|
|
66
|
+
repo_type=self.repo_type,
|
|
67
|
+
revision=self.revision,
|
|
68
|
+
commit_message=self.commit_message,
|
|
69
|
+
commit_description=self.commit_description,
|
|
70
|
+
create_pr=self.create_pr,
|
|
71
|
+
)
|
|
72
|
+
print(f"Files correctly deleted from repo. Commit: {url}.")
|
|
73
|
+
logging.set_verbosity_warning()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class RepoFilesCommand(BaseHuggingfaceCLICommand):
|
|
77
|
+
@staticmethod
|
|
78
|
+
def register_subcommand(parser: _SubParsersAction):
|
|
79
|
+
repo_files_parser = parser.add_parser("repo-files", help="Manage files in a repo on the Hub.")
|
|
80
|
+
repo_files_subparsers = repo_files_parser.add_subparsers(
|
|
81
|
+
help="Action to execute against the files.",
|
|
82
|
+
required=True,
|
|
83
|
+
)
|
|
84
|
+
delete_subparser = repo_files_subparsers.add_parser(
|
|
85
|
+
"delete",
|
|
86
|
+
help="Delete files from a repo on the Hub",
|
|
87
|
+
)
|
|
88
|
+
delete_subparser.set_defaults(func=lambda args: DeleteFilesSubCommand(args))
|
|
89
|
+
delete_subparser.add_argument(
|
|
90
|
+
"repo_id", type=str, help="The ID of the repo to manage (e.g. `username/repo-name`)."
|
|
91
|
+
)
|
|
92
|
+
delete_subparser.add_argument(
|
|
93
|
+
"patterns",
|
|
94
|
+
nargs="+",
|
|
95
|
+
type=str,
|
|
96
|
+
help="Glob patterns to match files to delete.",
|
|
97
|
+
)
|
|
98
|
+
delete_subparser.add_argument(
|
|
99
|
+
"--repo-type",
|
|
100
|
+
choices=["model", "dataset", "space"],
|
|
101
|
+
default="model",
|
|
102
|
+
help="Type of the repo to upload to (e.g. `dataset`).",
|
|
103
|
+
)
|
|
104
|
+
delete_subparser.add_argument(
|
|
105
|
+
"--revision",
|
|
106
|
+
type=str,
|
|
107
|
+
help=(
|
|
108
|
+
"An optional Git revision to push to. It can be a branch name "
|
|
109
|
+
"or a PR reference. If revision does not"
|
|
110
|
+
" exist and `--create-pr` is not set, a branch will be automatically created."
|
|
111
|
+
),
|
|
112
|
+
)
|
|
113
|
+
delete_subparser.add_argument(
|
|
114
|
+
"--commit-message", type=str, help="The summary / title / first line of the generated commit."
|
|
115
|
+
)
|
|
116
|
+
delete_subparser.add_argument(
|
|
117
|
+
"--commit-description", type=str, help="The description of the generated commit."
|
|
118
|
+
)
|
|
119
|
+
delete_subparser.add_argument(
|
|
120
|
+
"--create-pr", action="store_true", help="Whether to create a new Pull Request for these changes."
|
|
121
|
+
)
|
|
122
|
+
delete_subparser.add_argument(
|
|
123
|
+
"--token",
|
|
124
|
+
type=str,
|
|
125
|
+
help="A User Access Token generated from https://huggingface.co/settings/tokens",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
repo_files_parser.set_defaults(func=RepoFilesCommand)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copyright 2022 The HuggingFace Team. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Contains commands to print information about the environment and version.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
hf env
|
|
18
|
+
hf version
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from argparse import _SubParsersAction
|
|
22
|
+
|
|
23
|
+
from huggingface_hub import __version__
|
|
24
|
+
|
|
25
|
+
from ..utils import dump_environment_info
|
|
26
|
+
from . import BaseHuggingfaceCLICommand
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class EnvironmentCommand(BaseHuggingfaceCLICommand):
|
|
30
|
+
def __init__(self, args):
|
|
31
|
+
self.args = args
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def register_subcommand(parser: _SubParsersAction):
|
|
35
|
+
env_parser = parser.add_parser("env", help="Print information about the environment.")
|
|
36
|
+
env_parser.set_defaults(func=EnvironmentCommand)
|
|
37
|
+
|
|
38
|
+
def run(self) -> None:
|
|
39
|
+
dump_environment_info()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class VersionCommand(BaseHuggingfaceCLICommand):
|
|
43
|
+
def __init__(self, args):
|
|
44
|
+
self.args = args
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def register_subcommand(parser: _SubParsersAction):
|
|
48
|
+
version_parser = parser.add_parser("version", help="Print information about the hf version.")
|
|
49
|
+
version_parser.set_defaults(func=VersionCommand)
|
|
50
|
+
|
|
51
|
+
def run(self) -> None:
|
|
52
|
+
print(f"huggingface_hub version: {__version__}")
|