Spaces:
Sleeping
Sleeping
Upload 6 files
Browse files- .gitignore +4 -0
- README.md +6 -6
- app.py +232 -0
- git_commd.py +238 -0
- logger.py +89 -0
- requirements.txt +3 -0
.gitignore
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.git/
|
2 |
+
.venv/
|
3 |
+
vent/
|
4 |
+
_pycache_/
|
README.md
CHANGED
@@ -1,13 +1,13 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
-
sdk_version: 4.
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
-
license:
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
---
|
2 |
+
title: Wisemodel To Hf
|
3 |
+
emoji: 😻
|
4 |
+
colorFrom: yellow
|
5 |
+
colorTo: green
|
6 |
sdk: gradio
|
7 |
+
sdk_version: 4.22.0
|
8 |
app_file: app.py
|
9 |
pinned: false
|
10 |
+
license: apache-2.0
|
11 |
---
|
12 |
|
13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
ADDED
@@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import os
|
3 |
+
from git_commd import GitCommandWrapper
|
4 |
+
from typing import List, Optional
|
5 |
+
import logging
|
6 |
+
|
7 |
+
HF_TOKEN = os.environ["HF_TOKEN"] if "HF_TOKEN" in os.environ else ""
|
8 |
+
WiseModel_TOKEN = os.environ["WM_TOKEN"] if "WM_TOKEN" in os.environ else ""
|
9 |
+
|
10 |
+
|
11 |
+
def get_cache_dir():
|
12 |
+
from random_word import RandomWords
|
13 |
+
|
14 |
+
r = RandomWords()
|
15 |
+
return r.get_random_word()
|
16 |
+
|
17 |
+
|
18 |
+
def check_disk():
|
19 |
+
import os
|
20 |
+
|
21 |
+
return os.system("df -h /")
|
22 |
+
|
23 |
+
|
24 |
+
def pull_from_wisemodel(
|
25 |
+
token: str, url: str, repo_name: str, cache_dir, branch: Optional[str] = None
|
26 |
+
):
|
27 |
+
|
28 |
+
print("pull_from_wisemodel start")
|
29 |
+
print(cache_dir)
|
30 |
+
os.makedirs(cache_dir, exist_ok=True)
|
31 |
+
# os.system("cd "+cache_dir)
|
32 |
+
gitCmd = GitCommandWrapper()
|
33 |
+
isLfs = gitCmd.is_lfs_installed()
|
34 |
+
if not isLfs:
|
35 |
+
gitCmd.git_lfs_install()
|
36 |
+
gitCmd.clone(cache_dir, token, url, repo_name, branch)
|
37 |
+
print("pull_from_wisemodel end")
|
38 |
+
return f"Pulled {branch} to temp folder {cache_dir}: {url}"
|
39 |
+
|
40 |
+
|
41 |
+
def push_to_wiseModel(
|
42 |
+
token: str,
|
43 |
+
url: str,
|
44 |
+
repo_name: str,
|
45 |
+
cache_dir: str,
|
46 |
+
hf_repo_id: str,
|
47 |
+
branch: Optional[str] = None,
|
48 |
+
):
|
49 |
+
|
50 |
+
print("push_to_wiseModel start")
|
51 |
+
|
52 |
+
gitCmd = GitCommandWrapper()
|
53 |
+
gitCmd.clone(cache_dir, token, url, repo_name, branch)
|
54 |
+
|
55 |
+
repo_dir = f"./{cache_dir}/{repo_name}"
|
56 |
+
os.makedirs(repo_dir, exist_ok=True)
|
57 |
+
source_dir = f"./{cache_dir}/hf/{hf_repo_id}"
|
58 |
+
move_file(source_dir, repo_dir, excludes=[".git", ".gitattributes"])
|
59 |
+
gitCmd.add(repo_dir, all_files=True)
|
60 |
+
gitCmd.commit(repo_dir, message="commit from hf to wisemodel")
|
61 |
+
gitCmd.push(repo_dir, token, url, branch, branch)
|
62 |
+
print("push_to_wiseModel end")
|
63 |
+
return f"Pushed {branch} to {url}"
|
64 |
+
|
65 |
+
|
66 |
+
def move_file(source: str, destination: str, excludes: list[str] = []):
|
67 |
+
import shutil
|
68 |
+
|
69 |
+
try:
|
70 |
+
# move all files in the source directory to the destination directory
|
71 |
+
# list all files in the source directory
|
72 |
+
files = os.listdir(source)
|
73 |
+
for file in files:
|
74 |
+
if file in excludes:
|
75 |
+
continue
|
76 |
+
logging.info(f"Moving {file} to {destination}")
|
77 |
+
# move each file to destination Directory
|
78 |
+
shutil.move(f"{source}/{file}", destination)
|
79 |
+
except Exception as e:
|
80 |
+
logging.exception(e)
|
81 |
+
return f"Error moving files from {source} to {destination}, {e.args[0]}"
|
82 |
+
return "file moved"
|
83 |
+
|
84 |
+
|
85 |
+
def remove_file(cache_dir, repo_name):
|
86 |
+
import os
|
87 |
+
|
88 |
+
try:
|
89 |
+
os.remove(f"{cache_dir}/{repo_name}")
|
90 |
+
except:
|
91 |
+
return ""
|
92 |
+
return "README.md file removed"
|
93 |
+
|
94 |
+
|
95 |
+
def push_to_hf(cache_dir, WiseModel_repo_name, hf_repo_id):
|
96 |
+
from huggingface_hub import HfApi
|
97 |
+
|
98 |
+
if not HF_TOKEN:
|
99 |
+
raise gr.Error("Please enter your HF_TOKEN")
|
100 |
+
print("push_to_hf start")
|
101 |
+
api = HfApi(token=HF_TOKEN) # Token is not persisted on the machine.
|
102 |
+
output = api.upload_folder(
|
103 |
+
folder_path=f"{cache_dir}/{WiseModel_repo_name}",
|
104 |
+
repo_id=hf_repo_id,
|
105 |
+
repo_type="model",
|
106 |
+
)
|
107 |
+
print("push_to_hf end")
|
108 |
+
return f"Pushed to {hf_repo_id}"
|
109 |
+
|
110 |
+
|
111 |
+
def pull_from_hf(cache_dir, hf_repo_id):
|
112 |
+
from huggingface_hub import HfApi
|
113 |
+
|
114 |
+
if not HF_TOKEN:
|
115 |
+
raise gr.Error("Please enter your HF_TOKEN")
|
116 |
+
print("pull_from_hf start")
|
117 |
+
api = HfApi(token=HF_TOKEN) # Token is not persisted on the machine.
|
118 |
+
output = api.snapshot_download(
|
119 |
+
repo_id=hf_repo_id, repo_type="model", local_dir=cache_dir + "/hf/" + hf_repo_id
|
120 |
+
)
|
121 |
+
print(f"pull_from_hf end, output: {output}")
|
122 |
+
return f"Pulled from {hf_repo_id}"
|
123 |
+
|
124 |
+
|
125 |
+
def handle(wisemodel_link, hf_repo_id):
|
126 |
+
cache_dir = get_cache_dir()
|
127 |
+
wiseModel_repo_url = (
|
128 |
+
wisemodel_link.replace(".git", "")
|
129 |
+
.replace("git", "")
|
130 |
+
.replace("clone", "")
|
131 |
+
.replace(" ", "")
|
132 |
+
)
|
133 |
+
wiseModel_repo_info = (
|
134 |
+
wisemodel_link.replace(".git", "")
|
135 |
+
.replace("git", "")
|
136 |
+
.replace("clone", "")
|
137 |
+
.replace(" ", "")
|
138 |
+
.split("/")
|
139 |
+
)
|
140 |
+
print(wiseModel_repo_info)
|
141 |
+
wisemodel_repo_name = wiseModel_repo_info[-1]
|
142 |
+
stages = [
|
143 |
+
(check_disk, (), {}),
|
144 |
+
# # Run all the sanity checks on README.md
|
145 |
+
# (pull_from_wisemodel, (WiseModel_TOKEN,wiseModel_repo_url,wisemodel_repo_name, cache_dir,"main"), {}),
|
146 |
+
# (remove_file, (wisemodel_repo_name, cache_dir), {}),
|
147 |
+
# (check_disk, (), {}),
|
148 |
+
# (push_to_hf, (cache_dir, wisemodel_repo_name, hf_repo_id), {}),
|
149 |
+
# (check_disk, (), {}),
|
150 |
+
(pull_from_hf, (cache_dir, hf_repo_id), {}),
|
151 |
+
(remove_file, (hf_repo_id, cache_dir), {}),
|
152 |
+
(check_disk, (), {}),
|
153 |
+
(
|
154 |
+
push_to_wiseModel,
|
155 |
+
(
|
156 |
+
WiseModel_TOKEN,
|
157 |
+
wiseModel_repo_url,
|
158 |
+
wisemodel_repo_name,
|
159 |
+
cache_dir,
|
160 |
+
hf_repo_id,
|
161 |
+
"main",
|
162 |
+
),
|
163 |
+
{},
|
164 |
+
),
|
165 |
+
(check_disk, (), {}),
|
166 |
+
]
|
167 |
+
|
168 |
+
results = []
|
169 |
+
errors = []
|
170 |
+
for func, args, kwargs in stages:
|
171 |
+
try:
|
172 |
+
results.append(str(func(*args, **kwargs)))
|
173 |
+
except Exception as e:
|
174 |
+
logging.exception(e)
|
175 |
+
errors.append(str(e))
|
176 |
+
if errors:
|
177 |
+
break
|
178 |
+
|
179 |
+
return "\n\n".join(results), "\n\n".join(errors)
|
180 |
+
|
181 |
+
|
182 |
+
with gr.Blocks() as demo:
|
183 |
+
gr.Markdown(
|
184 |
+
"""
|
185 |
+
|
186 |
+
|
187 |
+
# HF-to-wisemodel/从Huggingface上拉取模型、数据集等到wisemodel
|
188 |
+
|
189 |
+
# 这是一个示例Space,实际使用请参考下面说明,先Duplicate一个私有的space
|
190 |
+
|
191 |
+
- 这个space可以把已经发布在Huggingface上的模型拉取到wisemodel上。
|
192 |
+
- This space uploads model from Huggingface to wisemodel.
|
193 |
+
|
194 |
+
- **请确认您是repo的拥有者或者有权限操作!**
|
195 |
+
- **Please make sure that you're the owner of the repo or have permission from the owner to do so!**
|
196 |
+
|
197 |
+
|
198 |
+
# 如何使用这个空间?
|
199 |
+
# How to use this Space?
|
200 |
+
|
201 |
+
- 点击右上角settings后面的“…”按钮,选择“Duplicate this Space”创建一个私有的space,同时输入wisemodel的token(必填),以及Huggingface的token(必填),确保有相应repo写入的权限。
|
202 |
+
- Duplicate this Space and providing WiseModel token (mandatory) and your read/write HF token (mandatory).
|
203 |
+
|
204 |
+
- 在wiseModel上创建一个空的repo,这一步需要手动完成,Space不会为您创建一个空的repo。
|
205 |
+
- Create your target model repo on WiseModel. This step is not automated.
|
206 |
+
|
207 |
+
- 在刚刚自己创建的私有space里填写相应的信息,wisemodel的git clone链接,以及Huggingface的repo名称。
|
208 |
+
- In your own private Space, fill in information below.
|
209 |
+
|
210 |
+
- 点击submit按钮,然后可以通过logs按钮查看进度。
|
211 |
+
- Click submit then watch for output in container log for progress.
|
212 |
+
|
213 |
+
- Create README.md file (since the metadata is not compatible with HF)
|
214 |
+
"""
|
215 |
+
)
|
216 |
+
|
217 |
+
wisemodel_link = gr.Textbox(
|
218 |
+
label="Copy the git download link from the model detail page of wisemodel(从wisemodel上获取该模型的完整git clone链接) "
|
219 |
+
)
|
220 |
+
hf_repo_id = gr.Textbox(
|
221 |
+
label="Source HF Model Repo ID (case sensitive). \nPlease make sure that this model has already been created"
|
222 |
+
)
|
223 |
+
with gr.Row():
|
224 |
+
button = gr.Button("Submit", variant="primary")
|
225 |
+
clear = gr.Button("Clear")
|
226 |
+
error = gr.Textbox(label="Error")
|
227 |
+
output = gr.Textbox(label="Output")
|
228 |
+
|
229 |
+
button.click(handle, [wisemodel_link, hf_repo_id], [output, error])
|
230 |
+
|
231 |
+
if __name__ == "__main__":
|
232 |
+
demo.launch(debug=True)
|
git_commd.py
ADDED
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import subprocess
|
3 |
+
from typing import List, Optional
|
4 |
+
|
5 |
+
from logger import get_logger
|
6 |
+
logger = get_logger()
|
7 |
+
class Singleton(type):
|
8 |
+
_instances = {}
|
9 |
+
|
10 |
+
def __call__(cls, *args, **kwargs):
|
11 |
+
if cls not in cls._instances:
|
12 |
+
cls._instances[cls] = super(Singleton,
|
13 |
+
cls).__call__(*args, **kwargs)
|
14 |
+
return cls._instances[cls]
|
15 |
+
|
16 |
+
class GitError(Exception):
|
17 |
+
pass
|
18 |
+
class GitCommandWrapper(metaclass=Singleton):
|
19 |
+
"""Some git operation wrapper
|
20 |
+
"""
|
21 |
+
default_git_path = 'git' # The default git command line
|
22 |
+
git_path='git'
|
23 |
+
MODEL_BRANCH="main"
|
24 |
+
def __init__(self, path: str = None):
|
25 |
+
self.git_path = path or self.default_git_path
|
26 |
+
|
27 |
+
def _run_git_command(self, *args) -> subprocess.CompletedProcess:
|
28 |
+
"""Run git command, if command return 0, return subprocess.response
|
29 |
+
otherwise raise GitError, message is stdout and stderr.
|
30 |
+
|
31 |
+
Args:
|
32 |
+
args: List of command args.
|
33 |
+
|
34 |
+
Raises:
|
35 |
+
GitError: Exception with stdout and stderr.
|
36 |
+
|
37 |
+
Returns:
|
38 |
+
subprocess.CompletedProcess: the command response
|
39 |
+
"""
|
40 |
+
logger.debug(' '.join(args))
|
41 |
+
git_env = os.environ.copy()
|
42 |
+
git_env['GIT_TERMINAL_PROMPT'] = '0'
|
43 |
+
response = subprocess.run(
|
44 |
+
[self.git_path, *args],
|
45 |
+
stdout=subprocess.PIPE,
|
46 |
+
stderr=subprocess.PIPE,
|
47 |
+
env=git_env,
|
48 |
+
) # compatible for python3.6
|
49 |
+
try:
|
50 |
+
response.check_returncode()
|
51 |
+
return response
|
52 |
+
except subprocess.CalledProcessError as error:
|
53 |
+
logger.error('There are error run git command.')
|
54 |
+
raise GitError(
|
55 |
+
'stdout: %s, stderr: %s' %
|
56 |
+
(response.stdout.decode('utf8'), error.stderr.decode('utf8')))
|
57 |
+
|
58 |
+
def config_auth_token(self, repo_dir, auth_token):
|
59 |
+
url = self.get_repo_remote_url(repo_dir)
|
60 |
+
if '//oauth2' not in url:
|
61 |
+
auth_url = self._add_token(auth_token, url)
|
62 |
+
cmd_args = '-C %s remote set-url origin %s' % (repo_dir, auth_url)
|
63 |
+
cmd_args = cmd_args.split(' ')
|
64 |
+
rsp = self._run_git_command(*cmd_args)
|
65 |
+
logger.debug(rsp.stdout.decode('utf8'))
|
66 |
+
|
67 |
+
def _add_token(self, token: str, url: str):
|
68 |
+
if token:
|
69 |
+
if '//oauth2' not in url:
|
70 |
+
url = url.replace('//', '//oauth2:%s@' % token)
|
71 |
+
return url
|
72 |
+
|
73 |
+
def remove_token_from_url(self, url: str):
|
74 |
+
if url and '//oauth2' in url:
|
75 |
+
start_index = url.find('oauth2')
|
76 |
+
end_index = url.find('@')
|
77 |
+
url = url[:start_index] + url[end_index + 1:]
|
78 |
+
return url
|
79 |
+
|
80 |
+
def is_lfs_installed(self):
|
81 |
+
cmd = ['lfs', 'env']
|
82 |
+
try:
|
83 |
+
self._run_git_command(*cmd)
|
84 |
+
return True
|
85 |
+
except GitError:
|
86 |
+
return False
|
87 |
+
|
88 |
+
def git_lfs_install(self, repo_dir):
|
89 |
+
cmd = ['-C', repo_dir, 'lfs', 'install']
|
90 |
+
try:
|
91 |
+
self._run_git_command(*cmd)
|
92 |
+
return True
|
93 |
+
except GitError:
|
94 |
+
return False
|
95 |
+
|
96 |
+
def clone(self,
|
97 |
+
repo_base_dir: str,
|
98 |
+
token: str,
|
99 |
+
url: str,
|
100 |
+
repo_name: str,
|
101 |
+
branch: Optional[str] = None):
|
102 |
+
""" git clone command wrapper.
|
103 |
+
For public project, token can None, private repo, there must token.
|
104 |
+
|
105 |
+
Args:
|
106 |
+
repo_base_dir (str): The local base dir, the repository will be clone to local_dir/repo_name
|
107 |
+
token (str): The git token, must be provided for private project.
|
108 |
+
url (str): The remote url
|
109 |
+
repo_name (str): The local repository path name.
|
110 |
+
branch (str, optional): _description_. Defaults to None.
|
111 |
+
|
112 |
+
Returns:
|
113 |
+
The popen response.
|
114 |
+
"""
|
115 |
+
url = self._add_token(token, url)
|
116 |
+
if branch:
|
117 |
+
clone_args = '-C %s clone %s %s --branch %s' % (repo_base_dir, url,
|
118 |
+
repo_name, branch)
|
119 |
+
else:
|
120 |
+
clone_args = '-C %s clone %s' % (repo_base_dir, url)
|
121 |
+
logger.debug(clone_args)
|
122 |
+
clone_args = clone_args.split(' ')
|
123 |
+
response = self._run_git_command(*clone_args)
|
124 |
+
logger.debug(response.stdout.decode('utf8'))
|
125 |
+
return response
|
126 |
+
|
127 |
+
|
128 |
+
|
129 |
+
def add(self,
|
130 |
+
repo_dir: str,
|
131 |
+
files: List[str] = list(),
|
132 |
+
all_files: bool = False):
|
133 |
+
if all_files:
|
134 |
+
add_args = '-C %s add -A' % repo_dir
|
135 |
+
elif len(files) > 0:
|
136 |
+
files_str = ' '.join(files)
|
137 |
+
add_args = '-C %s add %s' % (repo_dir, files_str)
|
138 |
+
add_args = add_args.split(' ')
|
139 |
+
rsp = self._run_git_command(*add_args)
|
140 |
+
logger.debug(rsp.stdout.decode('utf8'))
|
141 |
+
return rsp
|
142 |
+
|
143 |
+
def commit(self, repo_dir: str, message: str):
|
144 |
+
"""Run git commit command
|
145 |
+
|
146 |
+
Args:
|
147 |
+
repo_dir (str): the repository directory.
|
148 |
+
message (str): commit message.
|
149 |
+
|
150 |
+
Returns:
|
151 |
+
The command popen response.
|
152 |
+
"""
|
153 |
+
commit_args = ['-C', '%s' % repo_dir, 'commit', '-m', "'%s'" % message]
|
154 |
+
rsp = self._run_git_command(*commit_args)
|
155 |
+
logger.info(rsp.stdout.decode('utf8'))
|
156 |
+
return rsp
|
157 |
+
|
158 |
+
def checkout(self, repo_dir: str, revision: str):
|
159 |
+
cmds = ['-C', '%s' % repo_dir, 'checkout', '%s' % revision]
|
160 |
+
return self._run_git_command(*cmds)
|
161 |
+
|
162 |
+
def new_branch(self, repo_dir: str, revision: str):
|
163 |
+
cmds = ['-C', '%s' % repo_dir, 'checkout', '-b', revision]
|
164 |
+
return self._run_git_command(*cmds)
|
165 |
+
|
166 |
+
def get_remote_branches(self, repo_dir: str):
|
167 |
+
cmds = ['-C', '%s' % repo_dir, 'branch', '-r']
|
168 |
+
rsp = self._run_git_command(*cmds)
|
169 |
+
info = [
|
170 |
+
line.strip()
|
171 |
+
for line in rsp.stdout.decode('utf8').strip().split(os.linesep)
|
172 |
+
]
|
173 |
+
if len(info) == 1:
|
174 |
+
return ['/'.join(info[0].split('/')[1:])]
|
175 |
+
else:
|
176 |
+
return ['/'.join(line.split('/')[1:]) for line in info[1:]]
|
177 |
+
|
178 |
+
def pull(self,
|
179 |
+
repo_dir: str,
|
180 |
+
remote: str = 'origin',
|
181 |
+
branch: str = 'main'):
|
182 |
+
cmds = ['-C', repo_dir, 'pull', remote, branch]
|
183 |
+
return self._run_git_command(*cmds)
|
184 |
+
|
185 |
+
def push(self,
|
186 |
+
repo_dir: str,
|
187 |
+
token: str,
|
188 |
+
url: str,
|
189 |
+
local_branch: str,
|
190 |
+
remote_branch: str,
|
191 |
+
force: bool = False):
|
192 |
+
url = self._add_token(token, url)
|
193 |
+
|
194 |
+
push_args = '-C %s push %s %s:%s' % (repo_dir, url, local_branch,
|
195 |
+
remote_branch)
|
196 |
+
if force:
|
197 |
+
push_args += ' -f'
|
198 |
+
push_args = push_args.split(' ')
|
199 |
+
rsp = self._run_git_command(*push_args)
|
200 |
+
logger.debug(rsp.stdout.decode('utf8'))
|
201 |
+
return rsp
|
202 |
+
|
203 |
+
def get_repo_remote_url(self, repo_dir: str):
|
204 |
+
cmd_args = '-C %s config --get remote.origin.url' % repo_dir
|
205 |
+
cmd_args = cmd_args.split(' ')
|
206 |
+
rsp = self._run_git_command(*cmd_args)
|
207 |
+
url = rsp.stdout.decode('utf8')
|
208 |
+
return url.strip()
|
209 |
+
|
210 |
+
def list_lfs_files(self, repo_dir: str):
|
211 |
+
cmd_args = '-C %s lfs ls-files' % repo_dir
|
212 |
+
cmd_args = cmd_args.split(' ')
|
213 |
+
rsp = self._run_git_command(*cmd_args)
|
214 |
+
out = rsp.stdout.decode('utf8').strip()
|
215 |
+
files = []
|
216 |
+
for line in out.split(os.linesep):
|
217 |
+
files.append(line.split(' ')[-1])
|
218 |
+
|
219 |
+
return files
|
220 |
+
|
221 |
+
def tag(self,
|
222 |
+
repo_dir: str,
|
223 |
+
tag_name: str,
|
224 |
+
message: str,
|
225 |
+
ref: str = MODEL_BRANCH):
|
226 |
+
cmd_args = [
|
227 |
+
'-C', repo_dir, 'tag', tag_name, '-m',
|
228 |
+
'"%s"' % message, ref
|
229 |
+
]
|
230 |
+
rsp = self._run_git_command(*cmd_args)
|
231 |
+
logger.debug(rsp.stdout.decode('utf8'))
|
232 |
+
return rsp
|
233 |
+
|
234 |
+
def push_tag(self, repo_dir: str, tag_name):
|
235 |
+
cmd_args = ['-C', repo_dir, 'push', 'origin', tag_name]
|
236 |
+
rsp = self._run_git_command(*cmd_args)
|
237 |
+
logger.debug(rsp.stdout.decode('utf8'))
|
238 |
+
return rsp
|
logger.py
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (c) Alibaba, Inc. and its affiliates.
|
2 |
+
|
3 |
+
import importlib
|
4 |
+
import logging
|
5 |
+
from typing import Optional
|
6 |
+
|
7 |
+
init_loggers = {}
|
8 |
+
|
9 |
+
formatter = logging.Formatter(
|
10 |
+
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
11 |
+
|
12 |
+
|
13 |
+
def get_logger(log_file: Optional[str] = None,
|
14 |
+
log_level: int = logging.INFO,
|
15 |
+
file_mode: str = 'w'):
|
16 |
+
""" Get logging logger
|
17 |
+
|
18 |
+
Args:
|
19 |
+
log_file: Log filename, if specified, file handler will be added to
|
20 |
+
logger
|
21 |
+
log_level: Logging level.
|
22 |
+
file_mode: Specifies the mode to open the file, if filename is
|
23 |
+
specified (if filemode is unspecified, it defaults to 'w').
|
24 |
+
"""
|
25 |
+
|
26 |
+
logger_name = __name__.split('.')[0]
|
27 |
+
logger = logging.getLogger(logger_name)
|
28 |
+
logger.propagate = False
|
29 |
+
if logger_name in init_loggers:
|
30 |
+
add_file_handler_if_needed(logger, log_file, file_mode, log_level)
|
31 |
+
return logger
|
32 |
+
|
33 |
+
# handle duplicate logs to the console
|
34 |
+
# Starting in 1.8.0, PyTorch DDP attaches a StreamHandler <stderr> (NOTSET)
|
35 |
+
# to the root logger. As logger.propagate is True by default, this root
|
36 |
+
# level handler causes logging messages from rank>0 processes to
|
37 |
+
# unexpectedly show up on the console, creating much unwanted clutter.
|
38 |
+
# To fix this issue, we set the root logger's StreamHandler, if any, to log
|
39 |
+
# at the ERROR level.
|
40 |
+
torch_dist = False
|
41 |
+
is_worker0 = True
|
42 |
+
if importlib.util.find_spec('torch') is not None:
|
43 |
+
from modelscope.utils.torch_utils import is_dist, is_master
|
44 |
+
torch_dist = is_dist()
|
45 |
+
is_worker0 = is_master()
|
46 |
+
|
47 |
+
if torch_dist:
|
48 |
+
for handler in logger.root.handlers:
|
49 |
+
if type(handler) is logging.StreamHandler:
|
50 |
+
handler.setLevel(logging.ERROR)
|
51 |
+
|
52 |
+
stream_handler = logging.StreamHandler()
|
53 |
+
handlers = [stream_handler]
|
54 |
+
|
55 |
+
if is_worker0 and log_file is not None:
|
56 |
+
file_handler = logging.FileHandler(log_file, file_mode)
|
57 |
+
handlers.append(file_handler)
|
58 |
+
|
59 |
+
for handler in handlers:
|
60 |
+
handler.setFormatter(formatter)
|
61 |
+
handler.setLevel(log_level)
|
62 |
+
logger.addHandler(handler)
|
63 |
+
|
64 |
+
if is_worker0:
|
65 |
+
logger.setLevel(log_level)
|
66 |
+
else:
|
67 |
+
logger.setLevel(logging.ERROR)
|
68 |
+
|
69 |
+
init_loggers[logger_name] = True
|
70 |
+
|
71 |
+
return logger
|
72 |
+
|
73 |
+
|
74 |
+
def add_file_handler_if_needed(logger, log_file, file_mode, log_level):
|
75 |
+
for handler in logger.handlers:
|
76 |
+
if isinstance(handler, logging.FileHandler):
|
77 |
+
return
|
78 |
+
|
79 |
+
if importlib.util.find_spec('torch') is not None:
|
80 |
+
from modelscope.utils.torch_utils import is_master
|
81 |
+
is_worker0 = is_master()
|
82 |
+
else:
|
83 |
+
is_worker0 = True
|
84 |
+
|
85 |
+
if is_worker0 and log_file is not None:
|
86 |
+
file_handler = logging.FileHandler(log_file, file_mode)
|
87 |
+
file_handler.setFormatter(formatter)
|
88 |
+
file_handler.setLevel(log_level)
|
89 |
+
logger.addHandler(file_handler)
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
gradio[auth]
|
2 |
+
huggingface_hub
|
3 |
+
random-word
|