testdeep123 commited on
Commit
b13b85a
·
verified ·
1 Parent(s): 86296cd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -72
app.py CHANGED
@@ -1,17 +1,14 @@
1
  import os
2
  import tempfile
3
  from flask import Flask, render_template_string, request, redirect, send_file, jsonify
4
- from huggingface_hub import HfApi, HfFileSystem, login, upload_file, delete_file
5
 
6
- # Environment variables
7
  REPO_ID = os.getenv("REPO_ID")
8
  HF_TOKEN = os.getenv("HF_TOKEN")
9
 
10
- # Initialize
11
  app = Flask(__name__)
12
  api = HfApi()
13
- fs = HfFileSystem(token=HF_TOKEN)
14
- login(token=HF_TOKEN)
15
 
16
  TEMPLATE = """
17
  <!DOCTYPE html>
@@ -20,77 +17,69 @@ TEMPLATE = """
20
  <meta charset="UTF-8">
21
  <title>HuggingFace Drive - {{ path or 'Root' }}</title>
22
  <style>
23
- body { background:#121212; color:#e0e0e0; font-family:Arial,sans-serif; padding:20px; }
24
- h2 { margin-top:0; }
25
- .folder, .file { padding:6px 12px; margin:6px 0; background:#1e1e1e; border-radius:4px; cursor:pointer; }
26
- .folder:hover, .file:hover { background:#2a2a2a; }
27
- .actions { margin-bottom:16px; }
28
- button { background:#333; color:#fff; border:none; padding:6px 10px; margin-right:6px; border-radius:4px; cursor:pointer; }
29
- button:hover { background:#444; }
30
- input[type="file"], input[type="text"] { background:#1e1e1e; color:#fff; border:1px solid #333; padding:6px; margin-right:6px; }
31
- a { color:#8ab4f8; text-decoration:none; }
32
  </style>
33
  <script>
34
- function navigate(p){ location.href = '/?path='+encodeURIComponent(p); }
35
- async function deleteItem(p){ if(!confirm('Delete '+p+'?'))return; await fetch('/delete',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p})}); location.reload(); }
36
- async function createFolder(cp){ let name=prompt('Folder name:'); if(!name)return; await fetch('/create_folder',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({path:cp+'/'+name})}); location.reload(); }
37
- async function renameItem(old){ let neu=prompt('Rename to:',old); if(!neu||neu===old)return; await fetch('/rename',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({old_path:old,new_path:neu})}); location.reload(); }
38
  </script>
39
  </head>
40
  <body>
41
- <h2>📁 HuggingFace Drive — {{ path or 'Root' }}</h2>
42
  {% if parent %}
43
- <div><a href="#" onclick="navigate('{{ parent }}')">⬅️ Back to {{ parent or 'Root' }}</a></div>
44
  {% endif %}
45
  <div class="actions">
46
- <form style="display:inline" method="POST" action="/upload" enctype="multipart/form-data">
47
  <input type="file" name="file" required>
48
  <input type="hidden" name="path" value="{{ path }}">
49
  <button type="submit">Upload</button>
50
  </form>
51
- <button onclick="createFolder('{{ path }}')">New Folder</button>
52
  </div>
53
  <hr>
54
  {% for item in items %}
55
- {% if item.type=='dir' %}
56
- <div class="folder" onclick="navigate('{{ item.path }}')">
57
- 📂 {{ item.name }}
58
- <button style="float:right" onclick="event.stopPropagation(); renameItem('{{ item.path }}')">Rename</button>
59
- <button style="float:right;margin-right:4px" onclick="event.stopPropagation(); deleteItem('{{ item.path }}')">Delete</button>
60
- </div>
61
- {% else %}
62
- <div class="file">
63
- 📄 {{ item.name }}
64
- <a href="/download?path={{ item.path }}"><button>Download</button></a>
65
- <button onclick="renameItem('{{ item.path }}')">Rename</button>
66
- <button onclick="deleteItem('{{ item.path }}')">Delete</button>
67
- </div>
68
- {% endif %}
69
  {% endfor %}
70
  </body>
71
  </html>
72
  """
73
 
74
- def list_dataset(path=""):
75
- """Return list of dicts {'type':'dir'|'file','name':..., 'path':...} for this folder."""
76
- prefix = path.strip("/")+("/" if path else "")
77
  all_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
78
- seen_dirs = set()
79
  items = []
80
-
81
  for f in all_files:
82
  if not f.startswith(prefix): continue
83
  rest = f[len(prefix):]
84
  if "/" in rest:
85
  dir_name = rest.split("/")[0]
86
- dir_path = (prefix+dir_name).strip("/")
87
- if dir_path not in seen_dirs:
88
- seen_dirs.add(dir_path)
89
  items.append({"type":"dir","name":dir_name,"path":dir_path})
90
  else:
91
- items.append({"type":"file","name":rest,"path":(prefix+rest).strip("/")})
92
-
93
- # sort folders first then files, both alphabetically
94
  items.sort(key=lambda x: (x["type"]!="dir", x["name"].lower()))
95
  return items
96
 
@@ -98,15 +87,14 @@ def list_dataset(path=""):
98
  def index():
99
  path = request.args.get("path","").strip("/")
100
  parent = "/".join(path.split("/")[:-1]) if path else None
101
- items = list_dataset(path)
102
- return render_template_string(TEMPLATE, items=items, path=path, parent=parent)
103
 
104
  @app.route("/download", methods=["GET"])
105
  def download():
106
- path = request.args.get("path","")
107
- tmp = tempfile.NamedTemporaryFile(delete=False)
108
- fs.download(f"datasets/{REPO_ID}/{path}", tmp.name)
109
- return send_file(tmp.name, as_attachment=True, download_name=os.path.basename(path))
110
 
111
  @app.route("/upload", methods=["POST"])
112
  def upload():
@@ -120,44 +108,37 @@ def upload():
120
 
121
  @app.route("/delete", methods=["POST"])
122
  def delete():
123
- data = request.get_json()
124
- target = data["path"]
125
- # If folder: delete each file under it
126
  all_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
127
  for f in all_files:
128
- if f == target or f.startswith(target.rstrip("/") + "/"):
129
  delete_file(repo_id=REPO_ID, path_in_repo=f, repo_type="dataset", token=HF_TOKEN)
130
- return jsonify(status="deleted")
131
 
132
  @app.route("/create_folder", methods=["POST"])
133
  def create_folder():
134
- data = request.get_json()
135
- folder = data["path"].strip("/")
136
  keep = f"{folder}/.keep"
137
  tmp = tempfile.NamedTemporaryFile(delete=False)
138
  tmp.write(b"")
139
  tmp.flush()
140
  upload_file(path_or_fileobj=tmp.name, path_in_repo=keep, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
141
- return jsonify(status="folder_created")
142
 
143
  @app.route("/rename", methods=["POST"])
144
  def rename():
145
  data = request.get_json()
146
- old = data["old_path"].strip("/")
147
- new = data["new_path"].strip("/")
148
  all_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
149
  for f in all_files:
150
- if f == old or f.startswith(old + "/"):
151
  rel = f[len(old):].lstrip("/")
152
- new_path = (new + "/" + rel).strip("/")
153
- # download
154
- tmp = tempfile.NamedTemporaryFile(delete=False)
155
- fs.download(f"datasets/{REPO_ID}/{f}", tmp.name)
156
- # upload under new
157
- upload_file(path_or_fileobj=tmp.name, path_in_repo=new_path, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
158
- # delete old
159
  delete_file(repo_id=REPO_ID, path_in_repo=f, repo_type="dataset", token=HF_TOKEN)
160
- return jsonify(status="renamed")
161
 
162
  if __name__ == "__main__":
163
  app.run(debug=True, host="0.0.0.0", port=7860)
 
1
  import os
2
  import tempfile
3
  from flask import Flask, render_template_string, request, redirect, send_file, jsonify
4
+ from huggingface_hub import HfApi, hf_hub_download, upload_file, delete_file
5
 
6
+ # Environment
7
  REPO_ID = os.getenv("REPO_ID")
8
  HF_TOKEN = os.getenv("HF_TOKEN")
9
 
 
10
  app = Flask(__name__)
11
  api = HfApi()
 
 
12
 
13
  TEMPLATE = """
14
  <!DOCTYPE html>
 
17
  <meta charset="UTF-8">
18
  <title>HuggingFace Drive - {{ path or 'Root' }}</title>
19
  <style>
20
+ body { background:#121212; color:#e0e0e0; font-family:Arial,sans-serif; padding:20px }
21
+ h2 { margin-top:0 }
22
+ .item { padding:6px 12px; margin:6px 0; background:#1e1e1e; border-radius:4px }
23
+ .item:hover { background:#2a2a2a }
24
+ .actions { margin-bottom:16px }
25
+ button,input[type="file"] { background:#333; color:#fff; border:none; padding:6px 10px; margin-right:6px; border-radius:4px; cursor:pointer }
26
+ button:hover { background:#444 }
27
+ a { color:#8ab4f8; text-decoration:none }
28
+ form { display:inline }
29
  </style>
30
  <script>
31
+ function nav(p){ location.href='/?path='+encodeURIComponent(p) }
32
+ async function del(p){ if(!confirm('Delete '+p+'?'))return; await fetch('/delete',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p})}); location.reload() }
33
+ async function mkfld(cp){ let n=prompt('Folder name:'); if(!n)return; await fetch('/create_folder',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({path:cp+'/'+n})}); location.reload() }
34
+ async function ren(o){ let n=prompt('Rename to:',o); if(!n||n===o)return; await fetch('/rename',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({old_path:o,new_path:n})}); location.reload() }
35
  </script>
36
  </head>
37
  <body>
38
+ <h2>📁 Drive — {{ path or 'Root' }}</h2>
39
  {% if parent %}
40
+ <div><a href="#" onclick="nav('{{ parent }}')">⬅️ Back to {{ parent or 'Root' }}</a></div>
41
  {% endif %}
42
  <div class="actions">
43
+ <form action="/upload" method="post" enctype="multipart/form-data">
44
  <input type="file" name="file" required>
45
  <input type="hidden" name="path" value="{{ path }}">
46
  <button type="submit">Upload</button>
47
  </form>
48
+ <button onclick="mkfld('{{ path }}')">New Folder</button>
49
  </div>
50
  <hr>
51
  {% for item in items %}
52
+ <div class="item">
53
+ {% if item.type=='dir' %}
54
+ ���� <a href="#" onclick="nav('{{ item.path }}')">{{ item.name }}</a>
55
+ {% else %}
56
+ 📄 {{ item.name }} <a href="/download?path={{ item.path }}"><button>Download</button></a>
57
+ {% endif %}
58
+ <button onclick="ren('{{ item.path }}')">Rename</button>
59
+ <button onclick="del('{{ item.path }}')">Delete</button>
60
+ </div>
 
 
 
 
 
61
  {% endfor %}
62
  </body>
63
  </html>
64
  """
65
 
66
+ def list_folder(path=""):
67
+ prefix = path.strip("/") + ("/" if path else "")
 
68
  all_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
69
+ seen = set()
70
  items = []
 
71
  for f in all_files:
72
  if not f.startswith(prefix): continue
73
  rest = f[len(prefix):]
74
  if "/" in rest:
75
  dir_name = rest.split("/")[0]
76
+ dir_path = (prefix + dir_name).strip("/")
77
+ if dir_path not in seen:
78
+ seen.add(dir_path)
79
  items.append({"type":"dir","name":dir_name,"path":dir_path})
80
  else:
81
+ items.append({"type":"file","name":rest,"path":(prefix + rest).strip("/")})
82
+ # sort dirs then files
 
83
  items.sort(key=lambda x: (x["type"]!="dir", x["name"].lower()))
84
  return items
85
 
 
87
  def index():
88
  path = request.args.get("path","").strip("/")
89
  parent = "/".join(path.split("/")[:-1]) if path else None
90
+ return render_template_string(TEMPLATE, items=list_folder(path), path=path, parent=parent)
 
91
 
92
  @app.route("/download", methods=["GET"])
93
  def download():
94
+ p = request.args.get("path","")
95
+ # download via hf_hub_download into /tmp
96
+ local = hf_hub_download(repo_id=REPO_ID, filename=p, repo_type="dataset", token=HF_TOKEN, cache_dir=tempfile.gettempdir())
97
+ return send_file(local, as_attachment=True, download_name=os.path.basename(p))
98
 
99
  @app.route("/upload", methods=["POST"])
100
  def upload():
 
108
 
109
  @app.route("/delete", methods=["POST"])
110
  def delete():
111
+ d = request.get_json()["path"]
 
 
112
  all_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
113
  for f in all_files:
114
+ if f == d or f.startswith(d.rstrip("/")+"/"):
115
  delete_file(repo_id=REPO_ID, path_in_repo=f, repo_type="dataset", token=HF_TOKEN)
116
+ return jsonify(status="ok")
117
 
118
  @app.route("/create_folder", methods=["POST"])
119
  def create_folder():
120
+ folder = request.get_json()["path"].strip("/")
 
121
  keep = f"{folder}/.keep"
122
  tmp = tempfile.NamedTemporaryFile(delete=False)
123
  tmp.write(b"")
124
  tmp.flush()
125
  upload_file(path_or_fileobj=tmp.name, path_in_repo=keep, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
126
+ return jsonify(status="ok")
127
 
128
  @app.route("/rename", methods=["POST"])
129
  def rename():
130
  data = request.get_json()
131
+ old, new = data["old_path"].strip("/"), data["new_path"].strip("/")
 
132
  all_files = api.list_repo_files(repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
133
  for f in all_files:
134
+ if f == old or f.startswith(old+"/"):
135
  rel = f[len(old):].lstrip("/")
136
+ newp = (new + "/" + rel).strip("/")
137
+ local = hf_hub_download(repo_id=REPO_ID, filename=f, repo_type="dataset",
138
+ token=HF_TOKEN, cache_dir=tempfile.gettempdir())
139
+ upload_file(path_or_fileobj=local, path_in_repo=newp, repo_id=REPO_ID, repo_type="dataset", token=HF_TOKEN)
 
 
 
140
  delete_file(repo_id=REPO_ID, path_in_repo=f, repo_type="dataset", token=HF_TOKEN)
141
+ return jsonify(status="ok")
142
 
143
  if __name__ == "__main__":
144
  app.run(debug=True, host="0.0.0.0", port=7860)